EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。% G0 V/ n8 u6 y) ^0 y: j
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% ~* L/ x/ k8 i这里有相应的模拟器源码,就当送给大侠了~~
1 Y" p- N* ?' o, f: b( Phttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
4 o* [& C+ m% I) {5 \+ o4 h" D能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" L6 a# J$ j6 M9 |9 b) l楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% b( ^/ g. q  d+ G! I这里有相应的模拟器源码,就当送给大侠 ...
, Q9 L/ q5 P! \7 c& h
聲音部分(Audoi Process Unit = APU):8 @' N' L; E- j9 b+ ]' s
.\NES\APU.cpp; j3 b% M. v+ u( o( z( R9 @
.\NES\APU.h+ s, \4 E% K. ~
1 t/ m+ f! X( L2 O$ Y. a3 J

0 g6 f. ^2 d4 v4 \影像處理部份(Picture Processing Unit = PPU):
9 H9 }, j: F) Q1 b9 R! f1 |.\NES\PPU.cpp: c3 e, D- Z1 M) b3 X
.\NES\PPU.h
( ?3 L- e1 Y3 A0 G/ W- r
; f: }3 O: [1 Q! V如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 E9 r8 v5 ?) M& M
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
6 Y$ n- G- r/ i+ X: |! e/ ]4 s//////////////////////////////////////////////////////////////////////////
5 y! w1 D. C' }- @" j8 \//                                                                      //
, f' }# F7 A8 F2 a8 u* i1 b//      NES APU core                                                    //
* S8 n" i4 w7 l* i# I$ p2 d//                                                           Norix      //
1 k% N7 i6 i6 R$ b' A4 `//                                               written     2002/06/27 //- G' y* \; w3 X* q+ v8 m- j
//                                               last modify ----/--/-- //
% s5 g6 y7 I. f4 ^//////////////////////////////////////////////////////////////////////////
& A+ }# ~2 Q6 d' g#include "DebugOut.h"
6 c8 }* N% y2 u) F#include "App.h"
" T/ Y# ]/ J; _9 ?#include "Config.h"6 U" M' ~7 C/ i; y1 F: J8 v

# l; e& b. f. {6 k  v#include "nes.h"
. S; A8 Y3 V4 f2 g#include "mmu.h"" y. z" M0 F) P
#include "cpu.h"
$ |/ y; D3 P6 z#include "ppu.h"
2 Z/ W( u, v9 n3 B  b. |$ y#include "rom.h"
5 x- S) |. G% N/ u/ s) [/ w#include "apu.h"
' J3 V* v+ X5 f6 @- s, j
& g2 h* K, W9 b& T9 r' L: u# w// Volume adjust
) E5 J6 i% ~! S0 h// Internal sounds# Y8 S% e( @" M$ t7 ~
#define        RECTANGLE_VOL        (0x0F0)
0 L0 v2 x" A8 {! O1 [& W2 |& D# W#define        TRIANGLE_VOL        (0x130): m! Y; y+ A3 h! Z0 U; F! D
#define        NOISE_VOL        (0x0C0)
- {1 Q  {# V& G2 `9 f4 \#define        DPCM_VOL        (0x0F0)6 e) Y' i7 J% U, Z$ e" l% s. F
// Extra sounds  r7 t9 V6 U  H# d. R3 |7 d" g
#define        VRC6_VOL        (0x0F0)) F" L2 Q9 I4 L3 ^9 _0 _
#define        VRC7_VOL        (0x130)3 W# C! U4 _  }! N) o
#define        FDS_VOL                (0x0F0)
9 q2 k$ }; {) c" @- b#define        MMC5_VOL        (0x0F0)
% M0 b4 Y. q1 d% T& K6 B- H! Z% V% E#define        N106_VOL        (0x088). t# w* b  R3 G: k# M6 h
#define        FME7_VOL        (0x130)5 K- X9 q4 c* Z7 I1 `8 q
! L& E( u9 r( F# R6 B2 @
APU::APU( NES* parent )
, q" }( ?, t7 t4 K, p! {{
, B8 S! y0 X6 R& l9 [9 m        exsound_select = 0;, h' x6 l7 P0 `' `8 J+ q4 q7 O
0 Q" _& o8 D" ]* z' \) Z; ~
        nes = parent;
4 S0 y& e" B8 e" U1 Z  A6 j        internal.SetParent( parent );
# G) _  q  G# L* A. F  d  M5 ?& M3 u( v$ X$ T
        last_data = last_diff = 0;% I& r3 O% j; e- p, O# o1 o9 S% Y
7 G$ f: E) R6 C* s8 @& y
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );: |. ^# D3 Z/ D: {2 Q$ k/ S3 |
+ ~, f* h" G* D4 T( C' g8 `
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
, I4 N' ]9 ]! Y        ZEROMEMORY( &queue, sizeof(queue) );4 Q7 C) n& O2 s+ o% q# o9 o# ~
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( T, Z0 q( q6 ^- Z0 V9 J6 Y3 x5 B$ D3 ~) S
        for( INT i = 0; i < 16; i++ ) {
1 a. S  [& `' p; m                m_bMute = TRUE;. M4 ?) s* ^' b; u# ^
        }7 x8 x* Z' r4 v; H' O! f
}* y5 {% ^6 V3 [0 d3 q* I) w

1 ^6 R) ~# Q; n) {" a( wAPU::~APU()
$ |; @/ ?  N- ?3 i0 r# B' X0 |1 j# C; ?+ H{! _* I% r, e7 g7 e
}5 y% j4 T0 P% m5 \7 b4 @
1 u1 y: a/ {7 Y& X- c5 T
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' J4 S$ s1 g9 B$ {' d/ g5 C/ m{* f# F3 L. ?" G
        queue.data[queue.wrptr].time = writetime;/ G0 p8 J( T. F2 U
        queue.data[queue.wrptr].addr = addr;
) ^; D. |, ~, j* ~$ A        queue.data[queue.wrptr].data = data;# ?- v1 l5 k! c+ J- T
        queue.wrptr++;% w+ L0 C/ E7 Z' n
        queue.wrptr&=QUEUE_LENGTH-1;2 Q  N# l  X" Z% m9 V1 t$ o. I
        if( queue.wrptr == queue.rdptr ) {
/ d# L! x1 _& T                DEBUGOUT( "queue overflow.\n" );
1 w: G% f5 ~7 `0 ?  B5 E  n" d        }
; u, m4 u( U+ A; \+ s}
3 _% ^' Z$ V' J. n' F& \: g: `+ C% M3 p) Q& m
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
: b, Y+ m; T+ o" W8 Q' |6 \{! }" A7 g$ q0 f; S+ V$ u! I/ A) G6 Z
        if( queue.wrptr == queue.rdptr ) {
! |; _* P: ?3 U- {, h) x. S/ w                return        FALSE;
4 l% B+ h! J5 w5 i- }  T! W        }' z" @, y, L; }' K- L+ o
        if( queue.data[queue.rdptr].time <= writetime ) {
. G2 S5 L6 |8 }                ret = queue.data[queue.rdptr];. d" n' f' q/ W  h* z- y
                queue.rdptr++;
* [! Z6 w5 t6 G( G                queue.rdptr&=QUEUE_LENGTH-1;
+ Y# {* R9 O) j( h8 V  c7 E6 c                return        TRUE;
0 c0 x7 I, X$ ]" Y' J7 e        }
) b$ M, F: r( E8 \* c        return        FALSE;
9 M- V9 k* m" b* N5 t# F1 Z}
3 w/ ?# N* s% D5 ~5 v8 A' _2 t( t9 c$ p
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 m' n3 A: h; F$ O7 B8 i8 P( @2 O0 ?{
& T& W! Q; U$ C$ `        exqueue.data[exqueue.wrptr].time = writetime;
6 l, Y6 K" e% h        exqueue.data[exqueue.wrptr].addr = addr;9 X  h& T4 W" _2 D
        exqueue.data[exqueue.wrptr].data = data;
3 b" x( x! Q+ S" n, e* R        exqueue.wrptr++;$ R8 w& S/ ]& l, ^
        exqueue.wrptr&=QUEUE_LENGTH-1;
0 y0 \, _" T3 c9 G6 p( T0 x& r" y        if( exqueue.wrptr == exqueue.rdptr ) {& _. |- g: h% X, s0 w# _
                DEBUGOUT( "exqueue overflow.\n" );; p2 _4 K& Z1 H2 [$ h7 e
        }) E9 r" o1 I( C. P
}
- J2 Q3 Q  y! y  I; Q/ O: b+ ^
3 V- Y* z4 C5 w0 ]7 x. o/ LBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
% ^& q/ Y+ H5 j" ~7 g/ {' E{
2 U2 u: c+ U6 D% ^* }* y; G        if( exqueue.wrptr == exqueue.rdptr ) {
! d! v- i- ?& v- S                return        FALSE;
* T3 g. C9 }3 d        }
7 m+ l/ ^7 m; R        if( exqueue.data[exqueue.rdptr].time <= writetime ) {: u( a0 l  Y3 f! |, j; X& R* s* ~
                ret = exqueue.data[exqueue.rdptr];3 _% B. `8 m2 y" h! f
                exqueue.rdptr++;; k! r; Y2 r1 J8 U
                exqueue.rdptr&=QUEUE_LENGTH-1;3 \/ ?1 P6 [& b: n- ?: U4 F
                return        TRUE;
/ r3 s$ V0 e, A. c" e# e2 P        }7 r! C8 a% ?, U/ @; D
        return        FALSE;
3 `5 }6 b+ r1 S9 H}3 m" a1 {; x. b, U0 v

4 ~1 B9 D5 I$ q$ ~9 Y, uvoid        APU::QueueClear()3 z% V: j0 {: k7 y
{$ A4 I- T% e" ?' @8 }
        ZEROMEMORY( &queue, sizeof(queue) );
7 `2 ?9 A0 s( c1 h8 q: J$ g        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% Z: s9 w3 S6 i2 J3 s9 X: g7 N}- \  ?3 F4 ^8 ^/ V, i: J/ F3 J/ G
, y; l, B1 O! y* F) P* _1 k
void        APU::QueueFlush()
- ?0 X( r5 s5 S5 P* c) `" z{0 a2 I+ S3 u9 i: ]9 z( x
        while( queue.wrptr != queue.rdptr ) {
+ q! J& j: W1 W. U, }( K- t                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
! k2 y+ X* i+ v& u6 A                queue.rdptr++;/ |9 }1 W4 b8 c0 h# D  t
                queue.rdptr&=QUEUE_LENGTH-1;
* w  M: X% k( Q        }
  F% c9 Y8 K- T" n$ s5 `7 _- A! ^+ a. I) {6 z( g( U
        while( exqueue.wrptr != exqueue.rdptr ) {
; b9 s8 R  M+ w# ~8 b( ~& N* Q8 R                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );; u. K2 U& R7 T' x. @" m3 K
                exqueue.rdptr++;( O# O0 S" [' K- r# r* Z
                exqueue.rdptr&=QUEUE_LENGTH-1;
: F4 W1 W" T" H: g& c% O" n4 d( E        }
* q$ m5 L" |3 u9 e}
7 {' M: N+ G# I$ E+ X$ c* ]5 m
: Z; Y: F+ J3 Dvoid        APU::SoundSetup()
1 [; S9 r6 r; ?! H0 E; }4 a{
( s% @8 ~8 }9 p; T" s' L        FLOAT        fClock = nes->nescfg->CpuClock;$ ^* H( F5 J+ u
        INT        nRate = (INT)Config.sound.nRate;' J7 g  ?! T. h. m
        internal.Setup( fClock, nRate );
3 V0 X/ s, r5 X        vrc6.Setup( fClock, nRate );
) L+ x. G5 V- N' w        vrc7.Setup( fClock, nRate );7 p7 p' u1 l/ q0 Z0 |8 i8 w4 d
        mmc5.Setup( fClock, nRate );; t3 ]4 l  s4 m( V
        fds.Setup ( fClock, nRate );
5 l  k! E8 L* t" [: t+ t) j        n106.Setup( fClock, nRate );' E& V0 R: [8 D* E! l. e
        fme7.Setup( fClock, nRate );6 P% n1 V: K. B) r2 e
}4 u$ n5 d# A9 y' i+ _0 m
- K# ]2 J6 }- C' Z( d2 c' T  D8 J
void        APU::Reset()
3 c1 r' N7 A1 v" O- O! y{
5 |; y) c- K1 p% i, D        ZEROMEMORY( &queue, sizeof(queue) );  y* s: r8 h1 l$ j$ M7 [. k
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ R9 C9 `) n# E! `  J. W/ b7 R7 _) v  [# W
        elapsed_time = 0;
$ e, h8 f. v" y- \4 d: W# m8 a: _! A+ G: z
        FLOAT        fClock = nes->nescfg->CpuClock;  I6 U5 W" U: o) ?" y, k; q
        INT        nRate = (INT)Config.sound.nRate;
3 V- _5 N6 h" n        internal.Reset( fClock, nRate );
2 h' `1 |/ p  e) w1 z1 K0 J2 C) k        vrc6.Reset( fClock, nRate );
3 L- b$ A$ X4 m* f2 r        vrc7.Reset( fClock, nRate );3 A: b/ n9 C. D$ }- G: _, Z
        mmc5.Reset( fClock, nRate );
) B5 C5 R$ Z( d        fds.Reset ( fClock, nRate );, O& m: g* q& c) ?8 a
        n106.Reset( fClock, nRate );. o, [) R0 a' i1 u, ~0 \
        fme7.Reset( fClock, nRate );
% d. g* f1 F0 G9 q' l$ }4 \0 }# l" Z: I- c0 S
        SoundSetup();
1 t% N4 F+ x; X2 M. j2 c( h}& D- M0 c( H5 b+ R
+ t! k$ Y1 d/ }+ [2 E
void        APU::SelectExSound( BYTE data )
/ \2 O" y) G. C" V3 u/ ~, _{
- s' [& C: y9 g8 I6 B6 V        exsound_select = data;* O0 P0 }$ R% `" ?& g" [1 s
}. x# y8 D9 {, _. y3 i0 O+ `

3 R$ B6 T, q" D. T/ f( oBYTE        APU::Read( WORD addr )& V+ J  ^# k* u" Y0 x
{" F4 v. P, z) I* A+ x# C) }( @
        return        internal.SyncRead( addr );  ]0 T. P( m/ z  `7 T
}, h2 M. l! U, U" F- z

' G+ F) u( {  M$ A4 O! p  K! evoid        APU::Write( WORD addr, BYTE data )9 b' ~. l. ?, R4 ~
{
* N" O) {7 q3 R8 A. T        // $4018偼VirtuaNES屌桳億乕僩( i# b) F# k9 T) ]  x) K
        if( addr >= 0x4000 && addr <= 0x401F ) {6 i6 x6 g/ J) T
                internal.SyncWrite( addr, data );
  r: t. [, f+ _# g                SetQueue( nes->cpu->GetTotalCycles(), addr, data );- b: B' m" }5 f" S; g
        }
" H0 ]5 }6 e9 }! Z8 g7 G}' G' d/ u' B) c2 P& C$ n4 N8 G

2 ^4 X: ^3 {  [0 ?7 hBYTE        APU::ExRead( WORD addr )
* q2 J8 r1 k1 y) ?( H7 l  j{
) `' i7 m0 a  v4 Y( \% `3 pBYTE        data = 0;9 P' m* F5 @( t$ |
9 w( @- H; Q5 C* j- |) m
        if( exsound_select & 0x10 ) {
( t8 c* R+ _6 @- o9 |2 {                if( addr == 0x4800 ) {0 g$ q. Z* I: y# [7 r# F
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );; Y* n# z7 ?" {% ]
                }$ f0 E& q; B$ _
        }
' g0 {) p" ]4 d' |' Q/ F3 O; ]        if( exsound_select & 0x04 ) {
( V/ ]- }" [. L8 [0 Q2 Y4 g) `                if( addr >= 0x4040 && addr < 0x4100 ) {
7 q+ |9 N# z/ B! B( v- S( D                        data = fds.SyncRead( addr );
- a3 t& \/ O3 N3 u                }
! Z1 [9 r1 j+ Q        }
. L: S1 @3 Z% s: T+ U  A; W        if( exsound_select & 0x08 ) {
7 i) f: u# n+ N, V( _: I                if( addr >= 0x5000 && addr <= 0x5015 ) {
- B( h. s: X* M' v, }2 S                        data = mmc5.SyncRead( addr );7 p; m, w' X! z2 j
                }7 {9 \& o, c5 }/ t: D
        }$ V2 o1 X: x0 n  @

% Z! I' b' N( |$ I& i        return        data;8 X0 ^7 @( G" b4 |
}* A5 P2 ]7 e8 Q4 g: |( P+ B
7 }% b2 J0 [- Z2 t' [
void        APU::ExWrite( WORD addr, BYTE data )& g. \5 E7 I4 c9 ~! B
{- B$ S$ M0 F# T2 h
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );8 d) W3 [! W8 _2 l0 |

# f  Z6 }4 \1 a        if( exsound_select & 0x04 ) {
0 D/ Y, U, ]5 _" y* ^1 S$ j                if( addr >= 0x4040 && addr < 0x4100 ) {
# E) n, ~. {* G                        fds.SyncWrite( addr, data );! r& a9 D  W& I$ ^; x5 ~
                }
  w( [1 ~0 t# I# Q! P        }
. w; N6 \/ Z# C! }) w1 m* _( e
: ?  j( C$ E5 ~9 G7 x+ s6 T        if( exsound_select & 0x08 ) {
, r+ M# Q* G7 G  u' t                if( addr >= 0x5000 && addr <= 0x5015 ) {$ w# S0 d7 T8 Q3 _# D& U1 W  ^
                        mmc5.SyncWrite( addr, data );4 _: b' ]+ b$ [) v3 ~8 M3 L
                }% N- B# X  p0 ]: J: }5 `
        }
$ s* y% V: M% w}) b" z7 X9 p9 x4 b' E

$ Q* }! k) u* B1 w1 Ovoid        APU::Sync()5 g# w8 W# O" u
{
8 W, m, {  h! l}
2 `& _  P8 ]6 j& x% g# J# N5 R* Q' {
void        APU::SyncDPCM( INT cycles )% M3 s4 H& c: p! Z& f+ u
{( W6 k1 h, G# f3 G; ~; c
        internal.Sync( cycles );
* f2 E  ?3 g. t5 O: }, D- d5 n7 I) i. G6 G
        if( exsound_select & 0x04 ) {( x/ ]' e: z3 E' l! d6 O. O
                fds.Sync( cycles );$ j2 L0 S! o4 \8 F$ K! T
        }
0 B. f2 K5 p  w% m4 L) ~  G/ I! C        if( exsound_select & 0x08 ) {9 l- w, B- X; K% l1 E& U$ Q
                mmc5.Sync( cycles );
/ A: d6 k+ E* o8 H        }
3 U, i) Y+ K5 |  X% ^; l$ r}
) d/ B9 M! |* A& [
+ y# p7 F% Q1 d$ u* q+ [7 @' wvoid        APU::WriteProcess( WORD addr, BYTE data )! C1 C' y# m  g  v5 X7 f4 h
{/ j# k3 G: o$ Q8 o& y
        // $4018偼VirtuaNES屌桳億乕僩2 y% `9 o# w2 }- ~( e
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 }; O# \: u2 y" Z' I                internal.Write( addr, data );% o- x4 f; {& f2 c  l) ~( |) d
        }( X  R: z' ?' A8 ^
}
. [2 z1 d! G: z, V
' d: J3 z8 @$ z( R3 Jvoid        APU::WriteExProcess( WORD addr, BYTE data )7 s+ I* c' w" _5 ~2 V
{
1 I+ I+ x1 V7 ~( l  A8 t        if( exsound_select & 0x01 ) {
6 N) \: q6 j; q                vrc6.Write( addr, data );! k8 |8 h% {6 C& T3 D
        }
- l7 f3 v) A: W1 e! _3 S# O* P        if( exsound_select & 0x02 ) {% M2 c; W2 ]0 o3 K5 G" E# C: f7 G2 Y) r
                vrc7.Write( addr, data );
6 j% e( ^( ~3 ]' a' f# [3 Z( ^        }* T# k1 I' |7 D, q" f0 u8 [/ j
        if( exsound_select & 0x04 ) {2 @+ _1 X5 z5 G  e5 q
                fds.Write( addr, data );
% W5 L: I& w+ I2 ]) s; m1 f        }
5 K( v' ]% I1 X3 @% ?8 W        if( exsound_select & 0x08 ) {
7 d2 n0 W7 u' k5 V  U1 l                mmc5.Write( addr, data );! L: n; f! ~* j# o: {( _7 h8 s0 M
        }/ M# a% S! p& f9 S* a
        if( exsound_select & 0x10 ) {9 @( v  _1 U+ q  I
                if( addr == 0x0000 ) {
8 L' _7 G  Y1 v, u9 L2 J                        BYTE        dummy = n106.Read( addr );
6 B# h) e$ R. R6 Y                } else {
; p2 F+ s7 X( `0 F* c                        n106.Write( addr, data );  t) D* I# J2 `1 a0 p3 D
                }
: P. o$ d% U6 e  R        }
+ U/ L- H" s* U1 B5 w+ z        if( exsound_select & 0x20 ) {4 l; ^" }3 g7 t
                fme7.Write( addr, data );# L; O4 }' \, u! C9 N) A. ~. a
        }
4 ]( ]% K5 S( C* {' m( B; S}  V- }2 @# y- N8 Z# d# W. T- B
% F0 h$ |/ G" W1 q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )$ u" D& G$ `3 o; |) b
{
; F! J4 K# @8 V1 @+ IINT        nBits = Config.sound.nBits;  e5 ^, v4 @" I1 {
DWORD        dwLength = dwSize / (nBits/8);
) A) \  S0 v1 C  YINT        output;
# J7 y" ]3 z5 t% s! xQUEUEDATA q;
* ^/ D# R* K2 @2 r3 f4 E' ]DWORD        writetime;
! ?2 k& J4 e5 G2 Y5 |' i
& S& g0 Y* k' ~9 E& a! @LPSHORT        pSoundBuf = m_SoundBuffer;: x) a! q- r3 Z
INT        nCcount = 0;4 g3 K) Y5 k6 N& H' ], \1 Y) O

9 @! ]) `9 [: e* w, \$ VINT        nFilterType = Config.sound.nFilterType;
/ J7 [$ c2 A9 _! g1 O9 ~. ]+ G+ B5 V- I+ M+ s
        if( !Config.sound.bEnable ) {
8 c" V6 N8 b# {9 H4 t2 |1 u' [$ B                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
2 ^" p2 m* q+ A, Y  Z                return;
& k; X" ]6 O8 N5 O; x        }
5 ^+ k. R' w: V
4 F$ V# w: I2 d# F  V        // Volume setup- i/ Z. V7 K- _% K, ?* `+ \
        //  0:Master1 I& w' `6 \9 f- c( E; w
        //  1:Rectangle 1
$ T" X2 j9 ~- P0 k; U' C        //  2:Rectangle 2, O$ t: ]# ]! V
        //  3:Triangle% @% M0 g& g% x; S- x3 {
        //  4:Noise
+ q& }/ i& C+ Q  y9 P        //  5:DPCM
/ x! T0 \( w/ b4 q% j# ^        //  6:VRC6& O# C; o. M# S) G
        //  7:VRC7
+ r- _' H% d8 Z1 R  h        //  8:FDS
9 ]) O. ]) m. q5 P/ `        //  9:MMC5
3 x2 }: _5 S" z- \7 N9 K4 P$ Y1 M; A        // 10:N106
2 D; q0 D* Z/ {: W4 z& y/ _        // 11:FME7
2 T+ @4 g) P" i/ |$ r- i4 a        INT        vol[24];- ?, a! p: d0 p( o7 D
        BOOL*        bMute = m_bMute;) a9 E. w2 n3 ^/ V/ ~4 X
        SHORT*        nVolume = Config.sound.nVolume;
6 Y7 \  ^  a6 k# x" ^3 f8 g' o' z4 \/ S$ q9 o+ U6 s3 F) T+ b
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;7 Q' L) K- r1 ?$ u4 }. |

& p% |  n" ~8 S2 D$ j        // Internal
1 ~. ?6 K4 g2 b+ m) _% o        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
! s$ |8 o6 J2 q- C1 ?, g        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  O, b' F$ S% v9 ?, _. ^
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
" Y, d; a6 ]8 [8 L        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 @- d; u/ q/ v- R6 z        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;+ i, u) J7 s8 W; d3 m* }& I
# o  n+ U6 ~# Z3 i) s$ b
        // VRC6; O, C) y. X1 O
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. S  [5 i1 r2 i* N8 R7 q' Y
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; z- J, Z) W- Y# K* R
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: [8 B- h2 q& Y- c+ Y

- |: i3 r% _, a7 z8 b        // VRC7
8 b0 v1 Y% e- F" h6 B2 f        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 |' d5 n; a: K! t1 u& k
- [5 X' i9 A8 z! C' w# D        // FDS2 v6 W3 i4 ~% u  Z( _, |  p' Z
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;: i* U' l; `3 U, p7 c7 {
# Q# @* B$ ~6 t+ k/ ]
        // MMC5
( a; O$ n$ Y- j3 L% Q( |        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% }* R0 f1 l9 O# E        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 z! o6 p2 B8 J+ G        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( J' W( o: H, F9 E# M0 q

' c9 Q" W2 F8 F' V! n        // N106
8 _4 m0 u( p7 _        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. b, I1 u) H9 O" Q) o2 _# f3 `        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ M# M+ y& u" M' Q- l; j+ C        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 @% g) [( ]! H6 w' K/ d7 l        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 i" W3 u3 \) C( \! Q
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# F! w4 E$ [4 h- d. z) s+ a
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 ]. ]8 H! M# M- Z+ A
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ h2 n$ D* x2 ~5 P8 m/ D        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 I* O8 Q* J7 Y! N" L) o
7 ~' Q' |9 Q) X6 ]! A$ q        // FME7
& f9 o. n: n# b3 G& e        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. T$ f* @4 q. e: A        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" U) e6 u- D4 V
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  F7 E1 @1 M" f

* ]/ Z. U9 ?' |5 W1 c//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;6 ]1 y! d6 Q( K7 |# ?/ e! i+ h
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;" Y1 F9 N  f" N9 ^
4 M0 g4 ?0 e8 x& `% a
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟( k, ~, w. W& g- S6 l% y. ^2 @
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {! _& T6 I9 v7 Z/ z
                QueueFlush();, E8 R& k/ g3 p/ g3 T) T( ?
        }
; m3 Y$ a0 f6 g" }9 f
0 E: t2 O0 y) \0 C  p        while( dwLength-- ) {
0 V7 g7 h+ t  n4 Y" [6 T" {                writetime = (DWORD)elapsed_time;
  q! P' ~; s: J3 x. W! _7 w+ Z/ c9 B, k0 I2 N
                while( GetQueue( writetime, q ) ) {
6 g8 ]4 d8 @- r9 w! f! S                        WriteProcess( q.addr, q.data );; z( \! V& K% f2 {
                }
  `7 |4 @/ v! z! L, u0 a
) L3 d5 R. @! |# T                while( GetExQueue( writetime, q ) ) {
& o! w) Y4 Q; F7 d6 K+ D                        WriteExProcess( q.addr, q.data );; j+ `. D6 y0 R. W5 Q" X
                }9 U  O3 Z  S8 G" B* v
+ l8 W9 U3 z' a3 E' e/ g" C5 G9 ]/ L
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7- G4 V& ~' v- i! C% U0 T; v
                output = 0;
# n6 B% c, o: I- ^) i3 U& `                output += internal.Process( 0 )*vol[0];* K& l. {" Q3 K
                output += internal.Process( 1 )*vol[1];
; K  g6 K7 S( l                output += internal.Process( 2 )*vol[2];
# P* p  W8 c' A. r# X3 `                output += internal.Process( 3 )*vol[3];
! Z3 P. `' K! \& _                output += internal.Process( 4 )*vol[4];8 l9 o6 \! l4 O$ t+ e/ f: W8 I
5 D/ ]9 F) q! B( W9 J3 \, u; _
                if( exsound_select & 0x01 ) {. {3 V' l/ V9 ?, R4 a! P2 g! L
                        output += vrc6.Process( 0 )*vol[5];
% y& j( s9 |. s  M4 W7 u: b7 [                        output += vrc6.Process( 1 )*vol[6];$ `% y2 M& l6 b9 d7 G
                        output += vrc6.Process( 2 )*vol[7];; Y* g! n3 L& s8 l5 f' L
                }! b) f9 |$ L& \
                if( exsound_select & 0x02 ) {6 ~* j! K" g7 r, O6 `6 x; g$ O
                        output += vrc7.Process( 0 )*vol[8];3 ^* R1 b) f# W  v; G# D
                }; p- Q& X9 K. |* {# F  h+ O, E* K
                if( exsound_select & 0x04 ) {$ G0 }  F$ Q" Q9 \! c
                        output += fds.Process( 0 )*vol[9];
8 j$ q0 W9 J% [0 h& s/ g$ W9 ^                }
# _; L  y* ^6 s6 r                if( exsound_select & 0x08 ) {
3 p3 [8 |/ |- g# f1 W" f                        output += mmc5.Process( 0 )*vol[10];+ ?) p  R' m+ v$ e! r6 G
                        output += mmc5.Process( 1 )*vol[11];
5 W1 n7 H3 Q- k/ t  o1 a                        output += mmc5.Process( 2 )*vol[12];
, V7 F, s& D. s0 v, ?                }
0 s6 s" R4 O! b. H# [3 S                if( exsound_select & 0x10 ) {3 p+ z6 V1 I5 [& |+ d5 K" T' S
                        output += n106.Process( 0 )*vol[13];! D$ O, T. R7 P9 |% P/ a
                        output += n106.Process( 1 )*vol[14];9 w! G, s6 r1 t  {
                        output += n106.Process( 2 )*vol[15];
$ `3 E( ~! x( _2 F* _' _$ ~: I                        output += n106.Process( 3 )*vol[16];
/ Z" O9 J0 X: h7 a) G7 A) E8 m                        output += n106.Process( 4 )*vol[17];
) ]) f4 f5 A! Q' z" J                        output += n106.Process( 5 )*vol[18];
, {* z2 b8 \! |* y                        output += n106.Process( 6 )*vol[19];
# C7 k% f* n7 Q$ `; b' y9 C1 e7 U                        output += n106.Process( 7 )*vol[20];9 i8 p1 R6 l( M7 s$ v
                }! Z1 G' B9 s" B' C# b8 d
                if( exsound_select & 0x20 ) {
3 a: h# h) |. I. Y                        fme7.Process( 3 );        // Envelope & Noise- O- @: A, a5 g, W, s) R
                        output += fme7.Process( 0 )*vol[21];
; L5 l5 I: P: t* ?" }                        output += fme7.Process( 1 )*vol[22];7 L) N' T# ]& ]4 j" H% c
                        output += fme7.Process( 2 )*vol[23];
* z) t* E- \. }& _6 h! F                }
" |" T; t& H7 Z! o7 x. q- W+ c. h: k% e4 I* o# k' y) K5 d
                output >>= 8;8 {" ~. h0 J5 @8 I; V8 D/ p
* V" n- \- w! H$ i' [: ?. d2 t# O/ K
                if( nFilterType == 1 ) {5 X. U9 J) ^# A) R9 U
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)9 C3 t, r' L) w% e$ |
                        output = (lowpass_filter[0]+output)/2;
, T2 g6 r2 M/ ^) }) Y7 t                        lowpass_filter[0] = output;6 u; W" g5 x- _7 S; ?
                } else if( nFilterType == 2 ) {0 h0 U! q4 a3 c; x+ o. Y. ]' ]
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 L) p6 b( T- p  S2 U0 W( \9 V
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;- b0 G- ?4 P: {1 r4 f4 C
                        lowpass_filter[1] = lowpass_filter[0];
  \" E. z# \' L3 ~                        lowpass_filter[0] = output;8 v6 C+ A/ K% {: e4 L) y
                } else if( nFilterType == 3 ) {
& f# U7 R7 }$ `6 p0 L                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)5 j" w3 D6 k& |/ Z
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
2 d* m( `* T  I5 s% Q/ g% z  u                        lowpass_filter[2] = lowpass_filter[1];6 h. m" p9 N2 n
                        lowpass_filter[1] = lowpass_filter[0];  t5 @- ~' A" W0 X' t9 o
                        lowpass_filter[0] = output;' k. l0 X1 a/ [/ P6 ^. [$ a* T
                } else if( nFilterType == 4 ) {
  Z; [/ E+ ]7 F: y. p% u3 ~                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& v  s% h4 Q/ Q) ^2 T' `- F& Z8 Y6 v$ Y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
& U: w- {/ R) n  h                        lowpass_filter[1] = lowpass_filter[0];
3 d! z! ]8 R3 H. z. W                        lowpass_filter[0] = output;
1 O" [5 P! L/ i+ a2 D3 B                }4 y' @+ E( B$ n/ e* u! \
  o0 n- C/ N: y0 P) m$ L
#if        02 @: n# k; P' w
                // DC惉暘偺僇僢僩3 q5 ^; N# M+ l$ K
                {
% c1 V8 Q5 x$ x! ]8 h1 C. i                static double ave = 0.0, max=0.0, min=0.0;9 \9 i+ B" V$ l  s. O2 N- Y: W
                double delta;
0 t: x* q3 w/ R$ u. L0 i% G                delta = (max-min)/32768.0;
: R* e+ f) H# {, _' w6 A9 ?9 b% _" F                max -= delta;
" p0 h/ g4 }' ~4 }) V1 o  ]; C- v                min += delta;
& X- l8 O4 N. h1 p. t                if( output > max ) max = output;
5 ]6 ~" V# L- ~0 k                if( output < min ) min = output;
2 m8 t+ K) x: y# E                ave -= ave/1024.0;% z+ U  `" s% c' j# S# f9 E
                ave += (max+min)/2048.0;5 A' }& h6 _) I: b
                output -= (INT)ave;
, p* j, E/ f( Y                }) W2 ?1 S, F- M) L) D
#endif
# b4 [, C- v3 `& e, a4 M#if        1- s) J# N- G+ @% x% w# Y
                // DC惉暘偺僇僢僩(HPF TEST): c4 {" [- h1 b! q0 ]/ `' n
                {8 j8 ]/ f/ N" H# E5 O: Y  ~
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
3 \2 m7 D" z9 Q) f. y* _                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 y3 K( l0 Z) f- _8 n                double        cutoff = cutofftemp/(double)Config.sound.nRate;  u9 g3 U% V) V
                static        double        tmp = 0.0;" e' G9 N. V6 D6 e
                double        in, out;1 r2 i! n) M  y! f3 J

) |' G8 q# j3 P2 Y! ^                in = (double)output;% S4 _/ v% ?2 A5 F2 u
                out = (in - tmp);
# c7 o  r" E) Z                tmp = tmp + cutoff * out;
9 y. }: d9 X. R6 D* {* K# I4 W' @8 X  \( B7 n# B/ f' `, k; ^
                output = (INT)out;! a( w: B: O0 [# D# h, v
                }- k) {7 i' y, }" {5 b
#endif
. Z' U/ R; Y8 J6 v, X! O4 S3 k. E#if        0
- v* X7 x/ w* M7 ~: i" I                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* A% C+ N, G$ `* t0 U$ O0 P) |
                {
2 x. \; P, S8 E7 @& S6 X                INT        diff = abs(output-last_data);
! \9 V, U' z( _' M$ r. X                if( diff > 0x4000 ) {1 t  U" E9 J4 u# k, G
                        output /= 4;) o$ `  V# q6 Q9 w2 W
                } else ! O8 \8 @; S/ d( t" z& w+ J
                if( diff > 0x3000 ) {  e! e/ b0 ~+ f2 U+ I- q1 E' m
                        output /= 3;
+ G' j8 T5 c+ [/ Z* |7 |" t                } else
/ B1 K; N1 r0 X5 g+ X                if( diff > 0x2000 ) {
$ N9 T) G0 I4 z                        output /= 2;8 v& m/ g- h& T! h/ a5 F
                }
/ g, b  R% |& M- H( q, C  D                last_data = output;& ]7 d# n% i- t' R& }& M
                }
- p8 `7 ^5 I8 n) W  f  ]' m#endif
7 M$ m9 m% U9 L5 @7 K3 s: }' U4 ^                // Limit) b* F  ]5 j4 ~$ C# {
                if( output > 0x7FFF ) {1 \$ I( ?& D  ]3 _9 v; v0 m- x
                        output = 0x7FFF;8 R; O  {! D3 u% v
                } else if( output < -0x8000 ) {
2 e2 W( N5 Z# Z* a8 L+ W/ j* `                        output = -0x8000;- E: T' R3 [7 L* j) {# t
                }
; `  T  ~$ `/ Q
" ]4 R8 Y* M* Q& h* w1 {, I                if( nBits != 8 ) {8 \0 \  k: K9 ^; z( f' C: T
                        *(SHORT*)lpBuffer = (SHORT)output;
  B$ K- p5 ]2 r0 Y                        lpBuffer += sizeof(SHORT);
. {$ U9 n& w# a  x$ \                } else {' ]$ Q5 ^2 t; c) e6 M  L
                        *lpBuffer++ = (output>>8)^0x80;/ ^0 G9 X! ?: a% F9 a/ C
                }/ h0 i, G; H( M, d* v
1 u7 V$ U, {! n! [, s- l& P0 N
                if( nCcount < 0x0100 )4 t3 Y4 N8 S* c3 h& ]; _
                        pSoundBuf[nCcount++] = (SHORT)output;
% B( S: |) b, e. y" r. R8 \: G; v  M0 s2 g! n
//                elapsedtime += cycle_rate;
1 R: b! j! O# S$ e) x5 e                elapsed_time += cycle_rate;) D: Q$ |" I# Y2 \  s1 K, E+ }
        }& ?: x$ `5 J/ r1 M' x4 j2 s) P2 a2 O
( D2 F2 z/ _$ z- y6 o
#if        1
7 |4 B2 Y3 d+ B7 T        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
. C1 N* E& V, ]) D7 `7 s                elapsed_time = nes->cpu->GetTotalCycles();. o6 r4 A4 B: q: q3 T! ^4 k; K
        }4 h/ ?% Z( Z- A  t" P
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {: A% }1 i( t& {, O3 P6 b8 l
                elapsed_time = nes->cpu->GetTotalCycles();6 V2 Z7 _' J) W
        }
8 E/ c$ e) \2 T#else
# Y: Z& u/ t% u7 D) Q2 J7 `        elapsed_time = nes->cpu->GetTotalCycles();
/ V; q# e8 v* q& A#endif
0 v% B. M: X! O, T$ `9 Z}; p7 ]4 }/ W% D

# [+ H5 }' ~8 \' Q' J: J// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
# g4 J5 H' ]# }; D: g# M5 IINT        APU::GetChannelFrequency( INT no )2 Z3 ?  b) E& @7 W* N: ?
{
6 W/ V/ M, u* ]4 _        if( !m_bMute[0] )4 l' q4 J, b( u' ]5 w! k% J
                return        0;
6 U8 c5 N  ~3 C; P
% `1 ]) K4 {8 q& W  ~: r        // Internal
: k2 f7 N% I2 q& r        if( no < 5 ) {
- [+ J6 W/ m% ^8 u                return        m_bMute[no+1]?internal.GetFreq( no ):0;
9 T+ J' {6 N8 O# Z        }
4 r7 G; d5 e% ^/ l3 s) Q  X        // VRC6* b0 ?$ [+ e/ C$ r
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" K9 P# k, R1 u) s: n  A5 |+ ?+ t                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;) R3 k4 `; r6 ^& u. S& @
        }
# O5 c" I$ G- v2 v/ g  G& J        // FDS
$ S, O( E  e" V& z        if( (exsound_select & 0x04) && no == 0x300 ) {; \. \6 W) |7 ]$ K3 ^2 ?  [- P
                return        m_bMute[6]?fds.GetFreq( 0 ):0;' g- r0 j" t( @
        }
$ [+ E9 B, ^  Z+ U" a        // MMC5
" v0 m8 k" c, x: S& E& x5 \        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {1 B. ^! l! ^- j7 {5 P& w  X
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
& ^: \& K8 e2 j0 m2 f# [        }
1 p" R8 z1 I  a- e% [        // N106
  V' P5 X% O+ C2 P, z; V4 ?: G        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {. W  `2 Y) f7 R: p# L& i4 W: P
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ e4 y- B* z) i7 d        }# w% C- _: i: M* ~2 Z
        // FME7
3 [& \* J! |$ ]/ Y- P3 `        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
6 F6 U8 a- n+ n0 d- ?* P                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;; Z$ R; c; Z- V" K/ s9 \
        }
& H) ?. N% I+ W9 [! k: D* j* q        // VRC7. S1 y* c& l4 g9 P( o$ `
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
$ I  H' ?5 @3 ]9 P& ~& `                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: {% ]$ x0 r. h8 Z3 W  K* i        }
/ |! l, d' i. R# U2 @8 i" v6 ^  H        return        0;" b' G( c. ~  o  G6 a% ^3 ^0 i+ X
}
* F! z( j. a6 g* H
# s! k' W" Y! ?+ Z  f  A// State Save/Load
' o+ r# l1 Z# b( a5 C0 r/ Cvoid        APU::SaveState( LPBYTE p )- p' ~8 w  E1 \9 W
{- ^! `2 Y1 N2 }( ?$ `( S' ?
#ifdef        _DEBUG
  h& \1 s5 p  I& M) MLPBYTE        pold = p;
/ \7 O1 P7 i. Q2 r; a#endif
3 v+ R! H* a8 A7 s# P1 c; Q2 J3 ~
( B5 y6 S8 \; s        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
7 Z0 a" {' h- ?) g# w        QueueFlush();( t3 G8 S: g; E8 k8 v
9 |1 E) Q# F& |, C3 _
        internal.SaveState( p );" e, S: F) U4 p
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 E" q3 E2 T# R" c

  b/ u8 K3 L! D' N& N. M: O$ b        // VRC64 }/ [! U. O2 \7 i0 T
        if( exsound_select & 0x01 ) {( ?0 Q, L" n+ I7 n! R  u% J
                vrc6.SaveState( p );' l' Z' Y, S9 E6 U
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! q; e1 s, n4 \* l" @$ \5 S        }, @/ |* a$ h2 Y8 h* h, m0 j7 ^
        // VRC7 (not support)6 Z/ V- c7 y  T
        if( exsound_select & 0x02 ) {- A6 U: u' W" H& s
                vrc7.SaveState( p );, i( F4 m  _0 K: K( y, L9 W2 j- [
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" K( C: r2 g. ?8 _) Y8 K
        }) J# S* G0 u3 I. [$ M! d
        // FDS9 T  K- |1 X" C+ X& x* M: i/ w
        if( exsound_select & 0x04 ) {/ R5 E$ G. h2 K7 B) K" W
                fds.SaveState( p );
, i2 c* B( A  E( g) A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 F9 M, W. ~1 W* v' M" A$ X        }$ h/ c4 @- d" x$ Y/ E1 @$ C, z
        // MMC5
% J) C1 e' Q0 [" F2 g3 u! X        if( exsound_select & 0x08 ) {4 j4 P$ x, j: W9 L8 X7 s* _! Q" f
                mmc5.SaveState( p );5 m, a. `4 f: S  A- p
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 J% a) z. _; q$ z' m' N+ x! t
        }
6 U$ _/ X/ [9 J& |        // N106
" ]& b( h( r; D: N) k7 L5 H; a        if( exsound_select & 0x10 ) {
+ O6 ?* x3 @& U6 \: c6 B7 J# p                n106.SaveState( p );
% f7 D. s( S% y4 ?9 K5 q9 F                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 x4 c1 t& `7 C0 K5 B/ z, b        }
+ Y2 n! ^+ s7 B        // FME7
$ p! `- m( q9 W( G) B' u' H$ b0 b        if( exsound_select & 0x20 ) {% Z. o" G9 v$ b" ]& b& M9 `
                fme7.SaveState( p );( M0 w( B$ v4 ]# r# Q; p
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  ]0 L' ]" @0 }" U7 C        }) ]+ m; t7 y+ R2 [& N4 b+ A/ x

3 y* l: x5 T/ r* t% Z% W#ifdef        _DEBUG, P9 G' u5 L, q1 |2 l" l1 C1 F0 V
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );- m% e4 h0 X2 w* W$ F
#endif$ }2 _' j8 a& Y/ M& L& @
}
3 Z/ G5 R. A  P9 c2 Z) b, S
/ l6 P+ V2 Y) yvoid        APU::LoadState( LPBYTE p )7 j- e$ G7 U: Q0 Z8 ?0 `( Z  v* D
{
4 l; E% d& {$ Q+ D4 i        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
# L! S+ O1 l0 e3 ?        QueueClear();& p+ j! _, }1 L! j- \8 a) M* y

) N  Z# Z6 W: s0 [! i        internal.LoadState( p );
" w! F/ ^7 ^6 q( S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
7 f, k) T7 g* C. c9 d5 p" K: I. c" j( |7 b# n, a  c- Z1 d
        // VRC67 y) Z/ J1 K5 D# A8 z
        if( exsound_select & 0x01 ) {
- Y" z. M" W" j4 c* ~4 n9 E0 N                vrc6.LoadState( p );6 _8 F) p5 d, @  Z2 ~# g9 A0 \
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 C1 [1 C' ^' I5 r$ W- U- k
        }0 `6 s  p9 L% {1 x, f" W0 T: y
        // VRC7 (not support)
, u. y- r* j/ {- i/ y3 y* V        if( exsound_select & 0x02 ) {6 J- J/ n% M7 W, j& }3 K0 M; Z5 P
                vrc7.LoadState( p );$ {9 ]9 L' I# S. m
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
9 U4 i/ j8 r' c# S, e8 c; S1 c        }
5 h! p- W: p2 v4 l) U- L! p7 b5 s. w* |        // FDS& C2 k( O5 m9 B; Q6 j- x$ y1 F
        if( exsound_select & 0x04 ) {: L- M6 d9 k1 m9 H/ \7 H' S
                fds.LoadState( p );
; ]4 @4 T) \2 w$ u$ p6 p                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ L( |- N9 A9 N' A1 ^) S
        }
& ^8 _* O! U' m7 O; c        // MMC5
3 M5 ^3 L/ `* X% c        if( exsound_select & 0x08 ) {
1 l2 S  z; A  O* @                mmc5.LoadState( p );
, {7 Y( r  z$ j" f                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 ^, X4 c5 n$ f4 o$ }" a* Z        }7 a2 f$ N- @  t- @
        // N106: R- U9 X& ?8 ~% U
        if( exsound_select & 0x10 ) {! b$ S: ~% P5 A1 E- C
                n106.LoadState( p );) n$ s  m# q- U" Z9 w  W
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 Z' h# X& S+ Q4 n        }
9 h. b: P8 a1 N: X- e        // FME7! T, j6 u6 S& [% z- I
        if( exsound_select & 0x20 ) {
8 z5 q0 `& U( J                fme7.LoadState( p );/ E0 e0 b( I: x* V# ^
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; }9 C: c9 f, O- I        }
9 I9 X; Z0 q6 I9 Y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 y! d7 c% b/ j可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。& V) j' Q) G2 k. r% V: `7 @
感激不尽~~
0 `- O& U& r3 L2 @
恩 我對模擬器不是很有研究,
* }- |' |8 b- D" U( a* F' O雖然要了解源碼內容,可能不是很困難,% g3 c% t, \: {. o- |! r
不過還是要花時間,個人目前蠻忙碌的。( w. z8 l: @& y/ E& z) G
4 l& ?6 k* w5 f7 O2 E. `3 d/ Z
給你一個朋友的MSN,你可以跟他討論看看,
9 c( }* R+ U( A: g6 z4 a+ z他本身是程式設計師,也對FC模擬器很有興趣。1 u. t1 j& Q" q% \
# V' x! ^1 M1 N; a/ x
MSN我就PM到你的信箱了。
* z2 z, I! Y6 F5 Q
( Q5 F, M7 r/ t; c# ^- j$ |希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 % u, n0 T# p# P' \1 w
呵…… 谢过团长大人~~

) h& j( l! H( v9 T. y6 J4 B7 b6 N( h
; Y" w) V! u  n% A: [$ h哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
) t! U; u' O: T0 V+ J0 d团长的朋友都是神,那团长就是神的boss。

- L4 y9 N4 [( h) Y4 R# I4 E哈 不敢當,我只是個平凡人,! Q# L  ^; ~' u- ^
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙( O3 V: o# S* f* Y
ZYH
5 ^1 d  i( R. f3 tQQ:4147343061 k; o, H7 G& L
Mail:zyh-01@126.com
9 H- u! y9 G* J5 n" p7 J) l3 S# V9 n% K* q; K
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
' A+ b" [8 g! Q8 H* p0 a$ c' t再次对团长大人和悠悠哥的无私帮助表示感谢~~

' \+ ?: j1 g" z3 B3 J不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-18 02:26 , Processed in 1.120117 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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