EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 ]; o6 l9 z, k' L- @
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 U  M7 M" u/ s' c
这里有相应的模拟器源码,就当送给大侠了~~
& \5 f. |" N: o  C4 m3 \& Zhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ; r% _6 K3 {+ l
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 _8 `" E3 c' r8 a, e2 L4 n) V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. S7 c  O4 V3 U- |' W4 u8 }这里有相应的模拟器源码,就当送给大侠 ...

7 }- m* r# \; Y* k- R0 D7 q聲音部分(Audoi Process Unit = APU):5 G8 p& R2 E& _& y& @3 [
.\NES\APU.cpp. I' k7 f& T# Q1 `$ ]- c
.\NES\APU.h8 u1 A4 Z/ Y$ u  Q/ p$ c

: `3 m8 u7 J& ]. ]3 F! F( m! e+ q& G+ g, {# q$ |# s( P# f
影像處理部份(Picture Processing Unit = PPU):
: r3 V  M& ^5 b2 A2 T# y.\NES\PPU.cpp
9 P0 `/ S! w* d1 c  I( m.\NES\PPU.h
9 o# ?4 q% r  s! d$ r1 E  C, I- `+ Y1 ], g/ z2 R8 X. M; B
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 Z' k- f$ C/ H3 ~- ^) S1 W
(由于很多专用术语和算法机理都不明白,所以看不大懂……); X3 t- d( n2 Q3 v% |2 a
//////////////////////////////////////////////////////////////////////////+ a& S0 Q( K7 l4 J
//                                                                      //
3 W. b( p7 y4 y. q//      NES APU core                                                    //+ A- v& r7 C$ _, e$ a
//                                                           Norix      //# h. a+ i1 b1 D, `, T
//                                               written     2002/06/27 //
6 K, L/ B$ t  c( [2 E$ i//                                               last modify ----/--/-- //" P2 u2 i8 l) m/ o
//////////////////////////////////////////////////////////////////////////$ O; V8 x7 ^( W7 f  o' H" j$ V
#include "DebugOut.h"& n. v0 g" R# Y! i
#include "App.h"4 I$ g% w" ]6 C: R( a9 z
#include "Config.h"
! i/ u0 i" M# `( K8 O9 |' o5 W1 X' B* X: }% y- M2 y$ W/ X
#include "nes.h", ^* y7 L6 P+ H8 D
#include "mmu.h"
- @0 M1 ?( Q; I* u#include "cpu.h") B/ z/ f0 I* l* x  r; ~
#include "ppu.h"
8 J, r! m  u1 }9 ~#include "rom.h"
$ [. }8 A0 ]% W. C/ ?( d#include "apu.h"
; ?+ q8 ^: A5 t9 z! O5 I: S/ ^. l
5 O/ |0 p4 x4 y, J7 d: U+ w, W// Volume adjust
- j1 v; P( m: Q/ A8 P// Internal sounds
: ~+ [8 {% d( z% B/ t! S, B6 E#define        RECTANGLE_VOL        (0x0F0)7 ^' l  ?" l/ C- ^: c) B$ X/ {
#define        TRIANGLE_VOL        (0x130)$ J% F2 O5 P. M3 r+ y' @
#define        NOISE_VOL        (0x0C0)) z! X) ~$ X0 l; n- u
#define        DPCM_VOL        (0x0F0)
' n6 X; C/ V( }9 S! Z/ `% I2 R// Extra sounds3 I7 W6 ]' V& J! H
#define        VRC6_VOL        (0x0F0)
, x* k- q# r- o0 B& }! `#define        VRC7_VOL        (0x130)
' t4 ]1 x6 I9 q- i8 o% u1 S9 F#define        FDS_VOL                (0x0F0)* ^) l) @7 b8 s" J; {
#define        MMC5_VOL        (0x0F0)( l" a: ]9 ?; a1 r( ~" q; R
#define        N106_VOL        (0x088)
+ R9 V4 z' k( E+ q% ~" b2 Z6 b& k$ u#define        FME7_VOL        (0x130)
$ {' t7 b2 g" @& ~2 V( _0 E- e; v' V/ S2 j3 s1 x* b2 ^
APU::APU( NES* parent )
) I, U' `+ w" q& k9 i8 X" ]{
6 _8 i4 |6 l! |- ?, P/ V        exsound_select = 0;3 j5 z. u8 F1 x  N/ Y. A( N6 g: @
; o+ e9 J& @- ^0 |6 u2 ]: d  V
        nes = parent;
* ?0 P( }6 J2 |. v8 f        internal.SetParent( parent );8 }# z' I* ~4 H1 g, p8 ]" {. P

6 G* Y4 f: q& |% a0 c2 Q        last_data = last_diff = 0;
; L* u# j, x' s- s" m9 G9 m9 m! k
* x4 z& _/ L! A1 @" i        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
; |- W9 x' l; m- `. J( ~+ P" q+ g( F9 |  t$ h( h
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
0 z' G, I, k3 B7 J0 o* R        ZEROMEMORY( &queue, sizeof(queue) );
" v/ Z& O7 s: H: r+ j        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 G; f' Y; l2 Q6 w
6 P, n* K7 ~6 t; v, w. O
        for( INT i = 0; i < 16; i++ ) {
$ c7 y% D0 K+ B+ {/ W7 [3 r# o$ t4 _                m_bMute = TRUE;4 z8 @3 Z* E6 h1 o( m7 }+ m
        }9 O- m) \: H  h& l( ]8 q6 c
}- z) k2 x7 v+ [" J9 ]  ~

2 X6 U) i) q/ o6 o" nAPU::~APU()# J& q) e6 ~4 P
{
9 l; P4 @( q; Q. t}
  d5 J. A6 l5 e, r- C& }3 k5 F' ]
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )! i7 J5 w8 C8 ?& G% m
{
! X9 G+ Z4 Y- p0 s+ J" ^! L        queue.data[queue.wrptr].time = writetime;2 @5 _, y: F+ T3 f: {/ T4 u1 e
        queue.data[queue.wrptr].addr = addr;* T) d, M. a  `% b" }
        queue.data[queue.wrptr].data = data;2 S( \& ]8 l/ S* |
        queue.wrptr++;
8 a1 d3 z& _; P  V- w* H% s        queue.wrptr&=QUEUE_LENGTH-1;
; C+ w. |; u+ r( |9 }. {5 N2 J6 _        if( queue.wrptr == queue.rdptr ) {3 n/ ?  ?  h7 j5 C0 u4 T
                DEBUGOUT( "queue overflow.\n" );: _5 \1 C  Z2 L
        }
# P, ^/ t6 D" C}
5 r" l% k, m& B" H9 ~/ @5 C/ C# x/ |
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )0 d& U( B9 B7 y# g* U0 o
{
8 t6 }4 m1 d2 L* d" c0 ~, M        if( queue.wrptr == queue.rdptr ) {
% j/ i" b, F+ ]                return        FALSE;
4 f  `% v- M. j3 g! L0 q; M        }3 _9 \+ V0 V# e) T
        if( queue.data[queue.rdptr].time <= writetime ) {
$ Q# U+ D& G* p8 F% n' ]+ w                ret = queue.data[queue.rdptr];- d% y$ m1 ^5 a
                queue.rdptr++;
6 t- H; y9 b" Q1 O" P* @& t9 n7 U                queue.rdptr&=QUEUE_LENGTH-1;& r8 U' U' C7 d1 D% g& Z7 W6 Y
                return        TRUE;/ H% W- k& x* f
        }5 q* }3 {. l! v9 M0 ?, V
        return        FALSE;
, w2 {, N: D" P# H}
8 W& y( ]. u# {) S9 m% o- k1 U& O& n0 b+ J/ T2 c4 f2 c8 d
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
! s- v, S  G  D{( k8 x0 q0 r2 K/ P7 |
        exqueue.data[exqueue.wrptr].time = writetime;
+ c7 G, Q$ L9 @" M6 N        exqueue.data[exqueue.wrptr].addr = addr;/ @- {' x/ o1 c, P7 Z
        exqueue.data[exqueue.wrptr].data = data;7 F* ^, o* e4 I; j
        exqueue.wrptr++;8 ?+ ^" g- _% U7 N
        exqueue.wrptr&=QUEUE_LENGTH-1;
' ^% x' T1 Z! p7 g. N) H        if( exqueue.wrptr == exqueue.rdptr ) {
; W3 T! [4 T8 D7 U9 W                DEBUGOUT( "exqueue overflow.\n" );
# B3 |7 Q' e3 l& P0 M# _& T        }
9 ^# f8 S5 b5 i+ e* z, l& W  G/ W}
  g! Q# H' k+ Q! A  I4 V' s7 X$ @: l
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. b. G  e6 b. d" g" l; [* }{
5 y& c3 A2 }/ D2 w; }/ S  q        if( exqueue.wrptr == exqueue.rdptr ) {
9 n2 S/ j; W. @# V, t3 W5 P' O                return        FALSE;7 l! l* @7 s% v
        }0 Z# Z- K. _$ G
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {# C% T0 Y/ @6 v
                ret = exqueue.data[exqueue.rdptr];
' H$ c" N4 o2 w% k                exqueue.rdptr++;
+ v6 d! c" k+ q; @                exqueue.rdptr&=QUEUE_LENGTH-1;, d: V. x4 w* U. r: b
                return        TRUE;
; h# g' f, l; M3 x, M8 o0 y& w        }
/ {$ n$ e5 u  O, W& Q        return        FALSE;
: O' G7 ]* q# ^2 {0 f' {* i}
  k! ~9 P1 u0 `/ m4 y- d7 m; E: q/ P7 i% R! L+ g
void        APU::QueueClear()
0 c- v* H8 [" k{
  U: O. E9 u2 K2 e1 X& T        ZEROMEMORY( &queue, sizeof(queue) );
$ c# t* e% |; K6 m2 L        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. `% x: M# n) I9 z! y# L5 [}
  ~7 U# z' O% E1 v
% i' e& z' y8 U+ ~" D( m" Z0 A( ~void        APU::QueueFlush(). a3 \6 J9 c3 W
{$ e$ t0 ^, q+ K1 k( ?
        while( queue.wrptr != queue.rdptr ) {
( C/ X( p& g6 [* l+ s0 A# |. M1 D                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
) ]  J9 |+ M2 }0 F: i! C# D                queue.rdptr++;, c) [$ @) h! C6 Y
                queue.rdptr&=QUEUE_LENGTH-1;
5 x3 g# N1 ~* O( \8 _: {        }8 C; m. D$ C! w# Q
" F; v. Q# g- b3 V) v. U
        while( exqueue.wrptr != exqueue.rdptr ) {
# w8 h6 G/ m. ]% k                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );) S5 l) L, D& x$ |
                exqueue.rdptr++;* S; I' r+ E8 f; q, y% e
                exqueue.rdptr&=QUEUE_LENGTH-1;
9 I- f3 C+ f% m& P, F        }
% a& ~/ h7 M4 ~% T* M- T; t}
% ^7 S1 m9 {" z( ^& E8 L8 m, M$ T; K8 e4 ~
void        APU::SoundSetup()
% T  r2 ]& I3 O3 Y: ]6 G{( ?0 i2 k+ @, ?% @$ U' ?( q
        FLOAT        fClock = nes->nescfg->CpuClock;9 l4 O" j1 X9 g$ d
        INT        nRate = (INT)Config.sound.nRate;# r5 y. _+ _- _- p
        internal.Setup( fClock, nRate );; d( d* L- R* r
        vrc6.Setup( fClock, nRate );9 @5 s1 ^9 v9 a: G- }
        vrc7.Setup( fClock, nRate );; n  s" K2 m# G7 M, [% `4 ^, C1 i! ^
        mmc5.Setup( fClock, nRate );
! V' k# `) N7 a+ D; k  ?" e        fds.Setup ( fClock, nRate );
" A6 k" e% K, ], o  z        n106.Setup( fClock, nRate );
4 A+ i: A5 o) N9 F/ ?+ m) l        fme7.Setup( fClock, nRate );$ z' E5 w5 e! ~. u, I8 O/ H$ f* a+ N
}) u9 X8 u$ ?* P- U$ T

1 i0 T" w% c- J. P7 p4 i  zvoid        APU::Reset()
4 U2 K  w. M& |( p+ s{) [7 K3 J3 m" ^" F0 _5 V
        ZEROMEMORY( &queue, sizeof(queue) );
* U! X3 m7 v; n        ZEROMEMORY( &exqueue, sizeof(exqueue) );; d/ f# J% t' P5 J- H) X

3 _- |: J6 G; ~6 C6 [" ^        elapsed_time = 0;9 J( P: n" f0 y* C, _2 ^& h

8 l' j6 i. }! X* K        FLOAT        fClock = nes->nescfg->CpuClock;6 Z, ?. a0 o2 v. }7 i
        INT        nRate = (INT)Config.sound.nRate;
3 s* I1 X. S0 h8 v        internal.Reset( fClock, nRate );
+ ]1 f/ G( g# d6 X" B" e0 x; V% C2 V        vrc6.Reset( fClock, nRate );
8 M: r) b/ f; V2 G        vrc7.Reset( fClock, nRate );8 d5 L- n; [3 ^' t+ I9 a
        mmc5.Reset( fClock, nRate );
) N( c6 }( Z2 c        fds.Reset ( fClock, nRate );
( B; m$ @" `; c0 Q; ?& A; q6 @        n106.Reset( fClock, nRate );
! w4 j% o2 x( h% e' }        fme7.Reset( fClock, nRate );
4 m8 A, P- |- c0 ~
& a; n% E, Q; J( x" {* E4 l        SoundSetup();
! ^5 L" `+ X  |: M. c6 u8 ]( V}
) `& z% d' l) w- e6 J+ H  y, Y0 p# X0 y
void        APU::SelectExSound( BYTE data )
- @; `1 U' P- B; s% i# x5 c$ L( U{
! b0 _, R" `0 e0 I5 o        exsound_select = data;
) B% Q, Y% H% \  d' H}
/ c" z5 q. v' |$ [3 L6 R" ]; f( `% A, }
BYTE        APU::Read( WORD addr )
/ c% @6 ?0 x4 B5 X{! R2 n6 W& X0 T& Z' v
        return        internal.SyncRead( addr );6 F8 U4 ~4 O7 b) d6 G$ E0 {
}# d! ]7 _0 U6 z2 u0 f

# L! x. h2 H, s- {* M. b; u" Y( J% Xvoid        APU::Write( WORD addr, BYTE data )# @5 |9 V  ~9 v0 |# u
{+ Z) k2 P. s7 X7 C; o
        // $4018偼VirtuaNES屌桳億乕僩
7 F* |* G! r- n' w5 n3 t; \7 o        if( addr >= 0x4000 && addr <= 0x401F ) {7 `& ^) A# e3 ?/ S5 Y" e
                internal.SyncWrite( addr, data );; ?' v, F+ v( v
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 N% |1 L' `0 g. g2 Q4 M        }
8 ], |" }2 L1 v3 z2 y}
4 w- G. n5 }! P  ]+ }5 O5 h+ F
( U6 A" ?5 c1 [BYTE        APU::ExRead( WORD addr )& p1 g  X) l( }2 {# y2 \! L& ?
{
, e, t6 r; ?, C0 `BYTE        data = 0;1 u3 j5 E4 ^1 w7 j+ R5 |- ?* w9 Y
, n" D: o+ \& }7 }8 f7 f/ o
        if( exsound_select & 0x10 ) {( ?/ F+ J% H* W) b7 ?$ [3 n6 E3 f3 ?
                if( addr == 0x4800 ) {
% p$ A) H; c& _                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
; C" l' f! u" o. a; E! O                }) K; ?; J0 X2 e0 B. d
        }
% D) g4 E7 _& F        if( exsound_select & 0x04 ) {
/ B& }* p3 N8 D' `, c                if( addr >= 0x4040 && addr < 0x4100 ) {
  s5 ^6 {, m$ O3 f7 \& W                        data = fds.SyncRead( addr );9 e, ?  y0 D8 Y6 U( }/ }- U6 e$ d: E; b
                }
# h, ^  C; G# M1 r) h8 d. z6 j        }% _3 a' k; _- U5 ~  ~- V$ W6 t0 f2 t
        if( exsound_select & 0x08 ) {
$ t0 o. ]) ~. F; b( G4 k) k. G, p                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 h! w5 c, X5 s                        data = mmc5.SyncRead( addr );. R3 b. D8 n3 K* }  a# R) G
                }
8 X3 x! k4 L5 ~' F0 Z# a' I( |9 j        }- T1 y  @# M) [$ {% e' I4 C1 r
1 q0 c' G$ m6 G1 {  y+ G' C% I
        return        data;7 k; D; s, F1 S* J4 A. {
}
$ A: `. s$ U& x; p+ i2 v- `! ~$ \1 @
void        APU::ExWrite( WORD addr, BYTE data )
+ o  V6 S+ U5 a" a8 U7 l$ H9 d{
- j  a: m& p) {( f0 w: C1 w  b* R        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 h  x) F4 S+ d* ^7 c- m
6 F' _+ f/ r: @- b        if( exsound_select & 0x04 ) {
% Y3 B  r0 Y2 ~( o9 _) T                if( addr >= 0x4040 && addr < 0x4100 ) {3 [) g, T  s5 R
                        fds.SyncWrite( addr, data );
( m5 p* \3 B$ \# P                }) J! y2 K, e* y6 h1 A8 M8 m
        }
$ i$ ?2 a+ [: L! f9 t, Y3 [$ s. P: {+ H
        if( exsound_select & 0x08 ) {* d" G6 B7 w# l- }( G( y
                if( addr >= 0x5000 && addr <= 0x5015 ) {7 f7 R& d$ E/ Q! ]; t. S
                        mmc5.SyncWrite( addr, data );
9 }* @# T, Z  W# a4 E. Q. [                }
7 J* Q$ [  l4 Y5 Q1 \% E        }
5 `& J; m( l. b5 M! N' l}3 {, i* K) D9 r6 m$ ?: u+ @* C

9 a- g/ C# ?6 V- j2 t- s& }6 Hvoid        APU::Sync()' V& N( U- a" M: B/ n( l6 G$ f) v/ w. P
{$ j  B9 _; @* n
}
4 u, P5 r, ]4 I" l- x: Y
0 u/ W, r& Q* X; u4 L; q7 Cvoid        APU::SyncDPCM( INT cycles )
2 O' E3 s: B$ \) o{8 o$ [. }5 m/ v% i, ?
        internal.Sync( cycles );
8 ^8 k. P! `3 C) n4 f- ~- A- b6 g( G( e6 i8 l' e
        if( exsound_select & 0x04 ) {
) f4 O. ?+ i  N$ |  {1 P# ?! K                fds.Sync( cycles );
* s' V" K( o* U# Q        }
( `5 x5 {( }3 |- F! n  q        if( exsound_select & 0x08 ) {3 F* {8 S6 A1 E: |9 o: u% K4 l
                mmc5.Sync( cycles );
% q8 c, R4 L6 U2 w* g: L* {        }( J9 B4 `' ?0 {- _  U& x
}0 o. }! `+ C' I8 m
  x7 R% J# r2 i1 @/ x
void        APU::WriteProcess( WORD addr, BYTE data )% H+ ~' T* a/ P# C- u0 u' q/ b2 X
{7 q( N5 a% }  S' A( Z. Z! D. b5 y2 x
        // $4018偼VirtuaNES屌桳億乕僩& g3 G% y- [. y( m; F2 ^  e
        if( addr >= 0x4000 && addr <= 0x401F ) {2 L* p6 w" P) _( Q7 B4 A$ v
                internal.Write( addr, data );
! R8 d) @! V/ g0 ]) K7 ~# f3 k6 E2 X        }7 b; B0 m) A" r1 O) f
}  _' Z8 p) \9 K# U# K

: Y6 t% |: I: H! Cvoid        APU::WriteExProcess( WORD addr, BYTE data )
) }; f5 B0 C3 v+ q9 A6 ^. ~2 \{
) |3 G* R+ [6 k5 S0 U" k        if( exsound_select & 0x01 ) {, b/ t. @  u7 e, w! c+ Q
                vrc6.Write( addr, data );4 ~1 j1 L  B: ~* q% t. c* C  P
        }0 n1 d" U/ v# h' k: ]$ o
        if( exsound_select & 0x02 ) {
  c8 P; r1 s0 u0 P# N. a                vrc7.Write( addr, data );
/ Q- b2 o, C+ F$ o" T        }
4 A& {( a% q7 }$ G) C, ^        if( exsound_select & 0x04 ) {- o: R; }7 m6 q+ h5 S
                fds.Write( addr, data );% i+ h2 A6 I/ l5 ~5 L1 M
        }0 U# S% h' e; F' y  l: [
        if( exsound_select & 0x08 ) {
; e9 I; ?. p: F. U                mmc5.Write( addr, data );8 _2 [" j' h; J5 V
        }7 k/ X( z+ j& n9 v( `8 `9 z( B
        if( exsound_select & 0x10 ) {, v1 W1 b# a- N9 j
                if( addr == 0x0000 ) {1 c: D: r$ k* N4 k
                        BYTE        dummy = n106.Read( addr );
1 R/ Y3 L  g$ y0 l  M- o                } else {
6 u6 Z* B1 q8 F/ A6 {# \                        n106.Write( addr, data );
4 k: t6 m& R+ y9 R. B                }. e0 p& O2 p& R9 z& K1 h  N
        }
6 n/ o; Y2 T' g* ^; X8 _        if( exsound_select & 0x20 ) {6 A+ d8 H1 j1 [  `9 G
                fme7.Write( addr, data );, N# h( {& I1 v
        }6 f; k9 T# q$ O+ ^6 C/ I0 ]5 M6 q' y
}
& w7 G% q& {: i4 C' a. C: Q, P; R& \9 y' v8 t/ o
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )4 J+ h% a" Q2 l) o
{* `5 h7 Q! y0 ?, Y7 q8 R' J6 o
INT        nBits = Config.sound.nBits;
! y: T2 c  W$ Q( f* f, o! x  DDWORD        dwLength = dwSize / (nBits/8);
% |$ o+ `+ o* u* z& kINT        output;1 l  t  W: f0 J5 ]. f
QUEUEDATA q;) X& r' s- O# Y  r3 }
DWORD        writetime;
! Z6 Q. R: {! y6 a) q3 p& j# F8 d- G
LPSHORT        pSoundBuf = m_SoundBuffer;
( Z  T. n. l6 OINT        nCcount = 0;" x( s* A" D! `
, ?% d0 N' F/ c" b/ @. U
INT        nFilterType = Config.sound.nFilterType;: [2 e8 I) s9 i  t; D% }
6 _& ]# {* E& r  ?
        if( !Config.sound.bEnable ) {
; D& m, y$ e0 v# X2 d" p                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
& W- y' p/ p6 M1 r8 A5 \) k                return;" V: g3 u5 x( i! l8 s' _3 K
        }: y. m( M1 F. r2 K& X% w) C

/ C; W: u! Z0 @) P! c        // Volume setup- u, m& @6 q0 I1 |8 m
        //  0:Master5 H* x) }, q  g, ]* c
        //  1:Rectangle 1
' o  R/ Q9 [: r: v4 q        //  2:Rectangle 2
/ i1 `) N& m: i2 ]& D4 t$ }  K$ D        //  3:Triangle
. ]2 b- M' K! c* f) ~) |        //  4:Noise, `& z; s9 h( w, S$ j! A% c
        //  5:DPCM' ^$ X6 N' P5 G
        //  6:VRC67 S+ F" E/ B; ~  P4 g
        //  7:VRC7- K5 x# T0 O& F* s# f3 Y
        //  8:FDS
9 r$ Z8 D$ {% [        //  9:MMC5
5 ^$ x" n  Y6 D0 \' r        // 10:N106
9 N# Z0 F) \. |        // 11:FME7
7 J6 J' f7 J/ t% w. [3 K9 `  o        INT        vol[24];
' r4 `7 M0 c% V, L. |5 h        BOOL*        bMute = m_bMute;
* o% f5 q) a5 z* t3 t( e        SHORT*        nVolume = Config.sound.nVolume;
$ O7 Y6 y1 C" ?8 n/ F1 f; o( t& l2 v! P, N* n
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;% P) X3 o8 A! u) q$ P8 d( M
' q: A( X4 D. s: m" e) D9 M
        // Internal
% w: }0 d. A" A! d5 ^/ I! Q) B! a        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;. T1 V0 Y8 q2 M0 [
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
3 G5 s) ]; }5 g        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 w$ c8 i! x! T/ Z8 ^, S
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;* D& j- S% _9 N  }
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ H' k. M2 O! H6 o) D0 E( b; m% L' y$ R
        // VRC6/ L& w; _1 t2 S/ d6 c9 K  y$ B
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( A" i& `. m0 q, d        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( Z; `* x4 c- A        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# Z. i2 R. a- P# ~
) T: M* J8 W1 }' P+ }& }7 Z9 d        // VRC7
2 @7 d6 y, p2 i        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 Z" c( a* n: V- j: w" y* T

  L# [3 ]/ J; B# Y4 O        // FDS
( C3 v* Z2 q2 [5 g5 R4 }        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;5 \9 ~9 |' d, B8 [  [$ S
4 B5 v, f% I! I4 E6 v" V' Y
        // MMC5. g) g3 s1 s( _/ q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# m  h+ Y8 |& ?, `        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; X4 h5 [5 F7 t0 B1 r
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 A# _2 Q" p3 r% f5 A9 o; Y- j" J6 {) _7 q8 _7 a3 k9 J7 M
        // N1063 t! C$ ]8 ^; ~7 Q2 q8 E# Z$ \" `4 d) V
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ k3 T' [: Q7 S7 G2 O
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ {/ l2 J. C- I4 v$ [
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: A% h: K* E' J& l1 B* {
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 t( O4 F4 c3 C  c3 m        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 P: w  R8 d# t) @* |6 j# [
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" M- \+ t" r. m4 Q4 g
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ b! b4 q7 O1 q1 y% M  n( f        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. ~( w& [! {9 E
, U" u. d8 a  G8 d3 F! O
        // FME77 U$ w+ r3 e2 b# P  t- h
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 D0 m4 k" T: k
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
( h* u8 J0 H7 t  Y5 r  D        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- _8 i! [& Z; @4 i$ l
! z, [- ~: F* a4 d: ]! W
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;1 `8 O0 t' }7 R3 j: s7 g
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. L2 v: E4 B, ]. r0 q3 R5 T
0 j7 k- s6 d# s: }$ ~2 z        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ E8 I: L9 H5 X        if( elapsed_time > nes->cpu->GetTotalCycles() ) {" `7 X# ]7 [7 k+ G" y( ^
                QueueFlush();
" a# Q) }& j" U  q+ d' R7 F        }# D# L* F2 I0 Q' ~2 N- v- c4 J
% o1 z, s% L1 r, E
        while( dwLength-- ) {  E0 X  Y. f; S7 O! n% e( h# E) j
                writetime = (DWORD)elapsed_time;" f0 R2 G8 K- H6 S
9 X2 y; G& T# M- C) }* c: j& a4 |7 e/ g
                while( GetQueue( writetime, q ) ) {
0 d0 x. o. e9 |. S                        WriteProcess( q.addr, q.data );/ v9 t7 \. V9 D- S. k# L9 l
                }
+ c2 ~6 n0 P3 z
! R$ L1 x* G  y8 e4 `$ d: c                while( GetExQueue( writetime, q ) ) {8 R  r8 @6 e/ I
                        WriteExProcess( q.addr, q.data );- _2 q4 x) P7 L9 F2 A# A& _# ^/ d
                }3 P5 A) E; z' r9 D6 [4 X( I& c; E

" }, Z$ A$ n: ^" m                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 K; y& y, {0 b% R' n: l                output = 0;
0 v( |; J. D# `- i+ h" z& Z                output += internal.Process( 0 )*vol[0];
/ l7 z3 j" g( v% U) V                output += internal.Process( 1 )*vol[1];5 L- G; n9 u+ l4 {3 H: q+ p
                output += internal.Process( 2 )*vol[2];! W6 s1 j$ c" V8 W  D- F! ^
                output += internal.Process( 3 )*vol[3];
+ W5 a% B" I  W; J6 K0 M                output += internal.Process( 4 )*vol[4];4 \' L' n% s2 \
5 Z9 f- v6 \& t. Y8 Z) m
                if( exsound_select & 0x01 ) {
/ E# A* X) w3 R                        output += vrc6.Process( 0 )*vol[5];
7 ~/ |; [2 T. U1 }% D$ r( ?                        output += vrc6.Process( 1 )*vol[6];, I5 V; X  t" p
                        output += vrc6.Process( 2 )*vol[7];
! n/ }, {' o. \, u* K: z                }
& E( o. W1 L5 h# k1 @/ h6 W2 r/ Y+ q                if( exsound_select & 0x02 ) {: t' p: s& P1 O% c7 i- _
                        output += vrc7.Process( 0 )*vol[8];
0 N$ x# N" ]6 v. F. d1 t                }( h- Q9 @6 g! C* J
                if( exsound_select & 0x04 ) {
( j( z$ U" o% T                        output += fds.Process( 0 )*vol[9];6 L) q5 f+ @6 j( p/ w2 Q, B
                }
$ p2 Z* r* [- ?# V. E# A! r: L* r                if( exsound_select & 0x08 ) {
3 K, h- u+ X$ _: u% f# ~                        output += mmc5.Process( 0 )*vol[10];
( f5 I+ G9 M3 p2 p! e4 F                        output += mmc5.Process( 1 )*vol[11];
5 w3 ^$ |+ q. Q+ J9 o* q                        output += mmc5.Process( 2 )*vol[12];
& p# w4 _3 l3 ?. K( b- l                }
/ {. y" c: @7 p; @1 Z                if( exsound_select & 0x10 ) {
; v. x. t' x4 T4 P                        output += n106.Process( 0 )*vol[13];
, l% |0 Y/ b3 x3 d( n2 |                        output += n106.Process( 1 )*vol[14];
; |" |7 o8 V- G- U                        output += n106.Process( 2 )*vol[15];* c; V1 V8 j& |6 @8 @3 z
                        output += n106.Process( 3 )*vol[16];, l& ]& N# J  a9 I
                        output += n106.Process( 4 )*vol[17];% R# [; z* [; {% ^0 a; Z
                        output += n106.Process( 5 )*vol[18];
- b2 \& e, _. t& m                        output += n106.Process( 6 )*vol[19];! ]% ?2 ?* P2 e: e
                        output += n106.Process( 7 )*vol[20];
3 {* T! \9 e# j  c5 D; q                }
0 x  _# v2 \% E: J7 d4 M9 P                if( exsound_select & 0x20 ) {. e- `7 u* Y% @7 ]* W
                        fme7.Process( 3 );        // Envelope & Noise3 M) B/ `$ k4 v+ h3 l% X
                        output += fme7.Process( 0 )*vol[21];
& O6 o; R8 r) d' Y) R, P                        output += fme7.Process( 1 )*vol[22];
) t: L# s6 D+ d, m$ I7 U: M                        output += fme7.Process( 2 )*vol[23];
5 F! A# a* K; J9 _2 i. r! A5 a                }( r4 w0 [, t- T. N4 X
5 G# u( N" k0 a4 L: I
                output >>= 8;
6 v, A. c$ {. s+ q
9 E. e' P8 r' F! s) c) }3 y0 M  u                if( nFilterType == 1 ) {
$ V6 v/ `7 e* }* }$ M6 S- U                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)* U% u% w- H3 |$ e* {
                        output = (lowpass_filter[0]+output)/2;- `4 B9 n2 P% q
                        lowpass_filter[0] = output;
/ s+ U( [+ d" t4 Z( L: i                } else if( nFilterType == 2 ) {
' [: I& h1 |1 D' Z                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
) b5 _# i1 |, G' r                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;3 n- A* t+ R( d
                        lowpass_filter[1] = lowpass_filter[0];
1 U. V3 k  [7 a) V* Y- `                        lowpass_filter[0] = output;$ \7 U' w( \  D+ v
                } else if( nFilterType == 3 ) {( l: g( A9 \; E
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)+ e$ z6 f$ Y9 U' ]
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# r/ Z$ d/ j' `+ k0 w0 a                        lowpass_filter[2] = lowpass_filter[1];
0 [& K" j6 h4 g! U! U3 ~; D4 p4 P0 Z" K                        lowpass_filter[1] = lowpass_filter[0];& B, C& w. B7 s8 y- Y4 u2 b1 E9 ?; M5 Q
                        lowpass_filter[0] = output;
0 f: O" R7 x' w& \                } else if( nFilterType == 4 ) {$ D: V/ q3 i* C
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
# m7 D5 F0 r+ B6 f! Y" B# X1 U                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;9 D: Z" s# S% a7 w7 t7 s
                        lowpass_filter[1] = lowpass_filter[0];
  [; c6 d! ]  {9 w7 `& D                        lowpass_filter[0] = output;
# B) }+ l7 s) R1 n$ b: {* Q( A                }) m; s' m% P& t4 ?
- t! E; R, W9 L2 F
#if        0# K5 r! M3 Y2 H1 C& I
                // DC惉暘偺僇僢僩# G% K: h6 c& z# Z
                {5 l- L: z% F% o7 c( O
                static double ave = 0.0, max=0.0, min=0.0;
2 R/ q# g6 ], m3 p  S                double delta;
0 K  X' C1 H( ^: b; X                delta = (max-min)/32768.0;
- W7 r. H& [3 u                max -= delta;9 I6 |) c8 s, m$ R) \3 I, d
                min += delta;
6 W" W( f) D9 p3 [- D! `& m5 N                if( output > max ) max = output;
! |6 k8 c' G0 t, k- U0 u                if( output < min ) min = output;
5 V. V2 U0 {' c! r                ave -= ave/1024.0;5 t6 _9 q1 @) J- K( u1 ^( {
                ave += (max+min)/2048.0;1 g6 [  ?5 t/ z$ y3 B8 v( `" Z
                output -= (INT)ave;& v: B, U7 F+ T5 q0 L3 U
                }
, O- f8 ~. M% @% x#endif: c9 M/ F% z, ^
#if        1+ A! @& S  F* d
                // DC惉暘偺僇僢僩(HPF TEST)7 E( O' A( W  |! G+ _
                {
) Q: V& s' [+ V//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
1 N' L' k+ \' }9 H7 @% w' [# `                static        double        cutofftemp = (2.0*3.141592653579*40.0);
' I' A4 f$ U3 g* H( h                double        cutoff = cutofftemp/(double)Config.sound.nRate;+ w/ H$ o) p2 M) c
                static        double        tmp = 0.0;
7 w- N( w- s$ X% v( h, Y                double        in, out;
9 t3 z! P7 }0 D* a. S9 n7 f: z  t" _% F+ F
                in = (double)output;
0 L, R% D3 l0 j- h  z                out = (in - tmp);/ _8 y0 N4 Z4 H, _! I9 i
                tmp = tmp + cutoff * out;
, P% i2 o% f, k& e* U* f
  R5 C5 J3 F& j& s  r                output = (INT)out;
4 }1 R# B$ d- l7 X; k- a% h- T                }
: V: w% W1 {, W) |( o3 A#endif
8 I$ a- {: \* M/ x; [8 f#if        02 g0 x% U; r' Q. n4 y* o  w
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
7 n2 ]6 ]$ c3 y) ~  l                {
5 L& t7 q& J/ r* j8 L                INT        diff = abs(output-last_data);/ R  p( Q( {, K! T. w7 h" I
                if( diff > 0x4000 ) {
1 J1 V3 q  s) E1 H  R                        output /= 4;5 ]$ ~8 U4 U" ^) h
                } else . F* Q' b& M; t5 g( Q) _1 z
                if( diff > 0x3000 ) {
" G  e; i% f) u! }: B                        output /= 3;
3 q' d/ B/ j) ]0 i) G                } else
+ ?+ z) L8 z9 A5 H. y7 d( A                if( diff > 0x2000 ) {
; M" o2 S2 V) y  j                        output /= 2;' u% r/ j1 `" s
                }
* Y. Y3 \- @6 f                last_data = output;0 _5 q/ i, N. ~- ~# P
                }
0 _3 p: L( j- n0 v$ x' f#endif
8 `4 G% x: X" Q' w, z( t8 Z* z6 ?) U* N                // Limit
9 r& o% R8 A; G# a1 F* m! P% k                if( output > 0x7FFF ) {% x; Z5 i- K4 T, i5 W& w7 k
                        output = 0x7FFF;' g% m/ e$ I7 A2 Y/ a- U$ b
                } else if( output < -0x8000 ) {3 r' _2 F- X; @% c  o) C* V; E; O9 }
                        output = -0x8000;. v) T: H' g1 t5 v$ K
                }3 ~0 t; V9 Z  r; k5 T

" y2 Y, U% m* x9 b                if( nBits != 8 ) {- l' l6 f+ s/ s! U7 O
                        *(SHORT*)lpBuffer = (SHORT)output;0 q6 Q7 N( ~" B! ?5 C% E
                        lpBuffer += sizeof(SHORT);
% Y! b+ A2 x6 z. R  W% x                } else {& U- }2 i3 G& [$ X6 x
                        *lpBuffer++ = (output>>8)^0x80;- O; h# D/ q7 b  p! o8 J* I( C' W5 G
                }
4 m/ s& s) w% t3 F& v/ }
4 z7 j9 t3 u0 i+ o; d6 X7 b                if( nCcount < 0x0100 )
$ W' o, S9 s( v2 K% J4 b9 e( Y                        pSoundBuf[nCcount++] = (SHORT)output;
" I; `  g/ t* K" m9 B6 `( S) S1 q5 y
//                elapsedtime += cycle_rate;) h+ I6 G. W* n, {. s: p# m
                elapsed_time += cycle_rate;
" b0 V/ _9 j; r, I& b        }  o8 p; B6 H* F
$ z4 ^& a! H- v4 n3 Z* y
#if        1
& h+ R+ W. v3 h        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {+ v5 U: Y3 T& d2 `
                elapsed_time = nes->cpu->GetTotalCycles();
) l2 b3 X8 @3 P- q3 p1 E+ s) Z( V8 H        }  F8 `2 N! F, p5 @
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {5 P4 F$ X; F% k" C8 e
                elapsed_time = nes->cpu->GetTotalCycles();
# y6 s" s* u. F& W        }
8 e6 Y) b1 h6 Q1 e3 c* B6 F#else0 c/ b7 Z% V5 ]+ ^; R# R
        elapsed_time = nes->cpu->GetTotalCycles();8 M3 F$ I4 R$ j/ p8 T# r
#endif
5 k& V. G9 k% R4 v0 x  T}
- R" ?8 S$ m, @/ @! v: X+ i( u& w; f# Q5 ^9 b
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- ~) C) T( p6 a8 W$ {, nINT        APU::GetChannelFrequency( INT no )- E3 ~. \3 r& ~% A
{
% F9 w( [6 v- `$ O" N: S! |# |  R        if( !m_bMute[0] )! O* h0 t3 u  `+ n  w" o3 B
                return        0;' n% H9 G+ z' e" \

. j# Q# l2 e2 v! ]$ s0 E        // Internal
- B5 U4 v" [( G/ |( d8 r        if( no < 5 ) {
) q# F6 I1 {% s8 |. L( i+ T, q                return        m_bMute[no+1]?internal.GetFreq( no ):0;% S! A$ _5 g: z( A+ X
        }
$ S8 q' z1 _8 f1 i2 {        // VRC6
! Z; {+ j- r" X1 F- Z1 o        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
  W6 y1 F: O' }                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
5 j6 _1 {  N/ C        }) y9 C% J$ M7 j3 F4 Y
        // FDS
; n) f2 \9 D5 C4 M# P        if( (exsound_select & 0x04) && no == 0x300 ) {
' h4 g1 h3 m" ^! E3 G) R3 m                return        m_bMute[6]?fds.GetFreq( 0 ):0;
" }5 _' Z! s6 `        }8 ^( n3 U: E/ e
        // MMC5
/ R6 }0 P/ t8 U: R4 J( ^: i        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) [. b) Q! I$ ?
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;' ^) x: G; }$ `+ P. b6 a6 Q
        }
4 {) t1 _  `* t, V  x. T        // N106
$ |3 Q' h8 d3 a- X        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {% d  O& U1 @& C0 `
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;2 Z6 Z& T. `5 y- @5 W" v
        }" P$ o( e  M1 D
        // FME7# g& }; U/ I7 r1 V$ i' K2 g
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
$ E4 g* w) \% R8 L1 P5 v                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
8 g8 B5 i5 q; H$ L, T' B: y" w        }
) M% v5 b- G) d& X4 g# B+ T        // VRC7$ J1 V' A5 P3 |$ c# N
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {7 V; {( c) U) w; k. q* u& D
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
+ a0 G% W/ F2 a, w0 Y6 T4 W5 i( O2 A# A        }
$ |9 A$ G0 L4 m/ A. Y$ t4 I! n        return        0;
0 q+ G* x% y3 ]) \+ J; L0 Z' Y  C4 ?* e}- G3 }# |- w  O4 H3 c# S

) Y* {; s; T" a  H( S! ?# p/ l- t' v1 ?// State Save/Load, E4 {* s; Q  {. W+ h8 Q" n6 X
void        APU::SaveState( LPBYTE p )
$ t( `* P: V' f/ S4 j3 ]{
* Y* X" S- M; C* @4 H+ G/ X#ifdef        _DEBUG
% E: Y( N: q( n0 M4 t6 [+ e7 GLPBYTE        pold = p;' x. g  t% X- [/ l9 c6 b7 C
#endif$ G$ @0 ^, c  J! Z( F
# e$ m4 Q6 N4 K: {* g( b
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 g. n; b) B9 {( S
        QueueFlush();- Q: O4 p8 `( Y& c
! q  e0 q1 Y6 n; Q0 T' J1 }4 Y
        internal.SaveState( p );* x+ j! @+ n( h; \) [( A
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
- @. J# E- x" h& `6 s* `; M- R4 z+ f
        // VRC6% d' n5 A  Q: U- K; o/ b9 A0 ]
        if( exsound_select & 0x01 ) {7 }, U: M9 f( F6 b- A8 o/ A% }$ P, j
                vrc6.SaveState( p );
+ k2 J2 g0 K( h( f0 B$ V8 o; X% T                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding! k+ O- B, i- m4 L# V' U+ W2 \
        }
0 a+ o+ Y/ S% E( V- X% N7 a        // VRC7 (not support)
+ X7 K) V6 z& k: s% [        if( exsound_select & 0x02 ) {7 |4 X7 r) B) R2 v4 @
                vrc7.SaveState( p );: M3 S, j4 F- J, ^; {; i5 l) |  ]
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& j7 G0 `# J0 l+ S: C        }6 _( `8 p. w- M! f
        // FDS, [9 s7 g& T! F8 C. ^4 N
        if( exsound_select & 0x04 ) {  g/ N; a6 ^, ?7 r5 F# }0 X
                fds.SaveState( p );
- i# [5 Q$ X0 l, w7 o( j                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 e1 v' O; F5 V6 y/ n6 L/ O        }
# u/ P. d8 q7 M6 V        // MMC5
7 r9 s+ r/ G0 ~/ p        if( exsound_select & 0x08 ) {
3 U% {, a$ i- c: c8 o                mmc5.SaveState( p );
0 j1 t6 w; m$ V# q7 `9 `                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 \0 b' A& M/ m: K" v
        }4 ?5 ~' ~6 _) x, o  M, \
        // N106
) e6 V# s. p/ v! J        if( exsound_select & 0x10 ) {
% p, H% ?' i! c4 O# j* l                n106.SaveState( p );
( m. f) H5 @$ M+ \& H, A                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 a8 c0 |$ ~; q
        }# s% b* B% e. l; C0 n
        // FME7/ c: [2 u+ X2 @* h. X# K$ Q+ H; s
        if( exsound_select & 0x20 ) {
' B' _9 h1 n2 b" m1 l3 Z1 h                fme7.SaveState( p );
. l# ~% B* h. G% v- O" r                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 |5 \: A0 z! b/ B5 ^: z% B/ L& |
        }
& O9 ~7 |% f% I+ G; K+ d1 J8 R- B/ B! O6 O
#ifdef        _DEBUG$ J* Q* W0 ]/ h1 G& R
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
$ p# J/ k) e4 ]) ^#endif
# u9 y7 P; z$ v( E$ h}
+ w+ f+ r/ A* ~6 g7 J1 s
; c- R9 b# B, n! M& _+ fvoid        APU::LoadState( LPBYTE p )
2 U9 c* Q7 k9 P% ~7 s{, x# a( A. j& Z& N; b
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡) W( I1 V( ?$ W
        QueueClear();
& {2 Y' X1 q. R# Z) R) D5 m/ h7 I
        internal.LoadState( p );% b" S6 m; ]2 u9 m8 u5 D
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ u2 {0 k5 ?- U4 Y/ W/ i" t" E% y* v7 H3 C! J( q* e
        // VRC6
8 z+ h7 ]8 h% G/ t. ~+ m        if( exsound_select & 0x01 ) {
! E# H1 |: x" S" V8 a* a( Z8 ~                vrc6.LoadState( p );2 h& E- Z, A  L3 W2 Y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 t9 N/ O  c  i# J% g
        }
- p9 F" y# T2 G; h- F        // VRC7 (not support)/ k- m+ }) Z9 W
        if( exsound_select & 0x02 ) {
3 U! p" O# ?; h                vrc7.LoadState( p );1 d1 w* u) S' {% z4 I, e1 e; Y! R
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: O1 Y( d& y3 L0 |$ i! M        }
4 J: q4 u, [% u  H* c# D        // FDS
( w3 z; W* V# [. f" U9 u! \' C+ |        if( exsound_select & 0x04 ) {
: o: l- V" C" g8 {. }% C                fds.LoadState( p );) w; O; s# P) f  r4 p" i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 c1 n( W8 X4 S; D" C
        }
! Q6 Z6 x' m# z/ w6 C: r        // MMC5
& R& S, u$ x, b+ e0 F3 p        if( exsound_select & 0x08 ) {
5 P9 V% w& A! {3 m8 W                mmc5.LoadState( p );
3 L' n( S3 o' ^: Y6 X4 S                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- h+ m* F& j; i) q2 q. G0 V, W        }
, P% _  P/ y/ n) @7 J6 d( s  C        // N106) o0 r$ B' @& t& D8 @, L1 i
        if( exsound_select & 0x10 ) {
' m0 [$ K$ L6 S7 u! J1 v                n106.LoadState( p );, }% X- {/ ~4 q) [
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; E( ]5 ?+ ]0 J0 `9 x' C; p% u        }
2 e' ?0 O* c6 H        // FME7: C7 l; Q, V" v+ k5 ?! r9 Q
        if( exsound_select & 0x20 ) {- K$ o) v7 F, k: h6 v7 C! S3 G
                fme7.LoadState( p );
0 [8 N0 S5 j6 [9 i0 Q' D                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' W- L4 ?& [; I7 m# u& U3 B( x        }. N7 T  }, C% d+ K- ]+ h" V# a
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; V& k8 N) L) V3 u
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
# L) ?+ j- H+ i7 K1 d; q感激不尽~~
8 s' h( z% N  t- {1 E! t& \9 t
恩 我對模擬器不是很有研究,
% ^7 B: @! P6 x4 e3 s8 N  Y雖然要了解源碼內容,可能不是很困難,, d" ~  A4 Y' c$ S
不過還是要花時間,個人目前蠻忙碌的。4 I' X# c: r* n3 ~5 R1 K4 J

* }: Y+ `$ [: L' j# ^給你一個朋友的MSN,你可以跟他討論看看,8 A- G' W! k2 {( R
他本身是程式設計師,也對FC模擬器很有興趣。: u8 I+ a! E5 p* f- n
$ Q" T: y7 ^" k4 ?
MSN我就PM到你的信箱了。
- M1 f% u5 w8 N" b( x7 D1 G9 ?1 z- e3 d9 Y9 M( U9 ]
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' {$ B& I% Q4 {% M1 C
呵…… 谢过团长大人~~
: s* }* Q4 Q+ {7 s
9 _' D: C' m" {* U" l2 X
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
3 M+ D6 b5 C5 T0 L; B5 u1 U团长的朋友都是神,那团长就是神的boss。

% f" Z" {* _- V. x哈 不敢當,我只是個平凡人,! v' C5 S. T1 T2 h& h2 ]5 f
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙9 c/ P+ Y# h6 \
ZYH
2 M# q  D; p* l) t& e; HQQ:414734306
* h0 k0 y/ q% Q8 b% z/ K+ L! d0 P. qMail:zyh-01@126.com
5 f% N7 x7 L4 v$ Q5 B* B$ l7 @  j; [8 X2 T
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
$ z. [7 {5 [% m: s5 p1 M7 `7 k再次对团长大人和悠悠哥的无私帮助表示感谢~~
& u) {. y* }% H& D( @. b0 G
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-14 19:08 , Processed in 1.071289 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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