EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; K. P7 d9 ^7 X楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 K5 j% w7 ?! G- u( X这里有相应的模拟器源码,就当送给大侠了~~
, H3 |2 ?7 M0 n8 ehttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 * G3 ]; Z9 v, n
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 J: i* g( K. P  ~楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~' A( t- `! b+ {6 b9 w! l
这里有相应的模拟器源码,就当送给大侠 ...

6 e6 b) z7 B8 w3 j+ O0 K; X" A聲音部分(Audoi Process Unit = APU):4 i4 P& Y1 B- G' n
.\NES\APU.cpp0 h. D9 b, v" i& v3 X6 i
.\NES\APU.h% L* c( V" [! @/ o2 J6 W% _. Z

5 x* J$ q! B- z1 p/ `2 F5 c: v3 L1 q. u5 h2 P! {
影像處理部份(Picture Processing Unit = PPU):1 d) u, \6 k7 A) I# T4 i: U# s. k
.\NES\PPU.cpp
* S$ u1 x* O0 G( S6 n" H& H$ P.\NES\PPU.h1 m+ c: x+ j7 Z: C; G" r5 M

; l1 w) _0 c7 E* f如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:' k. q$ e. F( y$ J3 t; ~: q
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) c* j& m1 p8 c1 `( |5 F' B//////////////////////////////////////////////////////////////////////////* b0 f5 i0 m3 h* g4 N- [
//                                                                      //, s3 b( ^! O4 s7 {
//      NES APU core                                                    //
3 t; r/ Y& e# o1 M//                                                           Norix      //* Q8 d7 T' {" S% N1 ]( ]
//                                               written     2002/06/27 //) B4 l. [. W/ L4 F2 D# J2 }8 d
//                                               last modify ----/--/-- //
2 {4 T4 \# L" l0 \( a+ X  W//////////////////////////////////////////////////////////////////////////
1 z& B& d3 K$ E& K( S0 G$ {#include "DebugOut.h"+ j) M( U1 T3 E( V
#include "App.h"* i) \* ]) f( F& D0 u' e9 X7 y/ ~/ k
#include "Config.h"
% o5 @1 Z8 K7 g7 {$ U5 w2 K) R5 a! P0 K. Q. x
#include "nes.h"# _' `. t% U4 S  U: v
#include "mmu.h"
; ^6 j  k# ?" I$ ^/ l  U#include "cpu.h". m9 i9 K, n6 B; G
#include "ppu.h"
; i4 f. ~, B" U: L2 y' k( H& u#include "rom.h"
! h4 o" m: h" d& \. M1 o( L#include "apu.h"
; `! n$ I" @# F0 a% s) g* c( K5 S/ J* X$ S5 g
// Volume adjust
, [9 {  y) f+ ]; O8 e- ^// Internal sounds2 ^' c- m) d/ d( G
#define        RECTANGLE_VOL        (0x0F0)
& z" ]2 D, y3 N7 i#define        TRIANGLE_VOL        (0x130)
5 \; ]* D9 N  C" s  ?#define        NOISE_VOL        (0x0C0)
0 x8 b  i: p/ x9 q#define        DPCM_VOL        (0x0F0)
2 V5 h, I3 U! H/ Y( \1 j9 }// Extra sounds5 `$ D' T5 c4 j3 L& ~
#define        VRC6_VOL        (0x0F0)+ p- s# ~8 w( K) R) \* T8 t
#define        VRC7_VOL        (0x130), ?& ]+ g4 G1 |$ a. p7 s( [
#define        FDS_VOL                (0x0F0)5 s$ A& y0 X5 J0 Z
#define        MMC5_VOL        (0x0F0)9 u, A! o3 \8 M. G' R
#define        N106_VOL        (0x088)
) b2 i  h7 K2 A5 G#define        FME7_VOL        (0x130)+ z$ b1 M; _% h1 T
4 f6 x' }& n5 b. L0 J+ O
APU::APU( NES* parent )* j/ F% ?1 x6 U0 L
{0 o! Q, A( w! l$ |) P& G! t9 L
        exsound_select = 0;4 @( c& T+ t! R( B9 b
' h2 R5 `0 T1 H( S& C" s7 z: h, W" b
        nes = parent;! n- w+ P& a" `; x2 p0 e5 y. O
        internal.SetParent( parent );2 Y8 m) m6 q2 q% }- G, k

) k' N* B- v2 A4 F6 b7 i/ x" F1 h$ }; V        last_data = last_diff = 0;1 z0 _; W* m( ~5 y3 V5 R! [
2 W8 w) a! w5 c/ g
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );$ i0 A* j! P! ^2 F0 P. y8 E" D
' T1 b: v4 s: b: t
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );" ^. Y# Y/ \- p, C+ @
        ZEROMEMORY( &queue, sizeof(queue) );
9 B7 T6 O, s" N! d3 V        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" n2 t5 E% r; y! d. b
% a$ R. n. ], O2 Q* g% d# q5 Z        for( INT i = 0; i < 16; i++ ) {
0 M( ]/ M: p/ N: P                m_bMute = TRUE;% c9 [! B) d: F9 s" K
        }
3 B- W. V* P* ?# Y8 L2 D}
  h- X( }5 l7 ^7 Y( n; C
0 U+ t0 z3 G5 }  O5 vAPU::~APU()" H0 Q6 r) |0 U' M1 b! F
{
  B. b/ W* F* X0 j}  G+ C! L* f: G' d1 w/ V$ U. w

2 C2 u) X' [1 M. zvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )* }  R9 l' B* O1 q5 E: o
{1 S( \0 q$ F; \% x5 g0 b
        queue.data[queue.wrptr].time = writetime;
9 M: p$ U: n+ B7 x& M2 U3 ?        queue.data[queue.wrptr].addr = addr;
: }: U& ]4 [# ~- z$ C$ o; [# H        queue.data[queue.wrptr].data = data;
( u: k! s9 \% W0 F, w        queue.wrptr++;; G4 T' G: q2 H; h
        queue.wrptr&=QUEUE_LENGTH-1;
( l* {- |7 P9 w; H/ G6 ?9 l        if( queue.wrptr == queue.rdptr ) {
) C5 [6 ]% u/ a- j                DEBUGOUT( "queue overflow.\n" );/ Z7 J; d: X, u& I7 m4 E3 q9 j6 L7 f
        }
( x( q; B' v! j2 l* k}" [: D( E/ W' C/ g" g6 v
- l4 o( s0 c6 e6 Y" l, W
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
; ~5 c- W; O: H- P! U" ]% N) m{
. R% N% k* p+ e: f2 O( }; T        if( queue.wrptr == queue.rdptr ) {
0 L+ n: I, e# ]8 u                return        FALSE;% M" `$ U6 H, r) C. }# i  \
        }
( U# R: p, U' n! j& }5 _. S        if( queue.data[queue.rdptr].time <= writetime ) {6 e# X" b4 l  ?1 Y% {. }7 P% _
                ret = queue.data[queue.rdptr];
4 a- e9 ]. x" R2 P3 O' r                queue.rdptr++;" w+ @& n7 f# Z  R7 R
                queue.rdptr&=QUEUE_LENGTH-1;
. s2 ^; U$ `% t4 A                return        TRUE;
! E/ b& [0 n: t  l" S* Q! x" t        }3 Z0 d7 K2 ]! F2 V6 J! Z0 m
        return        FALSE;0 \$ o% S9 k8 [% T# F6 i
}
0 u8 f. A) W0 W) I) K9 d
5 n4 b2 }8 c. `6 b- Fvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
- u( f6 K! B1 ]. C# N4 P& y{8 ?/ v5 r# F$ z6 D& i
        exqueue.data[exqueue.wrptr].time = writetime;$ l* O/ U& N! y8 n; k4 M
        exqueue.data[exqueue.wrptr].addr = addr;: C4 e+ Z- F: j4 j! N( L
        exqueue.data[exqueue.wrptr].data = data;3 S! J3 D9 c  q3 t9 b8 o) o* }
        exqueue.wrptr++;  p/ o" I1 r) N7 K/ d+ i' x
        exqueue.wrptr&=QUEUE_LENGTH-1;
% r, k7 F0 f+ q7 N        if( exqueue.wrptr == exqueue.rdptr ) {* W6 R1 @# Y+ g; O
                DEBUGOUT( "exqueue overflow.\n" );7 [6 f* M4 D& E* h
        }
: U8 H2 E0 ~9 l% N5 [( H}' A8 R7 W2 c- |* t7 `  }/ Q
! B6 i7 ?4 d9 ^6 c- g# d1 z8 }$ h
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! O! G9 N2 ?/ ?8 u8 t{/ K/ Y7 |7 y% u4 q2 f. Z6 z
        if( exqueue.wrptr == exqueue.rdptr ) {
& ~3 K2 @. ?* ]! z7 I) l) x                return        FALSE;
. {: f" i5 B# M        }
5 |6 u/ A; o6 M; o0 s        if( exqueue.data[exqueue.rdptr].time <= writetime ) {/ R& C2 R( n. Q0 d5 x1 \
                ret = exqueue.data[exqueue.rdptr];
) r8 \  G( [0 |0 ^) x                exqueue.rdptr++;  m2 j" D8 a- J
                exqueue.rdptr&=QUEUE_LENGTH-1;
1 y  v1 q' U6 M. G6 k' a                return        TRUE;$ Y  Q0 Y2 M- q4 K$ B( U  S1 U0 G
        }
. L/ H- b! B  }- {8 K        return        FALSE;; m( L2 X) S& z! n
}( D2 s" ]* n; R" n4 ^- L" ]
# w1 C; l2 P' T* A; D% a0 F& c6 h
void        APU::QueueClear()
+ L* N2 u% Y$ c4 j0 M/ u# m{
# j/ m% Z" Y% [! A7 c/ {+ G; D        ZEROMEMORY( &queue, sizeof(queue) );! C  \% p; |2 n) d
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 }0 `5 z, t5 C# F2 h5 z+ E}
' l; G$ |" D3 e$ V1 U
  Y7 J$ e/ E! `/ |- P# Yvoid        APU::QueueFlush()) M$ h: g) S% {) \: x& J* i, N. \
{+ `, T; @! `! n) ^
        while( queue.wrptr != queue.rdptr ) {+ T& q' ~5 F) s% u
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; x2 H4 N) E& m1 [
                queue.rdptr++;
2 _' K; m9 S# O: b7 b1 Y                queue.rdptr&=QUEUE_LENGTH-1;
' d' z$ S% t& W% o; B! J+ [, l        }" H+ v! I* Y' s
0 o( |- q, z8 d, u- w% Y0 Y
        while( exqueue.wrptr != exqueue.rdptr ) {
' c! u0 |/ }4 }' @                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
3 {: D% Q7 c- C: M9 Q                exqueue.rdptr++;0 S& w4 d2 k* S/ P
                exqueue.rdptr&=QUEUE_LENGTH-1;' U$ k. D4 n/ F( h6 f4 _( H0 [; P
        }" ^$ [9 n+ I: B$ F
}
) \+ e, \' o+ _4 s% V* V3 b
  W$ W9 M; c7 L7 Avoid        APU::SoundSetup()* y# |  M# F; |6 Z6 O  C
{1 _: O3 Q2 X. F# s' U4 y
        FLOAT        fClock = nes->nescfg->CpuClock;
' C' e- u4 Y! s+ y. P( F. p; m        INT        nRate = (INT)Config.sound.nRate;5 G8 d# ]( A  A& e
        internal.Setup( fClock, nRate );
# f. b7 P" c; l8 [- _        vrc6.Setup( fClock, nRate );
' K$ P& h% Q$ {$ S; Q2 h: T        vrc7.Setup( fClock, nRate );
0 R- H  X  @+ Z- P( P2 K* F6 h- r3 _  P        mmc5.Setup( fClock, nRate );9 I" X, R9 W) |: y( p9 P0 w
        fds.Setup ( fClock, nRate );5 ?" n, B# S$ Q8 q* t
        n106.Setup( fClock, nRate );0 v' }* @* M4 U
        fme7.Setup( fClock, nRate );
# s' n5 Y; A% C" D  ~  a5 n4 I}
* Y+ Y: u5 h5 z! u& a7 u: }5 a' f0 H6 L/ e7 I9 ^
void        APU::Reset()) `) V9 T% i! L$ _6 b
{, H$ X- H6 B' |" m6 f% t% S: q1 @
        ZEROMEMORY( &queue, sizeof(queue) );
8 f% X9 w  V" Z" V# w9 H) D$ r        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; a$ J8 P% z& P5 T, O; d6 D
; J  y1 A+ r' j, G; A        elapsed_time = 0;
* @- B: `5 i/ e5 p7 V. z  e4 \9 _# i7 i/ w3 f
        FLOAT        fClock = nes->nescfg->CpuClock;
" d+ S% r% i+ u/ c' w5 f# M        INT        nRate = (INT)Config.sound.nRate;6 C, B3 e# `1 d0 I
        internal.Reset( fClock, nRate );
7 h5 E: V7 X2 D6 Z        vrc6.Reset( fClock, nRate );
& C& X! x" J, a( N# g# x( a        vrc7.Reset( fClock, nRate );3 }' k* e, _: \3 e* ~5 T0 w
        mmc5.Reset( fClock, nRate );
" S6 T0 h$ D4 v: e% {8 i$ }5 }  @        fds.Reset ( fClock, nRate );
1 V( I; N6 o5 j        n106.Reset( fClock, nRate );  ~/ p2 C( V. E; w. F- s1 k
        fme7.Reset( fClock, nRate );: _8 q% I1 |8 P5 B9 t+ x' ^) `2 V
8 R6 b" y1 ^# O+ P. Q9 e! H. H
        SoundSetup();
3 `2 N; Z+ ^* g0 q  W}
1 }: K$ F. O; q3 Y5 A* j
& ^6 y6 w8 W( n3 G: H. N6 Evoid        APU::SelectExSound( BYTE data )* K  K* P9 |' j$ z2 v
{. R) [! P$ V" X" w" o
        exsound_select = data;
/ T1 r. B! _! [# Y1 m% x$ p$ L/ {}
# K6 T9 i& b: F- e7 l& |+ B: _# d3 J! o$ H0 j3 t
BYTE        APU::Read( WORD addr )
( K. w# R! A7 X+ C' u; C! g{
' p! X' l. V6 O        return        internal.SyncRead( addr );
- @8 ]+ o6 f7 x. q& M0 x}" h+ [" `2 l- e! U9 b8 a2 G

: N+ R, ~* L: s8 Uvoid        APU::Write( WORD addr, BYTE data )
# ^! l( N) C* k* R9 R7 e# w{
6 p1 l- [! z; e5 D" V: M  c        // $4018偼VirtuaNES屌桳億乕僩
( t9 {9 _& S( @        if( addr >= 0x4000 && addr <= 0x401F ) {; q, @+ i& }6 S5 r' U  e  i4 C+ k; V
                internal.SyncWrite( addr, data );
5 D/ E0 {! `* I( E0 B                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
1 \6 W0 q) l- H* o        }7 ?' i+ c2 }: y1 B. c7 a+ f3 X
}  x7 G3 x- M4 u' d

, _# k0 O# ^/ E3 |1 BBYTE        APU::ExRead( WORD addr )
( p+ a4 A7 D' b& F: I% ^& }, U{! z- \/ r2 `" m
BYTE        data = 0;
; t9 t* `' l  r! v8 W" ?2 V, H( N4 L6 p; [8 r
        if( exsound_select & 0x10 ) {9 I: U  D9 \/ D& ~- ]& |
                if( addr == 0x4800 ) {
' y: A' Y# P" ]8 [, R; u                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );9 ^1 O/ O% u3 ~9 ?, W: E
                }) S4 Y; s6 D* _% k5 P& V7 n
        }3 O9 s1 v5 A' T( r. u* H% a8 p* F
        if( exsound_select & 0x04 ) {1 G6 S, `' y- r
                if( addr >= 0x4040 && addr < 0x4100 ) {
0 v7 x4 N/ W* J2 _1 f/ j+ r                        data = fds.SyncRead( addr );/ G# h3 n' a' [4 S4 e0 f, B
                }
$ v$ r0 f6 i' D2 \' E1 m/ F- M        }
* J& Z% P( y6 ~% `3 {        if( exsound_select & 0x08 ) {
9 e8 ~9 {, |4 Y. I# t; k* F( \. g                if( addr >= 0x5000 && addr <= 0x5015 ) {
, Y( w, r: p' A- e- X# u$ u3 f                        data = mmc5.SyncRead( addr );
- o3 a) P- Q: w1 p" l                }1 |- M0 e% J8 m/ y0 {
        }5 {9 L# D) L! R0 `# g% |. w$ C

, X* |; ?0 X& G$ M) O        return        data;
) ~0 l1 ^: S3 K" ~}& _* |$ {8 b* s. ^: m, c
$ \2 f9 h7 i$ a  o9 D
void        APU::ExWrite( WORD addr, BYTE data )
9 t1 O; P9 R! e+ y$ \" |% }( _{8 r7 y1 k; d  e; p( u
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );5 x0 R0 }! B+ b* ?4 c0 {% S, E, Q

# ?. P  I. h* [( B+ M        if( exsound_select & 0x04 ) {/ N# t& X: d! B) u2 r& N
                if( addr >= 0x4040 && addr < 0x4100 ) {" }$ W, B) i8 R; T8 k, X1 v2 M: n
                        fds.SyncWrite( addr, data );- W5 _) o( \" \. o' O2 P- [/ T
                }
! U# C) H$ w0 B8 @1 ]* _        }: k' a, Y1 {2 C! m/ I
1 ?) t# R, Q5 e# m
        if( exsound_select & 0x08 ) {+ o  Z% X' @. c6 v9 X, s. k- ^
                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 n# q1 V& T3 p7 n' L                        mmc5.SyncWrite( addr, data );
! q, B6 @. O% m- w                }
  u) L, [2 Z. Q% n* i        }
2 `3 J8 f" l, k5 I}  j& Z, B4 p) O; w* `$ t

( j/ F# [( x/ V# ~* ~$ }( kvoid        APU::Sync()( b8 z/ k+ v* U' Y( o/ s
{0 Y& q( X% S" E; W7 B) g
}! R1 L  T! q/ }+ p  N

9 g/ @. u# I' W8 Q) H) y- gvoid        APU::SyncDPCM( INT cycles )
( x1 |, l" O! M# D0 [2 e) @6 [{
5 {: t; D5 h- N; ~+ I/ V1 n        internal.Sync( cycles );
; v) G4 T7 f3 r: \9 [, s7 K3 g! D
        if( exsound_select & 0x04 ) {
' u9 h, g* d% o                fds.Sync( cycles );
0 q$ f9 h0 M2 J$ [  m" {" g# C        }
1 o6 R% y0 G  N0 `7 u  ?3 v" j        if( exsound_select & 0x08 ) {7 U8 U7 T7 w$ e- \% r; k1 i& |
                mmc5.Sync( cycles );
9 b7 r6 P+ m$ l8 P        }
8 \/ h9 m+ B$ y}6 ^$ I1 |. w2 Z1 e# P* O7 ?0 M
! @7 r" c+ `( M( }$ o2 M: b( n% E
void        APU::WriteProcess( WORD addr, BYTE data )( S* [4 g" [  f/ [7 _
{
: p; n% I( e5 h1 O/ C        // $4018偼VirtuaNES屌桳億乕僩
1 h6 t. W0 e9 T5 I; ~        if( addr >= 0x4000 && addr <= 0x401F ) {
4 Q: G: g: g( z+ y" e                internal.Write( addr, data );
' z; K* i: I0 F- ?0 e0 T" z        }/ P% r0 f- w. ?+ ]' \  a! Q, ?
}
2 @3 K6 S, u) j$ }/ e* |; O3 Q/ ~  h0 M) {; F' @) x: v& d
void        APU::WriteExProcess( WORD addr, BYTE data )
% E; _3 G2 Y9 ^7 p$ E! _{3 u! R1 \7 ?7 Q) A; ]5 s+ Y, }7 h2 U
        if( exsound_select & 0x01 ) {
/ O* \; A4 M5 w9 P0 T7 A                vrc6.Write( addr, data );; q: X- v; m  R7 ]9 j# v6 |( u5 J& O
        }
& O# j4 B" U+ J9 j) y7 H) r' V        if( exsound_select & 0x02 ) {
% S# s0 E; k6 L" W$ x                vrc7.Write( addr, data );5 Y) z  t7 {! D1 W& K
        }
* E1 B; [9 \: @0 L( G. L2 `        if( exsound_select & 0x04 ) {
- y2 Q  D- T6 \) W) {- a) d, {                fds.Write( addr, data );
- g; A2 n7 r/ {" }" Q1 z        }7 t5 s& ^' i6 {, l& n
        if( exsound_select & 0x08 ) {. Z, Q, v: @7 S# K5 N$ X+ z
                mmc5.Write( addr, data );
8 v, X* a0 ?- L5 y        }' i% N1 V& i7 d; p$ J
        if( exsound_select & 0x10 ) {+ \. t& [7 G9 r
                if( addr == 0x0000 ) {/ q8 X& _( T1 `: K& o1 O
                        BYTE        dummy = n106.Read( addr );
: m/ X$ I" H5 l) M% g                } else {5 O6 z! C% t: K. Q, e. M5 e$ k
                        n106.Write( addr, data );- S0 ]7 b0 C2 W/ |
                }
* `) W* X# Q0 p. y: j  Z/ Z        }. \, D; C: C' V
        if( exsound_select & 0x20 ) {+ f8 `. q* o8 F2 s
                fme7.Write( addr, data );$ W$ G  e9 H) }. A) `/ {' a* [- _
        }
; c2 w, L4 `- f& N+ A}$ C1 j; ^2 z' O8 \3 d6 j
& M* m6 k5 R8 C4 n+ M
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
* L$ u0 P& I2 Z( Y; F; @2 t9 N{; d% d- x: d" ~: _
INT        nBits = Config.sound.nBits;& {( G& K- G' y# i" k
DWORD        dwLength = dwSize / (nBits/8);
8 R3 n- P  |9 Z" h  }INT        output;
( G% C+ ]! T: SQUEUEDATA q;
7 z& w3 l* Q2 N% u9 v! f! cDWORD        writetime;6 i  k" _% I6 C8 `

( ]3 M0 D$ _& ?* nLPSHORT        pSoundBuf = m_SoundBuffer;- F+ J9 A6 f7 f1 |! {
INT        nCcount = 0;6 r: N& M0 ^& O' t: {, s2 v! [

; c( k) h- {$ l1 P- g2 BINT        nFilterType = Config.sound.nFilterType;
0 n. ]# u! |' b0 _1 }0 C- c" d! \1 F: \4 Z, L: I
        if( !Config.sound.bEnable ) {
# \1 m. g/ [. r; w4 c. s                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
) t5 U5 D! y$ U) a. k+ Q; x                return;7 X' I2 ]7 m8 A, Z
        }
/ f: }% O) f; z, l
3 B( l2 f& S5 h' s  G        // Volume setup
0 I. d, j! ^$ [/ i5 v' z2 E        //  0:Master
+ s0 g( [1 L. [        //  1:Rectangle 1
2 h/ |: ]4 J: P4 F        //  2:Rectangle 2: K1 h& l! p. b2 _
        //  3:Triangle* ^# o+ u) U& c5 w
        //  4:Noise
  T/ K/ ~. r1 C        //  5:DPCM
, x7 x$ `4 Y1 d8 W# B        //  6:VRC6; @# i$ u' o. ?0 R# A9 E
        //  7:VRC7
: |% Z+ Q  h9 t" |- Q        //  8:FDS
" f5 _6 a4 F  K        //  9:MMC5, k- \$ y  P0 _! e) N  s
        // 10:N106, M0 q; F9 s; \
        // 11:FME7! u! w/ a% [. `
        INT        vol[24];) _% {) r: z1 [2 i2 R
        BOOL*        bMute = m_bMute;
8 t: I% m+ H. a# }2 I- |        SHORT*        nVolume = Config.sound.nVolume;3 Y! o' `5 Y2 N  C6 K! }

+ `3 x# x( A! Y        INT        nMasterVolume = bMute[0]?nVolume[0]:0;7 Y4 v' J4 U7 y+ f" |
6 G' o- q4 H4 [" x6 r; K% G
        // Internal
* E0 o. T' o' z. e8 j        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 v, m, m/ J: `  _
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, L: J: F: W2 J' {, h        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;7 d5 K4 j$ }5 f" a* y
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;1 [5 f, M' d& c. b0 w6 B0 Q* \
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
- B* X, R; N0 F1 k* Z5 d8 t" u+ _1 k0 `: G5 N7 i
        // VRC6
$ e9 z3 ^4 f4 n        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, A# }6 `2 P1 {- f8 [
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ M2 J% ^1 K& f0 ]' v2 W# {- S
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 W+ A" j3 ~2 D* W; u) S

& W: D9 l0 G. L* R7 H/ @        // VRC7
9 p+ p- Y0 |; W% B        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- E9 z4 b8 D. i/ z1 L! \- V  c6 t; T% l5 C; Q& Y* ^5 C
        // FDS  k) y* F1 l3 b
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
  ^  A( W+ q0 l: D! `  P  i
4 t: g' c5 j; @) W        // MMC5# d& \3 q5 t% f
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 Q2 R% u# Q0 o        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ M' c0 ~' X( Z5 Q, ^7 r  o6 Z9 _
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. M1 m3 }4 n9 g/ g4 Y+ y

, E% D# q& g9 l( a3 S( f6 {1 A        // N106
' i% w% c1 V1 N+ m  W        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% Y) C! r# d/ B8 @
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ s4 A5 N* c" S5 b. P        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! Y8 c! c! P# k; p        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* @$ d) U0 G1 b( m: O. C/ e        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; l) H4 _/ T( B" t0 h5 c$ G
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) S" ~% c  `; D% r" Y5 V
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 }3 a3 m% C3 T6 _/ O
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 E  i3 @9 ?: k/ d1 v6 p  ?" |2 T) K$ G( f
        // FME7( H& A& I* O  ]
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ k) L8 Y# z) z+ [0 V
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 ^0 z" B! B& x
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ a* v/ X( y: f/ |* ]# f* W, i3 O3 G  E% P% z( g
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
" Z; S; S: D# V7 R        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
9 ?( C: ]3 t" G+ `
0 A0 m3 Q% a8 J; o# h5 i        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟7 U2 ?+ z" X7 b9 C
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {) u% {% ?7 Q# k. ^' D" r9 H9 ]
                QueueFlush();
7 x6 ~, [: Y" e2 L        }8 U% g2 V4 Y. H9 V& G8 C
# V5 c, _2 k+ h; \
        while( dwLength-- ) {* l) y- H4 `/ o" g- |; u) d8 a
                writetime = (DWORD)elapsed_time;
/ P7 J7 C, b6 ^7 v$ w  i* ^( b( G7 i% `8 e+ V) E9 b- b! R
                while( GetQueue( writetime, q ) ) {% W; k4 u3 h9 C" P
                        WriteProcess( q.addr, q.data );/ [* l4 h  o# Q+ Z6 \  k5 S' c! o
                }
7 k* v7 ~& {, n4 i1 Q3 H" W6 }- M7 b- b# k( J8 H' E0 J* t( ]
                while( GetExQueue( writetime, q ) ) {6 w: ^. d1 H% r
                        WriteExProcess( q.addr, q.data );
( K, [$ S* J$ P4 Y% M                }
: r0 c9 H" r1 `0 A* n, h( e: C1 c
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
3 F( B% g4 U- P0 Y8 l                output = 0;
' o. B' Z- r% s- Y! P% r0 V! U0 K                output += internal.Process( 0 )*vol[0];
) K  B/ E+ ^; n/ v# a; w0 e                output += internal.Process( 1 )*vol[1];
- n6 y2 m* ~! v" q+ Y  r* S6 n# A* u                output += internal.Process( 2 )*vol[2];
- t: U2 r& p0 V, h- p+ d                output += internal.Process( 3 )*vol[3];
, m# H+ M* O$ m7 ]0 c$ B; ?  C  u                output += internal.Process( 4 )*vol[4];
4 _& S* ]/ h/ Q; P2 i2 ]1 _! x! q3 |# I) K7 N7 d) \. w0 I
                if( exsound_select & 0x01 ) {; K! J; P0 Y! J' h
                        output += vrc6.Process( 0 )*vol[5];
0 @! p- }+ z5 D5 t+ Y" B                        output += vrc6.Process( 1 )*vol[6];8 N6 i1 l9 P/ o3 L
                        output += vrc6.Process( 2 )*vol[7];7 J$ w! C2 J' ^7 f
                }8 S. Y! O7 l/ I) B5 O
                if( exsound_select & 0x02 ) {
1 A8 w8 J0 e/ Y; r7 U* d                        output += vrc7.Process( 0 )*vol[8];
4 [1 q$ d: f. l, @, \% T* I                }
  Y% I( C7 X; f- p9 T3 [; s7 h# k% d                if( exsound_select & 0x04 ) {
4 J* a3 V$ v! R6 a/ i6 u: \                        output += fds.Process( 0 )*vol[9];6 e; h3 n0 v/ D7 C3 `, D
                }
+ ]9 Y; P0 O- g) J                if( exsound_select & 0x08 ) {& |' G; R# ]2 o7 A4 P
                        output += mmc5.Process( 0 )*vol[10];
2 f2 P2 ]/ t- i0 F4 O! ~/ \                        output += mmc5.Process( 1 )*vol[11];
( j: R; v3 z7 r& k                        output += mmc5.Process( 2 )*vol[12];
& T1 E. `# Y( i% ~' V$ u( U* L                }
, |  [. {& n: j! Q2 c                if( exsound_select & 0x10 ) {
3 j3 j$ u6 B0 h: V                        output += n106.Process( 0 )*vol[13];2 ^: N% A4 E0 V7 p
                        output += n106.Process( 1 )*vol[14];
# n; M$ d, `) _; z- `, @                        output += n106.Process( 2 )*vol[15];3 U& [: ^9 w- j- {. I
                        output += n106.Process( 3 )*vol[16];
' a% C2 m% E% }, Z# T                        output += n106.Process( 4 )*vol[17];& R9 u6 G- P2 M3 H' j% Z
                        output += n106.Process( 5 )*vol[18];
" Y1 z1 Y( h$ E4 G# [                        output += n106.Process( 6 )*vol[19];8 ?, ]4 H5 u; q( f2 s$ C/ F
                        output += n106.Process( 7 )*vol[20];3 N5 P, y' T" u6 U
                }) C* q& u3 u7 H$ X! V
                if( exsound_select & 0x20 ) {/ x0 m) w7 T9 {! u$ Y
                        fme7.Process( 3 );        // Envelope & Noise
9 @) a: A2 ]  k3 ~                        output += fme7.Process( 0 )*vol[21];
/ R) t- @$ K/ j$ H3 D+ X, }. `1 \: \                        output += fme7.Process( 1 )*vol[22];
6 i: c0 _2 h2 I                        output += fme7.Process( 2 )*vol[23];( a, N6 A9 d' V4 i" Q$ D  l
                }1 o: v& i3 f4 o7 I

" u0 U5 `" d+ z1 O  s; y/ A                output >>= 8;5 F6 z8 m' M5 X

1 S6 ]2 X1 B* [6 m* p                if( nFilterType == 1 ) {
" ]% d: g) m( ^+ R# E                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
  m( J* _3 _. d, G( O: l, w                        output = (lowpass_filter[0]+output)/2;
' e1 f" p: M* x, H/ H( z                        lowpass_filter[0] = output;
3 g' v' v4 c9 H# b                } else if( nFilterType == 2 ) {
0 e% `7 c2 m# I% p# @4 A                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
$ F* b1 p+ c( r( F                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;, \  N& H$ @- ~
                        lowpass_filter[1] = lowpass_filter[0];, s- e5 h0 b7 l1 [1 P* ~
                        lowpass_filter[0] = output;8 v% [( m* A' B' J/ X+ B& [
                } else if( nFilterType == 3 ) {1 f$ c* e  K+ K9 X5 }
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 X/ B; ~# i+ V+ }2 M7 [                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;2 q# v  [9 [% D5 \; N7 l
                        lowpass_filter[2] = lowpass_filter[1];6 p7 H$ I1 t, \! q; y+ u
                        lowpass_filter[1] = lowpass_filter[0];3 L" d9 z4 _3 X  _% t
                        lowpass_filter[0] = output;
' \& V  C( z% D! k4 N5 a                } else if( nFilterType == 4 ) {
- f8 f, h/ X& B; |" V. B                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)4 F1 r8 R) @8 O: t0 O+ N* ?: ^+ e* m/ `
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;/ Z0 p& W; e+ Y' Y$ m
                        lowpass_filter[1] = lowpass_filter[0];8 `; X* h5 G4 A9 J
                        lowpass_filter[0] = output;+ N, s5 I  c1 d- J. d) H
                }0 W% ~8 [; b, @

# S1 Y$ s8 O! A' m( O5 O5 P, a#if        0( t3 [; p+ c; W$ C
                // DC惉暘偺僇僢僩
0 J  Y+ O: \* K3 Z7 P, e1 s: J                {/ W/ O7 m5 a$ s( p( F, ~& o, c( ?
                static double ave = 0.0, max=0.0, min=0.0;
6 q3 y' z/ P+ W- l5 Z+ C8 F" b2 k9 Z                double delta;
$ y% U- Y2 J8 J0 L6 k8 i                delta = (max-min)/32768.0;
1 Y; N( t4 K! h8 z& H  F                max -= delta;
* V$ v: v3 p5 D- _6 z( Q                min += delta;( C4 m: {* Y) x- d
                if( output > max ) max = output;
  x/ `3 g/ J4 h, T: |                if( output < min ) min = output;
* f% i1 u3 q$ Y! N3 ^' y+ y                ave -= ave/1024.0;/ _/ b: N' d7 B3 i& C- g+ W# L
                ave += (max+min)/2048.0;
% q' x$ Z1 N+ g; \                output -= (INT)ave;
3 i6 ~+ K! |6 N" T1 N7 r2 J                }
* S& [# M" I9 D#endif
) C5 L1 {0 |- N, H" \& P, c#if        1$ p/ r3 K0 q0 d' w) e% r$ M( q
                // DC惉暘偺僇僢僩(HPF TEST)% p/ ~0 n2 A/ A( ~0 J; h
                {
" q% t( {$ i* V8 S1 B/ s//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
' R) \+ u7 @: I# K. P3 h" s: S                static        double        cutofftemp = (2.0*3.141592653579*40.0);4 W$ _9 d/ w4 S5 R1 ?0 F: x* l3 y8 M
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
& L, l( w8 A& _3 _, E                static        double        tmp = 0.0;: q8 R  l! R, \2 L; Y3 z
                double        in, out;
0 w8 v6 A" o& x/ c" K- C7 D
" I3 S4 _& q" i8 P8 j. N& ~                in = (double)output;
7 t& ~5 y; U2 ^$ T! Q  @( t                out = (in - tmp);
- [6 P# t% v8 f3 ~! j7 ~                tmp = tmp + cutoff * out;
3 Z5 b' n. U' _% d$ Q
4 a5 b3 }) ^. i3 g, F, O                output = (INT)out;
' q% m5 R* F! C- L/ T# l/ k                }
5 G& W3 X4 b8 I#endif
' c/ m, M; x9 Z0 j#if        0
  I% v7 U: X1 x$ l+ Y% m                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)" r. j4 G6 C; D$ q3 N6 X
                {
0 w' S5 N' t5 n" d- N                INT        diff = abs(output-last_data);
7 W/ V2 T; l, z9 O6 s( Z                if( diff > 0x4000 ) {  c2 M' {( F& Q2 Z
                        output /= 4;: n% F. W3 U5 F. A4 u' D9 M: P& |
                } else 2 l4 O" Y) g6 ^
                if( diff > 0x3000 ) {3 a6 A, f1 R0 F
                        output /= 3;
. ~9 A6 H, K: I( d8 k: F. C                } else
3 G# \$ G5 G1 T7 E/ r; H                if( diff > 0x2000 ) {8 O( o# e, x, o" S
                        output /= 2;
, p0 C$ u! \. _* R. t; [                }; U8 M  J( N) `* f) l
                last_data = output;; {, y& I; W+ x: e. O
                }$ M0 y" K; G2 S
#endif
/ d6 ]8 }9 q* C# {8 M5 j                // Limit
$ @1 E9 U/ c$ _' ~) @! g                if( output > 0x7FFF ) {
* h4 ^7 c4 x7 N! c1 ^' w                        output = 0x7FFF;0 G( I. p# W8 p1 C
                } else if( output < -0x8000 ) {
& t: @4 L( a' m4 T/ y+ f                        output = -0x8000;
5 u: {  {/ ]4 K, W( L4 r6 z                }
+ p- E9 `4 P, ]" a, U# T# n9 u
& Q5 S9 i- s) ?. @) ]                if( nBits != 8 ) {5 }. q# C" W; c; G
                        *(SHORT*)lpBuffer = (SHORT)output;
- L+ N" |& y+ j. j9 X                        lpBuffer += sizeof(SHORT);
, W7 ~; I8 H- ?                } else {6 T& w( u& k9 a# U+ W
                        *lpBuffer++ = (output>>8)^0x80;
  P6 Y( u# H  ^7 y$ n, e1 s                }% V0 z7 {9 p1 H; G
  Y9 X& t0 h1 B+ J( Y0 \
                if( nCcount < 0x0100 )# ~7 O) u* S) k3 a
                        pSoundBuf[nCcount++] = (SHORT)output;# o4 `. w+ y( d& `( Y
8 X- U$ l) s7 h8 I
//                elapsedtime += cycle_rate;
$ t) B2 T( h  ?) V( V                elapsed_time += cycle_rate;
: S$ h: _9 _  W! r* G        }
% ^5 ?/ c# g) V/ q- f2 C; e5 w
$ B3 A7 a. L6 S! G. P  E6 o. H#if        19 ]: i2 f7 B  U" V/ ~0 N0 g. T. R
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {  `3 [7 B/ F/ X/ G. ]8 b
                elapsed_time = nes->cpu->GetTotalCycles();
! {' r& a& ?3 j( P8 e        }1 n; e2 G/ ?5 i. m
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
4 i" w6 Y. M" |" W$ v: \                elapsed_time = nes->cpu->GetTotalCycles();
) n* ]3 ]. Q' s5 x5 t0 M        }1 h) E6 X& r6 b$ A
#else! J2 R* F0 a1 v- |* p* G0 y
        elapsed_time = nes->cpu->GetTotalCycles();
4 a. M8 X/ J: a, d- r! ?# T#endif
5 h. O: r6 C. l' v* M- C, I; i}
4 X3 b, m& n% K) @3 g
& r) y% j6 p3 _2 t// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)! ^7 v% Z7 G, p3 k' O- y! I2 O
INT        APU::GetChannelFrequency( INT no )
# c) l. Z% U4 O( D5 r{
* n; J  K% |( \1 {5 F        if( !m_bMute[0] )
+ A1 r1 f3 C( i2 E) W                return        0;
  C' ~$ |, E5 Z! L' t' A
6 R! [* H0 A! \- g& x4 U) C8 n        // Internal2 @; H0 W& R9 d7 k2 \
        if( no < 5 ) {9 j/ J  \6 F% L
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
, f# C0 A# }, |4 l2 e        }
6 F5 K- I9 c/ x        // VRC6
6 i  K5 ?7 T4 c0 F% A8 k. N- D6 a        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {2 j3 W# `4 i- o  T6 U8 F& `
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
8 V1 z$ K/ O" E3 ?* N( F+ a& _/ s        }
% I5 ]# t' S  v( S        // FDS. N7 d! ~+ N, V4 W9 K
        if( (exsound_select & 0x04) && no == 0x300 ) {( T- ~* P- u7 J8 R7 ~, }5 R
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% P% |/ R9 G4 r$ k. H- ~6 x) H        }
0 E* V. e- e5 [0 B        // MMC50 {) |0 J7 P$ c0 A+ J1 I6 o2 e
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
; N  o& t3 ]  G/ [                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ |7 t$ T, {6 Z* @1 q; ?
        }4 ?) X/ M- C0 Z0 k% m2 A; [# g; x
        // N106
2 p5 O7 E/ v* Q; y: d% C. \        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {) H% s8 Z7 i9 y* ^9 O: ^( P, o
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;8 z: y6 g) H' Q! |: h0 _
        }. x1 K% n2 D- Q0 {* c5 f' g, F
        // FME7. [& g5 |+ P. N" K6 Y# R3 z7 B* g/ D
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {6 e; X) V1 A. a2 @
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* L: \9 N3 h6 B3 y& M+ e        }
) O8 ^$ ?5 e- Q5 r: d6 k: O& Q        // VRC7
% n' E! p  s/ b+ m: b' o- Q; L) k        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {, t( e+ f- L  V  u5 U" Z
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;6 A, S/ Z, y' K2 C+ n& T5 d' Z; A
        }
$ L- q7 W( \! [6 b        return        0;( `0 q& |; \: L8 z
}4 o& f2 E  ?0 h

0 j- \0 S5 L) Q" J8 a) o- n1 ?// State Save/Load# j2 [  W) e' W6 z) c
void        APU::SaveState( LPBYTE p )% Q* b! v- @" m0 M- A
{
& K6 S# P( i3 }#ifdef        _DEBUG1 a. S3 |. |& t0 N3 k
LPBYTE        pold = p;
9 n1 q+ G4 }7 s; X7 |3 z# f/ z! E#endif
' e) E2 t* W- p+ t' h: b/ I
. J6 q* h. I. v# [- p6 b; P        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
# b. q# l4 Y$ h+ [# e1 @" a/ ^        QueueFlush();7 D# `# f3 D6 e  D# {1 J. G
' @4 b$ h/ V6 j+ S
        internal.SaveState( p );
6 g3 T' T" a2 T, P+ L! L  S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 t: h# T! Y- S5 F- o, V

. l/ M( a7 V: U# I7 @: P4 g; f" l2 n        // VRC6
  F7 s; i) v& n' `& z  v* P        if( exsound_select & 0x01 ) {. t4 V# g& M6 o# e' ]  @/ @
                vrc6.SaveState( p );8 ]7 X. o" n+ n8 R1 j
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
# K8 j- J6 D: x& ~+ p2 b  b5 c        }& N* y) G+ M. M1 o. N0 E
        // VRC7 (not support)
# S, j2 R8 y, J        if( exsound_select & 0x02 ) {
6 S! h% @  @! |! _# T                vrc7.SaveState( p );9 ]! I) w) @' z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( x# ^  Z; x# a8 }3 f( @7 V2 ~) }
        }
2 }* {- N; R- S' g' `; p' s1 Z        // FDS$ m; V& _9 G8 y* y6 x8 C% }2 R
        if( exsound_select & 0x04 ) {$ E/ }3 S2 }+ h3 T: W5 q
                fds.SaveState( p );2 ?3 {6 b2 w' R' I' Y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) M! B" E: Z  P' N        }5 U1 ~- ]) I' A1 _" b: K. o
        // MMC5
/ c6 M+ `2 S1 M% [! o7 g        if( exsound_select & 0x08 ) {& m, s$ I1 U+ p% Z
                mmc5.SaveState( p );
3 ?9 h( r& E) k& N# p# H( H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 s0 l2 E; a- V8 \3 ~$ q        }& G/ G5 d0 B( s9 x2 \; n& s
        // N1068 c. E% F$ d8 Q1 ~- l* S; x+ u
        if( exsound_select & 0x10 ) {
; o4 m7 J& Y. }) o  k) K- V2 b6 X6 h                n106.SaveState( p );( Q$ m5 q; {3 G( O5 H" i) ]
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( p9 Q" y8 n5 T. s' [8 h        }
# n; Z% Y9 X! O        // FME7
) ?4 E7 c$ D/ |* \; f        if( exsound_select & 0x20 ) {" X6 t! ?1 J, m
                fme7.SaveState( p );
! H. s. B) \$ R! ~1 a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding( w6 u: D' `& ~3 l* r+ M
        }
4 K+ ?$ Y0 l$ |' M# ~# o
! u4 Y7 G  T' {' a& K: w! }#ifdef        _DEBUG! G# L  j2 Z2 A* l3 u: H
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );- v! e9 G6 F' b& B" s, s6 L: k
#endif0 N- D$ p! l% S9 G1 _
}
7 R0 u) h6 {. V+ r  v
. {( B8 d  _4 `! t! G, n0 k0 Rvoid        APU::LoadState( LPBYTE p )# `- e. D- J' f: Y/ k$ k
{5 w# w- l) }1 p; }5 [# ?
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡( a# I0 F, h2 o, T
        QueueClear();. Z5 E$ S5 ]% D+ D
( _3 K* H3 }2 _7 s
        internal.LoadState( p );0 j6 ^+ d& \' Q3 ~
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 \: a! Y7 T$ d+ n
* G" j8 [0 g( B
        // VRC6( m/ y! ], `6 L3 Z
        if( exsound_select & 0x01 ) {" O0 U7 Z1 q% u( N! b9 ^  ~
                vrc6.LoadState( p );
/ I' g$ t8 u; U                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; J: M2 @6 q  {0 M; l& Y* O
        }
. ?. z+ J4 {' N        // VRC7 (not support)
7 `" P" u. r" m/ T' _        if( exsound_select & 0x02 ) {
) f1 I  R+ L; }  C                vrc7.LoadState( p );
7 C( y. I0 c/ s1 K                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: Q2 F. {1 G5 P
        }/ ^  s8 N% I% P) ~3 Q& L
        // FDS5 U' G  J- m% c- m$ K
        if( exsound_select & 0x04 ) {
2 m, G) L, ~* N: {% ~                fds.LoadState( p );+ F( M4 X0 y) p+ {. s& e" O
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- b/ ?& T2 }3 Q8 @) \; q        }) t* k4 y9 M9 ^) N( ^
        // MMC51 N% k$ `2 b4 i, `1 L( _7 {
        if( exsound_select & 0x08 ) {
. F5 @9 v4 j0 Q! G                mmc5.LoadState( p );
0 ^1 H3 C9 C0 ~% d: V                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding% P, B2 U5 J; R/ E! B: l
        }
7 `4 Z3 K1 M% z  p, ?* M# l: f        // N106
3 F7 T9 K, b, K4 X! Z        if( exsound_select & 0x10 ) {4 O% H2 t8 r0 T7 P/ m& v9 |( d
                n106.LoadState( p );* S9 x6 ?0 B6 v
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, C0 S9 O# B7 d, |9 s$ n+ g3 V        }
5 o! v# f  |; j        // FME7
: [; i8 T  y8 I9 `! F9 H        if( exsound_select & 0x20 ) {0 [6 w/ M! \) M
                fme7.LoadState( p );
: t' @$ n; X8 O+ i                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; H2 y2 H. L* i! ^  ?        }
* u, }5 A; Y# H$ E+ T. L/ f4 ]3 S}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& B0 U$ G. N; B可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
: M- v/ {% c2 A, N# o感激不尽~~
! t: H0 Y" k& S" J! q9 J9 n6 L" E+ A
恩 我對模擬器不是很有研究,% `+ W. \: U9 j" ~4 h- s' S
雖然要了解源碼內容,可能不是很困難,
- i7 n: N" L# z( p  ~不過還是要花時間,個人目前蠻忙碌的。
- U" [$ t. l6 D- D. Z+ M1 G3 z' t" }2 S# N2 u/ C1 `
給你一個朋友的MSN,你可以跟他討論看看,, [$ Q1 k2 I, l% P9 W
他本身是程式設計師,也對FC模擬器很有興趣。' e, Z# j6 L4 ]  g

7 _, A& a6 F# u. p. jMSN我就PM到你的信箱了。6 f$ I7 Y4 s( q# p  J+ e- I2 D

( Z9 q9 J& V; T" G, g! m* M希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
& y0 P' W6 o+ B# _6 H/ A1 v5 U呵…… 谢过团长大人~~
9 Q8 w1 t$ [& c) o3 m
+ c+ j! h& A7 R1 ^- `# R
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 : c4 M( N8 O. `  V7 T% v' s8 |
团长的朋友都是神,那团长就是神的boss。
4 F" P; G8 }1 x3 z  I- G* J. A
哈 不敢當,我只是個平凡人,7 s# O9 c8 H, D
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙% U3 K8 u: e, ~7 x) V
ZYH
  ~; p  C" C: n1 U; P. i2 WQQ:414734306- p- r, |7 P( ?/ }* m8 Y& d
Mail:zyh-01@126.com7 d- O% \% y+ a5 @5 a. R: r

2 m. }7 e. w# N0 [  E9 m. D他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * v7 Z/ e; f; w5 _6 n/ X
再次对团长大人和悠悠哥的无私帮助表示感谢~~
, A1 @+ j" Y4 K- c" `$ S. v8 x
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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