EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  q2 z9 i: z, o5 Q: D
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! e# b! S- U3 r这里有相应的模拟器源码,就当送给大侠了~~
" h! B3 O& X0 N* ihttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
3 s1 i+ C* P. ^% j3 ~! @' `能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 R5 T8 s/ n, }' i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 I- {2 U3 B& u0 D$ C3 T
这里有相应的模拟器源码,就当送给大侠 ...
6 z3 I, f% r" o6 K0 e
聲音部分(Audoi Process Unit = APU):9 X; C/ }/ l. a$ I1 w
.\NES\APU.cpp  ]% f4 @) s4 L2 \, U: O6 A1 J
.\NES\APU.h. @( K  o* ^" z; }+ j2 m

4 p& ?0 K  E. W& j
8 x7 Z. I& v% R3 }. g1 G+ [影像處理部份(Picture Processing Unit = PPU):
$ V% V6 b5 o  O0 m.\NES\PPU.cpp
2 S' n" c8 Q) j$ B* D.\NES\PPU.h
" N: t5 g. H) C4 l9 ?" E2 W/ i0 l/ F9 w7 i: ~
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
0 d. S6 k7 L1 [" @(由于很多专用术语和算法机理都不明白,所以看不大懂……)
+ B. q$ n% X! e3 ?0 P//////////////////////////////////////////////////////////////////////////4 ^, h  E, O1 {4 n" k
//                                                                      //0 c  h/ F1 R  n2 T, F) p7 f
//      NES APU core                                                    //
- O7 N/ `% |) a$ b" g//                                                           Norix      //8 {& l: z; K/ d; p" F, F
//                                               written     2002/06/27 //( f, y9 f' e# M0 f6 Q
//                                               last modify ----/--/-- //
3 r7 m; H+ D# K/ n+ y//////////////////////////////////////////////////////////////////////////
  s' o8 N6 ~5 D#include "DebugOut.h"2 u5 v' i9 J# _8 K: T7 E; @
#include "App.h"" M6 H# \3 ]4 |6 o; \; O1 H# b/ j
#include "Config.h"
5 J6 ?8 _, P5 p( M9 E1 v+ W/ h
/ z3 C, b7 i7 o7 j) {; @#include "nes.h"
/ ?2 t' {7 {9 V) B+ A#include "mmu.h"/ g$ e" \, O/ V6 x' H9 o
#include "cpu.h"
) z+ X' c7 \3 C* M3 v  g' b( i" w#include "ppu.h"
" @( s. C$ b4 {$ c% Z9 E#include "rom.h"
% k0 I2 [3 O" C1 g( z$ `) G3 N1 ]#include "apu.h"0 v3 z+ C- e2 J/ |8 z- @, R/ x5 G
8 Z% z) l) `( z8 f4 M- Q; i$ s  B( @
// Volume adjust
4 q) p3 x: b# d' b// Internal sounds+ \" i) J* P% q. R  B
#define        RECTANGLE_VOL        (0x0F0)
, [- y( G. r8 a+ C0 N* v$ k' c#define        TRIANGLE_VOL        (0x130)) {+ z5 C0 T3 I
#define        NOISE_VOL        (0x0C0)% f$ |0 E* E1 r" U) w& W- ]: E( _" H
#define        DPCM_VOL        (0x0F0)
. f. S: M! V1 D// Extra sounds( \7 U8 ]* S5 Q; K9 E
#define        VRC6_VOL        (0x0F0)" B& Q/ S# k4 B0 j- T3 g4 H! h1 o
#define        VRC7_VOL        (0x130)
; R' A  ?6 C5 H: Q# S, R) H- |0 Z3 v#define        FDS_VOL                (0x0F0)
" U$ p6 t, ?) u#define        MMC5_VOL        (0x0F0); h' S4 t; z+ `$ r$ T" Y9 L* s$ L
#define        N106_VOL        (0x088)
" J7 t; r8 T" J, W, o#define        FME7_VOL        (0x130)
8 n) U+ u1 o) A" \' Q+ S* B) N5 ?, w8 f
APU::APU( NES* parent )
( o* @9 h: O; N, F2 W& b5 ?+ @, c1 H; b; `{3 d1 R: v( F# e4 x0 ~3 {
        exsound_select = 0;) B/ p% y! c: q" b) c" W7 Q7 U

5 S9 U- c! h. r+ B: W  X        nes = parent;
; B/ n, @6 G. }        internal.SetParent( parent );
6 e$ Q6 d9 i8 C; v! t7 v. q% k' _9 m% y- c* H
        last_data = last_diff = 0;
" Z; v, @1 ?* u( z% G8 _( G
/ `) L3 z4 W) o& o' ]3 E( w9 o        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );) y- z' M7 y, d# R4 y; v
* i! O* p; n2 @$ W7 M- |
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
9 q/ ?: W4 D/ T! @  u6 b8 l3 [9 E& V3 w        ZEROMEMORY( &queue, sizeof(queue) );
* P  S3 c; ]4 W) E        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- f# g; ?# \) x6 J) R3 n- i& M2 K  C% b4 k  U
        for( INT i = 0; i < 16; i++ ) {/ C: M2 F1 a% I  x
                m_bMute = TRUE;% b) K# W4 v; \% l6 u7 R
        }( |7 `6 s1 }6 d# [: ?5 K- h
}& h) @9 R; m/ y! m3 F
( t$ c/ F1 j) ~0 U* I
APU::~APU()$ Q: ^6 F. Z: y) ^4 r2 w
{. z3 o& _3 E5 F* E* M
}  s" i  M7 S% q7 t( ~; I7 t. o
5 N* S: Z! ?7 v3 p& L1 k
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
! n$ D2 Z  I5 e+ `{
& j2 M- \; n, a, `        queue.data[queue.wrptr].time = writetime;5 b& a. v1 @/ {# ^* x, `
        queue.data[queue.wrptr].addr = addr;' X( b- B" m! H6 O0 e4 W
        queue.data[queue.wrptr].data = data;
, `. d% g/ ]+ u( O/ X: o2 f        queue.wrptr++;  }  f+ c% F5 H! \- h- M+ a8 q
        queue.wrptr&=QUEUE_LENGTH-1;
! T; h+ l& A, ~        if( queue.wrptr == queue.rdptr ) {
3 Z0 V) d+ ^2 e$ N. w0 \+ x3 _1 ]$ h                DEBUGOUT( "queue overflow.\n" );6 e* g; I+ L$ _
        }
" I/ ~1 ]3 I0 _) b}
+ }( i1 [, B0 {2 R
/ k4 s: N6 u  sBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )% o) m6 ?( H' H3 g$ T( {
{* x8 Y, @" g5 N7 q
        if( queue.wrptr == queue.rdptr ) {- Z( L9 q7 ^0 r5 G- {
                return        FALSE;! v" x5 {/ W; J" R
        }& h0 o  [7 W: Z% w
        if( queue.data[queue.rdptr].time <= writetime ) {
% r! O+ ?9 b0 ]3 z* J1 m                ret = queue.data[queue.rdptr];
* g! o( N( N1 }- a: d/ Y2 ?                queue.rdptr++;
8 w: y0 K# p+ r" ?' f, E: S. i7 [  t                queue.rdptr&=QUEUE_LENGTH-1;
4 J$ r7 [! |# G2 U- _) F) ^6 H                return        TRUE;
" C- B* ]8 s7 T2 Y3 V  |- z        }8 @* B* N% T& m9 n1 n5 C& S
        return        FALSE;
$ K* A7 w5 q( G/ f+ }$ j4 D}% I) H' p" J( K$ P" q/ ]

! H) e% x( I$ lvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
% s. R* {: H3 V& H  A9 k% i, Q{, Z' W; P( X2 F
        exqueue.data[exqueue.wrptr].time = writetime;5 a3 u3 ]' g* \, q  ?
        exqueue.data[exqueue.wrptr].addr = addr;
7 y, I* I  W; G/ ?4 X! O/ K        exqueue.data[exqueue.wrptr].data = data;1 b4 {+ |& g8 j" t8 b! ?! O
        exqueue.wrptr++;% |; C0 c) X5 X' M4 c+ @
        exqueue.wrptr&=QUEUE_LENGTH-1;
5 c# T7 O  C! g7 P7 M. X- A' b        if( exqueue.wrptr == exqueue.rdptr ) {
/ N$ ^1 {" \2 a, [: a+ V3 u# I                DEBUGOUT( "exqueue overflow.\n" );
  [! G9 J, ]0 \+ h" C) M        }- Q3 ~% Y, s6 w
}
& W. L# L3 B8 h* d( A5 i' p! r, R& V( X% O2 R% s
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )6 q- v- K  h" T  E3 A) _
{
+ c+ p8 `6 V4 n        if( exqueue.wrptr == exqueue.rdptr ) {
) A! \" B8 Q  j" ?5 V                return        FALSE;
+ @9 Q% D: O3 E. t- ?7 F        }- K3 N, g8 K8 G
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {# ?* o1 }. W8 X5 P# p
                ret = exqueue.data[exqueue.rdptr];
2 |" _. h  e9 s                exqueue.rdptr++;- ^+ o. s( V3 E. L# I
                exqueue.rdptr&=QUEUE_LENGTH-1;
+ u' L5 E( L& m' L# B$ U                return        TRUE;
+ L, V1 r/ u! W* X/ j        }7 p. I9 j/ `# s+ p
        return        FALSE;
% m* y& R& i5 w1 o! {& e; L}$ b' W3 E; ^4 V$ B  y
7 b3 X) Y) Z* s4 Z. X
void        APU::QueueClear()
4 `7 {* Z+ x: p9 c" |9 Q  w: Y{
. }4 p# m+ D. G- C0 A* O        ZEROMEMORY( &queue, sizeof(queue) );7 q$ T( m  N  p4 t5 @. [* m6 `: b
        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ o: K# e4 B# F+ o
}
& F# Q! H* r. q% v% f
5 m2 r5 a; r& a: s8 G* H" [, evoid        APU::QueueFlush()
$ x) m9 e/ i" t% ]5 i" i{+ \( p, t& L; B/ _* c" W
        while( queue.wrptr != queue.rdptr ) {  A- E3 X( D3 @+ ^
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ D' u0 D; n  c, O
                queue.rdptr++;# ?1 y1 R( a# Y3 L4 `
                queue.rdptr&=QUEUE_LENGTH-1;4 `9 @* m) ~. f3 i2 t1 M% v
        }
0 i, n! G+ o6 q8 k- H4 C1 B' z( L; D2 k. r5 H& z
        while( exqueue.wrptr != exqueue.rdptr ) {
0 t2 C8 e% a, u  K3 P$ {6 _                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );8 o: {: d* v9 I2 v- {! P, b1 U
                exqueue.rdptr++;1 Q0 M, l( H# X' l0 G: T
                exqueue.rdptr&=QUEUE_LENGTH-1;
* P2 ]* G8 x3 p# I! L4 W) }        }
9 y" y# \4 c! N% |# t% I% c}) W, g8 H9 b% Q. j7 `

; N. z! h5 h+ ~2 s$ xvoid        APU::SoundSetup()
3 ^) V6 U4 g* a& I: D{$ \1 t# ^7 R; M) g0 o
        FLOAT        fClock = nes->nescfg->CpuClock;% T$ h; }, ^5 _; A( D5 g  C
        INT        nRate = (INT)Config.sound.nRate;2 }7 I9 d% u) \8 @
        internal.Setup( fClock, nRate );$ m" U8 K/ X3 ~% }
        vrc6.Setup( fClock, nRate );& y# C$ |2 j2 N& |( Z
        vrc7.Setup( fClock, nRate );7 J; A# `: [# A5 V$ N5 Z( i, w* R
        mmc5.Setup( fClock, nRate );
( {& a+ Y$ x; |) S' t$ V        fds.Setup ( fClock, nRate );! X# d" ^9 ^# n" X
        n106.Setup( fClock, nRate );3 Z6 A% O5 v8 v4 i' e8 q
        fme7.Setup( fClock, nRate );
9 R4 A6 R8 p4 _/ d, a0 I& X}
" S; l* i* n& T& o. }
3 p' k  j0 @+ f: q/ m" |# n. Z# E7 uvoid        APU::Reset()
3 q4 X# l  s8 ?* _. M{
, \% T, ]: z$ _) G2 S        ZEROMEMORY( &queue, sizeof(queue) );
9 D, T& r+ q8 I' x" a5 x  O        ZEROMEMORY( &exqueue, sizeof(exqueue) );; g9 x2 E# i& Q# T
1 [, h8 J* [. Q/ T( ~4 R
        elapsed_time = 0;" w: k, t  k- @- W& w5 B
2 ~  Y! Q$ b* B4 G
        FLOAT        fClock = nes->nescfg->CpuClock;5 |+ c8 v, t: M
        INT        nRate = (INT)Config.sound.nRate;
$ u$ Y/ S( A( }; ]7 D( k* g        internal.Reset( fClock, nRate );! p* S+ j% o/ q8 ~' f3 w) d( l& \3 B
        vrc6.Reset( fClock, nRate );
1 C( T, C# g* v; g9 [6 R% W        vrc7.Reset( fClock, nRate );  u" b4 K( l8 C3 ]8 L' X
        mmc5.Reset( fClock, nRate );
- \. B% h0 }1 O9 e        fds.Reset ( fClock, nRate );( g& y$ i9 h0 _0 {2 @8 k
        n106.Reset( fClock, nRate );
& q) Y2 g: d4 A8 v# K        fme7.Reset( fClock, nRate );% i) A8 D5 F. N" Y# `9 u
0 Z# u7 c$ e# j+ n
        SoundSetup();0 h9 i* X5 f6 f' y: d, g
}
8 _# T0 f8 \% c2 h' E: i# \  B3 M  r7 T8 K$ B# {
void        APU::SelectExSound( BYTE data )" l' G  V+ Q' @! K# H1 p
{8 S! }0 U2 x# e4 S
        exsound_select = data;
; X# S! U8 L1 y9 @}
+ ^( ]0 O; U4 B: s7 P; T3 f4 [: R# Q/ W4 U* [0 ~
BYTE        APU::Read( WORD addr )" I0 }; @0 l- a  |# h, v
{0 D/ L* N4 {1 Y* ]4 L: r
        return        internal.SyncRead( addr );
: \& @$ Y; Q4 ^1 [1 b% A# i- \}
$ q( t. r9 c8 q" X' y
! V5 ~: I0 b4 I5 r4 d' A8 tvoid        APU::Write( WORD addr, BYTE data )2 W9 s3 j' b" K0 B8 |
{6 \: o' y+ e$ u! O
        // $4018偼VirtuaNES屌桳億乕僩
  w" y* b' v& d7 Z+ ]        if( addr >= 0x4000 && addr <= 0x401F ) {
, x: S+ {6 z  |% D. f% [                internal.SyncWrite( addr, data );
% c- y* B" F  J                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
% n+ p8 [1 J" g; o        }" x& ^/ F. h- L+ g: ~2 n8 Z
}
+ d# [  r- S' Y: Q$ s# @
% j; j+ ?9 u6 M( i/ X3 l; A+ _BYTE        APU::ExRead( WORD addr )
0 N) a: K* l! q: S{
8 S- d  d9 Q$ v+ z9 EBYTE        data = 0;
7 _8 q7 ]# b7 @) U# k0 W7 V2 O0 d! X6 \. A
        if( exsound_select & 0x10 ) {
0 v% X- S! c3 J4 r                if( addr == 0x4800 ) {2 M- H/ k! `5 Q* {' `
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );$ b- X1 u4 g, L
                }" V% g2 R% ~1 f: B  Y
        }9 M& R; o1 n' r. o) Q& h( t% {
        if( exsound_select & 0x04 ) {9 Y/ `7 z- ~* K# t9 W
                if( addr >= 0x4040 && addr < 0x4100 ) {, q5 I# `: F3 s( ~
                        data = fds.SyncRead( addr );% K- P- c1 w/ O6 v
                }
; U7 c! p3 b1 E/ A# n0 f7 j        }+ G: `& h* o9 T) x
        if( exsound_select & 0x08 ) {
2 y' E: `! e( n                if( addr >= 0x5000 && addr <= 0x5015 ) {8 n9 k! C! S, E8 {0 P
                        data = mmc5.SyncRead( addr );
' H* n' V' x4 A& }                }& t0 p( g; K: |% b
        }
! [% Z+ d+ y, N4 p4 q1 `0 C: A
* H' Y. m; P; S) I% Q1 i$ F        return        data;
' ]4 r5 i3 ^5 X1 E. H) N: @}+ I3 O0 T- e% R3 b! |. Q- [  K# e
1 k/ a0 F! v* D, ~4 v& F
void        APU::ExWrite( WORD addr, BYTE data )2 e& {1 b$ I" Z: f8 z$ z, ]
{+ m6 l! X* C1 l: E) |* @
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
7 \; P9 B3 l4 w2 q3 h9 Z; Q
. \  q; V0 r$ a        if( exsound_select & 0x04 ) {/ d* Y: [4 k$ I, m, B' U9 \
                if( addr >= 0x4040 && addr < 0x4100 ) {7 f2 @" L7 _7 E
                        fds.SyncWrite( addr, data );; @3 M2 v$ ^6 }$ r! p/ l
                }( B* [4 M8 C, X  L9 c! m7 Z
        }4 M% C8 t. T, z: d! R

/ E0 @. }# f' Y1 Z) _        if( exsound_select & 0x08 ) {
. s& D3 o3 O. v, A. A* Z, b- _                if( addr >= 0x5000 && addr <= 0x5015 ) {  Z" F% J5 o9 a2 O9 L$ p1 O
                        mmc5.SyncWrite( addr, data );
# c* D! I. E! b: c# k; ]                }7 Q/ X& k0 M" o! x
        }
2 ]$ y/ N" j8 h( i2 }* a; g}& l9 z) B" Z* k# y- ~0 J- v

1 \2 C! Z. B; t% kvoid        APU::Sync()4 c' |0 H! t1 z. V0 H$ `+ r
{
3 }. S# A+ `& T; Y, c$ N}
, r6 t  F, z* y: @4 L, a
2 Y$ W8 r# W# _/ `+ l( z& @# _void        APU::SyncDPCM( INT cycles )
, u- l9 A/ X  S) V: A4 f5 m* i{
5 t4 E$ d. t1 r8 l5 H        internal.Sync( cycles );
8 F& P/ n8 k8 G& z$ G7 k
0 O! v  }. s- f+ S9 \% i- Q        if( exsound_select & 0x04 ) {
2 |+ D0 o/ w! k7 `" Z3 W                fds.Sync( cycles );
' o! b6 C& E# y0 t8 a; |        }6 ?. B+ p* E# L  M. P5 G
        if( exsound_select & 0x08 ) {
! q7 V/ e- U% b* ]. }                mmc5.Sync( cycles );
8 N. x# n6 s% p# X7 A- r& ^        }$ R/ l* `- _$ ]4 D0 c1 l  h0 {4 |0 V# Z; A
}
' |+ x' |  l& W6 A! _3 A; T/ P2 R+ D
void        APU::WriteProcess( WORD addr, BYTE data )
1 t0 M0 `7 _1 _* d{
& Y9 Y" p* D0 l% X* G" [& Y- t7 E        // $4018偼VirtuaNES屌桳億乕僩7 g* S: r" V/ `3 u$ ]
        if( addr >= 0x4000 && addr <= 0x401F ) {9 Q0 n. E/ C! D, ]
                internal.Write( addr, data );1 }1 A! ]' |! J/ r
        }- w  A" s; }3 L8 g
}3 ?2 _7 O" ?# _2 B9 v) V; S
8 k. M& y4 g# f
void        APU::WriteExProcess( WORD addr, BYTE data )" Z' q% C, f4 c0 l$ l
{1 P: h. u, [+ ~. `
        if( exsound_select & 0x01 ) {
) f" Q1 ~- o/ M/ }                vrc6.Write( addr, data );
, l8 f! n' {9 X5 |        }3 U) K$ ~+ t1 T& j2 e
        if( exsound_select & 0x02 ) {
: L) I) b4 Y1 g3 S                vrc7.Write( addr, data );
7 ]( |% t7 s: @9 q        }
& B8 g3 z2 l& c, s        if( exsound_select & 0x04 ) {
! j8 |1 \# M  i6 a( E+ z! w2 W! ?9 }( h                fds.Write( addr, data );. L! l! r& ^. Y- g! B: w8 g
        }  `2 i2 K3 |4 ~% z5 G5 V
        if( exsound_select & 0x08 ) {
. x$ U# I9 \! c# L4 [1 @                mmc5.Write( addr, data );- A0 K& E: R/ \# R4 m. c
        }
' h$ l5 I4 q% z* x, H        if( exsound_select & 0x10 ) {, R, H: [7 [+ g/ z1 w
                if( addr == 0x0000 ) {3 [! ?# I2 {3 G& y$ l0 k
                        BYTE        dummy = n106.Read( addr );2 k# G% A, b: H7 K; v7 G
                } else {
0 ~! S. D2 r5 I$ {. e# @$ P7 H( e                        n106.Write( addr, data );
6 G. Y2 e! ]( f2 [9 z: I                }% B8 E2 ^$ {% p5 b, S9 e
        }. ?$ j; k# s2 ^5 {" s7 U: g
        if( exsound_select & 0x20 ) {2 G5 k4 A9 _' @. \" E% y1 G, a
                fme7.Write( addr, data );4 O; _7 U& S8 r* R. C
        }0 i( \- k! F, `2 m8 l2 o
}
' W. n4 w, l: o( j6 ?* _7 x# o, _( L. ?( N2 g& D
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). `1 A2 Y2 N0 c' r6 S6 P
{1 t  \' I: H$ [+ U
INT        nBits = Config.sound.nBits;
) L- S5 \  x' j  ODWORD        dwLength = dwSize / (nBits/8);( X' ^' v& A, W) Q+ W' c
INT        output;
: E3 A* p' h# E0 ?9 KQUEUEDATA q;
( ^! F' v# T2 W  ^4 i% Z9 a7 RDWORD        writetime;  ?: _# C; R+ b* d- J! X

3 T) N. `4 R8 \7 b  ^LPSHORT        pSoundBuf = m_SoundBuffer;
/ r1 h: V5 Q5 {* n7 ?0 ~INT        nCcount = 0;
- Q! e1 r4 O( L6 I) v! p; N# P# z+ @" k1 x% z
INT        nFilterType = Config.sound.nFilterType;
+ o5 j) Q! J) F2 J7 Q% b+ c: u6 {9 I8 D0 u% j. h
        if( !Config.sound.bEnable ) {. A, v" ^! s. M8 k3 Q
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
% ~# r; c9 P0 k2 \0 Q0 S7 _                return;
+ i/ u1 Y, P# K/ V- @  M6 Y, k        }
* u0 L. g7 H8 a, f( g# v
& p8 c; y# e: I7 i        // Volume setup, c8 E/ g8 w7 d. D4 ]2 f6 }
        //  0:Master
8 a! [- ]) i) N: t5 R0 n- A        //  1:Rectangle 1" s' h# ?5 m9 f) n0 ~6 A, M7 r
        //  2:Rectangle 2$ k4 R, j" i& {5 f! Y+ z0 |8 U$ w
        //  3:Triangle9 ]0 f+ n8 x3 r
        //  4:Noise
3 @5 C: `! f6 B! R0 r" z* P        //  5:DPCM8 p6 d% ]3 B/ X1 F: }
        //  6:VRC6
9 S9 R% F! J; I: D        //  7:VRC76 q  ?" q  u. n( S( x; Y
        //  8:FDS
' S0 o9 F: R/ y! Q$ _        //  9:MMC5
2 O; t- ?$ B4 E: {- E2 T) G4 A        // 10:N1065 z- p5 p8 h; s) X
        // 11:FME7
4 c7 B# p8 A0 @- Q        INT        vol[24];
8 }/ H, B# _* H% h) k5 P( s0 j        BOOL*        bMute = m_bMute;* ]; _# i! I$ F  W' ]) ~; O; J! ]' s. a4 u
        SHORT*        nVolume = Config.sound.nVolume;* {8 `9 q( u" i9 b
% L/ ?$ k; m# W( C1 }7 p% U
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
! r+ x1 K! v0 }+ G- @* ]6 H1 {& T4 v4 z
        // Internal$ T2 c0 c: _; p% m" \
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;$ W3 t+ H% {+ ^# v4 t
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
; A! [- a2 C$ ~! a  ]        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- ^' }) H8 r; J7 Z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 w6 j7 Q$ e  ^5 m6 N
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
% s8 W7 @* c- V) C1 F& C  L! V6 t; W  k) j, Q  G
        // VRC6. O4 i% B1 ?- n  G* E
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! s6 N3 J7 T" N3 U
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  a, x6 T% M+ x' k  K# t        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 }) R/ P9 j, r
1 u# l% U5 Y  f: r. ^+ Q5 S  E        // VRC7
  L  n6 W/ F' ^( V+ Y. R1 K        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;) B+ E5 Z! x# ^8 Z
+ ?% Z! [* }: Z
        // FDS
& G% k# k9 H; M  z! N" n% ^9 X3 y, t        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;" a/ N  b& N3 U8 ]1 X0 J) D+ @
" V: `: U8 |" d. D# C2 b" V
        // MMC5
) [7 u# X  v: E. \, |" O2 G        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 l2 E+ h  D* y( c1 c8 R        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. d. Q8 g* D  X" S) W        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* _9 ~( c: T' a4 W
3 C4 b! q, `& T: M8 u, j  h; k& R        // N1068 C$ P! S1 {) h7 H
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' @. j7 y+ C3 N. M0 s9 S6 d        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; Q3 }0 \, q1 _' h        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* s" I) i! x1 ?) ~+ ]3 G        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, {( s9 T: o7 y- M) }/ N7 j9 T        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! @6 s: d, Q* l
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 _2 z# m: O8 W$ o& z' _& b        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ t/ Y& Y# ^# a
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 S+ x9 e0 X. D$ [* Y* Y8 M- M: r: m
% G  |' N6 x# U) S
        // FME7$ p5 P6 E& p- ?; z1 m
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" s4 f2 M) d! Q' t1 t
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 N' ?& f  O/ _( l. `  s- q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. J$ r# T1 T- b
) n2 M* Q/ n+ J! R( b+ d//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ m) y- M: Q- ~& P1 z  u        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
+ y$ K  q' o; i$ c! x8 o% Y% k1 i& J
' `& e/ `( I1 O( C" q8 m  e        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
1 x) }- z' }: W/ v: t4 C5 F3 [        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
, g) l( [. ^+ q% e$ o1 l                QueueFlush();
# e, Z: X3 s3 b& Q8 b        }
  k2 e& O  J' f+ D) D) I5 p- [4 r
+ x: z; i: j; Y/ ]7 s9 x" Z' @        while( dwLength-- ) {
( P& d/ x) e* Y. `% p# B                writetime = (DWORD)elapsed_time;
' s4 c' X: u! T& i/ h( I% C/ q9 A0 B6 t; s  d8 \
                while( GetQueue( writetime, q ) ) {
3 l1 O" e) u( M5 X% X3 ^                        WriteProcess( q.addr, q.data );
9 r; K- d+ K1 P                }
$ E3 Z) f2 |1 N3 H$ A% a0 S" M; F: V. s) \- t  q! ?7 l
                while( GetExQueue( writetime, q ) ) {
6 I" y1 w! r; t$ |/ F: h                        WriteExProcess( q.addr, q.data );0 ^$ e5 D8 Q, W- s1 @
                }
% y$ T; k& \( `  c9 p
0 Q: Z$ x) a5 f( t2 F                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME74 e/ W1 n) o6 ?* C. o( M  b( e4 l
                output = 0;
1 q6 [  {# @: f- j                output += internal.Process( 0 )*vol[0];. c# g+ o3 G3 q5 E5 s- E, K1 L
                output += internal.Process( 1 )*vol[1];
2 r% g/ g- G6 N; F' H3 a- W                output += internal.Process( 2 )*vol[2];; C* I- ~5 c$ Y
                output += internal.Process( 3 )*vol[3];: z( m8 \5 ^6 `+ D5 C: S, m
                output += internal.Process( 4 )*vol[4];
  f2 L$ u5 z& T3 T5 {1 X8 z
6 Q* b) [/ G3 h! L9 d0 D3 \6 Q                if( exsound_select & 0x01 ) {! f" C* M* j8 V
                        output += vrc6.Process( 0 )*vol[5];
; A4 h8 s( B& N) T7 l                        output += vrc6.Process( 1 )*vol[6];
4 h4 m7 \: r2 l+ s                        output += vrc6.Process( 2 )*vol[7];
: N5 j6 s7 w' x3 k; u                }
0 A# z1 i& N* u+ K7 g                if( exsound_select & 0x02 ) {# f2 V5 Q5 m" P- c7 f
                        output += vrc7.Process( 0 )*vol[8];
; y; ?6 O8 N! h; ]' t0 z& a4 Q                }* g/ _; R! G! {1 o9 o7 K: Z
                if( exsound_select & 0x04 ) {; ]: ~; @6 P9 Z; ]1 Q. I
                        output += fds.Process( 0 )*vol[9];
/ i' i8 {7 k8 @5 t1 N: v: ]                }+ @- |- c3 t- ]# K
                if( exsound_select & 0x08 ) {1 \" a; r- Z+ J# F
                        output += mmc5.Process( 0 )*vol[10];
6 Y$ X; ^7 {0 Q6 J                        output += mmc5.Process( 1 )*vol[11];
! B5 q' q0 C6 X4 R3 Z' S# V/ \                        output += mmc5.Process( 2 )*vol[12];9 a( ^* m( v% ~  ]2 n9 Z5 B9 t+ m& K# ^
                }9 y) V0 _; n4 i4 @
                if( exsound_select & 0x10 ) {
9 S8 k3 [/ ]0 A. [: x( c1 v4 @                        output += n106.Process( 0 )*vol[13];
/ K: J2 j7 |' d8 j                        output += n106.Process( 1 )*vol[14];
- `6 Q6 N6 N( U- }5 E                        output += n106.Process( 2 )*vol[15];
# A+ u4 D% ~+ p+ R# h& E                        output += n106.Process( 3 )*vol[16];8 Z1 S& Y, t$ t6 m) F$ U' l* \
                        output += n106.Process( 4 )*vol[17];7 V8 D( l  n& N3 t
                        output += n106.Process( 5 )*vol[18];4 f+ x3 Y; A1 {  Q. V, l
                        output += n106.Process( 6 )*vol[19];  c" a  T) t/ ]! X# D. i. B; F
                        output += n106.Process( 7 )*vol[20];, [  V$ V) l: }/ j
                }7 I# T5 W( ^" t$ w& j" `" m% b4 c
                if( exsound_select & 0x20 ) {
! _* x) B& Y8 f5 t. {                        fme7.Process( 3 );        // Envelope & Noise
7 c. |- t5 F/ p0 Y( P) J5 X0 j                        output += fme7.Process( 0 )*vol[21];
2 r, R! M" M+ {0 _1 F                        output += fme7.Process( 1 )*vol[22];
  U/ D% n( a$ U4 L$ I/ ?7 q1 Y                        output += fme7.Process( 2 )*vol[23];
, m8 f6 k4 g: H# p                }* W% Q. f0 o" D& |8 ^  z

( P, t( b4 j6 I- P3 ^0 P                output >>= 8;) R2 x6 Q/ S, W- G% x8 H
( C4 s+ S) `& u8 c/ N" y( M
                if( nFilterType == 1 ) {
$ C  y% N4 j  _- s# V9 ^6 ~* i" f. b                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
- t9 }8 g/ y# e1 k( _                        output = (lowpass_filter[0]+output)/2;  b3 R4 b6 p2 }: a: ^
                        lowpass_filter[0] = output;
; l7 n. A  O% Q$ {/ F, }" T                } else if( nFilterType == 2 ) {! w& v: ^1 W8 z1 q" a! r% }2 s
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)! r1 V3 F+ A3 j' y* a, c6 K
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
+ t9 G& \! t. b* B' z2 a  {1 c8 h                        lowpass_filter[1] = lowpass_filter[0];
; T* t. Q% Q$ J: L5 \                        lowpass_filter[0] = output;
, a9 q: w  j- J                } else if( nFilterType == 3 ) {
4 n! l- g- n, J- F                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); Y3 H' E' O8 T6 Z- H
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;5 s9 b" O( p$ }( C% p' j
                        lowpass_filter[2] = lowpass_filter[1];8 R) T  r6 t  H$ y0 \
                        lowpass_filter[1] = lowpass_filter[0];
( {; o% k% D( G" D6 v- p                        lowpass_filter[0] = output;5 W: S; O+ h/ q/ e  Y* B/ n
                } else if( nFilterType == 4 ) {
  ~- V6 I. M9 r$ t6 n6 o) W' ~0 d# b/ x                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)" d6 g, h3 R5 F, G
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' E1 X- R/ u: v. _8 O
                        lowpass_filter[1] = lowpass_filter[0];
+ f1 ]- E' ?/ U9 L3 {3 m                        lowpass_filter[0] = output;
2 X) z  Y6 f6 F4 M                }7 S9 o; b" H, G0 k. v

+ z: ]& M# x) @9 P: o#if        0( d( l" d8 j* e* R8 i6 u
                // DC惉暘偺僇僢僩6 R! O0 N: h" }0 u* v
                {' J' U' Z. k2 @! P' F0 J
                static double ave = 0.0, max=0.0, min=0.0;
$ G6 s/ [( t# a: A3 F                double delta;
7 i* ~* D5 L! ~/ x                delta = (max-min)/32768.0;
9 s0 ~2 \7 x0 m/ f$ w  E+ y                max -= delta;
+ I# ]5 x6 a9 b' e4 [                min += delta;
3 V8 r. A6 F: E4 R9 ]4 T9 s                if( output > max ) max = output;6 G  q5 b1 e& ]  B
                if( output < min ) min = output;# R3 e7 B, l" X, q* ~$ l
                ave -= ave/1024.0;
$ z6 X: f( d$ e$ a                ave += (max+min)/2048.0;
+ X2 ]* T; Y2 c0 R                output -= (INT)ave;
/ y- \: z" {5 e# ]4 G                }
$ {; [" k, |' _. H#endif4 @1 U0 o: ~) l8 r' p
#if        1% O0 W. q& e( [' s/ T8 l
                // DC惉暘偺僇僢僩(HPF TEST)/ m. G0 I6 P) f0 T6 [, z+ K# U
                {  R0 x; g2 I6 O" ~
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* `; l% \% F% R% L8 B3 X0 h
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
/ }+ t. A4 W' v$ L5 }4 Y. j                double        cutoff = cutofftemp/(double)Config.sound.nRate;3 D- p, \1 l3 i: H* a/ C3 g
                static        double        tmp = 0.0;9 W, p" r. e1 b3 g* L: m
                double        in, out;
3 v; J" `& r1 t+ E0 ^, S
& ?; Y% a! g2 P  u                in = (double)output;
6 Z6 Y. F- `* d& t7 B0 V                out = (in - tmp);; U& }, J! f5 k' I; X1 k
                tmp = tmp + cutoff * out;
! b( Z! m* i2 v- _& j2 r2 W4 O1 X. }. @& Y
                output = (INT)out;
9 x% i2 Z% R2 w+ r" i                }  J% m0 }2 E2 B5 t2 q
#endif! d; |2 F+ H. D& J+ I' p+ }
#if        0
/ [4 L# L. c8 O& a; \# M                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
( Z% a# R$ I  Z3 I. [                {" t' i- h5 b4 W2 D, B
                INT        diff = abs(output-last_data);1 _1 U1 j" ?  @- ^. M6 R
                if( diff > 0x4000 ) {) O0 q1 n1 T. }9 K7 \( ]  B
                        output /= 4;
' T6 o# Q# D7 |9 d, j, S, ]" P) e                } else
% h7 \* w. \! g# \7 v) @                if( diff > 0x3000 ) {" i' p# y% a) x! @4 h+ J7 e
                        output /= 3;
7 `& s! j# k( Q" d4 o                } else: Z( M; q. B4 y; j0 T7 ^% Q2 f% X
                if( diff > 0x2000 ) {
" `5 O* V$ {$ n4 ?7 M                        output /= 2;9 B7 ^; E4 j% H$ Y* S8 Q+ S
                }5 b& E& F; K3 z0 H; A
                last_data = output;- g- H& [7 U$ `8 ^# M
                }
* a$ C$ q3 j% V  G6 l9 M1 U# a#endif
# U. ]6 t5 g- N3 d( z7 Q$ p                // Limit
. ]2 Q" G6 f5 p' Z                if( output > 0x7FFF ) {
% l, F5 o8 E5 S4 J. I% n9 m4 q) r                        output = 0x7FFF;
4 |5 F& |* [# Q+ Y( Z: Y                } else if( output < -0x8000 ) {
4 x+ U6 x% H9 y0 r6 ?" V- f3 h                        output = -0x8000;& y. K# E% T9 N' Y( @. t
                }
! R7 `4 f' K2 h: _) {- `# ^3 C% l0 J+ {  t
                if( nBits != 8 ) {/ J9 A1 x' W+ n" T# Z
                        *(SHORT*)lpBuffer = (SHORT)output;
; d6 I. c# m$ N4 c) q& G                        lpBuffer += sizeof(SHORT);
8 K; h+ N' l. {' r; K: x: U" h7 @5 w5 d                } else {. W/ b/ Q2 r" U8 w9 ]
                        *lpBuffer++ = (output>>8)^0x80;& g8 T( t7 D1 x- B2 u  D
                }" p) L9 _! V6 x+ E: z" O, M6 b' i1 Y

4 d$ `. R; y8 X( A) O                if( nCcount < 0x0100 )
0 I( A3 {. b  d+ o( e0 q1 [                        pSoundBuf[nCcount++] = (SHORT)output;
$ `" J; e% l3 p4 U" M7 a
( W) p* i: C. k1 g% v1 B% n//                elapsedtime += cycle_rate;, f5 z* M( K* ~. h4 ~
                elapsed_time += cycle_rate;
& |8 b  g5 S  A/ z; W/ a7 P3 W: u        }7 W0 [0 O8 B- k2 l

7 a. M3 |. o* X1 w* C* Q: \#if        1% h' B: ~5 I1 e0 {7 {* D) N! c
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
1 W  b6 @/ X+ g- h                elapsed_time = nes->cpu->GetTotalCycles();4 g4 A. ]3 r; H  l+ U
        }
2 h9 a0 l" t4 ~: n+ P        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {: i3 l# E( B3 ?9 A1 l6 `
                elapsed_time = nes->cpu->GetTotalCycles();
9 N& j8 [- k* C        }( n! L9 H5 O9 u6 v: o% e% R6 R  K1 ]
#else
( K5 R. s* h/ Z& D7 _        elapsed_time = nes->cpu->GetTotalCycles();+ F# d% @* C) M3 `6 h' s$ }
#endif5 d  i$ V8 Z) u8 l6 r. L1 B/ f
}
# Y, a) S3 W/ v: h2 ]1 r+ ~& z# X& W( L; U! b
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
, Q# X4 `! R$ j+ }9 P6 o+ d0 zINT        APU::GetChannelFrequency( INT no )
2 T0 B2 ]5 Z1 \% L' g% J; X{, Z3 u$ S3 O  u; S$ b
        if( !m_bMute[0] )
; c: t0 r5 d5 D7 H* l% k7 r' W                return        0;
, B* P3 Z& z; ?6 \) J% N% S) i& n
  p% T5 C0 b; m+ F' G  ~2 }        // Internal
: l4 r% p$ z1 N% J% K( I        if( no < 5 ) {
# H4 y1 Q9 @0 c+ n                return        m_bMute[no+1]?internal.GetFreq( no ):0;
* d- Z8 X& F9 R  i! B% J        }" \# d  l4 k" w- W3 [, Y$ B
        // VRC6
0 Y- s4 X/ Z" q3 |6 S8 M( H0 q        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; F7 @4 t1 N2 G  w* B3 e                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
9 E% W1 e' C) H/ }( A        }
3 p+ G2 e3 E' n# j6 }) H2 n' v& Y        // FDS
* q* n( t5 x9 @6 O        if( (exsound_select & 0x04) && no == 0x300 ) {
% P7 \( `% g; ]6 M2 C* s) Y                return        m_bMute[6]?fds.GetFreq( 0 ):0;
: I0 u6 \3 ~6 h3 u5 \( |9 N9 L, a! w        }' d7 P# o9 {2 P: y4 ]2 [/ e
        // MMC5" @* n* p# B% r
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
! M- g( T$ S+ D3 ^                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;9 [/ i# i% X1 M- H. i
        }
/ q; q8 k& x: D6 J9 g0 Q& |        // N106  \5 J/ Y8 G2 U' i  A4 h, f
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" O: A& @# C1 {$ ~1 C4 |/ `! g                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
. X0 F! {, o- k+ a        }$ \3 _! T) V" ~, b: H4 j
        // FME7
6 L& ]0 N# K: j( L/ Y        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 W1 L. O$ Q$ ^6 T9 w# w( ^                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;1 @! X- Q. i% O
        }7 z8 t; ~" ]- O  [* i4 S
        // VRC7+ k9 K! ~( L1 s" n/ B$ L
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {  v6 v4 e3 @0 N2 y6 @  _* {1 n) |
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;" M* `3 w5 O) U0 d  k& b# j& o6 h/ D
        }/ @3 x1 Z! u5 k& E+ X( P5 G
        return        0;2 R$ c, P& j" N6 I; x
}9 k" h7 Y. J/ F. X( l, D% ]
2 [7 Q8 M7 {4 R- T/ |: e- ?
// State Save/Load0 R7 s8 T. {% v# L7 H7 D
void        APU::SaveState( LPBYTE p )" K# A0 @4 L7 N" q& d
{
+ J1 o/ z( R2 U% X  Y#ifdef        _DEBUG, h- o5 m5 n8 A! z. q: L& c7 I# ~
LPBYTE        pold = p;
) @4 E2 M( x8 R6 Z$ |6 }#endif. @, o6 v) p/ n' h
9 _7 K* V) _: j8 o3 T; P
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞; n: p, s+ Z) _. a7 ~1 `+ n
        QueueFlush();
/ Y3 ?; i3 {) c$ d* g8 x7 y6 }' l* V2 [/ d
        internal.SaveState( p );
$ i: K/ p4 t& H( _& G  s# f; r        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( K3 ~1 @$ H  L: Z4 [; n/ U6 W

" n! @$ y' ^7 d" ]) K7 \        // VRC6
) q7 g* Z' @% [9 @2 i  Q9 ]( [        if( exsound_select & 0x01 ) {; d, W* F0 l* {
                vrc6.SaveState( p );( Y( S0 _% f$ e( D5 D% w
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' F+ m* f. M- @7 f: b        }6 o( ~& I4 g3 o) ]/ _/ A
        // VRC7 (not support)
. n2 n/ i* Z( k7 i. @3 U        if( exsound_select & 0x02 ) {
- \9 x4 O1 x. e1 }* B                vrc7.SaveState( p );& ?" R, u3 T( j" {% r2 j/ k% k
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' g1 }9 D1 f9 _6 s3 ~% L# J
        }
: Z% {" w/ R0 G( u        // FDS  A7 B* h, q% @9 H# X
        if( exsound_select & 0x04 ) {
! @, G$ w9 ?( }* @: H                fds.SaveState( p );
9 L5 G1 [3 W0 M/ q" t: m2 F                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  [( V9 S# G& j* ]& L        }
+ Y7 Q2 t5 I" [  P, f        // MMC5
6 E7 c* \& L# u$ d        if( exsound_select & 0x08 ) {
( x! q. W4 p( {) d                mmc5.SaveState( p );
3 `/ i( ?( j( i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 u' x/ K# G! J% K/ A2 A
        }
0 Q& u9 I) R1 y. @        // N106
* A9 w& l4 e2 }6 M2 G3 j  H        if( exsound_select & 0x10 ) {
( P# W5 R( [9 G) g- b9 u/ ^* L* r% B                n106.SaveState( p );1 [& y& `+ ^* Q
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, H! s7 q9 Y) g! d# I  \+ O( d        }
) j8 W* e  `, \+ o" R2 ]+ D( j% W        // FME7
# f1 W3 G. }4 ?/ I3 b5 f# p$ J        if( exsound_select & 0x20 ) {
) d8 I! v3 A! R( @                fme7.SaveState( p );3 P& X( l# Q; z! w
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 C& |% K# J! ]7 t8 m/ }9 d
        }, N2 J$ |/ \+ z# H. g

, O3 V  x0 K' J" {4 b8 Q#ifdef        _DEBUG
6 I2 K7 X" c, U& VDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
2 S4 {- Z, }+ h: M  J* h) |+ \3 Y#endif
: U( d$ E# p4 _}' M3 T, @" M' }6 w: N9 D* |; t

5 a/ B+ l6 m; Z- t4 N! ovoid        APU::LoadState( LPBYTE p )6 F9 F6 `- D( s9 H% x0 i& y9 P% P6 s
{
4 U6 v9 D' _& Y2 V5 i9 c" j" A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡' l2 H, P' R5 G( x+ t9 `
        QueueClear();2 v$ }6 a6 [* L4 I

7 S8 @8 ?! D- L9 |& H        internal.LoadState( p );. Q* x! g4 Z0 A" i' `2 U: v
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 }* E7 Q' T! S: G
" }9 {5 X& F$ f. b$ C( P4 w6 c        // VRC6
' z+ K, j' q* p$ c        if( exsound_select & 0x01 ) {. Z; P) x7 C6 C8 Q
                vrc6.LoadState( p );
2 L/ M5 Z8 E/ H5 N. s5 H                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" {# w8 m* h5 D
        }4 a) q2 p, D- a( N
        // VRC7 (not support)$ y8 }. X! S* @3 g$ o* l
        if( exsound_select & 0x02 ) {8 m- n7 }5 i/ m: l- o5 p  w. r, e
                vrc7.LoadState( p );& b! x5 S7 W$ p/ \& F
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# h; F7 }8 T0 Z7 Z0 c  Q( `8 n        }
9 Q' v+ t. c" S        // FDS& x6 J- O$ D. ]) F7 l
        if( exsound_select & 0x04 ) {2 }! a. E% D1 X! N
                fds.LoadState( p );
* O7 h3 [: k1 I; x) q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding  N8 [) H9 }4 Q
        }4 B* P$ g% H& z& s( L
        // MMC5
/ t& |0 x& Z* [, k  T' c        if( exsound_select & 0x08 ) {" `% _4 C' x  v; l
                mmc5.LoadState( p );
( h" w' _6 @6 m' Q6 t1 X                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 E4 X/ J" @! }. h  q' n        }, V# Q( u' k$ ?7 Q. g% Z3 k- b
        // N106
/ D) q. O  i  `( l/ V        if( exsound_select & 0x10 ) {) ^8 j. `4 [" ~* j8 L. R* p
                n106.LoadState( p );$ _8 `- z0 f/ j' T3 t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, d( T' w: R9 y9 b1 m4 l% z3 [) q2 j
        }# s5 Q- W' E1 H% h' C
        // FME7+ s) I2 A/ U: U4 G* l$ k" d
        if( exsound_select & 0x20 ) {- T! G; F1 Y% g
                fme7.LoadState( p );2 |# w: C) Q! A1 Z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 A1 O; i: i5 D* L8 |# E
        }6 j5 B" M) U1 O3 ]" c- y8 F* l
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 4 k2 G" V- T* O
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。$ f5 ]9 F, o2 {) `1 N
感激不尽~~

6 b$ U: L$ d& }2 k恩 我對模擬器不是很有研究,
/ C' u2 M4 ^: J+ T3 `雖然要了解源碼內容,可能不是很困難,' a$ C6 @* K9 l
不過還是要花時間,個人目前蠻忙碌的。; n5 S" P$ {$ ~. s

" ~. u; m! S$ \/ q3 B. h給你一個朋友的MSN,你可以跟他討論看看,
4 ?" \! G+ |  u7 g" n他本身是程式設計師,也對FC模擬器很有興趣。
' b$ z) n, T" T
5 m* I$ u- s" M% U+ M+ z/ _& }MSN我就PM到你的信箱了。
9 [4 ]2 r- t) {7 [6 K) d
- G# f6 o2 K, h: T; ^3 K希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 * K( r/ R) }8 a1 f
呵…… 谢过团长大人~~
2 \, Q/ a1 X% i( Q3 S) ]) m
6 W# r% h- p3 A5 A5 p+ @
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
" ]3 ^5 F; Z3 t5 V2 P团长的朋友都是神,那团长就是神的boss。
; f0 g' {* I. S1 T3 Z3 r; r
哈 不敢當,我只是個平凡人,
; g7 a$ f* s) s: \+ R7 V要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
7 l9 C1 N$ O, h+ [$ |7 w& HZYH
" ]3 a, c0 o9 A, A' O7 MQQ:414734306* D4 {/ Z: ^3 K: W
Mail:zyh-01@126.com
# ~$ `8 q& s5 z$ X
/ [; M- G3 C8 j% l; w' M他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 r) q6 L2 {3 U5 \( z( m再次对团长大人和悠悠哥的无私帮助表示感谢~~

+ ]- w9 H& A! X% h/ ?! v9 `不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-25 05:24 , Processed in 1.108398 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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