EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( x8 b) `" I7 [; u楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 D% M0 C& I( k1 Y3 g6 P1 B
这里有相应的模拟器源码,就当送给大侠了~~
3 D. H- X3 f) F/ f( I6 Jhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ; Q) }1 o# U1 @6 Y4 E
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ i) ~; F6 E4 A8 w" ^# p( V# _楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, Q, H! K7 D" o: e这里有相应的模拟器源码,就当送给大侠 ...
1 w) W6 A$ Q3 E
聲音部分(Audoi Process Unit = APU):
" @  r2 D- j! b( m  R8 v4 P% P.\NES\APU.cpp- A# J0 t  k3 q5 i1 {
.\NES\APU.h
( G$ `( j; `* q7 j* w0 ]/ e! a) I1 M! n( d% R+ `+ f  J8 F/ P

2 y' u, r+ t4 j  S" t6 q9 `影像處理部份(Picture Processing Unit = PPU):
& C; p3 X0 \8 I- c+ p  U.\NES\PPU.cpp7 C0 E$ ?& l+ o: Q# R
.\NES\PPU.h$ s* r2 J- o: B5 z
/ d1 A$ i) Y7 e5 O
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:- ~/ H& I( a( e( A* R
(由于很多专用术语和算法机理都不明白,所以看不大懂……)# G+ ~8 ?3 B% u8 z
//////////////////////////////////////////////////////////////////////////7 B" G8 u# F5 H- Y$ j0 B
//                                                                      //
8 j  ~" Y( L( r* M8 C//      NES APU core                                                    //; f$ t/ I; d$ s. w! m
//                                                           Norix      //
( [* _( C2 F- _  w/ O+ j$ J& A8 T//                                               written     2002/06/27 //& ]% B& }; n' H
//                                               last modify ----/--/-- //
1 K( e7 o! ^" G//////////////////////////////////////////////////////////////////////////
. q$ ~! w. e5 G- K" o9 F3 Z( H4 j3 k#include "DebugOut.h"2 K0 W9 [& K% [  K' x9 @* D9 k& H
#include "App.h"+ E1 q0 U4 F& K+ Y" G
#include "Config.h"' a. ?5 s$ \! }2 F" ~/ e& v
2 b6 y8 u/ v7 \9 a" L5 X
#include "nes.h"
1 P6 n6 i0 {3 n$ F* ]#include "mmu.h"
/ E% Y9 }( I9 i' p9 Q: P#include "cpu.h"5 p2 j  O) X$ g! U6 {: J
#include "ppu.h"6 z* e6 [2 x" g4 j' U
#include "rom.h"
, ]. |* o$ g% ]1 Q% }+ Q#include "apu.h"" }8 Q, ~) ~2 Y( W7 B. D
% z+ b" b1 M1 k
// Volume adjust
6 P8 F9 Y1 E; a( w) ^+ W: }// Internal sounds  d: B  K7 X! D- U) D. x) }% b
#define        RECTANGLE_VOL        (0x0F0)& S. C3 d0 ^1 w+ L+ o- i6 Z
#define        TRIANGLE_VOL        (0x130)
4 u) y( k3 f: F8 ~0 B  P1 B5 ?#define        NOISE_VOL        (0x0C0). F: ~! w% q' L( }0 P5 Q3 s1 R$ z
#define        DPCM_VOL        (0x0F0)
, g& z2 R5 f0 z4 d2 {- J// Extra sounds9 J/ Q( I$ [6 X4 L2 f0 Q" I
#define        VRC6_VOL        (0x0F0)8 A) P2 j+ U. c% a
#define        VRC7_VOL        (0x130)# \( p1 |/ Y5 y$ d, S
#define        FDS_VOL                (0x0F0)
4 D' Y3 Z" [/ f+ c8 v- O#define        MMC5_VOL        (0x0F0)
$ c# i1 B- z% h" \2 e9 }#define        N106_VOL        (0x088)) s/ u9 F2 q  p* i4 @, _4 k
#define        FME7_VOL        (0x130)/ a/ n9 ~" N; S" @1 [$ g: L6 `
% w' c- M! d7 k0 B; h9 [) }
APU::APU( NES* parent )
3 C5 _+ i1 |2 u7 z7 F& r{: ?( F' ~: Y2 T$ H( ~
        exsound_select = 0;
* q9 m" Y, M8 s+ Z1 U+ Z# V" S  ~
        nes = parent;
* _, Y4 z8 P2 G        internal.SetParent( parent );4 o# V0 I5 s( }! i, P
3 B( d5 T  d# r# L; O' _: a
        last_data = last_diff = 0;
* g0 l5 [& `& Z5 P  p" h$ S
5 _. F- `' Y1 d( J1 V        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );5 K) Z& p/ @- l# g2 |; E
9 g0 t( K7 d4 [4 U& ~) |! }9 N
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );: l( u) v+ J; L: }) e' s" O: ^
        ZEROMEMORY( &queue, sizeof(queue) );% \- D2 p$ D: Y8 \* F9 c9 ~
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: r% j" x" Q- P& }: ]+ T4 Y
& V! e' b" b8 @( C8 m/ l        for( INT i = 0; i < 16; i++ ) {% m! }0 l8 e! s1 W
                m_bMute = TRUE;
/ n$ R& R. C3 g) I! C8 x# o        }4 h! h6 T: V# K0 J
}
. C: a. i: n0 J& C9 n' q& _: z% F2 I$ z2 }8 a, C
APU::~APU()6 R. a9 z( z7 U: C
{
( G/ v3 L! T/ @% o' r- z* P. o) G}( {9 O* _/ }% g) U* o( P5 y- a$ l

( X+ T  H) ^# \8 P# `3 J3 gvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )$ u: B+ b! a: `- n2 h6 c. O5 y! w: e
{
" g- ], \% d8 q3 [& d        queue.data[queue.wrptr].time = writetime;
* p( W* ~2 ^6 i% v' E( y        queue.data[queue.wrptr].addr = addr;0 _: w6 H6 q' {' |+ P2 `! o
        queue.data[queue.wrptr].data = data;9 j' Q* c8 I; e7 m7 Y7 K
        queue.wrptr++;' k9 g) s. [% n+ X- P$ F  k
        queue.wrptr&=QUEUE_LENGTH-1;9 f: S( U% C  O3 T. `3 Z
        if( queue.wrptr == queue.rdptr ) {
8 p4 ~4 B+ n  W8 _                DEBUGOUT( "queue overflow.\n" );
; ]5 r3 |; i5 P7 N# F        }
8 ^0 k' F$ h/ {" L/ S: [4 @/ ?! M}
1 i% e( d0 [$ H2 d+ j7 G" q$ R/ O2 k2 I: i# [' s( e& _: R
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )5 M* L# x4 J8 s- _7 d/ w+ B
{
) a1 u0 ^" L, l& `" T: e        if( queue.wrptr == queue.rdptr ) {; B2 y& R2 A) N: Z9 q4 _2 a/ q/ \. j* j
                return        FALSE;; W4 c- |2 Q6 p# _, y
        }
- j3 \; r2 b& R; y. x$ w  K        if( queue.data[queue.rdptr].time <= writetime ) {
2 Z5 D7 M) N6 ^0 ]! W1 {9 @) r( s                ret = queue.data[queue.rdptr];
. A( O8 S( o. D& |5 e9 y% U                queue.rdptr++;
: Z2 c+ P# Z' U: X8 x0 u7 f! C                queue.rdptr&=QUEUE_LENGTH-1;+ M! ^' D: J7 M8 Y0 x
                return        TRUE;
& o+ e5 o% D) Q' T+ ?        }
/ X1 O  e" M* J- I7 N! f: n, d        return        FALSE;
/ k1 M  {1 N' R# d* {$ M}
8 T9 D) a8 K) Z( ^* W! g+ B0 }, M/ ^- h5 U
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )) n" i7 E/ [: t& U9 O$ V9 E
{7 K" V  ]) x2 r) `. U; N
        exqueue.data[exqueue.wrptr].time = writetime;& u# ~/ ?: ]6 v2 d9 q/ l$ Z2 d, Q
        exqueue.data[exqueue.wrptr].addr = addr;/ h# F. H( i) p! A
        exqueue.data[exqueue.wrptr].data = data;* K; O" v! n) K8 g4 `+ u7 F
        exqueue.wrptr++;
! O) H+ {! x2 D4 {- Z/ {        exqueue.wrptr&=QUEUE_LENGTH-1;. _* x% y; g4 {% |  X5 m0 V
        if( exqueue.wrptr == exqueue.rdptr ) {+ i0 i. m4 Y  D# ~7 z
                DEBUGOUT( "exqueue overflow.\n" );
/ r" w6 n; a6 P" _7 |  u        }
4 i5 ^1 p* n) T0 j}% a7 j$ P) J/ k( l& H) v( W

; s$ X6 G# E) `) HBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )2 G; Q: {( q  V$ x* N
{5 Z+ h* P9 L; E6 W; S
        if( exqueue.wrptr == exqueue.rdptr ) {
1 C! f. s0 C- C6 S0 D                return        FALSE;
" h$ z8 o* b' M5 E' P        }  V! q0 a- ~0 N0 e7 C2 S7 r
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
7 a3 \- x, C  x& n/ r                ret = exqueue.data[exqueue.rdptr];
4 N" v- c7 i, @' O! T6 F) y, D' J                exqueue.rdptr++;  [2 a" j/ w( h3 I$ `
                exqueue.rdptr&=QUEUE_LENGTH-1;
7 R( v* K& \. j' d0 u                return        TRUE;# U% T& [" [! X8 g
        }
- r/ Y4 y! u0 D0 W) Q        return        FALSE;/ h4 v2 B+ H8 U, B. N  I
}8 {: y! I' W) o8 o: _  @

( b/ R4 k( j: V& B9 o% }  pvoid        APU::QueueClear()
+ x- l, k1 u. F{
: F" P% ]' e7 e6 {' g5 T* f6 b# f        ZEROMEMORY( &queue, sizeof(queue) );
' x' K, }1 C/ j  x        ZEROMEMORY( &exqueue, sizeof(exqueue) );) R0 d# O" O: B
}$ z/ u( w6 F% r' ]$ c' @% p# m4 y
0 j- |) N3 N$ K+ ^5 i
void        APU::QueueFlush()
  C* _% h/ s' ~7 [1 u0 ~4 t# B{1 D3 ]7 A1 B  L/ o' S
        while( queue.wrptr != queue.rdptr ) {
9 a2 K9 B+ E8 M2 Z, Q                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );( Y2 l* [, w" A' V
                queue.rdptr++;; C7 ]3 `6 k: Y. ~- Y+ n
                queue.rdptr&=QUEUE_LENGTH-1;' H! F! P. Z! p' [1 {
        }
; M$ J! s- R$ g9 n" W
$ T# S  [( x" W( t/ s8 G% u        while( exqueue.wrptr != exqueue.rdptr ) {
& o5 ~3 G' c+ N: B+ N9 T                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
% f4 R1 i+ D6 F  E4 z8 e+ x                exqueue.rdptr++;
% Q" [0 }) Q% i2 s5 [                exqueue.rdptr&=QUEUE_LENGTH-1;' I* U% M& U) R" u2 Y' D6 O  r
        }
- S, P& B3 G& e0 m}( a9 V" O6 v: \- J' n4 h, [

: Y) d# |0 s1 q1 g* W9 @$ Bvoid        APU::SoundSetup()5 O; S2 }& r% }3 H
{
9 Q3 ]6 G/ o% ~4 v        FLOAT        fClock = nes->nescfg->CpuClock;/ P# G9 V9 {- Q6 {% B
        INT        nRate = (INT)Config.sound.nRate;, U5 w7 ]0 U4 K6 R0 f
        internal.Setup( fClock, nRate );
1 z2 l+ F' O4 N3 P% ]/ W% v        vrc6.Setup( fClock, nRate );
+ U' u9 F* t- A7 q* E, {        vrc7.Setup( fClock, nRate );/ u2 s  u8 v! l$ G% Q  |1 q- T. D' D3 L
        mmc5.Setup( fClock, nRate );  X/ d! h! W0 M0 ]% E# R4 L* T8 p
        fds.Setup ( fClock, nRate );6 o. }- v* u- S" d3 d+ K
        n106.Setup( fClock, nRate );) Q' z( ^! d& ?+ w' S4 T
        fme7.Setup( fClock, nRate );  O( [' l; |8 Z  k0 I3 ~+ V5 M
}* r3 d2 ^6 ~# n  v8 N8 G2 J
& l8 S% d! o& Z3 g9 y8 D
void        APU::Reset()3 \) D. T" w. k3 q6 j' J
{% p$ Q2 G& h0 g, H, X; E! t0 Z
        ZEROMEMORY( &queue, sizeof(queue) );
2 p5 b: Q0 c8 H        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 m& U5 N$ R- Q3 u1 S' g

1 M' z- G8 f: k3 P4 F9 G2 A2 Q        elapsed_time = 0;1 x1 M" g  a& I! K5 Y8 T% X

1 _% D' Q. X/ i" c0 D8 ~( w        FLOAT        fClock = nes->nescfg->CpuClock;
+ b# Z/ t5 g% R. t8 i" @# F8 m1 g3 z: p        INT        nRate = (INT)Config.sound.nRate;
' l4 r# e; |3 a1 v' ~% v        internal.Reset( fClock, nRate );
- {1 a* G7 `% S        vrc6.Reset( fClock, nRate );
; ~  L, z2 }' P$ W5 _2 s  x0 L        vrc7.Reset( fClock, nRate );, j, N) W2 z" I- K" Y
        mmc5.Reset( fClock, nRate );
3 |- i+ A0 r2 Y        fds.Reset ( fClock, nRate );4 x+ T; P' N6 Y1 w% w  ?6 _
        n106.Reset( fClock, nRate );0 n# h, J/ H( x2 q, u) P+ E
        fme7.Reset( fClock, nRate );
: @+ ^- l/ W8 V' ?: P+ ]$ ~, |9 U6 k
        SoundSetup();
# q. }9 V% {8 x) G$ `}- R2 ~+ Q) K! |0 w' D
1 R' p3 u. O3 t) c
void        APU::SelectExSound( BYTE data )
) V5 z, Z. |: P. j2 a: H' {{
. y1 }7 Q8 O6 M% w9 S        exsound_select = data;/ c6 }" p5 s  B9 u! |3 H
}' s9 L: T0 N0 {. O

: e) q- h% t6 a: M7 K$ nBYTE        APU::Read( WORD addr )5 ^7 J; O' n; u& Y
{
% h9 q" r" m- `4 e        return        internal.SyncRead( addr );
0 y% U; S8 x( g5 I# K. E}
) F3 t# {. \7 x7 \4 Z; K: D& k" c
" W, f7 h9 Y9 v: Y" k8 u: L7 Avoid        APU::Write( WORD addr, BYTE data )9 O$ T; n" S; g, G4 Q# e# L
{& U3 I6 k6 {# p/ C
        // $4018偼VirtuaNES屌桳億乕僩$ C3 {" p; x3 s  H. h0 T
        if( addr >= 0x4000 && addr <= 0x401F ) {
7 z. f  k4 k% [! [& z                internal.SyncWrite( addr, data );
2 f! x+ x5 E+ w5 v; h                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& _' U) e' N" b7 ~
        }: T# S6 `- B7 N) U1 q
}
9 o: A6 l+ w) ?1 `: i5 f. [$ ^# n& l
% N$ z3 ]; y# ^  s2 I) H! a" \BYTE        APU::ExRead( WORD addr )
# w9 ]! R! s! C! R. p{- U7 J+ U3 @& N1 t
BYTE        data = 0;* V  [* ?; q6 n% j/ |! A; S

1 i' v. \! u# x$ _2 T0 u4 U* @        if( exsound_select & 0x10 ) {! k7 P: `9 |7 x
                if( addr == 0x4800 ) {
) }8 r3 R0 |8 ^& z                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 K, u% ~! [% Z; y  ?$ c' a                }
. Z0 z7 M6 d+ F) U& y        }2 y8 C, I- O# j
        if( exsound_select & 0x04 ) {6 y. \6 G  S( Q% e) D5 A3 h
                if( addr >= 0x4040 && addr < 0x4100 ) {
6 V- w+ @& c; _1 Y. S                        data = fds.SyncRead( addr );6 I0 O" f( `, D- ~/ i3 H
                }
$ m' U5 @0 U2 ^9 T/ G' _        }! h( X: a9 X. H
        if( exsound_select & 0x08 ) {
" d! z; S% o4 e                if( addr >= 0x5000 && addr <= 0x5015 ) {
. S8 M/ i- ~. q* Q- T                        data = mmc5.SyncRead( addr );0 C. k( G9 T, Y
                }
! L' b; [" v( J  u        }# }2 i7 h9 B; Z, N: @9 m3 c
, ]0 a3 c( B, R! V1 [  ]
        return        data;
, H! c6 z) k5 P% r}
8 H! g- ?7 x$ i3 h& M* D* E# b4 o+ g8 K' }0 D% k2 d
void        APU::ExWrite( WORD addr, BYTE data )
6 U2 R$ q* s8 V8 \# p{( c" a3 v$ R( G+ y7 D- Y4 A
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );: |9 K! s* N' x5 ?; L9 l/ k

" J9 b4 v( }, s5 y" n8 e        if( exsound_select & 0x04 ) {/ ]3 }/ J1 c2 [: d3 y. X
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 M- r: i8 h5 h' B+ }3 S% W1 W                        fds.SyncWrite( addr, data );  W. |6 S2 d; M/ R. V$ e
                }! L1 A0 E9 H' r+ ]2 c7 `4 B
        }
2 n8 w- g7 @6 A" K) ?: v; ]
. `7 Z+ M7 n, M' O4 Y        if( exsound_select & 0x08 ) {
) t6 N8 H/ @2 O6 I" j                if( addr >= 0x5000 && addr <= 0x5015 ) {
# `5 }5 {4 @# t& b6 ^                        mmc5.SyncWrite( addr, data );7 O! @8 {# _6 A; p
                }
3 X1 [' H8 b' d        }
7 V4 f7 Q# v# @; U0 ?, t}$ P/ \1 u. }3 H% k( w! i

  ?& C. n# _1 o" g. {: ]void        APU::Sync()
: Z( H7 x  t5 U- n& j1 h{
9 I7 J, b1 S- x! X2 i: i2 h}
! c* d; s' \5 _2 G8 x/ H. }$ E; T, ^! ~5 p: U' v1 h  H5 O
void        APU::SyncDPCM( INT cycles )
# o. z$ j3 g9 D* f# v9 s{
) ~: M% b( @* T        internal.Sync( cycles );; F, g9 m2 m+ D1 x7 e1 S2 p

) t+ `% @$ R5 M  a        if( exsound_select & 0x04 ) {
1 c0 {! L5 z5 D5 C  S% a                fds.Sync( cycles );2 h' y; R$ M: ?1 s
        }+ V5 S0 f# c3 K, @
        if( exsound_select & 0x08 ) {# x* C! x4 I# Q+ I, D( Z
                mmc5.Sync( cycles );
" }' T5 ?3 G$ A6 @+ U: n        }
$ ~: Y( O" d1 u. [5 E1 v}! D, b9 T7 J$ E- S% o, A# d/ k

# w  V6 v+ E& o. i7 Xvoid        APU::WriteProcess( WORD addr, BYTE data )
5 s, x7 L3 K) R6 Y+ f" C5 r( Q{" p1 k) j, w' \9 u/ s. K
        // $4018偼VirtuaNES屌桳億乕僩2 n/ q$ U' b* U$ H& D
        if( addr >= 0x4000 && addr <= 0x401F ) {. l- i1 w, a- M7 |+ ]1 B" @8 j3 W9 S
                internal.Write( addr, data );  F7 L% d1 T9 _) W* e  a4 u1 K
        }
5 x' a  x' P8 t6 A' V}
  M: P( C" m; E9 b5 j0 N/ r, u
1 G+ W5 Q' U, Q, }' s* yvoid        APU::WriteExProcess( WORD addr, BYTE data )5 b) W9 J/ k- R, n3 F
{1 s8 h: F+ P  l. z6 ?& c
        if( exsound_select & 0x01 ) {6 M4 W1 b& t* U4 x
                vrc6.Write( addr, data );3 H! H( k; ]% q5 @3 Y
        }
' v2 M  _$ D$ x8 u8 \3 T        if( exsound_select & 0x02 ) {
' b& i+ H8 W! l                vrc7.Write( addr, data );
, T( C/ g. K; M. y- h5 F7 B        }9 h' o; F  _' t  J3 q" h- a  F
        if( exsound_select & 0x04 ) {$ f7 O" D8 J$ U  w
                fds.Write( addr, data );" x& B( C' l# n
        }5 y; B: G7 I3 g
        if( exsound_select & 0x08 ) {
7 n/ ^/ m2 ^, t3 M  {                mmc5.Write( addr, data );; u  t$ b# A6 H2 a8 s' J
        }
7 F7 p/ N% g! R" r! k( Q4 `7 `        if( exsound_select & 0x10 ) {+ j" l0 I0 b( T9 S, _6 e
                if( addr == 0x0000 ) {- D2 x* Z* K8 W6 j. X
                        BYTE        dummy = n106.Read( addr );
3 X7 e  X0 \  Q" G                } else {
- D$ v. C0 |/ N. x1 M1 J: a9 Y3 L8 x                        n106.Write( addr, data );
& q7 j. O  M% C                }
1 Q0 x- N' V" e' l- q        }
9 Y% h, J* S+ e$ }: P6 k5 y' @        if( exsound_select & 0x20 ) {( F# V$ P" O7 K% o% f
                fme7.Write( addr, data );
! A" N1 J6 C1 }3 |! W* N' b8 `; n        }9 m- e7 n' [) y9 b& n
}
  H0 C; B3 ^* V& E; r" W0 {$ I8 l, c7 D; H1 _2 t
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  a4 K3 Q. C9 f! b3 X
{, h5 i8 W/ p- d: m1 J
INT        nBits = Config.sound.nBits;
. Z6 w; l: l# O. n9 g4 o0 [DWORD        dwLength = dwSize / (nBits/8);, p2 s4 d5 H* m8 |- O" P
INT        output;2 v& o* u0 v4 R; P' |& V% ^: k
QUEUEDATA q;( m: N+ a1 R( X; M- ^" L2 U+ @
DWORD        writetime;, J% |1 X, T1 E
4 Y3 t4 M+ A7 _8 ?1 p5 Z5 _$ r3 u
LPSHORT        pSoundBuf = m_SoundBuffer;$ M2 A; L/ W1 ?7 d* D/ B$ [
INT        nCcount = 0;- ^, k9 K1 F3 `! X; O% J& \/ ]9 @
4 ]1 i# {" X( n3 S4 g- T
INT        nFilterType = Config.sound.nFilterType;1 ~. |$ `+ J5 v) M/ W" G
  A, @6 M" e, E! l
        if( !Config.sound.bEnable ) {7 Z; o7 x8 K1 Y/ h% Z  B
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );( L8 G9 V: C0 Q, C7 w
                return;# k& k$ d: H7 G& M$ X# }; @& }- k
        }
3 u5 o( f. i: P( Y# l: }4 D& b: \& G: B$ Y$ _
        // Volume setup
# g5 g" z/ z& r& K6 K" A        //  0:Master
7 U- x& j) |" N, G( v) I. T) A        //  1:Rectangle 1# H* s6 y' g. F& t; A
        //  2:Rectangle 2
4 {* e; ?3 R, K; V/ |" F/ O; V        //  3:Triangle
" D( v7 H8 ^1 M7 ]) l- H2 m        //  4:Noise
7 `; N; L1 D+ s8 F        //  5:DPCM  ^2 O8 S3 f9 N; a/ b1 Y) _& j- H6 k
        //  6:VRC6
* ]1 @6 ], R" Q2 N* r2 Y        //  7:VRC70 o+ G9 [/ n& s1 d
        //  8:FDS
# u; D9 ~- B- q        //  9:MMC5/ m, H. d! a; E" v8 \2 H7 S5 i
        // 10:N106
0 [: M' Y% T0 V# n        // 11:FME7( V! t+ P- J% }' x" t1 C# C
        INT        vol[24];4 y+ B% b$ C5 |4 s( B
        BOOL*        bMute = m_bMute;
3 q4 M6 r! }  w) `( s        SHORT*        nVolume = Config.sound.nVolume;
, p* r. {/ n2 E; O6 w& T! h: c0 r) V) T' A; J4 A. y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;% q; V8 [" o. p

! ^1 ^  h  x8 V' @1 ]% X! ], Z. \& {        // Internal
' V' y% V" i, J2 f8 n! p9 u* @        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
' F* g3 @. K$ u, \/ P        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
/ Q# g+ K! \8 ]$ S" x8 m        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 w0 n7 t5 m% j) l- [% N; ?/ n$ Z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;$ J0 M2 H( K4 l+ q
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
! L# h3 D* I3 m2 R/ N/ F
  R# c: O: `6 G        // VRC6% }* V0 y7 F8 e, [+ }, F
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 P5 l, T, d; _        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! }7 B6 q, ?. q$ l( X& }
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 |3 u' `9 d" q& j: A1 h; t
. k" o4 _& B, z, w0 B: M        // VRC75 c& v. t- \6 c9 n2 s5 k& Q/ v% `
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. U1 }# M2 G* q3 @# x

& a3 G9 z* Y& o* I3 O! S) B        // FDS
9 g, b; v+ x1 m        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, j, X' I$ _4 ^! |
' R; f8 _" `  e, w" _- X5 @) k, p) h        // MMC5; R$ y( ]9 c8 I# ^  F2 l
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 N) W$ E9 S! Z        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: S% K3 N; P* J7 {. n$ |# c$ [$ x" F6 D
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: }$ G' |1 a* L3 D
1 U0 O! R  ^1 y% l4 S
        // N106
1 L* |  [* q2 d. _3 Z. ?% u0 C- ^        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% b5 O- V, H2 D# e
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ z" V4 c9 F- v' }: n& _3 z        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 C% l/ x' q, ^+ q1 A) y
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  Q% H' J) s) u
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) ~) H3 B0 L+ S2 i1 ^9 ~        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& S6 b. Y2 b& k# P2 \
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& b" n. H2 L9 \
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 m/ ~  J/ [# Y5 t7 Z  @: }) V# a" q9 J
        // FME7
; m) c8 i& w% g; O* l6 K        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; X% R5 a; [3 c. V        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 p% ^( D/ e' c6 y; L& t4 x
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, ^; |" w9 e! |
4 g) e: j% `& y0 N
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
" y' {, B5 E$ y8 x: V' l        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
0 i, s: P$ p" e& s: Z4 B. j- o; p* y+ U2 F
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟  y2 {5 Q3 _# `& d# `
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
6 F1 W$ U" t( g2 v                QueueFlush();' r* ~) d5 O. J' ]! K2 M
        }) u& Q% b  Y+ b: d& R

$ S9 O$ B$ N4 N( W' z/ w9 R. q        while( dwLength-- ) {
1 t+ E) [/ \" B3 [3 n2 P                writetime = (DWORD)elapsed_time;
) L% X$ |0 Z3 @1 ~: b! g: L
3 D- u. d/ V/ o; F4 `                while( GetQueue( writetime, q ) ) {' L+ S9 K, i& o" k/ x& y; c
                        WriteProcess( q.addr, q.data );5 g" q0 H; T( B  J4 \
                }
/ `+ B' i$ F6 G' Z9 l0 A5 ^
# Y# A( o6 s6 a  f) r/ i! H; ^$ Q                while( GetExQueue( writetime, q ) ) {
; A% B; P7 m) F- V0 N                        WriteExProcess( q.addr, q.data );
# D/ A0 D: Q# B9 u! S                }4 G- X2 i4 f, \+ W# ^2 @" X3 p

0 G8 Z. D$ @1 O  H8 V' l* m                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME74 Z( Z; y( R6 ]$ I- U; z
                output = 0;- t7 H9 Z* Q% R
                output += internal.Process( 0 )*vol[0];
* |9 k( \9 E+ p                output += internal.Process( 1 )*vol[1];2 O6 Y4 C1 u. s$ ~( Z0 c7 d5 T$ y" v
                output += internal.Process( 2 )*vol[2];8 a! N  m) l. R# T5 X
                output += internal.Process( 3 )*vol[3];
" i( a2 @2 i' L9 p: G                output += internal.Process( 4 )*vol[4];
3 \3 j) S$ ^6 @( L3 \6 t) g" Q* e
                if( exsound_select & 0x01 ) {7 K, L' d' L. e
                        output += vrc6.Process( 0 )*vol[5];7 ^4 q5 @4 ]9 b% H8 D
                        output += vrc6.Process( 1 )*vol[6];
1 @# P+ O7 Z( |* n" y  d: K                        output += vrc6.Process( 2 )*vol[7];% N. _2 x( g5 e; A# J
                }6 D- j' D) W0 w' @: H9 m5 h# ?; h( g
                if( exsound_select & 0x02 ) {
: R, L  `" J+ B; D                        output += vrc7.Process( 0 )*vol[8];
+ p7 N( p+ S4 z4 C6 Q% ]: c                }6 z- m$ u& q- l
                if( exsound_select & 0x04 ) {
" I) L+ C* \) {. x                        output += fds.Process( 0 )*vol[9];
% z/ N/ b5 S6 i2 V0 W- R                }) Q4 S6 ~5 B. n" F
                if( exsound_select & 0x08 ) {
+ Q! `5 ]& T+ C  k6 q4 t* R                        output += mmc5.Process( 0 )*vol[10];
  ~3 `5 S9 J' y7 t, A7 d  i                        output += mmc5.Process( 1 )*vol[11];- M; u3 H. ~, \
                        output += mmc5.Process( 2 )*vol[12];
9 u; K/ [$ i. Z- x3 P& i                }
4 f( `+ G& l9 V* I+ J                if( exsound_select & 0x10 ) {
1 {+ l1 S) B  ?; l. _/ P                        output += n106.Process( 0 )*vol[13];
  [2 v" O2 h2 A/ |, Y                        output += n106.Process( 1 )*vol[14];2 u! e4 m! b0 e4 N4 X
                        output += n106.Process( 2 )*vol[15];
) U5 w* q& k  r5 L" l" i& v                        output += n106.Process( 3 )*vol[16];
' c7 k; u5 s& d* |* y2 t                        output += n106.Process( 4 )*vol[17];4 v0 l' H# c* a  i
                        output += n106.Process( 5 )*vol[18];9 w) }" D0 x! J% x/ v% @$ a
                        output += n106.Process( 6 )*vol[19];* J7 p. t$ k) A3 f& ~2 y  R
                        output += n106.Process( 7 )*vol[20];
8 I% s* j3 ^* V0 o' r8 q                }) z" z! N9 u7 ~0 B/ G( }( M) g9 H
                if( exsound_select & 0x20 ) {; {) x* r9 o& {1 n$ K7 _3 U% |
                        fme7.Process( 3 );        // Envelope & Noise* e! Y# Q  M9 ~+ _* A1 R
                        output += fme7.Process( 0 )*vol[21];
, a- ~# ?, P- \3 b' O' ?  S                        output += fme7.Process( 1 )*vol[22];3 \, I8 T8 w% K# [/ G. m
                        output += fme7.Process( 2 )*vol[23];6 r3 J. V) a+ t& a
                }! h" e( p/ F% |
) p. d$ X7 L3 _2 k
                output >>= 8;9 O2 d) y0 S$ z& D
5 E! E! ?. T+ T3 _; [/ V
                if( nFilterType == 1 ) {
- `  ^( f- i+ d3 t' h0 ]                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)( j' N) v; n7 p8 w4 B3 B
                        output = (lowpass_filter[0]+output)/2;6 X: t) j7 ]+ Z* R" x! N- j
                        lowpass_filter[0] = output;
( m( C+ z5 s% _: s% r2 i                } else if( nFilterType == 2 ) {
) a1 q/ u) |3 D+ s; u                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)6 Z1 }2 C# F$ T- Q! q  l( O/ T8 v
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
3 G! q0 ]9 h; x( F0 v                        lowpass_filter[1] = lowpass_filter[0];
+ X, z5 f" J" e- z1 W0 M) v                        lowpass_filter[0] = output;% Y% ^1 R2 \1 c4 {, e
                } else if( nFilterType == 3 ) {
4 S8 C+ P9 t7 Y8 Q                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
& m% k3 F$ w" u                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) f/ ]$ S" ^* v1 k9 A. }
                        lowpass_filter[2] = lowpass_filter[1];
4 h% _, K2 P+ F4 h                        lowpass_filter[1] = lowpass_filter[0];/ Z' r: f, L, x) n7 l) P' X- A
                        lowpass_filter[0] = output;: ^( s0 v' T  M1 l" m  Q
                } else if( nFilterType == 4 ) {
/ S  d; D2 O# W7 M5 ~  K, H8 |                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& [" K4 n' W) _- P6 o                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
# A" P# v# f! q! @                        lowpass_filter[1] = lowpass_filter[0];1 v' r$ i$ d6 @4 q, ]# W
                        lowpass_filter[0] = output;/ C, Y: Q7 _9 [4 L
                }
" P) ^, b2 `& x; o7 @5 I! Q& `, _3 ?; T$ E' Q& M+ i& g
#if        0
1 L) w9 U* O3 g& Z$ f                // DC惉暘偺僇僢僩8 {) a$ D; U/ k+ ^/ y6 Q6 Z  F( ]$ k3 u
                {
% Y0 a7 W8 r% A2 ]- g# a; ^: H                static double ave = 0.0, max=0.0, min=0.0;% n5 W+ j  T2 z6 s5 g6 |
                double delta;& |( j& F" o6 b8 A% K& [: J1 y
                delta = (max-min)/32768.0;
- u5 A' i# j8 C% o, `. n                max -= delta;, F8 o4 d; q5 h& v. b2 i' \
                min += delta;
& a/ d6 V, O* R2 X# v' ~/ ^                if( output > max ) max = output;
3 N' ^1 g1 n+ z                if( output < min ) min = output;
% M, b% p+ Z$ o) R. D* b                ave -= ave/1024.0;
' n7 i2 q4 n2 X: T! M                ave += (max+min)/2048.0;0 z; T0 z( `( B- g
                output -= (INT)ave;$ ^/ O8 s, `7 f; ^* s
                }
+ n7 Z& d2 ?2 O#endif
: C0 {- k/ y& r" U1 t/ |#if        16 R7 l0 [- P% D, `$ P+ K. e. G/ ~
                // DC惉暘偺僇僢僩(HPF TEST)3 _# j- [/ n3 o
                {
2 s8 Z- X5 T# e8 M//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);2 t8 W! V9 }, `) B
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
- S/ M; P  B% x$ t* D                double        cutoff = cutofftemp/(double)Config.sound.nRate;' T' g7 H' X  _, S/ {$ {
                static        double        tmp = 0.0;
) p+ S, x" k4 y0 w5 Y                double        in, out;" n* y! s5 c4 ^4 n1 y. b& `  v1 G- y

% B5 Q8 p2 L, k4 U                in = (double)output;$ \! b8 j7 v, }1 G, ]5 A
                out = (in - tmp);
3 w* z0 W3 `% L7 W3 l                tmp = tmp + cutoff * out;
& [. H* o7 N/ a7 p+ I' B( n% M% O! ]0 E4 y& T: P
                output = (INT)out;0 Y# K1 U# Y" z1 h
                }$ I1 I) U5 U" L# @
#endif8 s& F; X) T: W9 G" b
#if        0; |1 p3 k7 ~% P8 f9 t$ @6 n9 V
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 u4 K' p. d$ C+ Y3 x* Y& e
                {5 l5 E3 \* P! Y/ G: P
                INT        diff = abs(output-last_data);5 Q: D. y/ k* c% y) ]
                if( diff > 0x4000 ) {
' M5 b& I3 B. V$ s. Y% g                        output /= 4;& Y( j5 d7 P( E
                } else 0 g) p9 Y. `  G' o$ w, T) c
                if( diff > 0x3000 ) {
8 [; G: I5 `) K' h* H1 o0 U$ g                        output /= 3;( s0 v: w1 a/ w8 Y' G
                } else
9 M; b; y/ w9 N" j                if( diff > 0x2000 ) {. u/ T3 I8 Z  H; J* U0 _; z3 t0 B. ?
                        output /= 2;
# M; L$ Y1 {7 _                }: a. n% G$ j) |, i
                last_data = output;
( k6 ~5 ^) R8 u: I; i* h6 K                }
+ m, y/ Z& n" w- @# m, m#endif
: ~# P  h' S. {" D* L$ L% `# |7 e" |! S                // Limit5 u: g6 f2 x6 C  k
                if( output > 0x7FFF ) {* }2 D8 s, Z5 d6 v- p3 w5 n% [+ F
                        output = 0x7FFF;2 t' v  ]$ B! U1 c) B
                } else if( output < -0x8000 ) {
' b' j/ q& {+ ?3 ~# x0 _/ R                        output = -0x8000;. T4 r+ A; {# {
                }" ^; K" r0 J  k

$ W6 C7 a+ n: _& @+ `1 K; P                if( nBits != 8 ) {, `% u6 {8 ^8 [; q2 x( Z: `
                        *(SHORT*)lpBuffer = (SHORT)output;
" I( `% m( E! ]- S                        lpBuffer += sizeof(SHORT);8 K- q3 n3 u. j) K8 h  @2 s# \
                } else {
$ `8 b8 K* T% p! l                        *lpBuffer++ = (output>>8)^0x80;1 G+ |) R: ^5 U# Y5 w* a' O
                }5 N% ?2 c# H' a- c: m

8 o4 d% I6 P- v' J8 C                if( nCcount < 0x0100 )$ {+ d$ o. ]/ H, r* Z' ]# U
                        pSoundBuf[nCcount++] = (SHORT)output;+ b4 Y- E/ M: N
$ ^4 w' D. N: c* k; y
//                elapsedtime += cycle_rate;2 F* ^- B/ P8 N; q+ x( J- C* ?" I0 ~
                elapsed_time += cycle_rate;
5 O6 Z* A' n5 r% M+ |( L        }
, j5 i/ P# E# l# R: {( A
9 s  @. n$ M" Q# i* b#if        1
3 e, d# @! O: m- W# @6 b        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {+ w" Y+ r$ T2 m# o) D5 v5 Y& b
                elapsed_time = nes->cpu->GetTotalCycles();6 ^+ v2 F1 g9 L0 x
        }6 j# T9 [8 w" u9 N
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
0 C2 X  g7 w- _                elapsed_time = nes->cpu->GetTotalCycles();1 f" i3 C: I1 |! h8 p. Y
        }
& \1 H. Z; J& h% q) {3 C- b#else; `% O" Z- \2 |3 y) G5 \' M) ]# V
        elapsed_time = nes->cpu->GetTotalCycles();
1 }+ A! `: @+ z0 H3 C#endif
/ J2 g' x. J+ ?8 O0 r+ h! ~. s% m}
/ a! H! }( n% g0 N. Z8 n- k. B  p  S0 v: K) _4 h
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡), {' ~. u6 X/ M* t$ E* Q
INT        APU::GetChannelFrequency( INT no )
+ i+ k- Y  b( C% Q{3 w# @  P2 c' s$ W
        if( !m_bMute[0] )
7 ]: w$ _( y# Q/ k                return        0;) h2 v, _5 n# V/ m% a

/ A. Q& Y9 K; W7 H+ ^! u        // Internal
0 \6 o. ?4 l0 }% S5 @% u        if( no < 5 ) {
) y% k/ R  q% E$ [' i                return        m_bMute[no+1]?internal.GetFreq( no ):0;
' @! h/ L2 V. u9 @, ^        }+ M, M2 w( \1 J' }1 k5 H& j
        // VRC6
& k, p8 ~4 i/ k        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
1 U2 l7 O5 N& U. w) Q$ J2 T+ ~9 }                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 @  `; J" {% M        }" L( D2 C( s* O: V4 n  M1 ~' l  G
        // FDS
: o7 a! `- U9 a5 z/ `& P        if( (exsound_select & 0x04) && no == 0x300 ) {
! E' W2 S  j9 k. F9 z3 t6 x                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 G7 U" R0 j- D! I2 E* V
        }
# s5 r' ^/ Q* I        // MMC5
7 T: f( O" {/ }        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {1 O$ M# D  W9 Q
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;% A: \) W' N8 X+ f2 L
        }
/ E: O% Z  p3 `. d6 z( y        // N106) {+ N! F+ k/ ^8 S5 `1 ~9 w
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
/ {. Y+ Z$ V! m) ?3 x7 N                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
; a& Z9 v2 m2 \- P+ P5 L) X! k1 C! t        }
5 U( P5 V1 c! u3 b' R$ k7 d3 N        // FME73 M8 x) s' {9 W- l! P
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {! t( t$ ~$ p, W, i' I
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;& ]6 V. P; N: j7 o% J' L$ T
        }- G0 y: f$ r; A* D5 c9 g* V
        // VRC7
, {9 [/ p, P% w5 D/ P/ H3 f        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {7 p$ U8 w5 Q  s% t0 _1 m" a
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
2 l6 o$ x, K, t" q, k! A        }  z$ ?/ m( _' R+ j1 S. a
        return        0;5 ^8 G1 z$ B! K, Y) d' [1 T: ~
}; J! U+ c1 ]( ]7 q

0 q- E$ t* p* t2 S+ L! w// State Save/Load
1 p. n: a6 x/ jvoid        APU::SaveState( LPBYTE p )
8 N" g9 v9 Z! }' h. w+ J{
! {# b7 m+ D9 Z" D#ifdef        _DEBUG
" _0 g/ q1 C, ]LPBYTE        pold = p;) ]. x3 m& c2 U* P. P5 v! P4 ~0 i
#endif
6 C% R0 S" A5 k2 B- F+ f$ n( W4 H
( _( j. p1 l  I% t' x6 t7 Y        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% {2 \/ g9 Y: d5 z: Z* r        QueueFlush();, i9 y6 f5 \6 W

' q, ^/ R) @5 \8 K. {7 I        internal.SaveState( p );2 K3 \! B7 {0 s& u+ \5 j2 ]$ g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# b. z) _; V# S
& e9 C  P" G6 k) \. c& {) B- w        // VRC6
7 ~: }- d5 c$ M( |" `& M        if( exsound_select & 0x01 ) {
% l! E( a4 W7 N2 d                vrc6.SaveState( p );
$ n; c3 I6 a- |) U                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 o& S& x1 D7 }
        }% Z7 I7 x& O8 [
        // VRC7 (not support)
7 X5 W: z/ I' S0 p8 V2 z- H        if( exsound_select & 0x02 ) {7 t+ h9 W9 _1 v
                vrc7.SaveState( p );
* @/ D2 O0 C+ f                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! X+ v# ~0 U* d6 O( t        }
3 i8 V& x- p1 i- y1 z  x. ^        // FDS
% J3 J& n: a9 x6 B: w        if( exsound_select & 0x04 ) {+ D) {5 v' ]1 S1 o" |$ F) @
                fds.SaveState( p );$ m; j, a$ K8 ]) W/ n  F& |
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ @/ i3 Z9 u8 Z$ R+ e        }+ q- \% t( j) M4 C4 X5 g
        // MMC5
/ Q2 {/ x* t" K6 q        if( exsound_select & 0x08 ) {+ o& i( ~* P8 _$ B
                mmc5.SaveState( p );
# @2 t$ o# x% Y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 c# N8 P4 r3 E) B9 O3 R4 X
        }
  H- L; g3 D# Z2 p3 l% v% f7 Q0 ?        // N106, `4 G9 L; d4 X5 a
        if( exsound_select & 0x10 ) {2 }& a, @' r3 f* \
                n106.SaveState( p );
2 L( W6 E1 f! V                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. v2 m" q# w) W8 b+ t* k. n        }% H) w* |7 J! x7 z* A5 i5 L
        // FME72 H8 e+ c1 s8 s* F6 `- R5 ]8 s* e5 U
        if( exsound_select & 0x20 ) {
0 Y$ Y: t  x) T( V- K/ t. e- S                fme7.SaveState( p );
0 a  F# O) G' C& a) A8 v                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% q$ h+ o8 y- U$ t2 k% }$ V        }) z( B$ N  f4 L' m; a, `8 i

+ b; G# {& `3 a3 V#ifdef        _DEBUG
. N" \! q5 K) f3 YDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
& n% S0 q3 a7 S$ Z% Q$ b#endif& c! u* G1 ^" v
}  P/ t1 K' y6 m8 F4 V/ j

! p* D. q( d" ~& L: Uvoid        APU::LoadState( LPBYTE p )" C: O$ j  D. G/ H6 C( l
{  ?5 ~4 {3 ^7 Q
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡* P' S! Y  B' ^& Y3 U
        QueueClear();
9 Y( [; m, X. a; D2 i5 p' W0 ~
7 Z% c4 C0 M4 \3 D' v, z        internal.LoadState( p );( q0 S' r- Z0 I# M4 @
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ D, P/ m: N# k, z: r+ H, ], Y
$ A0 ^  M7 g$ x- B7 b0 G8 a        // VRC6* a2 _. v  k5 S
        if( exsound_select & 0x01 ) {6 G" N" B, v- [9 o' m, e. v
                vrc6.LoadState( p );% A0 d# {; g+ E: K& H, g
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding- Q. }8 T6 U+ i2 N0 y
        }
8 R" L* y9 s# |  l        // VRC7 (not support): y" `  ~# c; u2 e  H$ W( M
        if( exsound_select & 0x02 ) {' I0 d3 w6 K( G' {" @0 K' D
                vrc7.LoadState( p );
# R+ Y' Z( n' f" x# ]* E                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% g, }/ p6 C8 E+ \5 H" Q
        }
; m' l! |$ h* F$ L        // FDS2 c  f& @7 `% {
        if( exsound_select & 0x04 ) {
$ N: x# u# a9 Y                fds.LoadState( p );. S9 V$ I5 U/ ^2 |/ o5 e" ~
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" p) G1 N& z% N$ `" V& U8 ]        }  b: x3 [2 ^6 I! @0 M
        // MMC5$ r! e3 i) e6 H& J, x
        if( exsound_select & 0x08 ) {
3 l- |* \% j2 k3 v# }, g                mmc5.LoadState( p );
; @" }$ r: I' J( s0 F% Z& Z                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
, e6 j$ Q2 u$ \0 m' R/ h; `) e        }3 x5 F* X; s. y* z8 @2 g7 b
        // N106
7 C2 p, F+ k7 T: ]5 ^: r- D        if( exsound_select & 0x10 ) {
2 I0 T" x7 K2 v# ~5 N                n106.LoadState( p );1 M9 l* ^4 J. x, s
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% @$ {& C6 ^( @* |" j# l
        }
7 n3 K3 Z! v0 E0 A. p6 e0 ^        // FME77 j$ ]5 [* b9 D# u& e) s) _) z
        if( exsound_select & 0x20 ) {
1 q: e) f0 l1 i6 m3 a) a8 n  ~7 l# m                fme7.LoadState( p );" a  o/ V( h( F# r  L
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding/ x& m. Y8 S  C9 k. S4 V* k
        }! U, Z, \8 \3 V8 O; K( k0 P+ a
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
  D0 I( V# X( m  n8 R6 \可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。$ k/ \4 \' v: J3 J5 i" f
感激不尽~~
" Y2 Z: X! H" ^
恩 我對模擬器不是很有研究,
' i! n- y" h8 I2 n! q3 w4 _雖然要了解源碼內容,可能不是很困難,
: E; ?7 U; J: z5 I2 n不過還是要花時間,個人目前蠻忙碌的。
4 q6 O, B0 z5 f* \# d
, U1 I9 w$ n) |* g0 I  M  }給你一個朋友的MSN,你可以跟他討論看看,2 h7 P& p# [+ o
他本身是程式設計師,也對FC模擬器很有興趣。. ~: y, W8 Q# E6 z* T$ s

  h- E5 n, |7 KMSN我就PM到你的信箱了。0 _/ g" B" j5 N: _
6 q. e7 Y$ k* j$ K; V
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
2 s3 I/ m, |& s呵…… 谢过团长大人~~

; U! N( r9 A- m, j0 r4 O
2 p' @) s9 j( G% n哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 c) t, X+ ^( Y. u- A
团长的朋友都是神,那团长就是神的boss。

+ L; x- |$ A. Y9 z- A哈 不敢當,我只是個平凡人,$ f1 C$ g  a8 c+ G
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙9 f# v% _8 c- W- S- f
ZYH" ?$ o  L& j& l$ a: d
QQ:4147343061 a$ ~+ h8 @- x% t
Mail:zyh-01@126.com3 l' i! Y. L5 s" E& P4 a$ h
5 _" x1 _. f7 }
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
% Q( o' ~" b/ a4 g* V5 j" W再次对团长大人和悠悠哥的无私帮助表示感谢~~

; B- }$ X- G$ _+ A# @2 u8 Z: N. M不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-5-2 12:46 , Processed in 1.082032 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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