Added sanity checks to all RAM accesses in the GUS code, fixes #3790.

This commit is contained in:
OBattler
2023-10-31 21:47:45 +01:00
parent 69a5fbd01e
commit 9737a2c800

View File

@@ -427,7 +427,8 @@ writegus(uint16_t addr, uint8_t val, void *priv)
if (gus->voices < 14)
gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0));
else
gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
gus->samp_latch = (uint64_t) (TIMER_USEC *
(1000000.0 / gusfreqs[gus->voices - 14]));
break;
case 0x41: /*DMA*/
@@ -437,15 +438,28 @@ writegus(uint16_t addr, uint8_t val, void *priv)
while (c < 65536) {
int dma_result;
if (val & 0x04) {
uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1);
d = gus->ram[gus_addr] | (gus->ram[gus_addr + 1] << 8);
uint32_t gus_addr = (gus->dmaaddr & 0xc0000) |
((gus->dmaaddr & 0x1ffff) << 1);
if (gus_addr < gus->gus_end_ram)
d = gus->ram[gus_addr];
else
d = 0x00;
if ((gus_addr + 1) < gus->gus_end_ram)
d |= (gus->ram[gus_addr + 1] << 8);
if (val & 0x80)
d ^= 0x8080;
dma_result = dma_channel_write(gus->dma, d);
if (dma_result == DMA_NODATA)
break;
} else {
d = gus->ram[gus->dmaaddr];
if (gus->dmaaddr < gus->gus_end_ram)
d = gus->ram[gus->dmaaddr];
else
d = 0x00;
if (val & 0x80)
d ^= 0x80;
dma_result = dma_channel_write(gus->dma, d);
@@ -453,7 +467,7 @@ writegus(uint16_t addr, uint8_t val, void *priv)
break;
}
gus->dmaaddr++;
gus->dmaaddr &= 0xFFFFF;
gus->dmaaddr &= 0xfffff;
c++;
if (dma_result & DMA_OVER)
break;
@@ -467,18 +481,25 @@ writegus(uint16_t addr, uint8_t val, void *priv)
if (d == DMA_NODATA)
break;
if (val & 0x04) {
uint32_t gus_addr = (gus->dmaaddr & 0xc0000) | ((gus->dmaaddr & 0x1ffff) << 1);
uint32_t gus_addr = (gus->dmaaddr & 0xc0000) |
((gus->dmaaddr & 0x1ffff) << 1);
if (val & 0x80)
d ^= 0x8080;
gus->ram[gus_addr] = d & 0xff;
gus->ram[gus_addr + 1] = (d >> 8) & 0xff;
if (gus_addr < gus->gus_end_ram)
gus->ram[gus_addr] = d & 0xff;
if ((gus_addr + 1) < gus->gus_end_ram)
gus->ram[gus_addr + 1] = (d >> 8) & 0xff;
} else {
if (val & 0x80)
d ^= 0x80;
gus->ram[gus->dmaaddr] = d;
if (gus->dmaaddr < gus->gus_end_ram)
gus->ram[gus->dmaaddr] = d;
}
gus->dmaaddr++;
gus->dmaaddr &= 0xFFFFF;
gus->dmaaddr &= 0xfffff;
c++;
if (d & DMA_OVER)
break;
@@ -494,28 +515,20 @@ writegus(uint16_t addr, uint8_t val, void *priv)
break;
case 0x43: /*Address low*/
gus->addr = (gus->addr & 0xF00FF) | (val << 8);
gus->addr = (gus->addr & 0xf00ff) | (val << 8);
break;
case 0x44: /*Address high*/
gus->addr = (gus->addr & 0xFFFF) | ((val << 16) & 0xF0000);
gus->addr = (gus->addr & 0x0ffff) | ((val << 16) & 0xf0000);
break;
case 0x45: /*Timer control*/
if (!(val & 4))
gus->irqstatus &= ~4;
if (!(val & 8))
gus->irqstatus &= ~8;
if (!(val & 0x20)) {
if (!(val & 0x20))
gus->ad_status &= ~0x18;
#ifdef OLD_NMI_BEHAVIOR
nmi = 0;
#endif
}
if (!(val & 0x02)) {
if (!(val & 0x02))
gus->ad_status &= ~0x01;
#ifdef OLD_NMI_BEHAVIOR
nmi = 0;
#endif
}
gus->tctrl = val;
gus->sb_ctrl = val;
gus_update_int_status(gus);
@@ -540,7 +553,7 @@ writegus(uint16_t addr, uint8_t val, void *priv)
case 0x307: /*DRAM access*/
if (gus->addr < gus->gus_end_ram)
gus->ram[gus->addr] = val;
gus->addr &= 0xFFFFF;
gus->addr &= 0xfffff;
break;
case 0x208:
case 0x388:
@@ -874,8 +887,7 @@ readgus(uint16_t addr, void *priv)
break;
case 0x307: /*DRAM access*/
val = gus->ram[gus->addr];
gus->addr &= 0xFFFFF;
gus->addr &= 0xfffff;
if (gus->addr < gus->gus_end_ram)
val = gus->ram[gus->addr];
else
@@ -1034,21 +1046,41 @@ gus_poll_wave(void *priv)
if (gus->ctrl[d] & 4) {
addr = gus->cur[d] >> 9;
addr = (addr & 0xC0000) | ((addr << 1) & 0x3FFFE);
if (!(gus->freq[d] >> 10)) /*Interpolate*/
{
vl = (int16_t) (int8_t) ((gus->ram[(addr + 1) & 0xFFFFF] ^ 0x80) - 0x80) * (511 - (gus->cur[d] & 511));
vl += (int16_t) (int8_t) ((gus->ram[(addr + 3) & 0xFFFFF] ^ 0x80) - 0x80) * (gus->cur[d] & 511);
if (!(gus->freq[d] >> 10)) {
/* Interpolate */
if (((addr + 1) & 0xfffff) < gus->gus_end_ram)
vl = (int16_t) (int8_t) ((gus->ram[(addr + 1) & 0xfffff] ^ 0x80) - 0x80) *
(511 - (gus->cur[d] & 511));
else
vl = 0;
if (((addr + 3) & 0xfffff) < gus->gus_end_ram)
vl += (int16_t) (int8_t) ((gus->ram[(addr + 3) & 0xfffff] ^ 0x80) - 0x80) *
(gus->cur[d] & 511);
v = vl >> 9;
} else
v = (int16_t) (int8_t) ((gus->ram[(addr + 1) & 0xFFFFF] ^ 0x80) - 0x80);
} else if (((addr + 1) & 0xfffff) < gus->gus_end_ram)
v = (int16_t) (int8_t) ((gus->ram[(addr + 1) & 0xfffff] ^ 0x80) - 0x80);
else
v = 0x0000;
} else {
if (!(gus->freq[d] >> 10)) /*Interpolate*/
{
vl = ((int8_t) ((gus->ram[(gus->cur[d] >> 9) & 0xFFFFF] ^ 0x80) - 0x80)) * (511 - (gus->cur[d] & 511));
vl += ((int8_t) ((gus->ram[((gus->cur[d] >> 9) + 1) & 0xFFFFF] ^ 0x80) - 0x80)) * (gus->cur[d] & 511);
if (!(gus->freq[d] >> 10)) {
/* Interpolate */
if (((gus->cur[d] >> 9) & 0xfffff) < gus->gus_end_ram)
vl = ((int8_t) ((gus->ram[(gus->cur[d] >> 9) & 0xfffff] ^ 0x80) - 0x80)) *
(511 - (gus->cur[d] & 511));
else
vl = 0;
if ((((gus->cur[d] >> 9) + 1) & 0xfffff) < gus->gus_end_ram)
vl += ((int8_t) ((gus->ram[((gus->cur[d] >> 9) + 1) & 0xfffff] ^ 0x80) - 0x80)) *
(gus->cur[d] & 511);
v = vl >> 9;
} else
v = (int16_t) (int8_t) ((gus->ram[(gus->cur[d] >> 9) & 0xFFFFF] ^ 0x80) - 0x80);
} else if (((gus->cur[d] >> 9) & 0xfffff) < gus->gus_end_ram)
v = (int16_t) (int8_t) ((gus->ram[(gus->cur[d] >> 9) & 0xfffff] ^ 0x80) - 0x80);
else
v = 0x0000;
}
if ((gus->rcur[d] >> 14) > 4095)