EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 R% W4 @+ Z: q9 b# m7 L! Q8 G- C楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ c# g) r8 d% K4 U这里有相应的模拟器源码,就当送给大侠了~~# K5 M8 F! s( a) l( F4 j2 E! R
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 2 v- V  a% U" D. q2 z, b1 A: R
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。* M! q- g+ ~! B6 x% Q' E$ V0 ?$ X% `
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 w4 Q) a9 t1 h
这里有相应的模拟器源码,就当送给大侠 ...

. x' I  T3 K7 D4 W. X, |5 ^聲音部分(Audoi Process Unit = APU):
% k4 l9 p5 x' `/ ]3 L( `+ _) K* ~.\NES\APU.cpp
9 M4 V  O! Z: d.\NES\APU.h; a6 C5 l. W, J5 Y1 v

5 F# J' T5 n+ a
9 T' V8 X( K1 Q3 C, }! {影像處理部份(Picture Processing Unit = PPU):
8 u+ ~7 x! O0 A2 O4 ].\NES\PPU.cpp7 A* V4 b0 v3 R$ g+ o
.\NES\PPU.h! g4 v. G7 D2 {4 b/ m% m
+ X4 `5 e1 d* A; p6 C
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 }4 b, H5 s9 X5 y& p
(由于很多专用术语和算法机理都不明白,所以看不大懂……)" l) j9 i% m2 J3 X! [
//////////////////////////////////////////////////////////////////////////
/ R9 Y# Q+ g) v//                                                                      //
3 g5 U+ I' o0 l' i, F//      NES APU core                                                    //( @9 W) ]3 r7 c( p- \6 _
//                                                           Norix      //; n) ~5 N% h' {. r! y# e
//                                               written     2002/06/27 //
7 b9 a& w" T! I6 o//                                               last modify ----/--/-- //
3 Q& m" r6 e0 J0 t" M//////////////////////////////////////////////////////////////////////////8 N9 u- h0 D* Z2 F8 R8 `! A7 T' ~
#include "DebugOut.h"
6 H" ]" d! I) H#include "App.h"
$ P1 B3 c& E: A#include "Config.h"( _! F  d* V7 }) z9 x7 @: c
2 X/ U! Y3 T+ g
#include "nes.h"
/ A4 N' o* m- I: u0 P#include "mmu.h"9 m& b4 Z+ f( }, A, x7 `
#include "cpu.h"* S0 q' X, U, u+ F# _1 t
#include "ppu.h"
; w, C) g6 C  M$ {$ b' j* m#include "rom.h"+ p$ {$ B* X1 g" W3 T2 ^& K: H
#include "apu.h"
( u/ _$ s% e& D7 V* T4 j8 Y9 M+ P4 c* |7 q- G3 A5 H
// Volume adjust
2 K# R+ Z: z# T- ^// Internal sounds
4 |' L# ?- z4 p8 c* Y0 d6 J#define        RECTANGLE_VOL        (0x0F0)
+ Q; z" z. @& H2 V5 h( M#define        TRIANGLE_VOL        (0x130)
7 l: B- e) ]4 D* I( T#define        NOISE_VOL        (0x0C0)
# A8 a$ m6 ?1 x4 W#define        DPCM_VOL        (0x0F0)
) q/ x9 `; u# N9 X# B' I// Extra sounds7 M. {6 M* E0 n! u4 ]" f8 [0 W
#define        VRC6_VOL        (0x0F0)
& F) Y5 N) o  a, j#define        VRC7_VOL        (0x130), l3 a+ H$ I; [4 ]
#define        FDS_VOL                (0x0F0), M3 A' ^% ?) P: e/ r
#define        MMC5_VOL        (0x0F0)
- }9 e7 H. b" g: `! a3 ^#define        N106_VOL        (0x088)
) e( G8 `, {$ v3 ?( L#define        FME7_VOL        (0x130)
( [" x7 b- H. @. n' m" U  g5 m/ q* b# U4 X" h" v2 }) Q
APU::APU( NES* parent )  \. V/ ], Q7 V2 c/ P) E; t- v
{- r* A- ^3 @  [; k
        exsound_select = 0;3 R. {% g6 ?: ~6 O

* s4 V( l1 n. I9 j. a        nes = parent;4 J8 N9 \' V& ^* g9 C
        internal.SetParent( parent );% U: ~3 p6 B- ?; `( d& @- m) j- ]
8 S3 f# q) {* F$ M1 J# ]; E% v
        last_data = last_diff = 0;2 s$ k4 K2 S2 n9 y0 R1 ^, C
! [8 a8 A/ a( |1 h  V( O
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );/ ~. I* y2 {5 S& j- r
& ]4 [9 |3 j2 W" L8 `# x5 `- T
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );- H* K4 y; N0 s6 i  n7 c
        ZEROMEMORY( &queue, sizeof(queue) );5 J% y8 u9 G6 C  x1 n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );# c  }+ q  z" [7 e

+ s! @% @4 L- q, u        for( INT i = 0; i < 16; i++ ) {
/ u# X0 O" O1 h5 E* k                m_bMute = TRUE;
) T! b  q* v$ C        }
% f, \$ A- C6 ^- i$ W}
9 D+ j$ i  @, y
/ ?, Y5 C1 e; q1 P* a$ ^APU::~APU()4 [0 V; ~: o  `4 g  @7 E* ]
{
4 Y( h" r2 x& ]) I) u}
9 `& B* ~+ M5 l0 f* o# Y; p9 v1 I) K2 H$ ]+ g8 K4 a
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ K$ A9 D& }: i/ w  I9 `( A2 S: i{( R) N- D' l& W/ E& T
        queue.data[queue.wrptr].time = writetime;! x8 w1 ^8 Y! _8 A( @, x
        queue.data[queue.wrptr].addr = addr;& y0 j' y; s) ~- @. @
        queue.data[queue.wrptr].data = data;, r. C; O* P7 i" E: q
        queue.wrptr++;" G2 g, ^; B+ u3 u% O
        queue.wrptr&=QUEUE_LENGTH-1;% `7 b8 S" @  d5 x, V0 M
        if( queue.wrptr == queue.rdptr ) {; p: Q& `6 q  T) _8 w4 L5 T% i
                DEBUGOUT( "queue overflow.\n" );; U" L- m+ ~" P8 H( P
        }& W& \" \% E/ F. n7 X! u* f
}
$ u4 |! v& R* K* V
8 R, @& k, ]1 |BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )% z0 `& {( ^# f' L4 Z3 K8 C
{
0 E# Y- k6 _( v; [3 c1 Q. [4 Q5 {        if( queue.wrptr == queue.rdptr ) {
2 q, h8 _! t" \! v                return        FALSE;
/ q$ T/ p. B- U0 {        }3 L0 b8 [# @2 R  D4 ?
        if( queue.data[queue.rdptr].time <= writetime ) {! j( k: x7 M8 }, }; T( J! ~7 U
                ret = queue.data[queue.rdptr];
7 K% j! S1 O# O) \  U                queue.rdptr++;
$ ~% Z7 g# `* w8 Q& n7 J/ p: p$ k: T                queue.rdptr&=QUEUE_LENGTH-1;6 u. h( N; u- {. m- w: C
                return        TRUE;5 }6 M0 N# v  S! B/ y9 q( l
        }
% v( G% ?( D4 M7 _5 C" J# C        return        FALSE;
$ {! |/ \( F' A}
3 v1 G0 ?0 j2 V- ?8 L: I5 F( j& I% d" m
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
; x* z; Y' U8 a- `$ z* t{
6 A$ t; ~& N; l' i2 J# @        exqueue.data[exqueue.wrptr].time = writetime;
1 T+ y  P4 R8 \        exqueue.data[exqueue.wrptr].addr = addr;
' V6 L) G2 P: t/ m! K) q6 t+ X2 g        exqueue.data[exqueue.wrptr].data = data;
) f) ]  C1 n% o7 \7 C. N        exqueue.wrptr++;) J- M0 w2 g  A9 g* K+ l
        exqueue.wrptr&=QUEUE_LENGTH-1;
5 s1 @6 \& M0 p. B- ]2 s        if( exqueue.wrptr == exqueue.rdptr ) {, O& P: W# O9 ]
                DEBUGOUT( "exqueue overflow.\n" );, {) B" u, {6 M9 u
        }
; ]7 k# O2 v5 |% _}
8 S0 @4 {; d  A; x" i' c% K% _
$ m7 z4 E( M4 s. ~- e' p7 m% ZBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
  w* n5 Z# ]& I* L9 l- {5 A{: s" s# Z6 m! d- m8 w  K1 K
        if( exqueue.wrptr == exqueue.rdptr ) {
3 Q' J5 n- w0 {5 @" j                return        FALSE;) Y: J8 A5 @+ `8 \. Z/ ^
        }
9 c/ d. Q/ `5 i" u" Q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
7 C) B5 b  J( I& P                ret = exqueue.data[exqueue.rdptr];
( E8 e: t; A6 s0 v                exqueue.rdptr++;2 I7 S; X- r& n" |
                exqueue.rdptr&=QUEUE_LENGTH-1;* H4 H6 Y8 e  F
                return        TRUE;$ L; X1 ?6 V+ l- ]4 b
        }
; \/ j( g3 Y2 R6 m. o2 g' \        return        FALSE;
# T2 \8 u. i7 ^8 o' O}
, h  N0 r0 j; X% }! q2 ~: B' W$ w% g3 _* g
void        APU::QueueClear()
" U8 T* ~6 B2 t2 l! t4 w7 a) Z7 S3 U7 Y{
3 P$ w! W  W; \' M% ^, R5 u0 l, b        ZEROMEMORY( &queue, sizeof(queue) );
0 A. S. n/ h, i/ i" @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. [$ P5 m; `/ m+ y4 z, J' i}2 `- I, y. @; a8 O( N

* R1 D/ s& _- f4 ?: Cvoid        APU::QueueFlush()
! d1 T9 P5 U* T7 Z8 V{
# j4 `, C! a0 h; [3 {6 D5 q2 p. Y        while( queue.wrptr != queue.rdptr ) {( z! Z( v6 A- a! h* c
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) L. S  s7 o# |0 c9 M7 X* F3 T
                queue.rdptr++;
0 t* \1 E: ~% m# S                queue.rdptr&=QUEUE_LENGTH-1;9 ]- v5 E4 g* ~( [) s$ p; l$ p
        }, X8 X2 ~" [' r" c, ^5 s

8 |$ c  a" E8 q9 m        while( exqueue.wrptr != exqueue.rdptr ) {- `% C' d9 E/ n9 I; d1 Z) l
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 t" ~" B) q- Z: S) D8 z                exqueue.rdptr++;
6 W8 k, k  \" ^4 N, m                exqueue.rdptr&=QUEUE_LENGTH-1;) [, n% U8 R$ V
        }
- p& A' v$ @, w( m}
7 \7 B) r( i' t: t+ s0 `* x# g3 C# E, `$ K: y- [  y$ l" e
void        APU::SoundSetup(), K6 C6 e+ h% o$ z% G  Q
{
" i! v, C8 O- q        FLOAT        fClock = nes->nescfg->CpuClock;& v; G% g( `. J; w. `( }1 u3 X
        INT        nRate = (INT)Config.sound.nRate;
. ?8 a  h/ N5 w, ]        internal.Setup( fClock, nRate );
/ P( [: ?, Q: Z        vrc6.Setup( fClock, nRate );
* G. |- T% m! u* K9 ~2 e( }* M        vrc7.Setup( fClock, nRate );/ ~; Q( Y- K$ b6 ]8 o/ ]
        mmc5.Setup( fClock, nRate );
- v$ i7 U1 B0 \( v+ m1 {% v- F        fds.Setup ( fClock, nRate );+ a' b7 y' B) ~. s
        n106.Setup( fClock, nRate );
, v* q* ~. x* I3 K# v        fme7.Setup( fClock, nRate );' ?% r$ j: j4 a
}; J+ o! F9 }& `- E! S9 s, g

. Z& `8 G4 \( ]void        APU::Reset()/ |. C% z( m0 ~6 H/ X3 Q2 N& g
{( y5 D, q2 E. b5 H8 y; o
        ZEROMEMORY( &queue, sizeof(queue) );
) H5 n* Z( I/ f        ZEROMEMORY( &exqueue, sizeof(exqueue) );" \7 m! |- V; p5 C1 g1 k
. d; ~5 [+ f$ N& Z
        elapsed_time = 0;
( a( g& I0 v  Y0 L1 e+ U% t" ~  q2 h$ C, x0 K
        FLOAT        fClock = nes->nescfg->CpuClock;
' _' W* A; \: {! T/ i        INT        nRate = (INT)Config.sound.nRate;
4 q! R: l, t! v' j        internal.Reset( fClock, nRate );; V) f6 [9 Z% p8 T9 G
        vrc6.Reset( fClock, nRate );
9 x' I1 b% C7 B/ X        vrc7.Reset( fClock, nRate );0 i! ]5 P, t( w+ M7 p# P
        mmc5.Reset( fClock, nRate );+ S( J6 s+ E5 x8 U. q
        fds.Reset ( fClock, nRate );
/ Z5 u; v& ]8 @2 c# I        n106.Reset( fClock, nRate );
+ E# x: q) W, J: Q$ s        fme7.Reset( fClock, nRate );7 G: j0 Z/ ]% `& P

" c$ l  Z5 Q" v3 ?        SoundSetup();( O% `: _( u9 ~
}
! E" U5 r+ M- m3 E8 i, Y/ F& N! y& q* o( d
void        APU::SelectExSound( BYTE data ), |, B5 q" G/ Q, I6 s% }3 |3 b
{' M4 I, I8 k' D. f
        exsound_select = data;$ m+ W/ L+ o, U: g2 W  i$ `" g
}
1 N2 m: a! B# {% g: Q3 S# u& Q9 Q
# a, l4 ]: k  Y1 @BYTE        APU::Read( WORD addr )
7 g* N2 L9 B, t8 N' u9 I{
+ M" a. }! A1 L5 i0 l, c" ~' t        return        internal.SyncRead( addr );* f  c0 e7 L4 Y
}
3 J! z0 W9 B& ~, C
+ A2 K$ w; W, M: u( Svoid        APU::Write( WORD addr, BYTE data )4 H7 n4 F( _# t7 [% m
{  L9 V+ Z3 B( s* i, Z0 V
        // $4018偼VirtuaNES屌桳億乕僩4 D! u9 B: j8 h! N% K3 {5 Y
        if( addr >= 0x4000 && addr <= 0x401F ) {
# ?* G# T" n4 Z4 ^! h9 e# R                internal.SyncWrite( addr, data );, v% @% N, `( G5 I9 l
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );! N' E6 \: G; I
        }
% |* H, k( `: d' m" }6 a}' Q& V9 s+ o) h- k8 `. j4 S

$ N7 u6 c1 @$ k/ g6 DBYTE        APU::ExRead( WORD addr )1 R* u) T8 m* a; }! k- T
{
3 j9 Y+ a$ @8 l$ G0 _' ^BYTE        data = 0;
% F1 n+ y& u& g1 u: f$ u- c. T9 t) {
        if( exsound_select & 0x10 ) {
  _" d% T/ `7 {5 k9 d                if( addr == 0x4800 ) {' n: V  P% [) s% r, I8 F" |6 E
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );5 ~( n! J0 o' u: X+ m1 Y
                }
' A0 v# k+ A7 p        }: u: D$ x) D3 O& e+ l
        if( exsound_select & 0x04 ) {+ B+ P/ o; p% `: l0 y
                if( addr >= 0x4040 && addr < 0x4100 ) {( R5 h3 y3 v" t: J, f* G
                        data = fds.SyncRead( addr );5 N/ W5 `6 `% Y1 f
                }6 [4 b6 ]; [, L2 ]" u1 ]
        }
& u. U" x) G6 w* a$ g! \. C( D        if( exsound_select & 0x08 ) {: r5 m$ c+ R0 z4 g
                if( addr >= 0x5000 && addr <= 0x5015 ) {2 r/ d- U6 z( o& U" m
                        data = mmc5.SyncRead( addr );
- }7 G' E9 `  `3 k5 T5 B$ k                }
5 b: G. Q6 c! ?: @+ X6 f0 R/ ~& `        }
& J7 P  b4 ~% K% G" M* B; v4 [/ _
        return        data;
% M. D* @3 |6 r( M2 g}
  @3 G( a3 W" X9 q& @$ E- |/ V4 j7 }
void        APU::ExWrite( WORD addr, BYTE data ), X  g# {' e$ I; R9 p7 d
{
7 h2 j3 v8 ^! W0 r        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
* J4 B7 j, ?/ L2 }" a
* G- P! m5 I/ Y  o# J! e; v        if( exsound_select & 0x04 ) {- O0 \3 Y+ i7 h4 t. z, }6 `9 Q
                if( addr >= 0x4040 && addr < 0x4100 ) {
' |; O8 s& \9 ]+ `8 k! c* k0 r2 e                        fds.SyncWrite( addr, data );
0 t! \% M/ }. p1 g0 K7 y3 q  ?/ }' U& }                }
  f8 {: @3 e3 N0 m5 A        }
- J; P' `) }. w( A8 x% k* m, q" I% u/ w/ H/ _
        if( exsound_select & 0x08 ) {) ?( j1 Q# h- W6 c- M8 R
                if( addr >= 0x5000 && addr <= 0x5015 ) {7 f# m3 [" V6 X  L
                        mmc5.SyncWrite( addr, data );& S7 Q2 O0 O/ e- f5 C% c: R
                }
1 A* {- p- ]1 Y0 g, x        }
: Y  j  k4 D6 m2 j/ l" L}
8 w6 t0 |3 N3 t7 I0 I' b
8 j0 m! D( b. A/ T# q" ivoid        APU::Sync()1 ?+ O  |& E% C; o$ f0 w2 p5 m
{
+ m7 W$ c, _2 I$ Z1 |) V9 `$ j}/ k# h% A' u! a1 ^0 n8 {! w" K
! O4 n  L9 t, w* t
void        APU::SyncDPCM( INT cycles )
3 h5 A0 T+ C9 c  D* X{
+ X3 }3 G5 D- p! N        internal.Sync( cycles );
$ r8 u0 C4 \$ f% z' O2 l& G2 C: K* m, o6 U7 @& l3 V
        if( exsound_select & 0x04 ) {3 h1 r5 `5 j, a0 b( j- P
                fds.Sync( cycles );% Z. m  l7 s" p4 A5 c) @" }- Z# Z& B
        }' @5 H5 _' v' i/ W
        if( exsound_select & 0x08 ) {
0 z- z) v! S, b. u/ d& t                mmc5.Sync( cycles );2 w, J$ x8 }5 e4 A: Y
        }
- h) X; ^7 s, [9 x+ a% S% v8 W}
: r, S. e( }5 [1 e/ K1 e- s" T0 H
( p/ P  D( o; u4 @- g, Tvoid        APU::WriteProcess( WORD addr, BYTE data )! t* ~6 Y) ~8 x2 Z$ z
{
* A. A1 f' m$ f& v4 _( }        // $4018偼VirtuaNES屌桳億乕僩% M  J1 Z/ h' `* Q5 Y6 i
        if( addr >= 0x4000 && addr <= 0x401F ) {; s) {$ B* G/ c: c! n$ x- ]/ }
                internal.Write( addr, data );
' {4 ]( R, v; U1 u. _0 H        }
3 P  \8 `4 k# l! o( J}
2 ?$ m$ X2 N3 E0 s( \% O, |2 a
2 g2 `% ^3 J% l. X6 Z% L5 b$ Ivoid        APU::WriteExProcess( WORD addr, BYTE data )8 \1 Q9 S/ N7 @* B' I
{
$ M$ z* c, Z- l7 d0 K% L' v* L        if( exsound_select & 0x01 ) {
* U2 F: U8 }% N" Q+ ^4 q. n& ~$ h                vrc6.Write( addr, data );
- Q) u1 G+ W. o8 M1 p' h& ?/ o        }# O7 H1 v( {, C" q7 d
        if( exsound_select & 0x02 ) {; J# i& a3 I" D
                vrc7.Write( addr, data );! x5 \& n' G: {' P) |
        }* c) W. v1 o4 g2 e. f% a/ s8 P9 v& z
        if( exsound_select & 0x04 ) {" ~: [; V/ m6 [5 e) B* _
                fds.Write( addr, data );0 o5 y7 ~. H  t* H, z
        }% l" U* j$ S+ w2 _2 _% s( b
        if( exsound_select & 0x08 ) {
' @- Y5 ~; E6 V1 P$ n, f- D                mmc5.Write( addr, data );. r; P8 r. n1 o" ^5 E' C6 D4 n$ z: l
        }
2 n* G7 c2 V% J+ P3 f* {0 S, j        if( exsound_select & 0x10 ) {
) L: Y+ l+ N8 D" _% h6 ~5 G                if( addr == 0x0000 ) {' L4 w9 z( f5 c7 k, Y7 _
                        BYTE        dummy = n106.Read( addr );/ z! d9 j8 k# L2 p* A" B! `
                } else {
7 y( q, y. h/ @# `                        n106.Write( addr, data );
5 f: K5 D) C+ T- i3 X                }, K" v8 D* y& Y& d. _
        }
$ r% X8 H8 T. B" f- X# e$ n; H        if( exsound_select & 0x20 ) {% ]% I! |! z2 }( D: X$ {
                fme7.Write( addr, data );  }! P8 f# n& p1 `1 `: D) s, ^
        }
8 l! k8 f' T1 N  a; r}
3 {' P& [  d7 a# D! y( ]& e8 c3 v& p4 X* ]
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
8 _7 c0 |* s, L9 H( ~{
" j# I! L4 u  V! K" C0 y  T' AINT        nBits = Config.sound.nBits;  K" e- \8 b' q: }7 ^
DWORD        dwLength = dwSize / (nBits/8);3 u! B; c3 _2 `8 f
INT        output;& I5 t% p; b2 E  n1 P. T9 V
QUEUEDATA q;! `7 F" W, ^& ^; w
DWORD        writetime;
$ V4 F% z% l- v9 L: V5 r* P4 P& z* `# Q2 e6 W/ ?0 Z) O
LPSHORT        pSoundBuf = m_SoundBuffer;
2 A5 n% j: ?3 E" W9 f  xINT        nCcount = 0;
5 M# F4 l* e7 \! P3 R; V: `$ x
9 k3 F; e9 c* D0 c  s4 z) s: W9 vINT        nFilterType = Config.sound.nFilterType;/ ?8 A9 k# k3 X. m8 R) o2 b/ P9 _

5 f! `) ?( ^% S5 r6 N        if( !Config.sound.bEnable ) {$ e" Q' Y( v( m$ V+ G
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );' z' K, _( \/ S' L* c7 O9 H# c3 r
                return;
0 d* I8 f- O& f        }
6 a% u# o0 L7 V) E3 t
  n8 i  @9 |) y' _! k        // Volume setup" D! a4 h# N+ ^) o
        //  0:Master7 n1 y" b) E6 {2 r5 B2 G+ z: ^
        //  1:Rectangle 1
& D6 {: L3 W% l9 t% R        //  2:Rectangle 2
- J0 H: s  V( R! f        //  3:Triangle
9 N+ o  E; k* v& w4 J, t  n        //  4:Noise
! l! r3 K5 t0 b& L5 F* q        //  5:DPCM7 a/ q+ I5 R8 P9 ?! c6 D  q
        //  6:VRC6  k2 n4 ]7 q' h
        //  7:VRC7
! ?, H* n8 ?/ e! p. j) u: K        //  8:FDS
& H$ Q& h" o, P        //  9:MMC56 b& M) t" y; {+ M
        // 10:N106
5 v- ?/ O& e) U& H/ u5 d        // 11:FME7, Q1 R, m/ g/ s$ M8 l$ E. t
        INT        vol[24];
( H0 H5 t1 J6 k0 n6 m        BOOL*        bMute = m_bMute;! w: C2 Y2 c* |2 @1 p
        SHORT*        nVolume = Config.sound.nVolume;
+ V# ~, W, R/ E, {$ m
( @3 I& e* T- W# h9 X        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
3 j; v) t! z( F1 f
: {% L# `* l: H) A        // Internal
' b! I0 L: Z1 |# r& E        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;# J  E) j  v4 f7 D
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 H" k- M/ n' A        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
( v5 F5 h0 b5 Z  T, [3 A& h* o        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 @5 d+ A4 ~) y. H- F4 Y/ B
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;& ^  j. W. a, S$ ~# v5 L; |

" N  d/ g$ N* J! r, g' p        // VRC6
* F6 i" B2 e6 P! U        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" S, e$ c6 v: c7 M6 A        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 k* Y1 p( L4 P5 Q
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* X; w8 e2 \" A% W( A, J. E2 j( b" x) h1 j, _/ ~. l
        // VRC7
- q% u5 p0 D2 i( p7 h) M: {2 s7 |        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;* F: q% T; G- b- P. |
8 J" m' f4 k0 {0 Z1 S, c
        // FDS: w  L' D* u/ p* D. b) b9 m' O2 m/ ]( M
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;3 g1 X+ O( L1 q0 |* d8 I4 I

% S- t! U/ x- q        // MMC5
% }" g  j; S+ I        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% Q& t: X; }, D4 S) [
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* f/ U) Q, I  A7 q* @7 V. U
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! V: g  `. D& v
4 P9 ?% }: t' V; ]0 o, g        // N106* t5 x' t8 q$ n4 }7 c2 ?5 m9 @) h
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( w. j: G8 k6 D. k6 r7 l( I) t
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 j( @! ^0 N' @8 O- M( K+ x
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 A1 t& n! X/ s+ V" U6 \        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; ?" B# H- _2 w) S        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" y5 |0 ^( ]9 [" p        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* N' k+ n4 B8 `2 ?. Q* U7 B1 D        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" @4 L6 _4 b( N+ Y5 }3 r, X& G8 I) c        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ g$ ~3 b' l4 F- j4 {
0 u+ M$ u! s6 }% v% |        // FME7! M6 |% r! t# M# \3 Y4 B6 |
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* f* A2 c" a" {0 V( B( G1 \        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' f" k/ |& y# {% L' Q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" [0 |) o6 e- Q; v7 v! f; s

8 o8 Y5 G& [( _/ ^  o' c+ C//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
) \' t: }7 ^7 t9 |& i8 `: Z        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: ~* F: F7 }) @5 y. M, q7 X3 s
  t% h& U- }# k0 `9 b
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
. p1 n& d# Q3 m0 N        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# A5 E2 H- v: z( R: F( e3 z
                QueueFlush();
+ e1 ]" _4 n4 {  L        }
2 P, T: [/ l7 s6 U# G& S
7 W7 `9 M, h$ p  h/ G' O        while( dwLength-- ) {
! N  d: k9 Y7 v5 b1 e# `3 @- \                writetime = (DWORD)elapsed_time;( G0 Y" P% B5 l  f- O6 \8 y8 V

8 O+ n% a. B( L& s                while( GetQueue( writetime, q ) ) {
3 [2 L* Z5 }" ~( [  u; G/ W( X. }" M0 f                        WriteProcess( q.addr, q.data );- @. J5 s$ n7 r( Y5 n
                }
/ n  J0 m" s9 u. F0 x- c3 E& S, f  l' T2 U7 ?+ X3 V; W' s
                while( GetExQueue( writetime, q ) ) {
; r2 k2 B/ b4 D6 t/ g                        WriteExProcess( q.addr, q.data );/ j# K& b! l( ~% o- H
                }
1 L, @$ Y. u2 {1 d
- z( ?2 b8 t( u$ Z; e( g( Q                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
  v; I6 D& |3 z- k' ^* z' C! }                output = 0;* L2 s0 v* c* s- V
                output += internal.Process( 0 )*vol[0];& u+ N1 ]5 o3 W" }" o4 F
                output += internal.Process( 1 )*vol[1];
; ]7 h+ n5 C4 {& @                output += internal.Process( 2 )*vol[2];$ Z$ a$ |7 f4 ?. Y- u! f
                output += internal.Process( 3 )*vol[3];
4 a; C7 y% W  A$ B: G                output += internal.Process( 4 )*vol[4];
8 D  p9 j7 {" N: h8 r( D: S; Y* V3 F7 T! O0 p3 D
                if( exsound_select & 0x01 ) {
+ h- L8 M0 x4 b                        output += vrc6.Process( 0 )*vol[5];
# x! I& W2 o/ z2 e                        output += vrc6.Process( 1 )*vol[6];
0 b* z' p6 w3 Q: P" l: V                        output += vrc6.Process( 2 )*vol[7];. _: H9 G- W" _5 X
                }
7 {$ u; }* C: {' o                if( exsound_select & 0x02 ) {7 r4 e3 [3 D  K
                        output += vrc7.Process( 0 )*vol[8];
& ^5 \& J0 c* S+ w7 k4 G3 b. J7 t                }; J- v6 X$ U5 j) ^5 V' Q
                if( exsound_select & 0x04 ) {
  v0 I/ ^  K- e$ }* U                        output += fds.Process( 0 )*vol[9];
, k. l! E, X2 n% x+ |- h1 i7 p                }
7 U4 Y5 I: i1 D% B" p$ b2 G                if( exsound_select & 0x08 ) {5 t1 o  h. U/ }: T* Q4 e8 A
                        output += mmc5.Process( 0 )*vol[10];
- q% ^4 }: ]3 c4 E3 j                        output += mmc5.Process( 1 )*vol[11];9 x* R$ G! _( g0 }, C
                        output += mmc5.Process( 2 )*vol[12];
6 I* _7 A$ k+ q7 w0 i  ?8 L* T                }2 b- I4 @% ?; I# [. x/ M8 L
                if( exsound_select & 0x10 ) {" E1 B; e7 U* p, M* T
                        output += n106.Process( 0 )*vol[13];. v  V. g; l8 |% V: n4 T/ A8 @2 X7 o
                        output += n106.Process( 1 )*vol[14];9 F8 {: U( ]( c/ d: W  x& ~) ?4 J! W% s$ @
                        output += n106.Process( 2 )*vol[15];
0 e- x5 J5 V4 B  C                        output += n106.Process( 3 )*vol[16];/ u# U3 J1 x( h  e6 |
                        output += n106.Process( 4 )*vol[17];6 f* _& a. y$ _
                        output += n106.Process( 5 )*vol[18];
$ F7 E8 N! U/ M3 R                        output += n106.Process( 6 )*vol[19];0 r& y* m8 z' s# \6 _: S! e
                        output += n106.Process( 7 )*vol[20];
6 B; f0 {$ N- P! E' ~- @                }
0 Q* c/ m+ b2 n$ o1 s3 j( |                if( exsound_select & 0x20 ) {6 O. ^- Y$ E# j; @2 `7 |
                        fme7.Process( 3 );        // Envelope & Noise7 m2 j0 f* u$ W, B+ \
                        output += fme7.Process( 0 )*vol[21];0 |/ J9 R9 t- N4 K$ {
                        output += fme7.Process( 1 )*vol[22];8 A+ ?3 c/ z* [; J$ B
                        output += fme7.Process( 2 )*vol[23];5 q/ _3 R* B$ U9 s- ^; ^& I( T
                }, U. x, T6 o; c1 S7 s8 W( a3 @  {) z
: z: o- `" t8 k# D
                output >>= 8;
8 o$ `7 a5 T5 C0 d6 m6 B* Q# z
$ y/ p1 C2 M5 ~9 ^/ H2 ~                if( nFilterType == 1 ) {+ U4 s' N) P0 u5 O! |% {# E8 ]% I
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
9 r" h# E/ ~0 s" w                        output = (lowpass_filter[0]+output)/2;8 Y# f; ?: L$ I$ t2 a
                        lowpass_filter[0] = output;
/ z5 ~7 J8 r* g                } else if( nFilterType == 2 ) {; D: t, y% @  B, b6 W; O& y  R
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)/ t* {& `* v5 ^5 s0 j! x% }
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;$ E- J6 ^0 \& S  l1 J
                        lowpass_filter[1] = lowpass_filter[0];
7 m% i! u! w6 m5 B                        lowpass_filter[0] = output;, o" K6 ^, n& B$ u5 A
                } else if( nFilterType == 3 ) {
5 F6 K+ m8 A9 o; n1 h. e                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
1 ?. S  \( |2 K6 v7 F+ V                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;  I% k2 k* `  q" y& w
                        lowpass_filter[2] = lowpass_filter[1];* a6 p' V+ N1 V8 v( b* V4 g; r
                        lowpass_filter[1] = lowpass_filter[0];
* f* d1 k6 s# }  x( Y! o% B% [( x$ r                        lowpass_filter[0] = output;
, l: O8 f9 F% |5 I                } else if( nFilterType == 4 ) {
3 X: J: `/ M# n' v2 O                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3): }3 ~$ T& z+ K0 f. @3 k
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;& G. v0 `4 D* W0 G( s
                        lowpass_filter[1] = lowpass_filter[0];
; M5 o, B" \5 y+ @3 I( O7 [' z% _                        lowpass_filter[0] = output;
7 n) e: X9 f. y7 ^                }
! x: H4 r7 P, I3 l/ a
' I. u2 B+ p& d/ c  w. K#if        0% J( L6 i* q% K# U/ q3 a( C& ~4 i
                // DC惉暘偺僇僢僩
: k* s: O& l* Z; h5 @9 V                {$ d% F1 S& C0 M$ J) c
                static double ave = 0.0, max=0.0, min=0.0;2 z( Q4 z& ~4 A
                double delta;
9 @' t/ F. S0 U6 e2 U) \# |" A                delta = (max-min)/32768.0;- m# ^* ?! f9 P# O8 u7 ?& E( w
                max -= delta;8 w7 [$ ^# T' S4 T3 ?7 q! ~
                min += delta;
3 D1 B9 Z( p& m% t) n                if( output > max ) max = output;
' A) f6 ]1 J, ]7 |. G                if( output < min ) min = output;
7 Z# X3 R7 d, S+ [                ave -= ave/1024.0;
3 N; h8 k) F+ a0 _                ave += (max+min)/2048.0;
2 Z/ d# U" n/ ~                output -= (INT)ave;* w5 o1 x4 L! a' K8 I  f4 N
                }
0 J9 @9 E( ~7 N0 Y" R) f#endif
" U( z( S1 X# ^3 S0 Z3 M. a#if        1
: Q7 C. o2 J0 \, [                // DC惉暘偺僇僢僩(HPF TEST)
4 I3 u1 @, F6 Z; @4 p9 X2 [                {* D4 i. n' o# c6 o# z
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
7 L' ^1 c: o# v                static        double        cutofftemp = (2.0*3.141592653579*40.0);
$ s! ]4 Z6 T. Z; [# K" a  y                double        cutoff = cutofftemp/(double)Config.sound.nRate;& R) e0 q! X3 e& J7 n6 E% n
                static        double        tmp = 0.0;- E6 m* ^" r) S" y6 q, z$ n
                double        in, out;2 D0 x+ `9 h6 l8 x, s
% [$ s# g, w3 ^! A
                in = (double)output;. c0 D: s; ?, t9 a
                out = (in - tmp);
& a- W& D# \/ `- X1 `                tmp = tmp + cutoff * out;& O# q; L% H1 b+ V, G( _) @

# l. d1 Y. g* r                output = (INT)out;
5 C. k4 [# o6 I+ ?5 j7 R* M: a+ r6 X                }
& A$ @" l, v% G8 c; @5 f; N  o#endif
, F4 w( g! h/ u" f$ D; w$ E# N#if        03 x/ h8 D* a+ q- D$ Q
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)7 d( p. A4 }5 s( ]# c
                {
: S* ?' x0 R  q9 [. ~* X, K* q  k/ c# V                INT        diff = abs(output-last_data);
+ @- C' V5 `/ o6 \                if( diff > 0x4000 ) {
, _" m( E2 a) g3 T3 Y                        output /= 4;5 L1 u  }5 z% G5 i# h$ v) @
                } else
* ]0 @# @  Y8 d# I. J9 G                if( diff > 0x3000 ) {
4 F# i2 p2 y" l6 z, Q% u                        output /= 3;4 l4 z9 l$ Y1 l2 ]
                } else
5 l) `  e9 ^* _; G                if( diff > 0x2000 ) {
  Q, L4 X; V* b  z                        output /= 2;
# }1 C- K( M* V" y+ n  f4 T( o+ f5 {3 h                }
9 q8 H8 Y9 q( K8 E! q$ |: W                last_data = output;' \$ c! [* V8 ~0 x
                }, k9 G8 A$ F: f, H
#endif4 W; M. t3 g) ~* n  ^$ u* s
                // Limit
6 l; ^- L# A7 _2 q6 y                if( output > 0x7FFF ) {4 n- l# k# e6 ~: I5 q: R0 g
                        output = 0x7FFF;
) l( g  x6 Z  b                } else if( output < -0x8000 ) {% |4 ^# _7 D. D4 @' S3 E; }$ F
                        output = -0x8000;
& z' E$ S" s; a                }$ x. u7 i% n0 i

( Y6 R& h& L" O* E                if( nBits != 8 ) {& N" L! ~; R' D6 ^% ]# g
                        *(SHORT*)lpBuffer = (SHORT)output;
* z4 ~! _. ~9 E+ U- S; d% \% I; ]6 S                        lpBuffer += sizeof(SHORT);
% A: B! x" r7 t% [: y! m: \4 O5 D# z  D                } else {  w0 y; J1 {' P2 y% ]
                        *lpBuffer++ = (output>>8)^0x80;
: h( R% ^2 T- Y, e  e& K& `                }
: `  Q8 T9 [# s6 H1 w4 N6 N. _" r
; y; q- N6 W; \                if( nCcount < 0x0100 )" [, A+ E; V0 @5 H. X1 G
                        pSoundBuf[nCcount++] = (SHORT)output;/ P, k8 d3 y. ]0 m/ q. J

8 O; F+ n' j! W! |8 a4 K% E- v//                elapsedtime += cycle_rate;* M* i: L5 c2 y. ^' I9 K: d3 S6 K% a
                elapsed_time += cycle_rate;
8 G- ?/ H  i4 m/ U8 x8 O% r4 Q1 J        }8 M% d. E1 A5 ^  C) ]  i) g0 \

4 I5 {. B" C1 y$ n. Y#if        1
/ T9 T: T7 o) X        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 l! s+ J# Q4 i& S" A" c                elapsed_time = nes->cpu->GetTotalCycles();) l5 }% w# z0 G2 K5 ^/ Z
        }
! B# w# K! k0 y7 z# b9 p        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
( U3 Y+ u( ^: O4 K* D" x                elapsed_time = nes->cpu->GetTotalCycles();
' ^: F8 d- a: O6 N5 r: k        }6 k1 Q* \3 v) W1 ^) v
#else7 k4 K; E0 y- a" V6 g7 {5 ?
        elapsed_time = nes->cpu->GetTotalCycles();0 w2 t! R0 W! n5 G! k2 |# i
#endif7 Q: b6 |, ]4 W/ t5 X2 p5 S
}
0 O7 r! p' Y. z* Y" p# L
; |! g  @+ v$ S; g& {- k// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 C& H) O4 c4 l3 n
INT        APU::GetChannelFrequency( INT no )
$ _5 v% s4 Z  c{- Z2 w/ ~1 ~2 y9 b! P  Z1 z/ A
        if( !m_bMute[0] )
- D8 I. Z& z  p; j. w/ A                return        0;' Y, k4 \+ @- Q' A" P- _% z. W1 C0 T
/ s, r0 J5 \1 f2 d0 {5 y* n
        // Internal
$ G2 d6 P' o; O: E7 |. Q6 |        if( no < 5 ) {
* S& Z- {0 D; B& N; o3 C  `                return        m_bMute[no+1]?internal.GetFreq( no ):0;3 j5 T% \! C( k, ?) F
        }6 G( W6 j! T! [# }& U+ q
        // VRC6, z# v3 o2 H- E5 q4 U7 W8 c/ ]  G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {" g9 ]$ s: e' S% U
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
# j2 a; U$ f% Z# N        }3 [2 z' f6 F5 }5 I0 |
        // FDS
3 N! m. |4 X7 x3 g- r/ G* g6 {        if( (exsound_select & 0x04) && no == 0x300 ) {% N1 R* h$ H5 @- r
                return        m_bMute[6]?fds.GetFreq( 0 ):0;; c& l6 r- k/ z+ W, p2 _
        }9 a) `# F/ _9 g9 J" u5 p( d) w3 Z
        // MMC5( X4 i& n: f7 W+ l
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {5 \5 y$ m  d2 d1 j% m: J
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;( z4 u' i. v! E
        }
' m( S  e0 ?  S/ [        // N106
5 @& J; i5 z; M        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {4 n# \+ m3 n$ |& [6 p0 _$ G
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
$ T0 n* D6 L/ _! N4 J- I        }
. {& e9 L5 v; D6 j# g5 [        // FME7
, N) c! ^& K4 F, Z9 b/ r/ F7 P        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {5 o8 _* _2 N+ d" T- d
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
! p' |. F/ U% ~! H! Z+ P% L        }
( X% L+ k5 l0 [3 l/ w" e4 b        // VRC7' S& Y( }$ V3 x5 {9 S9 H
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {1 N) P3 Y8 m, j* I: X4 l
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;: W8 @& ~0 n. w  m) K; z
        }; _' m5 A& u# w. E; Q
        return        0;& j1 a9 f4 J9 F  e$ \
}3 t( k3 q0 P, N& R) s. |9 j! @

3 y9 L3 g# y1 E- Z$ @// State Save/Load; \! d. f; R# I; l4 z8 q
void        APU::SaveState( LPBYTE p )
) ~7 U* w( @4 n( |# b* q$ o{( [+ F4 Q0 n: ^2 j8 a4 _; a
#ifdef        _DEBUG
4 `7 k1 t% R; H/ {LPBYTE        pold = p;# U- ^' y: @; C
#endif  z- W+ M" o1 [0 R7 D2 K: X. l

8 E: k% F5 A- z        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
1 g$ H- ^( n; U( R* w. c1 ~+ P" V  Z# p        QueueFlush();1 u8 R. G0 Y. O

) q5 R( Q8 B4 P        internal.SaveState( p );) u. f' o3 a$ c- P. t
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! K3 Z# O6 U/ v7 b3 e
7 o2 \7 }: g; x# Z! u+ [: b
        // VRC6
7 ?9 o( O! U* v1 u        if( exsound_select & 0x01 ) {
' |; H6 k. c2 |- g7 i5 I                vrc6.SaveState( p );0 r3 c$ e$ \$ D% J
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! c5 C3 S- O0 N) y        }
& t3 a" i; t# a        // VRC7 (not support)4 d  G9 e, A- [3 X% V  n
        if( exsound_select & 0x02 ) {
/ |" A+ J( l- J4 A- r3 v; N& V                vrc7.SaveState( p );
' o' K% O) b0 i                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- u: L6 N, }5 F3 I; \
        }0 r2 [& c7 S- T9 }+ a# E
        // FDS
! T6 V# P! t$ d. X        if( exsound_select & 0x04 ) {7 }0 ~. I0 ^  [7 N$ `' A
                fds.SaveState( p );
( B1 h5 d1 D6 w0 k; m  i0 t                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) a4 H! J, U6 {# F4 S        }
2 d) S& g2 b3 x        // MMC5% s) y( @. d5 y6 d
        if( exsound_select & 0x08 ) {
5 I8 M6 u2 U1 i( B2 P% r                mmc5.SaveState( p );7 p1 _' Q0 ]$ ~% T: ]. |
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 ]; |7 _3 v; A2 ^6 C
        }
" E$ H# s% e5 ^' t0 n% A  x  k. c) ]        // N106
: d( U) _% Y8 u2 Y$ T7 \+ d        if( exsound_select & 0x10 ) {
2 r6 a9 W2 y3 s8 f- X! d5 d                n106.SaveState( p );4 o# [+ Y& u/ {' h- i( T1 u
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 _4 `$ ~! I6 ?# ?; j9 x        }7 q- m* P6 B( }! K4 h5 _
        // FME7$ O8 `  \2 B& w
        if( exsound_select & 0x20 ) {
; F! R+ P* b! U# ]                fme7.SaveState( p );" Q/ u; L# U+ |6 ]
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 o" j5 Y* R! r6 X) K3 f
        }* l- l+ z$ Y3 c1 x* z$ H

7 k# u0 G5 B  e* ?1 Q#ifdef        _DEBUG
* ]' d: X6 m6 I8 ^& c+ k7 _DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );" |6 {9 B& z! N% Z( K0 q( k
#endif
2 Y3 o  A5 o0 o! X}
, t( k  v, o: w& M* e1 u! S2 V- }4 q9 Y' F0 C5 o
void        APU::LoadState( LPBYTE p )2 r4 b) {7 _2 J
{
( A5 i' E" p" C$ j        // 帪娫幉傪摨婜偝偣傞堊偵徚偡* ]/ F, B" ?9 g5 C
        QueueClear();
5 |' f4 j1 N2 S+ T& }& l2 r  \, ^# c' W% k
        internal.LoadState( p );
2 @3 b% x3 G0 w9 \& g" Y        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 e( T# U1 B: |" g- \
1 [: c7 X0 s. c- G% F- K( q
        // VRC6' ~7 W. V' O2 h9 ~" |
        if( exsound_select & 0x01 ) {3 K0 }' j( L9 z, `( _
                vrc6.LoadState( p );' k; ^1 [% {6 S- A8 o
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
6 R0 t9 [5 q9 p3 v, i        }
+ V( O$ K. m0 I        // VRC7 (not support)
+ l; S; N9 g) B% @& B  V+ c        if( exsound_select & 0x02 ) {/ O; W  l: L, O' b
                vrc7.LoadState( p );
( E4 {8 v  W  n& ?  x                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 P- _1 e- ?' @. K6 _" g        }( E4 ?+ e; O6 n$ g3 @; T
        // FDS$ }& u1 ?- [. T. @
        if( exsound_select & 0x04 ) {
) g; [0 ]) t. P( k; i8 K" i" Y                fds.LoadState( p );6 W& \  o8 T4 t( m7 \/ s
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding) E6 x8 v0 g4 m
        }5 t. R/ r( x+ x7 c* a4 \% N/ x
        // MMC55 l' q% s/ ~7 i  K, w) f8 J: ~
        if( exsound_select & 0x08 ) {8 V7 F; V7 }* l
                mmc5.LoadState( p );
9 B" X6 p0 h- S) I8 H$ a* h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* @  d9 I' s1 i/ w6 p
        }& j* D4 d: w0 D! W
        // N1067 U' q- b9 Q  Q" K- q6 O$ A
        if( exsound_select & 0x10 ) {
4 y# w, P+ D) E( f1 L9 }/ r                n106.LoadState( p );
2 R' q" O; E7 u6 F7 G+ L, g                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- c1 _; Q1 _& e8 v: T9 d4 z1 ~        }
+ T% N' m9 J3 L        // FME7% L4 e( a& E5 p  f! i/ Y& U
        if( exsound_select & 0x20 ) {- n* |) b5 c% s! _$ n
                fme7.LoadState( p );) s5 f% i( v6 I' `9 G4 u/ k
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# q2 _" A2 M$ I8 N: o; h        }* [9 c8 K: D! G. ?& x, h
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 - ]; @5 i' z& K$ i5 p0 P1 j
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
; |, a" Q+ ~7 T3 i6 R+ {' O) ], s感激不尽~~
/ o; A# z) k# ]9 Q
恩 我對模擬器不是很有研究,
3 ^+ U3 C+ R: b, ^! Z" t# z' h雖然要了解源碼內容,可能不是很困難,) n6 A3 o3 G# E$ h% O) S
不過還是要花時間,個人目前蠻忙碌的。
0 W. z- O* O6 H- o7 J/ O" J/ X0 W! _
給你一個朋友的MSN,你可以跟他討論看看,2 G9 d+ o& r; `* N
他本身是程式設計師,也對FC模擬器很有興趣。
$ P2 v9 m1 c" l# d) r6 n; B
+ a, ]9 D; y. r: r) {MSN我就PM到你的信箱了。
( [  T7 v" Z7 M8 I% n7 Y
1 E6 N7 d; i+ [, v# b- p希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
, B% a& K: j* q2 `$ X$ l8 g呵…… 谢过团长大人~~
# Z1 w: H; C  d
' R+ C4 ^6 o! J# w
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ; ]8 q) I0 A' d4 h9 a4 B2 {
团长的朋友都是神,那团长就是神的boss。
) m9 Q: s; h! `0 T
哈 不敢當,我只是個平凡人,$ e8 N: d: V4 r7 T2 t) y
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙. v. V* m2 u1 q
ZYH4 [6 k' w6 f7 n7 y5 i9 M  [! Z+ c- [
QQ:414734306
; x4 ~) `! m0 ?7 R2 ^8 L7 L4 MMail:zyh-01@126.com- b+ e% V7 k! n! v. ]7 @/ Y1 X

0 H/ H: W! H( u. |# B& V$ O+ W他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
( m: Q1 E9 t$ `. T再次对团长大人和悠悠哥的无私帮助表示感谢~~

! R) @3 l; a: x0 t; N不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-17 20:53 , Processed in 1.089844 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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