EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 z) I; `. {: G楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~/ F0 B5 ?3 K$ b
这里有相应的模拟器源码,就当送给大侠了~~$ @# M4 C  {& x
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
: n8 C) G' V0 I$ S6 H. G能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; L5 B9 h1 z. `+ w' a楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; F2 q( w* x6 f0 }1 F, t: r这里有相应的模拟器源码,就当送给大侠 ...
  B/ n# G, S! p& j/ z7 P: ?
聲音部分(Audoi Process Unit = APU):  {& e( i& q/ ~
.\NES\APU.cpp
2 X7 C+ J. D: F.\NES\APU.h, s+ M( u' H3 Z' f+ }

$ e( A/ a9 K; q& e. A  w/ A. P; u# L" Z1 H, n4 z. T! d# U
影像處理部份(Picture Processing Unit = PPU):
( Z3 g/ A, x8 i3 m5 t% N) F.\NES\PPU.cpp) x0 _/ G$ O/ F$ a- N& s5 {6 ^& ?
.\NES\PPU.h4 \! q6 O1 Q. N" {* x8 j5 a5 K
0 H: U( u4 z# O. c
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
' y0 U9 H0 u: i5 O. t0 Z(由于很多专用术语和算法机理都不明白,所以看不大懂……)0 I: r2 k1 C+ g
//////////////////////////////////////////////////////////////////////////: d1 |' i& S! ], d
//                                                                      //
7 e; g3 W8 N" \1 K/ [//      NES APU core                                                    //
5 G! t" [+ v7 L+ ?5 t, Q: r4 C//                                                           Norix      //
4 [, b% A4 l" f- P9 V. _* `//                                               written     2002/06/27 //9 t( W- Q1 `" |5 e
//                                               last modify ----/--/-- //6 I. h7 S, P; q
//////////////////////////////////////////////////////////////////////////
  G: c6 ?  s% \* V#include "DebugOut.h"
6 ~* s, ?/ T0 D9 _$ X& o#include "App.h"+ H7 X" N' M' ]* ]' r
#include "Config.h"
( v  ]# ^& Z/ d2 w" [8 h
6 N1 S6 }' e$ F" U3 X4 Z: c#include "nes.h"% b/ |) c+ }% D$ ~+ [
#include "mmu.h"
" c& x6 b; O* A" G2 L, {#include "cpu.h", Q5 z% h- V9 v" m" c2 U$ V  b& i
#include "ppu.h"
4 x1 J! ^* x6 }4 O1 Z3 l#include "rom.h"
, m; ~: h) w1 o" g5 P9 H#include "apu.h"
; A" g% X4 I) `, u" X: c0 x2 Y/ H6 ^, e! A  d! B  _
// Volume adjust( \- Q$ I7 k+ x8 p
// Internal sounds7 R6 g$ E7 W( W- O7 j; k* Z
#define        RECTANGLE_VOL        (0x0F0)
; }7 q- p9 T# e$ b. R#define        TRIANGLE_VOL        (0x130)# A4 D: J9 G( ~# D1 O# M
#define        NOISE_VOL        (0x0C0)
& q" e/ F' k2 N: L" w* h% }$ V#define        DPCM_VOL        (0x0F0)
# a0 \/ z$ R+ n' p) Y// Extra sounds
1 l6 |) v/ k+ K' l2 F#define        VRC6_VOL        (0x0F0)
) g& a* N$ H. A) I& H. o; \#define        VRC7_VOL        (0x130); \- d; |  `& G  q6 H
#define        FDS_VOL                (0x0F0)' M; K6 \$ P" @+ s7 r& q
#define        MMC5_VOL        (0x0F0), F# {, |  _0 R/ O( e& [  n; l7 L/ K
#define        N106_VOL        (0x088)+ @. ?9 m# ?  |' G' o
#define        FME7_VOL        (0x130)+ t8 Z- M/ e0 H- ^# ~9 w% \" Y7 g

' k7 s3 {' a2 s1 k( ?% MAPU::APU( NES* parent )
0 D* \* k6 M0 r- k& }9 g$ _{) A- q+ t# I" W
        exsound_select = 0;
5 l. E) o0 V# s0 P8 j% z( U" w4 i& K+ f, p
        nes = parent;
1 x7 F/ }. ]+ Y* \  n+ K! X& A7 F1 \6 |" @        internal.SetParent( parent );) t0 n- _. G, X
' v, _$ a. m& i' X8 g! R+ N
        last_data = last_diff = 0;
. z. M- P4 x6 G1 }3 O' P' i
- ~* v9 Y0 j! E6 ^/ C' L        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
# v7 Y/ D7 n. ]
: {' u% X4 \3 s, ]/ Y& L. F: }        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );# A: F4 x( [, N& a  \, g$ _
        ZEROMEMORY( &queue, sizeof(queue) );
5 q4 e7 S# q, \        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 B! v( W. M+ K/ F! t- v

: k6 {6 s7 c! P1 X        for( INT i = 0; i < 16; i++ ) {# b5 I; S/ y* D& T1 b
                m_bMute = TRUE;
3 Q, w6 R; s% K/ I4 y* v, o        }8 L. H( }2 n( G9 {1 c
}
5 e! X  K* ]' N
7 C9 T6 \2 I; YAPU::~APU()
% m+ J4 f+ {, L  A{
7 j* N* U1 L( v% N- _; m6 z}
+ u  T1 n9 `1 W; o. z5 k7 x
4 c5 U% e! B2 u( i4 n9 Ivoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' [7 F4 ~6 n% T' z{4 M6 M: f+ m6 o6 U' f. T
        queue.data[queue.wrptr].time = writetime;( y- F  S! w: @( b( T3 d4 i  T% j. ]
        queue.data[queue.wrptr].addr = addr;0 u$ D$ S' d2 D& t
        queue.data[queue.wrptr].data = data;
9 v6 [+ ]9 t9 @        queue.wrptr++;
% Y4 }2 X4 W7 B1 Y5 X5 h6 x1 I        queue.wrptr&=QUEUE_LENGTH-1;8 u. C+ T( c% ^/ A& }
        if( queue.wrptr == queue.rdptr ) {
2 N: _. r  T; O: I2 D                DEBUGOUT( "queue overflow.\n" );$ ~/ @8 e# [. J, _6 G
        }: ?) K+ ]4 R3 w& {0 n1 B4 Y
}" ~! L7 X  g- F. Q# A& ^* X+ ?9 v
5 r5 M( g, f/ ^* O
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )8 o& [! {4 i/ P7 B
{
5 [4 `+ t7 _" R+ D# ~: K        if( queue.wrptr == queue.rdptr ) {0 i! U% A2 f  \/ P
                return        FALSE;
/ y* H" S" O. x  E2 G9 m        }
& v. p0 z% Y( M3 n. h3 k' J* P        if( queue.data[queue.rdptr].time <= writetime ) {' l% ^+ p" o) l
                ret = queue.data[queue.rdptr];
( o9 I0 m7 O9 u: N) @+ {                queue.rdptr++;
1 s( Q  ]) f! E3 Z: E" K' C                queue.rdptr&=QUEUE_LENGTH-1;$ L9 Q+ ]  w* d( ^! Q1 ]( H
                return        TRUE;
* v4 Z4 w$ A; E" W5 O6 B        }
  m/ z3 [! [% {) L        return        FALSE;7 A; {6 p7 M) _% ]4 L5 [: L0 [' Z
}
7 M/ u- s4 {& z9 }0 E
! d6 e$ E* ?3 j. {8 gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
' q7 R. m; _0 H6 |# a, t{: Z5 j. H% ]9 Q0 \0 @
        exqueue.data[exqueue.wrptr].time = writetime;
3 c4 Z% B6 G1 {+ ~9 O8 i7 `        exqueue.data[exqueue.wrptr].addr = addr;
, S: t/ V" B2 H' v5 Q        exqueue.data[exqueue.wrptr].data = data;! G1 h) l% u" J, w
        exqueue.wrptr++;
7 t3 S6 M& P3 L2 N0 T0 j' U6 b/ e        exqueue.wrptr&=QUEUE_LENGTH-1;9 B; B3 w7 c6 r, F* i) B, P: @2 ]
        if( exqueue.wrptr == exqueue.rdptr ) {( y; v2 o' q) I6 B
                DEBUGOUT( "exqueue overflow.\n" );5 w/ |& w- e7 m
        }
6 E- u$ C1 X' j5 e) H}: X) {/ L9 f- O& L6 l! m* m& l
1 _  m( v6 B, }1 Y6 [3 y4 _8 n
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
/ |* k2 R2 n9 h7 F{
: _& X3 X% b1 \% H& A0 [! O) P4 x        if( exqueue.wrptr == exqueue.rdptr ) {1 h9 r. v- x: Q% M  o; l* g
                return        FALSE;7 Q) z, b: P/ y% n" B& l# g0 F0 V% {
        }/ p" p3 t2 Q3 e
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, J9 _0 k' Q0 V/ T" V5 o
                ret = exqueue.data[exqueue.rdptr];
7 o6 m# f) H8 s* s5 n$ f                exqueue.rdptr++;1 |- \( z) J8 X. F" O- m$ v
                exqueue.rdptr&=QUEUE_LENGTH-1;
" q; Z3 w" e4 o$ s1 H3 [* |: z! R9 Y4 e                return        TRUE;6 G) _% n& h4 x4 e
        }
1 O2 o: c3 w) c+ i8 x7 X        return        FALSE;3 a- \; O1 F. Z+ N1 V
}
$ c. f; B: q! [5 [, t9 j
4 p& j; n4 l+ S- W5 T" o+ L( @% }void        APU::QueueClear()6 u7 Q6 c0 V7 V- f& O! ~% t& \, j
{
/ ^! }# a! S! J$ f' z- L1 ?        ZEROMEMORY( &queue, sizeof(queue) );
, l  B( }" ~! \$ z' P0 Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );& _9 v. \0 ~/ ~+ _3 A) ]& Z
}3 P4 T; p( t" k9 T+ z

2 F' D' r9 k* tvoid        APU::QueueFlush()
+ @/ l4 f* D1 P% M! D9 k{# _9 ]) U. o: p+ [* d% S# e' T
        while( queue.wrptr != queue.rdptr ) {
: s3 E3 d, @6 o8 M8 W  U$ z5 x                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ v/ {3 {3 V& V; ]: V
                queue.rdptr++;/ f- Z: w2 ?: H
                queue.rdptr&=QUEUE_LENGTH-1;7 _# L- C" ~9 D9 w
        }
8 Z. N+ h1 L' \1 F3 D$ y
+ [( O* l, C2 l. R" F        while( exqueue.wrptr != exqueue.rdptr ) {
( b  ~/ q8 S1 l8 I# P0 E                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );$ y6 S/ E7 w2 D3 h, |
                exqueue.rdptr++;
+ I6 u7 J1 G4 u, u2 c" i                exqueue.rdptr&=QUEUE_LENGTH-1;4 A0 f; o9 ~" C
        }9 _8 g8 W5 c! ]" Q% [
}
# h4 {3 c. k* W
5 `) ?5 C2 W& }* n7 @; Gvoid        APU::SoundSetup()
: y$ X2 G7 C8 K. F- ^{6 Q/ S2 O. [: h* `
        FLOAT        fClock = nes->nescfg->CpuClock;
/ n3 v% C: d2 T4 Y/ X. V; v  k        INT        nRate = (INT)Config.sound.nRate;* h( e; w  n7 C3 A6 f; E
        internal.Setup( fClock, nRate );
1 M1 |+ |9 K( |$ e# x        vrc6.Setup( fClock, nRate );
, C3 ~8 A0 @+ t        vrc7.Setup( fClock, nRate );7 [# Y6 E# e9 B9 w& T
        mmc5.Setup( fClock, nRate );
- }9 L& L$ L, }4 ]+ v! b        fds.Setup ( fClock, nRate );& w; Q/ S3 N7 q3 f2 W4 k6 P2 h
        n106.Setup( fClock, nRate );
; j# ?7 w- o& K5 F0 E        fme7.Setup( fClock, nRate );; P( e6 d& _! z# |% y) c( G
}8 x: K" A) c* b0 A
  n0 [) o( ^: B% v( h/ x4 s( F
void        APU::Reset()% p% T% e6 h: `2 B) |; U) _- f
{0 q* k6 G0 I. g! z& b& e
        ZEROMEMORY( &queue, sizeof(queue) );/ X" C/ q. {; S7 @, U7 C1 Z7 M' A
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 s' U0 P% L( r  ?! m
1 Y2 [5 B! V% N8 K: a        elapsed_time = 0;3 w5 j* j( O  x# q0 `3 o

9 U- z) k0 E# M' V, M        FLOAT        fClock = nes->nescfg->CpuClock;& Y+ c' s: u7 A5 o5 D
        INT        nRate = (INT)Config.sound.nRate;+ o2 E# C# T4 }. ]. y1 D
        internal.Reset( fClock, nRate );! i0 n0 H7 n/ L& S+ K
        vrc6.Reset( fClock, nRate );# ~: S: ]( }& V6 e9 t
        vrc7.Reset( fClock, nRate );
  j) k! n1 O8 ]# n$ f3 }) b        mmc5.Reset( fClock, nRate );  z1 _: v0 n4 W7 Y8 i
        fds.Reset ( fClock, nRate );( H; t) U' R+ R
        n106.Reset( fClock, nRate );
* ~9 L  p( t6 s# Y        fme7.Reset( fClock, nRate );, z0 q& ~7 W1 A7 I/ T. j
( [$ p2 L7 ~/ V8 J" \  [4 ?1 Z
        SoundSetup();4 w9 [9 t  b( W; D/ I( g
}3 H* H- R+ N: i$ p3 X+ t8 [

0 X: \& [9 ?1 Z7 v6 qvoid        APU::SelectExSound( BYTE data )+ Y7 }5 P2 W# y& O; y' ?
{" ^5 l; N( @0 l1 F
        exsound_select = data;
8 t9 P. y. K: i( k: Q. q}
/ x/ s; l7 |4 P* o; ]( z1 s
: r8 \, t( f/ B  j5 kBYTE        APU::Read( WORD addr )5 J: W/ j( M. D& L! f* b/ e% Q. H$ n" D
{, ?  m, o! a6 _" @& u2 J  D
        return        internal.SyncRead( addr );
0 v& i* [9 z% Y( B& N8 z9 T* ?, Z}( P% c9 G. {" _8 I+ `
. D; z9 d$ I9 l" g! X
void        APU::Write( WORD addr, BYTE data )% P* b) X, i7 R( p% c' }
{
& Z6 ]# M3 I! [        // $4018偼VirtuaNES屌桳億乕僩. S' B/ m, s& h! ?/ G
        if( addr >= 0x4000 && addr <= 0x401F ) {6 }, |5 T& U/ y) S, }
                internal.SyncWrite( addr, data );
0 G/ @: A  y, f9 J# i0 X3 X6 ]                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
; N' q- D; M, V( N  a% F9 A# f        }- h) F0 }9 l  S! B
}
: b: z8 g0 M& I4 M9 j, ]( K8 W6 i1 {5 v1 E# i
BYTE        APU::ExRead( WORD addr )7 T, C: q$ i) z- F
{6 F3 k7 q* g% D3 H6 X, e
BYTE        data = 0;
, J) h# k$ N+ ~4 K& F- R! I# }
9 o) @+ l$ S+ e+ D4 O        if( exsound_select & 0x10 ) {5 `% j% r) l: n/ T& H- a" C' M
                if( addr == 0x4800 ) {& L+ i6 a% O7 B  t
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );8 i" _2 W' W# c  Y7 C/ C: Y: G
                }
! k0 L: X' _6 c1 J* z        }
5 Y' @8 A, U' B" T7 C- T5 p4 R        if( exsound_select & 0x04 ) {
& z( m% g7 p1 N+ p! T                if( addr >= 0x4040 && addr < 0x4100 ) {
. S4 ?1 a9 Q' w, o3 t& W                        data = fds.SyncRead( addr );
& G3 a) F; V; X0 _8 _                }
7 |0 s5 K: `, u3 m        }
8 B( i, G  ?1 O  x3 B        if( exsound_select & 0x08 ) {
4 O# M, m7 B* p2 I                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 B/ _% E5 o! \6 Z* f! N                        data = mmc5.SyncRead( addr );
1 i( Q0 Z! t0 H2 H                }
$ J5 l7 Z, r' l" K. i        }# u* v) y0 H" S' V) b4 Q3 E- S
* k1 p6 ?5 `+ W! I
        return        data;
2 {1 R1 o& [0 e. l}
& b8 B7 o8 o' {9 N# m" x2 h% e  k% v! F% \! ~) N
void        APU::ExWrite( WORD addr, BYTE data )
( I, K+ K( `# t& Y{3 V" N9 {; C& o( I
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );3 y1 v; I; Z+ B7 ~6 Z+ W- |
6 j  }2 Y4 I& \+ @6 w2 ~8 U4 q/ z
        if( exsound_select & 0x04 ) {
! u4 `8 ~( l  V4 ]% D: W4 v                if( addr >= 0x4040 && addr < 0x4100 ) {7 m3 c0 ~, K0 ~( p' ?  U* D
                        fds.SyncWrite( addr, data );
3 s7 l, c% I1 S9 X+ }/ C                }/ v) q, j' G$ c1 v; Y: e
        }
0 u% W5 s) W$ x8 q
  S* f* j4 @) a  U        if( exsound_select & 0x08 ) {
2 }, }% C; a/ X8 J4 O                if( addr >= 0x5000 && addr <= 0x5015 ) {
) U! L! D9 K, x: B2 o  Q9 b                        mmc5.SyncWrite( addr, data );
% \; u$ T% X3 f7 n0 [! P                }8 n5 q% c+ [! c4 q
        }5 W1 h  v# C. x3 P, q' S+ ^
}
' z* ?( |$ U9 ?; J9 ^
  `' e8 g8 A; c5 l7 g% gvoid        APU::Sync()( |6 v3 p$ L% k8 N0 l9 l, f6 J2 C; A
{
/ k5 V" W. o2 v: u9 V. L) C}" x$ L& _" d. ]0 S
, |+ `0 o: M# G" [
void        APU::SyncDPCM( INT cycles )9 J3 V# }) ?$ ^. G  S/ Y9 _7 Z3 U
{
* c* c) Z2 X; G( ?0 @& E# j        internal.Sync( cycles );0 w: {; e- `: ?# Z/ ]% p
! Q8 H8 R: i; ^( ?3 _1 @
        if( exsound_select & 0x04 ) {  w, x8 a- {6 T6 n
                fds.Sync( cycles );4 D% E- U) f' r/ g4 z8 V- H+ p
        }
1 O9 p. v$ H5 h: f* X0 r0 c" r" \        if( exsound_select & 0x08 ) {
* F/ Y1 o$ @1 P                mmc5.Sync( cycles );) U; o; V. ?- B
        }( x( D% j) ?4 ~' B
}
' r; O4 t  g& u/ ^; y( i0 t# g/ i' Q; T2 \
void        APU::WriteProcess( WORD addr, BYTE data )
8 `# b4 G# Y2 g3 Z; }1 M" Q/ A: v{% {/ g# N1 d! |8 x+ Y7 k, Z; r
        // $4018偼VirtuaNES屌桳億乕僩) k7 r; a; x* V& @4 s
        if( addr >= 0x4000 && addr <= 0x401F ) {8 ], ?, J, S" R- j3 h8 c
                internal.Write( addr, data );
9 Y0 e) F# ], j) W) X; f7 P        }- i, B! @" D$ H3 @- O$ [2 _
}4 s" Z5 ]6 ?, B! U! I- L

: Y) w# Y; F6 }! N; Wvoid        APU::WriteExProcess( WORD addr, BYTE data )
) J8 ]4 f, T, ^2 ]{
9 Z& K' W1 }( K8 _2 F        if( exsound_select & 0x01 ) {; N% I9 K- V9 ~4 R! I6 h# [
                vrc6.Write( addr, data );( k& P3 a+ ~( T( p
        }% F, q5 d7 l5 h( H4 `
        if( exsound_select & 0x02 ) {# c, N1 m; D$ d
                vrc7.Write( addr, data );
' O5 U  b. I! Y2 }# y& s" o6 K        }
' O* Z% p& B7 g* P" N        if( exsound_select & 0x04 ) {1 V: k+ z- T; w
                fds.Write( addr, data );: |: A1 C+ {2 l* G0 @& }# M6 [' G
        }0 b0 Z' p7 z0 y3 Y2 z) V
        if( exsound_select & 0x08 ) {5 N) P* _; ^" {
                mmc5.Write( addr, data );
6 a% o  C2 Y5 ?- Z' {% P        }5 f2 N6 e/ s0 ~# t+ ]9 s, s$ J
        if( exsound_select & 0x10 ) {
) y9 j) Y; T7 O0 o                if( addr == 0x0000 ) {, d" H5 n; N+ ^* @4 h6 {2 g
                        BYTE        dummy = n106.Read( addr );
  V( H, }$ p3 B  N5 I% y7 u; t1 w                } else {" c- y" N8 ?- P+ G; }
                        n106.Write( addr, data );
. Z5 I0 t6 A$ ?6 }& o7 d2 [                }+ @# [6 H4 v$ {6 X. ~2 F. X, `
        }
! ]$ S' [. `% c2 S8 e. b* w        if( exsound_select & 0x20 ) {
; C$ a  @( V+ y/ E                fme7.Write( addr, data );
! {% {) W9 y: L- s        }
( R$ L/ b/ a. Q/ j* Z6 ]5 `}  k& ?5 h$ t( J. k

, H- L6 g" R/ X+ t9 F4 [6 S1 {void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )3 Z" L5 O. k& j7 m
{, a# f+ t! R' U) }  E
INT        nBits = Config.sound.nBits;
: S& w5 B8 Z: F( E! KDWORD        dwLength = dwSize / (nBits/8);
3 x1 `/ @( q  N( M/ _INT        output;
& E9 q4 B3 N/ U- Y1 O8 RQUEUEDATA q;
" [- T, {+ \2 rDWORD        writetime;" @% V( F1 h- S% h; k$ g" R) N2 T& A

/ W' f# f) ^* PLPSHORT        pSoundBuf = m_SoundBuffer;
" ~, Q4 b4 a  b' v9 r' {INT        nCcount = 0;
$ z& m- P4 B  J' e7 E$ C" b
" _! \: Y3 f4 j% U" |. _INT        nFilterType = Config.sound.nFilterType;
  d1 m! a/ c+ \, D: w, G, |) m  W, L8 m( {2 t' f$ d7 p
        if( !Config.sound.bEnable ) {7 s( O6 w/ L: |3 i! ^
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
' _, p, Z7 U, q4 u" L1 X                return;4 r6 H2 b" G( R3 p' t
        }
" Y3 L- A0 E  K; Z, H. q; a' Y- d6 _9 J
        // Volume setup
6 w' R  q2 h* }- K7 u. I; q        //  0:Master' C& N0 k: _$ K# o
        //  1:Rectangle 1
$ s/ e4 Q6 C" O' O        //  2:Rectangle 2# Z7 x. s; L0 V1 O1 e
        //  3:Triangle# v# @- ?4 d2 M5 y. G
        //  4:Noise+ o) w: A( j; _4 X5 g
        //  5:DPCM
) y+ \; l+ [( ^1 u7 m6 g* n/ X9 {        //  6:VRC67 J/ J7 d$ W/ b& F
        //  7:VRC7
3 K+ `$ i4 E( {: \        //  8:FDS3 x# C7 F% P/ o2 u8 y' c7 x
        //  9:MMC5
3 y# s* }1 P+ V* @% U4 p( s        // 10:N106
" \7 N' C) @" }0 m3 o: ]/ }6 _' y        // 11:FME7- A+ Q% Z: Y' y+ F
        INT        vol[24];
) u( l$ u9 A/ S5 X  a! s8 |1 K  _! w        BOOL*        bMute = m_bMute;7 x& l3 v8 I3 T* v
        SHORT*        nVolume = Config.sound.nVolume;
. ^% t' P" `$ E
& W; d, T3 f* I7 }* `2 b  }        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
5 L$ W% T' S2 P9 q; w" C( H) G2 A! H% X! ]
        // Internal
- J+ {- h* x. ]. @8 |        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;; |, Y8 Q" A( N+ u- K/ |! x
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;# Z* y1 J: e, |  ~9 A, A/ K
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;+ U6 Q2 h5 M3 c; d: e1 [
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;( p0 ]3 v4 T& a& C4 E
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;, k2 |* G! x& O3 P! W5 `
! D+ h" j$ R$ [2 C+ y. R) M  C
        // VRC6
6 z) [. Y& `9 A- `        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( u3 c. S  k( r% D7 `' E9 G& p
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 W) {  J0 k: I2 d. M$ [) B  u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 f9 {  d& ^1 o7 F! O, S' M, u
/ W' z. O+ P8 g9 s# z( `
        // VRC7/ O$ P5 q' U0 Q2 o) K. Y
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;# M( v: \, X* c" M( i0 e

5 M: [5 S: y8 ]+ ~  T        // FDS/ S& f  v/ a  }/ b# d. T0 K
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
: \% K$ t8 A6 q, c3 Y& s0 @; s
8 v! f4 {5 @4 y" F6 O& T        // MMC5, c' A0 `4 n; g1 I1 u0 N
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 w% y, X9 }+ P% n
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ h3 ~5 c( h! R# k4 Z0 p! R/ f8 J
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! Y7 `$ L# B' I9 ^, n( z+ X  n
5 ~! X( G& D4 W" I9 r% M6 H+ ^
        // N106
, p/ G% t4 |$ g% [        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" R* T- u: |, U8 N0 Q+ n) B5 @4 ~
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' u5 M/ a& K4 u/ r" p7 w, W        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! t5 o; X+ |, ?1 `- n3 u/ _
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* `& ?& l5 g/ E: v! M: D& a
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, V: I6 O$ o. `, c; y0 z) O( K
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! {& p* p/ B( M6 T! R        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! [4 j; ]. z- v( S, `# L# S
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: \/ U  f; ~2 E2 K4 [* [
3 K! H9 o0 C2 I8 ~        // FME7
2 `; J9 I& ~) I, u# Y        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 a* t6 x9 y3 h( Z, Y# L: S( v( a6 T        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, l6 b+ o: \8 \( R( S( Z8 e7 Y        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' a$ V1 b' L6 y' D; t
2 m  L' l7 P) m+ g: s) j
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
8 h+ I0 Z$ [& s% d, T        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
/ |' Q! f) y; l5 z' e5 U! P; g5 j8 _  M: X' i
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟; h7 ?- K4 n$ ?4 p9 \
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {( c! l, g9 @  C) d( p1 r1 I
                QueueFlush();8 N' q, n- |, g5 X
        }$ \! H. y9 p) t3 m; p

/ R+ p! j- ?  P7 E1 }. Z: N        while( dwLength-- ) {
3 d, ~% b8 i0 T7 `2 a/ n                writetime = (DWORD)elapsed_time;( w# D: t9 n' l' Z. P! _& P
1 H. l  _* B% C( e( X
                while( GetQueue( writetime, q ) ) {
5 G9 Q' I! U( `8 [$ O  F9 d. C$ _                        WriteProcess( q.addr, q.data );
. d  s0 l/ R2 @8 H: p                }
! l4 n4 m! _" {# T) D
# U& z/ ]: a4 j4 m( j6 A6 v                while( GetExQueue( writetime, q ) ) {$ u& k0 `8 D" r
                        WriteExProcess( q.addr, q.data );* e* B0 ?4 n1 b- Q% P
                }
/ b" @8 _  ^% Q" X  W7 f
  S4 c2 f& _) @! k  G) |2 A                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7: u  e2 P6 t4 h5 ~% p1 o( I2 H$ k
                output = 0;
( Y' c/ f$ g6 v6 O: x# U( R                output += internal.Process( 0 )*vol[0];7 O0 w8 ?; n9 u- M0 x6 \5 o. O" l
                output += internal.Process( 1 )*vol[1];" P% p& B9 |. Y! m2 r
                output += internal.Process( 2 )*vol[2];
+ E# _. Z; M  W  b/ \                output += internal.Process( 3 )*vol[3];
1 s* g2 |4 ], q3 B                output += internal.Process( 4 )*vol[4];
7 x: T+ w7 p9 V; R- A* L
1 z3 F6 k( t/ n. U# {8 Y/ {$ U                if( exsound_select & 0x01 ) {
* a' a% Q' f6 _, r. z+ b4 U                        output += vrc6.Process( 0 )*vol[5];1 D2 b2 b) Z0 w/ j, j2 S/ n7 d+ [
                        output += vrc6.Process( 1 )*vol[6];
' B2 g0 V# ^$ @& P/ [                        output += vrc6.Process( 2 )*vol[7];- ~4 z7 v+ E3 H8 s
                }. q8 t' Z) s" ]3 Y. y
                if( exsound_select & 0x02 ) {! I2 Y) r( w" z+ \' @7 {
                        output += vrc7.Process( 0 )*vol[8];' h* y! j# D8 T+ F1 Z8 O4 K/ q
                }
  o0 x" B' z- L, u7 p; p                if( exsound_select & 0x04 ) {
  A5 w; Y$ Y8 I' h- r! U/ X; ?                        output += fds.Process( 0 )*vol[9];
/ }/ @$ T* H2 T1 G- ~                }
. O. L9 Z3 ?5 {+ U. z                if( exsound_select & 0x08 ) {2 H3 C# P3 j; J9 k4 ?4 [( X4 ]
                        output += mmc5.Process( 0 )*vol[10];. R' i2 m% t* I+ O" f
                        output += mmc5.Process( 1 )*vol[11];
4 }% x) R. d9 D" F                        output += mmc5.Process( 2 )*vol[12];+ f2 h1 l. k2 o- o6 ^
                }& X( s/ J: X) R$ |$ Q, h' H4 X
                if( exsound_select & 0x10 ) {
4 X2 o5 s" F3 F! C; D! s0 b; D  J                        output += n106.Process( 0 )*vol[13];, L" R0 x' Y3 F
                        output += n106.Process( 1 )*vol[14];
7 O  V7 I! _4 G' f' H7 p) D                        output += n106.Process( 2 )*vol[15];
* K2 l# }, i3 ]% X# l                        output += n106.Process( 3 )*vol[16];3 ], C0 m& L* d1 ~* s6 [
                        output += n106.Process( 4 )*vol[17];. _% D6 Z/ a, x8 v; t( B
                        output += n106.Process( 5 )*vol[18];- _1 x: L" e$ `. d& Z: u
                        output += n106.Process( 6 )*vol[19];
% ]* [: y+ B- v. N) D                        output += n106.Process( 7 )*vol[20];6 D8 r! R' }  ^# J( |. W# X' @
                }
# T# d1 [, M  |                if( exsound_select & 0x20 ) {$ j4 G0 z+ m- b7 `6 M7 i
                        fme7.Process( 3 );        // Envelope & Noise
: n+ `! m8 a7 `1 r1 ^                        output += fme7.Process( 0 )*vol[21];
5 Y; X2 J/ z# B0 S                        output += fme7.Process( 1 )*vol[22];
( J3 M6 S  [: d0 ~' v                        output += fme7.Process( 2 )*vol[23];
6 C  i8 V9 _! ?; R$ l                }
' i9 N) H% `5 }1 n5 H2 ~( K3 w3 E9 \. @+ t8 ~7 _+ L
                output >>= 8;
- U# N0 a0 R" [  D" ?0 b
9 L- l! S1 t) E4 }                if( nFilterType == 1 ) {3 h# @) ?( D' b$ ^( p: U
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
" y  z: l. v% |' V. [                        output = (lowpass_filter[0]+output)/2;* ?+ k; ?; E, d, z/ k
                        lowpass_filter[0] = output;
9 F( U; C; z- M                } else if( nFilterType == 2 ) {/ m5 X& @  @% Y3 L6 n$ P2 F3 K
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
6 f* A( Z+ m6 R) n                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;! ~- u2 |' N. w; d5 X6 V
                        lowpass_filter[1] = lowpass_filter[0];/ J  W5 L! L0 T8 e* y
                        lowpass_filter[0] = output;
# V5 @% l" G6 ~- `- l0 v+ _                } else if( nFilterType == 3 ) {7 b; U: O- i+ J/ _" W3 b
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
8 }) W1 s6 V! _! K/ _0 d                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;% }2 @/ r5 h0 r9 [# e+ ^9 h7 y
                        lowpass_filter[2] = lowpass_filter[1];
0 P4 s6 G/ g( ?% |                        lowpass_filter[1] = lowpass_filter[0];; g' \) g( `9 i& _% O7 p
                        lowpass_filter[0] = output;
) r, V; N: E. j  H                } else if( nFilterType == 4 ) {
1 M  s& h# |2 A# U$ s                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
% Q4 l$ u; L! [) w, f7 ^3 d7 f: Y                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
% Q( B' @. J5 ?6 r0 R' H9 E. g                        lowpass_filter[1] = lowpass_filter[0];$ V- u9 H$ q" F+ j" [
                        lowpass_filter[0] = output;
1 N& `# @& q' f0 E4 a& @                }! `% k& E+ C5 C2 o7 w% A) n3 H

6 s$ Z  x+ x8 h' K9 i#if        0$ ?7 M/ V3 b: N7 i) k" y9 w
                // DC惉暘偺僇僢僩
" n  ~: y% }* _0 B! Q                {* r9 ~9 }' e% i6 D6 k6 d/ v9 \& p2 c) T
                static double ave = 0.0, max=0.0, min=0.0;+ w0 ^( A  I% s% v6 J) c/ t
                double delta;
, z- E  a: ^' f% v( j( u+ _                delta = (max-min)/32768.0;9 L$ u' _. P  _8 p% o2 o( X
                max -= delta;
7 _7 S) X( a: d- y  A9 K) K/ X                min += delta;
0 v+ B6 P: U. H5 ?8 z* j                if( output > max ) max = output;
1 @. l' K) d: c; i3 C$ O. A                if( output < min ) min = output;
7 R3 i: p! n' Q( A                ave -= ave/1024.0;/ |8 W# e5 V- I2 d" O( k
                ave += (max+min)/2048.0;: N; P2 w) r+ g0 ]. R, p# {
                output -= (INT)ave;
% z- _) u) n" z  e) c$ {7 u                }0 G3 @! X8 h, O
#endif
2 ?# \' l6 m2 j9 O0 d+ L4 l7 }4 Y#if        16 A* Z; ~! D/ ~  Z
                // DC惉暘偺僇僢僩(HPF TEST)
1 M/ G+ k$ R3 l) ]& |8 K9 x& u( S                {
7 l' g# E1 R" e0 B0 O* @8 u//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
: }! R) J( ^( b6 o                static        double        cutofftemp = (2.0*3.141592653579*40.0);, Q8 z: ]9 s& q) M1 P3 Z! x
                double        cutoff = cutofftemp/(double)Config.sound.nRate;8 Y# ]9 m, n9 ~2 j' P
                static        double        tmp = 0.0;
2 c' `5 n4 c* O" A                double        in, out;/ y$ F9 j+ V" u7 e  g
1 Q! j3 e; k% Z
                in = (double)output;% m" J4 i, y; Z: Q
                out = (in - tmp);
8 k, `) F/ g5 T  v( O6 K9 u# e5 B4 w                tmp = tmp + cutoff * out;
! V) d5 m* U# G  a: ~1 R) p& \
& s. j  ?2 u+ y+ V                output = (INT)out;
5 U2 x# q% M1 h6 ^2 T7 \, ^                }
  ~, c: Z2 B* W& O$ h#endif
: P. l: }: @& Y0 Z8 g#if        0
3 S) H* R6 L- S/ i( s, s/ Z: p                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
0 z  y- a6 {1 ^, k. B% T9 z                {
$ Z3 s/ q$ \- _  q3 C                INT        diff = abs(output-last_data);
, I. Q" N# d9 n) _7 S8 L" Q5 p7 h                if( diff > 0x4000 ) {! A1 A- U0 M( n
                        output /= 4;: P# p( B: X: T' ?
                } else
/ @6 S! V. \9 P6 L( \/ _' k0 W4 r1 ?                if( diff > 0x3000 ) {
/ g. s/ I( V2 L( I                        output /= 3;2 Q7 Q; u0 [$ t. U9 r. v
                } else
( _. w6 S/ {+ F$ M                if( diff > 0x2000 ) {* [7 q0 T2 x1 |& ~8 }  C
                        output /= 2;
! y5 C1 r+ f- T- g3 D1 R) N' l                }
3 r: k8 N; p: L# r% o* P/ ]. j7 X                last_data = output;$ U, Z6 Y# p% G! w/ i1 n% R2 M
                }
8 Q+ @4 r& `) p+ N- H( s; U/ f#endif
6 Q6 _) Z+ R' }4 v4 B                // Limit* A$ c$ H2 w) @3 a, _
                if( output > 0x7FFF ) {- @& d( V( d+ u; d$ R
                        output = 0x7FFF;
" |: o+ `; T+ V8 D9 p" o                } else if( output < -0x8000 ) {5 x( S  C& v& I& W# T
                        output = -0x8000;- Y5 C. ?- L: f, X0 M+ j
                }2 i1 Q9 B" g0 Y7 w! N' o( {
5 t+ k' O6 ~9 m3 L5 Q9 {( S# t
                if( nBits != 8 ) {  a" y1 ]0 D* h, f
                        *(SHORT*)lpBuffer = (SHORT)output;! Z8 D5 }8 p/ h1 H! b3 `% S
                        lpBuffer += sizeof(SHORT);8 ^* T8 r8 x8 O9 ]7 |; P7 R8 P
                } else {1 G+ B: ]) Y4 R" s- u
                        *lpBuffer++ = (output>>8)^0x80;) Y1 H( M' P) ]% n# q
                }
* S+ I9 b6 j% {0 E
( _' z' k) s! x1 B5 g                if( nCcount < 0x0100 )
0 b0 j  ^+ y& H- J                        pSoundBuf[nCcount++] = (SHORT)output;2 A$ J2 \, O1 Y' o8 B, K4 ~

; X/ v% K! i7 h- _& C( @0 f/ Q- C//                elapsedtime += cycle_rate;
2 c1 Q& z5 ]+ G                elapsed_time += cycle_rate;  c# W/ ~9 [! f9 K# B! d: X
        }
: u# \& }9 l+ T) \
! G! R# X' Y7 r: G, k; k# `#if        1* d/ J' q- g9 }. L
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {2 k- F% f6 b6 i/ A! M( l
                elapsed_time = nes->cpu->GetTotalCycles();
5 p" T. w4 R0 y( f+ n& x        }9 H+ Q. p0 y& s1 ?8 G8 l! J3 X
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {2 @, x1 S6 U& N2 o" N
                elapsed_time = nes->cpu->GetTotalCycles();+ D' A0 I: ]7 x
        }2 J$ H) b* E  e
#else2 W+ H6 Z% D3 b0 I1 }/ W/ P' I
        elapsed_time = nes->cpu->GetTotalCycles();- T" J  h9 R& P
#endif5 s6 J) U( E( [- b
}
2 f+ N: U" f" n7 N# M# k6 l
: {" a2 T" h- W, Z% h, x// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)( @9 u/ \3 C- i" Z( a: M
INT        APU::GetChannelFrequency( INT no )4 ]2 ]; J& Z' U$ ~
{7 L2 ^% y, g$ Q3 z4 {# Y0 x
        if( !m_bMute[0] ); ^6 x8 `$ y% v' m8 G1 A! A
                return        0;. d9 I* o9 j' U, b/ G9 v& D
$ M$ e5 M: O+ I1 a1 S8 @  L
        // Internal7 Y. h$ J& T/ O& I' ^. q) @
        if( no < 5 ) {% M, r5 O$ R& d5 ]
                return        m_bMute[no+1]?internal.GetFreq( no ):0;! V" C" l& ~% E/ f3 E
        }5 m  q( M# P; B% H. {8 K# K
        // VRC6
5 z; ]7 J# n2 ?) q        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
- }3 @0 P& U: x" Z% T  k3 J/ \& ^                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;$ G! L, M0 p3 X  \, {
        }+ k( v, Y( d# e
        // FDS
5 o, H1 @4 T2 i- K7 I% `        if( (exsound_select & 0x04) && no == 0x300 ) {
6 ]  {9 K8 q" U- p' k# P                return        m_bMute[6]?fds.GetFreq( 0 ):0;/ v: e! `1 ]% E: n  m; U
        }
" V6 i9 E# ?2 i" S( b; F        // MMC5
" u9 [9 S* d) G5 Y% ^" z; F        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
7 E/ M1 O, z6 `8 a2 [                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
, B' B1 O9 t' O  h0 \4 L        }8 H  \/ ?6 @3 S+ \
        // N106
# G. p. x& c) \8 X: H. p        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {# j+ J/ h9 m- _- l
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
; r+ l* J, q1 J( j7 H2 [        }# d# D, j$ u' y( H. J+ b( N
        // FME7
) i$ q& O4 _1 g, _4 w8 Z        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {$ M* I4 K2 X: r0 p& Z
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;2 L; f5 Z) Z/ r% b. G8 q9 K1 U
        }  L6 ?' B+ l$ f2 L: u* H* i' o
        // VRC75 n* j# w$ O  ^" N
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {, L- Q8 k1 B+ z2 d/ Y
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ A3 X5 t- u: D, C2 y. k
        }
0 D8 c1 q2 W: y# V        return        0;
" o% T' {1 d+ W$ {5 j}
  ]4 b" l& x9 t( B/ s
0 n' m2 N* \6 ]1 z. w- ^0 v// State Save/Load
+ L8 i( i3 F; }4 Hvoid        APU::SaveState( LPBYTE p )$ E4 `; b6 F7 ^' N3 S" \
{
) f5 t  q+ o/ I5 o. ^#ifdef        _DEBUG
+ W8 ^1 O, ]$ }LPBYTE        pold = p;1 z! x+ c# y% Z
#endif) e$ \0 A: s( C+ }+ `% R
! k. F) y$ {8 O4 Y, }3 e/ X7 C
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞6 \+ t/ ^* P+ k% R' [) ~" N! S
        QueueFlush();& p/ M* b0 c5 Y+ r: t0 N' D
5 {/ k+ y! L+ g
        internal.SaveState( p );' t  U2 a. l5 s1 u
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 p$ i. ^6 U/ O- A1 Y8 K
: q& C3 L' q* y& j( c" Q
        // VRC6
1 q' I/ y* _0 c, b        if( exsound_select & 0x01 ) {. r" N. P  U; P" I
                vrc6.SaveState( p );
. V: E+ [7 n5 u0 r( e9 v                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 a+ p: Z& K( W, r7 E' i) e        }
0 [0 s- y# h( Q3 U        // VRC7 (not support)
- [$ ~0 C0 A$ q+ u        if( exsound_select & 0x02 ) {. c  r- ~: O9 _8 l2 a& g6 ]( w4 }
                vrc7.SaveState( p );
  w, u8 w; D/ ]4 _- R                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 l7 L6 @: I5 r        }: p$ D0 {! G, [; l- z
        // FDS% ^  h( b# b, U- A- V. d
        if( exsound_select & 0x04 ) {: H( x0 b. i; ~5 b% j
                fds.SaveState( p );0 q# Q6 ^; d+ p# y  n5 c2 \) a
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 S4 v% l# n& j. g" ^7 Y
        }
; Z/ @  s3 ^8 k7 m9 F        // MMC5
! a1 s  \3 a9 ]. H3 D; G: ]; r        if( exsound_select & 0x08 ) {
8 u6 H! s2 x# C+ g4 i4 f                mmc5.SaveState( p );6 I- r! E2 f9 v& M
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 q  c4 m$ n* ~8 M; A
        }
+ P6 F6 D5 ^3 b        // N106
+ g5 u$ g! h) r0 m% O0 u        if( exsound_select & 0x10 ) {
3 t, j, M& Q0 E+ p# C) D                n106.SaveState( p );+ v0 ]; b% n( c/ m: j
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 W4 ^, g) Q7 N% C+ _# S4 }6 F
        }3 k+ M5 H3 w% O% B: T2 z! ~
        // FME7* x6 L7 m4 C4 r" H2 |4 o" N5 L
        if( exsound_select & 0x20 ) {+ M& G5 j$ |1 @5 ]4 f; L
                fme7.SaveState( p );
1 q; q0 Q4 ]' R, |+ h                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. l0 h3 m' r7 p9 n/ T% x  ~9 _( p
        }
9 U6 Z0 d  o) ^! z1 s! r+ d0 n& R: [, g6 @
#ifdef        _DEBUG
5 \- J; b) l, R: y% A2 fDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );4 u) x* f+ V2 P  l
#endif( f4 j. |) z+ c# u1 r# m
}7 G5 g! W5 i1 B' Q0 e: Q9 [
' q# I' R* q& x3 p
void        APU::LoadState( LPBYTE p )* k; P5 i; p: |& Q9 s( s. o; ~
{
" p7 A+ n+ d9 G' x        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
3 |, d- j9 L1 V        QueueClear();5 E- D7 w" I/ m' B6 `2 _+ w0 w6 l
( s% e7 f3 D4 G; j: y3 v/ g( f8 _
        internal.LoadState( p );
3 ]  }' }7 p& r        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 f. s5 X0 K0 q4 R) _

" `7 b% L2 \& l7 W0 m        // VRC67 G$ ~7 Q% P: n. k
        if( exsound_select & 0x01 ) {
" S$ Z5 h: Y* M! Q0 B0 F' V                vrc6.LoadState( p );$ B! s" ~8 R& Y- H
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding  O# r. e5 E# `, j5 y
        }# V7 j" Z8 m9 `: l  R  p
        // VRC7 (not support)
8 |1 i' }* V. o        if( exsound_select & 0x02 ) {3 a2 W8 f) A8 ]( ~* S; A
                vrc7.LoadState( p );' g+ R0 n5 V' y& w1 s2 |* R
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) A# b- p) d! p9 i9 F9 @' ~- d
        }" v. X' R6 D6 x8 J
        // FDS' M9 ^: z9 S# p5 R, J+ K2 A! a
        if( exsound_select & 0x04 ) {( T$ j9 J& ~4 g  m
                fds.LoadState( p );
. O5 Z6 H. @$ [0 }6 G0 E                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  `9 N8 Y0 q( {. \& t1 P* [        }
4 C% o7 L# R# o7 m# K# `        // MMC5
. q5 F7 R! e/ y# J9 s( F5 O8 d        if( exsound_select & 0x08 ) {* E' K1 Q) O- Y+ [
                mmc5.LoadState( p );
! j9 b; X+ r5 b1 Q7 x                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* v9 i) Y6 k' P' E3 g* y
        }) y+ ~, X4 I0 {/ Q8 p
        // N106) `/ G' q$ C" n0 |
        if( exsound_select & 0x10 ) {
% Z. r: t- D, L6 ~+ Y( Y                n106.LoadState( p );7 {$ W  f: I% Q- K* K0 }3 S2 ?7 c3 J
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# h7 q- B5 R, r1 Z+ V5 B+ u
        }* E! S) ~7 M0 q+ ~, n
        // FME7
$ f9 Y" n  G4 L, ~        if( exsound_select & 0x20 ) {% ?, K2 [; o  B" k: i
                fme7.LoadState( p );, W* X, t4 m! d6 C$ d  n, Y( H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 ]& ~/ q) @9 x2 @
        }( X1 e9 ^2 g: U6 u- p7 \/ r8 N
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 & W0 k/ q4 N4 n6 R
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。% `* I7 P$ _: m( T' D6 {! i
感激不尽~~

% e3 [) w7 F' ^' T# x" ?恩 我對模擬器不是很有研究,- A1 O! q- Q2 P% H
雖然要了解源碼內容,可能不是很困難,1 J  j7 c9 W, T/ w6 F7 q/ L  Q
不過還是要花時間,個人目前蠻忙碌的。6 B' C+ ^8 x# C- q( t  z! z
$ y4 c, \7 F% G& u
給你一個朋友的MSN,你可以跟他討論看看,
" y% ]- p6 q  M! T  }* U& X& ?6 G他本身是程式設計師,也對FC模擬器很有興趣。
9 w; K% V( }6 `7 d8 T* K+ W
$ @* o$ I4 W* a& [' BMSN我就PM到你的信箱了。) C, e) J7 _- P- J  B/ H* n
# P6 u" h. }) U. C. T
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
/ I9 ^" k$ h1 c* L, T呵…… 谢过团长大人~~

8 r" m8 k7 k: O% ]( f
1 @8 L3 |9 t1 N. N. k哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ' ]# Q" `8 M6 i( i  M% }
团长的朋友都是神,那团长就是神的boss。

2 q0 _6 s; T- Z, x哈 不敢當,我只是個平凡人,
. x4 M) ~) `5 j# R要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
% L6 D1 M  `& {3 C  h( m0 tZYH0 |1 V, J. A1 @5 h) Z
QQ:414734306
3 W* }% A' C" X) P& [' xMail:zyh-01@126.com
7 B- p0 w+ U7 ~$ |% a9 q; r- ]' @; p7 o% R
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 y; e7 k+ i" }9 E3 B% }
再次对团长大人和悠悠哥的无私帮助表示感谢~~
5 ?$ ^2 ?8 T; |0 W/ ^' {$ t
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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