EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% N% R/ r* \% u( Y: T* K6 I楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* j' [  X& Y! d这里有相应的模拟器源码,就当送给大侠了~~
: U( b4 l/ }. D5 P+ {, f1 J, e: {http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
# b+ V6 E( l1 z8 }能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' h& r9 ~+ C, O9 {( g楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  V+ ~  b- M! X0 }5 H, e
这里有相应的模拟器源码,就当送给大侠 ...

& m# W( C6 {" f0 b/ q! o聲音部分(Audoi Process Unit = APU):
! ~, |  O2 S# F, r+ B" g! |.\NES\APU.cpp4 D- @$ L6 O1 I/ y7 Y: ]' r
.\NES\APU.h3 H  n7 H9 T2 e* X& d( L

5 Z* ]2 X& S! j& b4 e; j2 y. {, [& J: B% a, e
影像處理部份(Picture Processing Unit = PPU):3 i8 b8 R5 f6 i
.\NES\PPU.cpp
/ P6 s: r2 s! b* _  k.\NES\PPU.h
; O) g: U) Z* k6 x% G; M: b+ D& k0 o& _' j: u2 v" j
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
9 f' x4 u  J' ~9 m(由于很多专用术语和算法机理都不明白,所以看不大懂……)* r/ d5 S0 B. f) N" ^
//////////////////////////////////////////////////////////////////////////1 K  J, j0 f# U
//                                                                      //
- L4 L  x3 L/ B; E5 @9 {//      NES APU core                                                    //
) }# G! f5 q- y' \: `//                                                           Norix      //
1 y4 s! E+ j2 K1 A6 l9 S  h//                                               written     2002/06/27 //- A1 m: g# F: }6 {5 W
//                                               last modify ----/--/-- //# T' I9 x% }- E* Z0 Z% [
//////////////////////////////////////////////////////////////////////////
9 ]; F9 F. c4 q5 A. i) v#include "DebugOut.h"3 S; o4 N( I7 b) B' X
#include "App.h"* u8 P8 d( l0 Z2 C( @; ?) c
#include "Config.h"/ q& m) }4 O+ Z$ r
- e* O# \- p; q. H  h# b
#include "nes.h"  @/ x0 H3 V# K5 h
#include "mmu.h"& v" u; @, n2 }5 t' w3 R5 U- \
#include "cpu.h"
# g9 b0 M3 s; t#include "ppu.h"
5 i5 f3 b( ?1 z2 o" a#include "rom.h"
& J' b3 M, c9 N2 i  ~" o8 ?#include "apu.h") s9 _# |9 O; Y# f) |
5 n# p1 L- ^0 I
// Volume adjust
& N5 f* Z. i3 o* f// Internal sounds9 G* b  y" U+ b3 N8 s# W' n" @
#define        RECTANGLE_VOL        (0x0F0)
) E' M$ i/ F6 C/ {#define        TRIANGLE_VOL        (0x130)/ ?( D6 ^, q0 ~( ^  _6 m
#define        NOISE_VOL        (0x0C0)
$ }' J2 w; O- Z# o#define        DPCM_VOL        (0x0F0)
" t8 p5 K" }) D// Extra sounds' O" J& x6 W; q+ R' r
#define        VRC6_VOL        (0x0F0)1 G  y: o) D+ a& ^+ ^# g
#define        VRC7_VOL        (0x130)& |4 U7 F$ C4 c
#define        FDS_VOL                (0x0F0): u2 n- X# u9 Q# v0 B
#define        MMC5_VOL        (0x0F0)5 c5 W  J  Z& ^  ?6 Y
#define        N106_VOL        (0x088)
* S% k1 e) W4 {3 c0 w#define        FME7_VOL        (0x130)
8 g. B& n! W/ [, E9 n+ N0 e3 Y0 I5 g/ ]- w* c* Z
APU::APU( NES* parent )* v( Q; Z2 ^+ f( ^4 U$ }
{
" m3 z0 }  E# f* C5 I" {        exsound_select = 0;( w6 n! T( l" F1 D1 v  w) U: _
2 @5 i* R% S! O5 G
        nes = parent;# V7 B- h# u8 O9 Q/ `) z
        internal.SetParent( parent );
  ?: h7 [+ {# U% c9 v0 K, r2 y; h; D; E; T+ D9 F/ c
        last_data = last_diff = 0;
* _+ p' X  W9 e2 H! R1 b) e6 u7 p7 F' U  z
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 P% m/ \/ O' Y
1 }% t! Q: \% ~, B7 X
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );. D1 t) c  l/ x, p8 i( M
        ZEROMEMORY( &queue, sizeof(queue) );
" n& b3 E2 V% Q# w6 |. B        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ o+ F2 R5 X+ y& r; i; N
  K, o/ a! {0 _3 {9 u' b( l        for( INT i = 0; i < 16; i++ ) {/ D% o! Q3 M1 v5 H! s, M
                m_bMute = TRUE;
) V3 `. Z2 U. \  z" C, O: Q: T3 W        }
* R+ p- o+ E& X! I( @: d$ F! A8 H}
: B  c* i* I# T( n5 r0 ^# f  R
: p, S% ~. I; U" d8 QAPU::~APU()* w5 |0 @8 @5 b) F1 e+ i, y
{0 {; s0 G  p$ g; b' ]- c! e
}
. `: M; L* h6 v: ^9 q: O$ S- N% |& Q- |5 C# |+ E8 F
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )- P+ w- u9 S" B( E5 i
{
# ?: s; t2 e2 B6 i' h# A8 c- y( I        queue.data[queue.wrptr].time = writetime;# l: t% e9 o( `0 Y2 ~4 Y
        queue.data[queue.wrptr].addr = addr;
, g) d9 p3 r4 Z7 K+ X        queue.data[queue.wrptr].data = data;
) J1 u# E9 Z& Z4 [. ^, _3 m        queue.wrptr++;
5 u$ ~1 O0 G+ c. s( `+ d        queue.wrptr&=QUEUE_LENGTH-1;
9 _( j# ^5 Z' y5 A  C8 O        if( queue.wrptr == queue.rdptr ) {
; ^$ Y6 o$ O7 _4 n0 K                DEBUGOUT( "queue overflow.\n" );
0 j+ }' _5 L' n  g0 q( B        }* I8 Y$ \, [$ Q5 I# l/ b9 Z6 t
}) K, g* `9 x. z! F/ o5 g4 G$ f, o
" w" t. I1 s1 u' r
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- k3 ?# w% ^- n1 a{0 |9 U9 z1 u+ i, Z' O
        if( queue.wrptr == queue.rdptr ) {
7 y# g0 u% R" [# a4 p& x                return        FALSE;' h7 i4 P2 p3 t! {' c( @
        }
% H) O# ~2 X& V+ w( J! g8 X: \        if( queue.data[queue.rdptr].time <= writetime ) {
7 Z  r1 T" z* R9 i+ t) h5 j/ T                ret = queue.data[queue.rdptr];. k4 ^+ W2 I& H: t
                queue.rdptr++;; v/ ]& h4 H8 i- I
                queue.rdptr&=QUEUE_LENGTH-1;2 z6 I6 e* j3 Q
                return        TRUE;5 t- c: r; Q0 Q: h  h+ n# r
        }
% Y/ Z! {+ }8 @! a# M8 }2 e" T% G        return        FALSE;8 N: ^$ Z4 x$ \6 v0 u; A
}% K- c' i  C9 O9 O7 \: l+ Q: J" h
# b- m( c  i! J
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
/ v& T( _$ [" X4 \8 U% y2 Y- x{% r& m; ]: _1 @' S
        exqueue.data[exqueue.wrptr].time = writetime;1 F9 v' G4 l, \( R# _6 A# N3 _4 Z
        exqueue.data[exqueue.wrptr].addr = addr;
/ Z# d/ V$ m; Y) z        exqueue.data[exqueue.wrptr].data = data;! Y2 R) H* {  @% g% A: {! e! E) }# y
        exqueue.wrptr++;5 [4 u/ h7 M% ~& @9 o# D
        exqueue.wrptr&=QUEUE_LENGTH-1;
5 x7 ]8 W1 ^' c; y3 [) h1 t        if( exqueue.wrptr == exqueue.rdptr ) {  c7 u" q( {9 f
                DEBUGOUT( "exqueue overflow.\n" );6 j6 l1 x  [! [- \6 h
        }( m: P9 O4 _0 ~7 `8 H) P
}
* v+ h6 v) `& ^' ]- j; o$ Q
2 z% ]0 Q7 {3 y% T6 w8 b7 x# CBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  b; s& |1 F8 P  z, g8 f5 r
{2 ]) x7 C& b" d9 Q
        if( exqueue.wrptr == exqueue.rdptr ) {
9 {7 b0 H) i! m  q                return        FALSE;
' G2 k/ B' |1 F; v        }" ^, L# Q% b: C2 Q( i1 S5 M
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
; l. Q- }1 k% d$ S                ret = exqueue.data[exqueue.rdptr];! n  q" N" s5 f2 P/ Q' M
                exqueue.rdptr++;: t4 q& O7 ]5 J8 h* O
                exqueue.rdptr&=QUEUE_LENGTH-1;
/ ?( g) \2 o; }; {                return        TRUE;
  q9 `6 D! v' m" x# T        }
+ ~: w( o$ U4 G% w        return        FALSE;
2 f( B$ L4 b# v5 t9 o}
& ]" [4 O1 J7 H4 r3 R0 x
5 k7 F! \1 F6 F# r) Kvoid        APU::QueueClear()# f4 y1 e8 y( T" c' O0 i8 F
{9 b& r9 @$ _* ~. J  P* K" u1 n
        ZEROMEMORY( &queue, sizeof(queue) );) d# G$ V8 [& `5 _' l! m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 ~9 h9 m- x6 c8 G7 h" r" I}
3 Y8 t- c4 G+ k- ~
' b9 X: a' T0 ]+ G2 g- evoid        APU::QueueFlush()
3 F& P4 R- x* o9 L1 ~{: y: v! ~7 p4 D" H+ }+ A
        while( queue.wrptr != queue.rdptr ) {' k; y* k# h+ k( A5 b# t0 n
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 C! N/ o' i, w, T# e: Z/ b% `
                queue.rdptr++;. ^2 j) H  y, {5 [8 t" o
                queue.rdptr&=QUEUE_LENGTH-1;
. h. D0 f( l. a: U3 }/ D  e        }
6 F& k7 s4 f" E6 L1 u. c" E3 a9 A: E2 D" @2 T. x! r, M4 c
        while( exqueue.wrptr != exqueue.rdptr ) {
8 u! S  i9 m5 [' b2 [                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
( {* k; s, S2 W; [' R# u3 n                exqueue.rdptr++;. f  J: T, w% x4 a- t- l* T/ ~
                exqueue.rdptr&=QUEUE_LENGTH-1;
" a! f; m+ l/ X" \, C) ?        }8 X+ Y5 A' W) W1 V
}4 t) Q/ Y  j( D: w: q( `

" \) t9 B: H1 w& B4 k0 Zvoid        APU::SoundSetup()
" B2 ~7 m5 W" v5 Q7 e{# Z- ]# X  `" G. {* n3 B6 T
        FLOAT        fClock = nes->nescfg->CpuClock;# o5 e4 t8 y* T
        INT        nRate = (INT)Config.sound.nRate;
6 K- O# q0 [/ F. x        internal.Setup( fClock, nRate );
6 v4 M: |  G0 x, V* ^8 j7 q        vrc6.Setup( fClock, nRate );
( c1 i4 T. V$ C        vrc7.Setup( fClock, nRate );
, K  y- [# V% [$ T) H        mmc5.Setup( fClock, nRate );0 a( W9 B3 o$ J/ G* N; U, q
        fds.Setup ( fClock, nRate );
. L  B0 P- H2 Q0 I- G: i2 O        n106.Setup( fClock, nRate );
2 C3 z& O- O7 ~( q& E. d1 ~6 N' W1 O        fme7.Setup( fClock, nRate );
9 g' W# m7 `) `  Q}3 C9 D) q$ h1 L2 E  H' H
: f3 w6 d9 O/ v% J
void        APU::Reset()
" ?( E4 G8 a9 W9 f$ R! w{
+ b  e* H4 l0 K& g        ZEROMEMORY( &queue, sizeof(queue) );) a7 r  r5 I% i( K2 I
        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 a4 e8 q4 B) r. q# N

: J; h! z/ y1 e7 a0 W        elapsed_time = 0;! ?$ R" f/ }5 W' G
2 W! D) z4 {% T0 W7 b
        FLOAT        fClock = nes->nescfg->CpuClock;
( v" v3 I" K5 {# e6 K        INT        nRate = (INT)Config.sound.nRate;
5 K  D3 L1 E% x; e% d3 z        internal.Reset( fClock, nRate );
. n3 M$ B% ]7 W8 {% H& |1 c        vrc6.Reset( fClock, nRate );: s8 P: r, M. ^4 H
        vrc7.Reset( fClock, nRate );
! i( `6 K9 \5 U+ k        mmc5.Reset( fClock, nRate );
; J$ m5 R2 C7 X9 F        fds.Reset ( fClock, nRate );
5 J, v5 u9 p' \! c1 G) c7 s7 l        n106.Reset( fClock, nRate );
; R+ j  K& M# \5 `1 V2 P        fme7.Reset( fClock, nRate );
5 l8 n1 }! Y9 w  D! m; Q8 y$ T, C6 z$ i5 K6 C
        SoundSetup();
+ q+ o9 v# `5 M5 O}
* Q+ A6 B( n: x: C/ O/ \: [
5 _4 C, b& p, K9 n! V& Lvoid        APU::SelectExSound( BYTE data )8 b* d" [+ \5 I3 _; u9 d
{
: w: ^& ^7 [, ~+ f4 C2 G, k. f4 h        exsound_select = data;
% ?& d9 w# A% b4 y8 E}
+ L8 W1 a! U. H3 Q6 v1 R3 l" T
BYTE        APU::Read( WORD addr )5 [6 v* I1 a2 L
{4 {9 f  I2 J" ~
        return        internal.SyncRead( addr );
/ |( g; {# d. u; H- `}3 K% }" m& [# o9 I( T* W' Y

) F- F' a; q/ _0 h3 I7 evoid        APU::Write( WORD addr, BYTE data )8 O3 }1 e& A! K8 N* `3 Z" Z! Q
{
. E3 z8 F7 T9 M& d3 d        // $4018偼VirtuaNES屌桳億乕僩8 m4 b# A9 U7 f. B# v# U0 s
        if( addr >= 0x4000 && addr <= 0x401F ) {4 {  w1 ^8 C; J0 z- e2 R, E
                internal.SyncWrite( addr, data );* o' ]& K1 E/ O( ^
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 ]7 C0 |! ]  r, ~* s; F( O        }. d3 d6 B5 F* f- F
}
6 k5 Q) S: q, |; T+ F2 b1 S; S% ^7 ?5 p6 Q0 G, R, h
BYTE        APU::ExRead( WORD addr )$ r0 `; L8 D2 v
{
7 `) C# \, u+ k% j6 ]$ @/ V7 h# uBYTE        data = 0;
9 m8 P+ `$ n5 I  _7 B( ^9 `4 ?; R# ^% z% |# n6 U
        if( exsound_select & 0x10 ) {
- T* M$ E4 v2 ?- V$ Z# \                if( addr == 0x4800 ) {+ N. B. m: Y: r* r. U$ d6 [2 z1 ~" \
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );; d# v4 s$ b$ G9 t; a0 I+ ]9 v  _
                }6 r# B- n( [3 J2 t/ d8 P' J) n
        }, t, L5 }4 u3 K! ]
        if( exsound_select & 0x04 ) {
& y& h2 k0 o! I5 c6 L5 `( w( G9 J                if( addr >= 0x4040 && addr < 0x4100 ) {
' d# c! X" N/ c7 R! f4 N                        data = fds.SyncRead( addr );
+ g& j. ~2 s& }) x9 Y$ D                }
' i$ g& j; T! A1 c9 M# v( D        }
1 c3 }; d* S1 g7 O: \* F        if( exsound_select & 0x08 ) {: M6 Z: ^: i& _- v4 q
                if( addr >= 0x5000 && addr <= 0x5015 ) {
- |) l5 u7 I% G; W/ H8 t# \                        data = mmc5.SyncRead( addr );
" o/ }4 Y7 O; E; q                }
0 {( d  Q8 G% A" D: H# ?        }
) z) V# Z& |3 y6 `5 b/ K
4 d/ T# d( Z0 u. X9 A8 B        return        data;
* B. t! D; @( C) w- n: ]}
2 E" o) [# I* y- k- x/ O" e5 d' |, b+ o2 f% j1 V
void        APU::ExWrite( WORD addr, BYTE data )" t% ?, ]  D7 `9 e# M
{8 z# v; \3 O) o
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );3 l9 L% e$ }' c: y7 ]  o
9 S3 ]1 a5 O" ~1 Y
        if( exsound_select & 0x04 ) {
9 l+ w7 h1 r* R: T, h0 |! ^7 _6 Y2 ~* w                if( addr >= 0x4040 && addr < 0x4100 ) {
' b5 B& m; m! J) F# {) k                        fds.SyncWrite( addr, data );; G4 v2 S' t9 ?* z6 I
                }
& \! P- O( p  E* h+ K- Y( S1 S        }
4 e1 b( H/ K1 M# q& f- u* c' V6 ~  \; S5 N! o  n0 I
        if( exsound_select & 0x08 ) {
) N# ~& L" B; L                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ M9 X- e9 D+ J3 {3 b4 ?                        mmc5.SyncWrite( addr, data );
( d9 N, a3 h1 k" U' a: Z% i                }9 Y4 _% Y$ n5 W9 U8 i9 D6 ~) Z
        }; P. M% W4 w9 X0 j
}
! g8 k4 c1 _* c' t# C: y% _8 @1 q
void        APU::Sync()
4 b3 q. I3 P; o3 x{/ z2 P" V* D  W* N+ K5 N' r- L, g
}3 z. I  [# u7 l+ f7 `( @: g  D

% g5 C8 l( x. x3 o# c1 N; D# G0 pvoid        APU::SyncDPCM( INT cycles )! S6 r, Y( Q: r5 p, {: l
{
1 P. |; O8 y, ^        internal.Sync( cycles );
0 o- M1 t: ?, o. z3 D
" `/ H8 e) e# p        if( exsound_select & 0x04 ) {0 y# {$ S: z3 E$ Q$ R+ j$ ^  c) v; b
                fds.Sync( cycles );  ]5 D* ?, t8 d) @
        }2 O" h7 R1 U& L
        if( exsound_select & 0x08 ) {8 j5 S7 h% d5 v# s" r" i" \+ T2 I" H2 `
                mmc5.Sync( cycles );
5 L% y+ p/ [/ W1 |6 N9 f2 Y        }* }6 H- v% ]; S' F" ]
}* M( H4 x# b4 B' ]3 l

& l# D% Z' e) kvoid        APU::WriteProcess( WORD addr, BYTE data )
4 W! L% r. u, p% w; K{
# P, E' u2 l5 b. |" `7 D6 Q" Z: p        // $4018偼VirtuaNES屌桳億乕僩' P6 r+ M1 w* t4 I
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 ~0 R; ]  O2 U# _                internal.Write( addr, data );) e1 {: X& I2 b; E: y
        }7 T, Z5 Y. z1 b6 k  a. p/ i
}5 }0 h7 R1 h) f8 y. G1 \" J

  ^! U' `2 h. `6 R- Evoid        APU::WriteExProcess( WORD addr, BYTE data ), ~  o' `+ F. ^. h8 A% B) c6 I' i% p3 \
{
* T' [7 x" ?" {1 T* P        if( exsound_select & 0x01 ) {9 {, h8 y8 U0 \3 I9 s1 h. p
                vrc6.Write( addr, data );
( N  z" j1 \8 L7 ^        }
' D+ h" s$ a0 A7 W  S0 e1 C  k        if( exsound_select & 0x02 ) {4 l! n/ Y' I2 n$ i+ g8 P$ S
                vrc7.Write( addr, data );
* H/ v5 z4 m8 _        }
/ E! z5 B9 B$ ]6 |4 Y: Q        if( exsound_select & 0x04 ) {9 ^  H9 B* K- [
                fds.Write( addr, data );5 g6 X* Q2 K0 [2 z* {: r8 [
        }2 w, z' k' r& }% _
        if( exsound_select & 0x08 ) {
: E' z# [) A4 w) B4 P. j                mmc5.Write( addr, data );
# a  F& z: d6 B9 Q  h7 `  _# a( k        }2 ~( ]$ o8 s  T+ b2 l/ ]8 ~
        if( exsound_select & 0x10 ) {
4 z% F2 q" A4 R$ F2 H! A, v                if( addr == 0x0000 ) {1 J+ p" ?  M% P1 j
                        BYTE        dummy = n106.Read( addr );/ ^* m+ F& F; s4 g- S- x1 C: r5 ?
                } else {
" n! S' @, V1 _; I/ U1 W$ h                        n106.Write( addr, data );
" }+ Y8 r) @$ I' Q/ c                }
, a% L6 q5 ?# Y  ?) e1 w: s: w        }
4 E, `( _4 O8 r0 r- f# W& z0 w        if( exsound_select & 0x20 ) {! E! W" T; v1 r# H  K" R/ X2 c4 m
                fme7.Write( addr, data );' {2 K  s( o; q5 ~" F% r4 Y  B
        }
$ C9 \3 b; `/ J# C}8 u& F$ c* u! U3 W; L9 N* U, }

+ }5 F. L+ ~3 a7 O) _  d$ Ovoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ U9 [' p# o5 i- |$ J* M{
! ~  d9 R0 S$ j( J( y4 RINT        nBits = Config.sound.nBits;6 Y8 B4 G0 r) Y! d. F1 M
DWORD        dwLength = dwSize / (nBits/8);
9 ~7 U7 N' C& N: b# }0 ^. aINT        output;
5 ~# S  F9 v! m0 f1 K1 `/ `' f5 _QUEUEDATA q;5 o5 i! e% f- m) q7 U8 T3 E
DWORD        writetime;  L* `4 i  p* S  l5 J0 F

. Y" T% B: Q! f% ~: F9 mLPSHORT        pSoundBuf = m_SoundBuffer;
# z4 s7 D9 e# |* g0 S. Z$ \3 BINT        nCcount = 0;
: \) V; \* [2 ]4 u
6 N5 I, L# ^. gINT        nFilterType = Config.sound.nFilterType;5 D% B/ |. q3 q# V1 Z

' t6 c4 j& x1 X# C        if( !Config.sound.bEnable ) {
& k6 R/ A# c  V$ D$ M                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ E9 R$ Y2 \" ?/ g" n, H5 K. {
                return;
) |9 F4 V% M# y        }
* p9 C, y- \' D0 I9 U$ D) p* ~7 f- Y  {5 p3 l+ _5 M
        // Volume setup$ C9 N0 `* l* _
        //  0:Master
. q9 a& u- L8 x5 r( u        //  1:Rectangle 1; w: R% r3 s# ?5 V9 a0 c
        //  2:Rectangle 2
3 }; Q+ ~" _# x! w7 c  J9 h        //  3:Triangle( K. y# ~& ?' Z9 e- [* l
        //  4:Noise
4 I6 J; K) Q: s/ E+ u# A        //  5:DPCM
* T- n! ]8 x! y, @6 b# N" @# p) I7 S- r        //  6:VRC6; z; Y0 G* O0 O
        //  7:VRC7+ ]% `# S1 s7 v) Z% o: B/ k5 n/ S
        //  8:FDS
0 z) D/ E, a0 N5 \, X6 N        //  9:MMC5
% \$ {# {" @1 A        // 10:N1066 O3 \# X- v3 J( J5 o+ z0 `
        // 11:FME7. M5 l. l( o; V2 m, V& W
        INT        vol[24];0 X9 R* _& o( W- k! I$ W1 K
        BOOL*        bMute = m_bMute;' y3 l; A" P. [$ l# w
        SHORT*        nVolume = Config.sound.nVolume;
; _- |5 Y  o+ X$ K; q% Y
6 @, I$ ?: j( C        INT        nMasterVolume = bMute[0]?nVolume[0]:0;$ {: w* h% ]; b" }& P2 B
" l  ]7 U6 {# r* A
        // Internal
; U5 u& S$ i' ~. x: d3 _$ A        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
, N2 ~, @3 B0 v8 O6 w        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& s! L, t( Y# C3 K2 K) a& d( T        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
/ [6 q4 `! o7 o" E        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;  c5 L& w3 _0 q. f+ o
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;* V/ t: o; ~8 i2 [5 h+ k) {' [; i
$ J/ w# v. f7 ^* U+ i" D! K* I
        // VRC6
- K. [0 R( ^. G; g1 X, c. O        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  t1 }* N/ A5 D* z2 Y        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 m# o+ n, X& E* c0 ^
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: B8 U6 B2 W6 D5 ~/ O+ U" v
' u5 D& V5 R% b  {) L0 B        // VRC7& t& R& G( V& K2 s- W; a" x# n
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
/ S) Q4 `" q5 z
- {/ n  h" ?# t- R1 O) G% s) h        // FDS* ?& e, \1 n% ^% O6 r, I- L
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
0 C  i3 J) J7 ~: z( U7 x- r0 \$ `4 j" C- T# B+ x* E$ q, d
        // MMC5
  ?8 O* J2 h% [$ z: m: M        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* @/ Q$ a" m6 g* n8 W        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! s/ h0 _1 \3 O) m1 U        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 A0 a* ?& N' ]4 l$ o1 ^% `5 g
  U+ \' i# }$ `2 p
        // N106
4 V4 L: r1 s# `1 Y. g        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 ?3 z  a# ~) K$ G3 ]. \. f2 l% y" O4 n        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 q0 i9 |$ P. x% {& r3 c
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 r6 o/ `% E1 S* g% q- J- Z
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 O/ Y) u3 J' H. ?7 C" R        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. h  P+ Z+ ]2 n/ m  L  ]
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* m( P2 Z. e# ?" X0 G4 ]8 z        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& o7 ~6 n$ C' O: e
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% f3 L5 \, n. [& t4 P- G4 k1 W6 ^% V# l1 G- I$ E+ n" l7 |! }
        // FME7
: Z5 r4 H2 P# T, ?        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ k4 \4 @8 q$ L        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 Q7 D" B/ {4 I4 H) [3 r$ v# x+ W        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# ]8 a1 P  E. O/ ?% Z4 S4 x9 }, J
0 l+ q+ p; A; n4 K0 h6 b1 ^//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
8 r4 v" E5 i: ^5 K        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
; Y9 [, N" |2 K4 J7 n; G' }+ H: y/ p" @1 w8 Q  _7 B
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟4 h! q0 {/ n# o
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
/ R2 `3 _8 b# l' W7 C- F) [                QueueFlush();
! Q; \+ B$ n8 J6 S; x" H        }
9 a4 N6 [) Q; F. o2 Q
5 V: F- h( _( _6 v, U' `3 ~        while( dwLength-- ) {6 K  r, @7 V* W, Q4 r
                writetime = (DWORD)elapsed_time;
6 f+ J6 E3 O2 a# Q- g6 p2 g, C0 p+ d( I& [2 j6 L
                while( GetQueue( writetime, q ) ) {
2 i- y/ O5 F7 w/ {7 B                        WriteProcess( q.addr, q.data );
- K/ L7 H+ e$ z0 k/ h; p                }* k+ h8 d+ O  I# ^
3 x4 y; p+ D, z+ j* i
                while( GetExQueue( writetime, q ) ) {" H- W7 [2 Z8 H
                        WriteExProcess( q.addr, q.data );
' B- e/ ]6 ?" f% d2 {+ d) p2 l) @                }
! \2 L2 t4 I. O* z/ f1 |- g+ {' j* f
9 B1 n7 g" I6 T, S                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
9 N0 G# P3 O9 @5 G6 B                output = 0;
0 |$ t" X/ ]/ V6 ~% A5 f                output += internal.Process( 0 )*vol[0];# n3 C. b! T2 t2 P& ?9 N1 ^# F& C. x
                output += internal.Process( 1 )*vol[1];" R8 M; n: h  D2 n8 d. A
                output += internal.Process( 2 )*vol[2];
3 U1 N5 j+ r2 V+ u- P0 u  \! [+ l% O                output += internal.Process( 3 )*vol[3];
( I* N) s3 x, s- H. D$ {* }6 y                output += internal.Process( 4 )*vol[4];  T" d$ k$ [2 n4 z5 Y8 i, p$ c, y
" h" I. \- C6 t4 g2 j7 c
                if( exsound_select & 0x01 ) {" y3 P; v( O7 B$ t2 D
                        output += vrc6.Process( 0 )*vol[5];0 k9 Y+ r4 x7 X, I
                        output += vrc6.Process( 1 )*vol[6];  @# y- _+ S6 L
                        output += vrc6.Process( 2 )*vol[7];9 `+ s! ]* \* b  q$ A- Q( G4 o
                }
' x. i6 {1 Z5 T# m3 s) q                if( exsound_select & 0x02 ) {
, d3 ]" e9 z" d7 ~* u2 x- \                        output += vrc7.Process( 0 )*vol[8];9 w; X' A! P0 `" m
                }$ d. @& ], ^( W. U3 j1 ~
                if( exsound_select & 0x04 ) {( g- L# M# b' H2 d. D$ Y
                        output += fds.Process( 0 )*vol[9];
- h+ J- C1 {9 h( N! t& q3 B/ ^& B                }
2 r5 ^; r- z8 L+ y4 n5 h                if( exsound_select & 0x08 ) {
5 S6 s6 A8 o$ \8 v& s: k' G                        output += mmc5.Process( 0 )*vol[10];
. r( m& {+ ?. p' |  b9 H9 c* z                        output += mmc5.Process( 1 )*vol[11];
" I- ]7 ]6 L$ X+ E# N                        output += mmc5.Process( 2 )*vol[12];5 K$ V: l/ T. t  D
                }
7 o. z# G& d4 {" ^; z$ i+ S                if( exsound_select & 0x10 ) {
3 P7 |' }1 N. {: x                        output += n106.Process( 0 )*vol[13];0 T! J) b. I/ d# [% d
                        output += n106.Process( 1 )*vol[14];
5 k5 z- s! D" @% u: S                        output += n106.Process( 2 )*vol[15];) A6 h. Q6 q; G3 p, u2 Q* T& @
                        output += n106.Process( 3 )*vol[16];% S0 c4 f' o) D& b2 _" u
                        output += n106.Process( 4 )*vol[17];% L. B* w, g+ g: Q5 O9 Z) s
                        output += n106.Process( 5 )*vol[18];
0 v- W! c8 R0 r                        output += n106.Process( 6 )*vol[19];
& ^- V( d, U! G, u: h) e/ L: \% D                        output += n106.Process( 7 )*vol[20];2 b  m: U8 G4 J! `& n* b8 `# s
                }/ J/ q5 u7 S: ~( B8 s
                if( exsound_select & 0x20 ) {
2 ^. @0 P8 r, j  `( Y+ `8 Z4 d                        fme7.Process( 3 );        // Envelope & Noise
7 C  W- ]4 J, O. e" `) s                        output += fme7.Process( 0 )*vol[21];
' T( F4 p+ h) R                        output += fme7.Process( 1 )*vol[22];
. Y5 I7 ]' [2 u. S$ \                        output += fme7.Process( 2 )*vol[23];
, l/ r8 L( C% x* H. Y( r! I                }. ?4 F# {( x  O' c

6 L) ]( m3 |2 A& a% \5 l0 }# P                output >>= 8;
4 l5 L  S/ \& V/ y1 Q7 f0 d) S( N. @* Z* ]; T2 w1 E0 t
                if( nFilterType == 1 ) {
( z  s" {/ ]4 D7 j  v                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)2 }5 X1 I+ [2 `! `
                        output = (lowpass_filter[0]+output)/2;8 v/ z2 ~: |$ C. H+ S9 \
                        lowpass_filter[0] = output;
$ ^, Z7 \+ c# n' y& p- d1 j. \                } else if( nFilterType == 2 ) {% ~( {# P& p. N4 J
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 b% o" G2 q6 m7 M
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;# j  F! [* _& T; K+ X* x
                        lowpass_filter[1] = lowpass_filter[0];4 f1 n* d8 f: G8 Z* k# K, v
                        lowpass_filter[0] = output;  ~5 W5 D$ Q# _3 E! y
                } else if( nFilterType == 3 ) {& [* N+ o/ o, J5 A
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 b8 g+ K7 P4 r
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
! ]; H% R+ F  N* L) g                        lowpass_filter[2] = lowpass_filter[1];0 m6 V. H+ V& ~2 F$ {4 [
                        lowpass_filter[1] = lowpass_filter[0];9 I. Y1 d& W( K
                        lowpass_filter[0] = output;
: W# B) ~4 q; G/ j+ l! W7 `8 l                } else if( nFilterType == 4 ) {
( S+ b. Y( m" y* D- a                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)0 e: a# E+ v6 R9 F5 ~
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;+ y; D/ O: ]. X+ G* c1 c% S
                        lowpass_filter[1] = lowpass_filter[0];
% t2 H6 y4 m- E8 R! L# M6 D                        lowpass_filter[0] = output;
4 L# o8 t/ h+ Z/ j* y/ y                }. l+ C* m+ ?+ U

' X8 x/ [9 A# w8 h#if        0+ w* D7 _' H0 K0 p9 a  L% y
                // DC惉暘偺僇僢僩- q3 ^* H5 E9 A8 h: l  e9 u8 j% N! ?
                {0 ]  |# Z2 _' d
                static double ave = 0.0, max=0.0, min=0.0;
2 J% z6 K, u4 N4 x0 A( z! K8 r                double delta;
  _2 N( z% P2 s                delta = (max-min)/32768.0;  |- ?1 P: [' F8 x
                max -= delta;) w" W  L' L' P
                min += delta;
" n/ B& p; u0 W+ d" l/ U: q& ]; X* {                if( output > max ) max = output;5 y4 ]7 w8 r( x' _) U
                if( output < min ) min = output;: L$ C  x+ J( t% n
                ave -= ave/1024.0;
+ v% u$ {1 y( F5 L, z                ave += (max+min)/2048.0;) r4 z, ]" P: @  J: _0 {5 S
                output -= (INT)ave;3 Y# o. B4 A; r& W; \0 e
                }
, c: g, |# G: @0 p% Z; O9 `4 g#endif7 s6 e, z2 }3 Z: |7 e  a
#if        1
$ a" d6 n+ a, }, B  \                // DC惉暘偺僇僢僩(HPF TEST)
4 f( G- s8 V' `3 W2 j6 o                {! @9 w- X- W  l# I
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);: K$ G' @8 {/ E. u  r
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
. i/ n. _5 M& p" ~" }, _                double        cutoff = cutofftemp/(double)Config.sound.nRate;/ R. P' J; x; f2 m& Q" {+ ~
                static        double        tmp = 0.0;
$ ?4 k) {0 T$ @) k                double        in, out;
; N0 _, {' C& T$ m; K7 C$ C$ Q- O1 i$ |
                in = (double)output;( U+ w; _% x" v5 o- R) X4 o
                out = (in - tmp);
6 s  D! p3 t" N3 k2 p% h                tmp = tmp + cutoff * out;
+ I3 p, l4 X% g# }" a( ?2 p2 h' N, U' a0 }3 o: X8 P
                output = (INT)out;& b( R- I( l% ?6 E( d6 {) q' }; v
                }6 m: g- s0 p+ [$ V) Q# N, f& A& Z9 d& F! \
#endif  \$ d; ~" W! P5 t$ Y) @- Y* b
#if        02 T$ L7 e$ v5 K7 @% I
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)  L% V3 r7 g4 E- i% I% P1 b
                {
: e" ]* w: Z7 b, s" U. i                INT        diff = abs(output-last_data);
0 q4 t+ ]  H6 X# J4 y5 n( d  J$ `                if( diff > 0x4000 ) {& q* y$ u5 q  @2 K& L
                        output /= 4;. f" e( {* k5 `3 b( N, b' ^/ a
                } else
. w- R6 K' e* ?; _4 R                if( diff > 0x3000 ) {8 z: |$ W; l% s2 n- b3 M
                        output /= 3;
! ]/ e' H5 U3 Y2 T4 i/ _1 f                } else
( Z1 K$ s2 L) C  f" [4 W                if( diff > 0x2000 ) {+ B9 e# w* w5 q
                        output /= 2;& S( b, }4 a& {2 H
                }" f6 T8 f- r) s  L/ N0 K. v0 n6 s
                last_data = output;; P/ r: r! E( A, W. o! z0 Y/ A7 C
                }
" G/ n; R. |$ t. q4 s#endif0 b0 F) g# \* [' @
                // Limit6 d. P; _( C% B& J
                if( output > 0x7FFF ) {3 Z0 E. s# j# \# ]
                        output = 0x7FFF;; F: P1 A* f% u/ J
                } else if( output < -0x8000 ) {! t4 ]  e- t8 F
                        output = -0x8000;! I+ `$ H9 t, s8 Q
                }" ~$ d% O0 N0 d: U. h
; c; I- R) {9 q; r
                if( nBits != 8 ) {
  Z1 }0 u% G  J" ]0 |7 X/ a                        *(SHORT*)lpBuffer = (SHORT)output;& v6 A+ y$ H2 R5 @4 R
                        lpBuffer += sizeof(SHORT);
8 i1 z, F2 R5 a5 {9 i                } else {
/ n: U, ?  ^! N6 A" ~0 Y* N                        *lpBuffer++ = (output>>8)^0x80;, `  m! B+ ?$ ]/ p. S5 H
                }/ J) G: U) t6 H

* b+ n/ H! g& U- s8 _, S                if( nCcount < 0x0100 )
7 ?& ~! d  O2 B                        pSoundBuf[nCcount++] = (SHORT)output;$ b3 G. R, s. Q! a
+ I( T! y; W9 u% b
//                elapsedtime += cycle_rate;
9 R  \( r' w9 Z" t& S" R% C* ]                elapsed_time += cycle_rate;
' z9 N, |* k* Z        }
- e) Y% h9 e. {1 v3 ]$ p  o& o. q2 L/ [. w& g' A; p
#if        1
/ Z$ W" i  [& q8 @# G5 f1 z1 T! A        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
* D! m& W% g) E                elapsed_time = nes->cpu->GetTotalCycles();
2 T( u% @& ?: y7 j7 R# [* D2 b        }; x3 K' `9 F/ N1 Z# p/ M+ |- ]
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {* e8 V& V( V8 T/ `3 @+ f
                elapsed_time = nes->cpu->GetTotalCycles();  r3 r4 ^' \; I7 K
        }7 Q& j1 Y. C5 o/ C  n  p/ r
#else* O3 A8 Y# f& ^. C1 [4 x+ ?
        elapsed_time = nes->cpu->GetTotalCycles();- K! U% Z8 M/ B9 o) Q5 s
#endif
( Z+ k2 b( d+ M3 D( V* P}
9 A! Y4 o0 U) d( c8 o, O! w( D1 u- }; z) u4 M" ^
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
2 b" o( t/ W  `7 s% Y2 aINT        APU::GetChannelFrequency( INT no )$ ~7 X* M- B9 ^
{
) o$ d6 L+ T1 a: W( m, v        if( !m_bMute[0] )
, ]$ @/ \7 M) x; t                return        0;# a- m8 K% u( o3 B1 N

6 J4 n% |1 R% Q) r6 B: J        // Internal
1 o; P5 V; {0 B6 r        if( no < 5 ) {
) ]) F" Y, o* G# C) [! L/ B/ E; E. |2 h                return        m_bMute[no+1]?internal.GetFreq( no ):0;
, n( O" Q' d" N        }
% `- h5 S8 @- k$ D& s. S5 t        // VRC69 H1 o4 g, w# `% Q3 R' G/ P2 A
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {2 e+ u; B$ r3 _$ c8 \
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 }5 w" N( Y% \. T
        }
3 d/ N) ?- @) G6 T% m% A        // FDS
6 ]1 b; J7 y2 x, s        if( (exsound_select & 0x04) && no == 0x300 ) {4 h  N. ^. _! {9 \8 e
                return        m_bMute[6]?fds.GetFreq( 0 ):0;  c) a6 X( I9 e" W3 C9 J
        }
) U- B' n: j5 {* m, K; R% X4 K        // MMC5
! D* m* q' ~3 y( _3 C; E) p        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
" n7 w2 w- j7 o& u0 a) B# K1 o- L                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
4 A6 U- P/ R5 |- s! |  y' I        }
9 ?9 q- R  O3 n        // N106& u8 g+ ^! T/ E. ], N
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" W7 p- \$ a9 N: L                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
# g' F# }' u4 `3 o) G- ~# U) E        }
7 m: D0 g  j/ \$ y        // FME7
2 Q: C8 i! n; H% c" Z( o        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {% f5 R' U% r( W4 b% [/ i
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;6 S0 k! e3 }+ j* ]7 q1 Y. d
        }* `+ A# i! a" {; D5 X
        // VRC76 s. P0 G( S9 u
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {/ P0 `) ]$ S2 g9 u6 l, V$ I& _3 O
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 T3 w2 i7 t; L: E' n7 z, Q. s
        }
2 f: j$ G& h" a, S, z        return        0;. t# H1 h" T% ^) T+ g
}. J" F1 O- a1 Z" ?4 V  `

1 [6 _4 s; G9 W* ]// State Save/Load
9 k/ K7 v' F; H9 A* F( Nvoid        APU::SaveState( LPBYTE p ), v- k- }2 p- m( e8 j
{
( ]' }5 O4 |2 A0 T& [8 I#ifdef        _DEBUG
6 V, v! F  T* T4 A& SLPBYTE        pold = p;
1 I1 u" o1 `+ x1 Y" v; A# }' p9 Y#endif
; ^# _/ q+ l: l  W1 A9 q2 C. Y# m
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
1 A4 N' A- ~& K' j        QueueFlush();
- G% w& A" E& M4 C1 L7 I0 d# o. E" @) E5 \9 v
        internal.SaveState( p );0 z& M! z" I( R9 G
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! ^9 G% M; Q1 S! {7 e; m
+ h0 c4 O2 S' k( G$ X' @4 w
        // VRC6" y7 O0 }+ v# D! C: V
        if( exsound_select & 0x01 ) {$ R$ L) s- R/ f8 {8 v
                vrc6.SaveState( p );
. ^$ O: ^- C9 }1 Q. y                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. o5 ^( r$ }) E, v
        }
6 X! ^) V# Q+ c0 g/ m        // VRC7 (not support)
2 K0 H+ N+ X* g- {        if( exsound_select & 0x02 ) {
/ v! \+ Y0 z) U8 b                vrc7.SaveState( p );
7 S( a# H; B3 Q3 Z- r1 l                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' K( {7 m/ u% Z" W# A3 y
        }
, s9 D, T( Y2 h9 U        // FDS. N. a* U& S  z
        if( exsound_select & 0x04 ) {8 l1 G, [, d! w" |) y. A" N1 ^7 F
                fds.SaveState( p );- U4 _+ f& y: u5 I) E# d3 a
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: x6 Q7 _; B3 I4 Q9 y1 c/ }        }) E+ A) O! n2 B! j/ d% p
        // MMC50 ^% q9 Z) ^* E
        if( exsound_select & 0x08 ) {
: [6 P! y8 c- S( Q1 x- ~                mmc5.SaveState( p );
' N% V; [! w8 r, q4 P8 Y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 U' K- b9 i5 P' S; n        }
! [4 h1 x" b5 K5 ^: U! j        // N106
) Z9 ~8 Z" j/ y2 B; n8 ]        if( exsound_select & 0x10 ) {
1 F. o1 \9 q& c: v+ |+ y! L& I                n106.SaveState( p );
( E- L  ^; z+ S8 L/ Y                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
7 w& k) M  b1 k( B        }
# l/ Y% i- m  B4 B# ]        // FME70 l& K5 [+ v4 Z
        if( exsound_select & 0x20 ) {
6 Z4 d9 q6 T* b                fme7.SaveState( p );
! y7 W1 n8 A/ x+ E                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 F$ o& J2 ]0 B. |5 x) I6 s1 Z
        }
! L7 C- P- u. ?+ i& j( w. v1 P6 \* W, z5 E% s( T& j
#ifdef        _DEBUG" m+ W1 R% k7 N
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 i+ b6 L$ N8 r* b* W5 p8 V#endif
6 [; \( I) a$ T6 h}
( q6 A# m! q0 B6 r) X3 z& z- |, F; Q- e, ?( d& p/ z% b
void        APU::LoadState( LPBYTE p )( G3 Q7 m6 E) p* g
{
- U4 g. l! x9 S        // 帪娫幉傪摨婜偝偣傞堊偵徚偡2 h6 @! R9 o/ s, S. z" u
        QueueClear();
/ K+ L# d7 h* I4 ]% p1 c3 q1 ]; ]  |  Q
        internal.LoadState( p );5 C7 {! z/ H4 L2 Y' i8 }4 v
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, X- i" j0 W# d* B' \5 ]4 }
" y: w1 H8 I8 M- m9 q: y
        // VRC6: k1 M9 W$ A4 c
        if( exsound_select & 0x01 ) {+ {4 }' R6 b% {) O" R$ X
                vrc6.LoadState( p );
8 S" {" `  ^$ s6 {) w% t) l                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ l0 N, c8 T" y8 _8 B9 H2 G        }
/ n8 j) N3 {. T1 b        // VRC7 (not support)  E% S1 z% L/ q7 y" O
        if( exsound_select & 0x02 ) {
; |, Q( `9 b- v- q! E                vrc7.LoadState( p );
/ p4 r" {) v* @% o& r/ ]+ B                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, B( n2 z7 ~; O2 T9 d$ l" U+ l( F
        }$ N2 H" I0 E) i
        // FDS! i$ _- d& G* p5 O# g$ b0 X
        if( exsound_select & 0x04 ) {
2 w, D2 Q( w! K1 S- [: R+ P                fds.LoadState( p );
1 ~7 D7 U# \5 J/ d. A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 w+ B8 ~2 u) }+ @  s3 J
        }- z: T* k3 t  K
        // MMC5" c% J. @/ ~) @2 m) w
        if( exsound_select & 0x08 ) {
4 b2 R4 `; w3 u- J2 p                mmc5.LoadState( p );
( k8 e9 G$ E% C2 j3 \9 e, f                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding- D, |: K; [/ s  L' l
        }
" n9 z6 s: r' M7 @        // N106
( d0 X& ?, x# Z( G4 G        if( exsound_select & 0x10 ) {
3 X" d5 ^3 ^, e: z' M: f                n106.LoadState( p );
5 W& x6 |( B3 s" L( b7 b* ~                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  y! w8 c1 m4 J$ p. ?) z3 I        }$ e  T% o9 K- b# j# Y
        // FME7
- {: U, Y& P; ~- O2 [5 r7 D        if( exsound_select & 0x20 ) {
, C& S( }& A( U! B; B                fme7.LoadState( p );% a1 F# V5 c6 Z6 V8 w6 r
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 L  t5 y4 v3 ?0 }; h
        }: u: i: k7 r4 Z: Y9 S! n
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 0 B, i. t0 x" O0 \( v/ ]* {9 L
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
/ U; L4 l  m7 Y: i" }# h感激不尽~~

4 `( b) Q% @7 s恩 我對模擬器不是很有研究,
0 v3 o) `7 M3 c/ u. f$ z雖然要了解源碼內容,可能不是很困難,
. J% K, Y6 \  ?3 o1 [不過還是要花時間,個人目前蠻忙碌的。5 U+ k/ U& {$ b4 E* t7 b3 ~- f
2 J/ B  \0 c$ A) m$ {! U% X- @
給你一個朋友的MSN,你可以跟他討論看看,
; ^, F+ t! t: u他本身是程式設計師,也對FC模擬器很有興趣。
- \$ R5 g! E: o( z# V* N. S
- q; b) j9 ~' |" @5 xMSN我就PM到你的信箱了。
9 r0 j6 ~2 |' s2 [4 c% T3 j8 _  b- q) C, S! O
希望你能有所得。

该用户从未签到

 楼主| 发表于 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, l9 r; P1 ^+ [1 Q! k呵…… 谢过团长大人~~
+ v. }) `( h! ~7 E! V
. j, k5 g. l5 v5 g
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & h* U) q* |( g' p$ B
团长的朋友都是神,那团长就是神的boss。
7 p. s1 n3 E6 A: G) |1 c+ d% r
哈 不敢當,我只是個平凡人,
5 Q* L9 ]8 {" ^3 f0 y要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙1 V# P, w' R) i
ZYH
+ f# P. v& y5 G0 r4 {( QQQ:414734306' W# T% _" C# g- k
Mail:zyh-01@126.com
' X4 a* q- ^+ D2 o% I& f( [% X0 C3 Q0 g: H1 y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 \2 t. B0 J: W: x- c& b' ?
再次对团长大人和悠悠哥的无私帮助表示感谢~~

  K5 |1 K; V3 M& p( I不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-10 02:07 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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