📄 apu.cpp
字号:
vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
// VRC7
vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
// FDS
vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
// MMC5
vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
// N106
vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
// FME7
vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
// double cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
double cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
// CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
if( elapsed_time > nes->cpu->GetTotalCycles() ) {
QueueFlush();
}
while( dwLength-- ) {
writetime = (DWORD)elapsed_time;
while( GetQueue( writetime, q ) ) {
WriteProcess( q.addr, q.data );
}
while( GetExQueue( writetime, q ) ) {
WriteExProcess( q.addr, q.data );
}
// 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
output = 0;
output += internal.Process( 0 )*vol[0];
output += internal.Process( 1 )*vol[1];
output += internal.Process( 2 )*vol[2];
output += internal.Process( 3 )*vol[3];
output += internal.Process( 4 )*vol[4];
if( exsound_select & 0x01 ) {
output += vrc6.Process( 0 )*vol[5];
output += vrc6.Process( 1 )*vol[6];
output += vrc6.Process( 2 )*vol[7];
}
if( exsound_select & 0x02 ) {
output += vrc7.Process( 0 )*vol[8];
}
if( exsound_select & 0x04 ) {
output += fds.Process( 0 )*vol[9];
}
if( exsound_select & 0x08 ) {
output += mmc5.Process( 0 )*vol[10];
output += mmc5.Process( 1 )*vol[11];
output += mmc5.Process( 2 )*vol[12];
}
if( exsound_select & 0x10 ) {
output += n106.Process( 0 )*vol[13];
output += n106.Process( 1 )*vol[14];
output += n106.Process( 2 )*vol[15];
output += n106.Process( 3 )*vol[16];
output += n106.Process( 4 )*vol[17];
output += n106.Process( 5 )*vol[18];
output += n106.Process( 6 )*vol[19];
output += n106.Process( 7 )*vol[20];
}
if( exsound_select & 0x20 ) {
fme7.Process( 3 ); // Envelope & Noise
output += fme7.Process( 0 )*vol[21];
output += fme7.Process( 1 )*vol[22];
output += fme7.Process( 2 )*vol[23];
}
output >>= 8;
if( nFilterType == 1 ) {
//儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
output = (lowpass_filter[0]+output)/2;
lowpass_filter[0] = output;
} else if( nFilterType == 2 ) {
//儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
lowpass_filter[1] = lowpass_filter[0];
lowpass_filter[0] = output;
} else if( nFilterType == 3 ) {
//儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
lowpass_filter[2] = lowpass_filter[1];
lowpass_filter[1] = lowpass_filter[0];
lowpass_filter[0] = output;
} else if( nFilterType == 4 ) {
//儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
lowpass_filter[1] = lowpass_filter[0];
lowpass_filter[0] = output;
}
#if 0
// DC惉暘偺僇僢僩
{
static double ave = 0.0, max=0.0, min=0.0;
double delta;
delta = (max-min)/32768.0;
max -= delta;
min += delta;
if( output > max ) max = output;
if( output < min ) min = output;
ave -= ave/1024.0;
ave += (max+min)/2048.0;
output -= (INT)ave;
}
#endif
#if 1
// DC惉暘偺僇僢僩(HPF TEST)
{
// static double cutoff = (2.0*3.141592653579*40.0/44100.0);
static double cutofftemp = (2.0*3.141592653579*40.0);
double cutoff = cutofftemp/(double)Config.sound.nRate;
static double tmp = 0.0;
double in, out;
in = (double)output;
out = (in - tmp);
tmp = tmp + cutoff * out;
output = (INT)out;
}
#endif
#if 0
// 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
{
INT diff = abs(output-last_data);
if( diff > 0x4000 ) {
output /= 4;
} else
if( diff > 0x3000 ) {
output /= 3;
} else
if( diff > 0x2000 ) {
output /= 2;
}
last_data = output;
}
#endif
// Limit
if( output > 0x7FFF ) {
output = 0x7FFF;
} else if( output < -0x8000 ) {
output = -0x8000;
}
if( nBits != 8 ) {
*(SHORT*)lpBuffer = (SHORT)output;
lpBuffer += sizeof(SHORT);
} else {
*lpBuffer++ = (output>>8)^0x80;
}
if( nCcount < 0x0100 )
pSoundBuf[nCcount++] = (SHORT)output;
// elapsedtime += cycle_rate;
elapsed_time += cycle_rate;
}
#if 1
if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
elapsed_time = nes->cpu->GetTotalCycles();
}
if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
elapsed_time = nes->cpu->GetTotalCycles();
}
#else
elapsed_time = nes->cpu->GetTotalCycles();
#endif
}
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
INT APU::GetChannelFrequency( INT no )
{
if( !m_bMute[0] )
return 0;
// Internal
if( no < 5 ) {
return m_bMute[no+1]?internal.GetFreq( no ):0;
}
// VRC6
if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
return m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
}
// FDS
if( (exsound_select & 0x04) && no == 0x300 ) {
return m_bMute[6]?fds.GetFreq( 0 ):0;
}
// MMC5
if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
return m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
}
// N106
if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
return m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
}
// FME7
if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
return m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
}
// VRC7
if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
return m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
}
return 0;
}
// State Save/Load
void APU::SaveState( LPBYTE p )
{
#ifdef _DEBUG
LPBYTE pold = p;
#endif
// 帪娫幉傪摨婜偝偣傞堊Flush偡傞
QueueFlush();
internal.SaveState( p );
p += (internal.GetStateSize()+15)&(~0x0F); // Padding
// VRC6
if( exsound_select & 0x01 ) {
vrc6.SaveState( p );
p += (vrc6.GetStateSize()+15)&(~0x0F); // Padding
}
// VRC7 (not support)
if( exsound_select & 0x02 ) {
vrc7.SaveState( p );
p += (vrc7.GetStateSize()+15)&(~0x0F); // Padding
}
// FDS
if( exsound_select & 0x04 ) {
fds.SaveState( p );
p += (fds.GetStateSize()+15)&(~0x0F); // Padding
}
// MMC5
if( exsound_select & 0x08 ) {
mmc5.SaveState( p );
p += (mmc5.GetStateSize()+15)&(~0x0F); // Padding
}
// N106
if( exsound_select & 0x10 ) {
n106.SaveState( p );
p += (n106.GetStateSize()+15)&(~0x0F); // Padding
}
// FME7
if( exsound_select & 0x20 ) {
fme7.SaveState( p );
p += (fme7.GetStateSize()+15)&(~0x0F); // Padding
}
#ifdef _DEBUG
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
#endif
}
void APU::LoadState( LPBYTE p )
{
// 帪娫幉傪摨婜偝偣傞堊偵徚偡
QueueClear();
internal.LoadState( p );
p += (internal.GetStateSize()+15)&(~0x0F); // Padding
// VRC6
if( exsound_select & 0x01 ) {
vrc6.LoadState( p );
p += (vrc6.GetStateSize()+15)&(~0x0F); // Padding
}
// VRC7 (not support)
if( exsound_select & 0x02 ) {
vrc7.LoadState( p );
p += (vrc7.GetStateSize()+15)&(~0x0F); // Padding
}
// FDS
if( exsound_select & 0x04 ) {
fds.LoadState( p );
p += (fds.GetStateSize()+15)&(~0x0F); // Padding
}
// MMC5
if( exsound_select & 0x08 ) {
mmc5.LoadState( p );
p += (mmc5.GetStateSize()+15)&(~0x0F); // Padding
}
// N106
if( exsound_select & 0x10 ) {
n106.LoadState( p );
p += (n106.GetStateSize()+15)&(~0x0F); // Padding
}
// FME7
if( exsound_select & 0x20 ) {
fme7.LoadState( p );
p += (fme7.GetStateSize()+15)&(~0x0F); // Padding
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -