EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ I( [( S8 a& S$ }+ R* m
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ K$ b8 \( W: J" R1 J# {这里有相应的模拟器源码,就当送给大侠了~~
! d6 _" N# H. W% `  fhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 8 b3 l4 h4 t, R
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 d: o, A$ G  b8 U4 m' h
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! ?$ @2 Q1 b4 `0 I5 V% B* k
这里有相应的模拟器源码,就当送给大侠 ...
  J% I# Q" x9 C; B% ]
聲音部分(Audoi Process Unit = APU):  B( N) Y( {+ ^- ?2 i! p0 ?
.\NES\APU.cpp
+ R  y3 s! X1 j5 N  y! ].\NES\APU.h
6 ]! |& _, {% e6 z5 i& \2 }' L4 [, |# E# o9 A$ M8 p# h" l

4 Z6 _) i$ U$ u7 M, {7 G影像處理部份(Picture Processing Unit = PPU):/ L& |* T( L7 R- y  s) z; m8 r* W# E* {
.\NES\PPU.cpp
$ y9 C% [+ G. U/ N.\NES\PPU.h
5 m; I+ ?! C& p1 K$ \
6 k2 @" G+ h/ o( p; W- d( N# _如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。. W$ y2 K. [9 ?5 L- ]  ]2 E
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:9 ^4 ~6 c* P- ?, G7 `4 Z& I% ^
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
. Z+ w  u! d) u& y/ q1 s+ e//////////////////////////////////////////////////////////////////////////5 F' [& @5 R: Z1 r( G4 }
//                                                                      //, ^0 u8 F. n. |, o6 f
//      NES APU core                                                    //
' u) R  L8 v- r3 u//                                                           Norix      //
! @0 N2 D* W6 c2 H9 L/ W//                                               written     2002/06/27 //
8 W* @+ X- j, [, b//                                               last modify ----/--/-- //- ?( R! ~" A: d- Q9 k3 K, J6 d
//////////////////////////////////////////////////////////////////////////
! T, H* W! T: P  S2 z+ w% s! Q#include "DebugOut.h", u$ i) U7 i( \# O9 Q! \+ G
#include "App.h"9 O8 M7 Z- M  O) O) R
#include "Config.h"
1 M) s. ^2 h" F5 }, w& Y# ~7 o" G! `& U! |
#include "nes.h"
0 U/ g  S4 B. }# D: Q#include "mmu.h"# H# \2 \( P9 H" P5 W  |5 B  {  \
#include "cpu.h"
8 a/ ?' f8 I5 S. c) |#include "ppu.h"
3 `( ]3 |% |' Z) b9 K/ D7 |" z#include "rom.h"
' j7 N. S+ H8 Y. Q2 [4 Y# ~#include "apu.h"
  [( d3 i, {, E. L: h3 u2 y) Q+ k3 F
# H8 n( M& {0 T/ s// Volume adjust
: r0 R3 P# V. z) I5 z// Internal sounds: i5 x8 p4 `6 |" u
#define        RECTANGLE_VOL        (0x0F0)
* D- t" Z2 r! D1 Z- P#define        TRIANGLE_VOL        (0x130)$ f) I  V5 |( b2 l' p; ]/ ?- x
#define        NOISE_VOL        (0x0C0)0 s: i, p8 [3 P! U( i" U
#define        DPCM_VOL        (0x0F0)
/ R3 J; Y1 p4 S6 @% ]7 i9 \8 j  K// Extra sounds
9 v, g( P6 v, H4 \#define        VRC6_VOL        (0x0F0)
$ s/ K8 P7 O2 m+ m0 j# s7 {' p#define        VRC7_VOL        (0x130)
; H7 {: S0 b5 S1 }" K" T#define        FDS_VOL                (0x0F0)# t% q2 a7 c. v8 H. ^4 R
#define        MMC5_VOL        (0x0F0)* W7 c" X7 h( |
#define        N106_VOL        (0x088)
) Y, M: o* d2 A+ n/ \#define        FME7_VOL        (0x130)( P4 Y1 E+ b# R; \# x

/ S8 Y, L* l6 B, |6 @7 z$ U. }APU::APU( NES* parent )# c+ V# K+ z/ n  W2 K! w' D
{: f# L6 W+ b4 N8 ]  i7 y  Z
        exsound_select = 0;8 c( V. G- {3 l4 u2 f
7 N- P6 u5 r& ]; d* e
        nes = parent;* p2 h  X5 Y( n
        internal.SetParent( parent );* z. ~& R( x+ O# J' A
% h: `% x; n9 _
        last_data = last_diff = 0;
8 R7 q! E% d7 @3 W4 Z
3 A. S: V  F: N! h        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );2 p9 v6 E) R0 l& k! G1 M! t' ?
5 e5 Z4 e; S: ]9 K* ]/ |# K; S
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );( r8 C6 M, i) @( B* }
        ZEROMEMORY( &queue, sizeof(queue) );6 L! Y1 O" j9 b# I4 K0 u' G: D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. D: [% f9 _& g

) O' M- k2 O$ @' d9 l        for( INT i = 0; i < 16; i++ ) {
0 a; z# D/ O# ]                m_bMute = TRUE;7 ]; N  Y7 ]% b+ L: W8 p* K0 l
        }
. F3 C( N$ ?; J( Q}
2 e- N* O/ |% C1 w; s3 r
% ?. _/ A5 J4 M* TAPU::~APU()5 U+ d! N9 @  s, Y6 _: |( ]9 @
{
, O2 V) c4 ?4 P! @5 j4 E4 [}2 ]3 V% A3 e2 t/ K8 n* y! z

5 t7 [2 Z; j* avoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )4 e- M0 l+ i* `& ?
{, A9 d' `  ], ~
        queue.data[queue.wrptr].time = writetime;9 n/ d$ {  y( T
        queue.data[queue.wrptr].addr = addr;6 b8 e, F/ ]/ g$ J6 w. I
        queue.data[queue.wrptr].data = data;
: `5 ~5 l% [7 Y$ T" D& f) j6 @        queue.wrptr++;
6 X0 @) y; }, Z' T        queue.wrptr&=QUEUE_LENGTH-1;2 m# u6 b% B/ h0 }7 {
        if( queue.wrptr == queue.rdptr ) {  Z& ~7 P! E6 Z
                DEBUGOUT( "queue overflow.\n" );" T* J; \/ p- `
        }- N! M' q" F; n  O
}
- Z. z3 D) Z# x/ \6 k
' T0 w! N! j3 d. vBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  G) H% ]! m0 |1 Y2 z/ c7 ~; {$ p+ l{
% ?0 \" u' m6 z/ f8 B        if( queue.wrptr == queue.rdptr ) {9 d2 [( @8 {& J/ P$ ?
                return        FALSE;, V( u& S- \2 k5 `# m: o* A7 {
        }
* x' w  _& H9 c) Q0 z( |        if( queue.data[queue.rdptr].time <= writetime ) {: B0 n1 T$ k, ^
                ret = queue.data[queue.rdptr];
, @. a) k- Z4 o5 _  M; ]                queue.rdptr++;0 v* r8 j' e5 z* ^% {
                queue.rdptr&=QUEUE_LENGTH-1;
& @% f' S3 }3 i; O8 X" p7 x                return        TRUE;
/ u' U! [6 }4 u7 D) y. Q7 R2 |        }7 B, `2 L7 g& g8 U( M% G0 t8 n! q
        return        FALSE;
: p& j+ m) u& p) M6 W) Y5 w}
+ K2 M6 y, B# |8 z, F7 _0 i9 ~5 [* q, i3 h5 t6 `
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
4 g; v: f8 }( i" r: w- p{, [  R: `  A$ u3 w! Z. K* v/ Q
        exqueue.data[exqueue.wrptr].time = writetime;
. C( `& @, m& ?, a        exqueue.data[exqueue.wrptr].addr = addr;4 V  c, _1 ]5 w$ C. C, L
        exqueue.data[exqueue.wrptr].data = data;2 ~1 ^7 P9 g- ]' g! l
        exqueue.wrptr++;
4 X. V5 L& X" D4 b6 _% z        exqueue.wrptr&=QUEUE_LENGTH-1;* ~5 X* G; u  N9 U
        if( exqueue.wrptr == exqueue.rdptr ) {
: `" t5 t% J" @$ a( a                DEBUGOUT( "exqueue overflow.\n" );2 C+ }* K1 b8 |- O
        }4 i8 [2 _2 i! e( D
}9 H$ i2 A' R0 e0 b+ b3 ?, p7 b- |
; S2 X# p) M% }
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 y: P' J; f" p8 P. h0 F{
3 W7 S7 L3 m4 n- a5 L6 c7 v        if( exqueue.wrptr == exqueue.rdptr ) {
  S- Y4 v0 Q/ o                return        FALSE;
# p5 E. \2 |1 _+ `        }+ R- w' ]* D3 [/ H5 l
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
: L' X9 D9 K# Y0 x                ret = exqueue.data[exqueue.rdptr];1 S( S7 O+ p& M: j* e  Z$ F  y/ y
                exqueue.rdptr++;
  i! @, a5 t: ~5 l. z$ t! ?                exqueue.rdptr&=QUEUE_LENGTH-1;2 @6 ?1 K2 L' q& {1 r( d6 ^
                return        TRUE;
4 n9 l* V% ^: j3 f' y$ ~- R        }% D- u4 P: S/ M0 z# |$ N  w) y- W* Y
        return        FALSE;
4 U. Q2 V0 e) g& }( K}3 s! f4 `0 t5 ~
& f7 c9 [" t1 T4 {8 \, y) }
void        APU::QueueClear()8 P" N0 z) E" R/ X  X/ l
{
# G: |! O1 V% E1 u        ZEROMEMORY( &queue, sizeof(queue) );- K  |- B  [! b8 k2 T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 @. b8 l. \- h! d
}
- U5 X* A* y/ H
+ w6 {  v) @2 ^' pvoid        APU::QueueFlush()
9 y4 u8 o+ c0 R8 |{, g& F7 r6 S5 M% }% p/ ^
        while( queue.wrptr != queue.rdptr ) {
* b' c4 M. c0 }' G! z& X                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );% |0 e8 P7 E8 c" d$ W: I& h
                queue.rdptr++;  i' R1 U3 h5 F  i6 S7 s2 t5 [
                queue.rdptr&=QUEUE_LENGTH-1;# _3 w7 S" b% O- o2 D
        }
5 H3 z9 a" G( `" t5 ~# U2 _8 I& N9 K" G5 I" f  J6 N
        while( exqueue.wrptr != exqueue.rdptr ) {0 f5 _  i4 _% m0 U) c
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );" f. e3 `8 ~" c& i" K
                exqueue.rdptr++;) n9 V# p; B, L: \( @2 x
                exqueue.rdptr&=QUEUE_LENGTH-1;
% M; U! ]" h, ]        }
% n1 }( y+ Y/ A* D! [; ~5 B4 }4 s( N}
% P: I+ d9 M  t( C( D3 h5 M) {1 A) _$ L: z& K
void        APU::SoundSetup()
) o9 Y/ G: e( o1 d' c  ~{- ]$ l4 v: S" ^9 Z& f! I
        FLOAT        fClock = nes->nescfg->CpuClock;
1 |( W. {9 C, g        INT        nRate = (INT)Config.sound.nRate;# Z1 ?5 x' s% p# o. j7 m8 v
        internal.Setup( fClock, nRate );
9 x( F4 Y  e, s# U        vrc6.Setup( fClock, nRate );1 f0 w2 p9 k( X" b/ ^! e5 ]
        vrc7.Setup( fClock, nRate );
) v; A, i9 B4 y        mmc5.Setup( fClock, nRate );
8 w, i3 b% U/ \        fds.Setup ( fClock, nRate );, U$ ]# k- P3 T; Y- y+ \) @
        n106.Setup( fClock, nRate );
; O- @% [6 d" ]& X# B        fme7.Setup( fClock, nRate );0 v9 o! V" @! _9 R. s& B: e5 d2 h) X
}( P5 X9 q8 E$ p
+ Z! ?" {4 l. h$ y: N* M+ ^
void        APU::Reset()
# B$ z, H# z0 c4 D{
' m) m# W7 F- d! n% c0 A9 v7 `        ZEROMEMORY( &queue, sizeof(queue) );/ U. }% `" h$ U
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 m% k$ a8 D  r( [) E9 a) E% I4 M4 |2 m  T
        elapsed_time = 0;* H. f6 o1 m+ n2 [# h

. S; w+ Z8 w8 F, K  l, ~* L        FLOAT        fClock = nes->nescfg->CpuClock;3 v  ^2 d0 \: R8 s, h* n$ e4 e' F
        INT        nRate = (INT)Config.sound.nRate;; P3 o8 A% H  r: M9 x. Q' Z+ E
        internal.Reset( fClock, nRate );
1 W! q; N: k5 u, g8 J' q7 h        vrc6.Reset( fClock, nRate );
' x! c; _" ~9 q3 ]- d$ N        vrc7.Reset( fClock, nRate );1 b6 o0 u. ^! Y0 R: {$ [
        mmc5.Reset( fClock, nRate );
5 Q( p* g4 M' \7 g# X        fds.Reset ( fClock, nRate );
8 y; P& G& X- s8 d; i        n106.Reset( fClock, nRate );" Z/ X5 Z, B4 t! }3 V( u* q
        fme7.Reset( fClock, nRate );
  w" c4 _# w0 A2 I! Z3 j% N- r9 u- U1 M# A; D8 r
        SoundSetup();
/ z+ s, _7 ~5 L* X}# X8 E. I3 ]# ]: {
- u1 d+ ?" s, B! i# s/ P
void        APU::SelectExSound( BYTE data )
" ~: C% m) B' ~$ f  Q1 f9 G{
0 ^( s8 k, x# q0 c: R0 e) [/ |        exsound_select = data;' f& ?- l4 e* Y6 V8 z- O
}
& U, \7 d- ~8 ]
6 B$ ?7 n! Q3 BBYTE        APU::Read( WORD addr )
. h5 ^: ?( e# H2 y{
; ?' P$ ]0 w; n, q* @        return        internal.SyncRead( addr );- x1 Z% s5 i$ K! e& n# @: G. N
}0 Z1 q- p' h& D6 P

: p# ~# y4 y- r5 |$ ]  ~2 _# Tvoid        APU::Write( WORD addr, BYTE data )
: j( ], X! D- _) z+ ]{2 ]6 M( f( [. W6 k6 E
        // $4018偼VirtuaNES屌桳億乕僩. I3 d2 ^" K/ W' h
        if( addr >= 0x4000 && addr <= 0x401F ) {" p& a% }; u& i/ b
                internal.SyncWrite( addr, data );6 |: L" z1 g7 s: V, c. c
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );1 |" O0 [; t% R! A( J; e( j
        }
  z- Y0 t3 F! a9 U7 G}
2 }, ^7 E1 u+ g* ]: M# O
& y# k4 k3 @+ @9 KBYTE        APU::ExRead( WORD addr )6 p7 e6 a* c/ l; y1 T2 F
{. u) P  \: X! I) ?0 N  v& a
BYTE        data = 0;
/ [# \; y! k; j) f5 r  T& G
( `/ c4 A. P3 B5 F        if( exsound_select & 0x10 ) {$ M- T5 \) w( ]2 @/ f0 C- x
                if( addr == 0x4800 ) {
! {" A' T4 u4 f; U                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );3 ?: \9 C! c# z8 k! s9 s+ @
                }! d9 c. m7 Y+ @
        }
4 J+ \% p% `' g  K- s        if( exsound_select & 0x04 ) {
; M) J) \4 v- N" q) D6 ]* T2 A! f                if( addr >= 0x4040 && addr < 0x4100 ) {0 I5 C  E* {  l. w6 T! q6 d( X
                        data = fds.SyncRead( addr );" b8 A/ ~3 b4 y) B8 n: y
                }% G. f, @- q4 Z5 ^; s% D- y/ B
        }8 v3 T# b6 r; ]; H% H
        if( exsound_select & 0x08 ) {
! m$ W( H; k, n  b+ j                if( addr >= 0x5000 && addr <= 0x5015 ) {$ }) G$ s) E4 q( d# J* \% U$ k
                        data = mmc5.SyncRead( addr );& `0 J: c7 a' O* N4 S1 O) U
                }
; W6 V. L% u+ [: T6 |' \3 l9 ~  d        }- G- }1 t. \: U
8 q/ I% O$ \2 D1 w6 F
        return        data;
: a; V- M& v0 B9 E% G2 F}
( E- Q4 [+ w8 A. N- H5 A% y
7 m9 E; P) X  L/ C( I* Qvoid        APU::ExWrite( WORD addr, BYTE data )
, Q. i" L# Q9 I{2 P4 N, f: `; ?/ o5 Z& t
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );2 ^+ ^. |6 O4 P$ \0 ~) |

. q' A* W9 {" ]0 A5 k0 e) F& O9 V        if( exsound_select & 0x04 ) {2 j; Z+ b; _+ z! c. O
                if( addr >= 0x4040 && addr < 0x4100 ) {$ G, |7 Z# O6 i5 a* I
                        fds.SyncWrite( addr, data );
8 ]$ u$ B7 q3 Z! _) z* @, {                }
, @6 B9 L0 i) r: ~5 h        }$ ]9 V) Z$ h) \; F

$ f/ p' T$ X( v; s% \# v        if( exsound_select & 0x08 ) {8 |: x7 s3 ^5 j* ?
                if( addr >= 0x5000 && addr <= 0x5015 ) {3 y/ U7 }# L  w+ v- M  j
                        mmc5.SyncWrite( addr, data );
# I: [2 V- I& [/ f( q                }) b) P1 t, U, X. {% }. P. v
        }* o7 B4 n1 j, u4 d: S& [
}
+ u2 f  ^& W" g! j/ Y. f/ n& I: t- l  U1 ^! B8 u  I4 K1 d
void        APU::Sync()7 l: d5 H+ \/ L/ ~
{
, o9 w. I2 E3 v' Q; U}, k. g) ]' ^- h* N# f6 H- e* ?

7 U* N/ E% l  e) cvoid        APU::SyncDPCM( INT cycles )
" N3 y8 m' w* S8 E% j) ~{
' {! C" r8 K7 e        internal.Sync( cycles );
9 F# K9 B1 R& E+ [: h! U9 O4 ^. v+ A
        if( exsound_select & 0x04 ) {) J/ [% k: w. @. ^: R
                fds.Sync( cycles );
8 f; P* g1 H$ W6 X( f        }
- Y* ^$ \+ g9 Y  X9 ]3 D        if( exsound_select & 0x08 ) {2 p( E- C1 E5 U, B
                mmc5.Sync( cycles );- d+ M: j. ?9 T- m- D+ p% N- M3 ]
        }0 q$ }3 U3 P0 ]& m5 e; P% R' F
}& u8 T! e0 W; D0 u) a4 i4 ^8 ^9 t

2 w1 x: Y* R# h. M& X8 j* D4 Ivoid        APU::WriteProcess( WORD addr, BYTE data )
7 w) w  d5 y' j) [. ?{2 u; I) l4 m3 a' H% B, v8 H
        // $4018偼VirtuaNES屌桳億乕僩
; t# g+ S/ c( T4 I. B        if( addr >= 0x4000 && addr <= 0x401F ) {
/ M- r& o; p4 d$ w6 ?. o+ m. U                internal.Write( addr, data );" C/ u& {" J" i& n1 l- g& O. M
        }' H* c' W8 f3 q3 G# v( Y2 _3 b
}7 C4 ^  m6 |) s' C
' ?7 L& l( `$ y5 C9 X) i( r
void        APU::WriteExProcess( WORD addr, BYTE data )
( J2 e0 B4 O# J5 Q6 m3 _4 s{4 W5 @! I6 N( ^1 F$ l; F
        if( exsound_select & 0x01 ) {
% d1 l/ J% G3 k, k* j8 D9 k" ~8 B                vrc6.Write( addr, data );
8 t7 b2 p  [! h, M        }- ]& U6 H8 w% h) e& x7 _
        if( exsound_select & 0x02 ) {
3 L+ l& E. ?" t                vrc7.Write( addr, data );
9 H- m& h0 f0 o' y% j        }0 m* ]1 _. W) N: M$ F+ q8 G1 a
        if( exsound_select & 0x04 ) {7 U$ `0 C* ^; ?; K3 x( f0 C
                fds.Write( addr, data );
8 s" X. B& G6 U        }
1 U+ A/ i5 d. Z# u6 u7 Y3 x        if( exsound_select & 0x08 ) {9 W( i) N/ S0 d. S+ U
                mmc5.Write( addr, data );
* {, J6 A" B. l) m) J) X        }
- @3 ^. M) _( ], k2 t2 Z        if( exsound_select & 0x10 ) {' u: k) x( I- ?4 }) t5 }% [. g
                if( addr == 0x0000 ) {% \$ q5 a4 k* q3 C) J$ T( P
                        BYTE        dummy = n106.Read( addr );
1 l1 Z4 B3 H& K# `6 P                } else {, G- E1 n$ U) ]1 E
                        n106.Write( addr, data );/ k7 l0 O* E0 r' z4 K6 [
                }
% `7 i7 _" |4 Q7 S        }& T! x, U; w% J, C9 [
        if( exsound_select & 0x20 ) {( k+ x8 L0 T2 [% ~. D/ A
                fme7.Write( addr, data );
5 O' d+ I& ^$ U9 p        }. z9 H% B* q) T& o
}
7 b' i2 K) X* k2 X: y( g2 D7 j4 N+ E( h6 L5 Z
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
8 W. _  b4 m4 e; o5 x{8 f3 z7 T7 q" V7 y+ Y
INT        nBits = Config.sound.nBits;  @( S, U5 |% d& r. Y" N
DWORD        dwLength = dwSize / (nBits/8);' E7 Y6 c3 R6 i' T8 C' h, G
INT        output;$ u, |, X9 |) ~+ [+ B5 `; F
QUEUEDATA q;0 w7 s- g. L: G
DWORD        writetime;- H, r( i; S0 g2 x# `& s

1 j; |* Y. N  \" y6 CLPSHORT        pSoundBuf = m_SoundBuffer;! @4 N" N: b7 u8 k) M7 `# \
INT        nCcount = 0;# j  Y8 e8 ?5 [" R0 e9 N% x0 u

* \* C, x% B) }5 q, y0 B2 vINT        nFilterType = Config.sound.nFilterType;
0 }8 L/ B) P8 W7 L8 K$ E
( b; e0 `5 ~5 q" r: O        if( !Config.sound.bEnable ) {
* o; i( b: Z/ H0 x3 y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
$ m7 U: ?# g- I' U0 l                return;
. _9 {  P; M) E" N        }
9 T# X: c5 b- A: U- T% S' l! \! g! y: P. i% O& H
        // Volume setup
: c  m8 [# T0 i" P# _1 P: c5 ?        //  0:Master
$ Y! s# s% f: ~4 a        //  1:Rectangle 14 t9 y! V7 U7 R, U$ [/ g* ]5 k* A
        //  2:Rectangle 2
: V0 j) D# v; S/ x9 ~        //  3:Triangle6 z# i; m2 a# k2 ^' R
        //  4:Noise( I- [' i' T6 i. _5 ^2 v
        //  5:DPCM
, m+ t" a" t" v$ l7 ~7 v        //  6:VRC6
/ E1 C  Z: u) ^& f+ t& \        //  7:VRC7+ v. q! x9 K9 A+ }! o( v) \: B
        //  8:FDS3 G, {! H- b5 _* E( S
        //  9:MMC5
, R; e- @5 f% M- U7 s. N- q4 n        // 10:N106( ]- P9 ?) _% P0 u+ |) {) t
        // 11:FME7. R) i8 h5 @/ L! d/ \+ m
        INT        vol[24];
6 A+ h/ i8 r, j, }        BOOL*        bMute = m_bMute;
( k- Y% y* I9 h0 @% G        SHORT*        nVolume = Config.sound.nVolume;8 O, N. K2 J9 k/ m

& O4 ?5 l; B( l2 I8 w- y) g8 h. G        INT        nMasterVolume = bMute[0]?nVolume[0]:0;' s) A2 j) Z7 L: k. @" f" v
) |! }5 G! i+ O9 d2 Q) S4 w
        // Internal* W0 W5 c$ r. P! ]
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;, `5 I# y  |+ T5 f- V4 w; p, |
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;3 X8 X. I/ q2 f8 g, n
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
1 Q. s" G1 W4 n* ~        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
0 f5 J3 O! Z. P% @( v( }1 ]        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;; G) M4 C1 k* s4 S1 A" C

2 O( }/ p  q2 T" |3 u0 D" e) e8 Q  G/ \        // VRC68 q+ O' D. t( @$ s; x
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* C3 q4 k' W+ j5 l7 Y. b3 F        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* ?" `, H) u  w- L        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  v4 N" l; d5 H0 c8 E% y7 V
7 M7 v+ X# k1 k% o
        // VRC7! L. l6 O$ P( e8 _" ~9 x3 Q/ s
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ K1 T) N+ T" R# x! O- z/ h7 e

% l1 s3 R) E8 @6 o- ]        // FDS
$ k6 ~. m+ U( q& R- E" j        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;8 B% @, T% Y8 \1 S

7 O0 X" W8 D$ W0 D% Z        // MMC5( L/ W5 f& e/ h2 A0 h. y
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# ~1 N1 o/ Y. f% S8 ^; g        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! @1 K/ C1 u6 ~( f. z3 Q  w5 n
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- Z6 V* T. o, X7 X3 N% Z
2 x% k* N' L4 h& m        // N106
! w4 m2 ~- t# }, m* i        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 K% q( `, e- n' m$ |/ t, F
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 B% M' K+ T' P        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ s( V; a2 _$ b5 P6 U0 P2 L        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) I7 f! h) T% t8 k& y% G) x2 ?        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: W8 _; {" F# r        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 P; R/ S5 p3 \% f" V* x- y$ X        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) D) x" _6 K; w: R$ z/ @, O        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 K. T9 o, l% q  v& n. X

: R2 |) [7 x8 s2 v  x        // FME7* j$ P& c2 `6 m! m. B
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% i) @. M7 x8 L8 Q        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ Q/ E1 F( [* F4 N# d        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 ]  n. B+ E8 ?6 E
! \" P! F7 f% ^' N6 G
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;4 d& @- k" W7 g
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
+ C" f& F# F2 v' i; O
0 s9 l$ M% o+ l& G        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& B. T# m5 B6 g  R
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {2 |+ m( ^/ _1 m0 z5 C
                QueueFlush();
7 v% v; j# s- Y& N/ b+ ^" H) Q        }( S" Y" w! `; X6 \) d

8 X$ F5 @3 B+ Z+ n0 U        while( dwLength-- ) {
8 d* f1 ~! a: V  m- b% d                writetime = (DWORD)elapsed_time;0 G: u- H  j3 c+ i  ]% p

8 m% K+ z. }3 f* S                while( GetQueue( writetime, q ) ) {6 i2 V+ Z; N: s' p) o0 R) i
                        WriteProcess( q.addr, q.data );
) O3 K3 `! e/ z7 o6 h$ c$ @                }
1 Z& y" ]" w$ x+ c$ C8 _) M2 I7 C9 ^8 e0 N4 _* S2 n
                while( GetExQueue( writetime, q ) ) {
* T% q+ a1 z6 @4 f. X6 x                        WriteExProcess( q.addr, q.data );! v" I6 S1 J9 @: r" z+ U4 ~' Q. ~
                }" t7 k7 P) e8 w. P% f( `5 {- C

4 U: C4 Z8 L; |% a% o% b                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
. W: x( P# Z- A* s1 J# E3 V9 N- k  J                output = 0;0 i, {8 K& Z8 l/ W, B
                output += internal.Process( 0 )*vol[0];- e9 x/ `9 w* B/ E9 C  Z: H
                output += internal.Process( 1 )*vol[1];
% B# {* l+ a( y% a2 S4 w. K                output += internal.Process( 2 )*vol[2];2 v8 G* R3 z3 M  I/ a5 W  a
                output += internal.Process( 3 )*vol[3];
7 J0 N4 a; C" _4 ]4 o                output += internal.Process( 4 )*vol[4];" P  Y6 }' a- v" M- P6 P7 x9 M3 O

! o' U1 y; e% C: `# y$ J                if( exsound_select & 0x01 ) {
* \& L$ g# i* t; N6 I/ j                        output += vrc6.Process( 0 )*vol[5];9 {  q# [7 z0 \, R7 m. R8 M
                        output += vrc6.Process( 1 )*vol[6];! [  y7 f5 D& `) o  P! b8 O
                        output += vrc6.Process( 2 )*vol[7];
' ~: i7 e( U$ y% k6 n                }% W" D7 W' i8 f
                if( exsound_select & 0x02 ) {3 O! q/ }) u. f+ x2 F+ q6 j
                        output += vrc7.Process( 0 )*vol[8];
& S8 B( V" A4 R5 s5 K5 ^! D                }; J  K6 G, I# Z, |3 y
                if( exsound_select & 0x04 ) {/ L3 e8 W( M" J0 P2 }
                        output += fds.Process( 0 )*vol[9];
8 O, Z+ C0 o+ M                }
" v6 ^% L- S1 L* X% l( m+ m0 k8 |                if( exsound_select & 0x08 ) {
( }: J* j' R& T                        output += mmc5.Process( 0 )*vol[10];, _1 i& J. X$ g$ d
                        output += mmc5.Process( 1 )*vol[11];. J7 E$ l+ `1 u$ e* w' t( t
                        output += mmc5.Process( 2 )*vol[12];' W5 e2 Q6 G# A: R5 Z3 d) ]' x
                }: n% }5 N$ q3 H* r8 ]* q
                if( exsound_select & 0x10 ) {
5 E/ O! y" C! f9 n                        output += n106.Process( 0 )*vol[13];
" i9 a. _( v) |! l; j, a# t                        output += n106.Process( 1 )*vol[14];. p+ r0 O( F0 {" l1 |! d3 u3 V
                        output += n106.Process( 2 )*vol[15];! V. s' L; M" B8 O3 D2 q
                        output += n106.Process( 3 )*vol[16];
# Z+ u6 ?+ h% u2 g8 i                        output += n106.Process( 4 )*vol[17];
0 a: d( U6 [1 l" n/ r                        output += n106.Process( 5 )*vol[18];
6 W# |  Z9 o0 @& Z2 l6 s( w* m                        output += n106.Process( 6 )*vol[19];* u- V% j% i" q& H# @5 W
                        output += n106.Process( 7 )*vol[20];
  M# C: ^* l: Z# n                }
5 Q- h5 \. S" ^, B; Y8 q+ ~% \6 P) T                if( exsound_select & 0x20 ) {1 `7 W# K+ o. {7 C, ^
                        fme7.Process( 3 );        // Envelope & Noise
/ h' T- G' i% g  m8 o                        output += fme7.Process( 0 )*vol[21];
0 |/ v9 v6 H0 P: E! U                        output += fme7.Process( 1 )*vol[22];
% @- V  z3 ^8 [. [% E' R) }8 m                        output += fme7.Process( 2 )*vol[23];
: b, u8 |& N8 f% W* [  m! ?                }
# }; D" _2 f7 {8 }2 ^
6 m  Q$ }! d* u1 L  q5 o8 E6 N! c                output >>= 8;
" z8 c4 f: T& y% E( s  h$ D, y) J$ i4 u% }/ n: s' t' P
                if( nFilterType == 1 ) {
3 g4 O( P* G7 K8 l# @                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
0 i- C/ R  i" J: Q5 _. v# U" t4 M& w                        output = (lowpass_filter[0]+output)/2;
( v" X% q: c; `. |4 O8 {$ C: g                        lowpass_filter[0] = output;
4 I. \9 U* D6 _/ e                } else if( nFilterType == 2 ) {6 i. W8 }" U7 M" f
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ x" m5 L( G1 t  p* F                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;- [) A" h) K; l3 }! [+ y/ M7 O9 b* h
                        lowpass_filter[1] = lowpass_filter[0];
/ \  V2 f) I' D) t) x                        lowpass_filter[0] = output;
1 H" v& Y0 C( X  G                } else if( nFilterType == 3 ) {
2 u! e4 L, L! u5 H! l+ {4 ^: j1 ?                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)% ]! _& d% T8 V2 Z
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
' s, O8 F" q# r: J                        lowpass_filter[2] = lowpass_filter[1];
" g; \7 q: Y- d: D                        lowpass_filter[1] = lowpass_filter[0];) l8 I" ]# X3 S* g* t- I5 D. I
                        lowpass_filter[0] = output;
1 p3 ]! O6 n  w& C3 c& o; B5 @                } else if( nFilterType == 4 ) {8 T0 k5 K" q7 ], f3 Q) ?- d0 O1 E
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)2 y1 @/ l0 i' |1 _3 X9 `
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
7 l" b7 D! R" U% D4 P8 y                        lowpass_filter[1] = lowpass_filter[0];
: V. _5 ~4 [! G( T/ T* S! B                        lowpass_filter[0] = output;
/ o7 k/ h0 R! i8 l                }, f/ O' L+ V0 s" v- g5 K' ]

( V- `, x8 N: {3 Z) G#if        0( `$ h# @  L' Q( h
                // DC惉暘偺僇僢僩3 }4 O, N( l: @7 V, W2 S
                {& Q0 V4 R) _2 H. O
                static double ave = 0.0, max=0.0, min=0.0;+ ?- l# u- V; B7 j
                double delta;
* N: z# t8 J' P3 D                delta = (max-min)/32768.0;
# D$ r8 `, S1 j; q                max -= delta;8 J1 B( {* Z6 @+ e& O
                min += delta;" r) O4 m1 ]7 v' Y- V  i4 p; F) {
                if( output > max ) max = output;$ q( R: ]+ C( f/ f2 h
                if( output < min ) min = output;$ q3 M* ?2 k+ Z
                ave -= ave/1024.0;
1 t9 r6 s% l+ V                ave += (max+min)/2048.0;& Q; U$ R2 `) f' T- v/ t
                output -= (INT)ave;
7 l* b- g: L3 a6 G                }
6 n; @% c: T1 [! t8 ?6 N1 m, L2 \#endif
1 {1 Q2 x7 R+ S- R- b$ p#if        1
( }/ J# X' R+ e3 V  x6 x1 [& Q                // DC惉暘偺僇僢僩(HPF TEST)2 C1 E/ U' O4 u6 z) G
                {
1 d. {( b: j4 {1 Y  r& h//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
+ [& O7 U3 l5 u, @. i                static        double        cutofftemp = (2.0*3.141592653579*40.0);
, @8 q' G* ]2 _0 _: h- {                double        cutoff = cutofftemp/(double)Config.sound.nRate;
" v8 n7 S* l/ Y' i- V' t                static        double        tmp = 0.0;" n5 R; @: @( a" L, y' q4 Z. I" v* c
                double        in, out;3 x3 k% ^' r- z/ U

" f: T7 j; H0 Y6 ?2 C                in = (double)output;+ q, ?% u& G# H! N3 S* ?
                out = (in - tmp);
$ M  X/ @8 d  ^; K4 m                tmp = tmp + cutoff * out;
  d: g( E( n; t1 q# u- |. X
5 `7 |7 A& d7 ~1 O8 |( y                output = (INT)out;
8 z7 C1 \" G& A# i/ ^: r                }
* {& b+ h! X& B7 p0 B. s) ~#endif, _0 T0 ^' c) u
#if        0
5 ]9 M: q- g6 H- ^. g* s. `                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)8 E, m7 I' w7 R; x
                {
0 a: O0 w' a+ |$ N                INT        diff = abs(output-last_data);
$ p4 ?% B  [) W3 w7 P                if( diff > 0x4000 ) {8 }3 P5 }1 C) S7 s) o
                        output /= 4;
2 Z; z$ Z2 ~& }4 z                } else 8 c# Z3 a2 D( p* r
                if( diff > 0x3000 ) {  C" M; ~, r% w2 i1 o/ x/ O' W
                        output /= 3;
1 X' ~4 x$ ?$ M: L; @- r  \                } else9 g( V) q; o7 ]; b3 L3 b
                if( diff > 0x2000 ) {! Z. }' u( H, c6 B! N. @2 Z
                        output /= 2;
8 _; j' n4 i, B+ V( t! k+ F                }8 R5 D( T9 I7 D& K+ N
                last_data = output;
2 A; b+ L7 m. e; n3 r0 @( T                }, _* \- n$ f" |$ j6 ~
#endif
7 p9 v( H' o! s                // Limit- j6 Z& k! ~9 f( A
                if( output > 0x7FFF ) {; N% F- t4 o2 o: ]& z, K
                        output = 0x7FFF;
/ G6 ^3 x8 ]3 F                } else if( output < -0x8000 ) {* z+ f; z- g2 F: A. T* X; m" s
                        output = -0x8000;
0 I4 r1 G" F% v* Z2 y5 {                }
# h% ]# x7 x; i4 ^+ i4 `4 u' ~3 g' ^" v& {5 t& ]7 ]' D2 O! G
                if( nBits != 8 ) {
( Z0 I  `" J7 ^5 }/ v# U                        *(SHORT*)lpBuffer = (SHORT)output;' j) l9 S5 ^! B8 V2 J
                        lpBuffer += sizeof(SHORT);
+ z- @6 ?; A! @5 `" c6 j& O! @                } else {& l. |8 \. [2 [7 g
                        *lpBuffer++ = (output>>8)^0x80;- S" k0 ?& ^3 A# s
                }  L( [2 O, c3 E- G: r9 o8 e' F

4 m; n8 r+ D2 @                if( nCcount < 0x0100 )! ?. O5 O& Y% G" I1 K, C8 J
                        pSoundBuf[nCcount++] = (SHORT)output;
# A( n+ U# K8 P9 G1 _# U
0 u! W5 l8 u. L  u& K//                elapsedtime += cycle_rate;
: b. q. p+ n+ l( V% p  c% g8 ~                elapsed_time += cycle_rate;
+ C# u5 f8 J$ f( R. X( `        }
" `" I* T: S6 Z  s" c5 o3 G2 f8 [, ~& g/ |
#if        1
+ f" O( c1 c2 W        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {; `2 J# w8 d1 e: ^$ ^
                elapsed_time = nes->cpu->GetTotalCycles();
4 k: H  K  {, ?# s( h        }
/ A1 @( f) H% z$ m8 i0 d4 T+ Y        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
1 o. G! G# M  \7 l# t/ e                elapsed_time = nes->cpu->GetTotalCycles();% c8 k1 z$ A* ]5 T
        }
: B7 d% ~$ Q& C. u& P0 t' C7 V#else: t4 R7 j& m0 S2 ?; Z  D& J$ p
        elapsed_time = nes->cpu->GetTotalCycles();
  W. C8 C3 ]# @% c; v. C. l#endif  ?( |# f* @) `# x+ K
}
# o) f0 J- x8 r7 h% ?/ m: }- l- K# E8 g  @. O6 D& |
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
: K3 ?+ q. b+ f/ A+ S. b* gINT        APU::GetChannelFrequency( INT no )
5 @: |! v$ u- j# D{
% w" f0 \3 N* c, o        if( !m_bMute[0] )
1 S& A" n% H2 g' ^& o                return        0;& M2 k) J! v! Y3 P% a. T' C/ j, a# }
9 b; `$ V$ g0 ~. e3 j
        // Internal  d4 |: n$ R/ T: s5 s( R- J
        if( no < 5 ) {
& G' ?, U; l& ^! {& ~( r: N4 B                return        m_bMute[no+1]?internal.GetFreq( no ):0;8 d+ ?3 c0 O) R" v" w1 F% G& j/ N
        }
- P! C$ M8 I' n        // VRC6
- n! k' I6 w7 s* _        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {# e8 G* p2 E/ \" R/ U8 X& y- o
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
& r" v$ @1 C- x, \8 h$ R, o  B! h        }
, `0 Q6 j% N- E: T- T! K        // FDS
0 p+ H6 W' B- W: U- t% x( S* [        if( (exsound_select & 0x04) && no == 0x300 ) {
6 N( c, z( P/ Z9 C1 I5 S; m0 Z                return        m_bMute[6]?fds.GetFreq( 0 ):0;( c6 C: {, F( E/ f8 \/ X$ x
        }
5 Y- [' h" ]) X! q        // MMC5
: G$ ~: r# H6 Y3 x1 c/ S        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
+ R' g# X! `3 M; O% X9 O                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;6 @0 C# s7 C1 I
        }! Q4 X1 A- i+ G8 A6 I) D9 h$ J( |
        // N106
  z% T7 ^" w# o; d0 H& r        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
. W% m) _* r9 o; q# m                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
, n4 x) }! c* N" s        }
/ u  d& s& q' J' x        // FME74 L4 b/ u( \! s1 r# M
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
7 u5 C! S% N! s# p/ V2 F                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' h& V$ q# m/ F3 Q, G        }4 D9 W; \! T1 S6 t, d# ?
        // VRC71 O9 _% C' R% N4 N
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ r+ t4 r5 m0 Q' A& s* j                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;; Z& L& m- M4 p: A- g* P
        }2 [# O# t' A$ c9 I3 l' M
        return        0;1 ?8 g  c0 A+ t
}
) p* y: S( Q  p9 U) [! C8 L. V& z% ]2 w4 O
// State Save/Load0 g1 U/ a; E* {# [5 h5 c9 j
void        APU::SaveState( LPBYTE p )% j6 K6 o+ v9 e- P3 c1 Z) f: W
{. N% l5 w) |1 `# L
#ifdef        _DEBUG
5 U# @. m# `/ L; n) _# TLPBYTE        pold = p;# F/ C$ B0 D; \) c& C# ]
#endif( B6 V- Z: k# a6 L
( f1 M+ L7 G: Y4 v  I( O8 g
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
& j- v! l- l, E5 `- [2 G% J        QueueFlush();+ S% x! {: u: U; \4 a3 r& s

" }3 Y7 a  E" R! |        internal.SaveState( p );
/ Y6 i6 w5 Q2 m4 |        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* X' I2 k9 \! b. w* A! V
. P- b% S$ C, T0 L+ x        // VRC6
# ~/ i; [, M8 W+ \# v        if( exsound_select & 0x01 ) {. I7 [6 M0 I3 j( @4 h1 O
                vrc6.SaveState( p );9 P$ j; z/ W9 D# F. n
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: o6 a$ [5 W  W9 t9 e+ h
        }
- C6 b; V- i  Q; A3 o( A5 b* M# i        // VRC7 (not support)
: V( q5 V, F. ]  E. w6 s' v        if( exsound_select & 0x02 ) {) o+ h& I7 l  r# i/ m. o
                vrc7.SaveState( p );
: |( [8 t; @9 F                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; C# b1 u/ C9 ?4 J: i
        }0 i, c+ i% T( b" ]2 m
        // FDS3 w2 H4 D- B- A% k
        if( exsound_select & 0x04 ) {
8 f4 u, t/ B6 h7 H5 ~/ _  E1 L; b                fds.SaveState( p );2 S6 t% o" t8 ^2 v2 E" ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' O! W: x- R) i, S
        }8 E3 m' h: U* x
        // MMC5$ E7 r, U% Y: c5 M" d1 i
        if( exsound_select & 0x08 ) {; A, u6 M& p6 T- a
                mmc5.SaveState( p );
4 ~6 E7 Z7 x) c8 p) |7 R                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' [4 @7 B/ c9 j- m' v
        }* p; b5 E* G) M/ ?& L( E: o
        // N106
9 K& E0 p7 ?0 o! g: J+ n. c        if( exsound_select & 0x10 ) {
( g, H2 J) [+ \) b  o. l                n106.SaveState( p );
5 I2 X0 g) k! i: T+ p                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 `) h" h& ~7 W9 @# w% w0 w6 |        }
3 K' @0 P; H* |9 c        // FME7" B! L7 G6 z+ K0 @% D
        if( exsound_select & 0x20 ) {2 X; L5 U9 C/ r; m* Y+ M
                fme7.SaveState( p );& r) q- P6 `: Y& c/ Q4 }
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
" l4 D0 m, I: j, _        }  G, e! o% T! h2 ~% s- C. E
4 A0 o2 O3 @' [& Q3 I& x
#ifdef        _DEBUG+ _" F+ W4 I2 o/ Y3 m/ e$ {
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
4 j6 o% U4 B  \/ K#endif
. G$ @' y0 h2 a$ H/ b9 ~/ Q) T* c}4 Y2 j6 K& C! r! I  [2 |* t8 l
7 {* z0 F  G9 A" y8 B) R  o
void        APU::LoadState( LPBYTE p )% L. g5 I3 P$ E! @8 q1 J8 G% v- {; A* x
{
1 [  K  j0 a. q! S        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
* \  \3 S/ d$ f' _' l. F        QueueClear();
, n. N% y' M4 O! o# W- ~/ d1 [5 Z0 A3 s$ a9 M1 i' I  u2 A
        internal.LoadState( p );7 ^( X% Y( A, R+ ^( O
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 c9 m0 C+ h# ~; o/ Y
  a! \$ n. p4 I& v( I
        // VRC66 y. f) x! t& G1 z' s
        if( exsound_select & 0x01 ) {: c* G* ~( S/ J, E' @
                vrc6.LoadState( p );
' p  O! z! V/ l% n% E1 E                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ L. w; T9 Z7 `        }9 f$ I) o7 d8 }8 z' i" o
        // VRC7 (not support)+ ?, T3 }9 M* I3 v& h
        if( exsound_select & 0x02 ) {7 T8 m' @" Q% ]7 ?6 b; Q/ {
                vrc7.LoadState( p );
" I. E% i, |" M. W" I1 k                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* P3 H$ ~5 M  e" b; E+ W
        }" i& M( T: E! q6 h
        // FDS% \7 m. b' ^$ V6 N6 r
        if( exsound_select & 0x04 ) {
/ i, n; B/ w, d2 E$ O5 c( l                fds.LoadState( p );
' `8 q2 C' P% i, @                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
/ ^* Z9 F% A7 d        }  m. F6 \9 `, ^% B- L
        // MMC5
  Z( l* m0 Z6 }/ y        if( exsound_select & 0x08 ) {
: I7 x+ ?, _2 ?# S                mmc5.LoadState( p );
* u, p3 M, A) ^! H( T) S0 K  C                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding$ Y  E+ G% R3 }0 H6 g1 J
        }: j0 ?# j3 ]( H% s$ {
        // N106
7 `: d. i" F- y        if( exsound_select & 0x10 ) {$ u% T! [, `' ?0 \: W# I/ _
                n106.LoadState( p );
  \, t* U9 z* |1 F                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. t& W) R& a5 O8 H. z
        }+ n0 u4 U* P# }/ ~4 M7 ?' L" A
        // FME7+ J" Q0 J, `( V2 H: N3 `* R0 e# a
        if( exsound_select & 0x20 ) {
( S" e' Z; t; a6 R! A# o- [+ B" Q                fme7.LoadState( p );
7 @, D( }) o  j- ^                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' w5 O$ A5 s; ]$ V$ x2 ^
        }
0 x% \$ {- n8 x}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
2 T6 V6 K. V; R4 M- x' m2 m可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 d1 _4 R) {' K  q( @. d2 O
感激不尽~~
) b7 n) d/ R; _1 S
恩 我對模擬器不是很有研究,
  b1 q' D6 |7 r0 Q雖然要了解源碼內容,可能不是很困難,
8 W7 [0 L1 l7 [不過還是要花時間,個人目前蠻忙碌的。
8 |5 G2 _! s0 f$ ~- T1 Y) E- E% J0 T) L$ [5 S
給你一個朋友的MSN,你可以跟他討論看看,' [+ q% b& @/ S8 ^: L1 X, M0 I
他本身是程式設計師,也對FC模擬器很有興趣。
# v1 [, L6 Z" q4 K, ~- p$ ~# d
, E8 R7 [$ w6 Z- C" W7 T/ RMSN我就PM到你的信箱了。
( c+ ?  a, D0 K2 A' ~1 L0 n; n3 |, b$ R1 Z/ M! m3 x
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
( C0 o3 U. y! W呵…… 谢过团长大人~~

# c' @' R+ g4 h/ i2 p; T# C
+ a# ]$ G0 p# o4 W; k1 ]哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 k+ F. Z2 l5 X6 v团长的朋友都是神,那团长就是神的boss。
/ f9 Y* j- a: ?$ l
哈 不敢當,我只是個平凡人,
, Q' M# P+ C  U8 S, G要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙; B* {  h" g: N
ZYH* n! p  C% b" l. [' m+ \4 y
QQ:4147343061 V) X7 P: j+ m
Mail:zyh-01@126.com) X% V5 M1 F9 \4 l/ @  |
5 D8 U) s- R) G6 g5 Z$ w
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! \, g- e( h# F. }8 v& D1 l+ _1 J再次对团长大人和悠悠哥的无私帮助表示感谢~~
% K: J' E8 ~: W. A% v+ _  N
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-20 16:55 , Processed in 1.107422 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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