EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ X- V1 w: x' j$ G% u7 q2 e
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
/ J6 P; Y- m, M8 W/ C这里有相应的模拟器源码,就当送给大侠了~~5 S/ f) l; @! I: o5 w; t# V
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( U. q3 e+ a8 k% m  u8 x( B能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 ?' f! z3 \7 C' C. @) E
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, D9 Y1 s3 F1 P5 _: n这里有相应的模拟器源码,就当送给大侠 ...

( ?' ?+ q2 K8 y( i聲音部分(Audoi Process Unit = APU):
( m, Q( {6 @, G& L5 f! d( U" I.\NES\APU.cpp- W/ V3 \" q8 P  w
.\NES\APU.h
( |# q% E& v9 o- u) L; p# v+ x' X) Z4 p7 j( M
% l* `: i# E# @% Y! p
影像處理部份(Picture Processing Unit = PPU):
' m; P5 y- F* G. {! @.\NES\PPU.cpp! o8 ~, j9 A6 e; d! p3 v
.\NES\PPU.h" W) N, y) R' B% @* n" s
$ O7 h$ G' }4 w0 T: n
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
' T2 V  J! [7 d! y0 a  p) J  ~(由于很多专用术语和算法机理都不明白,所以看不大懂……)
1 S9 M' Y" E7 u6 G9 M. w, F//////////////////////////////////////////////////////////////////////////: ^3 v0 _) ]5 b8 W' s. e& w
//                                                                      //0 H' y& B! j. U. }
//      NES APU core                                                    //& `: u+ G/ v7 y5 x4 A
//                                                           Norix      //
! ~$ k8 G* G. P7 e; l6 y//                                               written     2002/06/27 //& E* e  |: k! S' c/ D- R
//                                               last modify ----/--/-- //1 l/ N. }% _- u# [( M
//////////////////////////////////////////////////////////////////////////
# M" t6 r. f1 ?* s* V. B#include "DebugOut.h"
( ~& s- D* }/ R#include "App.h"
+ W9 y- z- _% h! O; T7 ~( E: Y: N#include "Config.h"1 q: m5 H4 f, G: ~

# R# w* U5 @8 g" t1 T$ o, ?#include "nes.h"$ o' Y/ ~5 K8 j# Z) r% u* e! |
#include "mmu.h"2 Y: K' d6 _7 R: Q5 j" [# I
#include "cpu.h"  O) X3 o5 A( h/ y4 Y8 S! t
#include "ppu.h"
2 z9 t! [. ~+ U+ M( a' l" ~/ e#include "rom.h"
+ Z$ [. F% d2 i6 V' |9 u+ d#include "apu.h"
. ~0 l  b6 O& \2 P6 K; ]# i( W
- n" s2 G  R1 m% a# O// Volume adjust, U% S  [2 E; R( w6 V
// Internal sounds2 A5 ~* R4 n1 |* T) j
#define        RECTANGLE_VOL        (0x0F0)
, P! Q- M1 a0 A#define        TRIANGLE_VOL        (0x130)
9 }* M6 {6 A' P; i) n4 }, |#define        NOISE_VOL        (0x0C0)
  J( s! d3 `+ _#define        DPCM_VOL        (0x0F0)
6 f% A9 ^! [3 S% j0 Z8 C// Extra sounds( |& ]* z8 G/ Y% L9 F
#define        VRC6_VOL        (0x0F0): v0 S6 i" U: |& L
#define        VRC7_VOL        (0x130)
3 \. T& u: R: c! h% \#define        FDS_VOL                (0x0F0)
1 G: @, j0 C/ H* M#define        MMC5_VOL        (0x0F0)9 m" x# V" O7 o3 h  ~" `% W; P9 j6 @
#define        N106_VOL        (0x088)
4 c$ q/ {, n; P5 ~3 f, ]3 _#define        FME7_VOL        (0x130)
* G, D4 y8 z9 e( L& i2 t! h5 v! R
APU::APU( NES* parent )( l4 o% r' `5 j! U0 m* c
{8 G2 q2 U1 S' f0 z( m9 W1 ]5 k
        exsound_select = 0;
$ G8 j9 o3 c% d$ H4 H  k8 u. x% ]" B
        nes = parent;
, l4 t0 R6 v" w" G/ F        internal.SetParent( parent );" W) X0 ~6 u1 F9 [! @+ u

4 z' T, T( Y* Q. e: s: ~        last_data = last_diff = 0;
1 F6 R1 V  a1 b8 w9 W% K! |+ e' P+ m
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );4 K: m1 v) a, L; X6 Z
" A. A; z5 B8 I" i2 _9 Y# k
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
( i! O' x) S) L* u        ZEROMEMORY( &queue, sizeof(queue) );5 D1 I0 Z4 Z: N& {1 d* @( v
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# S, N4 o( x; T- C& ^* c/ r
  L: T$ ?" Y$ }0 D9 ]        for( INT i = 0; i < 16; i++ ) {( N( ?- x  e+ x5 c+ o9 s2 A2 X
                m_bMute = TRUE;
, ]3 C0 K; b% s        }% p7 g7 x" E6 M% I5 H
}
7 `3 i9 ^% Q& }# c/ ~/ O* x4 k1 y5 s6 }, I: w; ]6 d
APU::~APU()5 a5 U7 a- g' F6 u. y* A8 g# i
{
  a% u; g; s0 j6 h0 h}  M. @" w# F8 y1 i' S8 u
) w9 r5 ^6 ?3 e3 D
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
$ [. j2 a5 b. E, ^) P{2 B$ B4 K9 [9 V1 T: |+ X/ A
        queue.data[queue.wrptr].time = writetime;
4 H1 z! X+ B+ H        queue.data[queue.wrptr].addr = addr;
4 V  w* r( H7 v- H6 Z/ b        queue.data[queue.wrptr].data = data;
- k8 P7 j+ D) i" w        queue.wrptr++;
' H9 u9 t3 U0 F( T  l2 @  Q& |9 M        queue.wrptr&=QUEUE_LENGTH-1;
) A% A; J% q( ], \& M7 T        if( queue.wrptr == queue.rdptr ) {, H5 g8 [7 u* S% [: D: u
                DEBUGOUT( "queue overflow.\n" );/ V, F+ Y* O0 @6 x% ~3 ?0 Y% x/ L
        }
' l, _" U; P) z) K  }! M}+ M/ i5 F! m" g  z* Z

: h' O4 V' ?$ hBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  Q2 K$ w4 d, G+ u8 c{' Q% ^2 ]: D/ U
        if( queue.wrptr == queue.rdptr ) {7 P3 n6 G( U3 t9 c% f# h0 V
                return        FALSE;, e/ m  y: a7 B- o- ~, J
        }  h  `* w) q$ l& [% [' j
        if( queue.data[queue.rdptr].time <= writetime ) {$ X! Y7 O2 R+ `, T8 H
                ret = queue.data[queue.rdptr];4 f+ L9 [, k7 `# y( Q. }
                queue.rdptr++;+ E' Q; u" @% ^# k8 N! u# o( c
                queue.rdptr&=QUEUE_LENGTH-1;
6 c) F) ^2 J: f2 Y                return        TRUE;
& d) i; S9 {4 ?$ v$ R        }
5 Z) e; H( w  A2 p7 V        return        FALSE;
& S5 }# o9 v7 ^9 ~5 R}: U2 S5 }: T9 t: Q# k
# T! V  g7 ^2 [$ R- f6 |
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )! d' h* B0 Z/ k4 Q( z$ G. M
{: D/ j7 `( z- j1 Z2 f
        exqueue.data[exqueue.wrptr].time = writetime;
% g5 D* h1 ?0 S! Y2 j) u# ]+ X% I# i        exqueue.data[exqueue.wrptr].addr = addr;
$ T- g& |; _2 V. E) L$ s        exqueue.data[exqueue.wrptr].data = data;% `1 U% O  E' l5 V' R# a% p
        exqueue.wrptr++;
: ~! @6 i" [/ C, R+ V        exqueue.wrptr&=QUEUE_LENGTH-1;+ k4 ^" a$ o1 c/ {6 F: D8 |& h& c
        if( exqueue.wrptr == exqueue.rdptr ) {
1 N. l' C5 _2 I% y8 {                DEBUGOUT( "exqueue overflow.\n" );7 w/ w4 A1 k/ s2 e( m* |8 I  Q, c
        }
, u7 V+ b$ a+ Q4 j) z}
/ n" I6 ^, ]4 J% r6 M3 e8 L# D$ n: n) S  E8 |2 A
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  d! U5 W& _$ u5 U; f* Y& I
{  ]0 _2 x( w6 d6 Q9 B6 ^, e& {# t
        if( exqueue.wrptr == exqueue.rdptr ) {$ G* ^& [" G; ^8 _
                return        FALSE;
  G0 B* A* D/ u. v  c3 X7 T        }
  ~! m$ j! N( ^5 W: q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
( U0 h9 I* O8 k6 g5 q                ret = exqueue.data[exqueue.rdptr];
! `" O- d" s! N9 |4 r                exqueue.rdptr++;3 q' ^' d, ]* D5 J2 M
                exqueue.rdptr&=QUEUE_LENGTH-1;9 H* ?# w4 y1 B* \: A; b
                return        TRUE;! f. C; K- V( `, J9 w8 y/ {0 Z
        }
# n9 {5 X3 j. ~( @) g6 r        return        FALSE;
) s* C6 V1 z* |% v) P}2 f% P7 y* V, ~+ z) y) y6 v
& r7 p. s7 Z! y, }$ W" b
void        APU::QueueClear()8 ^5 T+ v+ s% ]. J7 L
{7 g& H$ Z8 i7 N! E/ k5 U
        ZEROMEMORY( &queue, sizeof(queue) );
, g' x5 z1 n2 T& e7 Z        ZEROMEMORY( &exqueue, sizeof(exqueue) );" I6 f8 M/ q- V( W( ?8 a1 z2 I; K& L, w
}* q6 ^) d* d6 l7 q
( P2 n5 R& s1 E
void        APU::QueueFlush()7 [) p3 i# X; \! \! o# {
{
+ s/ `- l# C- ?        while( queue.wrptr != queue.rdptr ) {
9 H1 ^5 V9 _. ^$ \5 ]% X                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );, M2 G0 ]$ F8 T# j
                queue.rdptr++;
" w4 j. f# R9 B# r6 R9 m                queue.rdptr&=QUEUE_LENGTH-1;8 b$ z" V! {' x6 }, r5 W, A! [- W7 C
        }! `: a5 i' S4 n' r- @
$ c& v4 a# G' Q6 U. Q# `
        while( exqueue.wrptr != exqueue.rdptr ) {
- u. u; }' F9 k( B- V                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 h, E6 [# R* l+ i  R
                exqueue.rdptr++;5 x0 v* P8 ?* \1 v! j3 m
                exqueue.rdptr&=QUEUE_LENGTH-1;( z& n, A7 c' z
        }. r2 K' G" l5 X1 ~; I+ `8 g0 J# H
}
& S8 ]5 |0 q5 R  d( B$ G3 r$ F# l8 w" T/ K0 d7 a7 I3 o$ S
void        APU::SoundSetup()" x! Y+ N5 H0 V; {
{
, [3 p* I  f# x# t6 K) o% x- {        FLOAT        fClock = nes->nescfg->CpuClock;
- c; w3 G: [8 k) D9 w        INT        nRate = (INT)Config.sound.nRate;
' l$ G: k' P, W        internal.Setup( fClock, nRate );9 P2 F" @; K& `: ?7 V, o
        vrc6.Setup( fClock, nRate );, V& C* q$ V$ W
        vrc7.Setup( fClock, nRate );
+ ?" @) I7 [  m2 [: i        mmc5.Setup( fClock, nRate );
2 b& k3 [5 T% N, R        fds.Setup ( fClock, nRate );, c4 b6 I4 Q5 ^% R
        n106.Setup( fClock, nRate );' V+ I' S: G, _) J" H7 U3 l/ ^
        fme7.Setup( fClock, nRate );
' U, x/ z) ~; ]}
& R" D5 `# V4 i6 Y. e5 w
5 @9 V6 o, s  W6 L3 f& T& Evoid        APU::Reset()1 @  u' G9 a/ z
{
) P% j' p" @; W# m% s3 z+ W        ZEROMEMORY( &queue, sizeof(queue) );' ?+ l5 _; o5 H% _8 m! t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 U# V+ Z# x: i
) Q. L  |, H* H" L
        elapsed_time = 0;
: A2 Z; s1 Y. N$ B
- r! y/ w# o8 O1 k% X$ o        FLOAT        fClock = nes->nescfg->CpuClock;
: ^' s; k" ~6 F- ]  N        INT        nRate = (INT)Config.sound.nRate;/ z+ U2 F- Z3 |2 i' P# i
        internal.Reset( fClock, nRate );6 p. f  e% L4 I- N4 z! R
        vrc6.Reset( fClock, nRate );2 ]% d" [% N: z2 F
        vrc7.Reset( fClock, nRate );
" Z  I6 n4 T6 O- |        mmc5.Reset( fClock, nRate );7 L/ k; H2 s! J( N/ e. u9 M7 B
        fds.Reset ( fClock, nRate );/ u" |1 b3 o+ q2 N& n  B3 k; s
        n106.Reset( fClock, nRate );  T2 s9 S4 T7 o7 {
        fme7.Reset( fClock, nRate );
% x  P, P2 f- d2 Z& l$ E, J! F+ M" S0 l' h* p3 ?3 n  Y9 d- U
        SoundSetup();
! V2 F4 r" o7 O; y9 q7 \}
1 o; d% W5 i3 v. O* t+ v
- x" z! H; U3 m% N, R9 @; Yvoid        APU::SelectExSound( BYTE data )9 }- F( r6 g- k" a  }& O; [7 Q
{$ E1 l5 |* N2 e0 i3 r
        exsound_select = data;
! E( c" u! Z- R7 i7 y. U0 {+ M}
4 j% x; k7 ~+ F% E
% ^6 o0 j  K! h# h4 ^BYTE        APU::Read( WORD addr )
* S8 S" h, J3 y9 s{8 |) F- E5 ?3 ~6 W4 ?% o2 Q
        return        internal.SyncRead( addr );6 R2 R/ u6 f/ Q" A
}
4 h& [2 @) U; ^
  Q+ ^9 o  Q5 a# \. b+ Ovoid        APU::Write( WORD addr, BYTE data )
. T7 D. Y% i$ v! K; I) Y{
' d' D9 ^% Y8 a5 F" c( L& e7 G        // $4018偼VirtuaNES屌桳億乕僩
: L7 @, z1 D9 y7 j4 I- h        if( addr >= 0x4000 && addr <= 0x401F ) {
) x! R* f4 U  }8 n                internal.SyncWrite( addr, data );$ c% g# X' I% B) Z; m
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 v  g- ~$ [- ~
        }
9 a$ i, ~0 S+ B* Y/ B}
9 T5 H& @" H! z* B; i; R7 e3 J
! [2 z6 h. d6 K; E! k6 X* fBYTE        APU::ExRead( WORD addr )3 j" w. a1 L/ V. o
{
( D! v( l+ m! }* v1 QBYTE        data = 0;
) S/ D/ [1 \3 E# x
/ Z" S, Z6 X* T; w        if( exsound_select & 0x10 ) {
" A  \; z/ B- H2 O  n2 U                if( addr == 0x4800 ) {3 S! y  k* a& ~& |" ?; n
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );/ n  V( Z4 f1 n" A+ v
                }9 ]' P" j4 w* e) T7 f8 F7 k
        }
# {+ c" _. p7 m1 F, v8 a' D        if( exsound_select & 0x04 ) {
5 z# [  s8 m; v6 z, u' Z4 U                if( addr >= 0x4040 && addr < 0x4100 ) {
( g3 K( m4 \5 w1 d5 f8 O9 G                        data = fds.SyncRead( addr );
3 g2 |+ O  @" g8 R                }
! v0 s, a% |* a# i) W5 `        }
, k/ n3 \! u7 J5 S& {7 {) m        if( exsound_select & 0x08 ) {4 ?/ M# m. Y, R1 j
                if( addr >= 0x5000 && addr <= 0x5015 ) {
* }$ |- X+ g% u' \8 S/ D3 A                        data = mmc5.SyncRead( addr );
/ `7 x6 K/ \# y6 d                }
* r$ h2 T! G8 L8 N        }% k2 `3 f: Y, O, o0 |- \
- M( ]3 x; }0 M
        return        data;
' O( {  U% F# I/ b9 P" ^) w}
* d6 V) ?, R1 l) _+ ]: p2 x
8 m( p# M# Y4 ^% _) v; x' w1 q6 G* Ivoid        APU::ExWrite( WORD addr, BYTE data )
2 i; ^% {, P/ O, F% h: e9 S{5 X* K8 H  ]1 d2 C9 }, b! R1 x. @
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( B9 D( U" d$ u" g7 J
% O, H3 @1 O3 L" l7 L3 ^        if( exsound_select & 0x04 ) {
! p3 e, `  o1 K/ i- @2 u                if( addr >= 0x4040 && addr < 0x4100 ) {
2 g2 d3 C4 |+ a4 r0 W                        fds.SyncWrite( addr, data );9 ]2 z1 f7 i. m. M
                }
9 u& o* a2 U' e' Z" i$ e5 d        }
' D3 A& N& p, U) H7 n: ]. Z7 l+ n2 ^# V- m! P# E, i( O# r
        if( exsound_select & 0x08 ) {6 W# Y  q9 B: s
                if( addr >= 0x5000 && addr <= 0x5015 ) {
9 t; J- M% [' a+ z6 c9 t                        mmc5.SyncWrite( addr, data );
+ n6 ~, Z4 A* h: W                }4 h! e5 B# M4 B/ ^
        }
* v, h. k# N3 z5 h6 c* m}) W1 i4 k" V9 m7 H& T$ B! e
% T+ [: P& x2 @+ X/ F- p$ G
void        APU::Sync()9 e- j* |( E. t  t6 M
{- d# v1 m5 y: J1 L" z
}
+ S3 p. {, j4 z& t
7 @0 A! T. L, e1 M8 Gvoid        APU::SyncDPCM( INT cycles )& a% ^# N4 Q8 E, m
{
7 ~  F; ^5 d: g3 @; s        internal.Sync( cycles );
7 Q- ?/ ^1 v& g$ b0 V
' D7 x/ `9 U5 Q) `0 b0 b        if( exsound_select & 0x04 ) {
8 \$ J& T: {0 |                fds.Sync( cycles );$ u9 {8 @* E+ n, l/ P
        }
/ G0 I' \! s5 `5 o        if( exsound_select & 0x08 ) {
! F, d5 [$ q) L7 V) p                mmc5.Sync( cycles );
, W$ H' P; p/ |5 J4 C) @        }* ]0 Y5 a/ @2 q) h( V% l6 [3 _
}" Y7 ^" u$ d* Q
+ H* u2 M8 {8 N& h3 v; m
void        APU::WriteProcess( WORD addr, BYTE data )
3 T" P; O9 ]$ I0 q& s: Z, G{" v  A( n; |. u' c
        // $4018偼VirtuaNES屌桳億乕僩
) j) z) m# `  ~, P: o2 B0 q        if( addr >= 0x4000 && addr <= 0x401F ) {
+ C/ C$ M) N. E! I- _3 f7 S                internal.Write( addr, data );
$ G4 w% p1 o7 g9 E' A4 _' X        }7 S; o1 z: L, ~1 n5 v1 h# M4 ]; I
}3 b# {7 {+ D8 h% u% P9 H

+ Q. L3 s: I5 {* lvoid        APU::WriteExProcess( WORD addr, BYTE data )
* S6 v( V8 w* u$ s; g{7 @0 p3 |! r+ ^- S: i
        if( exsound_select & 0x01 ) {
. H: ~0 A" ^1 Y% Y- h2 y                vrc6.Write( addr, data );+ v4 h# k8 |; J7 u
        }3 l/ T1 ]. B0 T, P" X. K% x3 a
        if( exsound_select & 0x02 ) {
1 x* w- p2 n. S* T& c                vrc7.Write( addr, data );% x8 M$ \1 F/ k: a( `  Q1 r4 ~
        }
1 j, i% u7 e* ?6 f! b/ X        if( exsound_select & 0x04 ) {2 v/ v% j% T2 w& i' |7 J
                fds.Write( addr, data );. a; f6 h5 N( C2 @( F# j% k
        }
+ n* M0 e' l$ H- d        if( exsound_select & 0x08 ) {6 u; L1 Y% I4 j0 k, N  w& v; }1 Z
                mmc5.Write( addr, data );
) ?! ?4 f2 \! G8 h5 z        }
# h! }. `5 I- H9 q        if( exsound_select & 0x10 ) {
; h# Y% Z& V5 d                if( addr == 0x0000 ) {' B% ^5 c- |1 Y  d, @" b' S1 B4 M
                        BYTE        dummy = n106.Read( addr );6 ?! e, [6 O3 V  S
                } else {) f6 R* l6 o" |5 a; n: G0 v# L+ g' ?: J
                        n106.Write( addr, data );' P! S, Q" H, R: c  z" s
                }" g2 U9 z5 x5 j! x3 y
        }
/ k4 X6 q( c, L# y        if( exsound_select & 0x20 ) {
9 C* i4 @* C% W% B! s                fme7.Write( addr, data );
! r! Q5 c+ S+ g9 X8 |        }' `- D8 \% T1 m$ s1 `& K$ s
}
/ o0 V/ s6 b) }+ |% X0 e4 ]! i+ }4 A0 |2 N! y- |
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )- C9 f9 u2 k4 t: Y, U% _
{, F% D; ?6 W: K/ J+ }$ B
INT        nBits = Config.sound.nBits;/ f  X# i- C) u; x& ]
DWORD        dwLength = dwSize / (nBits/8);
* [+ w7 Q+ b5 C: a; DINT        output;+ E. J5 x0 I9 j! e, s
QUEUEDATA q;
  Q& W, ]* }2 q% @! l/ iDWORD        writetime;
: i+ M" \- }( \7 h8 C& N5 H* u! u+ M) l3 c; f
LPSHORT        pSoundBuf = m_SoundBuffer;
6 q& ?6 T2 x9 |* k% `" s0 BINT        nCcount = 0;2 S! T, f4 H' f, K. c
) J! d- _  U+ L0 W1 P4 X1 F7 E
INT        nFilterType = Config.sound.nFilterType;9 i- U" H  I0 m

* n6 l) @+ p! J% h+ w* }        if( !Config.sound.bEnable ) {
' S- e2 ?! T8 F* e! T* O+ d                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
! T3 K0 K. @( u% N                return;
9 J: ], C6 y/ D+ i        }& l! q: c* k5 g6 I

" P8 u* k3 q' h" k        // Volume setup
+ k% C$ _9 L% w. i% B9 i( n        //  0:Master# e$ \! S$ x* [( |$ ]% W: T
        //  1:Rectangle 1
* Z: i& y9 `: \9 m        //  2:Rectangle 2  T8 _/ Q& M; I7 m' Y# n& ~
        //  3:Triangle
% u3 J/ t  S! ^8 j& B        //  4:Noise2 d! G; N4 T# j; G2 _4 q
        //  5:DPCM, v# D/ J2 I1 e) O
        //  6:VRC6. c' X0 ~- i6 }! v" K/ r, R
        //  7:VRC7
( p5 b. q' z5 c9 I* p1 @        //  8:FDS! r0 l3 o4 D, I- G0 j
        //  9:MMC5
, u9 A3 @- B+ }2 H; R, d        // 10:N1063 w. J, @% l# O6 w  s% a) R5 r
        // 11:FME7- ~  w0 M8 b' H% e' `( V) ^; q
        INT        vol[24];  S4 N& {2 {/ ]( D& O- @
        BOOL*        bMute = m_bMute;
' ^0 |6 _, Z+ h        SHORT*        nVolume = Config.sound.nVolume;
8 n2 |5 e% }3 z! Z
" z" V8 v) a+ {* L5 l4 P9 G        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
1 W8 r5 B4 [& b0 [$ E5 H
2 T7 K0 r/ C) `4 t3 Q: r        // Internal
# H! N7 e8 t% B5 y' q        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
+ G% ^) N: z; X% W. l' }        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;. i! t+ E" g# r. X1 Z; m+ R
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
) T& G, J  `+ P) T$ r# {  _        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: ~: r: o6 F6 M0 t: X; M        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& X/ h% r/ e1 v" q7 z) L8 P3 X
2 w+ |: G, E( L: q( {4 k8 T        // VRC6
: e( I7 y% H) p4 C7 B        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ p) k) c9 ~" d        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 i9 @" B2 O# _
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' q9 j0 y. j! Q! r/ d/ b1 H6 ?% L0 l
        // VRC7
+ `$ {4 c+ G* |7 Z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( @5 e2 g& G. g/ V0 p

; x7 N5 n$ ]  f( L1 G) q        // FDS! Y; ?9 g7 `4 Z$ @5 |
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;9 W6 }. V+ g: ^

2 }; B/ Z/ M& |6 w' s( ^3 J% d        // MMC5
; q; t: |& V9 r" W        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, a. S- u4 b7 U; V+ j/ i7 z) q6 ^        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 y/ {) q4 d0 y9 s/ P        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# ~6 U1 @% [, i$ z

$ o% q" Y. }: J: J        // N106
2 f% Z4 m% o. O+ P4 `1 u: I        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 t) d( z' I! [7 _, P
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* Q& R% _! Q, n- P5 O) F( p        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ ]3 T+ {8 W& g0 p        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& _: A1 i1 m6 P6 h        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 D+ f1 p% R" \, P* A& n3 G; Y        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% S" ^6 Z9 d: d$ T% a+ {
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' _( f9 Q+ v  M$ f% F3 J        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ w% n! C# Z: l* C9 L- E8 F! J' G6 ^& G# [: m0 p- c
        // FME7
: w+ l) G# h6 |, z7 K/ A" T( \        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 M8 J: z* a5 e+ N9 N' d9 A& D        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 {  l3 Y3 m3 v$ t* f1 X        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  t) m3 R9 F% F5 T1 C! t

. n1 E$ [' J8 k; q5 v. |/ P  |7 l) @//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
3 M7 Q6 O* z  S" b. ?6 N  M" S        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;6 L. m/ `* \/ h2 {- b# F; d

* @, \* p; e6 Q4 O1 ]1 s; [& S        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟) B% X6 j2 @& V! ?! @
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {* G' {8 ^" g( O/ {
                QueueFlush();4 E2 x+ h: ?* g4 J9 A! w  X
        }! x1 ~( `* H  s# C$ v

& a0 M( \# C, N. M3 }        while( dwLength-- ) {
4 W2 O: g" B- X                writetime = (DWORD)elapsed_time;( _' k: G' Y$ o( O) K6 Z. r
) B2 B8 \8 Z; G3 V$ C
                while( GetQueue( writetime, q ) ) {
1 p) Z9 b" I  i7 f$ K                        WriteProcess( q.addr, q.data );
5 i+ j0 S1 G% l6 d  r% P# p& ~                }
' q) ~" o0 ]# J) ^2 }0 _8 t4 r( P! F1 v$ V
                while( GetExQueue( writetime, q ) ) {3 c8 j/ J+ E! {2 D
                        WriteExProcess( q.addr, q.data );5 [: {) P4 T$ M( ^( L
                }
, ]* x4 }$ V, A( U( m% N
7 S, V* z9 L6 `: b) _                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7- p( {& \' @$ V. r& O% y
                output = 0;2 X, c$ b  p7 s* B) {: O
                output += internal.Process( 0 )*vol[0];0 b0 y3 c6 T4 i( w
                output += internal.Process( 1 )*vol[1];5 M) i, o7 }: p/ @* M) h8 f+ I
                output += internal.Process( 2 )*vol[2];: [! K/ E  r' ]3 Z- ^/ s6 r9 J
                output += internal.Process( 3 )*vol[3];
" r) i9 \, G; K1 S8 t# t                output += internal.Process( 4 )*vol[4];
. J5 g# U2 `9 K! }0 q" V6 B3 q( `/ D
                if( exsound_select & 0x01 ) {
1 _) p: T8 k* c& H8 i                        output += vrc6.Process( 0 )*vol[5];
2 C1 @- T8 g% S2 K' f8 |' x; G                        output += vrc6.Process( 1 )*vol[6];9 q7 a; l7 g2 d5 S
                        output += vrc6.Process( 2 )*vol[7];' u  u  D1 ]2 M! `
                }! a5 V. |" x! q! ^3 C8 d' L0 S2 w" [
                if( exsound_select & 0x02 ) {6 L8 c/ M  k1 T4 N0 a9 ~/ L
                        output += vrc7.Process( 0 )*vol[8];
9 K  W7 Z& b( W* e0 c/ ]3 c& S" W+ T                }4 E$ x/ F% l' S" h! r3 C
                if( exsound_select & 0x04 ) {8 a2 J, R! F3 k6 p
                        output += fds.Process( 0 )*vol[9];  G0 a! F/ O5 o  j
                }, t  D0 M  V6 p7 p, c
                if( exsound_select & 0x08 ) {
, S1 k9 Q' ^7 t, Y1 a# V                        output += mmc5.Process( 0 )*vol[10];% v) x9 i1 B; S5 q' p
                        output += mmc5.Process( 1 )*vol[11];5 s1 n6 s* R- V3 f. ]
                        output += mmc5.Process( 2 )*vol[12];2 W! ?% b8 i; s' `, e. ]  o# j3 E
                }
, X3 s+ h$ O" M$ O                if( exsound_select & 0x10 ) {/ C9 R: j8 t0 O9 c5 {) E& S% C
                        output += n106.Process( 0 )*vol[13];
" P* `$ e$ R$ p6 ~1 f                        output += n106.Process( 1 )*vol[14];! @9 r+ `/ W- H1 J0 F
                        output += n106.Process( 2 )*vol[15];
. w. S' ?8 \, Z2 x                        output += n106.Process( 3 )*vol[16];  p6 z$ r* _, E6 X8 x' f' V$ K4 ]
                        output += n106.Process( 4 )*vol[17];1 w, M/ {2 v2 _9 J- z
                        output += n106.Process( 5 )*vol[18];* r' {9 ~" M4 Q+ Z  X( ~
                        output += n106.Process( 6 )*vol[19];8 P6 }* O$ t! x' ]7 _
                        output += n106.Process( 7 )*vol[20];# T+ O( A3 s: U( \
                }
9 F; E6 t, ]/ z2 H+ P                if( exsound_select & 0x20 ) {+ o$ z. i- G0 ?9 {8 g# b2 \) c) W" _
                        fme7.Process( 3 );        // Envelope & Noise1 x# _! \4 h$ d* Z4 l
                        output += fme7.Process( 0 )*vol[21];" P' j% }' A1 i( O
                        output += fme7.Process( 1 )*vol[22];& g- A- n6 \, Z, x. Y
                        output += fme7.Process( 2 )*vol[23];; c; d  [- @9 c! J4 g
                }
+ X/ ?& c0 `. ~0 w" b1 x( f1 I) ?; H% F' k# O
                output >>= 8;7 y1 U- k  g1 _
3 z6 K. a( l! y8 m+ q$ t  h
                if( nFilterType == 1 ) {
) Z* f0 s) B; C6 k* {$ u                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple). V! Y' D# t8 }! r3 V: [
                        output = (lowpass_filter[0]+output)/2;
: g! h2 m4 o. _3 Y                        lowpass_filter[0] = output;
. r  X0 Y& C7 a! ^; a9 _                } else if( nFilterType == 2 ) {
, B; E' I! [% e# c" x                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1); w" B) }6 e) w/ I* y6 D
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ r  Y6 v1 C  E- l$ z+ e                        lowpass_filter[1] = lowpass_filter[0];
8 w2 K7 e( K/ `* u& S3 [                        lowpass_filter[0] = output;$ ?0 p& K0 w4 f9 V/ X5 s. E4 Q! g, T
                } else if( nFilterType == 3 ) {/ }$ a) K" D) v# ?2 Q9 b
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 S6 s+ n4 c8 W, v0 G2 z4 }: u1 b$ Z
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;# D$ L7 O8 C2 u3 U5 Q+ H6 C5 h9 h
                        lowpass_filter[2] = lowpass_filter[1];
) ?& s$ u. U: n& O3 Z# O1 Q                        lowpass_filter[1] = lowpass_filter[0];
. F( B6 Z5 l! r1 q                        lowpass_filter[0] = output;6 F6 B" K# C6 F) C
                } else if( nFilterType == 4 ) {0 a- o2 v" b- \/ L" Y; ^
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 I- s8 E' L: w: Z4 C; I
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;$ I7 h7 t& ]6 y* Z$ x4 p3 A
                        lowpass_filter[1] = lowpass_filter[0];
+ i9 x8 ^0 s2 j: |3 i1 A8 f                        lowpass_filter[0] = output;
9 q& h) g0 O& y: c: ?& g$ Y( v                }- A% K' ^% s# D) A) D. z
8 p1 L; c" W( w7 L" p/ o5 {* X4 @
#if        0+ d9 d8 w: C( Q5 v# V6 X% Y4 w
                // DC惉暘偺僇僢僩
2 _: m8 B& P5 {# c1 q0 `2 S# b0 u& C                {: A* }' U2 K9 p. E* Q/ [/ E
                static double ave = 0.0, max=0.0, min=0.0;; ^# B$ [7 z/ ~/ V3 }, ]' e! [1 w
                double delta;
; I: S8 L8 k  o0 t) h) p                delta = (max-min)/32768.0;
2 T0 y4 y/ H/ s5 n                max -= delta;
, X) z# E6 j1 L4 p9 _& y( G$ z                min += delta;
0 [3 V/ O) h& S5 @                if( output > max ) max = output;9 U% R* S7 e: c" v, n
                if( output < min ) min = output;9 [3 P+ C3 W0 E  y0 R9 T
                ave -= ave/1024.0;& C5 l/ w) o( c! Z) \- G) g
                ave += (max+min)/2048.0;* `( U  K5 O; k' V8 w2 z5 C
                output -= (INT)ave;
/ e, t. ^7 }% ]% M3 t4 y& S( F                }
$ ]! ?6 i- x* \! G4 |) n#endif
- c9 p! z( I9 S7 K. T2 l8 h3 u#if        1
% ~4 b7 Z; c  H/ Z                // DC惉暘偺僇僢僩(HPF TEST)
; N5 M+ T9 y* ]6 G/ v, @8 T                {
  E6 \, }( z+ O4 v% `//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
7 W7 D0 w4 \, N" v) P                static        double        cutofftemp = (2.0*3.141592653579*40.0);1 `; S6 Q+ c  x+ ?. q
                double        cutoff = cutofftemp/(double)Config.sound.nRate;9 y$ r! l  f" T' q7 n. N
                static        double        tmp = 0.0;3 Z+ e" v' g5 t7 e! N* V
                double        in, out;( m* x1 p& [9 @8 B2 F8 i

: k( A: d% `1 |; l                in = (double)output;$ \& v# i. M" Y1 q/ ], W
                out = (in - tmp);
( Y% X0 y' z2 ^2 n8 S# K, A                tmp = tmp + cutoff * out;
0 f& H  ~" P- h; z0 J+ X% @2 u' D
                output = (INT)out;( i2 `) O" Q# j8 G" D! V4 U* T
                }
: {# K5 k6 D* p$ r" l. v$ `#endif
: e3 w. B' [% V+ w) }6 q+ s. h$ r#if        0
6 R, Y' _' Y5 d; f                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST): m- o" y/ Z; W3 ?$ a) m- l
                {, ]; ~0 I: F; e$ G
                INT        diff = abs(output-last_data);6 m7 q3 z) L* Q+ y8 o9 F% d; [1 G
                if( diff > 0x4000 ) {
6 r1 Q2 L' O! o5 f6 N; \% C! i                        output /= 4;
% o  R- ~0 U9 b- A3 L                } else
+ E" H9 }2 [" l9 Y9 n+ ^                if( diff > 0x3000 ) {' b* l) D$ i* `* Z8 b" J" ^: @
                        output /= 3;
% C9 Q# w9 n0 f( k% [                } else
; [. [2 V) ^3 D* m% o0 t5 ~: O                if( diff > 0x2000 ) {
& k8 c# A8 O. R+ V6 @; m                        output /= 2;
3 h& g$ \5 p, z# o! T3 x                }. u+ I2 G  z# l! }( S
                last_data = output;: u9 \! R+ {. Q' H' Z
                }4 Q, @  Y8 b8 _
#endif  e* d( E( i2 \* S8 }# B
                // Limit
, `3 a. A8 b! C. N. }6 c: Z& U+ O" R                if( output > 0x7FFF ) {: e( ^7 I2 _7 a  E, O! h" b6 M! X
                        output = 0x7FFF;. s% J! Q5 x1 S* r: i
                } else if( output < -0x8000 ) {1 D) |2 \% a$ G3 ?. {4 s& z* U
                        output = -0x8000;$ L2 s2 B% \) ?9 r9 o6 Y
                }6 x5 O+ K' e$ n3 @

# Q. T3 K! s8 ?6 Q+ ~% M                if( nBits != 8 ) {2 @5 w" j; `. F/ ]
                        *(SHORT*)lpBuffer = (SHORT)output;3 L0 q* J0 y2 H/ |( f3 q# n" p
                        lpBuffer += sizeof(SHORT);
( ^9 ~$ T% |! D6 r2 J                } else {: ?- q  B( u! i0 ]/ p
                        *lpBuffer++ = (output>>8)^0x80;  z$ Z. d% Y' h. V
                }
+ w0 ]" x8 b- Y, h1 V' m6 o* y! z/ U1 x9 X
                if( nCcount < 0x0100 )% B2 \  ~0 A4 a
                        pSoundBuf[nCcount++] = (SHORT)output;& G( E' Y. a0 Z8 f
& m+ i0 h( Y, B: s$ K* |
//                elapsedtime += cycle_rate;
7 K) R1 Q& V9 u& x. y                elapsed_time += cycle_rate;9 x9 m) W/ H: Q, c8 b& X" s. X
        }  c7 D$ j+ S# i0 l6 j( ?
. h2 @* u2 p+ R. X6 X/ V9 C2 D
#if        1
' {' s1 X+ \* x7 p0 [! h        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 z% J. J: |* d- B* [. ?                elapsed_time = nes->cpu->GetTotalCycles();4 r! `. l# w8 E5 _. Q
        }8 N# x1 s* I+ Z
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
) e* v2 ]  o6 b( z! r. z                elapsed_time = nes->cpu->GetTotalCycles();
" H% P% E/ ~7 @$ R( X" x        }
+ _  u$ ^5 k. Y' N: \#else
- d+ p- i5 c) D5 g6 I" f        elapsed_time = nes->cpu->GetTotalCycles();
7 p  x9 O% j+ @+ q! y% h#endif7 P0 _  B7 @2 I$ a# t! n, a, a
}9 g, a7 G/ F# E/ _* f
# r6 h/ b! Z; Y8 i6 n, @4 {
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)% }& A4 x% J' _
INT        APU::GetChannelFrequency( INT no )
; {, x; M! Z9 w. w' s  w8 V{* r* l; y1 ~& ^8 O4 L9 A
        if( !m_bMute[0] )4 H' n0 [2 U5 M
                return        0;
" e2 i, [/ c( b8 L8 p
! j: l) E! q# C. R) e- I- h        // Internal
- X0 Y! X* [8 |5 k. Y4 Z        if( no < 5 ) {
% e! l3 I9 a  x$ |                return        m_bMute[no+1]?internal.GetFreq( no ):0;  v; T' g4 V! v+ X
        }8 _( p! y5 H- o
        // VRC64 y. t3 K* t( i0 a- j& v
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
7 v% M( u3 ^; e+ H' L9 z                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 G1 P" [  D0 g! N- ?
        }3 v8 ]. `3 Y# E& d2 D- q/ \
        // FDS  g  E7 `' D/ h8 e
        if( (exsound_select & 0x04) && no == 0x300 ) {. s" }$ h' |0 G9 J1 u
                return        m_bMute[6]?fds.GetFreq( 0 ):0;; V0 k0 [6 E% m: q/ J
        }9 d% K' s  v( J
        // MMC5
0 m( }7 i, T$ j        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* ^+ j  u) h# E
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;- s- z+ w+ K3 q: A4 U* {
        }8 a' C2 A; P5 x& R
        // N1062 o) T0 e/ n7 H9 M1 x) F0 `
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
# B2 U! J( L  ?6 H                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; C( @1 x1 x& V$ q1 t. L
        }3 X# }  e; l) X+ W9 e' O
        // FME7
5 Z: [) ?0 o+ _2 Q( M* s        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
! _. E( P  n: F  B$ S; P5 g                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
" A0 l: H9 m, v& h# }2 b* K        }) y  n0 N% Z- L. v
        // VRC7
7 K5 z3 S$ b0 e4 I! x5 s- t        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
( W" d; u4 y! p. R; W( L) Z                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;* Y' r5 V  c: M5 A6 P: c9 v
        }2 _2 f! S$ Y! ]
        return        0;
/ N. I1 v+ k) O5 C4 q}
/ Z2 V) A- G' l$ ]! L' |1 ?8 N: n8 v3 b9 n
// State Save/Load
# ~, \% U0 O! `void        APU::SaveState( LPBYTE p )
. Q$ E5 F( L, U4 S' |4 y; D{
. Q. v) V" j# V. _9 _0 W#ifdef        _DEBUG; ]  q  f; u0 n# F! k
LPBYTE        pold = p;
. ]0 U/ N- m& T9 A#endif6 n. \, G* x3 X$ k

9 b+ A9 Z" x8 K7 Z2 `% m7 K. E        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
9 q5 G& R9 h& _! g+ E        QueueFlush();
' s6 k9 [) y8 Y# L$ s' x$ ^" N' t, A3 C  k5 R
        internal.SaveState( p );- a6 R6 X* S4 X. q
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; e9 W- l, L$ |; D
. s2 U5 `8 K7 ~# S) o8 R* E8 m        // VRC6
, L9 ]; k, V) h" T! R        if( exsound_select & 0x01 ) {7 o7 J" r, o7 p9 \9 f
                vrc6.SaveState( p );8 I7 f9 u$ x3 |
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. R. H. `+ a* \9 b        }* _3 l* D+ g4 e' d$ u* a- v5 `/ w
        // VRC7 (not support)" u+ I. K! {* P* R# P' h! k
        if( exsound_select & 0x02 ) {
$ T9 f0 u1 s! O' l8 }                vrc7.SaveState( p );  |! }! e) I! Z' n
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! m( O; U8 h: V" X" {  u* C        }! f+ T! `* D2 r: J! T
        // FDS
4 A. P1 P- k! ]& Q, C        if( exsound_select & 0x04 ) {
0 C9 V( F. I, }! j                fds.SaveState( p );
/ {1 Y% E$ |# ~1 i% _                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& W. X- Z/ O0 m9 L) k# t) W        }5 K: A0 k' W3 o1 U! `: ]' s
        // MMC5$ f) r# P0 n4 }1 G
        if( exsound_select & 0x08 ) {4 C5 Q1 y% y( e1 \$ Q  m3 D$ |
                mmc5.SaveState( p );
# k  Y" W8 e- y& {) U6 q' U                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. S% [9 S5 J8 T: \& p
        }* V+ N0 j% t2 I  B& K/ o
        // N106. W+ B) \9 U% W: l, _4 T: J' h
        if( exsound_select & 0x10 ) {" y8 W7 e/ R( x: u, x  y/ m7 R
                n106.SaveState( p );" a6 l9 h, J" ]9 \! ^2 Q
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding- }4 ~8 U" x" f8 ]2 D( q
        }
8 \! q0 t" m+ N3 z4 `7 }        // FME7
% ~1 Y9 L. S. [* o        if( exsound_select & 0x20 ) {
: K" ]5 o* T. t2 A                fme7.SaveState( p );3 |# S  M; i, o2 \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 C$ s  S/ X4 ~- O9 v0 s/ j        }
) _& l! j5 K  Z# s8 _2 Z  }4 ^  R
' o5 h  F& E4 h# l, e+ J#ifdef        _DEBUG
% J$ L# |8 [( W" f3 KDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );" l/ h. I- J3 t
#endif3 t5 g9 q! i8 M
}# i) r+ t5 W7 F
4 d  |6 @/ S% x& H
void        APU::LoadState( LPBYTE p )5 }4 D7 C& M  d3 J/ a- S
{/ x  |/ U3 Z: ]& C3 N
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡6 C; g9 c6 `) d4 F# r& p4 f
        QueueClear();
% {/ j2 r7 v; A4 S( I
  p, b1 n  [2 {4 k        internal.LoadState( p );
! W' s& H- d+ G9 p        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 ?2 P# R; D5 r3 G# Q
5 H9 t  u8 u6 B9 E( R        // VRC6
; W" B. p" s9 t- `5 {9 m' N+ m        if( exsound_select & 0x01 ) {: A5 p  x5 q+ `- ^+ R
                vrc6.LoadState( p );
) C7 M. U8 v$ Z& G: `/ r. ]; C( f; |                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' z3 ]* |5 [% ]+ y. e" _3 I0 ?        }( q4 u5 J4 G# ^3 Q+ b
        // VRC7 (not support)
1 [; N2 Y$ A" B8 m: D5 G1 i        if( exsound_select & 0x02 ) {
' B! K3 o1 ]6 |' r4 f$ Z                vrc7.LoadState( p );' @8 O+ x4 h; E5 h; u! X
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: j; n5 Y1 s5 D$ K) h
        }
" P; S) A: e& m3 s; S8 _$ G, P. ]6 D        // FDS
# H" y% h" u$ C5 Q9 ^' C) ?# I        if( exsound_select & 0x04 ) {
) W! s6 m9 D* M2 L                fds.LoadState( p );1 l* A( o& H" ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 Y5 }5 C  p: z/ k
        }
/ ]9 M4 |1 e9 L. {        // MMC5
8 F( O8 f* e& _/ ^6 W, Z. h2 e        if( exsound_select & 0x08 ) {/ z( ]" k! |* m% }; D% T8 h$ j7 L) ^
                mmc5.LoadState( p );
" B. L7 S3 r! \) t                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 m8 k7 {, E. Q8 G# X$ A/ G        }
5 S- q% O' |# c9 O' E: V+ Q; [        // N1069 @6 N- W: Z2 H' J$ g: `
        if( exsound_select & 0x10 ) {
. a5 }( W) k$ m0 e! \/ A                n106.LoadState( p );  X8 f# K* K( E' P" }) u
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
$ _" F, F2 Z+ b7 n" G4 {% L; R        }5 o2 e7 K. S8 o4 p6 G4 N' u
        // FME7- |  ^$ i4 |, W2 K& e  J
        if( exsound_select & 0x20 ) {* G% m* e) v. _' B4 q  e
                fme7.LoadState( p );$ F& @. H& W) q. U# x* j# L
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 P+ M$ H' H4 X7 g- X: T        }" ?/ F. U/ x5 v8 v( n0 H4 t; ^( E
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
  g$ X9 ]9 R; X& j可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 ?: e1 T2 k* v/ H6 f+ i$ O) v感激不尽~~

* L' K$ w$ a0 l* [恩 我對模擬器不是很有研究,
7 a9 m) h4 e: g" O# i& \雖然要了解源碼內容,可能不是很困難,
* x6 Q- O! q' Q# h5 P% L不過還是要花時間,個人目前蠻忙碌的。4 z7 h$ `" {2 P& C0 f

- |1 E: M* |5 _" B: W' e給你一個朋友的MSN,你可以跟他討論看看,
. y/ R2 b6 n7 a他本身是程式設計師,也對FC模擬器很有興趣。3 [, z/ L0 l% N/ |: f
! K3 J, [8 E! S) M5 C% v' a
MSN我就PM到你的信箱了。
4 d$ {8 v) J4 m0 H$ ^9 G6 V0 B( U/ ?
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 / |- K8 P+ A. g6 V3 A2 l
呵…… 谢过团长大人~~
) r' F) t& |* ]* B1 j7 p0 t
% |3 D/ c6 \3 r  B- C. u$ Q! t0 }
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# G( o. {3 S6 I+ q  \团长的朋友都是神,那团长就是神的boss。
4 J7 |4 O. l/ f6 D0 b- ]
哈 不敢當,我只是個平凡人,
6 i& g- @# Z1 A( a) f" w+ |% ~8 s要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙% x6 J9 [( g" T+ b/ t* l% E
ZYH1 K' C0 n5 J' a' c1 W" Y4 Z
QQ:414734306
' j  C( H5 t( EMail:zyh-01@126.com
6 V$ d9 ~5 r% R8 b9 b! m3 H0 |# M6 D- B$ z7 E0 J
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 , I" u' M4 i% g2 u
再次对团长大人和悠悠哥的无私帮助表示感谢~~
* ^* b5 d, G' P" X4 J8 u( ~4 x/ ?2 n
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-2-19 07:08 , Processed in 1.094726 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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