EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' C$ v9 \* ^+ P) d8 c5 a$ h
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ L5 S8 B  |" x: R
这里有相应的模拟器源码,就当送给大侠了~~" b% |; @# q* u  b
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 * G( I7 }. Q, r" u5 x
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ y6 K% {. z* j8 W( K/ z
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; P% e/ D6 A8 f, r- s7 z& d
这里有相应的模拟器源码,就当送给大侠 ...
, F2 i5 k6 m5 K3 N# G; _
聲音部分(Audoi Process Unit = APU):
2 Q+ t8 Z- ~8 o4 v/ J+ N0 a0 M+ ?.\NES\APU.cpp
4 e6 ^% e. ?/ d1 i- i.\NES\APU.h% Y( V3 C+ A. f4 C- l7 c7 C
: c4 Q: W) m' s) i

1 l* `- a6 M& c4 j3 \影像處理部份(Picture Processing Unit = PPU):1 k: Z% W9 S, d' S+ \6 V) r
.\NES\PPU.cpp
/ I& `* _4 @5 a) @9 _.\NES\PPU.h
- [% v& Z* r1 z  C( Y
4 _" s1 a6 U, w( M如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 ?& Z; L7 N: @& B/ O(由于很多专用术语和算法机理都不明白,所以看不大懂……). C. t3 q. A  a8 }$ A# y; q
//////////////////////////////////////////////////////////////////////////$ W9 d& W5 C& o( L7 t
//                                                                      //
6 y, l, Y/ A! ^( {3 ~//      NES APU core                                                    //
+ j! @4 c) F, Y& w/ e1 x//                                                           Norix      //: q; N  Y5 q5 ]0 |" l
//                                               written     2002/06/27 //
& E5 N" p% Y- `; X//                                               last modify ----/--/-- //* r" S, c; H$ u3 [
//////////////////////////////////////////////////////////////////////////; i% [& ]$ {1 f& k" x; T# `. Y
#include "DebugOut.h"
) w9 A  e) B: U4 ~# n  h; c#include "App.h"
$ ~2 t% E8 ?' a7 {6 e#include "Config.h"( l1 [' L  s7 p$ I7 X

$ z+ G1 d9 ?" R- `#include "nes.h"
' z" j% T( }* N#include "mmu.h"+ G4 B+ ~: X  e! |0 K( [
#include "cpu.h"
. k7 M! t1 l2 b7 l* {#include "ppu.h"
8 `* X5 e/ l6 Y# Q1 Q$ w#include "rom.h"
$ |: C% C7 h0 m/ b: Y#include "apu.h"1 U( K. J* K# e. @' ^/ ~% V

6 ~. `8 ?. p% C$ @// Volume adjust5 y6 v3 p: \* c
// Internal sounds, x: i& w$ X# o; n" u. u! t
#define        RECTANGLE_VOL        (0x0F0)8 A% V' ~6 K% x5 n/ {8 s; W' _
#define        TRIANGLE_VOL        (0x130)
* d5 d& ]2 n+ c8 v#define        NOISE_VOL        (0x0C0)) Z, h/ D# E( C/ _+ P% d+ f
#define        DPCM_VOL        (0x0F0)
$ r$ L* ?/ H8 k$ e2 l// Extra sounds
3 @- I0 x9 [1 @! n#define        VRC6_VOL        (0x0F0)6 ~" _- t  H9 [; K4 {: r$ H
#define        VRC7_VOL        (0x130)
; `; L3 F( \/ O. z9 o8 A#define        FDS_VOL                (0x0F0)
1 k# N  T4 l" J; N# p7 E) f6 R#define        MMC5_VOL        (0x0F0), [$ i* r1 b0 E; `' x  m4 D
#define        N106_VOL        (0x088)  _7 Y4 a4 c; ?/ M9 J
#define        FME7_VOL        (0x130)4 t# l3 e9 V; A) ^9 m; r
5 i  v% E$ l! L' K3 h& ^
APU::APU( NES* parent )9 ]+ ~6 `5 k- g# F+ G! G+ e2 S
{
: P7 J: K9 G3 G1 H7 G  k; K) Y        exsound_select = 0;
4 w0 Y& N' j: n) F
% f1 I2 |' D9 ^  }        nes = parent;) f8 h- O8 `) m+ x9 |
        internal.SetParent( parent );4 e2 i! q$ N) D, f6 [
# H' C" |* T7 L8 N
        last_data = last_diff = 0;
7 c8 d/ L( G# _- z3 m$ }7 v4 _9 e  z& p+ [+ Q
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( ~2 l0 g4 Q) j2 Z1 C- a4 {  G
- W0 o2 C0 G9 T; y, e) U' v" G& Z
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- h6 s. r+ D4 A7 W0 c& h        ZEROMEMORY( &queue, sizeof(queue) );7 F1 |8 c: m/ R# g5 _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 ^8 U% O9 V0 y* T8 z/ l* M% I3 J) h% b! i8 v2 |
        for( INT i = 0; i < 16; i++ ) {1 }* z, S. m+ I0 R
                m_bMute = TRUE;
) s: P9 ~- _; {- f- b        }
2 P& w7 }5 c$ W4 p+ J& K}
+ x1 ?. t- w: G2 y( t" t
# }, _, c. ~9 Q" lAPU::~APU()& a  |+ M. f0 q0 J- P" ^
{
" S" E& }4 `* }( U}
3 S. M+ Y) o5 ^* Z! G5 \2 s. Q3 R% j. j: [- j
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )) {4 r& e% M8 I' \$ [
{
, N' X( |/ D) K- V' t& i2 C- o        queue.data[queue.wrptr].time = writetime;$ k/ D$ T* }1 W5 J. _1 k
        queue.data[queue.wrptr].addr = addr;
5 t0 v: G* A2 o2 t        queue.data[queue.wrptr].data = data;
8 b6 k" B" Z) q- V        queue.wrptr++;
( n9 m* r2 w6 T  Y2 ?9 T        queue.wrptr&=QUEUE_LENGTH-1;/ d) h# x( {2 d- ]4 o
        if( queue.wrptr == queue.rdptr ) {
/ [+ n; h( D1 h- x5 B/ O4 L                DEBUGOUT( "queue overflow.\n" );& F2 B! n0 ?# P0 H& x7 x
        }8 A7 N5 T! Y' k/ k3 f0 j
}' n5 Z8 w/ b7 r3 }, V- i6 B: L

' P. L: D# l% H7 H/ I. W6 p3 ~BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. o! b# \9 H3 W/ \- V: @3 N. `{
$ j& G7 R( C( k  f* a6 @! N# n3 ]        if( queue.wrptr == queue.rdptr ) {
/ E; ]( }  x3 s. ^. R! v                return        FALSE;
  X* c  P+ i% D        }
/ a  q* F2 _6 m! ~  l$ H- ]4 t! S        if( queue.data[queue.rdptr].time <= writetime ) {1 |. H# g% X0 R  Q& B% `
                ret = queue.data[queue.rdptr];' G2 b' H1 M) t$ l$ H
                queue.rdptr++;* T( V$ Z! o! A9 i/ D' E
                queue.rdptr&=QUEUE_LENGTH-1;& Z6 v3 @: \1 K. C' ?# j
                return        TRUE;. R; t6 D: X4 h0 h8 r% F( M+ K
        }* f) ~/ u/ d6 `6 g9 T
        return        FALSE;
: V; S$ h6 l+ T) }- ^& ~}
/ X% {) _, z/ g
5 V7 v: }& `# A* ivoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )* C2 Y% n4 ^% k. S" ~
{
- P/ X  _# o! ]5 @( W; s        exqueue.data[exqueue.wrptr].time = writetime;/ x! Q6 g# E9 i" B8 n8 K
        exqueue.data[exqueue.wrptr].addr = addr;
: G% Q8 j( A3 D& \& p, B        exqueue.data[exqueue.wrptr].data = data;4 A7 `; N% ~9 `
        exqueue.wrptr++;' W' W& s# D5 `4 f3 s. T( d
        exqueue.wrptr&=QUEUE_LENGTH-1;
& L; w8 `4 p5 Z- P, S        if( exqueue.wrptr == exqueue.rdptr ) {
7 l; o0 V. x' [9 h/ Y8 s' |1 B                DEBUGOUT( "exqueue overflow.\n" );( ^2 Y1 J+ W# }& z" ^
        }
% ^$ e: R+ t! _# u+ C}
% U& @9 _& z) }; [8 n7 T
3 q" k9 x7 c( h' H) ZBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. z# L% h/ T( o* g: N! `{6 z# K6 I2 \6 p- C
        if( exqueue.wrptr == exqueue.rdptr ) {
0 t4 O8 y3 D7 O  K                return        FALSE;+ H/ C) v* f( S- e
        }
( y3 S( x  N2 F2 Z* |7 t        if( exqueue.data[exqueue.rdptr].time <= writetime ) {7 O7 {4 d, F! c. x" f
                ret = exqueue.data[exqueue.rdptr];
  V  L  I1 V( h% x. U& u1 _, L* h                exqueue.rdptr++;
0 r- |7 ^/ U3 ~; ^* V) K                exqueue.rdptr&=QUEUE_LENGTH-1;7 G' U9 ^+ g2 m! J7 E3 L
                return        TRUE;. p3 W! g% [7 d4 o+ l# X
        }& p3 P, X; L3 K2 _$ I
        return        FALSE;
6 p- g1 p% d1 N) h# U}
! E4 ?/ `! m( h
+ a' d/ W' t! i+ @4 kvoid        APU::QueueClear()
" |4 ]7 C+ f0 d" B  o# E{
* G1 W3 [7 E; N        ZEROMEMORY( &queue, sizeof(queue) );- Z: d: `7 ^0 W6 [* e4 b' w5 D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 T* |- H9 }; S" q- s}
# r* T% ~8 x$ D: g- M
0 {. g$ S& @' r  f& D" u6 i( qvoid        APU::QueueFlush()0 L2 \2 S9 ]+ G5 [3 {- K/ d
{
# I$ m& ]  A, l6 S        while( queue.wrptr != queue.rdptr ) {
& w% m! s8 @/ Z  @  Z2 z+ ?4 l                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 {, j% C6 c2 @  C1 g
                queue.rdptr++;7 u3 I  G3 C8 p" m
                queue.rdptr&=QUEUE_LENGTH-1;3 v' s' P9 Z" z8 a- ]( y
        }) a/ u0 z, W0 T: Q9 J) k

2 _7 V8 Z0 ~0 d/ {; C2 `8 n$ ~        while( exqueue.wrptr != exqueue.rdptr ) {
* g* p" I* A: Z* O& B                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );, `; k% |3 Y) v1 G( x) S( f% J
                exqueue.rdptr++;
3 m& i* U& D! J# |                exqueue.rdptr&=QUEUE_LENGTH-1;# Q3 l7 d2 e* ?, g$ ~( {
        }+ F* g% U1 [: A* j% l5 x
}# K) }: S! T& D- Q0 @
! X& [/ n# {' M9 m
void        APU::SoundSetup()
: q1 s# B+ T$ F2 V6 o{
+ i1 o- D2 i; ~/ m        FLOAT        fClock = nes->nescfg->CpuClock;* Y+ M$ u7 z6 u% M4 ~* O" [: O
        INT        nRate = (INT)Config.sound.nRate;
5 N" T0 q- r/ a/ K0 C) v  O        internal.Setup( fClock, nRate );& Z4 y: |/ ^% b+ c1 d
        vrc6.Setup( fClock, nRate );
  d8 s4 P8 r! b. p. x        vrc7.Setup( fClock, nRate );
: u# I! R( s* e, \6 H$ `' V( G        mmc5.Setup( fClock, nRate );% S) e$ h4 l+ ^$ k) d
        fds.Setup ( fClock, nRate );/ |. P# u+ n% Y3 l
        n106.Setup( fClock, nRate );
! r+ [$ Z% a6 ]# K/ d! k9 ^% o        fme7.Setup( fClock, nRate );
- k9 m6 \# t& v2 `5 s' W, b}; V  u6 E: D" i. j

! {1 |* r! e9 \6 g' P. \* Q0 bvoid        APU::Reset()
+ Q: R6 B- S, W$ C8 P{
* S4 |( X6 X3 o; c; y5 k+ x        ZEROMEMORY( &queue, sizeof(queue) );8 ~* j& @, [7 B7 N& g
        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 Q! Y$ k; U4 e: }( }! X
2 j1 ~: w; l) G6 D% V5 @
        elapsed_time = 0;- x3 p8 V" F/ A+ N

% ^6 t, R4 o( M! L7 h0 f        FLOAT        fClock = nes->nescfg->CpuClock;
- `8 }  q% m6 x. j  z        INT        nRate = (INT)Config.sound.nRate;
1 x3 g" X6 ]( Z5 t* U# `2 i        internal.Reset( fClock, nRate );
; B3 N/ z! I& A; w, d        vrc6.Reset( fClock, nRate );
. M9 b" n  _+ s, [( `( C8 g. _9 e        vrc7.Reset( fClock, nRate );3 G0 o2 S* F6 R  x6 e( p
        mmc5.Reset( fClock, nRate );
. ?2 r3 x+ U2 @( T+ L        fds.Reset ( fClock, nRate );
5 _; @, B5 j+ e7 Y5 S2 Z9 I        n106.Reset( fClock, nRate );% f5 j3 y: H# E! S% m: @4 L8 M
        fme7.Reset( fClock, nRate );1 P! Q& `# g2 r5 H+ a. l
7 C2 @, h+ Z  z0 P0 p7 m, }
        SoundSetup();: N, g' J$ v) S& `7 D
}
9 r/ t) a3 T) L
0 {8 B( M& A( ovoid        APU::SelectExSound( BYTE data )! x: b' x! Y$ t) z( j2 A7 r
{$ w3 x( |% G0 a
        exsound_select = data;
1 G9 G( J0 }2 ~4 a, n- }, W1 M5 Q}; h! X8 [* H$ @# m+ m
- I. M7 Q/ K7 u( v1 ?9 F' n% l; y
BYTE        APU::Read( WORD addr )8 m0 J5 g# j: E7 k2 m
{# }1 I3 i) q9 \- ~0 \$ y
        return        internal.SyncRead( addr );2 S1 m. N/ g- W( w; W7 F, Q
}
' Q  h* _- x8 `8 _! v. ~! [( g$ y! T  H2 |0 z
void        APU::Write( WORD addr, BYTE data )! p* N: o( w0 U3 A1 |) V9 `
{
) c$ b7 c( S/ R) L( O        // $4018偼VirtuaNES屌桳億乕僩
8 Z) u% u" n( V# o7 M' f        if( addr >= 0x4000 && addr <= 0x401F ) {
( J, u: N' a0 \8 Z3 }                internal.SyncWrite( addr, data );7 q; Q4 d& I5 W9 W8 _2 K2 o
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
% b& q( H: w: f# ^        }/ F% J( n! ]% |6 h
}* A0 T7 Y+ V6 T3 ~% Q0 V
9 U4 Q7 C9 ?5 y
BYTE        APU::ExRead( WORD addr )
% R" L5 X; r7 @! @  \5 R{3 d/ M' p* z; q- x$ }5 X; n& V0 L* F* f
BYTE        data = 0;$ X0 U* y( N5 \! m

' p3 v# y0 o/ V  g) E9 b) Q        if( exsound_select & 0x10 ) {
! n7 r* Y# B  R+ f5 B) {                if( addr == 0x4800 ) {. A5 V5 S; `# W3 x/ Q- e% {
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );) y: ^* H$ z! ^' L2 H: b
                }
7 U/ L+ s; S* w: Y1 Y        }) z, s$ h1 A, x  u5 R& B: v
        if( exsound_select & 0x04 ) {& k0 c2 g5 j# N: u2 V
                if( addr >= 0x4040 && addr < 0x4100 ) {- i# r! ~" D) F0 S4 R9 @
                        data = fds.SyncRead( addr );
9 W! \& u3 T2 }7 ]                }! K2 `' L( J8 J; E$ j6 j  s
        }2 ^2 Q9 C3 |+ e6 J7 z3 h& N# H: c
        if( exsound_select & 0x08 ) {
( k. d" P( Y, d1 @                if( addr >= 0x5000 && addr <= 0x5015 ) {
) r& E' W- X0 K                        data = mmc5.SyncRead( addr );
# J9 A' U. i/ [% }% i) I                }. u4 N8 |9 h' ^! `* d. H
        }
! S5 p' K4 Y  V. X5 G- N7 _* M6 x9 W# K
        return        data;
1 P. j. n5 f! i; j}
" k- {1 z# {- P, M' u( C6 T
% e. N$ Y8 l1 u8 c" e1 h7 Kvoid        APU::ExWrite( WORD addr, BYTE data )
" d* {7 `1 q& B: l{) ~# b' m0 ]: V# x
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& R9 r" e- c1 c. R0 P* z# P9 e3 m6 u( s
        if( exsound_select & 0x04 ) {
- ]4 Z: o! n' W* ]. V; m) m2 S% k                if( addr >= 0x4040 && addr < 0x4100 ) {
) _% Q. X! p0 @                        fds.SyncWrite( addr, data );$ J0 i) W: G6 o; R6 `$ z
                }
7 m2 S' u2 M# V" d* B+ h, W        }7 [- h  {. ?) M! x2 `2 x* [

& u0 n: g$ M' g0 m( j        if( exsound_select & 0x08 ) {
1 }, i& @2 b; M+ [  P                if( addr >= 0x5000 && addr <= 0x5015 ) {5 K# e6 R- _. ]. G$ M
                        mmc5.SyncWrite( addr, data );
& t; h& f1 U9 \' p! U                }
/ e7 o# v) E2 u! Q. i1 a/ p7 K$ \. G        }
6 N0 X, X: |  q. K" d( l}) J4 B; z- \) U' S
, v& R/ |1 t" Y
void        APU::Sync()
( M" q% R* M* U/ s) i{  f! o7 `; }% r; l/ c
}+ T( J% y' C* U9 z- O$ ]

  U4 e" j$ Y+ k. d- }% Hvoid        APU::SyncDPCM( INT cycles )& E3 \" n' C( Z
{; a) v( G  B( H0 `0 a/ @
        internal.Sync( cycles );
0 o2 i9 D( }* ]2 I* a* U  A" {* d
6 g4 i$ ~) `: y7 A3 d  s6 N3 x" e/ k( t        if( exsound_select & 0x04 ) {
+ n, F; T* [( ^* J& t4 G- c                fds.Sync( cycles );
( ^9 N, g5 @4 y9 D1 }2 E" L        }
8 L$ n: H7 R: v- f% _' f        if( exsound_select & 0x08 ) {
) e" j9 d9 L" {6 \1 t; P4 |* Z  t                mmc5.Sync( cycles );
% N7 Y; n. w! q9 o1 Q1 ?: ^        }/ g- T. E7 [% O9 e6 B" `0 z
}
; B& t9 x+ W7 l9 Z6 {  k' V% r. |2 ~
void        APU::WriteProcess( WORD addr, BYTE data )
3 b: j1 U7 `& n9 t, X* Q( u{" O1 y! w5 L' ]# \* }6 J
        // $4018偼VirtuaNES屌桳億乕僩
* K$ a/ c+ u/ w5 a# f0 H        if( addr >= 0x4000 && addr <= 0x401F ) {( S+ ~9 J8 \$ y; \! g' _' o4 Z& F) t" f
                internal.Write( addr, data );/ W9 t! e* O4 A1 D" u) q0 G
        }
3 A' r- |5 O# N( G1 Z}4 [0 X. Z& W+ J- j

$ d2 A$ j# M  P0 L0 f! t; f: c' Fvoid        APU::WriteExProcess( WORD addr, BYTE data )
- |' k) ?6 S! V; m5 u7 a2 c5 V$ z{
4 @) J8 x  y, p. j8 {2 H$ D        if( exsound_select & 0x01 ) {; p: V! e* @8 C/ V
                vrc6.Write( addr, data );6 Y& g3 k3 i( k; B8 l% U
        }. {$ }+ l+ [; [. c0 V% T2 Y
        if( exsound_select & 0x02 ) {9 B9 n  |! y" x8 L3 \! s" y; d
                vrc7.Write( addr, data );: F* \  h& R5 V8 t: }, Z
        }; y( E+ L5 k5 j: h1 ~
        if( exsound_select & 0x04 ) {$ c$ }$ j/ n0 \* Y& q, y& B
                fds.Write( addr, data );2 ^9 I3 R5 k7 O% E. M
        }9 O: m; ^' Z4 F0 a" M
        if( exsound_select & 0x08 ) {
6 c8 a- ?5 d" \1 f+ T                mmc5.Write( addr, data );
# E+ T# s* C* Z3 v% C# r3 c9 F        }
1 m% s# c) O" C/ I/ \        if( exsound_select & 0x10 ) {
, ?7 n! ?( m) u% m3 P7 t, D  I                if( addr == 0x0000 ) {
1 Q1 Y; g$ @8 t( E2 z9 J                        BYTE        dummy = n106.Read( addr );! {1 @/ H. v& e9 s7 ~5 p
                } else {
$ k: r, I( e  X& X. t                        n106.Write( addr, data );
- g1 \+ B! B1 f9 P+ \                }
) y3 T. K: I1 c+ n/ a: F- v        }
3 j" L" j/ J2 ?* e5 g4 p6 G        if( exsound_select & 0x20 ) {% L4 s* G4 W, g/ S$ x( q4 e
                fme7.Write( addr, data );! A9 |4 s0 ?& k4 h
        }7 {( N! k# y+ u+ {/ @
}2 E  j8 @5 V+ L/ R  s
1 D! d. P1 W$ ]
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
5 _. `) v( r9 j8 K{' U# y+ ~  M" x% q. p% n
INT        nBits = Config.sound.nBits;
! u& f2 t* B9 I! G6 VDWORD        dwLength = dwSize / (nBits/8);
7 }; t+ S3 n+ Y& X# S; U8 NINT        output;- G$ O% M) n* v6 R3 y& i
QUEUEDATA q;8 z7 G1 D: V, |
DWORD        writetime;4 S' H* I3 t$ _' \7 ^/ v$ ]

% z3 e! I. j. x  A% QLPSHORT        pSoundBuf = m_SoundBuffer;( W$ f3 K  C- W" H' }9 J
INT        nCcount = 0;
" |* K6 }7 y% {2 D" B! p) i0 p% o$ v  i0 ~$ i7 [) ?
INT        nFilterType = Config.sound.nFilterType;
8 Z9 m" K1 x# d/ I1 x7 W9 ~% n% S* t7 r  n7 g3 B8 ^
        if( !Config.sound.bEnable ) {
5 ^; r0 Q3 X4 @( C                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
/ [9 A/ Q% o2 S1 S( l                return;
, ]- a3 p+ s% e, I$ G        }
; E. C$ s5 t+ {# k& g" |; a
; ^. l4 U: P. R; U8 I        // Volume setup
/ _) I1 O1 ]" j( o        //  0:Master
! x7 [; v8 D- r# W5 P        //  1:Rectangle 1
- c  |3 w( a, o3 W4 P- E1 d1 c        //  2:Rectangle 29 X7 U) v3 V/ H9 O+ ?
        //  3:Triangle
4 w' P" A3 d5 k1 ^1 l0 H( F        //  4:Noise
7 c' y6 W, ^  i0 ?, n- |        //  5:DPCM* e3 |9 k6 a' b4 y, T2 D) a% p
        //  6:VRC6
9 L0 G( @% F& a" w1 ^3 Q( M; j        //  7:VRC75 r% x5 f- J( b6 m; \1 X+ U& ^
        //  8:FDS4 \  o" g( P7 G" d# z/ x. X# F
        //  9:MMC5
; x+ ~( L: M8 a$ b2 c  n* m        // 10:N106
8 f. S; o# [8 M& M* f/ R0 M        // 11:FME7& n8 ?3 \2 G8 {9 E) \% X( c
        INT        vol[24];
; I0 I9 F0 d. @' ?7 f- _1 l- k. n        BOOL*        bMute = m_bMute;: s+ F3 E2 y9 }1 z6 \
        SHORT*        nVolume = Config.sound.nVolume;
% G" J; v8 q; g' {- y( M% s$ i) M" X2 |8 h1 h6 [  ?
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;$ ~- O2 H0 O7 @* [
8 n$ k- f# l9 A7 E1 z
        // Internal
& w/ \; C$ s0 V# d, P$ e3 p        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 c. v* _- e$ x- k1 o) B
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
" ^# z  @: m/ q$ S* E3 D8 v. F        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 n) b4 b% N* e( e7 N* \( T        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;3 c1 e, U+ S) q# {
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;0 k! H. M7 ]# j% s. j1 g

- [9 n; c# k8 _3 I" a* T9 ~        // VRC6% ~- A4 {' o" M6 l  H; n3 X: V4 n
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, c* E" I: l. V: ]        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) H8 [3 o/ ?3 U& b. S! k        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 t. V+ _, N1 ?( [( _0 W( n' i4 b4 ~
        // VRC7
  C/ {3 m: w# z3 _        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, l2 {+ T0 L6 l/ h+ k1 }3 W4 C  o
" V) ~( H9 m* R$ C        // FDS
/ m8 G9 x9 J6 f8 ]        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
( N* t9 p' g: V  Z) @
, I! k5 [; _) l4 q* v        // MMC5
3 C! L+ Q3 u" v6 q5 v. b2 [* l        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' m% `! J6 @" ~9 f$ i7 r' Q
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& o1 s" V/ U+ t
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 e& `8 r( v0 x/ V) {, T( F9 |6 `1 V4 Z# |! n2 a
        // N106
3 o, Q- P$ F$ Y- D- S9 t7 k7 I        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 h; J2 M8 S( h( C- g' V
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 l- d% K! r7 W# i  w; Q. X        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- ^: F* {8 G; T# Z# z2 ]4 d        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- a0 R  R% T9 d& U( w, z( @# D& q( d        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( D$ g# z! Z- p5 W        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( `$ U) \* L) p' A4 w, q& l1 L
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* [" T$ X3 j; G: w$ a8 s
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 a: g% B  \0 {% O
, u; g7 c1 x, o5 m* y
        // FME7; E. Y7 i5 K9 Y1 N  ?( f: y
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 G% i  a" W7 a7 L, W2 N) I
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! p1 g, a* b4 u+ a2 w
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. Y5 |% ?! N. k7 t" l* u
7 j6 C! W4 G: T# \2 F
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;/ \, g3 t. f. u9 U7 t, X3 E
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
+ K$ \" |2 O! {# t9 F" n8 s& o* ], F9 B7 i- ^7 ?: k% w' @% z4 b/ I( S
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 X+ T- I8 o  c1 @  U
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' h6 M$ d4 u4 u' s/ d0 i  B
                QueueFlush();
, Z' x) _  N% Q9 j; ?        }
8 h8 A6 n; \- v
2 O- R# b' U& P' e( n  @0 M. V        while( dwLength-- ) {, d+ E8 {7 B! f! c1 Y8 J  J
                writetime = (DWORD)elapsed_time;
4 L( P4 D8 ~$ e+ [$ @: G$ i
# z7 p, l, I/ O7 g7 X( s: ]6 @$ x4 E                while( GetQueue( writetime, q ) ) {
+ R6 {4 \/ E! ~  v: b3 {                        WriteProcess( q.addr, q.data );
, P# Y) N) c( g# g, a/ H  V                }5 C  O* c: P. U+ Y* j' e0 U. u% w- z
- I7 \2 [- t  ?0 z
                while( GetExQueue( writetime, q ) ) {
, r, W4 |) t1 H' @6 F                        WriteExProcess( q.addr, q.data );+ V- a) O! l) }0 G
                }
" K; _% p. s# T2 ^7 @7 b- Q: c6 p6 D6 k2 O/ b9 n8 ~4 m9 f
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ z3 K  }) F/ o
                output = 0;
3 l: C3 Z7 ]- K& ?                output += internal.Process( 0 )*vol[0];
9 k& q5 e% L1 ~! p                output += internal.Process( 1 )*vol[1];
5 Y: h% D$ r" L" `: z                output += internal.Process( 2 )*vol[2];. [8 b$ X8 R  \! Y5 ~
                output += internal.Process( 3 )*vol[3];
: x" C( G( T8 k8 _) f1 {' U3 R" D                output += internal.Process( 4 )*vol[4];
9 u4 ?; t* J) F1 c+ C4 z, B6 g7 `  Y! `6 f4 {
                if( exsound_select & 0x01 ) {
. a0 `; _* \5 }* \                        output += vrc6.Process( 0 )*vol[5];
3 D" V! d- ]/ K* U) V7 T8 j+ G2 ~9 h( {                        output += vrc6.Process( 1 )*vol[6];; U/ [% x! V5 h3 o3 T
                        output += vrc6.Process( 2 )*vol[7];/ M; P# k* B9 L0 P1 |! P
                }
  }2 r1 U/ M1 Y6 a3 G3 b( i* e5 H+ `' W                if( exsound_select & 0x02 ) {
( a/ U4 I4 F* m! H. {- C                        output += vrc7.Process( 0 )*vol[8];
8 d9 @5 X$ E% J, z  Z) ^- k) Y                }
0 C, Y- h- @2 \                if( exsound_select & 0x04 ) {
; g6 H4 U& c( l" ^( u2 P' c                        output += fds.Process( 0 )*vol[9];3 a$ e. D) M: V- Q8 E
                }
: G; ~2 S! P* T+ F3 I5 Y                if( exsound_select & 0x08 ) {2 t! ~, E* h2 i, W, E5 t  i
                        output += mmc5.Process( 0 )*vol[10];
- \/ L: U+ D) }  }) F! G                        output += mmc5.Process( 1 )*vol[11];
/ s3 E/ c) n; \% o                        output += mmc5.Process( 2 )*vol[12];
6 x9 v3 j" Y- }) E5 ~! C                }8 M, e  u! l1 }" ?; s
                if( exsound_select & 0x10 ) {' a+ a/ }  }+ N% `
                        output += n106.Process( 0 )*vol[13];
! K. X4 R. s6 Z8 X                        output += n106.Process( 1 )*vol[14];
2 p1 s6 R- t0 o2 T                        output += n106.Process( 2 )*vol[15];
! c, @0 k6 u- G% X, z( |                        output += n106.Process( 3 )*vol[16];1 r* }/ C# Q6 P
                        output += n106.Process( 4 )*vol[17];
. K- Z- t, `2 A* C. F                        output += n106.Process( 5 )*vol[18];
( b! t6 @9 C8 R) ^                        output += n106.Process( 6 )*vol[19];" A# o) V) m2 G- |* u5 s
                        output += n106.Process( 7 )*vol[20];
" H' `' c1 a4 w% D1 r8 a3 `5 D" h& k                }  Z* M1 ]4 f) A, ^+ f1 a
                if( exsound_select & 0x20 ) {7 m; \/ f0 a- Z( ]6 G6 e5 x/ u
                        fme7.Process( 3 );        // Envelope & Noise
5 W6 v# r3 k% k; S8 ^. U$ x9 n- L" t                        output += fme7.Process( 0 )*vol[21];0 F$ F/ B3 n3 ]) ~! c# b
                        output += fme7.Process( 1 )*vol[22];2 J' J8 J$ u( L
                        output += fme7.Process( 2 )*vol[23];+ F! g1 G7 S- k! @+ u$ {7 B
                }
( R6 L  `" f3 d3 {0 x( m* v3 ^# y* ~9 p* D- s) s' J
                output >>= 8;0 W( ]0 e9 z' I* K

/ R- L% i  X/ A4 a                if( nFilterType == 1 ) {6 l$ Z8 W# M7 u7 q2 I1 N
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)$ ]7 v; T; [9 p2 q
                        output = (lowpass_filter[0]+output)/2;
" \6 N3 t) g- x0 n* h                        lowpass_filter[0] = output;9 J. ]6 `- T& R4 y
                } else if( nFilterType == 2 ) {/ |2 D8 T0 z8 b" }
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
! r4 i) O( ?# h                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
; s+ ~4 E% _( i3 x                        lowpass_filter[1] = lowpass_filter[0];4 S& A! f3 N; d6 R+ X
                        lowpass_filter[0] = output;0 k6 z- U; S" B1 x
                } else if( nFilterType == 3 ) {
, R' m4 X% |0 W0 k" [. ?7 R, P                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
; c* B8 v/ t  s; W% |  q                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
* k, T4 t: _; I0 [4 f! j                        lowpass_filter[2] = lowpass_filter[1];
9 s5 |1 Z! Z$ M# U# i+ I8 D                        lowpass_filter[1] = lowpass_filter[0];5 t4 Y, ]: I: i( [7 u* a
                        lowpass_filter[0] = output;0 g- M+ X! z, ]
                } else if( nFilterType == 4 ) {1 j, q! d: o/ y
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
: c6 h0 \" }: E: B% `                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;% u$ X8 S. t& L2 r( T
                        lowpass_filter[1] = lowpass_filter[0];
/ @0 H& w7 H% R3 \! J                        lowpass_filter[0] = output;9 E3 Z# J; J3 p  J9 i( i. e1 \7 ?
                }
* p6 U4 _& `& G# b" _/ `6 z; [
* d% V7 [( l* j, ?$ p' F#if        0
, G( p/ D2 D- A1 I' u                // DC惉暘偺僇僢僩7 \6 {7 K$ N; Q9 I# \: R; S
                {# X0 D* Q8 [# f; X* K' I( V$ n
                static double ave = 0.0, max=0.0, min=0.0;3 e) d. `% r( ~; d7 E$ A) I
                double delta;3 t/ r  g) A& u' r- v0 g  p
                delta = (max-min)/32768.0;
4 \; E9 ?* S2 w4 w8 |7 ^                max -= delta;
! j6 U% M# q1 F4 V% U                min += delta;0 D+ r5 G4 p' f2 [
                if( output > max ) max = output;, K7 ?9 _5 k( p+ F/ q1 z
                if( output < min ) min = output;
' I8 q$ f" c8 g* |+ @; h, I2 f% w                ave -= ave/1024.0;
( I# }: M- X' U# \4 D0 t( h9 s) p# C                ave += (max+min)/2048.0;& E! |7 Z0 D: Q1 k% i' k
                output -= (INT)ave;, s* ^4 p: p* e0 w# `% j& h7 P
                }$ R7 F! G- \6 ]
#endif
+ X' `/ t7 ?: I% N8 X# j) ?#if        1
4 g2 L8 V0 L2 g+ M$ _                // DC惉暘偺僇僢僩(HPF TEST)' ]( a+ B0 ?' m6 i7 U& f
                {0 @  Q8 _0 R, J7 R* L. t* ?1 Q2 S: V
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 k/ [6 w* R7 A                static        double        cutofftemp = (2.0*3.141592653579*40.0);$ q! M& f, m0 \: P
                double        cutoff = cutofftemp/(double)Config.sound.nRate;0 O' \6 y- U% y3 s/ [
                static        double        tmp = 0.0;
) k" ?1 v& E  |9 J( s                double        in, out;9 j4 V2 W- k# V6 \- f5 ]3 A

- g- T0 w1 Y! X/ ?7 e1 w: J                in = (double)output;7 G' Q6 `# k5 U8 I% a+ F/ j
                out = (in - tmp);
/ H* R: W- {% N9 K                tmp = tmp + cutoff * out;5 P) G# B: _1 J7 b1 A8 `

5 x/ x+ B! Z" W( R' ]( r" j                output = (INT)out;# |4 R2 d9 @2 `7 n0 h
                }! J3 |1 o  Q8 \7 C
#endif" C! I( J+ B! a; [8 k
#if        0
6 m5 r3 H0 B1 @  |                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* o) V) U* k4 h$ Y. p
                {- ]- W. q2 P* I+ V) @$ T
                INT        diff = abs(output-last_data);
+ v) X/ o4 Y; ?( r) w                if( diff > 0x4000 ) {8 F' Q# j" W% B6 e
                        output /= 4;( J$ O& ~% E  F$ _. n
                } else ; Z8 s. y$ E# j9 S; H& ^
                if( diff > 0x3000 ) {6 H% e: ^7 n' Q$ E; V
                        output /= 3;! Y' |0 z# |3 }( ?* `- _! `
                } else
; {$ z+ p9 ^3 I' ?; i4 y                if( diff > 0x2000 ) {$ j- T9 Q9 E# j* z4 g
                        output /= 2;( ~; t" T: K: w2 ?
                }
0 M& V0 o( s) H9 Q. M; f% [                last_data = output;
$ Y1 f4 c# @. A                }
5 b( K. e( P: u- m+ |3 b; K#endif
! K0 q1 O% `' t; T: o2 X- T                // Limit
0 s/ a4 E. x- J2 b" M8 d: g                if( output > 0x7FFF ) {
# u1 m) E' T* D                        output = 0x7FFF;
! I" Z' o/ B0 {                } else if( output < -0x8000 ) {
, @  S2 f6 D: n# Y2 w! o6 P9 l& P                        output = -0x8000;( b( k- N( M6 \# S; Y5 |9 @5 ^) v
                }( n. v) e) J4 u+ Q  O

" B& f3 F5 H4 p' O. o5 M: @( ~                if( nBits != 8 ) {9 z+ E$ v4 B- F) T2 p
                        *(SHORT*)lpBuffer = (SHORT)output;
5 D& ~$ H3 B! o6 p- T$ V                        lpBuffer += sizeof(SHORT);6 `- z: G3 P5 A4 Y. s, w8 f
                } else {
- R5 W" C7 o+ S/ i                        *lpBuffer++ = (output>>8)^0x80;, A" V4 [; p$ u) K4 F
                }  i( Q. i" p% e3 S  {( ?

6 [$ p% f' ^5 I  P* n% k! s1 D                if( nCcount < 0x0100 )( ?9 a3 U3 `0 ?) d8 h  W1 M+ E, ?
                        pSoundBuf[nCcount++] = (SHORT)output;
1 r; s$ ^: u6 R* i
9 [/ C. ^+ Y+ I: _( Z//                elapsedtime += cycle_rate;
, a2 v0 U, v/ j6 {                elapsed_time += cycle_rate;
0 N, y3 `, m$ \" J, M2 L        }
( C+ ~6 `; ~, v
" ^; l! J3 Z- R1 ^# X6 Z" n& Z#if        1( E- Q: P) Z; n: z
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
2 r$ L! H1 a6 A" p" F4 P                elapsed_time = nes->cpu->GetTotalCycles();
, W/ y5 [# @1 G5 i3 T! t& ~. D        }6 F# X, H# @7 ?7 v" g$ d; R
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
8 a, n9 K0 q4 ^& q+ t& b- C                elapsed_time = nes->cpu->GetTotalCycles();
- s1 r% \% G- E0 ^        }
: W7 R# H0 ^- ^" J#else# a6 `! ^* t- Z( A2 c8 F  D
        elapsed_time = nes->cpu->GetTotalCycles();
  J8 {! e% s: W# y5 j#endif7 S: y$ F# D! U
}' N5 I$ w& q/ ?! u5 h* Y
' a' F4 j) G( A( Z! f% r1 F. `2 t: v
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)) @/ F5 E4 _5 R" v8 `/ w2 p+ l
INT        APU::GetChannelFrequency( INT no )
7 K1 f: a* p" q$ \8 @{
. v7 Z  O, J' D2 Y4 W2 F& j, A        if( !m_bMute[0] )) ?. x! j. n* D8 Z# K" O2 N. B
                return        0;2 J! N# Z9 b& c; [
) o: y) W; S/ b% J: F2 |
        // Internal
! Y7 j' N* E3 {3 {5 W0 H  z        if( no < 5 ) {+ i. D, K7 f; o
                return        m_bMute[no+1]?internal.GetFreq( no ):0;" N2 M8 d: Q4 P7 v2 X9 w( N: k
        }, k) c! c2 R7 F' u- V
        // VRC6" r: ?- ^& E: M! \5 I0 E
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {4 i' z# u) i; g4 U# ~7 `8 c. S
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;3 v* F5 o( ~  R& V3 P6 n
        }1 o5 V$ C5 ?6 m% o
        // FDS" E! ?, T. ]5 U. D% n
        if( (exsound_select & 0x04) && no == 0x300 ) {0 l4 k" A1 J( `" V, a8 t8 u1 f
                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 b' s3 K: p- i/ i( B6 A( W) K
        }: t4 M) N7 ]1 q& ^2 v
        // MMC5
  h1 z2 j! H7 r- ]% G+ Y        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
9 S+ D# [) }1 V( K& L" ~                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;, Y( L( ^& ~2 C, ?2 L- v
        }, B2 O: z& X! C' I" ?: y
        // N106
+ M. N/ }6 ?$ a# p% {" B        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {; [0 i1 a% q7 V5 |8 D' v
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; H# y, q7 F" p' m' b, }
        }0 u$ W. F4 Q7 p5 ~) @
        // FME7
3 t: s+ S3 X$ g: N! C        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 M' Q/ o8 ~  M1 D1 c# ?( c$ p                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, S( K' c3 _8 H) z5 u+ l6 K" J
        }! x; A, z+ l9 Z- N" U; P5 \( X
        // VRC78 X6 S/ B4 `# H" Y; k$ q: ^
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {, F6 ]7 E) l5 \- r9 U1 l& ~! R
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;. f2 P2 i+ Z4 @5 o2 t0 I' a
        }
4 A# Y/ U% l, m        return        0;" z. M9 E! l5 I' [) S- D( x
}
5 K1 Z( t" Q6 E% O0 `, @% J! J' t9 a3 d% |/ C& u
// State Save/Load* w( s$ O" F! `$ W0 }
void        APU::SaveState( LPBYTE p )2 a$ f% t% s$ L
{
: ~* q8 @" U% ?' @#ifdef        _DEBUG! ^% Q7 H/ }1 V. n+ S+ A: `
LPBYTE        pold = p;9 l* A# Y, o- a/ g
#endif
4 o5 v- f6 O- o+ P3 @* h  J* N; z- W
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞4 |- Y+ R: Z- l0 a$ Z
        QueueFlush();6 M. Z( u& p) H' G1 O0 Q1 e
% I2 I7 p5 v1 S7 |( c( }& l
        internal.SaveState( p );
/ E- c% D: {( _% U: a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' V' f7 m, h! o" ]; x+ `3 q: A( d; W
        // VRC6
$ l; N* X/ |: ]7 u* C7 c8 c: ]        if( exsound_select & 0x01 ) {
* c3 @+ Y+ J- }% H  J8 d/ q                vrc6.SaveState( p );
3 q, J  G+ d! k& T$ i                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" P' t3 U$ y' e( _+ E
        }% }$ z) h& y* a7 H3 \
        // VRC7 (not support)
$ k+ O2 C+ b- w, i. t        if( exsound_select & 0x02 ) {3 A; j3 k+ W1 \
                vrc7.SaveState( p );1 U5 D, J. b/ d1 Y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 c0 o8 j* j. W$ q4 Z
        }
2 ]/ n. d4 b7 N; f3 e8 [        // FDS/ `. v$ {8 {$ }  D9 Z# ^  G% s
        if( exsound_select & 0x04 ) {, w& f- L, z$ A' x! v
                fds.SaveState( p );
  Z3 P  ?/ r4 n. K                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 m2 H$ `, H; \# y
        }
! P% W" Y. k9 f5 u  T, W' k) P        // MMC5
; i, y+ Y. g" _; D2 }        if( exsound_select & 0x08 ) {
6 e2 W( u* p& {& c' {8 d8 c5 ?, m                mmc5.SaveState( p );! E4 Z+ n8 f& l
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  B. p, }# |; E  N" J
        }
- x6 f7 K% N2 c  z1 ~        // N106# X& w# V& ]% Z: t
        if( exsound_select & 0x10 ) {. O, Q# R( Q. j. Z! e$ h7 N
                n106.SaveState( p );
  J6 K+ ~" J4 W# a3 h1 S                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. e7 l  R8 r& W- q2 G+ [1 @
        }
/ F5 t/ P' N7 h& P( @$ B        // FME7
1 B' ~& H6 ]/ _/ u! R. r# W7 L  p        if( exsound_select & 0x20 ) {
# p# C9 L% \3 ?  r6 V3 M' X( X/ Z                fme7.SaveState( p );  G3 `4 _5 ]4 y. X% b6 w5 J( a8 F
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# F4 S$ d, t8 h5 z        }4 X9 I% B# \- Y. ?

( ^7 L2 G6 C0 \#ifdef        _DEBUG/ {* F- M7 p" l( j
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
8 [' F6 F, i1 q' ]) n& j#endif" w2 L2 `/ \" d% V! \- J
}6 x/ W& o) n7 Y% [5 y# u6 c

, i& b2 V5 y6 R2 W2 |2 l8 cvoid        APU::LoadState( LPBYTE p )
9 H6 B- D- p- z' D; I7 X{; T  U# W0 G' }5 @* n/ w
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
, Z5 L* t/ R+ {) W) n1 J2 R        QueueClear();
; Y3 i# j! P% O/ U7 ^
6 W' D, ?2 W, N        internal.LoadState( p );$ ~0 m. h* D; i) M" u; S# m
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 q1 V+ ~. b& l; U, j0 m7 _; o9 ~" e: K% x
        // VRC6
  f3 p+ m9 h: n* L        if( exsound_select & 0x01 ) {! Z, I' B0 n" [. V) x, J( X- x
                vrc6.LoadState( p );
% j+ x: N& ]1 S4 Y$ ?) K! D                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: l) }* |2 P# m* d; n" \# J
        }  c% A" l/ \  ?# O  U5 D; q
        // VRC7 (not support)  x4 r- t5 o3 H* p  f
        if( exsound_select & 0x02 ) {4 h+ }3 i1 Y# ?. K
                vrc7.LoadState( p );: t3 z: e/ G- H2 {7 S9 f& ^: m
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ T# ?) t) u! }% X, A) }0 H  X        }0 i( X6 g0 S( W  u7 M' e
        // FDS& C* \! {- i# N% s) [; a
        if( exsound_select & 0x04 ) {
0 S: A. H% N9 c( d( _                fds.LoadState( p );  d* m0 w- ^* ^
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ T, d, J% y) m        }* W' {, P/ R* w4 y  D8 E7 t
        // MMC5
8 Q9 Y4 `$ @8 u, A        if( exsound_select & 0x08 ) {
# }( J5 {2 i  g+ U                mmc5.LoadState( p );
  n5 B5 n$ j; f% [$ n                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 T) W, V" M, t" y2 F2 ~9 J" h
        }
; r& v$ ]; K7 h5 N1 j- f        // N106; {) K. q  t$ V, @' m
        if( exsound_select & 0x10 ) {6 E/ g+ `, d1 O5 l0 c2 S
                n106.LoadState( p );
/ f. q) f/ [9 G  x                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* q9 g* i+ H2 g, P% ^7 Q  `        }
. y1 Q. `; |& E8 r4 a        // FME7- ]1 g. _% L; L: j7 G
        if( exsound_select & 0x20 ) {
+ i% R9 J7 V& I2 {% z                fme7.LoadState( p );
& ~8 _. }( _. D) ]# t                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ J% N, f2 B( N9 \9 ^, y
        }
* S' k! J7 O+ g5 N" P  f* V$ p* K}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 7 q% M+ u% n+ J7 v; |7 n2 e
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。6 L# N+ \0 M5 S8 \; m& n
感激不尽~~

. L' Z( _' Q! q( k  K9 H恩 我對模擬器不是很有研究,
' D) d) X( d0 F- D4 E3 p6 Z雖然要了解源碼內容,可能不是很困難,! Q9 W) ^, M: ?1 h, A3 A8 ^
不過還是要花時間,個人目前蠻忙碌的。  s$ l9 P+ W+ K/ |7 X/ \! x

7 p% M! p& w6 [給你一個朋友的MSN,你可以跟他討論看看,
  F6 w( \: N( @9 Q8 L2 n他本身是程式設計師,也對FC模擬器很有興趣。
, o- \( D$ T- l# u4 S+ J
0 y6 ?* Y6 _- L- P: _% e" NMSN我就PM到你的信箱了。
! Z, J. F0 I- J( s
+ M- _5 {3 V6 N/ U; C6 l$ N! b希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 2 `* U" f& Z: e# b
呵…… 谢过团长大人~~
; |2 `2 q7 r$ a# C0 q7 e0 E

* e$ t& d* {7 }5 g哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
! e( K! p# I9 H) i; s( ~0 t' a团长的朋友都是神,那团长就是神的boss。
. m, w; g" b: e1 b' ?! E
哈 不敢當,我只是個平凡人,5 ^' p( g" |* z% U+ y! i) T7 @
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙4 o: x/ l4 `# y; `" o, r0 M! y( i
ZYH
# d: t$ i5 f5 U) X+ OQQ:414734306; @; H& j5 e# ?( v4 E) ~$ `
Mail:zyh-01@126.com
4 d  c* R( z# ~; r& Z) R2 S6 I! k3 P/ l( `6 b0 \
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! ]2 I$ V/ p' A: T再次对团长大人和悠悠哥的无私帮助表示感谢~~

, }0 T' M; m( G9 W- F4 y+ v不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-26 02:47 , Processed in 1.095703 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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