EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ g4 ?7 s" w/ @9 X/ E) r
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~1 J3 N' v9 N; S1 Z/ H4 h0 @6 K* B' N
这里有相应的模拟器源码,就当送给大侠了~~. f6 o) e6 N; R$ E) Z
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 1 S; M6 B5 c2 |* F
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  D6 c8 x! d+ Z( R楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. [4 Y& w0 f1 w: \$ Z" D* _
这里有相应的模拟器源码,就当送给大侠 ...
6 z+ Z( h4 y6 n& V$ Q( r
聲音部分(Audoi Process Unit = APU):$ W. r1 `# J+ f- W
.\NES\APU.cpp
' \- q  ~1 }! g, ~- I.\NES\APU.h
4 u! K% X1 e# r
+ @- `! J& [. q1 L: b; F' V5 W2 m# Z3 c; _" f, ~7 S* n" H+ {
影像處理部份(Picture Processing Unit = PPU):
; Q0 s) ^6 ^5 C- E  t. V* e! I.\NES\PPU.cpp
1 ~3 D2 x9 }+ x( `.\NES\PPU.h
, ?: s9 b" ?( I2 W% j2 W$ H3 \$ R/ A0 N8 h# d7 y1 _
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:3 s4 T. T! e" Z1 ^, v
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
( Q4 h% Q- I, v# A+ o//////////////////////////////////////////////////////////////////////////
$ u( `: F( @) d: n& D7 V' m6 U  b//                                                                      //
2 _  b) {* X" j//      NES APU core                                                    //7 E+ {9 h% l0 |* T4 X- Q. F% P& W
//                                                           Norix      //
  |; X( v' R( `4 f0 y//                                               written     2002/06/27 //- g' e" ^2 ]* e5 b8 Q  l
//                                               last modify ----/--/-- //
/ T* B$ o5 g; ~* k6 Z//////////////////////////////////////////////////////////////////////////
8 z9 h8 Y' u" @#include "DebugOut.h". u. S# C$ ]; z$ \- o% z
#include "App.h"' @& `1 j% B0 {' m) T& A* z
#include "Config.h"# O6 F- S9 A, [. p$ W/ q% ?0 o6 c

# d% ]' I; K/ q. u#include "nes.h"' s+ r: x; l0 [* s2 @( @* ]0 N7 t
#include "mmu.h"" I- S/ ^* J3 j  Q4 ]
#include "cpu.h"5 z3 E! Q* c$ ?+ F8 ^
#include "ppu.h"
9 i" l8 z4 O& A( g5 y8 {#include "rom.h"
2 e5 j7 |( [! _8 b9 O( @#include "apu.h"
  O. U8 _' h! T9 m
' ^% U% }4 }- Z1 C8 c// Volume adjust+ G& H; G4 x6 ~% ?1 Q" S
// Internal sounds7 ?$ B6 G  B, C- L7 A6 h/ b% B1 n6 _5 |
#define        RECTANGLE_VOL        (0x0F0)
2 i6 P: X/ F5 L9 v8 }7 ~- n#define        TRIANGLE_VOL        (0x130)
/ I0 l. j/ g% X' m; Y/ T#define        NOISE_VOL        (0x0C0)
0 V# d: C! q4 Z+ h8 _8 n- ~#define        DPCM_VOL        (0x0F0)8 M+ b" ?( K4 u+ c' r+ b! f
// Extra sounds
. ~6 v- F3 M  z  N* M% a$ o#define        VRC6_VOL        (0x0F0)
% K7 |( o; z$ \* X; V9 C+ \5 K#define        VRC7_VOL        (0x130)
+ Y1 l( E3 n  x3 B5 s#define        FDS_VOL                (0x0F0)
0 R* m* D+ M6 O8 j: t. X; p4 y#define        MMC5_VOL        (0x0F0)! g1 T: S8 F0 m4 \" h
#define        N106_VOL        (0x088)
9 J, {; f! R& \: Y# S#define        FME7_VOL        (0x130)! j' D  `6 P( q! m  }
% j1 S2 H( l3 P  \( [
APU::APU( NES* parent )" i, M" i1 q$ C' K; Q6 Z- _6 h
{( E1 b' w. ]1 V" B3 {: R  p) P
        exsound_select = 0;
" r2 g9 p# u4 c& O; }1 Z: ]; f8 W8 o* L" i2 r: S
        nes = parent;' {% t3 x0 v$ o9 C  n8 q
        internal.SetParent( parent );
4 y6 M  X5 R0 |# S
& C) u4 o/ \  c        last_data = last_diff = 0;
8 ~  ?# E0 ~0 x) s1 i/ G
2 Z# J( T1 e' C2 U8 L# H        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );9 x7 d( |' U( c+ R' O

. w6 k) j. U! g! O$ n$ s6 |9 L) U        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );0 K* |4 ]# D* V$ J0 ?' j( q. r8 q+ d5 x
        ZEROMEMORY( &queue, sizeof(queue) );! a, T7 x' A( e0 @- m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" t% Q. K7 ?& N
* J" ~  J, W/ t, E3 Z; I" e8 P        for( INT i = 0; i < 16; i++ ) {
( X9 H/ b1 _2 A& t+ Z                m_bMute = TRUE;
' M1 l. \) ]& n6 M        }- o) S& W" ?+ B. K" X5 y  d: d8 R
}
1 B4 [0 p8 O% W- J% K% y
9 y' v6 Q1 q7 PAPU::~APU()
' s5 E: d8 B; h9 L{
# m+ m+ E  {- R8 _}
, T4 U$ m# n& t8 C, i4 P& h% V6 B
2 `. `( V0 p* T3 e8 k$ r% d# Bvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: \3 M+ U( n# \1 a* r' K{
' Z. h: @  ~+ y* `& M        queue.data[queue.wrptr].time = writetime;
- p. e! H3 k( ^1 V( y        queue.data[queue.wrptr].addr = addr;
% {5 S7 Z7 _% u3 o        queue.data[queue.wrptr].data = data;
) a! i& G3 ^% v        queue.wrptr++;
( e% h4 ~. G/ W4 x( S        queue.wrptr&=QUEUE_LENGTH-1;1 ?  H( H7 y# M' R/ b4 y+ z
        if( queue.wrptr == queue.rdptr ) {0 I- R2 c& N+ t: S' G1 A
                DEBUGOUT( "queue overflow.\n" );
: t( [, [( V5 \1 o        }
4 s2 C2 ^6 m$ |" r, n' [) C}: K( D1 ^* z; M  ?. L
' ?* }* m  `1 {# ]
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
& `8 c  s# T. Y7 _# r{
; M' Q% n# {% C9 f; S( d        if( queue.wrptr == queue.rdptr ) {
( x# V, `1 c7 y                return        FALSE;
6 ^( n" H6 }& U0 I        }
7 a5 @) @8 i7 z4 K9 |5 o. i        if( queue.data[queue.rdptr].time <= writetime ) {) C  ?* S. o( B) y9 E8 T7 m7 z
                ret = queue.data[queue.rdptr];; M+ G# m4 w0 X
                queue.rdptr++;$ I, M  l: K5 B. Q- I% a
                queue.rdptr&=QUEUE_LENGTH-1;
; G' l4 c! ?5 _2 |                return        TRUE;
& {1 x4 F. ~: Y4 \* P3 J) I        }
; c. T, k6 J( S4 i        return        FALSE;/ f0 ?) }5 M. h! L7 Z
}
# A5 s9 B8 c1 R/ N8 C; P, N- S& |8 n, \
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% `. n  ?- S8 J: g. S& f: @
{, H& a% x: b$ y
        exqueue.data[exqueue.wrptr].time = writetime;( t6 ]- u# N  `% s3 h% V2 A
        exqueue.data[exqueue.wrptr].addr = addr;
$ t/ p7 y- m2 a4 _1 }        exqueue.data[exqueue.wrptr].data = data;+ q9 F% M3 R9 A9 c3 X: f! b
        exqueue.wrptr++;
$ ~! t" i$ r9 v- o+ E8 C" G& J        exqueue.wrptr&=QUEUE_LENGTH-1;
9 u+ U! R1 c8 Y; V4 A2 Y' ~- P7 G        if( exqueue.wrptr == exqueue.rdptr ) {/ i# ?" d# I- Q* E5 [6 u! i
                DEBUGOUT( "exqueue overflow.\n" );
' b. S. b+ N/ X6 h2 `1 B. ?5 {        }7 b3 d( G& T5 q0 r+ y7 R. x" Z0 L. Z
}
5 p* L2 M0 E# j" g, ~
! }) ~, A% F; x/ M/ aBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  P+ ^. ^: C# z& j9 @8 ]
{
( d1 L' i7 Y8 A) J4 W1 P3 _+ }- y        if( exqueue.wrptr == exqueue.rdptr ) {
) ~2 L6 _5 j! X& B' X& W  ?/ }                return        FALSE;* W0 M6 Q, ^' y3 R( \
        }
- q$ [9 ~: }# A        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 I; F7 e, G* ^0 N# v2 ^3 y                ret = exqueue.data[exqueue.rdptr];
' }$ |4 y! R; N                exqueue.rdptr++;
! ?  _; F+ q- N7 [7 t% Q6 p                exqueue.rdptr&=QUEUE_LENGTH-1;. T6 k2 V/ a+ U' d4 }
                return        TRUE;0 K' p4 ]- i# z7 ?0 D4 ?
        }+ o* F6 w6 s) m- V0 O. Y
        return        FALSE;
& d8 W2 G) S' o$ T}
" V; s* G% ]  u1 m! p9 |4 ^: ]7 I2 ~) {
void        APU::QueueClear()( s; w6 n% K) h% @
{
! ?" Y- v& f4 s& J        ZEROMEMORY( &queue, sizeof(queue) );9 ]4 p5 l' N* R* x& F2 c
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 V6 k/ T. c) ~
}* k4 Q% X& v& I4 @  K# g& f
; G) d* S" u1 q. r6 n! A, S
void        APU::QueueFlush()( g& c: {/ x7 N' o6 e& |, g8 U* g
{
  K9 k, f& o) _. ], S$ {        while( queue.wrptr != queue.rdptr ) {
4 X& _6 w2 Z2 V% t8 |5 a                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ l: k. f( h' f& }$ g  w* A                queue.rdptr++;0 A* T2 w: A& m( G
                queue.rdptr&=QUEUE_LENGTH-1;
. u, P6 c. h8 H) P4 l% T        }
; D5 Y! K- e' B$ t" ~' ?" E" {
) @3 A* `1 b1 V3 Y6 ?6 P' @        while( exqueue.wrptr != exqueue.rdptr ) {5 D) j; k0 z/ }: q5 P0 t9 E
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );4 p3 |! r* y% n! I
                exqueue.rdptr++;/ B" ~: x$ @, ?9 `% A
                exqueue.rdptr&=QUEUE_LENGTH-1;2 K+ b9 Y# e4 B, C" W" @, {& `
        }) v' d( u% V/ n
}
' c" t0 n3 V  O' K2 T" x8 ~0 S$ P
/ F: ^4 K" U' I) {void        APU::SoundSetup()
; n) x# E! {$ \9 Q2 ~$ a. o{9 W- s' e+ O9 @
        FLOAT        fClock = nes->nescfg->CpuClock;
  D8 [# O6 l  d$ N2 H; T        INT        nRate = (INT)Config.sound.nRate;
3 J, t; e0 c( D- w1 ~) F        internal.Setup( fClock, nRate );
1 e* G* d1 J3 d' |, x        vrc6.Setup( fClock, nRate );6 x& S/ Y/ L3 A4 n  k( v
        vrc7.Setup( fClock, nRate );2 J6 K& ]+ ^: }0 Z5 z
        mmc5.Setup( fClock, nRate );
* l% }: [* `' {2 O% _) W        fds.Setup ( fClock, nRate );
8 y$ _7 d! `7 N        n106.Setup( fClock, nRate );( Z& d9 s4 p5 o) ]5 K/ K& w3 T+ t
        fme7.Setup( fClock, nRate );
/ o/ m" `4 i, @" |% R}
. |( M- d  k: ~# _# ]8 m1 r6 o7 B# h' J
void        APU::Reset()
' A/ X# s: [7 t{4 ]. D* t& ]) ~* @# I6 n+ m
        ZEROMEMORY( &queue, sizeof(queue) );( f9 e/ @1 G3 @0 q" h
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! z$ ^$ ?6 B) d/ g1 o( `# Y
! q9 Z- f5 y: e3 d0 H5 ^$ N
        elapsed_time = 0;
3 d; z" O3 R) o- x6 j4 j
# c, D! ?; E5 U8 S5 g2 K        FLOAT        fClock = nes->nescfg->CpuClock;
% E* V8 q5 N: P8 b8 U4 }        INT        nRate = (INT)Config.sound.nRate;
2 W6 U# ^" J. j7 X, o; w+ ^        internal.Reset( fClock, nRate );
# L( K$ p, k- D, M        vrc6.Reset( fClock, nRate );
% n; @+ |( {1 h; d/ W        vrc7.Reset( fClock, nRate );0 ?7 j: C; S2 C% S3 L! p& \3 |
        mmc5.Reset( fClock, nRate );
& h' k. x/ A) c$ h- V        fds.Reset ( fClock, nRate );4 e6 u8 ^1 z+ k8 Y  c! x4 K
        n106.Reset( fClock, nRate );
9 ~' _$ j9 u8 s8 a+ G+ k3 l3 F: h        fme7.Reset( fClock, nRate );$ l6 Q) Q" z- p. O) g! n# `" ]* _+ D
& [* r. y  B7 _, J8 u" [4 J
        SoundSetup();2 T4 ~, V, N2 ^+ V6 z9 Z! @8 _* i- d
}) e2 k0 U$ m* f  w7 G

: G0 Y7 |. Y& N$ n. jvoid        APU::SelectExSound( BYTE data )# R1 j* z: m) m4 d9 r( ?! E
{; Y- u% @9 y% W* [4 @) U
        exsound_select = data;
' W- }, _' d' x6 `$ g' l5 t}( T% h6 A: d$ h( k

3 b; t; K: E6 B/ h( K" RBYTE        APU::Read( WORD addr )
6 Y9 T* J) N: `  v3 C{# l7 z- O6 s6 g5 v. ^' q
        return        internal.SyncRead( addr );
$ N$ o/ h( \, b6 [: Y2 ~4 U}
- }' ]$ k0 X8 k8 U/ q8 s* w
$ n. f7 k# T/ ^void        APU::Write( WORD addr, BYTE data )
( }+ g5 y: N* J1 C( r! M4 @{. K% `5 d6 _" L2 ]8 U  F+ [
        // $4018偼VirtuaNES屌桳億乕僩
: B& I! N) W# I2 [        if( addr >= 0x4000 && addr <= 0x401F ) {
% R$ e' ~4 }1 x/ s                internal.SyncWrite( addr, data );
2 z4 ~& v9 k/ j" s2 ?8 j                SetQueue( nes->cpu->GetTotalCycles(), addr, data );( O8 y) Y0 W3 {! n0 J8 {9 p+ q
        }+ w+ o9 |/ E' [: x' ^; z8 F
}
8 H, u7 a; G; Z' _+ a: O, @2 Y
( W5 `! C0 p% Z6 X# }+ t% BBYTE        APU::ExRead( WORD addr )
; }/ w7 n5 Q: Y% t{+ n6 u$ h2 @% b$ b  u8 D3 X
BYTE        data = 0;9 `) s4 w) I8 {' D. L" `

( L1 b4 O5 \; M' l6 Z3 P% i- X        if( exsound_select & 0x10 ) {
/ F/ T8 g) g- S/ e                if( addr == 0x4800 ) {
# Q7 F& W+ w! `                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );/ f# f2 I, `( d& k
                }
' `3 d' {/ @- l" @        }9 H0 A$ \2 x6 |6 X6 c
        if( exsound_select & 0x04 ) {9 m- h1 G$ x% Y2 C
                if( addr >= 0x4040 && addr < 0x4100 ) {
( D. X( x5 l( E                        data = fds.SyncRead( addr );
+ i  o+ h% {! ]) z; {, c                }
) V* p2 r% r; Z/ T5 s        }
/ \& y6 W$ d; [+ W% W        if( exsound_select & 0x08 ) {
, t& A" I  C1 G+ X0 ]3 D                if( addr >= 0x5000 && addr <= 0x5015 ) {- F: Q7 Z4 @6 p
                        data = mmc5.SyncRead( addr );' _1 @% t% _) ?
                }* b3 P7 N, R" i6 j' u
        }
3 S! _  X% ~& o4 M5 C) c' V9 \
" m5 B% E, D5 b        return        data;6 |' u9 u) Z9 r- r% N' W9 S7 v
}! d, _6 k! u5 d& ?7 s1 o
, ~8 @" s* C6 [3 @
void        APU::ExWrite( WORD addr, BYTE data )
6 H7 N  J/ \2 ~: s! x- v: t2 k{" G( ~. S6 D. M- h* K( a
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );5 Q2 k% g+ w% p& s- I" e* k8 S$ e
5 V7 g; Z' q& e0 i; X& g0 V* ?# c; M! K
        if( exsound_select & 0x04 ) {5 s& n  l' {. e8 u( }! R( m
                if( addr >= 0x4040 && addr < 0x4100 ) {
( H6 S7 }- b/ J4 i- D, D* J                        fds.SyncWrite( addr, data );
$ w$ g) O$ Y4 E' e6 q) V                }) f5 B7 J' E( o( T3 j
        }! Q8 a" ^2 k- P; q

9 R: k% A& p3 N- o8 \5 C" ], f        if( exsound_select & 0x08 ) {
: u( E% h7 Y1 ~$ q' R                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ N* l4 q) }. E# U                        mmc5.SyncWrite( addr, data );
  T- b/ R# T  Z3 S4 j; M( `- h                }3 W2 {, x5 m+ s: P
        }
; ^, m3 o4 Q2 j2 B7 ^5 R/ k3 Q}
% \7 b; R8 M  H* q4 @7 k9 F
4 Z. g6 m) V' z( g4 Kvoid        APU::Sync()
; Q0 z8 s. W* Q3 z{
' n* f& `' W+ X# A' l}  {# ~  M9 G# v7 l0 n

" _) ]. p+ D3 mvoid        APU::SyncDPCM( INT cycles )
- b+ p" G. Z6 K/ z  d8 o{/ Q  p/ v  z! g! X; h: u
        internal.Sync( cycles );6 o% q5 }) n" }8 s

  T, l% n* `4 h- V8 U) w9 Z        if( exsound_select & 0x04 ) {
& j4 r% M; L/ C' U: Z7 h* s" b                fds.Sync( cycles );  P% H$ f/ U2 Y3 C7 V) X
        }# ]7 E/ G; ^1 ^
        if( exsound_select & 0x08 ) {  `. ?1 y# j6 t# r* }* e1 Q
                mmc5.Sync( cycles );. j" K$ Q/ K# D* b% ]0 }
        }/ R7 `- b$ D" B0 M6 q
}. y+ n* Q6 Y, s; w' y

; g& Y' B! L4 k$ @3 g& \1 Evoid        APU::WriteProcess( WORD addr, BYTE data )0 f5 v. I' l! g! _
{0 L7 x% |2 ]- F. t. Y+ ^1 e0 T
        // $4018偼VirtuaNES屌桳億乕僩
+ s- {# b: ?+ S4 ?# }7 S# n/ B& E        if( addr >= 0x4000 && addr <= 0x401F ) {
9 }9 u+ `- U: h# b7 c; \( Z, j! d                internal.Write( addr, data );
7 h3 J' _* C0 v        }5 u! X% G5 V  W; m" D, F8 }. `
}9 f( R( u& ?& R

# F1 ?4 p: V( G, x( Rvoid        APU::WriteExProcess( WORD addr, BYTE data )
7 ~4 e* T% y0 v& S2 @, f( p{
' w6 V8 [8 U+ @5 `. W/ U& l; }        if( exsound_select & 0x01 ) {
& c  v. |2 f) {) U# V. c! z1 b                vrc6.Write( addr, data );
) i; ^, b6 Z5 z- ?/ l- e/ F% A- N        }6 r- x. ^0 y; p! L
        if( exsound_select & 0x02 ) {0 x" ?" H$ K. u5 w- \
                vrc7.Write( addr, data );* l/ s2 E; b+ s# K  x
        }# U! Y: V' [1 j
        if( exsound_select & 0x04 ) {4 h; E/ A+ ~) M
                fds.Write( addr, data );1 e# F3 z- ?) q9 p
        }# C! u* c" O/ ?
        if( exsound_select & 0x08 ) {
# Q$ @/ H& w" H" z. w5 q                mmc5.Write( addr, data );0 c8 ?; V5 p+ t  ?: S$ u
        }; f8 B0 h: L  b/ d" Y
        if( exsound_select & 0x10 ) {6 b: m3 E% U3 Z6 i0 D+ Q8 a
                if( addr == 0x0000 ) {# p6 k. G3 `+ o% I
                        BYTE        dummy = n106.Read( addr );! A8 R- `& A4 N: l7 `- h
                } else {
9 `( Q, o; P4 a                        n106.Write( addr, data );
( C( f6 v- z2 W0 Q& T7 ?$ W' ]7 v0 V                }
: \; A7 X8 c2 [1 j! q% n        }. W8 u6 f5 D5 D0 T) w0 ]' L
        if( exsound_select & 0x20 ) {
* E0 U& h& y- A0 r: `% L                fme7.Write( addr, data );
7 u' [; b( g2 r# ~+ s        }
$ E0 l: G% x+ }, @/ D( l6 @}
4 `( p" i) s; j
/ Y; t$ W) n2 \( K5 t  r3 }3 kvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& @$ d% z. J6 U- t  d{( r0 e- }) J3 C% `5 M# K
INT        nBits = Config.sound.nBits;" r9 J; r, L- P6 c6 y
DWORD        dwLength = dwSize / (nBits/8);& x7 |; u8 F( a) n, u! }* h
INT        output;0 t2 `4 a" z& p- o$ H
QUEUEDATA q;
# u( e  ]  k! s0 ]  `9 R0 F" KDWORD        writetime;& j4 X) x3 P- J' W! i/ {+ D5 k

( z9 E. C' \  U8 ^% |LPSHORT        pSoundBuf = m_SoundBuffer;
8 l1 }2 y$ B5 W2 sINT        nCcount = 0;
! Y4 ~  @: c# V6 B) G
; n4 W8 T/ E' \" Z8 V3 ?! j# z( qINT        nFilterType = Config.sound.nFilterType;- }% d! y7 R4 \$ e

; a, ]2 M. {) ]* X: g8 J1 ?; W        if( !Config.sound.bEnable ) {# m$ ]: l* t/ U* e4 G. z' w6 b
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
; i" J) q/ h- P1 i) |; R; j                return;. @' P6 V! K( J6 ^6 O
        }) R' l9 D) G( {) @

% v: k6 H, O9 |4 P3 U5 @        // Volume setup3 h% |; ]% k5 q* b
        //  0:Master
% [* d+ w% M$ g5 b. V2 m; N# N        //  1:Rectangle 1( C, E$ p' X# x( r
        //  2:Rectangle 2" u; ]' q( |: D# C
        //  3:Triangle
# L% Z0 I7 T/ k0 T- N: n        //  4:Noise) s" E! R( R) ^3 r: [
        //  5:DPCM* h" c& ]# R' G! {% B+ k+ V/ Q
        //  6:VRC6
7 N* E0 Z1 V3 n- T3 S        //  7:VRC7
+ N1 T6 O, b7 T7 `$ o( j" [5 K        //  8:FDS& {' b' k0 G7 H  ?
        //  9:MMC53 X9 }4 c. U4 Z% e) w
        // 10:N106: j$ D% s9 [+ E/ P8 ]3 }' F+ j* N
        // 11:FME7
. ^. o* j4 G/ K: O9 ]6 u% M* y" Z        INT        vol[24];, t( c" x/ [% O
        BOOL*        bMute = m_bMute;
+ D2 h- v6 f: W6 b( }& j4 Y7 N3 ]        SHORT*        nVolume = Config.sound.nVolume;
8 P( W$ G' R" R" @7 [, b- I! ?& v. x3 f" D
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;7 ]. k2 G' W% k  _
( `# T1 R0 a" c& O
        // Internal- R: P( s+ |( w/ C
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;+ G; z- U; k+ ^( d) U1 A
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;$ ]+ s- W' }- }5 P# `. I
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
/ r' C" w* D5 X: A        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;5 k! L% e* J0 ], E$ O; u5 k
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;( Y$ ^0 F7 C9 n" e2 J; m) m4 h
6 H) I6 d0 |3 |) `2 i) m, C
        // VRC6  _* h. d8 f8 \$ S" Z0 S6 |' N* g
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 s" e( V  G5 C6 S' W& v4 c/ b8 X        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ O% O& p8 G! q$ D7 U2 m) L        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# o/ J  h# Q' k3 H6 t5 v* n) ~6 ~5 N# R+ w0 ~
        // VRC7
- w5 u9 H8 R- _% i        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% P* f, f) J! Q; U( L* H
6 g' w+ {9 C+ Q
        // FDS
& r, k$ Y: d. M$ L/ g2 T, f( t3 I& T, B        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;, o9 x$ l% Z/ E9 X0 V$ X' X6 E! |3 U  U

0 f) Q; q- h/ P/ i& h6 p5 E6 g        // MMC5
& L( |2 ~" P" s" a$ v5 y$ P        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# L) o6 F9 Q, v( o        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ k3 K+ k' l6 @" W        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* r* v. @5 _3 r( T1 x
$ \( N7 d9 O& `* O9 X        // N106
; l- {3 o9 w1 A, |! n$ E        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! W: p+ t" o) @  D        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 L; N( m$ r& ~1 D( k+ |# J
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. u! j5 p: s8 n3 ]        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' E  g, Y  V) C* S9 \3 s( `        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& I/ n  v5 M+ |7 S5 v        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, a  S- C" B+ |$ v5 [% ?
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. z  X0 n! Y' g9 f; ?8 p( v
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ j7 m8 v8 r! Z' j$ Z% B* G5 W
% ]* \# g, U* j1 ~/ R( |        // FME7( ], R7 a1 `; A
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ Z$ s$ ^# a* c. x& }# O- I- @! h
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 Y+ z# {* ]& H+ ^; o7 u        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- u) Z; i) `3 @% J2 N/ @6 S

; N* n" y' J: W6 E$ }$ X//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;: I) U9 a3 }* ]. F- [4 a$ A
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
, h$ i3 ~5 c1 L5 W6 I  S4 }- p" j$ `; h4 L9 ?! r2 d
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
  n7 Y3 j7 e: J2 d8 J. a        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
- _% [" D) _& P: b7 R! E+ h                QueueFlush();; o& n0 I8 Q7 K9 H8 L- c
        }7 P0 q3 S3 v7 a% q: f" X

" V) f, r& K- Y, N* z        while( dwLength-- ) {' r/ l3 N6 y+ V0 I
                writetime = (DWORD)elapsed_time;" T' C5 `, T, t- l) q
1 N- [7 Z9 |2 z$ L6 S
                while( GetQueue( writetime, q ) ) {
$ ]* p# L' }% Y! ]8 ^+ ^! u# Z: T2 B                        WriteProcess( q.addr, q.data );" k( c7 X. X  u5 L; A% Q
                }1 s0 d' R9 U: a

+ V0 R+ J, a* W9 b                while( GetExQueue( writetime, q ) ) {
8 [# l3 ~8 i0 ~$ Y                        WriteExProcess( q.addr, q.data );
4 R4 t2 p: U1 w/ U                }  \" t, R- H+ u1 z' |

* z% d% b$ s! W6 L, H# K                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
7 |; p- G/ B1 r, b+ W+ T                output = 0;% p4 F2 `6 F. ]: C
                output += internal.Process( 0 )*vol[0];8 G' z; q% Y) O! `; h, u+ O# L
                output += internal.Process( 1 )*vol[1];
  E$ M' p: ]  U) S/ T                output += internal.Process( 2 )*vol[2];
/ c- {, _0 Z1 |% C: f                output += internal.Process( 3 )*vol[3];6 j: U2 O2 N& }; a
                output += internal.Process( 4 )*vol[4];. s& l7 B! R& ^% c6 d
6 P9 {3 U  V+ P7 |4 W% F
                if( exsound_select & 0x01 ) {
% G9 X4 ^: i! i" `; u' m9 j                        output += vrc6.Process( 0 )*vol[5];0 [% e6 Q: L; _  {
                        output += vrc6.Process( 1 )*vol[6];
7 a) N6 g5 Q" ^" M( A- ?9 W                        output += vrc6.Process( 2 )*vol[7];
" k; o: l; ~5 T  h+ f" w- [/ B                }
7 T( ~/ o0 Q# m, r9 J# |+ D$ K9 V                if( exsound_select & 0x02 ) {
9 H6 I# r# s7 X# C                        output += vrc7.Process( 0 )*vol[8];2 H' b1 p" K/ |, I) r/ p% O
                }! h( Y7 P3 _) B* f; D
                if( exsound_select & 0x04 ) {
( i, n7 x" \- q& t9 s                        output += fds.Process( 0 )*vol[9];  `3 _/ I- ]# `, o; G( e
                }
0 P% p" u/ k* f, [( a) l# j                if( exsound_select & 0x08 ) {
5 b8 M! ^. y( f2 g1 \9 P9 ~                        output += mmc5.Process( 0 )*vol[10];
' Y$ ?, A. L2 g6 F                        output += mmc5.Process( 1 )*vol[11];
# |2 S/ s6 S/ Y) x6 V                        output += mmc5.Process( 2 )*vol[12];* m1 O: Y  y  r* [# N
                }, o, D& k+ z- h9 `8 p8 O
                if( exsound_select & 0x10 ) {0 z' _' V+ ~$ B6 x9 ^8 J
                        output += n106.Process( 0 )*vol[13];
- P$ `+ F# [3 V) F& _/ W! R/ D1 X( w                        output += n106.Process( 1 )*vol[14];2 i  w$ D5 o5 v; P
                        output += n106.Process( 2 )*vol[15];2 g: \6 J8 E& c& _
                        output += n106.Process( 3 )*vol[16];$ d+ y4 W# g+ u, [) A
                        output += n106.Process( 4 )*vol[17];
( V4 w6 Z: }% s; q' T: ?6 v                        output += n106.Process( 5 )*vol[18];4 }5 c, m1 Z6 k( Q( x6 \' V
                        output += n106.Process( 6 )*vol[19];$ t+ H4 l- ~8 @' b. `( i9 ?: _
                        output += n106.Process( 7 )*vol[20];, n' r" n; M! `8 k7 n2 T
                }8 s) @5 [& x. q& e2 r5 ^* N
                if( exsound_select & 0x20 ) {
/ k* h' Y- ?1 d! }* ?                        fme7.Process( 3 );        // Envelope & Noise0 t2 p; Q0 \, g  m7 U
                        output += fme7.Process( 0 )*vol[21];5 r# I5 ]6 I" }. `
                        output += fme7.Process( 1 )*vol[22];
+ h, z; c) W' Y; l) }9 a) w                        output += fme7.Process( 2 )*vol[23];
3 N1 @8 p; d1 G6 i1 ?' y                }
0 k7 p9 F6 ~4 ^. Z! h% l
, Y* |7 H* o) ?* J9 Q  \: l0 U' A                output >>= 8;  k8 U' u% R  G- @" T& l3 x

/ y2 j  f! f5 s, p/ K9 u                if( nFilterType == 1 ) {
$ m3 @$ ^" `% f- D) n) t. L                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 S: L& V) ~  y, P, C6 d% H5 J+ A: E- [
                        output = (lowpass_filter[0]+output)/2;
* g# ]: D9 ~. I. o( {                        lowpass_filter[0] = output;, k; o& O7 C: @" n: ~2 m
                } else if( nFilterType == 2 ) {4 F% e  J8 O, _( P( K) t: `
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
9 c" C. p/ F& c) H' P  d                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;2 {4 l* Z% [. N) T
                        lowpass_filter[1] = lowpass_filter[0];
- x( K$ ^- m; {  @! Y                        lowpass_filter[0] = output;0 q. C4 M1 h2 V
                } else if( nFilterType == 3 ) {" _! X$ s* m. G) u8 V' O. z* p
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
2 c+ k3 C' m  X5 V1 W0 o/ ?                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
' J" {2 @) [9 o4 B! s                        lowpass_filter[2] = lowpass_filter[1];- x3 H' `6 d. y1 L! v
                        lowpass_filter[1] = lowpass_filter[0];, X' K1 @( Z/ i. z+ T( O5 x8 n4 A) m
                        lowpass_filter[0] = output;; n9 u; u. Y$ v( O; H1 `9 z1 {
                } else if( nFilterType == 4 ) {' ]8 m( x9 o$ x, o/ s
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# ~5 z* B- F! A9 f) T9 m
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
( ]7 C) }6 i2 j                        lowpass_filter[1] = lowpass_filter[0];! I; G  T5 n3 |8 N$ ]0 t
                        lowpass_filter[0] = output;
- m% T' k, }3 M" n                }
0 W8 b2 h0 @0 [5 e1 C6 Q5 j2 L  P4 |/ H" h2 k6 n# l  J
#if        0
) i8 D6 N1 z  V8 @% U                // DC惉暘偺僇僢僩1 i' y  p3 c1 {$ W0 [
                {3 f3 R" O6 ?6 b' P; c0 X
                static double ave = 0.0, max=0.0, min=0.0;$ l5 g% A- Z+ M7 Z* \7 q
                double delta;
  H0 J# D$ [2 _- \; u* r                delta = (max-min)/32768.0;
8 J& B6 A7 g) l+ }5 [1 T1 I                max -= delta;
# [; B3 n; U; S8 X; }% ]                min += delta;( o, ^$ ], J# @8 r! E$ D3 k
                if( output > max ) max = output;
2 L( Y' A. l/ x                if( output < min ) min = output;: ?! W3 m3 C  T7 S7 F  e
                ave -= ave/1024.0;6 \7 H# E+ S" R
                ave += (max+min)/2048.0;
# y+ L1 ?& ?' h                output -= (INT)ave;
4 f6 |  z* Y4 g5 w3 e# `                }! W* X& o- s$ S7 Z" }' l/ u' \- o
#endif: s; c7 _  J5 L5 e: o% B! L
#if        14 N/ F0 a( r" ^/ ^, a$ l
                // DC惉暘偺僇僢僩(HPF TEST)  N) L, D% \; g/ S( H2 \
                {
; m" m, G7 j1 R( C- R$ [) t//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);+ W0 Q$ f/ d, r6 ^
                static        double        cutofftemp = (2.0*3.141592653579*40.0);3 q" e; [/ [3 F! X  x) D
                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 Z9 `# D6 [( ~
                static        double        tmp = 0.0;( m8 F4 Z$ I( w1 n
                double        in, out;
. T! T2 V( O4 N7 C' y" N3 k: {8 x& o# x% F1 Y
                in = (double)output;. i/ I8 i. j. H! R7 K4 i
                out = (in - tmp);
& W0 U% ^7 I$ f                tmp = tmp + cutoff * out;$ S& z' b& V/ @
0 Z0 F) B% T% l" k( |& O, B
                output = (INT)out;( D, N  h# l# J4 _( A
                }6 o: e6 B: ?" l7 F- F( W
#endif7 M0 p& g% W3 ^6 O2 F  K
#if        0  Q2 h" R, }4 Q& j
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)7 c2 v5 G& ^+ B7 K  T5 E
                {
2 G7 u6 f. X' d+ j" Y6 ]% m4 p                INT        diff = abs(output-last_data);  e. y1 o5 P% W5 i3 Y+ V7 f
                if( diff > 0x4000 ) {
+ W& C& r2 y! n+ x                        output /= 4;) m" p' _* q/ V, ^8 k# h
                } else 8 F- n1 z" j) x0 Q
                if( diff > 0x3000 ) {
1 m. p, J: n* b! C                        output /= 3;. W4 v) k1 Y! f$ i7 i) \- |
                } else
; ?2 z3 G/ a9 S2 ]' u* r                if( diff > 0x2000 ) {
  s6 H- T. [0 U  S7 M                        output /= 2;0 y" p: o0 ^8 ^- Z+ l% U; G
                }. n) L6 X" ~: p, I3 d1 y. x
                last_data = output;
0 L# G2 I9 b5 c                }/ V# }# }6 o' s" T& D% @
#endif
& I0 N6 K) @8 Q/ e. ?                // Limit
, n: W% |* {5 _# L) M                if( output > 0x7FFF ) {
4 [1 O$ B5 f6 n. B5 m# |+ |                        output = 0x7FFF;2 p+ z; z- F3 q
                } else if( output < -0x8000 ) {9 W$ _1 ]6 F  p4 f! n5 U% o# \$ f- y
                        output = -0x8000;
/ v6 k: ~3 v, D9 S' H& t                }4 A5 e! N- m9 j' G/ p6 @
# P1 }0 b/ }8 P; ]% d8 c: W
                if( nBits != 8 ) {7 l, W3 ~) [9 h2 R
                        *(SHORT*)lpBuffer = (SHORT)output;3 b( _# g! ]( m! @
                        lpBuffer += sizeof(SHORT);
+ b$ s6 Z; B$ r: W5 M5 Z4 T                } else {( O. [/ `9 e7 }2 s8 j
                        *lpBuffer++ = (output>>8)^0x80;/ ]5 C& Q( `: D
                }
! {$ F* j/ Q0 X3 U- ]7 y9 e: z/ [; J# d: S4 j8 j* ~
                if( nCcount < 0x0100 )
9 L1 S9 J. e6 L% O: U                        pSoundBuf[nCcount++] = (SHORT)output;0 D7 k  h. B( A8 [% ]$ w

. |5 ]: m7 P% H8 |5 s3 U8 l8 h//                elapsedtime += cycle_rate;
6 |2 a$ c2 Z1 o" ^4 h                elapsed_time += cycle_rate;' O2 T1 k  k# m
        }
9 ^+ @' c5 r+ S6 @, S3 D* w% C* h. j4 t: Z1 r! ?5 T
#if        1# p0 Q, P) S9 |# `' @) A9 b7 m
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {0 _# E1 O: s9 L! b+ z
                elapsed_time = nes->cpu->GetTotalCycles();0 F0 m0 e) t- S: p
        }
- I( N# W. M" x) O        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. B1 l' h3 m1 h  y! q3 s0 V5 Q                elapsed_time = nes->cpu->GetTotalCycles();' B$ \4 R- z: C
        }
! V3 _0 _- O) s7 K! y* J2 Z#else
% `3 j% R5 B: t9 ~9 W        elapsed_time = nes->cpu->GetTotalCycles();
2 o5 D+ s" C* K# ]2 @: E' f#endif' Q* r* Q  s5 l8 Q( S
}
3 H1 m) V3 ]0 ^  L
$ [4 y) D6 I; a! z& {4 G// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
& |) e3 O4 q% W: |1 _+ iINT        APU::GetChannelFrequency( INT no )7 E1 w# k/ F* d  m3 R
{
% s4 t. n; o. v. N+ q0 ]        if( !m_bMute[0] ): ^0 H5 G: d  D' o/ R9 G) U- j5 `7 [
                return        0;/ y1 q9 S# D  q4 c# N, S
* ]! i" N# |3 a" i. S1 P6 N+ c/ x" Q
        // Internal. K: B7 ?5 s8 A4 D5 R6 \
        if( no < 5 ) {- N0 A1 n8 k1 |2 Y* z% S
                return        m_bMute[no+1]?internal.GetFreq( no ):0;& [; _  {7 Z5 H" {4 ?8 Z
        }  t% j# S' d2 N
        // VRC64 v. y1 Y6 N' z& E
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {) E* J+ L# k8 v+ m: `7 b
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
5 p5 }' c. w! t5 Q* J! k        }
4 Z1 e& l: j8 H' m% U        // FDS
+ F& L! @1 I2 c; @' E        if( (exsound_select & 0x04) && no == 0x300 ) {, l9 n) n4 M2 g1 Z$ L
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; }1 p- O  ^2 w5 O* F: d! Q        }4 [. V  R7 y. l$ g& u! h" y
        // MMC5
9 I6 ?! x; }1 C) W  M" H9 C        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* i5 G+ C" C+ v8 m8 l* e
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  e+ K# M. M- M1 N8 N
        }
/ c4 F8 c8 o7 ~6 c" G1 h1 C' m1 X        // N1066 [( S! R% ?' C' j/ E. s
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
9 F) v" t/ a) \9 E% E                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;/ R4 X; z3 Y- u& n8 [8 C# j2 D
        }1 M8 o& c* @2 `6 c& u
        // FME7
+ K1 Y' F# h& K) U        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* s& s7 Y6 y( F' L6 J9 h
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;! A2 R8 G2 v' z8 o& i; U+ K
        }
$ ?, E8 ~; m4 w  P  a% ^, u        // VRC7
5 j! U& r7 x+ z/ ?        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {4 v8 y" P9 p" W/ E6 Z, Q
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
% D! C' q% n% h, _) A2 Q7 }        }9 ~+ I  F* ?) ~$ {2 m
        return        0;2 E/ }8 c& E2 ]5 ]) j$ A
}" \* ^& J; P1 z; G- T) t  m4 x
9 R. C) ~3 ^& U" c5 P
// State Save/Load. ]7 C! ^2 I6 \
void        APU::SaveState( LPBYTE p )# s  K; N/ e  R9 |9 Q
{) D$ X, f& X) y
#ifdef        _DEBUG1 y! {6 r3 R0 t# a9 }! @8 s. o
LPBYTE        pold = p;
; r3 C# _* N. E4 ~7 o! G' K#endif' S0 w; O: r% Z( e3 X3 F7 M: b
( y# n2 l+ P( y$ P% ?% E! B
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞, k" f1 V+ Y  C, w6 o* O
        QueueFlush();! v9 O; n6 n( D2 w  q

+ N; u9 l6 I; o        internal.SaveState( p );) j! |# M  x2 P9 O
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% {4 d+ S. y( ~7 X
6 M0 y% O: X+ {9 r3 N
        // VRC6: I! j9 o9 m6 D+ O
        if( exsound_select & 0x01 ) {
8 H% X4 M2 U" |( D' u; @( W8 A' i9 l! x                vrc6.SaveState( p );: K* j8 R3 ~! o( S1 n0 b, e
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  ?3 `  K: m1 F+ `3 m+ c4 f5 I2 b        }! y7 x% G3 ~9 v: ?  U, t
        // VRC7 (not support)
- ?, S8 `3 j4 ]1 \) c        if( exsound_select & 0x02 ) {
- n0 O, b# m4 e( j                vrc7.SaveState( p );
- M) |" p$ t6 a- }# H                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- F2 i% t. I# a+ W) f6 ^; W        }6 |% S- I* b0 h
        // FDS
4 o* t# o1 i2 K& |/ M        if( exsound_select & 0x04 ) {
. s7 E9 B: c' J  K                fds.SaveState( p );. J0 r' o' s5 h$ `4 V
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
# Z) d6 Y  \9 X1 p( @' C1 a        }
3 n8 U. }" n# V. v# \        // MMC5% K7 [6 \5 H$ H$ p2 @! ?
        if( exsound_select & 0x08 ) {
( r. [3 p0 b) Q                mmc5.SaveState( p );0 m, T/ ]1 e7 x# x) Z! w9 _
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 K' M/ I+ c0 w. ~        }
1 A4 a2 ~  }3 s+ m        // N106
6 Y9 A  }9 M; p( H2 }; H& k        if( exsound_select & 0x10 ) {* S' E+ Y2 }" ]
                n106.SaveState( p );
/ y: C& g2 o2 T2 O2 N+ @                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 |7 h7 m" o7 Y  s
        }
/ g, x0 _7 W7 F4 A; _; \" v& t        // FME7
6 U  j) \) i: N; t* L% t        if( exsound_select & 0x20 ) {
  y- N6 n' q" C2 o# u+ |2 |                fme7.SaveState( p );' l# Q9 r( d( S1 K# e5 i  \/ n: N0 E
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ F' X! t9 U: q
        }2 ~  p9 U8 U4 B+ A* ~% I
' q2 |& a0 G$ w2 ]
#ifdef        _DEBUG
. N! P+ I; B; i2 wDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );$ ], ]# Q$ l7 {; L* H
#endif2 g& N: K4 a& O5 \1 v
}
9 e9 D1 K3 r- d5 p1 X% n8 U4 k& v1 h) u/ _9 L, Z" Z4 M
void        APU::LoadState( LPBYTE p )
: y+ w1 d0 j% l{
: s  {1 z; X5 v3 @+ [( a        // 帪娫幉傪摨婜偝偣傞堊偵徚偡8 K  e, R8 K9 U1 J, G9 p# o- `
        QueueClear();6 x, R5 y" j- Z: q
* V* B, x2 }, ^1 M7 Y6 o
        internal.LoadState( p );7 H  ~+ e- {9 w# |' L. m
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 r# L8 W4 W/ O* o2 P( K. t# W: O
        // VRC6
5 F/ A4 _5 }7 P& r% X( d# L        if( exsound_select & 0x01 ) {
% A$ j" |+ p- o! a$ E4 E                vrc6.LoadState( p );/ }7 e; i% z( x. @( i' v
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
1 N. P! E; d; N4 t        }
6 E+ _& C. G; e6 o        // VRC7 (not support)
: Y3 B3 o* l* @" D3 @* ^- \        if( exsound_select & 0x02 ) {! ?& b% s* }9 x4 o+ v
                vrc7.LoadState( p );6 Z7 h# X$ H" H4 |! w& @) ~
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* j( i4 D6 D+ x% v        }5 q( H. F* n: y5 ^
        // FDS% o- U4 v! l1 Q
        if( exsound_select & 0x04 ) {8 F& W$ W& [' v8 a; w
                fds.LoadState( p );
! g8 C) V$ A* G6 C                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding, d; M# T& N# N  b6 N: C
        }4 N. p$ M/ j3 |' p$ h; A
        // MMC5
- s2 H7 ~! W" I        if( exsound_select & 0x08 ) {
5 I4 V2 U- V( w: E5 C' x+ |                mmc5.LoadState( p );. I1 O( g! m" u3 R
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 \4 i  Q2 [1 _; ]7 O
        }
5 p( W: \4 w. p5 y- `2 n4 ^4 c/ {% I        // N106! i( D( N; n) [7 l% P3 l. v# n
        if( exsound_select & 0x10 ) {$ \! ~+ A3 \# A5 \' y* c" `' v6 ~
                n106.LoadState( p );( k) u: P5 B0 ~# R3 f9 D
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( f/ y2 V$ c6 M  j
        }
2 B) ?9 n, ]) k/ P+ h5 P. a$ ^/ c- N        // FME7
2 @6 Y6 ^. a8 {) D0 b7 L        if( exsound_select & 0x20 ) {7 z8 a' F; y8 G- L5 K' J6 I" Z2 C, q
                fme7.LoadState( p );  B5 [1 J, N; b% V. X
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding% g3 E* t2 U2 x' l" V9 V
        }. K0 t+ v& e& V0 v: g- f
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 0 z0 G4 M3 h0 V% _2 j  ^& D
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。  `9 H# C8 `4 o
感激不尽~~

9 C! e3 V- p0 d3 R# g恩 我對模擬器不是很有研究,) o  Q) H1 n# g5 R) {6 r
雖然要了解源碼內容,可能不是很困難,+ K% A2 I* i  h
不過還是要花時間,個人目前蠻忙碌的。
2 q( J! h3 N* ?1 D8 V7 }* }
+ ]+ y7 a+ E! |9 D給你一個朋友的MSN,你可以跟他討論看看,: X  f# d, w- g7 x/ x
他本身是程式設計師,也對FC模擬器很有興趣。
! r5 E6 V, _) A( o( P
  l8 m; Q) T1 A3 c* ]; I* o) p/ W/ {MSN我就PM到你的信箱了。
$ V  B: A1 O% }5 q; E9 `+ x5 ~. ^7 [7 O- r
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
$ s* D$ j/ e5 S: g! B' D/ l+ [呵…… 谢过团长大人~~
: o0 D" O1 Y( R3 z

/ O/ l  Y# |7 T5 G. Z6 ]哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ ~7 |6 `0 F+ Y" C8 i( G% j/ X团长的朋友都是神,那团长就是神的boss。

; M8 P. {. s- ]) X, v. R8 V哈 不敢當,我只是個平凡人,
0 D- Q% l: m, f要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
* ^4 h5 U; b: u; r& R) B4 z# sZYH
: U( U4 g; R3 h* |# |6 ~& v# tQQ:414734306* b' U$ X! M" q* g9 D5 T# A
Mail:zyh-01@126.com8 V" f, t, i( o/ a

2 N6 H8 b* P# G4 s他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
% y& o! c7 `' O. @! P, x0 u# I! k再次对团长大人和悠悠哥的无私帮助表示感谢~~
8 l: M+ i+ I  O* E
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-3 19:31 , Processed in 1.094726 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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