EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* Q* U" U& @: M4 E& x( w* C1 N# v# A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" o' w7 M, X- i, T- m9 Y
这里有相应的模拟器源码,就当送给大侠了~~
3 g; H/ O- G8 Dhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 " G: A- N2 m1 i, _; W$ o) O) K- o
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 i* F# ~* P0 o3 R# y楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& T: D3 G4 t8 @( r6 M
这里有相应的模拟器源码,就当送给大侠 ...
4 f: `( ^. n5 ^( T0 u: K7 p1 Q
聲音部分(Audoi Process Unit = APU):
- A( x) k1 b7 n3 ^1 f$ E1 t! @.\NES\APU.cpp/ I/ d+ P6 P6 @0 R- z
.\NES\APU.h
( q7 Z0 e  n- l' g% D2 W- {8 X1 ]; \" H
4 Y5 q5 y( s# E/ I
影像處理部份(Picture Processing Unit = PPU):  Y2 P( ~" y8 B% ]7 M
.\NES\PPU.cpp
; y1 q: N) M0 ]7 G4 [.\NES\PPU.h
, C' U* @6 [6 h! [. s9 ~7 O
$ {& j; n! N. e3 r0 q: Y如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:" n2 U1 h. \- U4 m! B! R  J' s1 M, z
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) A7 M1 _: m+ ?. b4 g//////////////////////////////////////////////////////////////////////////8 F1 R$ c' n# f% }9 N
//                                                                      //2 P4 ?/ Q" z1 O- S* @
//      NES APU core                                                    //6 R- q& B2 L& v; W' z
//                                                           Norix      //
* G: J2 {3 i; O9 A% i//                                               written     2002/06/27 //
# ]2 r) o3 S+ ]4 q//                                               last modify ----/--/-- //& J- o$ ^  l/ e, a/ ^! i) I0 k
//////////////////////////////////////////////////////////////////////////
# i# g, o. x  F8 l# J& N- W' F; \#include "DebugOut.h"* @  G. z0 S( `+ F9 G- K+ F
#include "App.h"0 P$ r& p2 Q* H: v. F6 J5 c+ C% s
#include "Config.h"
; ~- D- ^4 l$ z& |# |+ T
: S- O% @$ A+ f6 x8 h- U# [: i/ ]#include "nes.h"
3 [' _$ K7 A: H/ ?0 ?#include "mmu.h"
% g3 j; J# l$ v) V0 K#include "cpu.h"
* u& H6 A6 w: P; C; h/ u$ L#include "ppu.h": Z( y9 l7 |, `* u
#include "rom.h"8 {8 R! W* y3 m+ C' O. {
#include "apu.h"
; }+ y% H" [3 Q. f* r3 m
! ~: y5 t% v: \4 ?' b// Volume adjust4 W" d& j% R. n: N% _1 ~
// Internal sounds* v% K  b# y  |  c. H
#define        RECTANGLE_VOL        (0x0F0)2 L; w  S$ j: }  w
#define        TRIANGLE_VOL        (0x130)
4 h# V) l2 V+ ^* f4 L, a5 {6 \#define        NOISE_VOL        (0x0C0)1 Z1 v1 A/ J  M8 A
#define        DPCM_VOL        (0x0F0)
: [0 J* ~. t( I4 ?% i// Extra sounds
1 }! K4 L5 H& N#define        VRC6_VOL        (0x0F0)8 |5 j, o. @" ^9 w
#define        VRC7_VOL        (0x130)& o6 W" u% x- m+ q/ R0 }; A
#define        FDS_VOL                (0x0F0). ~0 B8 F. X# F" t1 o
#define        MMC5_VOL        (0x0F0)/ h9 r! z0 ~9 I, ?) W1 b2 S7 B4 @) f
#define        N106_VOL        (0x088)9 p$ t1 ~3 H8 g% m' j0 S
#define        FME7_VOL        (0x130), }( E  n0 K3 X5 T+ o

5 }! v+ j( j$ AAPU::APU( NES* parent )4 z6 H! `$ F7 @  z4 K  W( I
{7 H1 \4 ?* j- C" N& K7 f
        exsound_select = 0;9 u, L5 w' f$ _7 ^8 `* M# J
1 h0 S- l# p8 |, ~
        nes = parent;
4 f' ]* [  d/ Y! c; q, w        internal.SetParent( parent );
7 h- Q% q" e/ }. A  |. d) _7 z& ~% Z: B% N5 N/ p5 Q! ]; o
        last_data = last_diff = 0;
" |5 m9 ]# V  r5 X" U1 L! ~- w+ j1 p, ]
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );% I5 ~* u$ U! t, Q. [% D) @# a5 e

& g% u/ E, i! x3 w        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );' p! o8 `  ~/ ~" `8 w
        ZEROMEMORY( &queue, sizeof(queue) );. l+ K' t: `/ T2 H/ F* ?( @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* i- T+ |' `& I8 L) {

) ^4 @6 ^7 R% j3 [" B        for( INT i = 0; i < 16; i++ ) {
7 ?* d/ b! _7 Q+ ]$ v+ K3 i% d                m_bMute = TRUE;
  N& ~9 x6 Z: `4 Q- I        }6 |( Q) h) E, ~; Q# F* O2 K. s- K
}, C4 G. h5 {, W2 ~

2 V! J+ G7 A9 H+ M5 H- jAPU::~APU()' F1 C2 b+ M. F
{: P4 D% A7 r* A* H: l+ u
}
3 {& |" Y% s; H& S
9 e5 d6 ?$ A5 \) l: Qvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )% B6 w9 g. ~- ~8 u# @7 a* j
{0 K4 k3 L( L" N' u5 W' P
        queue.data[queue.wrptr].time = writetime;
; i5 H! z! i& z3 e/ R        queue.data[queue.wrptr].addr = addr;. }6 i; n: K! I. ~2 g( e
        queue.data[queue.wrptr].data = data;
3 ~( F% L/ r3 B. ?2 C* {4 A: i        queue.wrptr++;# d! }$ n0 N+ }" b
        queue.wrptr&=QUEUE_LENGTH-1;
' i) |+ G, K, i4 F1 x3 x6 B" q        if( queue.wrptr == queue.rdptr ) {
3 D" X% j- ~/ ^4 A) S+ P# B                DEBUGOUT( "queue overflow.\n" );
8 a6 P) q, w) ^: T- U' R7 B4 y9 ^        }4 E( f& v8 w8 I& b8 c* X
}$ a0 q* r. k- h% p2 V5 Z0 ~6 T" Q
9 f  b1 k! H" |$ A% d. y
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
; f* n6 u% Y; W{8 e% |% }0 _4 ~! @/ Q6 Q
        if( queue.wrptr == queue.rdptr ) {
5 p1 m  M5 {/ t: l! N3 \7 |                return        FALSE;) N: x' G/ o* ?' a
        }5 O$ P0 c! T; [5 n9 n6 I9 L; _( e
        if( queue.data[queue.rdptr].time <= writetime ) {
3 ^( f! _6 f! h" J) |                ret = queue.data[queue.rdptr];: T5 A" s/ x: x; a' ]2 M' r- |
                queue.rdptr++;# V+ W: I' a% b5 G7 b7 A$ k3 s8 w
                queue.rdptr&=QUEUE_LENGTH-1;# i4 Q4 O+ i8 w
                return        TRUE;/ h9 r9 o( _3 j
        }  i$ k& v/ H9 V, ^# Y6 W2 H  \
        return        FALSE;5 V' f% u0 ]4 x
}# M" i9 d- r, T

. o6 a! z! k% z$ P# Z( N: nvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
- J- Z( u7 o) Z0 N% v! f% e$ s3 s{
+ ~/ ~# E8 c, u        exqueue.data[exqueue.wrptr].time = writetime;  q2 j/ E$ r1 Y8 b9 V- s! b2 r
        exqueue.data[exqueue.wrptr].addr = addr;
" ]* v# r- ^* P+ [        exqueue.data[exqueue.wrptr].data = data;
+ l  t  C, b' f$ j( b0 [2 _        exqueue.wrptr++;
$ y+ \- f% D( h$ d/ B, a        exqueue.wrptr&=QUEUE_LENGTH-1;
: |4 \7 ~) b. B5 |( s3 s4 |6 t        if( exqueue.wrptr == exqueue.rdptr ) {
3 w( _$ {) {9 L9 [& u( h                DEBUGOUT( "exqueue overflow.\n" );
6 t' y! I& a% W+ ~8 ~        }
7 O& ^! N# p/ }4 {3 S/ ~}
8 O# z" Z2 R( K; S! }& w5 Y8 f: g9 f% W6 B, d( E/ C4 r& y
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
* S, |0 L( j/ K, x  Z: U+ ]& F{
, K& |6 @1 T2 i        if( exqueue.wrptr == exqueue.rdptr ) {' f  D5 C/ f( ?, d
                return        FALSE;- a) Z# s$ b3 T* [- Y- Z
        }0 d" k2 Q$ m3 k( T
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' D. j' b8 [2 M5 g: ]/ B
                ret = exqueue.data[exqueue.rdptr];
, x6 g. v& E( E/ s2 k! E                exqueue.rdptr++;1 d; A# d* _2 S' I1 m9 X8 T
                exqueue.rdptr&=QUEUE_LENGTH-1;& z) C1 n9 f) @8 b- M3 F% q8 E
                return        TRUE;
( _) \" _7 C4 c1 T        }
. R3 f$ d( }. t, S3 E+ L        return        FALSE;
* |+ N' Q3 ~- d  e( s% V0 Q) y}
) W9 j3 b" L1 h0 `
/ s+ O- l# u7 Ovoid        APU::QueueClear()
4 W5 x- V6 I4 m' B7 v% [5 e9 O{  Q, Z3 u2 X; H1 {" C: X- \. e
        ZEROMEMORY( &queue, sizeof(queue) );
* R0 K7 c, u8 |0 A        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ [5 u. g( N. D' P8 u/ m4 y
}
9 R/ \2 E1 N! `. F! V0 m9 j) F2 ^+ E; A
! u' h/ d& ?1 T- Bvoid        APU::QueueFlush(), w( r, L! z* \) y- w
{
' x7 G) [) `7 X- y  G        while( queue.wrptr != queue.rdptr ) {
; a& k& m" c) b! `  y) k                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
/ o$ `1 ^+ V/ k                queue.rdptr++;
  R/ }/ z2 i% r                queue.rdptr&=QUEUE_LENGTH-1;
  O: w6 N( V/ b) P        }
& ~6 f9 {2 y1 ]5 B$ P( a8 m
# _1 n0 r# j/ {# E1 v' o        while( exqueue.wrptr != exqueue.rdptr ) {
9 z/ Q$ D3 @3 j                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* v- c+ z% i% H6 K+ V9 l; T2 V3 }                exqueue.rdptr++;
5 ]: o) t, O1 i' U                exqueue.rdptr&=QUEUE_LENGTH-1;
3 E  a7 y) x$ _9 K) R        }
, t+ l, h2 u- r, ~3 _}2 d( e; C( Z# K) E7 ~  H  H

2 E# z: k0 n# Kvoid        APU::SoundSetup()
& F8 C5 L& _. a& l, K2 S{
; v% {3 O9 `( @' E( A        FLOAT        fClock = nes->nescfg->CpuClock;
! D% n) ^. X- x7 L1 }        INT        nRate = (INT)Config.sound.nRate;. ]$ J4 ~: r7 o# j
        internal.Setup( fClock, nRate );
2 J8 T# x. K. G7 k! y1 R        vrc6.Setup( fClock, nRate );/ p& @: E7 E0 Z
        vrc7.Setup( fClock, nRate );3 k; p6 V9 A) l4 a2 j: ~
        mmc5.Setup( fClock, nRate );! t3 ~3 B, d" S% x: q
        fds.Setup ( fClock, nRate );" a# [7 [4 Y0 O8 R6 O& u
        n106.Setup( fClock, nRate );
, s  V0 j4 k+ C: K        fme7.Setup( fClock, nRate );; o  k  s1 |. O0 [4 x
}
* y& z7 ?# L& v" t/ _# S" ~9 {8 O  E
void        APU::Reset(): v4 n9 r9 Y% H, D& U
{$ ]) x1 K/ J* e2 f7 O% k/ W, z
        ZEROMEMORY( &queue, sizeof(queue) );8 n1 g8 s+ E; Z2 y  m2 c: t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# u9 T8 H) F* e0 v& v
0 f- g. l8 d& J        elapsed_time = 0;5 ]  [  Y, }- F; }( _

  o! ?2 f' m# Y  b        FLOAT        fClock = nes->nescfg->CpuClock;3 M0 ~0 {3 b2 `$ ^, ~0 p" Z
        INT        nRate = (INT)Config.sound.nRate;
; g% a* d) W: t: }        internal.Reset( fClock, nRate );
# X) `/ H/ L, |: g        vrc6.Reset( fClock, nRate );
3 m. }) c8 d& E# s( h6 f        vrc7.Reset( fClock, nRate );0 j" V+ N- }/ Q/ d' R' {
        mmc5.Reset( fClock, nRate );* _1 p' d' p/ b  R7 ?
        fds.Reset ( fClock, nRate );1 {) w: X$ q; G. t# m
        n106.Reset( fClock, nRate );
  @; m1 u. t  }% y        fme7.Reset( fClock, nRate );
, B3 J: G' x) l5 {" n6 B: }! t( W% S' A. y6 \4 ?+ W1 N
        SoundSetup();6 e, `  F+ Q4 E9 q  Z/ W0 y1 ]
}6 `8 o, A% A  M: T2 ^, p6 U

& V( ~6 h" `' u( Fvoid        APU::SelectExSound( BYTE data )( p7 C# q/ m# \4 u
{
4 G/ e# ^+ ^. t+ ^0 `7 A. y% p        exsound_select = data;, B$ K3 }' [1 G9 _
}
3 Z% w' D4 ]' P( H$ y& D1 `$ d! @! c! ~8 f2 `  R* d& {
BYTE        APU::Read( WORD addr )" u) A" H& W9 H4 V- F
{
# K' D# V2 S0 C1 W9 A. {: M4 q1 Y        return        internal.SyncRead( addr );
( e* [  A: n  W: {  k1 e( {/ B7 T}
: H! X1 q* }- o3 Y+ V/ X+ X
, f' U6 A- [( Y7 ^. Z  o; ]void        APU::Write( WORD addr, BYTE data )9 S$ w. o$ G8 w9 X
{7 I" {3 d* m7 v% T: {( {
        // $4018偼VirtuaNES屌桳億乕僩
6 _( k+ N, I1 E+ O& ^) `+ N        if( addr >= 0x4000 && addr <= 0x401F ) {
& s5 P5 C. z& j$ [                internal.SyncWrite( addr, data );
& m/ B1 v* K+ ~2 X/ x( [; `  `                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
9 g6 {6 z/ a6 f' n" o7 L: a        }6 T- k- d" p: Q+ G$ _
}
& H2 Z1 @0 T5 ~4 E0 Z6 v  b' I% s" Z
BYTE        APU::ExRead( WORD addr )4 F8 Z3 V& @5 ^) \% e+ k
{
, x& v* S& y: m9 y  i& YBYTE        data = 0;1 K8 Q* H/ w" L- _7 V

7 d) y8 F  c1 m5 h4 s# x2 r        if( exsound_select & 0x10 ) {
* v& Z( ~6 Z" h4 a& E. ^                if( addr == 0x4800 ) {, `6 S- R: `- e( K, U6 G9 {
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
% _0 h9 k4 _, Y+ W                }
9 ~6 Z- H: B9 }6 C3 o0 `        }
5 @& C2 x- [0 [( B. x. E) n        if( exsound_select & 0x04 ) {
3 N( n/ ?% w8 u) e) h, w                if( addr >= 0x4040 && addr < 0x4100 ) {
0 S# m1 \  n: {4 y" ^4 f) a                        data = fds.SyncRead( addr );+ i- G# _5 m0 M* d
                }# H3 [4 t. e) M6 Y) S: `! s! @
        }& g. f9 y& d+ b( M* C! ]$ c, N
        if( exsound_select & 0x08 ) {
0 }9 n0 f7 {+ {5 F; \- g                if( addr >= 0x5000 && addr <= 0x5015 ) {1 T, W# w$ `% \) l! `
                        data = mmc5.SyncRead( addr );8 ]/ J/ f4 A6 Y" L: Q
                }: ^6 b6 q( o$ ~3 {* T
        }
  F9 V% O$ A% J* q
/ a6 U# ~% z1 ]6 R7 V        return        data;
5 @' s5 B7 R, z  O' L}
3 H8 L/ [! t# L: |: h$ m/ K+ \" K6 s3 e- u9 N5 C
void        APU::ExWrite( WORD addr, BYTE data )
" R( w2 `" r" o, r, {' h; s( s: \{( ^" q6 E3 J$ z4 M
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
7 p( y+ R6 G7 {3 k& }
4 E  ^4 y2 q- Z6 M5 i. H        if( exsound_select & 0x04 ) {! C, V+ M7 k3 Y4 i/ t
                if( addr >= 0x4040 && addr < 0x4100 ) {5 p( l6 c- ^5 t! b, ]
                        fds.SyncWrite( addr, data );' }4 [9 ~& z7 R7 A3 t
                }
" U( L6 c3 s4 J% N4 ~3 Q4 \7 E        }
4 E9 u! m+ _/ ~- F* _" l" K- O, d2 `, ?" y& a" ?. p/ r" w
        if( exsound_select & 0x08 ) {0 l6 w& E* B, X9 }; x; f* \
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 F9 F  @% K& y: y" A9 F4 c                        mmc5.SyncWrite( addr, data );
8 j" c7 t5 R& t1 U5 l/ G7 ]                }
: s% I% u4 G! N& h, t# S        }
5 e, E7 d- e1 Y" `$ X- M}9 ^2 p2 H- L+ v1 g1 Y! x

4 \4 Z8 d/ L5 @7 y$ }1 x0 ]void        APU::Sync()
1 V+ e- e' T+ W$ t/ q{( h1 o3 S2 x  U- W9 |$ S
}
4 y' T; U* F& |2 r  z* w. L0 o: ]
void        APU::SyncDPCM( INT cycles )2 I( B, [  |# B, ^
{" |" o  m; q' V( _! ]  `- u% |. X
        internal.Sync( cycles );5 p3 S  |! D: d
. H: Q0 c+ g# A3 `
        if( exsound_select & 0x04 ) {
2 m$ d2 M% ~. D3 P! g  U5 f3 `                fds.Sync( cycles );5 {& c. }0 L* P  `* w' R$ m- H
        }' y5 M+ l% ?8 `, R# G
        if( exsound_select & 0x08 ) {) `2 O" y4 d; ]- h1 t, u0 Q+ `
                mmc5.Sync( cycles );* w  C) r3 A' G0 u& w
        }
# ~* s* W# U& Z. D}
/ i( m8 L/ i4 D4 Y
7 Y5 P5 v# X3 c5 |9 m' Yvoid        APU::WriteProcess( WORD addr, BYTE data )" i' {- O  p; h$ b1 y
{
1 S- |3 `5 a% z0 z+ @        // $4018偼VirtuaNES屌桳億乕僩
- o& G8 t3 g8 j! ?        if( addr >= 0x4000 && addr <= 0x401F ) {2 N1 X, v. W* U3 r# d
                internal.Write( addr, data );1 `( Q4 S/ O' w9 W% [' C
        }; I9 T4 D, l2 d+ [( L! u) w
}/ n) S* \/ n& }% g1 Y4 D

% O) p: E3 G' @, Xvoid        APU::WriteExProcess( WORD addr, BYTE data )
4 V) x) ?9 y0 F, A3 Q9 L{" H2 r; |' P; D& P& k( L2 E& r( V
        if( exsound_select & 0x01 ) {
4 J$ [" ^, W: v) q. H( U5 O# t                vrc6.Write( addr, data );
+ p( d. @1 S! |1 c2 k- G        }  ~. M$ v( r& r  F# h
        if( exsound_select & 0x02 ) {
% f  U% W5 p$ h& Q                vrc7.Write( addr, data );) |# e- q" I/ n9 y
        }* z% Z% @7 q9 h. v( k
        if( exsound_select & 0x04 ) {4 G) S0 M& e3 [$ n6 B- k' w/ V% c
                fds.Write( addr, data );, t) l7 T% p( N4 a) s3 Q4 v
        }5 k1 K- a( \, k9 u" V
        if( exsound_select & 0x08 ) {
) q, X0 N6 |- g                mmc5.Write( addr, data );3 w; o/ j8 R9 A6 S$ R9 {9 h0 U
        }, |) e7 R6 F( N5 {$ G
        if( exsound_select & 0x10 ) {
, n! c( J  m2 v% C4 Z! |                if( addr == 0x0000 ) {7 n: t4 m- \0 x, T
                        BYTE        dummy = n106.Read( addr );
9 `# ~# r0 a3 I4 }, _) h                } else {
: F+ D  r: {2 H. Q                        n106.Write( addr, data );# j. f8 @& D& K; X0 \6 b
                }
, R9 s4 b) i) @2 L        }4 ?' E2 s, [0 D6 I3 N
        if( exsound_select & 0x20 ) {
& W+ i" P% p- y( v% t8 w                fme7.Write( addr, data );2 u. t. j' O+ U. w# x. W
        }9 `% [5 b- H5 ~2 O( T  H
}) T# [/ I: o. R2 [5 r# U! E/ Q1 i9 h

7 ]. b/ k  w$ Y; P% s, y/ Evoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
% H( Z5 F% L  O) S3 ]5 q* |{
( j' \) n* X' |( D& E4 P& J2 [INT        nBits = Config.sound.nBits;, n3 K3 O/ t! u7 K# p% E
DWORD        dwLength = dwSize / (nBits/8);& ^. t( D* _, E2 r
INT        output;1 o  C: P( ]; W* |
QUEUEDATA q;
6 |: k. P) H2 R& TDWORD        writetime;
( f) S6 @) t  ]$ _. v9 y2 T5 o$ |6 X+ `6 q! d* b( `
LPSHORT        pSoundBuf = m_SoundBuffer;3 H( G- Y9 ?+ K0 l, c1 i
INT        nCcount = 0;) {, y: w3 R- A- w2 V7 D9 J

% O2 B: C; c" o( W9 xINT        nFilterType = Config.sound.nFilterType;# E$ V: m# c8 _) |7 `" [' Y

+ L# o1 ~& ~6 l- |        if( !Config.sound.bEnable ) {
7 j9 e4 ~) z6 D( |, U2 U( {                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 x. ], N# s$ A+ f! Z  j                return;
; J2 ]7 F$ k: t& |$ ]) D        }. H- w/ s9 L) [' M3 {3 {! Z
- d; q4 u: E9 @2 E1 p
        // Volume setup% c  V. ^: N0 A# L( s
        //  0:Master! ^- m( |. c' d( P
        //  1:Rectangle 1
9 O& ]( S' A. F% i        //  2:Rectangle 2
! t- |  b  h% V  q        //  3:Triangle, J2 q- D! t( ^
        //  4:Noise
6 [7 h: o1 c1 a' h" s: `        //  5:DPCM0 Y: I; E* R% _- T0 |4 E
        //  6:VRC6) ]6 `6 ?% J6 t  M: U( [
        //  7:VRC7
( ?, S/ |$ A/ u; O$ z        //  8:FDS
7 d" v  N& }( u- h( a        //  9:MMC5
2 U! Y, I+ A8 ^; R+ j        // 10:N106
: c3 i5 F+ l* B6 H) }        // 11:FME7* F# x4 v# w! q" p4 w+ l
        INT        vol[24];
/ ~( x# l5 o4 t4 A        BOOL*        bMute = m_bMute;0 P5 E2 o. w7 f& h1 D- K
        SHORT*        nVolume = Config.sound.nVolume;# U: A1 ]1 I& q% B! t: U
$ l4 L1 S  t5 c8 e! x
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
% Z, S# h& r/ e+ k+ i9 _/ W1 w$ O7 q, [- T) O$ t& {
        // Internal
0 {, n8 \3 g3 [+ y# _* ]; L$ V% u" ^        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
* b3 S: H# d  {. a        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& J6 ?& y- j3 }6 E3 L0 u' L        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- l4 y- f8 m1 A9 E1 z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
5 v7 j: d7 o. k. Y        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;5 O! \& m/ {2 p
7 v0 j8 O6 P6 r( s5 c
        // VRC61 e( E& {2 J, c2 t4 ]- d
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
1 t1 i: f: a/ v1 O: n: n/ ~        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# n, h( q# e7 M$ b3 |& P
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 I" D* O' j7 v* ~' ^" P! C6 q

0 _9 Z2 E! X  k  @4 U        // VRC7" {- I: v6 A- H- }" t% D, C8 e
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
) J1 C$ U. z' i! f" z3 _1 n" g, a9 j* l. Z' Z% v( O
        // FDS
6 \4 O& a6 [7 `% [/ R        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
1 F( F1 h/ U% T: _2 |! J
$ N2 M0 i  B' @( O8 T3 |4 |0 }' G6 c        // MMC5
( n. t7 g# F) w% b: A3 Y* k        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( A& L. o2 h+ h4 m. H5 V+ g0 l        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& J# \9 B5 ?3 w* ?        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 e5 H3 D& g& ?; I6 {/ L! h( h5 Q4 U/ j4 \+ ~
        // N106
4 q" N/ l2 o: s* {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) p/ y5 _7 b1 X3 l7 }% n        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! a9 n' G2 P* W, ~( R% V
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ i- F) j: Y9 |  u
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! @. z' ^- L: w, Y
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" {) k+ Y$ Z' T: H, r# a+ C8 C        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: K0 V; ~- Q0 ]5 S4 A1 }% u$ B
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, h8 _2 B3 a3 }% f% U5 b1 a( J3 Z
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 l/ F4 \" P9 M* y0 s2 A+ z# M5 U
: a" p* k' X" I5 |$ Y2 Z& r" u
        // FME7
+ B% |. A( M! J3 w0 I        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; `. Z" |3 r) C; O( b- G        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 R. t* M8 K4 ]! s' z. J4 R) f1 Q/ t        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; Q7 Z0 x, V! |1 h! m+ T9 ?! m; K  w8 G9 }$ F/ |) X7 Z
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
, N* q% ~0 Y- P        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;3 V# o$ v& @8 x9 {5 b

# {8 _, R% q( x, n, k4 i        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟$ _: d8 [& r7 L! K# A  Q8 \
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 ^% c$ C( B: O9 L* L
                QueueFlush();
3 ?/ o' f: v7 W& J8 o, L$ L. G1 e        }+ N0 j2 k/ b# J# g/ r0 x

: B5 [7 O0 Y/ ~, ]        while( dwLength-- ) {4 [# A( ^3 C( }' v  W, d% \3 W
                writetime = (DWORD)elapsed_time;
& \( j" R! L2 h: }
% S' k9 w5 {5 Q, f# _6 ?4 U                while( GetQueue( writetime, q ) ) {  B  O6 Q: o$ N0 ^7 F; ^' e
                        WriteProcess( q.addr, q.data );! u) w7 _4 z9 `) \! B5 ~
                }/ W+ W6 J$ e$ @3 h: E% ]

! C$ J; A! K; R" J2 T  h                while( GetExQueue( writetime, q ) ) {) @2 i( o9 c" c8 h" m' I. K
                        WriteExProcess( q.addr, q.data );. X! l1 G" O3 q. w/ ~
                }
/ f  w$ K  l. o4 a1 p- B
) R8 _2 Q- B. Q5 M) P0 g/ c. X3 ]/ [                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 s2 d, |: r' f+ L  z                output = 0;
2 q& Y. o! q1 `6 ~1 W                output += internal.Process( 0 )*vol[0];
, P  E# y# A1 J7 W! A" Y7 o                output += internal.Process( 1 )*vol[1];5 K7 {! k5 ]8 Q$ Y
                output += internal.Process( 2 )*vol[2];( T! i- e% s7 }7 @9 X* {+ ^
                output += internal.Process( 3 )*vol[3];" I4 `- _% a( G5 {0 {
                output += internal.Process( 4 )*vol[4];
/ w4 F8 O4 N, X8 U
4 k9 ]$ H8 m& w8 q                if( exsound_select & 0x01 ) {: q) e7 h" g3 f  ~1 u
                        output += vrc6.Process( 0 )*vol[5];
) s4 Y6 T  E* Y% |4 G, x                        output += vrc6.Process( 1 )*vol[6];; Y- S/ G0 h8 S. Z  e
                        output += vrc6.Process( 2 )*vol[7];
( e5 `- x3 i. ?, A                }
  z9 j3 a* ^6 g1 T# F                if( exsound_select & 0x02 ) {/ M/ I# m6 Y: u5 f; b3 F' S
                        output += vrc7.Process( 0 )*vol[8];4 j/ V, X9 p, a9 ~+ U5 W! J6 @$ b
                }
  G! X" T/ z7 ]% u* B                if( exsound_select & 0x04 ) {4 x& L6 k# z; J# `6 H" w
                        output += fds.Process( 0 )*vol[9];
- @6 t1 `% t  G# Q                }
0 U+ r' F, Z, f3 b' K% P                if( exsound_select & 0x08 ) {
6 W0 J8 Z+ c$ f  X# m                        output += mmc5.Process( 0 )*vol[10];
8 C2 M! A4 F% v1 X; g4 Z8 e+ a7 A+ D                        output += mmc5.Process( 1 )*vol[11];/ M: f) g( a3 y6 d
                        output += mmc5.Process( 2 )*vol[12];
1 }- i' |; ?4 V* A. ]" e/ R                }
* A$ U. U: q0 m. ^" `( K' [                if( exsound_select & 0x10 ) {* M  k& _; K  P
                        output += n106.Process( 0 )*vol[13];
7 I* U' R, S  S                        output += n106.Process( 1 )*vol[14];
/ [! s) ]/ c& ^2 r5 f5 h                        output += n106.Process( 2 )*vol[15];
4 A# P' a1 D) \4 s                        output += n106.Process( 3 )*vol[16];" v9 X9 I% P6 j6 w  n+ \% Y& s) J+ k
                        output += n106.Process( 4 )*vol[17];
  J) P3 i) W3 S! f/ _; P0 ^                        output += n106.Process( 5 )*vol[18];
& u7 \/ g# k. v                        output += n106.Process( 6 )*vol[19];1 G! l! `/ q8 M% O
                        output += n106.Process( 7 )*vol[20];
" ]! q& }1 w1 z8 _9 G1 N                }% e" E' T, a) h% M: z! |2 N
                if( exsound_select & 0x20 ) {
6 e0 K# u6 T3 u1 v                        fme7.Process( 3 );        // Envelope & Noise& y; F) ]. r- k; x
                        output += fme7.Process( 0 )*vol[21];
' P* j7 U  y9 \/ x8 S/ h                        output += fme7.Process( 1 )*vol[22];
' m% {7 n0 A+ I' r                        output += fme7.Process( 2 )*vol[23];! |; \0 U& i; q2 j/ ^. v
                }: _# D$ f) a$ g- M1 x3 o+ q/ E8 N
# r+ l, m4 b8 \8 l. Y* q
                output >>= 8;. j+ z& I9 T7 M9 D4 b$ ~
" i% R" w1 a$ P
                if( nFilterType == 1 ) {
4 I  d, z/ {! p9 F9 N& J: h                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
" u( |' z4 v+ X5 a' M" O                        output = (lowpass_filter[0]+output)/2;( S( r( h) l- s5 \5 L3 p0 X
                        lowpass_filter[0] = output;# r) G, K; Y4 K6 Y! r/ Y: _4 w. t
                } else if( nFilterType == 2 ) {) q7 g6 {; t( D
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)$ l/ R  J. A5 v$ ]8 E) w
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
7 P7 q8 n3 r5 F( N% h& y; R                        lowpass_filter[1] = lowpass_filter[0];
8 Y, [8 q: Z; L: U$ o6 Z" k                        lowpass_filter[0] = output;( O$ v1 O" P, |+ u; E
                } else if( nFilterType == 3 ) {
; s  W5 w( w- N                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2). A( U" Q# |4 H' B0 B$ F
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
, D! B/ ?. k7 |7 ?                        lowpass_filter[2] = lowpass_filter[1];
# U3 a( a9 z' n                        lowpass_filter[1] = lowpass_filter[0];1 @" I9 u3 \/ |; j
                        lowpass_filter[0] = output;- k0 a" a3 n" E6 D: n
                } else if( nFilterType == 4 ) {! i0 P. F3 d% C1 G: g& B1 x' S
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
5 R) n8 i8 s7 U  v                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
5 @2 w0 ^" L# T                        lowpass_filter[1] = lowpass_filter[0];
, r! V& n" R; L5 f                        lowpass_filter[0] = output;3 k7 ~5 D- g7 J! T4 h6 a' \: s
                }
! |+ ?6 L, [/ W1 u. f$ x" l: s) q+ J5 @; t/ e" z. n. K
#if        0
0 Z1 q8 t( g! t* k* B. m# P) h8 m/ d                // DC惉暘偺僇僢僩% C- ~6 S5 [* P4 M
                {
- a1 Y' F' k. x; O) T3 _                static double ave = 0.0, max=0.0, min=0.0;
/ V& j! O$ ~+ G                double delta;3 F# q! q: R4 W' |  i; B  X- w: }
                delta = (max-min)/32768.0;
' }' L$ W3 N5 D/ f                max -= delta;
4 k  k  O: \* U' ]. h7 X- X                min += delta;" }8 T- b0 ]) X4 h% T1 t
                if( output > max ) max = output;; o1 ]+ D. @/ Z7 z3 O2 N/ F  W
                if( output < min ) min = output;- @: q9 l+ @  I8 h2 H/ Z
                ave -= ave/1024.0;8 i! G' O+ J" K7 d+ j  K
                ave += (max+min)/2048.0;, h/ W1 D* |" c" c9 B3 m
                output -= (INT)ave;
1 h' B, l6 h& G# f1 e                }# f: d8 }- D( B% P
#endif
5 Z2 S! b6 g2 y9 Y6 G  w6 o#if        1
4 [8 n8 e: I0 A; e& L                // DC惉暘偺僇僢僩(HPF TEST)
: j$ n. _' V8 p. F4 i0 q  p                {
( X" c' B1 Y1 P' n2 Y//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( u) B2 l. b" ~. M% I0 d
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
9 Z( `' @, M7 M( n% A                double        cutoff = cutofftemp/(double)Config.sound.nRate;
" G8 S- g& f" |8 R0 y8 h. Z                static        double        tmp = 0.0;
+ ~6 i1 J# R" S$ `' V                double        in, out;0 k1 p) V  g! V2 ?0 F) w) _; c- v
% z6 w5 E: l: E; |/ y1 `
                in = (double)output;( U$ }% H7 }5 q% [9 `8 [
                out = (in - tmp);- D# ]! ?. {# q8 S
                tmp = tmp + cutoff * out;3 d) c. r: N6 E& c( B
9 i/ j. [3 y$ L8 n$ W
                output = (INT)out;% w- _& D) r# v4 h, d: E* Q# |
                }
! E7 }1 W7 o8 ~#endif
! k! U( I! H& I, C#if        0  ^- S: S9 m  d( a% i! Q1 B0 [, r
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
& s" A+ Z) F9 M" j                {* X$ ]# T- v3 M6 n  }
                INT        diff = abs(output-last_data);! M4 b8 [  o# W5 L" q# c
                if( diff > 0x4000 ) {
- o& c0 k) o7 j, N/ _7 M                        output /= 4;
) R" w  z+ _7 `% }) B3 @                } else
$ {+ h2 U8 D  z$ {  S                if( diff > 0x3000 ) {! i1 ~; B. c9 s
                        output /= 3;
3 I9 Q$ x+ _6 ?7 A/ S) h                } else
9 M6 T# R" U! K1 E5 ^% _                if( diff > 0x2000 ) {
/ V' K, g) k$ H6 t# h6 k                        output /= 2;: D: k. X3 @' @
                }$ y. h; J* h$ M! N: h) p7 T
                last_data = output;
. {4 H  O8 g  P, |" \. W5 P                }; M! C' |; C+ L6 ?  v/ K
#endif
6 W. h7 a9 w1 a7 e  N                // Limit
, B& q& p" H0 g' @                if( output > 0x7FFF ) {9 M) C0 w' }$ T$ m! D- O+ J, S5 r! F
                        output = 0x7FFF;
- Z5 Z( \6 s2 l# t% ^& V                } else if( output < -0x8000 ) {
! Y% D2 N7 b# w" h- ^% ]* o! J# Q$ t                        output = -0x8000;3 g. e; g, H1 O, ^% |- ~- j
                }& A3 @' n. I: l
; {2 V  q0 W6 c
                if( nBits != 8 ) {
# u$ a; I' J# c2 t                        *(SHORT*)lpBuffer = (SHORT)output;9 g- g% _. H2 {- i, b3 g
                        lpBuffer += sizeof(SHORT);
1 B% g& c1 L) n7 B                } else {# \. p8 m' y; }, H5 }
                        *lpBuffer++ = (output>>8)^0x80;, u( w  H( p2 T8 w6 z* ^# R( X
                }
9 \7 m; ?# p* J& |
, F7 O( i; b" Z, N" W$ |( A                if( nCcount < 0x0100 )' d2 X/ C* E9 Q6 P$ o
                        pSoundBuf[nCcount++] = (SHORT)output;
/ u# P" i/ _  F- N; D' I
& V& c9 D5 T! X' R  [( v6 l0 e% q# X//                elapsedtime += cycle_rate;
4 \9 w1 H0 k2 J% M8 ^/ C/ H                elapsed_time += cycle_rate;- l8 W. N  V* Y* S2 @8 u: A( `
        }
! k' k: N' s; {- z8 P# g2 q- D) j& ]# [+ R
#if        16 z6 K/ D" Z9 `* c' U( L0 O% u7 ]
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {8 @% l. F9 J  c2 }
                elapsed_time = nes->cpu->GetTotalCycles();& H* x1 V* v% D
        }
) ~7 ^8 F& v1 {/ B& [4 o        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
) ~4 Q) O- W- n* t* _                elapsed_time = nes->cpu->GetTotalCycles();+ ^# `' u/ [$ a' }5 {( I5 p6 R, G
        }/ ]5 O5 O7 q# g; W7 M4 x& s
#else3 s# \4 Y* p4 d6 R& T1 J$ W+ \4 z
        elapsed_time = nes->cpu->GetTotalCycles();
9 t" S5 Y0 L% L3 l$ d0 u#endif4 |' S3 F4 F3 q4 x& G( }
}( c3 o+ |( R5 w+ r/ R$ {2 K
% ^$ D( a& d% n6 Z! {, J# N
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
. r/ p- \8 l$ l; {+ S8 dINT        APU::GetChannelFrequency( INT no )
! ?& e1 U- B% J; v: q, R1 f1 Y{3 B, x+ S' o& B' p2 @; d7 H! B" k+ ]( j
        if( !m_bMute[0] )' A  O5 ], P7 i( J5 J/ \  j, k2 g
                return        0;5 L' u+ j7 g1 Q7 ?7 F: g3 L

( b$ e/ c  S5 [, x, p" ~$ t        // Internal- \$ P3 w& A( K6 X
        if( no < 5 ) {
5 m. u% Z5 ?, w( k" l                return        m_bMute[no+1]?internal.GetFreq( no ):0;5 g+ l1 F5 F4 y4 M
        }
3 C5 j) `* t3 b$ \; N        // VRC66 R! l7 `7 R& P$ f/ d' W- G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {" Q- ^# E: o. x5 ]9 @6 r0 q, R
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! [7 M, A% I3 I: x7 G
        }% W" V$ u0 k" G7 F" z; d7 o
        // FDS
5 Q: I( R1 A7 a3 R: {        if( (exsound_select & 0x04) && no == 0x300 ) {
; e3 c  ]& @+ E# ^( O                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; t' ?& ~% t1 ^  ?7 G. ~2 l. A        }/ r( I4 a; u7 k/ |
        // MMC5
+ a& w7 X1 y2 A        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
. H* f5 h6 X( W                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
7 Y4 Q! @$ t+ h  n: j1 a: J        }
: W0 ^) K' ~, S) p/ X3 @7 O# ]: `        // N106
& V7 o) t% r$ \: a5 V. ^* c. {4 F        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {! M) I9 C: _$ G4 w4 w4 E9 A( K
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;( Y4 z* S* j/ ]5 I
        }6 o- h' Y4 D0 W  P( ^) l8 G
        // FME7
  U% c" x8 N4 U; G. E; X        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {. C3 I3 e6 C! v* l+ F5 j, ~
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;- N. ^% g, J5 c6 I/ a1 i
        }  c+ o8 Q; @$ H6 W9 D& ?$ A
        // VRC77 O+ t* M# b4 U. v5 u8 ~* K+ i
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
# ?1 N8 ^! N" Z9 e6 I) H7 [$ K                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;" F0 X# r6 C. u# f
        }
# i- s/ a# a" b        return        0;/ R8 W+ B4 X- k9 N# u
}/ L+ }- ]) A) k  h! o/ `$ k/ f2 Q
) @2 _. O9 g: T% g
// State Save/Load
" a+ t: z: b/ [void        APU::SaveState( LPBYTE p )$ q; i- N2 m9 {
{. I) z* y$ \7 l, v
#ifdef        _DEBUG
; n! f- {; _4 K- a- uLPBYTE        pold = p;7 X% t+ E3 _  ^6 T7 u# [7 y& a
#endif4 d: b% c3 t* }

! a' d  s, a1 \6 [0 Z        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% u$ `* ^/ ^  U9 Z! r        QueueFlush();
# u# [1 l& I) s; a
0 H: @, J& W" ~1 V) E; L/ l        internal.SaveState( p );
8 E3 M, i% s9 I9 `  t        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! Y' p. m! U. H4 v8 W( `' X
, }0 D/ J- M- j( S" w( N' a        // VRC6* P$ ]/ {& H7 z7 J; D2 l
        if( exsound_select & 0x01 ) {' g( P4 ?  _+ l8 N
                vrc6.SaveState( p );! `0 n; j$ K/ E( T
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 ]  u* b" l2 H. |        }
! z5 X$ ~5 k$ W        // VRC7 (not support)
0 o8 f1 d' H6 u% `) v& I  |        if( exsound_select & 0x02 ) {; A. B2 h8 v( o% O, G4 C
                vrc7.SaveState( p );
; c& ~0 T/ x. t+ u                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 E5 A* Q9 {3 c, B' R        }6 q; ]! K9 E. @, x& }
        // FDS- z% A$ r6 A; c- D: ]
        if( exsound_select & 0x04 ) {
  v  G$ b$ B4 x& ]' x6 }" u+ c5 i- m                fds.SaveState( p );/ l* S) n1 h0 W5 a7 @
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* J$ n/ _% A) u) t' U        }  |3 j" R5 j* t( R1 Q- m% P+ _
        // MMC5
; x3 g" R: o! Q% A        if( exsound_select & 0x08 ) {
" z9 u4 O6 t* [/ a  G1 l7 M                mmc5.SaveState( p );
9 V; R$ r7 s- O9 e6 w# U                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ K# j7 v: N% x4 X; Q8 U8 v        }
6 C( Z2 k% \- x, e$ G& Q        // N106+ B( z& D( f4 J
        if( exsound_select & 0x10 ) {4 M, T; Y* D! r+ c; z5 ?6 [% O
                n106.SaveState( p );- j1 ?* }& _; Y: u1 ?1 V) S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* X; b" _6 ~0 d0 ~& C2 Q* J        }3 H7 u- w3 z/ x/ E+ R) ^
        // FME7
+ j; N6 U% u3 }9 o        if( exsound_select & 0x20 ) {+ S, S( \  a! `0 T3 U5 u' h
                fme7.SaveState( p );
' i* g9 Y7 e1 U                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ v- W$ b3 Z1 W, z0 q% P/ E
        }" N8 _% [+ z; Q0 l" h( N! s

7 F# U( N5 Y5 v#ifdef        _DEBUG
1 u. M' U9 z, S$ F, d) BDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
1 p; J* H2 [  N0 u) l7 N2 x#endif! q& h9 R+ s1 T. S% C' J: q1 f+ t
}  w% ~4 M- J) A" C! V1 u" n6 v

' I5 _- Y" i: ~6 y8 @0 m5 N" c) ?void        APU::LoadState( LPBYTE p ). e8 J6 w. I* N) l( {! c
{: W# R; n! i  d$ n7 h# }
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
+ D! J" V, O$ B! Q        QueueClear();% z  l6 B0 g: y1 V) U+ f( B- C9 ~
4 Z: k: H& v$ x9 P
        internal.LoadState( p );, s5 C" B4 a$ ^1 l9 D
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 q3 h( ?# Q! O( Q
6 }$ R; X: E# N4 U" m  u* F        // VRC6/ E. T; E; \0 s$ F3 M# ^$ C
        if( exsound_select & 0x01 ) {
7 J- q* z: M  m' `* f( V                vrc6.LoadState( p );
2 c  `  R- I: {+ M& q                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* U, ]$ S$ S! r3 C. o& ~. c$ c        }
) b3 ~6 Z! z3 v% K4 S: n2 c1 G1 Z        // VRC7 (not support). c& Q) @5 P7 B7 y- A: h7 H- N
        if( exsound_select & 0x02 ) {
# W4 H) C  ?2 Y' u$ |                vrc7.LoadState( p );
" @; D% U  u( l3 I! A& Z; q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 V  p4 j+ B3 c* }        }
9 r5 \4 @4 {! ^  w  `4 Z        // FDS  H/ ?# ~+ s& Q9 p# @
        if( exsound_select & 0x04 ) {: u. W( C6 O, T
                fds.LoadState( p );1 v) G3 z7 [! N  y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 S* o4 T5 Y, S( k' d* e
        }4 E& g  }/ x6 U; o# q7 Y. T5 U
        // MMC5$ N4 r0 B& N% }% X9 H( A4 M- B
        if( exsound_select & 0x08 ) {
2 J6 Z0 n& ]8 Z5 Q  {8 f                mmc5.LoadState( p );! y; f; R5 C0 u5 S% B1 e( m+ x
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 w. }; U- {. `2 k# r9 s4 }- k
        }8 f* f0 q% b/ c- t7 I4 f- i! i
        // N106
- e' ?: C# o4 O. u        if( exsound_select & 0x10 ) {3 V* O. P; Y' K! A/ [) G& p0 C
                n106.LoadState( p );
4 {/ ?! }4 B$ H                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding) l+ ^$ t9 x2 Q5 T2 y3 t* S
        }7 k9 t: Y9 y* \, R  X0 O* u3 ^, e
        // FME77 E8 z& d3 L+ O4 [0 N& c# ~. x
        if( exsound_select & 0x20 ) {
! F$ r: n- t% g+ t* _                fme7.LoadState( p );
8 {4 e8 g" y) E$ W: m                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* [' L" h3 f6 ?4 ]* U$ I        }
' }  _$ S$ E/ {6 [/ S# B6 E( h}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
0 m& G5 {9 C; f' Z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
* Y& q8 L6 ?' }" @# J8 x感激不尽~~
9 D( O  r+ {# ~, k4 w
恩 我對模擬器不是很有研究,
" i: U) h4 O* A雖然要了解源碼內容,可能不是很困難,
. \. h- p9 ]" ?" h不過還是要花時間,個人目前蠻忙碌的。
- J1 T0 A- N+ H3 m9 F( V: s/ m) c- b! O
給你一個朋友的MSN,你可以跟他討論看看,* R2 U, r) L; k, H( `
他本身是程式設計師,也對FC模擬器很有興趣。+ g  `' c1 P( D0 u! H- C0 T
% ^/ ^3 n+ P; Z6 d* J/ G* _
MSN我就PM到你的信箱了。: W# O- x6 j6 a3 T6 \2 K
5 O& Y% l; I2 ^& b5 b' {+ [  L
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
8 h- \- L+ Q2 F8 [! ?呵…… 谢过团长大人~~

$ ^& {6 L5 u3 w6 ~, l: a7 `- x; k
7 v7 G& S+ e/ u1 k& |1 s哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
1 l$ o2 y9 O* k$ _% ?; Z团长的朋友都是神,那团长就是神的boss。
/ P. q* J1 i! C, g
哈 不敢當,我只是個平凡人,, l/ k4 V0 `4 l- [& t
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙: B& ~+ U  S2 z
ZYH
3 ~) [7 n& s  z+ P, P4 i1 Y& ZQQ:414734306: E' W7 o. U! f4 Z- D. r. \' {3 l
Mail:zyh-01@126.com
+ p  O0 l, B: [+ i5 ^1 h
1 U0 }9 H, P) O3 l0 {+ F) q. K1 ^- m他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
# Q( m6 Y7 S, X" m再次对团长大人和悠悠哥的无私帮助表示感谢~~

& k/ B( Q3 K) F2 ~  ^/ j不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-8 17:41 , Processed in 1.087891 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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