diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index a68435815..d0af5c564 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -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)