EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?( p6 H/ Y7 q  N5 R  e* K
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
: I, x- J! }# P5 j# a0 G楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* J' t/ Y2 F: ^1 T% S  [! ?这里有相应的模拟器源码,就当送给大侠了~~0 f% r6 H& }7 [* s
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
8 E; J! N9 e: r7 T3 n能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
0 M1 g5 k, c0 M( g+ p楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( R% `' e  A' X& [+ R这里有相应的模拟器源码,就当送给大侠 ...
$ N  ~4 [7 z6 c. T4 R& N, r
聲音部分(Audoi Process Unit = APU):( L) n, v* q8 K+ b& J& c' p# h
.\NES\APU.cpp
+ \$ d7 n8 Z4 Y8 x4 @, O.\NES\APU.h
9 Z- d* x7 Q7 ]+ l$ L/ V5 j4 n

  C: u! _1 a' o# m8 \+ _0 o: U影像處理部份(Picture Processing Unit = PPU):
. ^; T+ T1 K9 f5 V  Z$ L.\NES\PPU.cpp  P5 M8 y' h5 S5 V6 b! x7 g
.\NES\PPU.h
4 @1 A0 k5 h& q8 S- e9 p8 N& P# S* ^0 }) W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
0 ^& L+ g7 Z7 f' E& y3 `(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% `, l* r; C0 G* ^* ^+ n  y  D//////////////////////////////////////////////////////////////////////////
0 _  r: \9 ~! _& |; Y2 O, s$ q//                                                                      //
) ~+ i' u! e% ?7 ~//      NES APU core                                                    //+ p; {' o/ T1 A1 H' t9 U
//                                                           Norix      //% S1 i8 L: Q% }7 `+ Q6 q6 m6 ~
//                                               written     2002/06/27 /// T& e6 s9 ~& E  D$ ]+ z; C( R
//                                               last modify ----/--/-- //7 A# k5 h8 u2 s
//////////////////////////////////////////////////////////////////////////  o0 X1 j& T" {$ Y# [! z7 V$ ]
#include "DebugOut.h"2 Z0 T  v9 U0 F3 `: y5 X
#include "App.h"
3 H5 j, A. M* Q4 ?+ P; E  _#include "Config.h"
8 e/ B- D+ B0 ]" F3 O. H
( ^! \  E" x; v, S1 f0 ~#include "nes.h"1 }( g" G0 m0 P# h: _6 Y1 }
#include "mmu.h"
  m/ }; ^5 [9 r; ^6 \  H8 d#include "cpu.h"5 X0 o. ?* C: }6 F0 X, Q7 j9 @
#include "ppu.h"
8 d4 C' |9 `, y- \/ \1 n#include "rom.h"+ U! g' S) B/ o8 D
#include "apu.h"
! ]* }5 Y, l% J0 b2 }0 J
8 A$ V# l0 p+ Y0 J! C// Volume adjust
# K+ U5 {  y$ m  X( k' }// Internal sounds
  o8 _5 m! O) D5 X5 R$ C. m  e4 O#define        RECTANGLE_VOL        (0x0F0)
3 B3 S" w5 N# h) ]% a4 N0 t#define        TRIANGLE_VOL        (0x130)0 k/ N+ |4 K+ b# B' {1 E$ W3 u2 w
#define        NOISE_VOL        (0x0C0)
2 {( W- A( p; Q$ m  S5 T4 p#define        DPCM_VOL        (0x0F0)4 G+ I0 |, b4 x* d" }0 U) p3 U
// Extra sounds8 |% Z- p/ H( W
#define        VRC6_VOL        (0x0F0)
4 m. Q' q8 O0 s. m; |2 b#define        VRC7_VOL        (0x130)
( J, w! G7 Z$ E# c# W/ c#define        FDS_VOL                (0x0F0)+ ~, u: ~( s) l$ I5 I" x; I; d
#define        MMC5_VOL        (0x0F0)  y: c7 }  V; k, I" S
#define        N106_VOL        (0x088)
3 c  i9 H* l( P" z#define        FME7_VOL        (0x130): u, F% O! l6 j$ c' P. v. p9 ^

6 U3 |: B+ \: }( |' V5 d) i$ @/ |6 N5 fAPU::APU( NES* parent )4 r7 p* F" Y- n  U8 `2 O: d, b; L8 A
{
" P4 L* Y2 e" q& T        exsound_select = 0;
* Q& C* E& O, B, X, X! O, A! {6 w& {- S
        nes = parent;0 @0 Q6 N+ g& d" P; i& ^( [
        internal.SetParent( parent );
& [5 K" E+ L7 N  o3 L* a2 D" e( P7 F) \7 W  m' g0 ~
        last_data = last_diff = 0;2 I1 K2 A2 Q3 q" K% g, Z% |" m
7 G! e5 X/ o9 e2 h/ Z
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );6 [3 s$ a" [! S

+ g- u+ z3 u5 C4 ^& {        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );2 k. q5 v3 ]7 N0 L8 ~' N. P' Q: M
        ZEROMEMORY( &queue, sizeof(queue) );
$ Y9 G2 ^' \7 M7 M4 I* j        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ Q) h  Z6 t; y) n- K( d, |* u# q0 f- |" s# M5 X+ m# S
        for( INT i = 0; i < 16; i++ ) {: @9 k. J2 u5 ^9 t8 x
                m_bMute = TRUE;& g3 _( g5 c" P$ f4 m& ?1 D& u) O
        }
4 e7 `' O4 Y- C% L' Z7 {}
* W% s- `, S& d; Z: {" B2 R
; R& c; T5 c) r2 e3 Z- dAPU::~APU()
3 i4 y9 d2 h3 z0 N1 P  ?5 B' `{" v4 X' \! s. D0 M( W- Z! [
}
( d8 L- N  E! d5 ^& ]% j# v
0 x- e5 ]8 R- Rvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ H- u5 R. v- g8 |{; `/ D* J8 E2 n. w
        queue.data[queue.wrptr].time = writetime;
2 t: c! V( a9 N' a0 Q( k; }        queue.data[queue.wrptr].addr = addr;& D: ~0 Y& J/ e1 O4 C
        queue.data[queue.wrptr].data = data;* i5 C# H6 X: V$ M- W4 x& u
        queue.wrptr++;
. b4 p# D1 s% ~8 H/ ]5 E( l5 q        queue.wrptr&=QUEUE_LENGTH-1;
% u8 ^/ i! @  @* `; W% g0 C0 H2 i        if( queue.wrptr == queue.rdptr ) {
+ N' b5 [, X* _7 N                DEBUGOUT( "queue overflow.\n" );
; D  T3 L" O. z  R+ q        }+ l* H0 V. ]. b/ ~) Y
}
4 V) W. a, N# L* Q* E' e! ^, j0 D, ]. B5 f0 f$ L7 f  S
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ). j$ U* ?& P9 a. e, y2 `& ?+ r
{
. e; K' e0 k% S! d7 a, j# j        if( queue.wrptr == queue.rdptr ) {9 d% j8 k3 B; ?9 E0 |
                return        FALSE;
# G$ R1 T7 l7 O" R7 [! C2 d- u8 g        }
' P( S6 l3 `$ {; M        if( queue.data[queue.rdptr].time <= writetime ) {5 r" Z) v8 l: ?% X5 i2 d% c" U
                ret = queue.data[queue.rdptr];+ r4 u( ~3 W# w) w8 P
                queue.rdptr++;0 F- S! q0 Y9 g" x( V) h7 j
                queue.rdptr&=QUEUE_LENGTH-1;
. P1 J1 `8 ]# ^' t- j                return        TRUE;# j: U6 w0 A3 c' b7 O( y+ F* b" ~
        }
# E- q7 m8 _7 N7 m        return        FALSE;
( ^  \& t( L+ g; |2 |- e3 @- r* [0 V, Q; f}4 x8 g$ Z+ \$ S7 ]
) b$ {0 h* E  U" Z! x; ?
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
& ?4 X/ Z6 Q1 q; d, P# c4 J{& Y/ ]) p4 x. O. R3 H
        exqueue.data[exqueue.wrptr].time = writetime;! E2 O9 p0 w! @6 `7 ^
        exqueue.data[exqueue.wrptr].addr = addr;. W& F1 d9 c5 N& V
        exqueue.data[exqueue.wrptr].data = data;
4 E( U( r8 [" _, d        exqueue.wrptr++;
1 e& x; K8 i9 T$ h  |  ~        exqueue.wrptr&=QUEUE_LENGTH-1;
+ t' q1 K5 C8 @' T        if( exqueue.wrptr == exqueue.rdptr ) {' e' f: V; x) ]6 ?" O  |) u5 ]
                DEBUGOUT( "exqueue overflow.\n" );
& m# L: y4 C. D2 V, o! c5 _        }
, e7 J; Y: k: N; w3 K, ~! _$ V}
  A. r% b/ }8 G  T* N; a+ D- C6 D9 Z6 m# @( K+ t9 H  W
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )& k: a) y; s. W3 i0 [& N0 L
{
6 g* Y- J1 x1 E        if( exqueue.wrptr == exqueue.rdptr ) {
7 M* i; b9 f& f: i1 \                return        FALSE;
% }( R0 O7 |( I! E$ ]6 _5 n        }
% V& Z) b5 ~6 \6 `  J        if( exqueue.data[exqueue.rdptr].time <= writetime ) {2 s/ U, ~) u  b1 h2 d/ X( e; k
                ret = exqueue.data[exqueue.rdptr];" S) g. o7 p2 ]* S9 J
                exqueue.rdptr++;: i% I5 a) x0 p( Z; z
                exqueue.rdptr&=QUEUE_LENGTH-1;
9 |$ j; `- y; P" k$ e+ {) n                return        TRUE;5 z' r0 u& {0 L- w, W
        }, ^; I2 |( R2 z0 P' e
        return        FALSE;
7 y$ e8 U1 L1 n2 m6 q}
4 f4 |" b# G" E  Y& ~
& F, o/ R$ I) _- d9 g, pvoid        APU::QueueClear()+ r* o0 s; W! P
{
+ m( T( \4 C( w2 {. s        ZEROMEMORY( &queue, sizeof(queue) );
4 O7 Z5 e( Y* A8 w, O        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 Y: J' |. ?, `* s5 W' B9 n( O
}
8 i; o' b& x) n5 z% z% K. p0 q* K
, X8 M" A( ?' M7 fvoid        APU::QueueFlush()
( }2 k) @3 X0 R{
/ u- e- o4 _" u) h% C. T4 W4 m8 G        while( queue.wrptr != queue.rdptr ) {
# L7 w0 I- p5 q1 g; Q5 B- e% W0 z                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) g1 T, w* \# h8 {
                queue.rdptr++;
$ ?; Y, F4 n- \+ \6 B                queue.rdptr&=QUEUE_LENGTH-1;) _! e) {3 |) _3 v. P
        }
- G6 i$ I8 m* n+ F3 A+ Q) ^
# f7 I  |# r. r        while( exqueue.wrptr != exqueue.rdptr ) {+ N8 ^( r$ O& ^! b9 }7 I6 @
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
( V8 g+ m" F4 q* \8 A% ?- x                exqueue.rdptr++;
3 F0 v9 m, C5 @- o6 c                exqueue.rdptr&=QUEUE_LENGTH-1;
+ |5 Q& O) G3 b0 u8 w+ `" ?, M        }
* t0 ?* x& h* R}
$ R) {: }" q+ L' f. G4 v# F7 N* q: P
" S5 J* u- X/ c+ C  s# wvoid        APU::SoundSetup()
* K- z: M5 f9 R+ i{
) u7 T# E7 G" R- C4 \3 v        FLOAT        fClock = nes->nescfg->CpuClock;7 N) R- w# x+ D! N% j6 m9 t* C
        INT        nRate = (INT)Config.sound.nRate;
7 T4 s  b. L+ a8 Q        internal.Setup( fClock, nRate );
4 \# M( {3 ?% z2 k5 t1 P        vrc6.Setup( fClock, nRate );) K7 Z# N/ e/ Q7 |9 ~
        vrc7.Setup( fClock, nRate );
" {7 u6 p/ ]" i0 C# }        mmc5.Setup( fClock, nRate );
- t% d* S  n. y, f9 u- U2 r2 r        fds.Setup ( fClock, nRate );
. I8 d: V/ x/ V# y        n106.Setup( fClock, nRate );
9 k+ ~2 H& q* p; ?' Z        fme7.Setup( fClock, nRate );
# Q# m% Z& x- c$ _}
( p0 H) z0 |! G( ~! P7 B1 q2 K) Y/ ?( L/ l/ u. B2 m  \
void        APU::Reset()
" F6 R8 r/ C" s& }* l/ ?$ O{
8 q# Z' b, e; A) r        ZEROMEMORY( &queue, sizeof(queue) );# l$ ~6 j& X1 R4 g! n# C
        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 i/ O  ?# ^0 v9 B5 Y% D

+ ?2 v+ A7 s0 @! N        elapsed_time = 0;! v6 V& \# ?- Y6 i6 ^
  V$ _& k  ^7 r# v$ N7 \  d" c2 P- X
        FLOAT        fClock = nes->nescfg->CpuClock;
3 b8 K) S5 q/ k. U+ Y        INT        nRate = (INT)Config.sound.nRate;8 y# I' E% ^4 q8 S1 `
        internal.Reset( fClock, nRate );
8 c/ e* v1 ~2 _% `0 {        vrc6.Reset( fClock, nRate );
' K6 C$ |* W6 f  t$ t        vrc7.Reset( fClock, nRate );
2 n/ Z8 y/ g& F% Q6 b" B+ R" `        mmc5.Reset( fClock, nRate );
' L! d  `% q5 Z: y, b        fds.Reset ( fClock, nRate );* n$ v! k6 [' M! b% ?8 i
        n106.Reset( fClock, nRate );
7 E, M0 e3 h' q' i        fme7.Reset( fClock, nRate );
  y2 z: @/ _$ y* k5 X3 B9 s+ R( ]: }& M
        SoundSetup();
& j" k+ [' T; H; {0 [+ @. I}5 H6 Z0 b' d) Z

% `" z% u4 F! j! Jvoid        APU::SelectExSound( BYTE data )
# O$ b1 S2 w! A# w' S, v4 y{
) K4 ]1 r8 O8 _, M0 `5 m        exsound_select = data;7 g; P' I( i" ~" U! L# c- o
}4 E7 ~7 {. U. N7 g  I  M$ s! J8 H

! B4 h, a- O5 G) P( @7 }9 vBYTE        APU::Read( WORD addr )
! |& D; B& T9 U* Z) }{* i/ A6 |# e4 K% v- j
        return        internal.SyncRead( addr );; u2 e% c% t$ p+ E, J( w( f% U
}) C7 B7 o: T# q# G

+ k% R# `7 a! U4 cvoid        APU::Write( WORD addr, BYTE data )7 P* f5 x& {; L' \, O
{
! x  O: o6 M( q8 \; K5 ?; b        // $4018偼VirtuaNES屌桳億乕僩
( K- T) J: \* p* V; H( m        if( addr >= 0x4000 && addr <= 0x401F ) {
- `' Y, O) ]! W1 u+ W9 s) j; m$ ~                internal.SyncWrite( addr, data );
/ H2 v$ v( U0 h, S6 D. q* i. E# d                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
! |8 U" Y, Z2 j1 q8 h1 w        }
- }: y; s  o+ a9 T1 x}
: t6 i' K8 T1 I( {
" u) n% [5 L1 r8 N+ zBYTE        APU::ExRead( WORD addr ), ^" @/ t9 @. p% Y( }- Q9 y+ _8 x
{
2 r2 ?* Y0 e& e' rBYTE        data = 0;; O! q! P0 E6 p1 z; W* R

5 ?$ z; F. r$ K8 X2 y- C0 x, p7 l        if( exsound_select & 0x10 ) {# u  a0 J; o. Q6 h% d8 y
                if( addr == 0x4800 ) {
2 J: q: L7 Y; _1 j1 P$ a                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
' n* m, y; h" `1 l1 j                }" n$ E9 f& v* q% m/ ]
        }. t7 t6 z: j$ X0 k* x- m2 E. E
        if( exsound_select & 0x04 ) {
& O* e2 z2 B% `) x                if( addr >= 0x4040 && addr < 0x4100 ) {
  @0 Q0 j, l) D7 U2 ]4 x                        data = fds.SyncRead( addr );( x9 O1 V+ L% m% s. ~  G
                }
6 A. b# H" s/ m# J) ]        }
$ X* _$ k) ?  r; S% Y8 V        if( exsound_select & 0x08 ) {
4 J/ N/ @& }# `$ O* ]% L                if( addr >= 0x5000 && addr <= 0x5015 ) {7 X1 T+ p# C* ~& {  h
                        data = mmc5.SyncRead( addr );
9 i& p9 ]$ i4 d  B0 d: R* e                }; u6 q8 x) R3 c: ?' i7 j  L
        }9 Q, ^" w3 z1 R9 l& B  H

2 ~! g# @2 ?" ^7 v  g5 T        return        data;
6 |8 m' R; e* n# w6 W+ O" p}! t  v( S; U* f: ^5 _9 r" S
% l# M0 J. I* h5 @1 r, @8 ]* Y  t
void        APU::ExWrite( WORD addr, BYTE data )
3 ~8 t5 h: j% {# c, m' T& Z( w' F) i{
, e# Y1 X" @' n5 `$ ?2 r. h  W        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );; a  L  z( v7 O& M( _% o( i' {
0 N; R9 f( O% p5 d
        if( exsound_select & 0x04 ) {
5 r4 ^. q+ v; X7 f2 Z+ K& {                if( addr >= 0x4040 && addr < 0x4100 ) {
0 K5 m' Q1 w& x) E. o1 E                        fds.SyncWrite( addr, data );
* A$ J* f  B. c' R! t) R, c                }
2 p+ R2 A3 B7 i6 U! z2 ?        }
8 D& V' o8 N  P4 |8 C) Y8 O8 |0 [. l6 |6 t% u+ r
        if( exsound_select & 0x08 ) {
+ o  N6 ?7 g% }# b0 ~                if( addr >= 0x5000 && addr <= 0x5015 ) {
  j( R$ e) r  M8 Y8 ~6 f                        mmc5.SyncWrite( addr, data );
/ X0 L, a3 I. m9 h& W' H% i5 `                }) n+ R: a! A- |1 {2 J* Y
        }0 e5 ^" `; M* N% ?, i
}* D* N0 l* v5 ~+ ~: W6 ~$ j
% j3 {. X( l' X0 O4 A' a; }
void        APU::Sync()" S& ?4 D7 F- t$ X' N" j8 H
{
% V" u4 J* [* P}0 M9 r4 y' m$ u) Z3 V' W& A

; [7 N/ m2 L. e" s% t* X+ U' Yvoid        APU::SyncDPCM( INT cycles )
: E5 F1 A" ^4 R( r) O+ |{
* a$ |, v( P, w* i. Z4 O# c        internal.Sync( cycles );
# ?3 V  `+ b% `* D5 P: p5 s0 m5 I6 J- ]' X1 ~4 j8 n
        if( exsound_select & 0x04 ) {
7 p9 m1 D( a  S- s/ x+ U                fds.Sync( cycles );& M2 g6 H- A! m" N. Q9 }" `
        }
; D9 o: N3 n3 Z! v# Y) K) T1 z        if( exsound_select & 0x08 ) {
$ v- i& B& ]; I. g4 H  b                mmc5.Sync( cycles );
1 d1 M$ |% p; @        }# O7 S. E6 o' U- c4 h# \
}9 O$ r. g' ~* x3 f" L3 o- @

3 ~5 a. u) U2 U1 o# f1 s: T( avoid        APU::WriteProcess( WORD addr, BYTE data )
1 [. t$ G5 S6 r% c% S7 e{+ u( D$ o$ J% F+ M. E; H
        // $4018偼VirtuaNES屌桳億乕僩0 t9 Y8 \1 l4 ~- x9 E0 F
        if( addr >= 0x4000 && addr <= 0x401F ) {# A! M2 s* k4 l$ f. X
                internal.Write( addr, data );# L( A; P2 O# M4 m- s7 V$ w. r
        }
' l/ O: g$ Q$ {4 l- r. @* @}0 R% b! I2 K. m. \+ p' G
3 Z2 ?" e! U! w0 u0 C+ r
void        APU::WriteExProcess( WORD addr, BYTE data ). I3 B# |( O. C2 E+ V
{
$ q) R, X9 ^5 N; }8 m2 I; D        if( exsound_select & 0x01 ) {1 {: w/ G% h3 p
                vrc6.Write( addr, data );5 j; E' t. \6 X" `8 L" {
        }
4 d& t2 }* r, D2 H% q: [9 |        if( exsound_select & 0x02 ) {
: U" r3 Q$ `" j8 H9 ^/ K. A+ r                vrc7.Write( addr, data );- a, O3 T+ _7 p, S( z1 @1 ]! B
        }
- \, L! o' f9 {+ M$ n8 M* O4 S        if( exsound_select & 0x04 ) {2 K) F' D8 u# U, [; t
                fds.Write( addr, data );7 v. l6 ?% _# v+ c
        }/ T- Q$ q. Q( a& i4 x; x
        if( exsound_select & 0x08 ) {
& Y( M2 T/ p& M  P, f                mmc5.Write( addr, data );0 A( q' a0 C. u
        }
6 L/ G% ^, a1 `        if( exsound_select & 0x10 ) {1 j; r# D2 G( ^# P1 C
                if( addr == 0x0000 ) {6 T3 T) {9 d) y$ O( D* N
                        BYTE        dummy = n106.Read( addr );
! ^; G6 A. U3 P5 P5 P1 u                } else {; ~& U" A" Y1 `/ _  w7 |6 `3 s/ L  ?3 k1 Q
                        n106.Write( addr, data );
/ ^# ?# r  Q) M; d                }
1 _8 P. K" l; z        }
: a! E/ T1 r$ Q3 Q) |8 u        if( exsound_select & 0x20 ) {4 x) S. u; J- t5 @3 ?+ c+ O- q
                fme7.Write( addr, data );* t( B0 `) C8 Q7 [1 B) D3 s
        }
: Q' _8 V$ {1 x& P5 k) a! N% Q}
3 c6 l0 h4 n; E& K3 I( ~
$ y; M' y2 K! {, k7 b+ L  @( Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
5 G, k7 `' r' A6 t4 N. @8 b- p4 D* D{
& O! Z* M; z1 O& MINT        nBits = Config.sound.nBits;( c; Q( H0 K2 F
DWORD        dwLength = dwSize / (nBits/8);9 M7 Q  x  M) ?8 @- f; p! X% k
INT        output;0 N6 l& x" E6 w$ d( v5 u2 e
QUEUEDATA q;
% `: s0 {% P. P; \DWORD        writetime;  @2 B% o) D4 k- \
2 o1 v5 p1 b- {; \9 K% b, T8 E# ^  c
LPSHORT        pSoundBuf = m_SoundBuffer;; \& a+ ~0 h4 D+ ]) g: q
INT        nCcount = 0;
8 x" V, g/ C* J3 p! [; H  K9 I' d
INT        nFilterType = Config.sound.nFilterType;
6 Q" j! w8 A8 D# J- y
) o4 c& |- d% J* ^. g        if( !Config.sound.bEnable ) {
/ C) s) a8 \9 X; g! K# l                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* o6 ~+ G$ e' r. Q                return;. f* }0 L. t$ g( @# s# \9 t& i
        }
, x' t. K5 Q+ B" L6 f5 k
) D0 `. k& r- x7 a( u( K: Z+ G# h        // Volume setup! Z' I- d( C3 \6 Y9 e* d
        //  0:Master
2 Z7 A' ?; [# O+ [* J% M        //  1:Rectangle 16 j3 K( ]% X+ w) ^
        //  2:Rectangle 2
. ?) }/ k: h; r! _        //  3:Triangle+ _2 D+ ^  e+ Q/ Z& i
        //  4:Noise& Q( a( k- _1 v% ^/ b. w0 g& ?
        //  5:DPCM
9 M5 b4 Q8 i+ R        //  6:VRC62 u7 z4 w3 m' \  k8 C, a1 w+ h, l
        //  7:VRC7
! e! ?7 O: v$ j; M( Y$ t        //  8:FDS' L8 [" U4 s3 T/ `+ ]
        //  9:MMC5
- E% K4 G1 W  @, p! [3 K# i1 _; w        // 10:N106. z! \, A4 H8 I) V& ^3 O9 [. T. K
        // 11:FME7# ]( a( T& F; Y$ s
        INT        vol[24];, \" U9 X! A# A+ \5 s* [, u. D1 F
        BOOL*        bMute = m_bMute;
+ W# Z2 l- Z& g4 Z3 p! z/ |        SHORT*        nVolume = Config.sound.nVolume;, V3 v4 S/ K; n3 G: _

5 Z8 _, B1 {0 H' n        INT        nMasterVolume = bMute[0]?nVolume[0]:0;6 m9 E. |: B! Y8 W3 t4 Z+ u* d# s! v

2 i' m" S- X  ]' D: X6 F        // Internal
" B: k# f( P  U7 }8 s        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
! c* y# A! M  Q. A9 Z        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  f, d2 d+ F, s' h
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;: i9 i0 }, a! }  F
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;: V5 R* v5 a  j
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
3 B: r3 ?: L0 M9 D
7 U# p% a8 K8 |! ?; d. O1 c, j        // VRC6
2 v% J1 l. m3 Y6 u3 t        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. }( l8 C* i: Q' `" x        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( V" g+ M( L- N9 R        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, A; {0 x" ^7 T: y- K+ N& a, z
, I5 E( z: I+ z6 R6 ?5 n        // VRC7
6 I+ \& d7 G, ?/ n/ e7 D$ V1 d        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
+ |3 ]- k+ k# g$ z* c' N3 K4 K% K$ z3 d0 N  h5 y+ `
        // FDS
9 x+ ^- K" A$ I  [' i# J% o        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
% p8 q+ T9 \& J. n" e" U7 E7 H; L$ G5 [5 x4 W3 O9 p# t3 J9 M
        // MMC5; E& j# O- K3 g
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  g3 F+ ~9 N. a; R- L
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
7 \# u; P0 x% a# Q* U        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, E+ U; E  c  }0 j- s! A

, Q& O, _; d6 V( c. P- p3 c        // N106, s. a7 D1 u2 \) i
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% e; d# \5 ]8 f5 @7 d  v, q3 p
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" e. g- C7 i# d: i( d
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ Y3 x. D* d8 \6 u
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( X2 K+ K. p5 a* |% h+ S
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; P% W$ J& |; Y$ K0 p7 ?        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  ~& M6 R8 A: ~, i2 a
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 y4 q! G5 u2 h0 q% s$ U2 V' g
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  W8 U5 d+ ~; }- f) F
7 i7 e* N# k% h0 @3 E" Y% n        // FME7: g5 A, ]( d! a. l3 ], g- m
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, m. i1 E  V6 e! C/ h
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; e! x  m. a9 r  H, B* Z        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 {2 O# ^7 a6 v8 X  x

4 k4 G4 N+ p* m# S0 |( n5 B//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, [+ H/ v1 m0 X. x3 t! c
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. ]& A1 x6 O7 X% @
  S% D  P2 L. z. w% a# }8 h        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟7 t( S, Y7 R! f$ h  x& i
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
4 D7 x5 e) n6 [# e( f3 N                QueueFlush();
8 E) X: a' f" b- I        }# U) J* F" W: t9 ~2 r& s0 F1 x
. Y* W  X& \& j1 ?% @
        while( dwLength-- ) {7 l) V- N8 C! E5 c) P
                writetime = (DWORD)elapsed_time;
2 C' {/ t( r. Z1 x) c, u  V  k( x( P
                while( GetQueue( writetime, q ) ) {
7 q! k/ o! |( j' A5 d                        WriteProcess( q.addr, q.data );
+ A' p* @; C; o0 h0 w2 K                }
$ Z* T# q) w% I7 l! q2 @
# ^* g( t* U( V( e                while( GetExQueue( writetime, q ) ) {& g1 I) |! T9 o+ Y0 L$ K4 i* v( H
                        WriteExProcess( q.addr, q.data );
: h  C. `, w4 ~3 a' \                }
8 k$ X$ `' T7 X2 t3 S
4 r/ ^/ i8 ~$ R- ~9 Q9 I- F) {                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
  r! C+ H/ j2 u8 a                output = 0;
- j& I. \! k5 h: a+ o8 ^# V! u' x                output += internal.Process( 0 )*vol[0];) s( A" t2 s' p6 \# s( m
                output += internal.Process( 1 )*vol[1];
8 x' u& [0 R5 L! n                output += internal.Process( 2 )*vol[2];
* o$ d) X3 ~8 ?                output += internal.Process( 3 )*vol[3];+ I; \- `8 d; c3 W2 k
                output += internal.Process( 4 )*vol[4];
& |! ]) R9 k5 B$ T( `6 Q7 G$ W! U- r: N: W
                if( exsound_select & 0x01 ) {% ^' ^8 t& ^3 ]2 N3 u. v
                        output += vrc6.Process( 0 )*vol[5];; ~/ n* E4 {+ @- H
                        output += vrc6.Process( 1 )*vol[6];" f  w5 L- m' W0 u
                        output += vrc6.Process( 2 )*vol[7];
+ d+ L% Q+ e; D1 E, T( ~$ S                }
7 B1 U3 O" d# _/ y+ ^6 j                if( exsound_select & 0x02 ) {
* d" A/ [+ d% @/ F0 @; B& D                        output += vrc7.Process( 0 )*vol[8];
4 k9 |$ d  o# J, |) E                }
' a# _- i* Y# O5 C                if( exsound_select & 0x04 ) {
- l/ m" v" Z& X( j% J/ M+ ^                        output += fds.Process( 0 )*vol[9];4 U% E8 q6 N9 R
                }
: m- ?" Z! ?8 z4 s: ]) s+ a* q                if( exsound_select & 0x08 ) {
! R. C! T! |0 {, W+ m# c3 H& |                        output += mmc5.Process( 0 )*vol[10];
  r8 s3 {: V" F/ E$ z* L                        output += mmc5.Process( 1 )*vol[11];/ a9 r( Z% Q6 R7 y' C- k
                        output += mmc5.Process( 2 )*vol[12];
8 V5 E$ @# _" U, T' D9 t                }! \4 ~6 _3 m4 T/ I  w
                if( exsound_select & 0x10 ) {$ b/ J5 T( E1 e! `6 s8 a- R; p
                        output += n106.Process( 0 )*vol[13];
3 @2 v( X: c9 `; A% s( E                        output += n106.Process( 1 )*vol[14];
2 \! K) g; D6 ^6 f$ T+ H4 d                        output += n106.Process( 2 )*vol[15];$ Z, l6 C9 ~9 L& v
                        output += n106.Process( 3 )*vol[16];
5 b5 }& y# C; p. U# V                        output += n106.Process( 4 )*vol[17];
) K/ o9 [, j9 k0 e                        output += n106.Process( 5 )*vol[18];5 E7 [8 p/ U: h+ v* l+ O8 R) {
                        output += n106.Process( 6 )*vol[19];
; S$ q5 ]0 G# v7 L3 \' y. l- m* X& j                        output += n106.Process( 7 )*vol[20];
- f1 O0 U( ^6 s5 L2 }* \                }
# g. t* c; o1 O$ J& x, s+ ^                if( exsound_select & 0x20 ) {3 Y- \3 V0 k7 D
                        fme7.Process( 3 );        // Envelope & Noise: {. I" _& [6 L0 Y# G1 j
                        output += fme7.Process( 0 )*vol[21];9 R- @% }& }/ C# W5 ^4 U; p
                        output += fme7.Process( 1 )*vol[22];
  f' r! j4 W$ |3 Y                        output += fme7.Process( 2 )*vol[23];/ e7 s$ ]* s4 |. ~6 w
                }
. L+ J  O  T  P1 O8 m. W' e# V
5 o" d1 i( O% {, s. f0 B                output >>= 8;
3 ]6 f5 J( j! a  I# E% Y4 d) t& g; a; k/ |6 S  Z, P' o& g# T
                if( nFilterType == 1 ) {
& {4 s% E) E$ C* _                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)) O' ^  T: z3 y& L" w! q* v7 Y& P
                        output = (lowpass_filter[0]+output)/2;
. }4 a# S1 e7 x9 Z$ U& X- }( T/ L                        lowpass_filter[0] = output;
' k3 L+ t, R2 e& C7 x                } else if( nFilterType == 2 ) {
0 h. H: w% [" B, s" o+ P* j; b# ]                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
  A4 o! P# `- h8 x# ]$ G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- i: O& a' n/ D5 A1 Q1 T  e% o                        lowpass_filter[1] = lowpass_filter[0];7 C- v5 N7 @" Y( i
                        lowpass_filter[0] = output;3 z1 c9 D  x' X4 n  n6 W/ T1 q
                } else if( nFilterType == 3 ) {
5 {1 W$ N0 U- y# Q" ~                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)( o2 \: q1 O4 J' l$ G
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;( E4 _7 h: n% {. W
                        lowpass_filter[2] = lowpass_filter[1];
+ w1 C; U  N, T0 D/ h+ z, d7 J                        lowpass_filter[1] = lowpass_filter[0];
) L" {8 V0 V! X' \                        lowpass_filter[0] = output;( t  p! i3 N9 e, B, Q3 T( o
                } else if( nFilterType == 4 ) {, Q' p6 P$ J- M" x
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 P) l" q7 p( }7 p5 M% G8 i
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* Z/ D1 x7 q( F9 ^0 q                        lowpass_filter[1] = lowpass_filter[0];
" o1 c! ^* m- c6 a" Z* u                        lowpass_filter[0] = output;/ p0 i: ~3 h5 m6 n' ^
                }
0 p0 C# X( r9 e* S& H- ^: L" i6 p# ~! J/ F3 M1 T% g4 j
#if        0
2 T5 p& U; U& G0 j6 P5 G                // DC惉暘偺僇僢僩; A2 \" n" Y6 m  h- O
                {& Q& H$ f+ m3 W, U
                static double ave = 0.0, max=0.0, min=0.0;
( R0 ^) T; [+ D, M+ m9 X                double delta;# V0 |; j6 _' P4 D
                delta = (max-min)/32768.0;
7 F# V& {; _  C8 \- |" U" l                max -= delta;
! V& X4 [/ b7 M. B                min += delta;
& R$ h7 i9 J% w- G6 d                if( output > max ) max = output;. ?7 t7 {" [) X9 U6 X5 d2 m& Q
                if( output < min ) min = output;
* Y0 Z: s# w  @. A                ave -= ave/1024.0;
; n% G* g0 ]7 ]) D; ~7 g                ave += (max+min)/2048.0;; m* Y1 C8 m2 e3 d$ S5 |8 m( J$ U
                output -= (INT)ave;5 d8 I4 f; M# J* M( H2 m3 }4 A  Q
                }
; R7 B2 F( a6 Z3 t4 q- J& ]- U% g6 r#endif3 i. A8 J5 b" b( F. U
#if        1$ o* {# ]: u3 _: ?6 S$ v# A
                // DC惉暘偺僇僢僩(HPF TEST)" M$ V; O3 W6 v$ p2 D
                {6 N* _" L& H& P1 K7 e3 D
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);, _% Q7 \6 I$ p! u
                static        double        cutofftemp = (2.0*3.141592653579*40.0);* n+ J  |! i( D0 e, s
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
. t! w+ i' Y5 [% ]1 @+ j' v                static        double        tmp = 0.0;
! y- u) Z* _+ f9 e' P                double        in, out;
% i5 N/ ]9 r! _" I/ N8 Z7 Y: }5 H  E+ |
                in = (double)output;) Q% B( v6 h8 k- W9 e
                out = (in - tmp);
% O; d- y' K: _( V                tmp = tmp + cutoff * out;6 Q. J- M% r' p
, C( k. B2 D- {6 {* z7 R
                output = (INT)out;- ^* M9 [5 A+ J  M# p6 w
                }$ f* o- f" M0 X" H2 f
#endif, E* k7 o: n' @! ^* i; N2 N. `
#if        0
: a, t, k5 }2 [( y" A. \                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
3 F6 f: U4 R; V: h- C) d" I                {
& c+ Y; V" ?7 B7 g2 R+ G& y  S9 Y                INT        diff = abs(output-last_data);
% M4 X  o. k: I. {% _                if( diff > 0x4000 ) {7 R  V; v; i8 `. Z' j" ~
                        output /= 4;
2 s5 |) o. D5 w0 q/ ]                } else 8 ~! w3 M5 j8 V) l, I( @2 L
                if( diff > 0x3000 ) {+ u5 |  q7 y4 m, S$ k" {$ ]
                        output /= 3;
" J$ C+ M* R6 w; ]; e( U/ P3 Y                } else3 [7 b4 {% e7 u; r
                if( diff > 0x2000 ) {
7 N% w4 q6 I8 ?1 x' w/ i. v                        output /= 2;
6 U. l7 D- F( {2 W- m# f: M; z                }$ ^3 L: I' S( j- z, u
                last_data = output;3 D" F' r$ D7 ]5 }+ d; S
                }) K' m* }: D) ]& E9 Q8 A
#endif$ s; T% j$ J7 G) t2 k& [
                // Limit2 `2 E, J+ F, z9 C
                if( output > 0x7FFF ) {
4 n2 |6 P) P7 H4 h                        output = 0x7FFF;
+ L. W- O& a' z4 X0 B1 ]: z                } else if( output < -0x8000 ) {+ ~7 L% p) N9 i! l* S9 p6 G
                        output = -0x8000;0 p9 _: W! s- E. `7 ?1 F
                }
+ V9 o9 `$ i* G* v
: `' r) z5 ], z) m# d# p                if( nBits != 8 ) {
; v4 g  ]- Y6 s# e* I2 C, Z                        *(SHORT*)lpBuffer = (SHORT)output;
2 r8 \& n+ t- Z2 {                        lpBuffer += sizeof(SHORT);
4 O$ z8 w6 J! B4 c                } else {& {% F0 p" K- V3 F7 B, m
                        *lpBuffer++ = (output>>8)^0x80;
- ]# Z+ S9 z, Z& ~) V  o                }+ U; d" m6 U) w$ g: ]5 j* ^
7 Y" ^/ r) x6 ^4 K
                if( nCcount < 0x0100 )
! M) H- L  G- s1 g1 o                        pSoundBuf[nCcount++] = (SHORT)output;
# D9 x' T% {/ \
5 x' T0 A1 D. ^8 D' }//                elapsedtime += cycle_rate;
8 l9 B1 z/ \1 _: r                elapsed_time += cycle_rate;
3 I- w" G  q& q6 ^+ F        }, R1 W, d8 h/ x9 y+ g- g
+ s; s8 h& a  C5 D
#if        1. m$ w) Y# d1 y, M7 v
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {" B1 A, `1 j; ~* [
                elapsed_time = nes->cpu->GetTotalCycles();2 j  c7 `& W& H, o
        }, J# k; C% o6 ]$ C1 R+ F) m
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
5 C: ]1 u  H$ g! J1 g' }" [                elapsed_time = nes->cpu->GetTotalCycles();
* i/ R3 m( B: A, ~5 m. A        }
2 G* ]; q( d  G) [; {  `) D#else$ E) e) S4 f! p! k- ?. C
        elapsed_time = nes->cpu->GetTotalCycles();% Z) L9 b; R& i; G$ i& M, b
#endif" {. B4 j3 D- ~& ^
}
* A. j* \$ H) k- v" a6 m, s* t2 j( R, i
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 V; @1 m3 o' n# x$ n$ a+ c) cINT        APU::GetChannelFrequency( INT no )( m: J  ~$ ~5 P* r
{7 R. a6 l5 k) w1 @& A
        if( !m_bMute[0] )
$ [3 [2 T& p9 p- r! W                return        0;6 G& U) A0 I/ R& h
, \2 P; q, _1 e( o: r# [
        // Internal) z! Z1 d0 V. N
        if( no < 5 ) {
+ i5 S# w3 q- I                return        m_bMute[no+1]?internal.GetFreq( no ):0;
' U7 I# a/ n% G: R. P5 p2 I* C        }
: ?9 ?5 L8 A3 X. q3 T        // VRC6
* D( I: u5 h1 k        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {/ q& }4 [$ A/ n& K, m
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  B4 I2 q3 g; \; p8 w
        }
. J2 r+ `6 d/ o        // FDS7 n. R* J0 f7 A8 w& a2 b
        if( (exsound_select & 0x04) && no == 0x300 ) {
4 R6 A. V/ c7 X+ A6 n! o: E                return        m_bMute[6]?fds.GetFreq( 0 ):0;8 ~* _( b& C& o1 d( {7 _3 Y7 P  J8 z
        }* t' F% c; `+ h* \( s% h/ ]
        // MMC5
( O9 D$ y8 U: O/ k6 {        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {0 }6 w: v# [/ k( |. @' d+ x2 a
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;( H6 V8 o! b4 T; g
        }; S/ o, L/ o* G) |- f; _
        // N1063 C$ M* \+ t0 s4 R
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
- l1 f# y* @; y6 D' E                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;* `; E& f1 y; d; y
        }$ T- _( H/ b2 f) s: g' ?
        // FME7
9 ~( a- P( J' L3 M5 ^        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 F  {* ^. r; v4 z6 G8 X) u                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;! q5 T- X' L+ _  L$ m
        }- `7 y. b$ j* p# S
        // VRC7
7 a9 y- y3 b/ B& L" g( ]; C! w        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
3 X) y4 F" b4 [" m$ c                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 U! v( b; l. W# J7 c# I
        }" ^7 m# b" E2 r
        return        0;
3 p& R# w+ @  u  r- A2 {+ L! i! p}
% M1 m1 J2 D) n* w9 W' C& B, u# }
. m9 U/ C# o; u. g' Q7 y- c// State Save/Load
8 U! }3 ?4 T0 i! R9 ~; Hvoid        APU::SaveState( LPBYTE p )
, ^3 R4 ?/ V# E6 H8 _7 U{& U) Z" [- o8 |1 n
#ifdef        _DEBUG6 A2 E. B; C, y# P* b, {
LPBYTE        pold = p;
# M" c* l' |7 s! F7 P#endif5 d" _: V" m0 y) \8 G' U: |1 B

# q1 r* R: W$ x& E3 |        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
7 b& x( t) B/ o4 p: w/ ~+ z        QueueFlush();, `( }! H  Q' A. f0 T& W% ]2 m

9 X# V* C% Y4 r( {- b        internal.SaveState( p );5 @7 Y% k. v7 }2 M
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ p, M  k# z) g6 ?9 l3 j* W1 n- d" V! k7 K
        // VRC6
% f6 x$ l2 P0 w, v, g) t        if( exsound_select & 0x01 ) {
" ?$ N- W! P+ Z3 R) [4 s                vrc6.SaveState( p );4 ?9 w  @+ h1 F" p( t
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: T, m5 |7 T; V0 t" i        }
; P* f0 K) m" p/ k& H1 j        // VRC7 (not support)
6 [7 U+ ~' w- m2 @        if( exsound_select & 0x02 ) {
, _3 g3 f8 G# z% b                vrc7.SaveState( p );
, b* u6 U4 B( E+ Z- K* |. [) f/ A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 Y# a# ^! i% |* Q& l        }
1 N9 L8 s; G3 S- L: U        // FDS2 v$ {) K7 a, }7 O! X6 c
        if( exsound_select & 0x04 ) {
0 n0 w# i- {+ p0 O. [3 V( @" V- t                fds.SaveState( p );
7 N6 ]8 ?) A/ f# ^                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% o: @5 Y- A2 s5 A- Y) y
        }
( f4 d. ^* C  {3 X% X& A9 a7 D        // MMC5
0 m4 u4 z$ l. A3 h/ E& a        if( exsound_select & 0x08 ) {& n, j9 C% _2 N
                mmc5.SaveState( p );
# p' [& O4 p) ~- k                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
2 Y- L6 ^6 n5 {        }
: M; I: l+ n  T: f1 e$ c* r( e        // N1060 A2 o1 Q9 T6 G2 i/ D
        if( exsound_select & 0x10 ) {5 x- i0 c- g7 X' f" `. |2 U
                n106.SaveState( p );$ W6 K  `% F- K; H
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# T7 M/ l+ l3 z! v
        }
" W* A4 O) \* l8 Q" t3 X# x        // FME7
  D8 o) n( x1 N9 Y" i        if( exsound_select & 0x20 ) {: z: y* d8 {3 _8 w+ g
                fme7.SaveState( p );3 X! J' z' z# g2 M: `4 n, j
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- u% D1 k, \1 X' T6 q
        }
1 |3 U# J+ h0 r0 p0 H: C
& Y: D  W$ I$ r  b- J#ifdef        _DEBUG' ^$ m' C$ {+ b& V5 R
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );3 E. S# r' m- N7 l1 a5 `0 Y
#endif
" U" [+ y4 f. n1 S& `! }; q}
* l" e" G8 n  m6 S9 e8 ~7 C- q; @) `, e) W" Z
void        APU::LoadState( LPBYTE p )
6 p+ M. r& M& K6 e{
0 S# ~3 y/ F# J1 r( ?: E3 i4 b        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
  h. p( A1 `4 u, `2 S        QueueClear();
4 }* W8 c! |' u& S7 g: J' J; a* b
        internal.LoadState( p );
, s. n: C! L. a7 c; |: L        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 i% _/ J3 e1 L: p- H1 `
2 E  L1 A6 d' L7 v/ m( r# I        // VRC65 [2 U# ^: I9 p, P: a4 g  R
        if( exsound_select & 0x01 ) {
7 ~7 Z% t; `7 @1 J: f                vrc6.LoadState( p );  t$ p  q. Y& C7 Q" \
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; A6 \; p& F6 k; x3 i# S. X
        }6 s5 Q4 D0 M0 y' h( |
        // VRC7 (not support)% O  V  k+ q% x  `! v$ N/ N
        if( exsound_select & 0x02 ) {$ @3 g) x0 R: a6 X6 b) U
                vrc7.LoadState( p );
/ D8 P& \3 X! M+ Y. u                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- P  Y( X/ |7 w
        }2 U& ]& X$ H$ }. T
        // FDS3 o: L1 \! y  B& A- y
        if( exsound_select & 0x04 ) {! R2 w3 f3 R5 h, p% n: N% R" x" \
                fds.LoadState( p );6 k6 Q+ B0 H' R8 G; @
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- @1 n2 U; H. w/ l
        }
4 g' _; h# R$ e3 i" `# H* j4 k        // MMC5
' y% E  X. P  }& @" J" C        if( exsound_select & 0x08 ) {  f  e+ {* Z& c/ G" v
                mmc5.LoadState( p );7 s! j5 F6 O' i: S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* w% D2 p) n( k4 y: ^  _4 m) j* i
        }
1 W) j% D: }4 E8 v- ]) u7 I. g; @        // N106
6 [' Z4 `5 \# C! X        if( exsound_select & 0x10 ) {
% q- i0 J& t: ]8 l                n106.LoadState( p );% O* X+ c0 m0 z( K
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
7 `: n! b8 @, \3 w4 D" v* ?        }1 p2 C: [8 F' f2 G1 C9 z! h
        // FME7/ H1 S8 A. h8 N0 ?! n  v
        if( exsound_select & 0x20 ) {+ K, _5 ~8 F, l, U# @# |0 V( }
                fme7.LoadState( p );# w1 m; G" h9 k* |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 q: I% B3 r" ?. V( `        }
6 ]% ]! P9 P+ G7 u' A/ H6 {}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 $ [0 _1 n) ~) ?, H/ j8 M3 D
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 F# f, @3 M3 o. ~5 c/ ~
感激不尽~~

8 z3 y/ P& z6 q6 N9 |1 i! j恩 我對模擬器不是很有研究,
, }$ I& B) W/ O) A7 ~雖然要了解源碼內容,可能不是很困難,
4 I; H3 d# L! {0 r1 c! Z不過還是要花時間,個人目前蠻忙碌的。# C7 P. }" P8 Y. c6 H! a' N- a, t

6 x% h# a8 S) F, Y" O; J2 z6 ~9 |給你一個朋友的MSN,你可以跟他討論看看,/ _) w  X! u/ L' S9 L6 h
他本身是程式設計師,也對FC模擬器很有興趣。+ `7 w% t+ B. r  J4 W$ D, R9 z' A( }7 P

; U; o9 {6 `! C; e! e/ M! Q/ |! bMSN我就PM到你的信箱了。
4 C% e/ t& S4 P) L1 k+ Y+ p- O) w  q& b9 N
希望你能有所得。

该用户从未签到

 楼主| 发表于 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* T. T. x4 t1 C$ h  Q$ {5 y
呵…… 谢过团长大人~~

  U$ g# A  Q( o  W! O8 M
( h* d1 g5 k: H: ^) F6 U9 Y2 C哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表   ~& H' I: D' Z; s  [5 y" S4 \
团长的朋友都是神,那团长就是神的boss。

: V6 Q0 [' F; j6 `0 F哈 不敢當,我只是個平凡人,' V/ O5 F8 r$ l
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙0 E1 A2 w: `" u% k, l' T% u7 G
ZYH) p& P, P# j; Z. z
QQ:4147343062 a( c" e2 w+ D
Mail:zyh-01@126.com
  b& }+ I: T! k4 \7 \7 l  i: m6 K9 r4 o
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 s' j- X0 k; I0 ~# S再次对团长大人和悠悠哥的无私帮助表示感谢~~

) Z" n8 q7 _+ W) y: w不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-12 08:59 , Processed in 1.084961 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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