EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 o& n; C, R. F0 U5 P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
- x0 e8 Z8 G+ M& x4 e这里有相应的模拟器源码,就当送给大侠了~~: M. q) M- M1 E: `7 _
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 % m7 s  n7 x( c  A: R
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。; T; F/ V" |8 J+ z
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' f3 Y% b* r+ A8 d5 D这里有相应的模拟器源码,就当送给大侠 ...

4 {3 S4 M! Z5 ~# z* g" Z聲音部分(Audoi Process Unit = APU):* R; k& \8 F: {- W% t* g
.\NES\APU.cpp
4 d4 P* N2 q+ r% K( i, _- D.\NES\APU.h
) O- c! k/ K1 b& x- |  w) u' ?& x+ ]; W/ C$ G

9 C' C* \, V8 v$ p影像處理部份(Picture Processing Unit = PPU):1 K& }. y' O. ^6 H/ n. I& ^2 ]
.\NES\PPU.cpp
# e7 [5 T2 C- H, H4 p) s.\NES\PPU.h
( G& y6 M% @* K) V7 K* s9 I( r
! T( V0 w/ i) f( c# y! L- t如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( N/ x; P- @+ `# w/ d3 W(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% M0 [1 T* A# E5 K8 g//////////////////////////////////////////////////////////////////////////( s& c( Q: K+ i( k8 T  f
//                                                                      //
, L4 y) w- S) s) B0 [7 L//      NES APU core                                                    //
7 W% N- |5 }0 z6 |* p//                                                           Norix      //
1 U6 P& n; R0 N6 D/ t' g2 l: J- u//                                               written     2002/06/27 //
; A) X, ]/ i4 `: g( s# [//                                               last modify ----/--/-- //- J5 ]. M) F8 v2 o" R5 j( p: d
//////////////////////////////////////////////////////////////////////////; O" `1 N+ m# }5 t  G% q
#include "DebugOut.h"3 S$ e; _- _6 ]/ z2 s  N
#include "App.h"4 t/ R! u# C& U3 C6 i
#include "Config.h"
* Z5 l% R+ W2 b
) v( [- m4 ?3 \/ r1 G( d( Y$ B#include "nes.h"
% a: t- ?" n; q! U#include "mmu.h"
  Y) w3 F# D( h& c9 K#include "cpu.h"& l- t. z2 D" k, H4 s
#include "ppu.h"7 M5 ?! W4 R8 u: n$ H+ @
#include "rom.h"
) N3 f2 |6 |. D2 x- t! I( y9 V( g#include "apu.h": z7 ~! _' O: x( D. H0 q
0 _# s; P  f. }: k! D" B2 _
// Volume adjust- h8 H3 J  i1 \# Y  M% J. s0 v: I
// Internal sounds, C; g1 c  s/ K. x6 [: z4 e
#define        RECTANGLE_VOL        (0x0F0)
- t4 d9 n: H, C+ P#define        TRIANGLE_VOL        (0x130), X$ o. _% @, e' f
#define        NOISE_VOL        (0x0C0), d7 b7 q* t+ j, O+ z
#define        DPCM_VOL        (0x0F0)
# c; _% ]% d' P" a: B* f6 U4 z# b// Extra sounds$ d0 B+ q+ v2 ]2 M0 Z2 g
#define        VRC6_VOL        (0x0F0)
* l) v% B, [% [: P#define        VRC7_VOL        (0x130)1 I+ |: V* C0 l* T0 f- X/ m+ \6 M
#define        FDS_VOL                (0x0F0)
: f0 v7 F8 I  r& ?, T7 t- u# O#define        MMC5_VOL        (0x0F0)
- v  I7 C* {# p! `0 b7 R#define        N106_VOL        (0x088)
. S8 |5 I) z% [/ Z" M#define        FME7_VOL        (0x130)( Q  \' R0 `2 z) F2 W9 _

3 @( W8 I2 J6 z& h2 S0 ]APU::APU( NES* parent )9 s; v' m3 F* a+ v) i6 S" V: }
{$ n9 F9 f. ?  x; R3 t; _$ Q
        exsound_select = 0;! w; R( ~7 W  d; J) V6 n
1 U5 ^* y  J  r5 c
        nes = parent;
% Y' o! x/ K8 J. s' K. g7 G- e$ U# T        internal.SetParent( parent );/ u; Z$ h: z& p1 |' h9 {
7 U' ]1 c( k( P3 v$ @2 x& k
        last_data = last_diff = 0;# v6 M" K8 @, \8 Z6 [' O6 E

  U6 e0 f: v+ i6 p% v        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );' p; i* Y& [5 H, ^0 K

4 q) w' a  ]* Z- G; J7 k. u5 O+ A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );1 l7 N3 Q5 I/ v6 q! u
        ZEROMEMORY( &queue, sizeof(queue) );
) N7 U- H: q& q5 X% B6 ^        ZEROMEMORY( &exqueue, sizeof(exqueue) );* Z/ `- M6 ?* @# _. v
. X* P2 S5 v! w( |! A! a) V* N
        for( INT i = 0; i < 16; i++ ) {; E/ _( w' I, N4 l( E
                m_bMute = TRUE;4 n8 }: s  z( \- j2 C9 J8 J
        }8 s9 O8 p# p8 F  z$ T( @# X. ]
}
! x7 ?- b; r, p: ?, ~. r! T- O" Y" Q) y/ |( g
APU::~APU()
2 E1 _3 T7 }1 d/ Z; k' u  O{7 _+ w5 Y$ K- z7 a! S! m2 ^
}0 j! w4 v1 E, ~- W9 d
9 C1 i; j8 S; h+ ~' w: g6 L+ x) y
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )+ a" k3 e. l4 }1 C$ ?+ z
{
$ {# `4 s" c6 Y2 b" N2 g. _0 _! @        queue.data[queue.wrptr].time = writetime;, c! J% ~% y' p7 p. A
        queue.data[queue.wrptr].addr = addr;
) \% W7 g6 }9 ]* ~2 T        queue.data[queue.wrptr].data = data;" ]4 v0 y7 j0 P$ N
        queue.wrptr++;8 F" F5 e0 a* y7 B* U' U2 J* A& a% n
        queue.wrptr&=QUEUE_LENGTH-1;/ q0 \1 }3 ?+ c/ T" Y  f5 O( i, r
        if( queue.wrptr == queue.rdptr ) {2 y% S$ g, x3 G( D: L: ]
                DEBUGOUT( "queue overflow.\n" );6 K2 k) h4 A" P4 e
        }* l2 z$ H( u# y. E( T  i
}
& \1 W- H3 O3 F) _4 l% z+ l) W2 [2 M% }, }
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )9 B7 P' s9 e- n6 Q" x
{
. T: O5 w' B9 r% `        if( queue.wrptr == queue.rdptr ) {
  z. Y6 }; y  u                return        FALSE;1 G& S. h2 F% W7 @# {% F
        }
3 i, _8 x) ]& c5 n        if( queue.data[queue.rdptr].time <= writetime ) {
" ^, f/ H) C, p/ h                ret = queue.data[queue.rdptr];
, d" ^+ }1 w* G: B+ @( x                queue.rdptr++;0 H! ]- N% e: G& `
                queue.rdptr&=QUEUE_LENGTH-1;- R; |' G$ r) F& p: W
                return        TRUE;  N/ V5 [# o9 L, W" T, z
        }2 B2 u1 I+ B8 k0 V% Z$ q
        return        FALSE;: Z! _) X: {  }) V, n8 N. ~
}) i. y9 l& W: ~

; L! V! M1 I' k( u- Wvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 Y, H8 }5 w8 O4 E3 s# R
{
3 F$ w  b; g  e3 _: M" F/ E6 b& D& R        exqueue.data[exqueue.wrptr].time = writetime;# D2 J; q( Y3 `
        exqueue.data[exqueue.wrptr].addr = addr;
. s3 p- b  N1 M4 s2 c        exqueue.data[exqueue.wrptr].data = data;% u: y( B2 z1 G- C3 b1 W  L( p
        exqueue.wrptr++;
$ G5 @$ ?8 h% b" N( [        exqueue.wrptr&=QUEUE_LENGTH-1;" X6 w5 D" t6 j
        if( exqueue.wrptr == exqueue.rdptr ) {
6 |) ]3 H* y4 v% v( C; j  u3 k: ~6 x                DEBUGOUT( "exqueue overflow.\n" );
, F* R  H' w& Y) |% {. b        }
9 `6 z; z: d' z6 F}
7 ^% @" q: C( c3 Y0 K) N. @2 m. o. F
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )1 Q/ N( h% _( @
{
5 N/ S7 O+ X  H- P* Y% T5 G5 w( N# ^& N        if( exqueue.wrptr == exqueue.rdptr ) {
) [& |7 [8 [% n/ I6 m$ F                return        FALSE;
3 D" q+ P- b; P) i. `        }! c0 }7 `0 r. q. R4 G% U! |3 r
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
: q9 F" e/ W, @4 h                ret = exqueue.data[exqueue.rdptr];" K( p# x( R- s. Q6 Q& t$ g
                exqueue.rdptr++;9 T$ T( V8 Y" w7 w4 u- s9 m9 r
                exqueue.rdptr&=QUEUE_LENGTH-1;
  ]* i. d! H/ e& H' J                return        TRUE;! F8 K: }4 r7 o) M+ @0 l+ v* I; `
        }3 ^2 P! y% T: N' }3 Q+ _
        return        FALSE;
5 u. f, ^# S- O; M}5 E9 R! P2 {9 T% o
# q0 _2 N: H6 `: b, |
void        APU::QueueClear(): C5 g& v( J  R& G9 N  B
{7 V5 g2 G1 ^( C% U6 A$ n* S
        ZEROMEMORY( &queue, sizeof(queue) );5 v' C8 I1 ~9 S0 @' p4 \
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 E6 `. L1 R" `, g
}
+ a7 b2 B: R! n& _, L
* {: d: X$ e  j4 Gvoid        APU::QueueFlush()
9 i: D+ L  S! r! i: B{. T' J# n. {( T: X! e0 p' h9 ^! X
        while( queue.wrptr != queue.rdptr ) {
+ f; N9 j0 o: N* o$ f) B/ c+ U                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
, m  |. Z- }3 m                queue.rdptr++;
4 s2 p5 \7 p$ ~$ b9 p% N' n                queue.rdptr&=QUEUE_LENGTH-1;
& ]. j4 R' v" K8 M        }
% Y7 D8 W* Q5 H' ~" s1 d3 g1 H
4 x2 C6 e4 J1 L! S8 f# m        while( exqueue.wrptr != exqueue.rdptr ) {
1 P- j9 s0 x, c' L" L                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% Q  L& M7 ^1 R/ N
                exqueue.rdptr++;" j) f& }( v% g& ?, k  w" t5 k2 Y
                exqueue.rdptr&=QUEUE_LENGTH-1;
" l) e" \9 p( J4 z        }; W0 I% ]4 r7 }8 ?
}
! F. G! n' z9 G) ]' }) l- Z) Q0 W. t3 f1 _7 o4 M( j
void        APU::SoundSetup()3 F7 N, r1 Y1 N0 S6 I
{
8 G4 D8 ]: B. `: d        FLOAT        fClock = nes->nescfg->CpuClock;
) f5 W9 b2 J) `        INT        nRate = (INT)Config.sound.nRate;
1 _) L) [2 [+ u+ |        internal.Setup( fClock, nRate );$ s$ i- J4 q& {# D. R, K$ `. K0 i
        vrc6.Setup( fClock, nRate );$ @* e3 E% f' f1 i3 L& S2 F
        vrc7.Setup( fClock, nRate );/ D- B( p  j+ h$ L( f, a% S
        mmc5.Setup( fClock, nRate );2 B7 t) \1 H* ]( G
        fds.Setup ( fClock, nRate );8 s* r7 ]) i( O9 y, k
        n106.Setup( fClock, nRate );3 r3 [3 Z6 l9 J9 v6 e
        fme7.Setup( fClock, nRate );
, O3 |, J6 Z' R, }: y/ H* i6 `}" ?  p, s' A* E6 \
; Y6 D7 v% [; r1 |/ ]4 q! x
void        APU::Reset()
: W5 S! P- ^& S{
! E% Q* T4 {: u! Y7 |  I% {0 N/ A3 q        ZEROMEMORY( &queue, sizeof(queue) );: u, s; }1 V% g( h3 p3 ]" B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 j7 x4 L6 b5 h3 {* u, L1 T0 o

9 {# O1 W5 x( m        elapsed_time = 0;
! i( J9 u+ X. s3 `3 Q; X, \0 b3 ~+ s& {! i- d$ [
        FLOAT        fClock = nes->nescfg->CpuClock;
/ U- M( `( U+ g3 i        INT        nRate = (INT)Config.sound.nRate;
0 b& `5 ?% k/ `% m  n) R        internal.Reset( fClock, nRate );
" e3 J" x" `: j# z7 g' W2 Y        vrc6.Reset( fClock, nRate );0 A0 ^8 f( X2 l2 m! z1 |. j/ b" m& M
        vrc7.Reset( fClock, nRate );) k1 o+ Z+ i) R8 v/ S% y3 u
        mmc5.Reset( fClock, nRate );# w  L) w! ]5 i; f
        fds.Reset ( fClock, nRate );& C' u) o* h& }5 u
        n106.Reset( fClock, nRate );3 g. d; o$ k8 N. S& e
        fme7.Reset( fClock, nRate );
* j3 a! Z) A4 n7 b* q5 m4 V; d0 a* W% k1 g+ Q1 n2 g
        SoundSetup();
( T, j: l5 a3 K+ Q, I}
% g- Y: Z: Z5 f) P6 R1 u) _, b$ N  N/ L- f
void        APU::SelectExSound( BYTE data )% o% A# |" z' C2 N& [
{
4 P& [. ?% _8 N- S% S9 ?        exsound_select = data;5 A6 h$ g* {5 U1 F- x6 G: l# ~
}' B7 a5 h' Q1 i; F& {
  p& J! o7 R: z- k$ d1 ^6 t
BYTE        APU::Read( WORD addr )
6 i7 Q$ _5 O: g5 ?+ l: O8 b6 M{
" |6 S; O; R7 n2 d( i9 H5 K        return        internal.SyncRead( addr );
3 {! K) g: }- v8 T: Y8 d}
/ b- a+ p- P# n. D. ^0 r
' X* r0 G& s$ D# h) \0 ovoid        APU::Write( WORD addr, BYTE data )
& K8 a# q" A& K{
  L& Z9 }" ]( k6 [8 @        // $4018偼VirtuaNES屌桳億乕僩7 H) T6 ?- [2 n; @. T' B
        if( addr >= 0x4000 && addr <= 0x401F ) {
! U4 [3 S0 r4 c                internal.SyncWrite( addr, data );- \2 q! c, w! ]$ X# y) c  |
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 O4 t0 B/ @; u  C  n8 i
        }; m! j+ |9 ^0 j+ M' F% s3 {
}
  v6 [8 j; i3 C# d: X1 ~5 T/ n4 i+ j+ {  w3 I9 P
BYTE        APU::ExRead( WORD addr )( N. ~( ]9 P) e( s
{8 D. E/ [! k8 T2 G0 m  s5 N, y
BYTE        data = 0;! t) l6 L6 f8 L2 X, x4 q* i

; ?0 W# U5 T' s" y5 r        if( exsound_select & 0x10 ) {
! t+ l1 r4 w2 |% n& R* t                if( addr == 0x4800 ) {5 L6 Q. G' y$ K( G
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
+ D  K' Y8 X3 S                }" O# O7 V0 N+ q$ F( B& M
        }3 F" R1 d4 r. j0 c
        if( exsound_select & 0x04 ) {" w  A* E# H4 j$ \6 w1 B5 g
                if( addr >= 0x4040 && addr < 0x4100 ) {
; }% N+ T5 D2 B: a                        data = fds.SyncRead( addr );
( {1 S% b; ^6 u# }6 j8 d+ J" u                }
2 u, u  e" u4 I% B        }
/ z* H: @$ v* I' N! A        if( exsound_select & 0x08 ) {2 k  J1 j0 D3 j$ Y$ J/ ?  K' a
                if( addr >= 0x5000 && addr <= 0x5015 ) {
4 B/ s0 h! w- r* e  S! R                        data = mmc5.SyncRead( addr );
8 _8 k+ M1 \6 ?: u' I! A                }
. P% h7 \% m: O- w) @% D        }
5 \. n0 R8 Q& I0 D2 r2 t5 `8 N' I* W5 X1 k: l
        return        data;
5 d6 Z: C) V6 C$ ^% y) R}- m) I* c- m& G% ~3 J6 q6 E

+ Q% K! O) m, m' M4 a, M; avoid        APU::ExWrite( WORD addr, BYTE data )
/ }1 [! v# {- X4 R9 j{
+ L  w. d$ i; w, z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
/ ?- Y4 f) ^8 e0 |( C4 p$ |3 L, N9 t% A+ T4 k* N
        if( exsound_select & 0x04 ) {
: P9 z5 X' Z. |                if( addr >= 0x4040 && addr < 0x4100 ) {
7 w; u1 l9 B) f. Q                        fds.SyncWrite( addr, data );
5 @. Q0 W7 T/ x8 J7 g  h# z                }
! M# d5 r9 }- I  E5 b        }
$ m0 _% H4 b1 ^; Q4 {% F: |3 W9 U
        if( exsound_select & 0x08 ) {6 r$ b7 A; I2 ?" u& B( ~- {
                if( addr >= 0x5000 && addr <= 0x5015 ) {
; C, t7 C9 ^& X5 f                        mmc5.SyncWrite( addr, data );2 v5 t5 O( `4 F2 b
                }5 Z6 d4 z1 x4 m  L$ U
        }8 d& R# h# }; z; o: z) K+ o1 y2 K: G% U
}# H- C9 q% S- K; }$ [
* o2 b4 F4 n& W- B6 U1 g6 O" D
void        APU::Sync()
% d0 ^' ]9 r0 `4 g1 a6 Y$ G{$ Y; p1 x! |; Z
}/ M( f! l3 W0 r: E$ X" c) f# v

2 e* \" Y( k; k7 cvoid        APU::SyncDPCM( INT cycles )
9 d. p$ N3 G  Z  f( @2 k6 ?{) P9 X: \- ~4 b$ U% T4 `, s  @
        internal.Sync( cycles );
9 g6 \4 }2 B2 w* R3 Z% {" H3 P
5 ?' l9 e3 j1 ^- }% O- I7 Z& e" Q        if( exsound_select & 0x04 ) {8 v7 g4 d' D& t' l
                fds.Sync( cycles );: b, q5 A2 @4 c) c
        }
% q/ {7 I2 @2 z  |  {        if( exsound_select & 0x08 ) {+ C9 i3 X0 w( M9 R0 i4 ~) Y
                mmc5.Sync( cycles );0 ^$ ?$ Q9 E& W3 [
        }
, q, a! L! T; N9 r* ?$ M- i}/ V4 K) {0 q9 ]3 G
& \2 _/ ?8 q4 r# n
void        APU::WriteProcess( WORD addr, BYTE data )
! E5 t+ X6 ?' l. I{8 B8 l; x& E; t
        // $4018偼VirtuaNES屌桳億乕僩( c* n3 }& `+ R% a* k
        if( addr >= 0x4000 && addr <= 0x401F ) {7 A! d. V1 B* g2 y: z! q5 ~. n
                internal.Write( addr, data );
  f3 I$ m, C) \$ `6 H: o        }- ]% {/ a( u9 ~# L# D1 V; P
}
' M- M* B. a$ B) j' L: \! I9 t
& |3 f# f1 G% g0 Q6 D5 r  {$ Qvoid        APU::WriteExProcess( WORD addr, BYTE data )3 c+ ?$ s, u' l# H
{
2 g  u9 }( _! @) a$ I2 P6 W        if( exsound_select & 0x01 ) {; i! U% t  n; A4 \1 m$ u  V
                vrc6.Write( addr, data );
' r8 T3 k3 X+ {+ A: R        }
6 L. p! e' z% }        if( exsound_select & 0x02 ) {) j+ p8 T$ A( _' _: x9 d- r0 y
                vrc7.Write( addr, data );
- P7 c* E. [; ]/ g        }8 o: {- A4 c7 r! S$ h* k# ~
        if( exsound_select & 0x04 ) {
. j0 c2 \; ^2 p. q                fds.Write( addr, data );# R* \9 I2 {- }! a, f) B0 c5 y
        }
9 a9 K" P7 c, u. g        if( exsound_select & 0x08 ) {
! x4 T2 c2 F4 R. Y# N                mmc5.Write( addr, data );
$ |0 M3 O$ w4 {3 z2 F: |3 i  G% N        }4 l4 C9 m. f  E' w3 n/ Q3 U
        if( exsound_select & 0x10 ) {
/ J6 X! Z+ ?# V& g# H                if( addr == 0x0000 ) {
- O, i2 r; e; V3 M5 Q. W% X# Y                        BYTE        dummy = n106.Read( addr );7 G" R  ^# v5 l- z
                } else {. E& D3 Z1 o' i$ k
                        n106.Write( addr, data );2 r( _8 V+ W3 M
                }3 W6 o& P. B. |+ h
        }2 Q3 L9 C. G* J- Q
        if( exsound_select & 0x20 ) {
3 h+ g/ F1 X& s                fme7.Write( addr, data );
' t. I; w; @8 D$ R4 T& R9 y( ]        }
0 q) X" l/ q  n% n) s  z}/ v! z$ y4 Y5 }/ i
! _7 [  `5 I2 ]1 A: `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
- q- `" |' E" J3 K/ }3 _& g{/ w( F) G0 b0 m1 J! t1 q: i
INT        nBits = Config.sound.nBits;. U+ f1 i' ~1 H5 K6 @2 K- e
DWORD        dwLength = dwSize / (nBits/8);
& ~$ p( `  F' |! ~INT        output;
$ e8 T" @; j: S# |# MQUEUEDATA q;
: A  n! j$ \$ I( Z' t; iDWORD        writetime;
! n1 q4 v" m2 T/ C$ q: _3 M
1 R0 F. y3 d& ?# x0 A: u" N2 z" f; ELPSHORT        pSoundBuf = m_SoundBuffer;
# ^+ K  P, j, x+ p& HINT        nCcount = 0;  u8 A" ^0 H$ I: }' ~, _8 [* U

* m% Y6 y) K0 o' X9 ^) gINT        nFilterType = Config.sound.nFilterType;
( o1 S4 z& `, ]* ^! x5 ^) v, @+ x8 r  s- _
        if( !Config.sound.bEnable ) {/ z8 P- z2 d+ F, e0 o8 j6 Q; Y& s
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
" B3 I, L9 P; N6 N                return;1 r& p' f( v# X* x
        }
8 E* J, e% E6 F5 C! _! i" B8 g6 B. z/ R* @2 a; e4 Z
        // Volume setup
3 @2 |  t+ I3 P1 \4 m( b0 }) z& V        //  0:Master0 n& H. }# H7 X9 F4 d
        //  1:Rectangle 1
; W! E/ |$ M- z/ l        //  2:Rectangle 2
9 }9 ]8 X# o* V$ L& w0 ]        //  3:Triangle; @4 F- G# A9 a2 w) H* R5 @8 h
        //  4:Noise
/ {7 u9 K2 m% }8 B6 C4 {. c9 B        //  5:DPCM: {+ w/ ^. ~9 z6 J# g$ K
        //  6:VRC6
7 }/ r- V, J! m$ O5 I, W        //  7:VRC7
+ }$ E6 w% z. `; @7 d: s/ {        //  8:FDS  j2 y9 K6 e- T0 C( x, c3 L
        //  9:MMC5
$ F' y% J0 W* m        // 10:N106
( y% _, I3 d( M, L' j& G- v        // 11:FME7
( V) Q' v; x; g" g5 s' N  I8 Q        INT        vol[24];& N5 ], E( G  w. L: m
        BOOL*        bMute = m_bMute;: I! a- C2 t; ?9 Y* b2 N+ q% B% c$ J
        SHORT*        nVolume = Config.sound.nVolume;
- r5 S% |1 i' X1 x, F
1 l0 F6 q& }: \1 L5 H* ~/ d+ j: Z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;! a: {& N' L8 j7 ?8 \- s: a

2 x6 h6 ^: A0 A- I        // Internal
4 s- _# s( m& q        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;' F* P! H2 u/ V$ O
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;! G( m6 ]& I! V/ k* _- K
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;' r( x; F0 {% m! f
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
+ b% l! E, o1 d# c2 y        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;- H0 z7 e% }- Z9 F- M& x
4 x6 C3 a1 M" L6 E
        // VRC6$ i0 c  j' c/ g0 t7 O
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! i9 N8 q6 m& z! I! Z1 y        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 Q1 M% a) V) Z1 e. s        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  v" I+ x4 P+ f; V/ o7 }9 i" c
$ N& X+ W* @3 ~) t0 `        // VRC7. D; I/ o' W1 I& k1 c# c, u7 _( z
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;/ z- v$ c/ n5 }. l1 Z, _
) _9 n# k: Q" _, R( M4 G3 r3 R, E
        // FDS2 e/ O, \3 }/ ^2 F1 t  A5 U
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& p/ l( f+ w3 G0 y  u/ o  }/ H

. s+ B' U5 m5 z  O8 y7 H# A        // MMC58 W- O$ W) a$ S: ~4 W" m
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; K( G4 u, U; B1 f& `; H
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) f! X9 I& c# A$ ~3 z1 z' ?        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' D/ ~8 j" e* _* u
* D& v; U; W4 N) J! h4 n/ ]7 R        // N106
0 o4 W0 f. p! K1 d+ v  o: _' j0 f        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ o- c2 Q+ {7 N; v
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) z5 @2 T& ?, n! z; ?( n        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) H. M; ^  w  r        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; v* }) J! ~9 E! k1 Z        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 E! R2 K4 d; Y% N+ F
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: }  G# L* `' X5 h, T# i        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 K9 D( A: Z' g
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 R0 K. {2 [1 l& X4 k6 p
) W  e8 p( K  ^" T3 U2 U1 t
        // FME7" B, v# B: C. t6 q( k/ H
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. x* g# q$ l& O        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% b" B# i# x6 Y" \1 q4 D* D7 j
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  C: e$ h0 F3 N: t6 C! \7 j/ r$ V( R& {% d" e/ y# |# h
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;( o! m& G8 v2 l- x" v0 O( ^# B
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;% a1 b' X7 x+ N/ L7 V! K5 A* k) b

. R+ O. A/ }4 x( p: E9 ]        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
  [* g+ I8 s& ?        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
5 K4 E8 C. p3 [  p! j                QueueFlush();8 L( J% f* c8 p" Y& O/ G
        }
5 G4 s5 F8 R7 N" @  n5 {" s! O# X9 Z  D) K/ o% J" g9 o
        while( dwLength-- ) {
$ ^  X0 |, P: e                writetime = (DWORD)elapsed_time;
# W* n, b) x0 k( s1 k) p2 j
# {  [: J- y  y8 e2 {9 b3 N" q; g                while( GetQueue( writetime, q ) ) {3 I' a- a, B9 b* G% w" e% X
                        WriteProcess( q.addr, q.data );5 \0 H( K  D& {* u* I* ~
                }; |% _7 h$ S' R2 P4 Z+ x. e
' N7 p0 H- d$ L3 c% r, q4 B
                while( GetExQueue( writetime, q ) ) {
" x" W- T' g# j) r1 V+ a: _                        WriteExProcess( q.addr, q.data );6 z5 k2 {: S- I: t: x" _0 B9 F' y
                }1 Q! {4 _, \- Q  u
- s# b, u8 R' I. Y) |) h
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7" F: D' M+ @1 Z/ m
                output = 0;- w# u. H" @3 u' i* B
                output += internal.Process( 0 )*vol[0];6 F* S( p7 `  [7 N
                output += internal.Process( 1 )*vol[1];
: v$ a$ P, V( J  F; \  r# x                output += internal.Process( 2 )*vol[2];* x  s. _$ R; \7 L7 X3 v
                output += internal.Process( 3 )*vol[3];3 u. d/ P! D6 w6 b, b
                output += internal.Process( 4 )*vol[4];
  z9 r! W( I; w4 M# q+ {4 v9 a; z" K+ Y$ D; y
                if( exsound_select & 0x01 ) {/ d& K4 q* t4 q! `
                        output += vrc6.Process( 0 )*vol[5];
  m% ]- R9 `2 Q8 z/ D; J( j8 w4 H                        output += vrc6.Process( 1 )*vol[6];' U9 ?1 B4 N% q9 C, F
                        output += vrc6.Process( 2 )*vol[7];
2 e0 U: |& z) Y' o6 L                }7 y1 h; ]& Y$ C% S6 O- A5 H6 n
                if( exsound_select & 0x02 ) {
0 x& ~, o2 Y' Q# q9 m                        output += vrc7.Process( 0 )*vol[8];7 ]4 [8 \+ m6 \
                }
+ b6 @+ D6 O4 b! o: C0 A% ~                if( exsound_select & 0x04 ) {
, r, _1 }. ]6 l                        output += fds.Process( 0 )*vol[9];+ w9 A- Y/ c# m/ I
                }
- z# N/ f8 d3 w& ~0 m                if( exsound_select & 0x08 ) {6 d0 W* o" r4 n8 Q
                        output += mmc5.Process( 0 )*vol[10];
: ~' ^' K7 {5 x' W2 v* N                        output += mmc5.Process( 1 )*vol[11];
+ F: c" w$ N$ S8 W                        output += mmc5.Process( 2 )*vol[12];
7 u- X$ h; w; G* }                }
5 q& g8 K8 I' q9 @' y                if( exsound_select & 0x10 ) {6 S* M' K/ c6 k: @
                        output += n106.Process( 0 )*vol[13];; G5 A" `( ]# t& d
                        output += n106.Process( 1 )*vol[14];
! z9 A- k  E" [' }1 A, M                        output += n106.Process( 2 )*vol[15];8 x8 x  [% ^' }6 Z) p4 e
                        output += n106.Process( 3 )*vol[16];  `& N8 `# ^# k6 z# _
                        output += n106.Process( 4 )*vol[17];2 w$ n0 J4 D: ^' ]" w$ J) W5 g
                        output += n106.Process( 5 )*vol[18];
0 B5 l  g+ R# K" H                        output += n106.Process( 6 )*vol[19];
* v$ v9 u3 H- |0 k  \8 P6 Q* Z                        output += n106.Process( 7 )*vol[20];
9 d! A! m7 g4 k$ M. q  P, U                }4 V0 |4 h; W0 J' D
                if( exsound_select & 0x20 ) {: U$ i* v* c& n0 [/ F# S, j
                        fme7.Process( 3 );        // Envelope & Noise
7 f2 o1 a/ }+ t# C0 b- v                        output += fme7.Process( 0 )*vol[21];
" J8 E# @, @4 p7 c                        output += fme7.Process( 1 )*vol[22];; S9 P4 ^1 l, y
                        output += fme7.Process( 2 )*vol[23];
. {8 ~4 C3 v4 v4 Q) U  C                }3 r- h4 [, d& n# T; K2 w
4 m  l9 E* V- g5 d8 H8 f
                output >>= 8;
: w' o7 F" a0 g8 x1 H
: b! @5 K8 S8 `& ?4 Q: r2 F                if( nFilterType == 1 ) {
  F' m* W( u; T9 }3 Q( m                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)- [( q" _; S! C0 S& F
                        output = (lowpass_filter[0]+output)/2;
' T! Z. s1 E& |% ]  Y' M6 Q! A* e                        lowpass_filter[0] = output;+ p+ `& _+ j- V8 J/ Z: \6 s
                } else if( nFilterType == 2 ) {
, p1 h3 d( t$ g6 [* j+ _                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 H2 A( @5 b' X; J  v  y
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
6 y9 X" p+ _/ J" v                        lowpass_filter[1] = lowpass_filter[0];( H8 t- P7 ^* ?8 C6 l% w# W
                        lowpass_filter[0] = output;
, E6 b, E3 _. \6 Z) L. t) @+ G                } else if( nFilterType == 3 ) {- L* ?- Q) \4 j7 `/ _
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
: D; L5 [* Q0 f# J  s6 p) W; ?                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
6 N1 K+ C5 u4 N9 T7 i8 E                        lowpass_filter[2] = lowpass_filter[1];3 S7 w  N) r/ L3 y3 q( z( y6 C
                        lowpass_filter[1] = lowpass_filter[0];5 g7 |' S! c5 X0 e
                        lowpass_filter[0] = output;. R% D# `5 l, f7 w- ]* m
                } else if( nFilterType == 4 ) {: U9 O) h2 o% E% p5 E* B2 i
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
3 a# e7 D! j7 [/ }' L                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
5 B6 V5 `' u4 O                        lowpass_filter[1] = lowpass_filter[0];; W7 n2 j3 f! `" h" ?: C9 R6 o" f* y
                        lowpass_filter[0] = output;! D' H3 v7 w9 _1 m7 I
                }
( h; v! i! R& x) C$ |/ s6 V2 Z" `9 z8 K
#if        0
3 {" Y) N8 ?: y; i                // DC惉暘偺僇僢僩
7 x/ Y. v7 |5 a                {
2 R- h" l4 |, F8 F& S' H% a7 B" q                static double ave = 0.0, max=0.0, min=0.0;
9 e1 K( d; B, w) w5 {8 T3 v& M                double delta;
1 Z0 I  Z' `% F0 N9 v* l5 r( ^                delta = (max-min)/32768.0;4 E. z$ `. L' O( ^  m; c2 B
                max -= delta;  ?% b- ^0 r' d, X1 @" s) _+ U5 ]
                min += delta;
' u, Z" N4 _. ~2 B  s                if( output > max ) max = output;
0 w/ G* x1 h/ I9 I/ k# G- l                if( output < min ) min = output;
! R0 M& [% Y; q6 d# I5 n/ ~; q0 C                ave -= ave/1024.0;
" Q1 z" [) @  B: _                ave += (max+min)/2048.0;
0 [% x9 ]* ~5 }* k' M) a                output -= (INT)ave;! e- W* d- [4 a  Q1 E9 Z# U
                }
( r4 W! r9 R  x' l% s% h- k#endif& _: x: X7 @. p2 a
#if        1
2 t1 h0 r" q8 V0 @9 i                // DC惉暘偺僇僢僩(HPF TEST)& {& P! p, c5 l
                {
/ `" L; b: t1 p4 Z//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
. s  N" `* }- y1 }                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 x( I. c. @) y( ]% X' C5 d                double        cutoff = cutofftemp/(double)Config.sound.nRate;! P8 y  T8 t) @& H3 J
                static        double        tmp = 0.0;
( }( t0 t  o8 K" h# _4 `4 |& J                double        in, out;
9 P0 E. H* n& k. f; }& E/ P! F/ k5 f2 ~6 ]' H& x
                in = (double)output;
4 `- w& ~. x& i  u& }                out = (in - tmp);
' w" K/ C. h5 }1 @, s& h                tmp = tmp + cutoff * out;
5 A  _2 g$ [2 J1 w9 E6 V
! @) k2 K( C) [3 T1 J                output = (INT)out;: d' S: y" S4 E# b# u& _
                }
( P" u' X0 Z& \5 A- H' |#endif: S  [: U- P+ P. t
#if        0! s! l, }( M& E9 ~# \
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)  Z1 x5 `8 \6 y. F$ |4 J
                {/ b1 U, l0 U* `# z+ F
                INT        diff = abs(output-last_data);2 m( p6 R5 S* L' z4 y$ U
                if( diff > 0x4000 ) {
2 B& B' K4 I* R                        output /= 4;
( Y1 \$ Q/ Q& H) M                } else 5 x( B9 ^2 h7 C, F4 v- c
                if( diff > 0x3000 ) {
3 A) r, {. z* _- z                        output /= 3;- j: Y  s# T- G; g3 q( ^/ P, E- ]
                } else
4 V" e% T: G  i$ g. G                if( diff > 0x2000 ) {" t$ k  s! o/ {1 `; }/ {
                        output /= 2;% d2 u: n& X2 F( N& M7 t
                }
1 d4 L' ]$ m) g% ]8 ?4 \                last_data = output;
+ t6 a0 I" c" c! w( ]8 S                }
. j% K5 T* V& J- Z7 F- _#endif
  F% Z* d" F" q5 s                // Limit9 u% v6 q$ c( m; H" v
                if( output > 0x7FFF ) {* |2 T+ S/ }* F; X* z
                        output = 0x7FFF;+ W- S# Y$ ^& z
                } else if( output < -0x8000 ) {' y  M; [6 r" Q: t/ l8 }
                        output = -0x8000;
+ y6 T1 m$ e7 h: F                }
. x& R% `4 s% e( J; ^* ]/ b/ A4 w' C5 I. e9 q( _7 y& Y
                if( nBits != 8 ) {* z" _/ G5 \2 O, V
                        *(SHORT*)lpBuffer = (SHORT)output;+ W% I6 d0 D6 r8 q
                        lpBuffer += sizeof(SHORT);1 l  N0 K# K# g0 I! ?. [! @
                } else {
, D8 o) v- H; }6 w                        *lpBuffer++ = (output>>8)^0x80;
- W! E3 _& a! m% V* J8 G) z                }
# o. r4 Q6 c8 j: e7 Q. ~
, c  B; T8 k: G. o2 a0 }                if( nCcount < 0x0100 )" R/ n1 u& E1 r; \* I4 |& V, U
                        pSoundBuf[nCcount++] = (SHORT)output;
8 B4 D/ i. b7 `6 [) T7 |, c
* N0 A  T( T$ c! n( I/ W& f+ v//                elapsedtime += cycle_rate;
' v" ?8 g# V0 V7 ]                elapsed_time += cycle_rate;( Z- Z* K3 S* r' [, y9 b
        }, _2 u5 v3 |5 |9 q; i

' q, i& s. N; z$ L( v#if        18 R0 _$ ]3 C; P; K8 |/ B
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {' H6 c+ r! m2 y& y1 u$ u
                elapsed_time = nes->cpu->GetTotalCycles();8 m. Z4 s6 C& o6 q+ J
        }
; o, K/ t# ^+ m7 \; [        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {# u2 g- R3 `6 Q- W) J
                elapsed_time = nes->cpu->GetTotalCycles();2 X* g9 B, Q: T! j( W) T9 F
        }
* N/ C- s$ A3 c4 u6 r$ A, I#else+ e4 a4 J  ?6 K( S% i4 U9 s+ l# B
        elapsed_time = nes->cpu->GetTotalCycles();
7 @! h1 s; C/ C* `6 k#endif
, `# W8 P5 K" N+ j" Y- N}+ w+ f% p8 R& q  M" M; }

6 |2 ], n- J; M( k5 S/ S: @9 F/ k9 N// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
) h/ S; v; X' v* n* C5 N1 @INT        APU::GetChannelFrequency( INT no )
7 R9 |; y5 \, L: y  ^7 O{
- q) r9 O4 m: N& g5 Q        if( !m_bMute[0] ): E; T8 c# s2 S2 u6 Q& R2 a" g
                return        0;4 B. ?' B6 ]: F( e, [& d+ `! o; N
' i2 v2 e5 L$ h) l6 Z/ a; m) H
        // Internal+ H- C, K# |7 x$ r9 G8 k8 h( t
        if( no < 5 ) {
7 o, C  q/ e( V) [" I& J/ y4 _  Q/ O& x                return        m_bMute[no+1]?internal.GetFreq( no ):0;
* s" E  D0 T$ f% c- u7 P: Y        }
7 h5 @- [7 @6 Y# S8 M7 u) u6 D* q        // VRC6& s' }9 }1 a7 X& J$ Y# \
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {) o1 O# z* w- C# b. X
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  l& f! D' t9 I$ w; L
        }
& I. T3 o% j. K$ e# x8 g        // FDS/ W5 {  h3 U* d+ Q$ _( V
        if( (exsound_select & 0x04) && no == 0x300 ) {. i3 [% @" k1 [+ R( u' i
                return        m_bMute[6]?fds.GetFreq( 0 ):0;  r- K; v- M1 Y. @
        }. K& _: S! ^- ]/ q+ {# H, {8 X
        // MMC5
1 P9 R; w- E; Q- L        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
1 n: I& L4 p) M) T6 P                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
/ Y5 d* \% ~; ]        }
/ w( M) y" F: o        // N106
$ f5 H, ~" j( V: u4 s2 F        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  y' \6 u/ q* X9 G+ N( H9 M* i
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
  r+ d  `6 L& t+ i8 O$ o        }0 x1 C; g, `* }5 N0 v1 `
        // FME7; z: y: u+ }. D
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
# |9 _, S( w4 m/ ?7 J' r2 a& v$ @                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
, {2 B1 l2 e0 I; t0 K        }4 ~# W+ H: C5 h) o: a& ^
        // VRC7) v. v0 ~0 z3 x/ b
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
, ]6 z) ~; w( W- }, c! p2 B; w0 @                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& l  h  {5 a- d% d& b! q        }
3 W" F+ q  X6 m        return        0;
8 a/ s5 C' }; p; c) i. E/ u}
. L! Y8 x+ ~) i4 _) h
3 `0 e& h- h& Z# |# p// State Save/Load
' k9 r: Z' E7 G% Z0 \void        APU::SaveState( LPBYTE p )
7 Q9 c( W4 p) ~2 ~' {' W, n6 a{( M; H1 K3 b$ D
#ifdef        _DEBUG2 h2 v/ I- k5 f1 e
LPBYTE        pold = p;" [0 ]1 [7 n! T, @/ K8 f- ~
#endif
+ G  i( ]+ ]0 d% z: c- E* K% u
# j4 @+ ]2 V9 U! i- n        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
: B4 D" v6 V8 C6 s; j* F# Z# l        QueueFlush();
: ^% G  x0 d* L) X
/ \  @  n  r( i; _- e+ }6 {        internal.SaveState( p );
! Y7 m. n" T- [7 P; ^% Z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 R: M, ~; h0 U
* V. @6 U, g$ b, i* z# K4 }5 h        // VRC6, {0 T* H9 m2 e  D& _
        if( exsound_select & 0x01 ) {
+ \( K* Q6 K! d& `' O                vrc6.SaveState( p );3 F2 W. w' E. a9 U9 C6 I, C
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 d0 F1 n+ R" B6 y& F
        }, o7 L. F& p9 M
        // VRC7 (not support)
* p) m% r1 U& v6 i, r- _! R        if( exsound_select & 0x02 ) {, u6 O  q7 Q: [$ ?; H8 B
                vrc7.SaveState( p );9 t. \, m2 r4 l
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) }) r8 a$ B: i$ x9 E5 K8 ], h        }
+ _$ V6 E8 p+ _/ i$ T5 X. _. t        // FDS
6 \1 m# j$ c4 z4 |        if( exsound_select & 0x04 ) {
3 m7 F2 k5 @: Y! m+ p0 Y1 Y                fds.SaveState( p );
1 I: J3 l% D9 i! b. f; Z1 Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 e& o( l3 Y. c9 I' N8 B        }9 g) k$ h& g% A7 B% `( I
        // MMC5; o; Q2 h8 C: [
        if( exsound_select & 0x08 ) {; Z3 G; R# U  s% g# H2 K/ ]
                mmc5.SaveState( p );
: o% a* C- ?5 ]' O6 `8 T                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding/ w. l) R' w% e3 P7 P& [
        }5 y8 s3 Q  k, \( Z7 M
        // N106* l( W3 F- d# i' I. g3 t, `$ p
        if( exsound_select & 0x10 ) {
2 V* U) {4 C# Q7 k/ X. ]7 D" |                n106.SaveState( p );& _5 U* Y& L* N4 y& w# I; l6 K
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding- Q$ L: f7 [0 X& C. F
        }8 y0 l7 S: }! J9 B
        // FME7
# B, x; ]4 T0 t' s# p6 b        if( exsound_select & 0x20 ) {# C$ g! Y# {$ {. E
                fme7.SaveState( p );' I6 X4 s7 X& y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# F& b8 ?" Z# j$ N
        }' `+ p3 f  x! s0 }# M# f

/ ]5 p1 z- s/ N% [#ifdef        _DEBUG  Y1 G, q' o7 [/ v. |9 q6 Y
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 R. s, v+ {7 i" G- ~& ?6 o! {  X
#endif% d6 g6 r) a1 e2 `5 G9 ^; k7 E
}
, Y1 a; t) B7 @
7 \& c1 N. h8 Z! ^. Dvoid        APU::LoadState( LPBYTE p )
# H1 w" ^: c9 \/ K" j{
0 r( b8 U  l5 M" _% G; c        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
8 h; ?2 Y5 k/ u        QueueClear();
( ]7 u3 N: m% F' L2 _, w# d  I
( z& K1 \) }4 y' J8 \5 j: I! G        internal.LoadState( p );
8 W! _! ^7 Y% G        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, @8 A' o0 R/ v1 t( i
  ?( a/ J0 s# x% X2 V
        // VRC6
1 j& w( _% y5 U7 C5 [# \        if( exsound_select & 0x01 ) {
$ t2 u$ `' L2 T( L( G                vrc6.LoadState( p );
: J0 B# |% r8 c                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, b9 L1 i, a8 H7 r  |9 e- R# t        }" S8 Y2 ^1 O0 L9 Q' U' g: n6 q
        // VRC7 (not support)
7 V9 n9 U/ D. `1 |        if( exsound_select & 0x02 ) {$ R/ m+ e+ C; T- Y) U! e
                vrc7.LoadState( p );
- F) G& n4 x. k9 Q% e/ w9 o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. N' A/ W3 ]4 d% p6 a5 X+ E8 G        }. h$ D. N, r; e( b
        // FDS
4 P/ r& F5 p: T$ }        if( exsound_select & 0x04 ) {% j* t# q( _) s5 J
                fds.LoadState( p );
3 ^9 U: r: r8 O% f1 W9 ~5 [* t/ s                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
/ V" g$ z2 W* Q8 d+ D* ?        }
; y3 {- |6 ?! ~% H# q        // MMC5  G) z" r- R" p: v  Z
        if( exsound_select & 0x08 ) {- k( _# p. U* S5 k: z$ @( V( M0 s
                mmc5.LoadState( p );9 F& C, ~9 {" S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 ~- i$ e  G4 ?4 }4 r9 A, w0 [        }
& D: K8 Z" i- H! w# X: i; M        // N106
$ u6 S0 k( j; ?1 D  J7 ?' V) y        if( exsound_select & 0x10 ) {
% X. V& m) k( X- J* I. t+ `1 ?                n106.LoadState( p );, b; [/ R" s! G9 K* S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
7 w9 I2 v* C4 _  I        }
) |3 Z  q& W3 ^& \# v7 R* I6 D# G        // FME7$ l2 H( u! u! M. d8 ^) E
        if( exsound_select & 0x20 ) {
: c% L- j# K; b" X                fme7.LoadState( p );
& |3 e! ?$ V3 a/ z6 Y) E  Y" p+ f                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ x" a$ H; _! i3 g
        }' ]0 y/ f4 O; b; ?  k
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 : o  J/ ^* i) W$ a) t  l% j# @( J
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
  P4 C2 d6 X; i8 k. [# H+ P# Q- l感激不尽~~

5 |9 @# p( w5 S/ b  c) J; }2 t9 [恩 我對模擬器不是很有研究,6 }+ J2 A* Y! k; A& }  _
雖然要了解源碼內容,可能不是很困難,
0 I5 P: U! m- T1 ?) x4 P+ _5 J/ W9 g/ z不過還是要花時間,個人目前蠻忙碌的。2 L8 Q1 u1 M: T* D2 ?  [
" Q" R5 c& Z4 c6 Q9 K
給你一個朋友的MSN,你可以跟他討論看看,6 J4 g# S0 l; @. _4 e1 J6 `
他本身是程式設計師,也對FC模擬器很有興趣。
8 l# x0 E0 C  Q* n& W
  z9 x* ~: s' m* v3 h+ OMSN我就PM到你的信箱了。
/ U4 g% e+ X" j. r8 q+ R2 o) [% d! {! r! M' `1 @1 m
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
% F4 n. e# ^" c/ d9 N8 z7 ~$ E呵…… 谢过团长大人~~
- x: n) R) @3 n+ c! U1 |
+ \; w3 b" ^- f. f  Y4 m1 e
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
& }$ h' H* o7 O, u+ ~1 V团长的朋友都是神,那团长就是神的boss。

% b( m  V5 M/ j9 `9 s: g) {哈 不敢當,我只是個平凡人,0 A4 s6 R( I' E
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ }7 W; M% Z3 I2 ~
ZYH; K$ E. v' d3 R, D# |; e. l
QQ:414734306- W# V; H/ k# j1 }8 o- @! S
Mail:zyh-01@126.com
3 ^$ z) M' [) c" Z, D, z& a& a0 d7 i8 H( A* w# L) Y5 F
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 1 \7 t, n/ W# ?$ q" e  }0 U- K
再次对团长大人和悠悠哥的无私帮助表示感谢~~
( l/ ^; |0 B) c2 {! [( ~- _. a
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-22 09:17 , Processed in 1.113282 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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