EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 T9 v& r3 a2 r4 j1 M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
2 ~! ?+ O/ j2 F# u9 H" W这里有相应的模拟器源码,就当送给大侠了~~
7 o9 F) N1 Y+ P8 Xhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
* B; V$ V4 ?: Z& U& T% X- ^3 n能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" ~# ?7 A6 i% ^
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 ]  d: J; w( n$ O+ v
这里有相应的模拟器源码,就当送给大侠 ...

3 h) R  h, E% H* d* i聲音部分(Audoi Process Unit = APU):; @; X2 p( C7 e
.\NES\APU.cpp
, A* V+ W. {0 Q  j9 N! E- T; c# P% l.\NES\APU.h
0 \+ u0 i8 @4 t, a7 U* V4 `0 L8 y3 q9 t

( j5 ~8 D( a  C9 A影像處理部份(Picture Processing Unit = PPU):) s/ R3 r. ]/ l5 X, G) c4 @
.\NES\PPU.cpp3 e) p/ |; Z! w6 U% Y
.\NES\PPU.h
' n' Q* _! W% m/ D; K7 T- e" H+ ^% t
0 v: I# [6 M4 o: h. T如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
) m1 W* K: j5 o& B& }, Y6 C/ O(由于很多专用术语和算法机理都不明白,所以看不大懂……)0 \. _- _. v+ q" ^! |: u
//////////////////////////////////////////////////////////////////////////
; J; W) C0 t0 u' o1 ?" X//                                                                      //
3 b4 j) M7 c% K7 F//      NES APU core                                                    //& U8 N! y$ [& G' y+ \
//                                                           Norix      //( a) E& |7 U$ D- V+ v! Q
//                                               written     2002/06/27 //
, D, p  H5 k" n2 x//                                               last modify ----/--/-- //
3 e3 x0 H  O* I; C* i! G, T//////////////////////////////////////////////////////////////////////////, F" j/ O% t  K# q1 d& a# G0 N
#include "DebugOut.h"4 M% t* t  j4 `! I+ b
#include "App.h"
& v5 W+ \- z+ M2 S" s' A#include "Config.h"
3 N; m7 K8 M9 o+ i5 g9 x9 L+ j; ^: j# b* t' d
#include "nes.h"0 G( Z2 [1 @5 A) d% K
#include "mmu.h"' x7 R+ ~8 U% a9 v
#include "cpu.h"
8 ]9 }% [" O6 v. b% l- O1 {: S#include "ppu.h"
% s0 @" D: Q+ _#include "rom.h"0 j4 c, F" e' v$ v2 `) ^
#include "apu.h"
4 B/ i% g$ u3 \9 g9 B8 g! r7 j
% G& a5 l; z" w7 ?( O/ V9 L0 A0 h// Volume adjust5 n1 ^/ c1 `6 H8 z+ e) G
// Internal sounds6 J+ S0 E" M. C5 s/ M, X8 q4 k, f
#define        RECTANGLE_VOL        (0x0F0). Y3 Z2 ^' K$ P8 J: L9 a
#define        TRIANGLE_VOL        (0x130)
; _- v" h+ D+ `& r#define        NOISE_VOL        (0x0C0)' q8 q1 j4 @4 t7 |- N- M
#define        DPCM_VOL        (0x0F0)) r- ?$ \) x# y
// Extra sounds5 k7 W9 z; H) D6 s
#define        VRC6_VOL        (0x0F0)
: K6 Q. ^; W# i* @( t#define        VRC7_VOL        (0x130)
1 i. @. }3 q. Q5 b. T#define        FDS_VOL                (0x0F0), B- H' s, T* F
#define        MMC5_VOL        (0x0F0)8 d# V" s* b, |3 N, ^/ Z: E" w
#define        N106_VOL        (0x088)
7 W3 f- I! x% H#define        FME7_VOL        (0x130)
' d/ C  i0 K( L0 i+ a$ B, x, S
( W& G$ y0 L  n, }APU::APU( NES* parent )
' z. o) r! I1 G{$ n8 X: u6 Q: h& F
        exsound_select = 0;- W8 d9 T+ `8 o0 J5 O
1 R: l! v, F9 g0 Y. a
        nes = parent;
9 C5 K1 O' b1 y; C! `5 q( G        internal.SetParent( parent );
" t. p+ h  F( p; ]  l+ |" F7 Y7 b+ g
        last_data = last_diff = 0;0 j6 s( f; o& W1 m# O% \# Z
8 o) D( m: J/ O2 W2 @; {+ S
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );! O  o8 l7 M- F& }( r8 x

, e& e4 r9 a+ `" a        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );: l5 e: j0 n! J  N5 b
        ZEROMEMORY( &queue, sizeof(queue) );
# l6 q/ `- ]; r; }" W6 U' d# b' R        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 ]' s8 W5 H+ ]% f# z3 _
' j, h% p6 V( T4 I! m- ?        for( INT i = 0; i < 16; i++ ) {
; E/ P$ ?5 W! W* |& |( W                m_bMute = TRUE;
+ s8 _' b4 I6 U* ?1 m% ^0 q; t        }
, f) d: v! }. V# {* t) R) [}
7 S. m6 \/ k* k/ f$ i: h% h$ w' u. {& v" l
APU::~APU()
, J) Z) a. Z' M  J: L- S{
6 J, ~; M) U7 x; ^4 e2 z! g% n}
' q* O7 X' r9 o& i8 l( [
- @4 P& s2 b! A4 ^void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
5 u( \/ u7 B' n% L9 E# s3 \( K{
6 K  n/ p9 ~! N& ^% O        queue.data[queue.wrptr].time = writetime;5 Z/ p2 m  `) ?  |0 M) H. b: j
        queue.data[queue.wrptr].addr = addr;
- Q; s8 x3 V3 h, B        queue.data[queue.wrptr].data = data;7 \! X8 l! @* q
        queue.wrptr++;
6 f2 \- d, r( @3 j& h1 z, @        queue.wrptr&=QUEUE_LENGTH-1;
" b7 V* Z+ E& f        if( queue.wrptr == queue.rdptr ) {
% e  s. q  K+ v  @. Q% E1 G                DEBUGOUT( "queue overflow.\n" );
. K# W, B& \' V        }+ s, i/ `# y' E7 @$ u2 g+ r; B
}2 d8 Q2 K+ I6 t! G2 i0 [9 M
+ M* c/ s( R3 i0 x
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )6 V& }0 K7 w1 `, G  M, W
{0 n& l: {' l/ N
        if( queue.wrptr == queue.rdptr ) {# m% Y: R+ P) G% V/ h5 P' C
                return        FALSE;
$ u- \7 r( {; O8 w4 b& {2 H        }
( N9 D' y4 }' ~# c        if( queue.data[queue.rdptr].time <= writetime ) {
  S1 ]* v0 K$ F1 X$ u                ret = queue.data[queue.rdptr];
8 r$ m4 G+ f% D+ @                queue.rdptr++;
3 \4 j0 i' D/ {6 B4 t/ j                queue.rdptr&=QUEUE_LENGTH-1;
) M6 h: ?% ~7 H+ F' _8 C                return        TRUE;
# D4 l/ n! T0 @' E% n8 [$ v0 P        }
! n+ Z0 E) C/ P* Y        return        FALSE;
3 q6 A  `# Y" b& y( C, \* R}, B5 n" q$ c7 x1 H, {) a/ j
+ K% b- F, z) |  g9 P7 h! y' t% E
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
/ y# @; r. I$ X3 |0 {4 u' s+ t6 ?{
1 J& D* [3 ^4 U, y2 i% b        exqueue.data[exqueue.wrptr].time = writetime;' M$ I: z' u0 [. H) i: [, j
        exqueue.data[exqueue.wrptr].addr = addr;/ `- D# m" i/ ?& e! K4 S
        exqueue.data[exqueue.wrptr].data = data;4 d/ _( \0 z+ E' Y" i" Z2 u- w
        exqueue.wrptr++;
' f( J- i# t5 `, J0 A# }        exqueue.wrptr&=QUEUE_LENGTH-1;
" W( A& y" {7 r. \: ]/ k2 V# {        if( exqueue.wrptr == exqueue.rdptr ) {
! B, j  K- S. [+ v6 o% y, ~                DEBUGOUT( "exqueue overflow.\n" );
' K' E) m) ?4 R. u0 V        }+ x6 R" p; C4 I+ T- }$ S& p
}
: N: B; y' r& y1 H  n' q7 e
6 w5 J0 L$ M' j/ p1 m0 cBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )7 T) h( c# `( a7 h( n3 b
{+ l$ O8 w- q. _. a% N7 b" ?
        if( exqueue.wrptr == exqueue.rdptr ) {
, z* ~3 {$ c/ ~" k: X! n                return        FALSE;1 N. r5 z& f, K7 y. D" ]: O2 L
        }
; D: \" _5 \5 W2 I5 G" F6 `        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 k- {, z, C0 s( n
                ret = exqueue.data[exqueue.rdptr];8 R6 Y5 q1 L/ F" s4 \
                exqueue.rdptr++;3 _7 X+ B' Z9 _. g8 g
                exqueue.rdptr&=QUEUE_LENGTH-1;
, m( h/ H. j  E0 L9 Y$ P' \                return        TRUE;. C% P9 N5 X/ ?) s0 d
        }$ u( a! x5 _. U2 d/ H4 u8 p
        return        FALSE;7 h$ y7 Y( T+ G% m, o/ @
}8 m1 r( r4 ^3 y1 R2 {. S0 a1 h" J

8 i* w9 @5 r2 z8 y: V% Zvoid        APU::QueueClear()5 A0 t8 x$ x: q, D! F6 @
{
, y7 N  j* {, x$ F2 Y* z/ L* E9 e        ZEROMEMORY( &queue, sizeof(queue) );4 C5 g' k* l) A3 V2 H4 H
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! s  W% N8 _0 U6 r0 [: K}
4 ?: U5 L/ x8 T2 G8 `; h# C3 \  N6 o1 [, k* \" B7 z! {- H) r" Y
void        APU::QueueFlush()# d( Z# x& P; S. B8 B/ ^
{
1 L3 v/ I; O3 i( f2 @1 u! b% v        while( queue.wrptr != queue.rdptr ) {
! C0 c0 K: `+ U                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) ^, G) J5 W, H
                queue.rdptr++;# P" _" t6 a0 _# r+ E) ~
                queue.rdptr&=QUEUE_LENGTH-1;5 E2 x2 O8 Y* f& Y8 f" |7 P* e
        }
$ O, j, m' L0 }9 ]& V. N/ i" r( k- h% G3 z  M
        while( exqueue.wrptr != exqueue.rdptr ) {
: _) X2 o% L! x' G# W% F                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );8 ?$ `. Z) r1 a# D& k
                exqueue.rdptr++;
6 j& Z+ R- D( T( v5 J' T% ^                exqueue.rdptr&=QUEUE_LENGTH-1;
$ f: t, n, h1 [        }' q  B9 P  B3 b
}/ x& i: U) @) A$ E8 V+ b+ u8 `

" O" o3 H! V# K( B1 B, Rvoid        APU::SoundSetup()  ^6 I2 c9 n  |: D( v
{, _  c; N7 ]+ |# k) O
        FLOAT        fClock = nes->nescfg->CpuClock;
9 {. K6 u9 a' f2 C' m        INT        nRate = (INT)Config.sound.nRate;2 e9 c! @. r/ U! D
        internal.Setup( fClock, nRate );% h. _" t9 D6 |7 N' `' o: k
        vrc6.Setup( fClock, nRate );
: O8 ]4 l: \" F9 w5 [" g+ R        vrc7.Setup( fClock, nRate );' C7 J6 k0 J' i; v2 `5 h
        mmc5.Setup( fClock, nRate );
& v  i4 Z  b, V8 ~: I- X        fds.Setup ( fClock, nRate );! G  X/ K- f( U/ X
        n106.Setup( fClock, nRate );, `( m: @! l) k" P/ N' e
        fme7.Setup( fClock, nRate );, c- A7 u/ v8 T5 A% B
}5 U' X/ A) p. n5 K9 b

0 I' Y- X- {: b; w. [% C+ L! Ivoid        APU::Reset()
  p4 ~/ D& R6 v{8 P) C. e3 Z0 `# z  a6 l7 Z& T$ y; [
        ZEROMEMORY( &queue, sizeof(queue) );
: o2 d0 e) S. O+ t* p. t        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' B( g; i5 [$ K7 b$ T
3 _. X! B+ J5 [4 c% n        elapsed_time = 0;
+ e! i8 |  S5 ]% T% f" c# a# ~! _: V. H, _/ o* \8 n) N
        FLOAT        fClock = nes->nescfg->CpuClock;+ _3 c8 g& I. Y# Y3 ~
        INT        nRate = (INT)Config.sound.nRate;) d1 i8 ^' u3 w" l
        internal.Reset( fClock, nRate );
. R( p- C/ u& ]+ D. p+ V1 r        vrc6.Reset( fClock, nRate );
* l6 W; h$ Y/ ]2 R" R4 o        vrc7.Reset( fClock, nRate );
0 }$ F4 [. c0 g; {: d        mmc5.Reset( fClock, nRate );4 t2 K* T# H; F# |4 J" ?
        fds.Reset ( fClock, nRate );0 s/ C4 c; c: y' Z7 u
        n106.Reset( fClock, nRate );
0 N& E$ I2 Q( X# o  G# ^1 u% l# W% A' @        fme7.Reset( fClock, nRate );0 _! G+ C, Q8 z, n: J8 s

9 J9 L& @6 c5 m. u, F9 Q- U$ \1 U) t        SoundSetup();* a' t% Y* q3 C5 D3 r1 P
}7 ~  T& v1 l+ f1 d
# z0 L3 z' |8 j5 Z0 b6 V6 C
void        APU::SelectExSound( BYTE data )
4 Z6 e/ L+ h4 z& k. V- j, A5 g) e{8 W! K( t0 k" n( c) t! d0 z
        exsound_select = data;0 P: O) @2 S. j5 s; Z% n4 Q
}/ v, k# R2 Y/ \9 L3 V% `3 U

8 A3 X/ M; g/ h6 ]- y; jBYTE        APU::Read( WORD addr )
" l. |& ^" @* w: L* C{
/ r$ T4 g! \. |* K  y  F        return        internal.SyncRead( addr );( ]  f7 a" K4 O) n# x( T
}
7 F9 s% j2 M  N- |3 ^2 w$ \8 M! U% K. n# r5 G0 D' m
void        APU::Write( WORD addr, BYTE data )! U8 ?2 u1 e9 q( n
{
$ u* _7 E" K, i" w4 U; c        // $4018偼VirtuaNES屌桳億乕僩6 ~7 a; F- i$ |% Z
        if( addr >= 0x4000 && addr <= 0x401F ) {
( A) `( O9 @6 v2 L# D                internal.SyncWrite( addr, data );: F$ [- n: C& J8 ?
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );$ ]( z! b. W( K4 d! |$ G9 o# T
        }7 i' e0 e  b1 p+ i- S/ U' j( y+ h8 J
}
  F! Z: z* Z- ^7 r5 O! H
7 }/ Y3 P% P  R. H  Q0 C" `BYTE        APU::ExRead( WORD addr )
, A' K4 G7 X, u  s: s{  n/ B4 Z" w3 F8 ~$ j5 W+ a6 H
BYTE        data = 0;
2 X: Z/ |/ v. X" Q5 q$ Q" T+ G" O2 u# y/ G- T
        if( exsound_select & 0x10 ) {" ^. r6 l' c# T
                if( addr == 0x4800 ) {
6 {+ R: X3 i7 K' d( y' l                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! i3 b! l0 @+ `5 ]+ S. x6 e
                }
$ [! F( m( e7 |+ D* Q        }- l6 v6 y' ~$ m& V+ s4 j
        if( exsound_select & 0x04 ) {
1 F% Z; n  d0 M5 h6 {: y1 Z3 h                if( addr >= 0x4040 && addr < 0x4100 ) {* c) N1 g: r1 l* W! C5 j
                        data = fds.SyncRead( addr );/ e5 ?% }3 W1 Z  ]5 _! X6 ]
                }8 e- Q2 h! {) Q6 U+ }; K
        }. N- y; m5 U3 Y/ ^5 C" @( `
        if( exsound_select & 0x08 ) {; Y9 s* `7 D1 ^, T2 a- p1 Y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
" F" [- K9 u: w" R) m! r                        data = mmc5.SyncRead( addr );
0 F- x" N% {6 `" d                }
" O$ p* m+ T+ y        }
. K- b* N2 n+ m2 n8 h: Y
/ f( t) l- {/ V& F& u8 n( o        return        data;) Q! W2 U' |4 \* O) [1 M0 P
}0 @. X4 \8 K1 R" j: m0 J3 l

2 U; V9 |4 n1 b# X/ S  m; I9 }void        APU::ExWrite( WORD addr, BYTE data )
& q- ]5 g0 u( V{
7 \$ ~" k8 x& }' h        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
9 k) |3 _( T7 i+ ?. O9 U/ G( j! H  ~, e
        if( exsound_select & 0x04 ) {
5 J8 c6 f, C2 o4 X" G/ K$ x1 C                if( addr >= 0x4040 && addr < 0x4100 ) {. Y, c! ?5 Q# a8 P9 l
                        fds.SyncWrite( addr, data );& \! C9 G% }9 {7 b; C' C
                }
( R3 L* d& i# g: E        }
% |) `) ^" `8 _- Z; r7 _- |2 F  Q+ m
        if( exsound_select & 0x08 ) {6 p. \3 i% _2 ^/ a4 J
                if( addr >= 0x5000 && addr <= 0x5015 ) {- U( l: \7 e3 {+ W1 L
                        mmc5.SyncWrite( addr, data );" i/ |- i$ a6 z' r( _
                }
& t1 f, R. k9 h" |% `7 s        }- L8 v  k, b# b( I; G
}) |4 Q$ f! k% z" w( M% s
9 S+ K; p! b3 S4 o" @; [9 U; o; K
void        APU::Sync()
  U! }$ p! w6 J) Z4 \2 _9 y& g{/ @  l  c: o- `3 \3 ]
}
& G; G! ]3 W: A, I4 S0 `# v' a; W8 o/ m  {
void        APU::SyncDPCM( INT cycles )
" i$ a$ V; ]% ?4 G+ U* Z6 R& R2 b{* k9 V7 l2 J- k/ v* P5 i
        internal.Sync( cycles );( K& p6 h. y( F" T% L

/ ?, Y: E; l/ H: t4 ?# Q. H        if( exsound_select & 0x04 ) {
' ?2 n$ T& K$ K                fds.Sync( cycles );
0 _5 c3 T! h5 k- m! ?        }4 e6 R0 `, H: l, x2 F
        if( exsound_select & 0x08 ) {
; r5 b* v% |0 Z3 F( a+ z5 O                mmc5.Sync( cycles );; Y6 T3 g8 t. \% c3 L7 @, V4 R% K3 J
        }
3 D+ e7 E* }4 Z$ L# T7 i}- g4 s. O  O) m8 @1 j; t

$ E+ x- X% e8 K6 |$ U0 {void        APU::WriteProcess( WORD addr, BYTE data )
$ s! ~' a, f7 L( }- }{
$ L( K) a- V6 B' m/ p* ?; R        // $4018偼VirtuaNES屌桳億乕僩- J0 x8 k$ F! i! o& e# u3 `. J4 \
        if( addr >= 0x4000 && addr <= 0x401F ) {0 o% E  y: q; E. i; ~: g# @* w
                internal.Write( addr, data );
; s3 F; s% A! [% q/ O" m        }' g# q" p0 h& x# Q1 r. O) {
}
- k& g" B7 q& O# f" h' W6 Q7 ]& J/ g' c9 q. G
void        APU::WriteExProcess( WORD addr, BYTE data )7 S4 r( e2 W6 x( Q
{
# \1 U5 z+ ]2 m: q        if( exsound_select & 0x01 ) {
9 f  ]" _' l" o                vrc6.Write( addr, data );
6 p( l3 Q# v  D8 u- H, _$ d  f        }8 ?0 S+ @, o4 S  X4 H
        if( exsound_select & 0x02 ) {
+ ^- L9 S9 n0 a" e& Y/ P                vrc7.Write( addr, data );
( O2 p- |, p5 s% l4 Q        }3 o' e2 v: Z3 f+ ]/ u: o
        if( exsound_select & 0x04 ) {
4 C4 I% O4 r/ w+ u3 ?* `                fds.Write( addr, data );
5 b5 R; C( v6 U- N7 ~        }/ L) V4 Z4 e/ d, s/ R2 w
        if( exsound_select & 0x08 ) {
/ {) J& B$ V3 a- u8 v/ p3 q                mmc5.Write( addr, data );; w5 ]( Z7 e$ ?5 H" c1 t$ u
        }
3 Y. m% z7 R6 y9 c1 {$ _3 ]! c        if( exsound_select & 0x10 ) {
# x9 B; \; T) l" b; M. S                if( addr == 0x0000 ) {
6 q% R' q' G9 ?; g1 A1 {# ~                        BYTE        dummy = n106.Read( addr );% I5 \9 \/ d& ]/ A% r% K
                } else {
* P5 ~  \& M2 H. f" T1 X                        n106.Write( addr, data );' W6 R1 c% f: ?. V
                }! C0 `& F2 w. q9 }* E% Y
        }% y& T$ S/ K# F5 L5 q" h& {
        if( exsound_select & 0x20 ) {
$ s) T$ G9 k2 {6 }6 w                fme7.Write( addr, data );
/ ?# W4 D. ^( Q        }' h8 o* I' L, Y6 d' ]' a# {
}
& E6 f1 p; ~  I
/ \: F4 J" D- G) E6 Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 `( U& j2 {& A7 \* M& N9 C{
  a* W# _: x* j4 r! s# m4 WINT        nBits = Config.sound.nBits;
3 n: o8 Y1 g' p" s4 `* vDWORD        dwLength = dwSize / (nBits/8);
; X- v$ U( N! Q$ Z* t- Z% g/ sINT        output;
5 _* V+ d, Y0 N/ r0 cQUEUEDATA q;
1 Y: Z3 P3 r3 Q/ m; aDWORD        writetime;
# v" Z2 w' ^$ I/ w; @: L
% N& a* S5 ^+ S7 b# gLPSHORT        pSoundBuf = m_SoundBuffer;
3 l2 @  H8 \! h9 rINT        nCcount = 0;; t9 n9 S* J% m) N" J& ~1 d

8 l4 `- L5 G! n: A5 o9 G0 LINT        nFilterType = Config.sound.nFilterType;
/ z2 N  j3 S7 U- q+ e; j8 E5 J2 G7 g5 x- E
" d2 X/ x$ U) V% ~        if( !Config.sound.bEnable ) {) K2 T+ Y* q! q# J
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );) G8 ~5 F9 d, R; |; O
                return;9 G$ ?) |6 |+ b# B- t
        }
) s: P8 b6 R, Z" E' {/ B2 J: U+ @4 ?4 J9 G! \! n% K# m( Z# M
        // Volume setup
" y& U, u! |: |/ y1 R        //  0:Master
' x) ^( Y% H% k. M' Z! J. t& }4 C        //  1:Rectangle 1
% y1 \# c! b0 I5 s% N% V        //  2:Rectangle 2
# c5 K6 t0 ^4 K2 h+ a. j        //  3:Triangle. L' K, U$ T" P! e
        //  4:Noise! @1 o. s& H% o$ G/ F' h
        //  5:DPCM- \, H) C; m) O1 O
        //  6:VRC61 c! A' X% E* s% ^3 I2 o/ X
        //  7:VRC7
: l- a# Z! h+ N$ P        //  8:FDS2 t/ J5 L& U6 W3 l( }
        //  9:MMC5
5 U7 D1 Q0 w8 d1 D. w        // 10:N106
) J4 Z2 R* s. \8 ?) ]2 Z( w        // 11:FME7
; y- `1 h" D0 ?4 `        INT        vol[24];
& J4 ^' m7 ^/ R' U        BOOL*        bMute = m_bMute;
3 H! W0 ^- I' S        SHORT*        nVolume = Config.sound.nVolume;/ o0 r3 f6 h% M# p
" V9 R. H* Z: q8 C. F
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;7 e8 J( X7 k  r, N- b4 e+ G- L

( {3 ~7 W9 [$ N7 f; m        // Internal
8 T2 e6 X) ?. j: _& o- m" F        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;  B8 ^% J) Z* f' H2 }( w9 H' o" A+ |
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
: O2 P, N) n% M9 a( C        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- I/ T, G6 K$ l( L2 J1 B" y! y# Y
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
5 D2 G" ?: ]! i' a( N        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
) }; m& u8 |# {$ F3 u4 @
- W9 j4 K% X4 f+ g& Y        // VRC6' k- m9 ^' T! p" U" @( r
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 ?; E3 ^$ t+ }8 q# x        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% a5 X7 s" x4 M0 l
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 \- X, p8 ?* B5 H1 A$ E; g
& V2 g* y/ y/ M% H0 T" k1 ?
        // VRC7% y$ Y, o1 e! r8 Z0 b, T$ R/ _4 l, l
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
* }. G4 Y( F: O( G4 a5 \& E/ E( K3 `# X
        // FDS( p( V# \" f% S# i; o9 G9 n, ^3 c3 B
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
' q5 f* U' w- u* V  R: l/ D* i& r8 `3 C4 q+ e7 q/ i/ y. c/ A
        // MMC5
$ |  Q/ Q7 N$ e8 V1 f6 I" {" H        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ Q6 I9 \; k  ^% l- k
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ P2 m0 }) n- L. o' q4 t
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 |' n8 _9 ^4 o
' Y% X+ d5 ^9 N0 w; ~4 H
        // N106( E) U: W6 H( o& p1 Z: U
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% q" G  a7 h3 \9 y; k9 E        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 H  @; A& g" ~2 \& a& R  ]
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ m9 F( u+ N2 a4 y
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 a8 |- e$ ~6 P' y" M' m        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ x$ ]- d  Z! }" `        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 t/ @! ]3 n0 B8 X1 x/ Y/ m( t! k
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: Y! Q& x5 Y& c        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 M  t: g, A8 K+ _. }, {* R7 T* f
        // FME7
" u1 U, `& Z- P# j  |! [0 }7 o        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* q+ O; {! U; @% J1 ^: G1 O$ q5 ^        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 T4 D  e. Y0 e5 w
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* S3 e. p) v7 k& {
8 N7 S6 [5 M7 a4 M5 Q//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' x4 z) ^7 R' G! W5 z        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
  j. p* S/ t- q! I1 t# t3 Q7 [2 J, w- m- t7 V' O& `
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
: k- K7 j1 v: m7 u& O        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
4 c. _$ C2 V% ]0 {& z4 V9 q                QueueFlush();' R) a5 k: ~5 z
        }
: D, O: d3 I7 z8 ^& i! M2 a$ d9 X# N  _
        while( dwLength-- ) {
) B) S' _% b9 _7 M                writetime = (DWORD)elapsed_time;9 A" S& c9 o3 E

; ]8 c, Z9 f; o0 {! w                while( GetQueue( writetime, q ) ) {  y" z; Z9 W+ M4 U, J9 w1 I
                        WriteProcess( q.addr, q.data );2 S) ?) w. Z" k- G" K, f8 B
                }* K8 t( s! h2 f4 Q% A) ~1 T2 P
3 {9 O3 x! v: `! E7 o$ A# k2 U  u
                while( GetExQueue( writetime, q ) ) {
2 y2 d6 ]  g; ^; y2 i/ v0 C& Q, E/ P. B                        WriteExProcess( q.addr, q.data );; Q! ^( {, x; W3 ~% W
                }
8 z, {& u2 b) P' a
2 \3 v% k" a1 v                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7# O) t1 K/ B7 e* L+ V( m
                output = 0;* H7 G- z9 I: C+ T: i
                output += internal.Process( 0 )*vol[0];
6 x* c; C4 V! R: f" K$ G                output += internal.Process( 1 )*vol[1];0 s) h# ~0 B# o* b) M
                output += internal.Process( 2 )*vol[2];
: s' a' S) L) ]# ?2 ~                output += internal.Process( 3 )*vol[3];
& I9 H: S; u& y0 R  ]                output += internal.Process( 4 )*vol[4];
4 m( N+ J2 H3 i9 t6 f- r5 Y$ A/ I2 m+ r9 w. f+ L6 C
                if( exsound_select & 0x01 ) {
" K* ]1 I. ^! M! ^$ |                        output += vrc6.Process( 0 )*vol[5];
, \7 {% X6 P9 M                        output += vrc6.Process( 1 )*vol[6];( g0 O7 S+ n  b4 X  N
                        output += vrc6.Process( 2 )*vol[7];( e+ I7 V0 S3 g! q4 T7 V/ h- P0 g
                }
' o/ V( d, y! [% a  ]                if( exsound_select & 0x02 ) {% W; [! @% X6 O. ^
                        output += vrc7.Process( 0 )*vol[8];* I/ z: o5 j1 V% @* ~
                }! V# a) [% H$ u, n" \, r6 C
                if( exsound_select & 0x04 ) {5 L; X# O' Z* j/ ~% Q
                        output += fds.Process( 0 )*vol[9];
- U, u' G5 }& I5 o                }
9 f& Z5 @- U& r% U( y8 M. a3 n                if( exsound_select & 0x08 ) {+ Z) v* }7 D( [; Y) X
                        output += mmc5.Process( 0 )*vol[10];
+ \4 u; ]  a3 f                        output += mmc5.Process( 1 )*vol[11];
6 K0 `7 o, l* @- u/ I% G# ?4 o                        output += mmc5.Process( 2 )*vol[12];% l& ~( q5 B: d. D1 h$ g( f8 d2 }  T
                }
6 P) A1 }3 V. q1 X: f3 _                if( exsound_select & 0x10 ) {# E0 a4 e0 z& i, B
                        output += n106.Process( 0 )*vol[13];; R  g6 a( R& r1 F
                        output += n106.Process( 1 )*vol[14];
5 k) B  I. E8 S0 I5 y                        output += n106.Process( 2 )*vol[15];1 K2 ~; @- ^! j, y$ b- j/ L
                        output += n106.Process( 3 )*vol[16];
! d7 i# q" M; x                        output += n106.Process( 4 )*vol[17];
  A6 d5 X0 X. M1 d9 X                        output += n106.Process( 5 )*vol[18];; P) W7 o( `) U- d
                        output += n106.Process( 6 )*vol[19];
, ^( T" n3 F# h% D' T9 a, T1 [. B                        output += n106.Process( 7 )*vol[20];
' m3 F' S0 F9 a- ^1 {0 A3 f                }
" j! ^1 }$ p& Q. N5 K8 U                if( exsound_select & 0x20 ) {
& [% n3 g  r) y$ h                        fme7.Process( 3 );        // Envelope & Noise
, y9 I2 g! L% G                        output += fme7.Process( 0 )*vol[21];( l& p& q4 g1 x3 A6 [4 w9 J
                        output += fme7.Process( 1 )*vol[22];/ Z; s; t& v8 v9 @9 Z& i+ X' T
                        output += fme7.Process( 2 )*vol[23];
; `5 b6 y% G9 h' A6 ]                }2 n) ?* v" x. ^8 M7 B
7 Z  |9 D0 q: z0 T& P% T0 R6 C
                output >>= 8;% H5 Y2 M" H$ `

5 Q2 d7 V1 Y* o                if( nFilterType == 1 ) {6 R" j5 z2 w- x0 h4 ~" o
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& F, q' X' J' y) `! l8 d" s0 u3 R
                        output = (lowpass_filter[0]+output)/2;
5 M+ n7 p% N0 w0 G/ u- e+ r9 M                        lowpass_filter[0] = output;/ |2 g4 S) i3 J# x5 n+ x& S! P- D
                } else if( nFilterType == 2 ) {
1 E, W3 E. J4 u& @/ ]$ U: W" X                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)2 I! Z0 |# E) T: ]! ~; F3 v
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
" W8 h, J3 I$ R* |( A: z, S* j                        lowpass_filter[1] = lowpass_filter[0];
* a7 @$ x5 i, [0 A: y9 o                        lowpass_filter[0] = output;
- j# f) o9 C0 k( t/ O; t- F                } else if( nFilterType == 3 ) {" o- x/ X5 A6 }% y: o# O
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)1 e: n6 J# l3 N! R! h3 Y# O# H
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
% _7 h. _& f) P; E- n                        lowpass_filter[2] = lowpass_filter[1];
' G* F3 \0 {% K8 f1 X. S2 k+ }                        lowpass_filter[1] = lowpass_filter[0];
9 v$ m; C/ p" q                        lowpass_filter[0] = output;
3 ^& j* w" A& ^$ K! i8 C                } else if( nFilterType == 4 ) {) r; q+ D! U: C9 @, j
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
2 }" g* k* L; \' H2 |4 \3 j; }% @                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;% N, c1 l9 z2 I
                        lowpass_filter[1] = lowpass_filter[0];0 R/ P1 {: B* J1 F; u1 x
                        lowpass_filter[0] = output;
- n3 X8 y  l5 e2 b" m                }1 X8 X: e1 J* R* S* R7 I
0 n" p) u4 v4 U& e: |, ?2 q# T1 G
#if        0  S: Q9 t8 S, D9 J" m4 g
                // DC惉暘偺僇僢僩1 v7 h$ B( N0 c1 g# q+ w, L
                {5 U: I3 H; B/ L
                static double ave = 0.0, max=0.0, min=0.0;8 ~7 a& y) C) m- V- A7 o1 _
                double delta;
$ k* h- |' j- z8 g4 x, i% P% N                delta = (max-min)/32768.0;$ c( R! ^% H. Y
                max -= delta;* j# H! ]% x, r1 e( F. }8 p; O3 D5 M
                min += delta;% r  d. c: Z$ _  Y3 ^% ?
                if( output > max ) max = output;
% }# X& E8 z  }                if( output < min ) min = output;
/ k% o. v, e8 s" T" t( e                ave -= ave/1024.0;# l* ]7 s6 F. O  w- @
                ave += (max+min)/2048.0;# A) H" |1 k) \
                output -= (INT)ave;9 ~5 W9 ?' ?; {( u" R4 l' {( s
                }
5 a: `0 Y1 [; l( O3 ]* ^, Y#endif
3 \& h! C5 q2 }% Y+ U#if        1
6 R# z5 e/ B4 ?  |7 c! ~, l4 {! l                // DC惉暘偺僇僢僩(HPF TEST)
# ^9 x) Q8 V% h* ~  s* @9 {: P  O% p                {
! j+ K% Z: `9 I7 l# ~6 b$ j//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);  J5 r9 @* l6 I0 ~: X" O8 E/ D2 [
                static        double        cutofftemp = (2.0*3.141592653579*40.0);- c8 s: I. j1 U
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
) a" [4 T3 X2 ~" I7 q                static        double        tmp = 0.0;7 {$ \+ L# e2 ~8 ]
                double        in, out;4 Z; U! y' y2 `( T
  U+ @! r/ [3 d4 [8 E- b
                in = (double)output;' A3 f+ V( c$ B6 \+ O
                out = (in - tmp);$ T; k1 `6 U  N& x" Q+ \
                tmp = tmp + cutoff * out;- ?7 }, d: b: k) w) x0 d3 D
' B5 p' A3 S) @. W
                output = (INT)out;" Z% U7 ]0 e: \5 x$ X5 _1 Q% x
                }: T- E- e  Z2 \7 w9 `
#endif& e* L$ X2 w7 m2 \' T
#if        0- X( a: r, q* C! q. h
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* v# v( V3 S; N8 k# r, E3 q, L: B                {2 ~8 x" r2 T; O7 |  h
                INT        diff = abs(output-last_data);
4 h# _9 ]* I8 X9 [3 B9 c7 q                if( diff > 0x4000 ) {0 X& i4 D9 Z' _* L6 l7 l
                        output /= 4;
0 O- s6 J2 i: Z) d- J: a                } else 4 B' A& d4 g! r
                if( diff > 0x3000 ) {
$ b3 F7 }4 s- w# F                        output /= 3;2 p3 e, b: z, C: ], Q$ Z$ h- [
                } else$ {: r  }( F9 k
                if( diff > 0x2000 ) {) Q+ V/ v. Z- M7 Y
                        output /= 2;
/ e5 h+ p2 f7 E; j; x9 F                }/ {8 N3 W! i0 S3 {1 `/ L6 t7 C( e% t
                last_data = output;' N( S1 _) l+ ]! C0 b2 _
                }/ A. T8 y9 H4 l" J; w& k
#endif& F& M7 ^1 q6 M6 N
                // Limit
9 W" V+ m% {: }5 ^  J# g- }* O, K                if( output > 0x7FFF ) {
. m$ R) t0 n: k0 [/ N1 X                        output = 0x7FFF;* l; j& o2 w/ b" i5 S1 K4 W
                } else if( output < -0x8000 ) {
' p6 y$ ?0 l0 b  D7 e; ~                        output = -0x8000;; w* g$ R3 L1 \2 a) L8 G3 l
                }
1 c$ A. G6 m3 u* m$ X, i
3 }2 d8 o) r; d                if( nBits != 8 ) {$ N( U! b' `* B$ V
                        *(SHORT*)lpBuffer = (SHORT)output;4 ?0 x0 S  H5 I2 z3 ]5 H
                        lpBuffer += sizeof(SHORT);
% p* m9 p" Y" G$ z* P$ l                } else {
5 v5 @; \) @2 W; d/ z/ j! W5 b                        *lpBuffer++ = (output>>8)^0x80;
8 j! b( H" g, M; g$ |! r4 f                }0 W+ r5 t6 }: n2 b8 l1 N
; C. f2 A, o: i# E+ c& |$ `
                if( nCcount < 0x0100 )7 Y, f; F+ p2 D: O
                        pSoundBuf[nCcount++] = (SHORT)output;( Y1 k  r; g. f) `3 l

0 T# h; {$ @. j! Q: ^//                elapsedtime += cycle_rate;
! a" O+ h# \2 D                elapsed_time += cycle_rate;% J/ \) o% c6 t0 T- B
        }5 F: r- f! C. h. E0 h

3 P& g( \/ z' A9 E8 m#if        1
, m0 q3 q! U! G        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {( l  r5 [3 K% q. f
                elapsed_time = nes->cpu->GetTotalCycles();7 B; _3 i. g/ M- Q/ A5 F$ k+ m
        }+ e+ }) K2 ]# o& ?% f# b
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {; ?# o9 x  Q5 @1 o7 ?3 {( ^. A' S
                elapsed_time = nes->cpu->GetTotalCycles();
- S* {7 I3 g2 h5 Q+ ]        }
* y- Y9 `( i1 G) H  N' K( c#else; z- G. d% B: k8 w
        elapsed_time = nes->cpu->GetTotalCycles();: ]& x2 J! U6 @! M  u
#endif
7 O! T  O2 x0 b& c8 {}
" Y; T* ^8 Q7 c7 C
1 m. P( W1 h& @0 {7 ?2 B* A// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)/ Q6 D" z6 ]8 M+ F6 O# c
INT        APU::GetChannelFrequency( INT no )2 I* W0 r  h( A$ t, P
{$ ~6 v6 d; f5 o8 A8 I7 o5 e" H
        if( !m_bMute[0] )& j% y2 `$ r  e/ w
                return        0;& Z  r! I: I0 C

# X3 p# ~" L$ f        // Internal
. y5 u7 `5 ]/ b+ `: n. I4 N, P% Y        if( no < 5 ) {2 _$ V/ @0 l, [! y( S: E
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
) k; M* [  P* z9 \0 F3 F        }
5 ?; G" M+ z" t) @) A        // VRC6
" V- P4 e! S& ~3 }3 d- j        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* k  y7 S" X) y! u                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
( g1 l: _. w% ~! V) e! w3 N1 J0 k        }
, L0 b$ R" P& `0 C. a        // FDS
9 j1 t" d6 z( U7 ^8 y8 q        if( (exsound_select & 0x04) && no == 0x300 ) {
. E2 t! ?: r" B7 G                return        m_bMute[6]?fds.GetFreq( 0 ):0;
7 Y) @8 [+ U. n2 @: G. r& e+ Q        }+ S! c! m. z% z9 b; X; [# Z9 s
        // MMC5
0 A  H$ W+ x# e# l. e6 n; ?# g2 H        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {' u3 `& ~& M- q) ?9 D7 u( L' ^
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;' _' L+ G  e8 Q- b# T  X0 G
        }
6 b6 m) x+ O( a! C1 h5 \; ?        // N1064 q  ]8 Z  N% f5 I: a
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {; e- W( J+ s. h. D' q+ x$ s
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;) w$ D4 h1 `) V* I+ w/ Z7 k  p
        }8 @: Y2 g+ g6 \4 e; Y
        // FME7' e, g0 f6 Q* B9 j. B6 o0 }' a
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {/ H1 Q2 V; V. n) r9 B/ l; t- M2 c! B4 o5 X
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;6 Q7 s) N2 Q3 q0 O: m, |6 {9 d6 y5 @
        }7 y# [4 I& \2 o( c3 c; @
        // VRC7
' Q5 a3 ]* H5 A) H2 h        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 K2 G+ w: _3 Q/ I' P6 u# ?                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
3 P) L) k+ s* g        }
- h1 h! P3 G5 v        return        0;" B5 V/ f+ R* B$ {
}' z; L) p! Y% g4 a) n
* o. J" \) V2 x- i  r3 V9 i! F1 T/ u" k
// State Save/Load
4 c" m" c* ^. z- c" wvoid        APU::SaveState( LPBYTE p )% S4 R3 v  Y& R% c4 l
{! w) ^, K1 }: N3 Q
#ifdef        _DEBUG
& O( z6 X7 m$ B' Q, I' n2 hLPBYTE        pold = p;. o3 t  O/ ^" j7 I" I9 `/ d
#endif- D* U* {7 ]+ O' \
8 V& T# a/ }! r, e
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 D! I) v) s3 m4 \% T
        QueueFlush();
* g8 O/ ?8 [: |* g  n+ Z9 ]+ l1 K. @* V- X5 I# v
        internal.SaveState( p );' b' z9 Y- h' m* i1 o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( I) _( l& I6 Q) ?: F( I' |( n! x; I$ d* ^9 {/ c  Z2 m' D8 g/ r# M
        // VRC61 Q: N% p1 C5 Z7 L1 H- {
        if( exsound_select & 0x01 ) {
" R! Z+ _- r  X: V                vrc6.SaveState( p );! @/ w# t2 O/ n. w$ `% b
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& b, R: T! L4 I& _6 r5 z* t
        }# I! g' B; ]/ I  X6 o7 G4 R
        // VRC7 (not support)
' ~5 c# W3 i3 x3 @        if( exsound_select & 0x02 ) {
. r/ P$ Q2 v* n! S; j- |6 g                vrc7.SaveState( p );
+ |8 C% D; }6 t1 _* |" N                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) M6 z( s" e4 Q1 ]& ~6 f
        }
. v2 a! ^6 n( d$ k7 p1 z        // FDS
* u6 i# N5 a. \* f        if( exsound_select & 0x04 ) {
% C5 J" o" A! |# V8 A6 m                fds.SaveState( p );
) g4 g) I7 U1 R9 Q- K& V                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding# R* r$ k2 u. {  a& v% v3 h
        }5 h1 ]. ^& u; m( M0 w& ~
        // MMC5
2 T1 Z4 c5 Z+ K- c2 z$ N4 W0 F        if( exsound_select & 0x08 ) {
4 |# D4 G5 a' U& d                mmc5.SaveState( p );
$ [/ Q9 V5 T, O                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 H3 D/ P) |( }        }0 h& S3 V' Y$ c& P0 Q3 {! ~* C
        // N106
& i7 h7 p3 _3 a- ?/ V3 M7 }        if( exsound_select & 0x10 ) {
  P( W6 I5 p3 o2 \) m" B! V                n106.SaveState( p );
* h1 D3 h) b: }" h$ f/ Z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 P# C3 T% `3 f' P% H5 H1 q% g
        }' Y- Y3 C$ \% ^# A# w
        // FME7! l3 A4 f, P, E# f  ~$ ?
        if( exsound_select & 0x20 ) {. ]9 m7 _( e$ X' N/ @# t7 |
                fme7.SaveState( p );
% r, V3 J# l; [. w( s                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 |5 `/ A. B$ y( @" E; ]* D
        }
9 J+ n5 a3 i  n4 l# _  ]5 H% ^6 d9 F- c3 J0 @
#ifdef        _DEBUG
! |* f7 z1 i5 y) \0 _! F' }- a4 xDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );+ Y; P( a" y2 k
#endif" |+ K4 i4 F3 Y* S% u. B
}( _7 x& _% S0 `# a; X2 z

4 A2 t" H8 P. }) l- j/ lvoid        APU::LoadState( LPBYTE p )/ O$ j) ~) C5 b8 `2 ~  J
{
" q& r) t$ \/ X; P" @" D. f        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
" ^( ?8 \* `; G) M# Z7 R$ v1 K        QueueClear();$ J2 _8 G8 f" h( B. z8 ?
- r* |+ U: d$ k) ?
        internal.LoadState( p );  _  y- _  u* i  ]. f2 @; ~1 ?+ Y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 a8 p: W9 f4 {' I( M0 k, J

2 E9 j1 p  j$ i) q        // VRC6
, Y3 T' ]4 T6 N; N        if( exsound_select & 0x01 ) {- \' y2 e7 {: B% V' O8 E# A
                vrc6.LoadState( p );0 u6 ~7 N% x1 h
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: ~' }7 W9 D( n; d        }
4 s- G, x9 Q, s2 l* v        // VRC7 (not support)1 ~  k  u. D% s  A2 l1 X6 B( U- r8 t
        if( exsound_select & 0x02 ) {. z$ D, y6 b' k8 _6 R4 m) J6 o. O
                vrc7.LoadState( p );
2 E  H+ C& U8 \) M2 K" b                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 s6 d8 T- ~4 ]3 H$ m, u        }
4 {6 k# n. K/ n3 z- |# ]  P& O8 w        // FDS- c% Y- X. @0 ?/ U) A
        if( exsound_select & 0x04 ) {
- ~2 l5 ?8 J* S                fds.LoadState( p );
: F2 e0 I2 k8 n  g' x                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 L$ K' w4 h- v- C2 H
        }, f5 O, I5 F. _; |. z# _5 e! h5 W
        // MMC5$ y1 Q- j6 \% O
        if( exsound_select & 0x08 ) {: }" K3 g8 {& C! X3 E1 o
                mmc5.LoadState( p );
( W- C& `! s: M" Q  e% P                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" t: [. w# t  D( \
        }
3 D8 G3 a( ]  }6 u2 b        // N106- V# s+ Q: o1 V) ]2 |
        if( exsound_select & 0x10 ) {& k: \" U7 H6 O3 ]# A
                n106.LoadState( p );/ _+ G+ \$ j+ U0 q9 b6 o) i* t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 P4 Y0 E% X& [
        }0 i3 P7 X$ c& i1 P( e& A
        // FME7
3 g  G& Y# E( T4 T6 j1 x; ^        if( exsound_select & 0x20 ) {& ?1 Z4 t5 y' C% A
                fme7.LoadState( p );: h4 P$ b( k) V0 V
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 M, A+ ]% G# ^% l- Q
        }
7 N6 Z  Y- x# {+ P  q( }2 Q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 , |) n) s- b$ n0 Q3 E
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. P% Z( a+ m: `感激不尽~~
& J/ P0 r( n) v* c% S: p; V  g
恩 我對模擬器不是很有研究,
8 `, D" A( s  R. T$ ~雖然要了解源碼內容,可能不是很困難,
3 F/ P. ]% y* P3 Y0 I不過還是要花時間,個人目前蠻忙碌的。- X6 |; E) V/ q, h
" t; T5 \" A. I" a
給你一個朋友的MSN,你可以跟他討論看看,
4 r; Y$ H- Q9 @. J; \% H: e他本身是程式設計師,也對FC模擬器很有興趣。' u- A- T- R  t" C2 H4 f/ G
  l# @8 _  z+ L, m; U5 L
MSN我就PM到你的信箱了。
' t  N+ f: D3 ^* ^+ y; `7 t# G1 g' a4 x% S. V+ J0 I9 L" }
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
" L, K" P8 c. Z, X$ `$ f. x呵…… 谢过团长大人~~
+ h7 @' A" g0 v' M9 |$ a

, H$ b  r6 ], C哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
& Q0 J8 ^; p7 A/ W3 {" Z团长的朋友都是神,那团长就是神的boss。

7 `$ W+ b* @% @" N哈 不敢當,我只是個平凡人,* n( K- j& b4 R( p/ F5 @) t
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ C( r# [# d- z/ Y: u6 |5 p5 F; bZYH
9 N+ `5 V/ @/ i( r: VQQ:414734306
+ W; _; x( X/ R' yMail:zyh-01@126.com; b: ^$ U) T; V5 u

8 r: p4 d5 t$ \' ]3 x4 n7 D他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 }4 q2 t* H3 M9 B: G( i2 Q& }6 P再次对团长大人和悠悠哥的无私帮助表示感谢~~

# f, z* p! E% f/ c) M不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-2 01:32 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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