- [NEW] Canal 4 (ruido) implementat. Encara no sona be
This commit is contained in:
71
APU.cpp
71
APU.cpp
@@ -26,6 +26,7 @@ namespace APU
|
||||
#define DAC1_enabled ((NR12&0xf8)!=0)
|
||||
#define DAC2_enabled ((NR22&0xf8)!=0)
|
||||
#define DAC3_enabled ((NR30&0x80)!=0)
|
||||
#define DAC4_enabled ((NR42&0xf8)!=0)
|
||||
|
||||
uint8_t duty_cycles[4][8] = {
|
||||
{1, 1, 1, 1, 1, 1, 1, 0},
|
||||
@@ -74,6 +75,7 @@ namespace APU
|
||||
uint8_t NR52 = 0; // 0xff26 - Sound on/off
|
||||
// 0xff27-0xff2f - Not used?
|
||||
uint8_t WaveRAM[16]; // 0xff30-0xff3f
|
||||
uint16_t LFSR = 0;
|
||||
|
||||
|
||||
void audioCallback(void * userdata, uint8_t * stream, int len)
|
||||
@@ -127,6 +129,17 @@ namespace APU
|
||||
NR51 = 0;
|
||||
NR52 = 0;
|
||||
CH1.duty_cycle = 0;
|
||||
LFSR = 0;
|
||||
for (int i=0; i<16; ++i) WaveRAM[i]=0;
|
||||
}
|
||||
|
||||
uint8_t getLFSR()
|
||||
{
|
||||
LFSR = (LFSR&0x7fff) | ( (LFSR&1)==((LFSR>>1)&1) ? 0x8000 : 0x0000 );
|
||||
if (NR43&0x08) LFSR = (LFSR&0xff7f) | ((LFSR>>8)&0x0080);
|
||||
LFSR=LFSR>>1;
|
||||
|
||||
return LFSR&1;
|
||||
}
|
||||
|
||||
void triggerCH1()
|
||||
@@ -159,6 +172,17 @@ namespace APU
|
||||
// sweep does several things (check documentation)
|
||||
}
|
||||
|
||||
void triggerCH4()
|
||||
{
|
||||
CH4.enabled = true;
|
||||
CH4.length_timer=NR41&0x3f;
|
||||
uint8_t clock_shift = ((NR43&0xf0)>>4);// if (clock_shift==0) clock_shift = 1;
|
||||
CH4.period_divider = clock_shift << (NR43&0x07);
|
||||
// envelope timer is reset
|
||||
CH4.volume = NR42>>4;
|
||||
// sweep does several things (check documentation)
|
||||
}
|
||||
|
||||
uint8_t readRegister(uint16_t address)
|
||||
{
|
||||
switch(address)
|
||||
@@ -180,6 +204,11 @@ namespace APU
|
||||
case 0xff1d: return 0x00; break;
|
||||
case 0xff1e: return NR34 & 0x40; break;
|
||||
|
||||
case 0xff20: return 0x00; break;
|
||||
case 0xff21: return NR42; break;
|
||||
case 0xff22: return NR43; break;
|
||||
case 0xff23: return NR44 & 0x40; break;
|
||||
|
||||
case 0xff24: return NR50; break;
|
||||
case 0xff25: return NR51; break;
|
||||
case 0xff26: return NR52; break;
|
||||
@@ -227,6 +256,11 @@ namespace APU
|
||||
case 0xff1d: NR33 = value; break;
|
||||
case 0xff1e: NR34 = value; CH3.length_enable=(value&0x40); if (value&0x80) triggerCH3(); break;
|
||||
|
||||
case 0xff20: NR41 = value; CH1.length_timer=NR11&0x3f; CH1.duty_cycle = NR11>>6; break;
|
||||
case 0xff21: NR42 = value; break;
|
||||
case 0xff22: NR43 = value; break;
|
||||
case 0xff23: NR44 = value; CH4.length_enable=(value&0x40); if (value&0x80) triggerCH4(); break;
|
||||
|
||||
case 0xff24: NR50 = value; break;
|
||||
case 0xff25: NR51 = value; break;
|
||||
case 0xff26: if (value&0x80) reset(); NR52 = (value&0x80) | (NR52 & 0x0f); break;
|
||||
@@ -284,6 +318,14 @@ namespace APU
|
||||
CH3.length_timer++;
|
||||
}
|
||||
}
|
||||
if (CH4.enabled && CH4.length_enable) {
|
||||
if (CH4.length_timer==63) {
|
||||
CH4.enabled = false;
|
||||
CH4.length_timer=0;
|
||||
} else {
|
||||
CH4.length_timer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
DIVAPU_CH1_freq_sweep++;
|
||||
if (DIVAPU_CH1_freq_sweep==4) {
|
||||
@@ -315,13 +357,23 @@ namespace APU
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do the envelope sweep thing
|
||||
if ( CH4.enabled && (NR42&0x7) ) { // If sweep pace != 0, envelope sweep is enabled
|
||||
CH4.envelope_sweep_timer++;
|
||||
if ( CH4.envelope_sweep_timer == (NR42&0x07) ) { // if timer == envelope sweep, increase or decrease volume
|
||||
CH4.envelope_sweep_timer=0;
|
||||
if (NR42&0x8) { // bit set increases, reset decreases
|
||||
if (CH4.volume<0x0f) CH4.volume++;
|
||||
} else {
|
||||
if (CH4.volume>0) CH4.volume--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t dots = 0;
|
||||
uint32_t dotsCH3 = 0;
|
||||
uint32_t dotsCH4 = 0;
|
||||
void update(uint32_t dt)
|
||||
{
|
||||
dots += dt;
|
||||
@@ -350,6 +402,16 @@ namespace APU
|
||||
if (CH3.duty_step==32) CH3.duty_step=0;
|
||||
}
|
||||
}
|
||||
dotsCH4 += dt;
|
||||
while (dotsCH4>=16) {
|
||||
dotsCH4 -= 16;
|
||||
CH4.period_divider--;
|
||||
if (CH4.period_divider==0) {
|
||||
uint8_t clock_shift = ((NR43&0xf0)>>3); if (clock_shift==0) clock_shift = 1;
|
||||
CH4.period_divider = clock_shift << (NR43&0x07);
|
||||
CH4.duty_step=getLFSR();
|
||||
}
|
||||
}
|
||||
|
||||
t_sound += dt;
|
||||
samples_t += dt;
|
||||
@@ -369,7 +431,10 @@ namespace APU
|
||||
sampleCH3 = CH3.volume==0 ? 0 : CH3.volume==1 ? actual_sample : CH3.volume==2 ? actual_sample>>1 : actual_sample>>2;
|
||||
}
|
||||
|
||||
uint8_t sample = (sampleCH1+sampleCH2+sampleCH3)&0xff;
|
||||
uint16_t sampleCH4 = 0;
|
||||
if (apu_enabled && DAC4_enabled) sampleCH4 = (CH4.duty_step*CH4.volume)<<2;
|
||||
|
||||
uint8_t sample = (sampleCH1+sampleCH2+sampleCH3+sampleCH4)&0xff;
|
||||
|
||||
sound_buffer[(sound_pos++)&(AUDIO_BUFFER_SIZE-1)] = sample;
|
||||
audio_viewer::addsample(sample);
|
||||
|
||||
Reference in New Issue
Block a user