EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?4 }5 b6 c4 e- e& `9 K/ s# ~- s# _
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。% e: h1 a/ t" w7 c
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, B7 K$ }8 g9 z0 [/ m! D
这里有相应的模拟器源码,就当送给大侠了~~
# v: A! ]7 A, e5 R9 Q- h5 I0 zhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 n7 r6 {7 c  x
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 }: ]* m! P6 H5 ]楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% `- Z) M9 {& [3 s' u  P  v
这里有相应的模拟器源码,就当送给大侠 ...

  j% B2 U% O) F- l% _聲音部分(Audoi Process Unit = APU):
+ x5 @. v7 Q7 z! L: ?6 o! _.\NES\APU.cpp
& Z) S; q2 O: S.\NES\APU.h
9 |+ x+ b' ]$ D; P; Y, V( ^0 e) s3 y4 B/ F( g) I
- R7 G) c- K8 e4 n# G
影像處理部份(Picture Processing Unit = PPU):
" l) R/ J) t" C; p9 C, p. j( v.\NES\PPU.cpp
/ i4 O' v& p$ C( m$ z.\NES\PPU.h6 G$ n1 M* K/ X& J, [3 }
7 j; D0 u! o/ c; I* X: O2 W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
6 D; v3 V6 E( c- R0 h(由于很多专用术语和算法机理都不明白,所以看不大懂……)( Q% I" B3 d7 m& F' Y0 {6 L8 D
//////////////////////////////////////////////////////////////////////////4 w1 m/ I  q6 M: @6 g- N6 _% G
//                                                                      //
: ?6 o2 ^! |) N: M9 T//      NES APU core                                                    //7 R, x) \) O; B# Z0 g0 }
//                                                           Norix      //
7 ^3 a1 j* i& L5 y# r% B9 b; S! z//                                               written     2002/06/27 //
% }/ H# e4 _5 h2 l* l# `5 v//                                               last modify ----/--/-- //; s* f8 v( p$ S, ~6 |) M# }' P$ `
//////////////////////////////////////////////////////////////////////////& \8 F5 M* Z( ~5 a2 N/ t2 }" }1 `
#include "DebugOut.h"+ R, U& G* H! o/ H  n/ f- ?; Y$ ~0 g
#include "App.h"5 D2 L& u  S8 s! b1 c
#include "Config.h"
* Y2 q9 C4 V4 t2 E  L' @
* z% {8 n* z# q7 e# C#include "nes.h"
- ^* }& }3 B7 C! o# y4 O: F9 j#include "mmu.h"
  C, O* V) B- D- q8 }3 Q% E#include "cpu.h"" y9 @* p; a8 Y7 Q
#include "ppu.h") P" G* ]5 O7 d3 U8 G: R
#include "rom.h"% z: p' Y: z* ~& f
#include "apu.h"
, H: E+ \/ P, d% c- Z7 d( S+ i4 _6 v, R$ g5 x# K- L1 i5 @; Z) f( ^( h( ]0 y
// Volume adjust
: ]5 w4 q! p4 V8 ^0 z  }" Q2 ?// Internal sounds
  G; [: o" L: `) E6 ?#define        RECTANGLE_VOL        (0x0F0); V! |' r9 ~1 z' ?7 l, f& a& H2 [  T+ S1 Q
#define        TRIANGLE_VOL        (0x130)
9 e; a3 S3 k& Y1 o#define        NOISE_VOL        (0x0C0)
" R' g, S6 D, E- o#define        DPCM_VOL        (0x0F0)
/ \1 a& c7 z0 ~// Extra sounds
& X/ h( Z% p) ?; k. P5 V! }#define        VRC6_VOL        (0x0F0), B* i+ T8 J6 V4 j, J  j# q- P5 W
#define        VRC7_VOL        (0x130)0 }: [2 d, E) M9 g; w! j0 c% G: O
#define        FDS_VOL                (0x0F0)- n' t: ?7 G* I0 C
#define        MMC5_VOL        (0x0F0)1 |+ W/ X* }9 A) J- \5 d; E
#define        N106_VOL        (0x088)
. }3 G; d" g+ K% t#define        FME7_VOL        (0x130)4 \* b; x0 x! Q. }' O1 d4 p

0 L% {' ]) d; H7 v3 {APU::APU( NES* parent )
  w( K, a3 `% u- D2 {7 Z{
7 v5 v% r- J2 c5 ]        exsound_select = 0;. E1 k7 }. z8 B/ l' _! m

+ j2 b' p) d9 @2 {. w+ q) U' ]        nes = parent;
1 K; l" l1 K" B        internal.SetParent( parent );7 f+ @9 D0 P0 A. c) M

) O' M0 @9 ^; O$ e" @  ]        last_data = last_diff = 0;8 t+ [7 x$ n$ l+ G0 y3 j' J
" z6 S6 ^) b8 H8 G* N
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
& Y/ E8 I  o) \# e( W: d
4 W4 u$ n# U  w. {        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 t! w$ h, ?4 m* o4 Z
        ZEROMEMORY( &queue, sizeof(queue) );" B" j8 j# [* Y2 e) H5 m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 ]- U* ^0 M# `: T" k
4 z( t7 W# @' Z; _$ `/ W1 C  j
        for( INT i = 0; i < 16; i++ ) {
7 `+ w3 V7 {# p& W5 N                m_bMute = TRUE;
4 r' N+ [, D3 ]$ d" K8 j        }
! `/ b' F4 N" l+ y1 Q) c}
/ n5 A3 r! a7 x% z- m( H* T
* }- S; T' ~6 yAPU::~APU()  F% }- \7 f  o( \  _$ z
{4 @" L4 B& K+ |7 I
}: \/ Q+ y( P! x

& }8 }; i0 Z; ]- p& Pvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )& v& V8 r& D. P$ ]" N7 T# W& m
{: B1 n! }+ H/ T! M5 k; O2 C* M
        queue.data[queue.wrptr].time = writetime;
# W! j( {% Q8 Q- q        queue.data[queue.wrptr].addr = addr;; B$ ~1 z% x5 [+ a2 g6 K) `
        queue.data[queue.wrptr].data = data;# k: S- G6 N8 e7 A* S
        queue.wrptr++;' v$ |, ]; i6 Z# x5 j
        queue.wrptr&=QUEUE_LENGTH-1;
' v1 |. O/ y! \. j        if( queue.wrptr == queue.rdptr ) {6 u& s* H. o0 t, U2 e
                DEBUGOUT( "queue overflow.\n" );
9 w6 |0 F6 i# e8 j% G; b        }, t9 K6 c. {; [1 P) `+ F
}
9 ]) S1 H* U) ^
* f% s( ^: E- e. L, K& a& \BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- |# E4 N; R0 C4 H{1 l' b2 z, u6 U! w* l
        if( queue.wrptr == queue.rdptr ) {
2 g7 [6 s: J9 l! `7 k( @                return        FALSE;$ z, V" Q! M* Y* S
        }
( H  i* D; z  T/ q. e" y' y        if( queue.data[queue.rdptr].time <= writetime ) {8 [) w2 j0 n9 J% w4 g  A& F
                ret = queue.data[queue.rdptr];; s  j  N+ J$ i8 y' \0 @
                queue.rdptr++;/ D" _0 [1 q0 T" V& W' w
                queue.rdptr&=QUEUE_LENGTH-1;
6 k& j; b/ _1 n/ {                return        TRUE;; O1 a) j( j, l* y6 T
        }; Q3 O5 S' I1 y
        return        FALSE;
8 ~7 M( y& e/ U! P! y}" A1 h5 f+ k0 C2 d9 M, g

6 U" X) E3 S' M/ f! ivoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ B. m  b# j) V# a, b6 Q
{5 X1 F% e; W& N- E3 y" I7 K: E
        exqueue.data[exqueue.wrptr].time = writetime;
! X" {3 {( r( G4 K: Y" f        exqueue.data[exqueue.wrptr].addr = addr;
, C* r- n0 C/ h, C- r2 u, O! p5 ^        exqueue.data[exqueue.wrptr].data = data;3 H! F9 H. A; ?6 j1 v5 G
        exqueue.wrptr++;
: K' G) g4 r, \# S. F& G        exqueue.wrptr&=QUEUE_LENGTH-1;
+ k& x2 T7 j$ v: q, v        if( exqueue.wrptr == exqueue.rdptr ) {
5 h9 z, a' L0 t/ L4 a6 ~5 Y                DEBUGOUT( "exqueue overflow.\n" );, I  O. }' K3 p7 m
        }
4 }- A1 h2 A/ G* V$ Y! V/ j$ p}' b8 @% T* p- t1 K" e
+ x  x' t! {0 [! k* Q3 B; E
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
% N; |( t% g0 Q. U, G: H0 [{% `( Z% k+ B/ A) d
        if( exqueue.wrptr == exqueue.rdptr ) {
) z% W) J5 d1 }  k1 e2 C. H                return        FALSE;
* y) K/ U# u0 n5 ]7 E5 h' L        }
& f3 Q$ t7 X2 A        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
" j- Q; }$ o& \7 w. J                ret = exqueue.data[exqueue.rdptr];
! S% q# q0 E% i6 `9 V& p3 H# g& ^                exqueue.rdptr++;8 q2 T- U. y7 T3 ]- e* E& @
                exqueue.rdptr&=QUEUE_LENGTH-1;
9 V' _( j/ U( H. X! r  W                return        TRUE;3 e0 `. J0 I: J1 w; M
        }
/ o9 Q# R; W& h8 M" W        return        FALSE;
$ A, O9 }3 @+ G. ?+ ^0 R0 H3 G}
+ U  L- l6 T: J4 h6 W/ G7 d" E
" V" ]  {$ z7 b% Pvoid        APU::QueueClear()3 A1 g5 t+ u9 [" x4 }
{  @+ G: l* z  O3 J3 L7 W, e" |1 y$ ~
        ZEROMEMORY( &queue, sizeof(queue) );6 f) k$ |4 \* @" \+ N7 h
        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 q: g8 H( E1 T$ ]* r
}
" \5 p$ U( q3 E0 e2 ?; ?8 b# h2 z
; p4 C* s( t: ^& @/ k! q# fvoid        APU::QueueFlush()% j2 O2 Q$ Z3 q/ Q( V; Q
{
6 T* j8 E4 c" w+ m% L0 C6 P        while( queue.wrptr != queue.rdptr ) {
! [4 w2 t; v$ I7 w& z                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
. @- v" t  f' w1 V" q, ]                queue.rdptr++;, D. w- `( N* p, }. B; G
                queue.rdptr&=QUEUE_LENGTH-1;" p7 M4 E" q8 c6 }. Z
        }
! @5 o: E; H4 [6 H/ ?' `& h7 R, \) z7 u) `0 L! U
        while( exqueue.wrptr != exqueue.rdptr ) {, T0 }: i) z- Y3 |) j: v* Z  \
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );" \2 M9 m8 n- Z! `- J4 V. p9 B6 g; c
                exqueue.rdptr++;8 y, i# b( S' b4 |! E7 W
                exqueue.rdptr&=QUEUE_LENGTH-1;1 f/ \% B  i6 K8 K$ D
        }
1 H( x5 Y3 E/ n, h}
- Z6 g9 U' [2 ?: o3 F% Q; w9 I
3 I$ T! c2 r4 A' d2 y- z  Svoid        APU::SoundSetup()& |: D4 E4 n2 _% D: @: l
{
; C( V1 `8 {- t; R; B- F        FLOAT        fClock = nes->nescfg->CpuClock;, U3 o4 l; ^8 \$ p( L3 j
        INT        nRate = (INT)Config.sound.nRate;/ ?4 D" E% @) V* x- i+ p! l
        internal.Setup( fClock, nRate );
8 A% J, \  d# {" `. `" r0 ~        vrc6.Setup( fClock, nRate );! n9 m& `2 h) o0 Z& n7 o& ]" V1 q2 X
        vrc7.Setup( fClock, nRate );! E3 l' ]5 b/ c) H, [
        mmc5.Setup( fClock, nRate );
1 Q! ^. c- E9 }% ?) @2 g        fds.Setup ( fClock, nRate );
1 \! P2 Y4 x; Z( o: I3 C8 C1 b        n106.Setup( fClock, nRate );
( K0 T* u/ ^0 R) y4 b- Y        fme7.Setup( fClock, nRate );. l* f5 O: T  I" c5 i
}6 h5 u1 u" ?, l5 a9 R2 v, l

( Y: d' y6 A; e8 d3 E" hvoid        APU::Reset()
) X. q% P& S" F+ S{
2 }1 @( a2 Y! R; ?; [+ P; B        ZEROMEMORY( &queue, sizeof(queue) );
3 x; b: {2 p! P( @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 L; x/ I/ P) s! s4 h# E0 R# @4 U+ s; V- [1 L/ E7 N: ?
        elapsed_time = 0;
: p( S5 D- `1 V8 c, s* t! v! u" n/ W4 A" V2 ^, Y6 g
        FLOAT        fClock = nes->nescfg->CpuClock;
9 ^. V' g5 O' F7 T/ F        INT        nRate = (INT)Config.sound.nRate;% `8 ]* W, i) ~1 N
        internal.Reset( fClock, nRate );
7 d8 n  I# |; {% m7 E8 ^4 e' f+ k( E: ?        vrc6.Reset( fClock, nRate );
3 R* H' ?; D  P: N) @9 t        vrc7.Reset( fClock, nRate );4 ~* o. p* j2 N2 R: I" m
        mmc5.Reset( fClock, nRate );
) X( @/ |; [6 A2 x        fds.Reset ( fClock, nRate );
0 N, i0 {- Q! S- a, D        n106.Reset( fClock, nRate );
# G" s( A6 S) u! D" t  {8 s        fme7.Reset( fClock, nRate );
, i( s) C# N& W6 h7 u
( G# G4 j) t2 T* x/ ^# a, L        SoundSetup();
$ l8 |8 g8 c. f' W  M}+ d9 ?* t7 e( I) ]* d

) x& N/ Q7 e: @8 ?9 t1 ivoid        APU::SelectExSound( BYTE data )
) O+ |/ k$ ~6 U5 O2 f{
: A4 d$ l# X+ }        exsound_select = data;- Y. G" k" V0 ]3 V$ E6 }4 t
}& h3 Z$ O% }- U8 K) u& f' K# T+ \
" b2 {5 B0 f2 N6 C2 `! J- P/ l+ u  c
BYTE        APU::Read( WORD addr )/ u: Z4 a& ^8 T' Y. y# C
{
; D3 O! y4 w8 b# B        return        internal.SyncRead( addr );
+ g* G0 z9 T% g( n7 J5 i}
/ H3 w! r' j% m1 G: t
+ A' A$ b1 }' P; jvoid        APU::Write( WORD addr, BYTE data )* f- G$ |4 f. X# T  ~' u
{7 p( J. G1 M0 a/ g$ R# P1 W5 i0 P$ S
        // $4018偼VirtuaNES屌桳億乕僩4 E% G6 L% j/ p$ X$ l  S9 r6 ~
        if( addr >= 0x4000 && addr <= 0x401F ) {
" c% n7 x" d6 t                internal.SyncWrite( addr, data );) q& B# M. a: `0 h5 \! }
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
( T: O: \: X2 E) c# E( ?        }3 X2 x# a4 L) X1 k
}
. X$ d1 w- f  U- n
  [* O5 C5 u/ L. x/ lBYTE        APU::ExRead( WORD addr )8 J$ K4 x9 J2 M  Q: |
{6 |8 c) h4 S% }
BYTE        data = 0;
' v& _! ~; E# [, N
) N$ C7 W- e- Z/ o3 Z& L' A        if( exsound_select & 0x10 ) {% E% r) G2 _8 I$ [
                if( addr == 0x4800 ) {2 t4 |  l# w4 [" E& X# f
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
% g- x- D! E* h0 _# M& o  K6 S                }0 X: Q' [' o2 _
        }
" F& f" b2 b* j7 s$ C+ q        if( exsound_select & 0x04 ) {4 y  T) g$ o) n. n8 j4 Z% }5 T- z
                if( addr >= 0x4040 && addr < 0x4100 ) {5 z$ y7 e  b' M
                        data = fds.SyncRead( addr );
+ p5 j/ h4 n$ c! {. m$ W' ?/ j' x                }
" V$ c. g- q8 I  i' e4 x2 b        }
9 k8 W- }6 a! E# ]* I# Q6 N        if( exsound_select & 0x08 ) {  W" d; P; L9 I+ b1 Z, j
                if( addr >= 0x5000 && addr <= 0x5015 ) {& d5 u: i: J$ ?
                        data = mmc5.SyncRead( addr );
, V: ]$ a' p$ n2 ^. t/ }) Y                }
  \; p) R# _4 {. h        }7 g9 S' [9 `' U9 P3 z9 j, _
& G, l4 H  Y6 a. X, F. l
        return        data;7 o+ h( B) W# U0 E* v8 }4 @) b$ }7 Z
}( r( _, W2 g- ]+ Z. {. d1 d0 z

3 p/ U8 A2 D, B/ A1 lvoid        APU::ExWrite( WORD addr, BYTE data )$ s7 _' L4 u6 y$ J
{: B  _" `" R- P/ W3 k
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
, V7 _" z& y5 h* M  `
. |! z. _" j7 B6 ~# S        if( exsound_select & 0x04 ) {) A3 D. x* Y, g+ s# n
                if( addr >= 0x4040 && addr < 0x4100 ) {
6 c) q; O" c% P9 U4 U8 j                        fds.SyncWrite( addr, data );
: t) \; g4 @, D# I( S                }) B% c4 c: K. `* x2 n) X. w
        }% i5 |1 z) d2 j
9 b; j7 N9 B- K3 G+ Z$ R7 v
        if( exsound_select & 0x08 ) {
; U8 M- \4 e5 C' E3 t3 I                if( addr >= 0x5000 && addr <= 0x5015 ) {2 I. G0 f( t/ _9 y: X! X/ L
                        mmc5.SyncWrite( addr, data );
; J& `' P( B) P: z. ^0 u                }
; b$ {, ?9 M" M- I) W$ C& i0 E        }2 _' P, o1 k5 @1 e2 N4 T
}( B: Y, b5 E+ p1 Q

" K: R  W" q) z* x% c& B! n2 @0 Y4 ?# }7 Vvoid        APU::Sync()1 _6 M( S1 Z4 E, X6 K" A
{
% G% M( ?0 E) |, M/ s# P) p}& j0 t! K: e- U0 ?# ]

7 _) |' Z" M; Hvoid        APU::SyncDPCM( INT cycles )
5 l5 R# z! z" E# b2 [* F. v* V: `{
9 H- m, p0 x2 Y: s1 P        internal.Sync( cycles );
4 r) x. V, P5 {, S% b4 o5 T9 r; i" `* d5 }
        if( exsound_select & 0x04 ) {
: I# Q5 M, q6 B  X' g8 J& x                fds.Sync( cycles );& X  @2 m: `0 n% J: H
        }
( P" d6 H2 r4 k2 p, p; L        if( exsound_select & 0x08 ) {
, k7 v" w+ M7 Q& v                mmc5.Sync( cycles );7 Q6 k+ e& ~1 _5 X3 {
        }
7 F. T1 f7 @% `5 q1 |' h3 A}( V( O& `( r" r. e3 t4 ~
% |0 c: [  C# L. X# o! p
void        APU::WriteProcess( WORD addr, BYTE data )
# I& X# P/ m1 b' Q- d{
8 N' n' X0 z( ^0 a! P# R) u. j" d        // $4018偼VirtuaNES屌桳億乕僩8 a/ |/ `+ w% z. G4 v2 a' `
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 J. s% j: K# G+ n" Q* O( t7 Q3 y                internal.Write( addr, data );8 N) R- X: D* k- N2 D$ v* K
        }
( @% i' g% {$ o7 v- N% j  q) S}: A% }% U, u4 T+ ?( F
7 ?' c3 T6 I: ]8 A( k8 f
void        APU::WriteExProcess( WORD addr, BYTE data )5 X. s. A, p$ b  C
{8 ?5 P; A- `% c2 J
        if( exsound_select & 0x01 ) {
' X: u6 F; T" K% Z1 C0 S, @9 X: P6 T                vrc6.Write( addr, data );
* ^/ X1 h* h; b+ t  ~        }* B3 ^. U0 D! C: G1 n  o9 z( F
        if( exsound_select & 0x02 ) {% \, @# q* b! [" d$ h0 T5 ?, x
                vrc7.Write( addr, data );% d! {  u' p$ q, R
        }
* o' E6 k6 U+ _        if( exsound_select & 0x04 ) {( h1 W+ m  @0 C0 x! W; H
                fds.Write( addr, data );
5 \' y" K1 y" j5 L) e! u        }# D1 N4 |) G1 ^9 ~' u7 f
        if( exsound_select & 0x08 ) {
3 }2 q4 g* S5 G                mmc5.Write( addr, data );! P" W$ m0 z3 k
        }
" u! D5 s$ Z& ?1 R2 `        if( exsound_select & 0x10 ) {6 }- c2 I$ }! [
                if( addr == 0x0000 ) {
: N! Z% z1 N' }$ }. Y9 l1 S                        BYTE        dummy = n106.Read( addr );2 Z/ x4 T! @# T, c4 _& o
                } else {7 {& l, k) U9 f( Y
                        n106.Write( addr, data );$ H" R( ?9 d% A/ b
                }/ [# {( w3 ?5 ?( R/ T( W
        }! K/ O; O# H6 \$ y6 f
        if( exsound_select & 0x20 ) {
$ `/ n- b/ [9 V- r1 V                fme7.Write( addr, data );3 t( U  r# U9 c
        }; l+ l6 J7 _$ U% b; P' t
}9 k) _9 {  X% z

, a7 ?4 ?8 K8 L0 o. bvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  f* Z  G2 S) Z
{) P! N" Q1 g1 |' A: v5 F) r
INT        nBits = Config.sound.nBits;
  i* i' t2 m  b" xDWORD        dwLength = dwSize / (nBits/8);
  u4 Q: j& u/ E; qINT        output;
; J5 u& D5 E) _. WQUEUEDATA q;& o# ~. o1 I6 C, L
DWORD        writetime;
: n# ^7 B6 G' d) ?2 T1 a  N; j
- N# C7 {( [5 h; ]/ ]LPSHORT        pSoundBuf = m_SoundBuffer;
7 d1 R( L3 d, f$ {INT        nCcount = 0;+ Q& C* `) J6 H0 q' P  g& E! y
8 q1 R7 T$ ?0 a5 @1 g
INT        nFilterType = Config.sound.nFilterType;
+ O+ x  I# b) f+ G' W# |9 G3 d( h+ Y) x7 l. D
        if( !Config.sound.bEnable ) {% d& _# X: H8 s8 ?! I
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
8 U$ P$ \/ Q, {! N8 t                return;
/ E5 t% ?- C5 \' `4 {6 ?! x$ d        }; v) E5 f% H1 l6 h6 k
' o0 G& D; b( _6 [% N) k  H
        // Volume setup* F" r% d! {- r! `; x( J+ y
        //  0:Master
+ _4 ~/ P5 g  Y' R7 `        //  1:Rectangle 1
* i) E" O: e6 r$ Q  s        //  2:Rectangle 24 L  |, ?, X3 z$ c( ~1 k
        //  3:Triangle% @8 O- N9 Q7 K" ]9 ^  f( h- Y
        //  4:Noise
& m$ t6 R% P' T) d/ V, {' c. }        //  5:DPCM
9 ]" r2 f) @  d0 `  c  d1 N        //  6:VRC6
% u1 s9 [$ P$ D( Q% ~+ x        //  7:VRC7  |2 `& c2 h5 E4 ^( ~8 i
        //  8:FDS
' i; T+ i+ D6 Y* v        //  9:MMC5
+ n# ?1 z2 u  b3 [/ C; ]- d0 Z/ ]9 a% a        // 10:N106) P  K/ H. M( ?7 y! F1 f. s* H
        // 11:FME7
/ B1 l8 R. ^. u9 o  C        INT        vol[24];) y4 r' g% T+ N% `/ B
        BOOL*        bMute = m_bMute;& Y4 L  u3 H& I+ ]9 C
        SHORT*        nVolume = Config.sound.nVolume;, b( p  v& u) D2 D2 o

3 l7 S* M) o# H, V" [+ K6 j        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
" H% v* V; g6 S" E7 h( g, g5 B; s
5 E& ~. M7 w) j# [        // Internal
( V8 ~8 S9 w* Y" I: V- Z( j        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;$ D0 d' q  }9 P  @4 O
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;, A5 J/ |9 o% d& ^  |/ y' N5 C5 r4 y
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
; {" k1 X+ {" L, Q        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
- `8 ]2 a6 h2 B) G7 h        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
  f( ]8 h0 K$ j
  v. O" ]# O2 E/ `% u# e7 s$ r' X0 w$ H        // VRC6: F" ?# j9 G" @# J6 c- P8 g; w# Z
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) F! i, ~3 o6 R% H" \& {; N        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. F1 x& n9 o' V& k/ h6 `7 @  u) }0 b        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, x: G0 i1 j* w+ i4 @5 [

; D: H; U) R! _+ h/ [* U        // VRC7
& x1 y% }8 M3 e; [; H# a9 o        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- y) u7 H, p0 Q: |1 J# D% U
) p( X0 K* q7 i        // FDS
9 s* f& l" W9 H5 w7 `% n" x        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 c, w- A' ~9 h7 `9 A/ ?
9 M! `* K6 z( {) `( x        // MMC5  _6 `7 f1 c, d% t
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' t7 ?" Y5 b  B/ [6 }        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) ^. x% O2 `% E) P6 J9 _        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 C& y1 T! @. I5 Y: E3 D. X

3 V, v; H6 ]1 A( d3 h5 _; ^        // N106
) ^0 t8 A9 ?9 e        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 U; q7 _* q5 o& U        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: x) ]2 h+ _, H3 Q- E        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# B1 f# k; S! G: R        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  j" S0 A* r, [
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( ^& q  B5 h' p) G2 ?. X  m) j
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% F  V6 g! G! {/ W) E! E; q: P# i        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' N- I! u  m2 F" j4 ?& v7 o
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' B' ]- q5 o2 v# U
/ J" R0 r) S+ a0 o6 F+ u2 |9 _
        // FME7
& S/ A; Y' `+ P$ ]        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. K1 s: ^$ X( M
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# ~  c2 R  y. x& D9 c% x0 q: w$ y
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 F; U1 _9 G$ C$ e3 _8 R' ~) H$ `. P' J0 ?) n  d$ B$ K
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 G2 k4 [7 L% y- u  a% C+ W  J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 {1 h2 b& x# r0 B& z

, X! D& p: |7 R$ D4 o& \# X        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟8 U  m5 s- o) G$ W
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {( Y6 @; q' _& o! |
                QueueFlush();
8 Z. W" _  A- ]4 A# z        }
+ o, J& Q) P/ c
+ V6 b2 b. t# U% A        while( dwLength-- ) {4 x4 r5 v6 X" b4 q7 Q* g) m
                writetime = (DWORD)elapsed_time;0 n2 E$ H/ }  k) n  [

( x6 O. F4 w; E2 }. Z3 q1 X, n                while( GetQueue( writetime, q ) ) {) ?1 D( ~. F  q) a" F
                        WriteProcess( q.addr, q.data );5 s2 d6 L* \: D5 W% p7 d
                }0 F- _9 i6 U9 t7 C

8 s* Q: x# e3 v, c+ j                while( GetExQueue( writetime, q ) ) {
" W6 h- t. y; c3 S, v5 @2 F# P! z% y                        WriteExProcess( q.addr, q.data );
, y! E6 Y8 o! T% V                }3 z7 n5 Q6 T# w$ I/ \& q( z
! k% W7 ~& y& J! b
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME74 y+ O8 |6 K. W8 z/ L
                output = 0;" R+ Z( f$ R. ]; p& F' O) g3 S
                output += internal.Process( 0 )*vol[0];
/ y' p# l2 f* d- b- a& ]                output += internal.Process( 1 )*vol[1];/ e! a3 Q! F7 j4 R
                output += internal.Process( 2 )*vol[2];
2 Y+ a- G; N4 C& W                output += internal.Process( 3 )*vol[3];
* ^( X" ^  a* I: I                output += internal.Process( 4 )*vol[4];0 M! v+ b" C: H9 J; Q8 x/ f

' n. E, x# j/ [                if( exsound_select & 0x01 ) {4 s  P* H& I4 Z- D7 C8 d% a2 g3 {
                        output += vrc6.Process( 0 )*vol[5];
% G" f* o0 B5 W# h* h                        output += vrc6.Process( 1 )*vol[6];
, {5 |  Y) }. d8 @3 q+ |                        output += vrc6.Process( 2 )*vol[7];
2 n7 ]  e* }9 n* K                }
9 @: K- ~4 {4 y! Z# u* G0 p% r                if( exsound_select & 0x02 ) {. h0 q: t; |7 `, G% Q' P
                        output += vrc7.Process( 0 )*vol[8];% C# F0 K2 W7 {  ~; C
                }/ p% r2 k3 l9 v( _, J
                if( exsound_select & 0x04 ) {" s: k: j+ T% L6 I
                        output += fds.Process( 0 )*vol[9];  b! z( t$ w. {  h& t/ H+ S# n8 {" Y' }
                }
; p6 R! ]4 v5 t9 w1 E) i0 h                if( exsound_select & 0x08 ) {
# \3 Q' e/ [/ w                        output += mmc5.Process( 0 )*vol[10];
$ l: h- \1 v, Y' |                        output += mmc5.Process( 1 )*vol[11];
& R; O% Z8 J" T5 s# o7 c3 h                        output += mmc5.Process( 2 )*vol[12];# o% w$ s# @( R9 ]: R
                }1 m( z' M! o# S! K6 H6 @+ g- k
                if( exsound_select & 0x10 ) {8 N4 K" D/ N# P7 t3 ^1 S( w+ F% g
                        output += n106.Process( 0 )*vol[13];0 ?" z7 l& \7 {/ U; y1 b7 |
                        output += n106.Process( 1 )*vol[14];
/ V8 d4 E! \4 M0 z5 C- R( ?7 l                        output += n106.Process( 2 )*vol[15];; z3 P4 S" T' u; u! P& a! Z. \
                        output += n106.Process( 3 )*vol[16];; ], l4 \- h2 V0 ^
                        output += n106.Process( 4 )*vol[17];
) j1 @$ j4 W( Z% F& a9 w                        output += n106.Process( 5 )*vol[18];) F) F" Q# n) H) B. {
                        output += n106.Process( 6 )*vol[19];3 K0 L9 z8 w; z, E- i4 S9 K
                        output += n106.Process( 7 )*vol[20];2 S# @2 q# X& ^1 r7 ]8 u) @, v8 o
                }
0 C7 @7 @/ f6 l( ?% s                if( exsound_select & 0x20 ) {
3 g$ J# A! n( A+ e& r                        fme7.Process( 3 );        // Envelope & Noise
) }; I' O9 |5 R! I) `7 x) E  ?' ]2 T                        output += fme7.Process( 0 )*vol[21];$ _% o9 N/ H2 z9 ~  o! ^
                        output += fme7.Process( 1 )*vol[22];
0 e, {5 \0 L8 @2 J                        output += fme7.Process( 2 )*vol[23];
* b& z! m) z/ f6 r                }* f7 G$ ?2 ^; T7 q) y

' b) D9 j0 w$ g% `                output >>= 8;: e% S; H8 r& X
+ z; v6 Z+ \4 i
                if( nFilterType == 1 ) {7 L- r" {" c& V& L$ m3 Q
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
8 f2 k- D8 ?; O* z6 I' P                        output = (lowpass_filter[0]+output)/2;
6 Y2 x  G0 o/ l2 X. V' `2 R                        lowpass_filter[0] = output;" c8 @+ o& n3 n& ]
                } else if( nFilterType == 2 ) {' s) ~8 x( m7 M8 M
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
1 m, w) y+ T" {3 q' a                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- n- @% c6 _( C; P. H2 J; E                        lowpass_filter[1] = lowpass_filter[0];
& x- Y" E7 U1 f+ E                        lowpass_filter[0] = output;
2 S. l/ J3 C8 W. S& @+ ]  J1 K. }" B( ^                } else if( nFilterType == 3 ) {0 n6 S* r- n% x3 j
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 V4 h% i5 \# _6 _! @                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;% Y0 l+ A$ \. ]0 F+ J! {( R
                        lowpass_filter[2] = lowpass_filter[1];" v7 Y& n2 _7 y! Q; m8 S4 r. V3 C
                        lowpass_filter[1] = lowpass_filter[0];; Z2 z2 z' n" f7 k  ?& ~5 t3 {. Z
                        lowpass_filter[0] = output;
8 l# z$ P- m0 q! U; W( m                } else if( nFilterType == 4 ) {
2 {( v6 _9 c. m" u( d                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 d: i$ ]2 c$ n% L% q( a                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;6 p4 m8 b2 s9 Z! x4 h
                        lowpass_filter[1] = lowpass_filter[0];
' {% i; j* [9 c1 D                        lowpass_filter[0] = output;
8 V6 Z* z. e+ x2 R0 a% x                }5 l6 z, l4 C9 D6 |% W$ _" f4 m

* U3 `( m8 m. q) L0 M3 X/ t/ e0 d#if        0
6 a) ~( Z+ J. B4 V9 U                // DC惉暘偺僇僢僩5 y/ q8 O/ G9 W% \! t- E
                {
! `$ `9 `$ P8 Q% E2 e4 y6 c* l# ^4 K                static double ave = 0.0, max=0.0, min=0.0;1 J& u1 d+ A6 ?% x
                double delta;
2 B5 \0 B0 }) z7 E# b5 E" |% V) s                delta = (max-min)/32768.0;
: L" @9 `6 A9 Z* ~+ i0 \" ]7 \                max -= delta;
' V& t& O1 I& z& ?, L                min += delta;
" M) d$ B/ R0 w; D+ I1 r( m                if( output > max ) max = output;6 q5 ?, n- {( X4 q
                if( output < min ) min = output;" d% Q% j" X6 i7 C
                ave -= ave/1024.0;( O$ S- K. H9 }6 @0 m5 l5 w( d
                ave += (max+min)/2048.0;! P. `5 A# h- R, m- W9 ?
                output -= (INT)ave;) L! K$ W( `* T* i8 R8 y
                }
, G! z6 q( H& W9 i# k7 |#endif( r5 s. l$ e1 Y& {. x
#if        1, E8 K2 r+ i2 f( s' u, o
                // DC惉暘偺僇僢僩(HPF TEST); I" T0 s$ n! C
                {# C& ]: M, M. W, p- C+ e6 A
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);$ ?- p4 _6 l) f$ x% ~8 Q
                static        double        cutofftemp = (2.0*3.141592653579*40.0);" V9 X) R% G/ U
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
8 \4 w0 q8 Q/ I* ^- ^$ t; l8 h                static        double        tmp = 0.0;
0 u3 Y- h7 M2 j8 I                double        in, out;% S  N$ n' f/ a* m
' D  ]* G' H: }! M5 a
                in = (double)output;" C0 n$ j1 I- Y% R5 u
                out = (in - tmp);
1 M5 X  r" X% H                tmp = tmp + cutoff * out;
/ F% x2 m" y; p7 X% s
4 u: [" y# O4 F2 ~5 [                output = (INT)out;
1 v, i5 J1 W! k- g                }
0 A9 X# l% N& X/ f  G#endif
9 W0 f. N* y3 S#if        0* ]- R5 u6 ?3 E8 _* w
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 S1 p5 p2 K. q2 n- Y) C
                {8 a* l% G* S# V' y" x% \
                INT        diff = abs(output-last_data);
" c+ K, u) |0 v4 u1 I                if( diff > 0x4000 ) {
' @0 Z* b/ b- p2 b* }                        output /= 4;
2 O4 [4 w* K# U8 `                } else
) f7 O# h. g4 Y+ f                if( diff > 0x3000 ) {
1 A7 ^. S/ @( z. A+ G$ z                        output /= 3;. D' D& S. R8 S2 ^' i
                } else) I% C( E/ r* e' t- S
                if( diff > 0x2000 ) {* o! ?8 h1 I2 Y  t& A
                        output /= 2;0 S" `* f) K& [/ x
                }6 r5 ]' J0 u* ^& Q/ U# I
                last_data = output;* ~' n  P+ k& Z7 m# s+ v
                }
+ ~( }4 i* e% S#endif+ O% M* I' ?! i6 \2 \
                // Limit
  \" v: P/ l0 U# p7 T3 T6 F( q                if( output > 0x7FFF ) {/ G- ?; ]3 S) h; {5 ~
                        output = 0x7FFF;
2 H- F0 E' q" Z, p* O0 t                } else if( output < -0x8000 ) {
# n7 y$ M9 e3 h; ]3 t2 ^                        output = -0x8000;' H; q! n8 J0 {0 R( P# P+ i7 w' P; X
                }$ E5 {7 N0 A: l4 d4 `- P: k* v
- j1 J- b+ Z7 e' G; }. f# ^
                if( nBits != 8 ) {) B$ f, |; y3 M7 d
                        *(SHORT*)lpBuffer = (SHORT)output;
3 d7 ?" Z' J/ ?' j; q& s0 w: Q                        lpBuffer += sizeof(SHORT);2 V# I5 N: ^$ h. }
                } else {1 }$ E* I% M& t+ W* v
                        *lpBuffer++ = (output>>8)^0x80;
. T  k# V1 D  j2 V: n- M# d5 X                }, x1 s/ Y+ D5 A  @, t# p; B

3 f$ K9 [9 T+ w                if( nCcount < 0x0100 )8 Y- T' [; _3 ^6 Z+ Y# G+ n6 g; f0 E
                        pSoundBuf[nCcount++] = (SHORT)output;; e( X: m7 N3 r( k
* z3 a: t) n+ ~/ O2 B! G; w
//                elapsedtime += cycle_rate;
! Z& @1 _+ v/ h  ?8 T2 S                elapsed_time += cycle_rate;
4 R. S/ ~' q. @        }
- i) d& W! {; x( U" B& P0 _1 D# N4 C" n3 l5 R% _
#if        1
3 U) `( {6 O2 Y& d9 T- }        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, b7 l; i3 ~' k- W% N+ X+ E7 R
                elapsed_time = nes->cpu->GetTotalCycles();
& x! q- f/ B( V7 S  a0 T  z        }
! L7 g+ J4 o* p/ e6 o        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: q1 ?- O/ V) j, V/ D; B2 R                elapsed_time = nes->cpu->GetTotalCycles();
9 w- p8 K5 H. G6 d% w        }
' U5 E8 _: P5 g! U; {#else0 H* x! G; a* S, z
        elapsed_time = nes->cpu->GetTotalCycles();
" w! |# F" ^' F3 D#endif
# D7 \7 C) s: Q. V}
/ r# h4 g% B9 |2 F6 E7 H5 m" p
) d$ K+ i% a2 N5 a) [" N7 p- h// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ q" i- [6 y. \# Z: iINT        APU::GetChannelFrequency( INT no )* G- z, y9 a! N! k, t* Y
{
1 C5 b* o. x; S  y- Q        if( !m_bMute[0] )8 |9 F6 r9 ~( }/ e4 A) w
                return        0;
9 T9 S5 V6 T! L2 r* b" b. o8 L4 @" c+ g( U5 y
        // Internal
6 k  ]+ E, K' W9 ]- z! J        if( no < 5 ) {
! P# m- ?/ X  E8 c# k# h0 H                return        m_bMute[no+1]?internal.GetFreq( no ):0;
7 _/ U8 @1 H3 }; ~! D6 e        }' [4 ]. c( k- F7 D& E$ p
        // VRC67 N9 j: N* s. D0 E# `0 x
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' g# [2 @  G  Y1 b8 h0 [                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;9 d& @5 \- Z% {& w2 e
        }, @7 Z; @& W+ K' r* B
        // FDS
" y. C7 k, K- Y2 E, q* ~* x$ i" C        if( (exsound_select & 0x04) && no == 0x300 ) {/ b1 j; b' U# z' g* v
                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 ^  K. w5 y! D3 M9 _
        }
9 i. B' ^0 c# P# Z        // MMC5
# m: ]& i6 _! K* x        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {. o# V8 r' _) e1 m: d
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  _$ N1 |: X& H, w6 D
        }
8 Q7 }0 O2 W/ z  D* y& i        // N106
0 O* g. `9 @, Q' k; Q+ A        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
) u& x5 \2 S8 q9 \                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;! ^4 M* n5 Q% ~, P% e7 V" S! J  ]
        }
$ J  l# r1 |8 r8 i# _& C/ ~& ]        // FME7/ L  `; w  i! G2 K4 Q( Y0 {! }" ]
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
* d; d0 m+ A" o" o                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;# d# d6 ?5 a0 w( C  _
        }0 Y6 i6 ?/ s  f
        // VRC7
" T0 y% L# j; }        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {, i# A' V% c% D* W
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;& H# c2 O$ w. f/ _( K7 _9 D$ M  D& t
        }
  n: J' u: T* j$ O3 e- G6 U) C        return        0;0 f4 n  g8 Q' H8 Q  d* o2 n
}) z2 p. P# y$ m

7 _6 [  b8 k! b" ^8 h// State Save/Load
# |. P% `" S5 ~, _5 Cvoid        APU::SaveState( LPBYTE p )
8 ?) N, w- i! j! b: g* s{
% P+ a: u6 `9 f+ o! z#ifdef        _DEBUG! q/ w: k7 [! N2 H3 e
LPBYTE        pold = p;
) g9 d$ ]& r+ T3 h  r#endif* h% S$ t; E0 E
# @1 {! y1 `" p. _$ Q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞6 v2 x; Z# ]2 D" t1 `' ]6 P* a
        QueueFlush();
% F; A1 e( g' @# R
  y+ Q* ~, H/ K1 n6 E        internal.SaveState( p );
( Q# I" ^  E/ o6 _        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 M1 A! [' s; N! n* O3 ^* ~2 L' E/ D' @* u# D$ r7 ]6 x
        // VRC6# ?1 p* K* k# T4 ]: t" n
        if( exsound_select & 0x01 ) {
5 m' @! T7 L$ i6 ]  j( Q* U- ~                vrc6.SaveState( p );
& v* J* ?) m7 H0 u* X% x2 r                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 x: U& e( P" v3 d
        }
+ O; H8 Y( m( r2 \& ^        // VRC7 (not support)
) G! t  v4 W9 l) O& l3 E        if( exsound_select & 0x02 ) {; `. D2 k; N% m2 U" o% v3 y( s7 Y
                vrc7.SaveState( p );
( M8 b" b' F5 Q" [) ^                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
$ p- u8 `2 z2 Z        }
% g5 I, [- G: f        // FDS1 N" J0 m; _  H/ A
        if( exsound_select & 0x04 ) {$ r9 g1 b0 H+ \/ q+ x
                fds.SaveState( p );  P% l# M+ R( c
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. `7 `  t, Z4 M$ {1 E0 x1 j        }; F  _( w9 d0 Y7 C2 h( P8 {, |
        // MMC5
+ U2 t8 [0 [! P( ]        if( exsound_select & 0x08 ) {
* {9 M" p* T0 T4 L" K; S: G                mmc5.SaveState( p );
8 [8 ?: g( V3 F" R( t! h9 ]3 V                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
" [. v7 q  d5 C5 E! c        }6 K  R4 I- l) R0 ]3 |
        // N106( f) [. z, h' K$ T/ u
        if( exsound_select & 0x10 ) {
6 G# K, H$ Q. k8 D) i: T# L) K                n106.SaveState( p );+ s5 i& t& n' s, |
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# [: u; |0 Y9 K7 z" Y        }' T5 {1 _9 F$ t" D+ F4 E
        // FME7
6 J- J5 |  \( N4 ]& h& o        if( exsound_select & 0x20 ) {, y5 {1 @% \: ]- ?
                fme7.SaveState( p );& J9 X( V* E: P, [$ ^
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding& h3 i7 Y2 L* J: F: T/ D, u0 e7 @$ `
        }
% Q' g7 f" D% [1 N! U7 j8 c/ X; f# t1 ^$ t$ I+ u6 j5 j
#ifdef        _DEBUG( p6 {8 x" }: l+ s  u
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
6 \' `& ?$ H6 k' W, ]#endif
( ]. Y6 p8 J, \5 @}) n' x% d6 h/ B1 s% ^: g& W
) s' I( ^( x: P1 `. t$ G9 J# |
void        APU::LoadState( LPBYTE p )
7 O+ \! j* A" w0 Z{# H9 k8 T" u8 d3 }, p
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡7 W8 e! ~. M3 _  w
        QueueClear();
3 m0 e! b. b1 }  c4 w
; k9 n. g! y( ]5 V; l        internal.LoadState( p );
8 z1 k) G, J0 u" `" W  `$ i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 X5 }( N, l7 s# n2 |

& [3 ]1 a# N  }/ I) s8 F' D        // VRC69 Y3 {5 v5 v  t4 |
        if( exsound_select & 0x01 ) {
% p& T& \# w- |8 r  N! @6 D                vrc6.LoadState( p );
. G" _4 T& @) c                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 C8 D0 x9 Y# o9 H, g
        }( T9 d) N! R9 x4 X
        // VRC7 (not support)
/ R8 N0 i$ P, g" a        if( exsound_select & 0x02 ) {
  O0 V# l9 }0 x$ d& \: N                vrc7.LoadState( p );
+ }- G# q( D9 i2 ~; ^8 E3 C                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: ^# b9 f* t7 J4 I2 n. ^0 `        }) `8 o6 Y" r" [4 M. R
        // FDS3 h* [7 k! `- g2 K1 q3 a
        if( exsound_select & 0x04 ) {
( T3 |( f0 R: q3 i8 @                fds.LoadState( p );
8 H1 Z1 }9 q) x. Z4 O9 Z. ~" L                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 K% f3 a( Y4 M8 [6 l
        }: @( }! Y0 b5 b8 b4 S8 a9 b
        // MMC5
7 G! g5 }( ~* Y9 a' z% C        if( exsound_select & 0x08 ) {
# I* E+ o8 i8 O: p; F                mmc5.LoadState( p );8 C: H( P/ R5 D, B% c
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding- [% N& Y9 ~0 a/ f9 @7 T- p
        }& ~/ \# H4 r6 X& L- J
        // N106
$ H! [8 a$ q0 B; o! j( C- f$ r+ }        if( exsound_select & 0x10 ) {/ ?+ s4 }+ I9 c; ?
                n106.LoadState( p );
/ L: K# |( P% j0 m                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 {7 e5 m$ \: T% E) P& M) }- m        }
3 k) {% C4 {/ B; X8 B        // FME7
5 p4 x7 a: ]+ H* ^0 \        if( exsound_select & 0x20 ) {( y& u8 k$ X7 d( p
                fme7.LoadState( p );$ A  ]& G1 \) I! ^  u4 C
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# N4 b5 g8 v, W/ F$ J" ]: D
        }$ R$ |! J! ?. u! }& w; o. b
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 : f' U* G0 N. B" w" N0 I1 w( N
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
5 a2 ^! C* @2 l' E1 ~7 y- r; |感激不尽~~

; W" E( I! G2 K6 [! I2 O2 e. Z恩 我對模擬器不是很有研究,6 _8 [0 F, a7 i& R
雖然要了解源碼內容,可能不是很困難,
2 q, e# D1 B( X不過還是要花時間,個人目前蠻忙碌的。
7 s  f9 ?7 b! R" e- i9 r' D' y  u0 V' w
給你一個朋友的MSN,你可以跟他討論看看,
, ^( I$ }' U' `& @( h( ?( f他本身是程式設計師,也對FC模擬器很有興趣。
* F; G0 ]" U, ^  b4 q% v/ T7 a% r( F) n$ @3 f/ J% \& ]
MSN我就PM到你的信箱了。
5 @6 t2 I; c8 b3 Z1 y3 j- G: q6 E8 }; K: M& [5 K4 Y1 z9 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 发表 / z9 T2 T! @8 F' O) ~3 |
呵…… 谢过团长大人~~
2 N$ U; K. c0 Q: X$ [: \
& C' E6 w0 r2 U+ _7 ~  S
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
" O( \2 X/ M: o  j( D. u团长的朋友都是神,那团长就是神的boss。

' [# V- W' [; ^! `" _; y哈 不敢當,我只是個平凡人,$ _( M1 V+ O9 u% m/ Z0 i! X# U
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 I7 ?) c( O  u3 |% b) j* w7 t8 c3 t4 B2 UZYH
, X8 R0 h" u- ^5 \1 T# rQQ:414734306
$ b; r8 @! y9 {9 u  Y; j4 }Mail:zyh-01@126.com
( q. o1 B$ g" {7 E3 L' W0 a( }0 y4 a; t- W& P& Q! Y: T2 W
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . z+ `$ a% C3 K' K2 I9 I+ [
再次对团长大人和悠悠哥的无私帮助表示感谢~~

' _% @+ C  N! ^! R5 o( U6 }不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-8-25 12:12 , Processed in 1.081055 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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