diff --git a/src/emucore/CartBUS.cxx b/src/emucore/CartBUS.cxx index aae86c48b..8b2ff9636 100644 --- a/src/emucore/CartBUS.cxx +++ b/src/emucore/CartBUS.cxx @@ -69,7 +69,7 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size, static_cast(32_KB), 0x00000800, 0x00000808, - 0x40001FDC, + 0x40001FFC, devSettings ? settings.getBool("dev.thumb.trapfatal") : false, devSettings ? static_cast( settings.getFloat("dev.thumb.cyclefactor")) : 1.0, diff --git a/src/emucore/CartCDF.cxx b/src/emucore/CartCDF.cxx index 1c81ff681..1f1b9f154 100644 --- a/src/emucore/CartCDF.cxx +++ b/src/emucore/CartCDF.cxx @@ -95,7 +95,7 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size, } else { cBase = 0x800; // C Base Address cStart = 0x808; // C Start Address (skip ARM header) - cStack = 0x40001FDC; // C Stack + cStack = 0x40001FFC; // C Stack } // Create Thumbulator ARM emulator diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx index eb32e5eb2..e24317438 100644 --- a/src/emucore/CartDPCPlus.cxx +++ b/src/emucore/CartDPCPlus.cxx @@ -55,7 +55,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size, static_cast(32_KB), 0x00000C00, 0x00000C08, - 0x40001FDC, + 0x40001FFC, devSettings ? settings.getBool("dev.thumb.trapfatal") : false, devSettings ? static_cast( settings.getFloat("dev.thumb.cyclefactor")) : 1.0, diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index a71f2cb5c..add92d874 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -353,11 +353,6 @@ uInt32 Thumbulator::fetch16(uInt32 addr) void Thumbulator::write16(uInt32 addr, uInt32 data) { #ifndef UNSAFE_OPTIMIZATIONS - if((addr > 0x40007fff) && (addr < 0x50000000)) - fatalError("write16", addr, "abort - out of range"); - - if (isProtected(addr)) fatalError("write16", addr, "to driver area"); - if(addr & 1) fatalError("write16", addr, "abort - misaligned"); #endif @@ -370,6 +365,12 @@ void Thumbulator::write16(uInt32 addr, uInt32 data) switch(addr & 0xF0000000) { case 0x40000000: //RAM +#ifndef UNSAFE_OPTIMIZATIONS + if(isInvalidRAM(addr)) + fatalError("write16", addr, "abort - out of range"); + if(isProtectedRAM(addr)) + fatalError("write16", addr, "to driver area"); +#endif addr &= RAMADDMASK; addr >>= 1; ram[addr] = CONV_DATA(data); @@ -399,8 +400,6 @@ void Thumbulator::write32(uInt32 addr, uInt32 data) #ifndef UNSAFE_OPTIMIZATIONS if(addr & 3) fatalError("write32", addr, "abort - misaligned"); - - if (isProtected(addr)) fatalError("write32", addr, "to driver area"); #endif DO_DBUG(statusMsg << "write32(" << Base::HEX8 << addr << "," << Base::HEX8 << data << ")" << endl); @@ -546,34 +545,96 @@ void Thumbulator::write32(uInt32 addr, uInt32 data) #ifndef UNSAFE_OPTIMIZATIONS // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Thumbulator::isProtected(uInt32 addr) +bool Thumbulator::isInvalidROM(uInt32 addr) +{ + const uInt32 romStart = configuration == ConfigureFor::DPCplus ? 0xc00 : 0x750; // was 0x800 + + switch(romSize) + { + case 64_KB: + if(!(addr >= romStart && addr <= 0x0FFFF)) + return true; + break; + + case 128_KB: + if(!(addr >= romStart && addr <= 0x1FFFF)) + return true; + break; + + case 256_KB: + if(!(addr >= romStart && addr <= 0x3FFFF)) + return true; + break; + + case 512_KB: + if(!(addr >= romStart && addr <= 0x7FFFF)) + return true; + break; + + default: // assuming 32 KB + if(!(addr >= romStart && addr <= 0x07FFF)) + return true; + break; + } + + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Thumbulator::isInvalidRAM(uInt32 addr) +{ + // Note: addr is already checked for RAM (0x4xxxxxxx) + switch(romSize) + { + case 64_KB: + case 128_KB: + if(addr > 0x40003fff) + return true; + break; + + case 256_KB: + case 512_KB: + if(addr > 0x40007fff) + return true; + break; + + default: // assuming 32 KB + if(addr > 0x40001fff) + return true; + break; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Thumbulator::isProtectedRAM(uInt32 addr) { // Protected is within the driver RAM. // For CDF variations parts of the driver RAM are reused to hold the - // datastream information, so is not protected. + // datastream information, so are not write protected. // Additionally for CDFJ+ the Fast Fetcher offset is not write protected. - + if (addr < 0x40000000) return false; addr -= 0x40000000; - switch (configuration) { + switch(configuration) { case ConfigureFor::DPCplus: return (addr < 0x0c00) && (addr > 0x0028); case ConfigureFor::CDF: - return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x06e0) && (addr < (0x0e60 + 284))); + return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x06e0) && (addr < (0x0e60 + 284))); case ConfigureFor::CDF1: - return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x00a0) && (addr < (0x00a0 + 284))); + return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x00a0) && (addr < (0x00a0 + 284))); case ConfigureFor::CDFJ: - return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))); + return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))); case ConfigureFor::CDFJplus: - return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))) && addr != 0x3E0; + return (addr < 0x0800) && (addr > 0x0028) && !((addr >= 0x0098) && (addr < (0x0098 + 292))) && addr != 0x3E0; case ConfigureFor::BUS: - return (addr < 0x06d8) && (addr > 0x0028); + return (addr < 0x06d8) && (addr > 0x0028); } return false; @@ -585,10 +646,6 @@ uInt32 Thumbulator::read16(uInt32 addr) { uInt32 data; #ifndef UNSAFE_OPTIMIZATIONS - if((addr > 0x40007fff) && (addr < 0x50000000)) - fatalError("read16", addr, "abort - out of range"); - else if((addr > 0x0007ffff) && (addr < 0x10000000)) - fatalError("read16", addr, "abort - out of range"); if(addr & 1) fatalError("read16", addr, "abort - misaligned"); #endif @@ -599,6 +656,10 @@ uInt32 Thumbulator::read16(uInt32 addr) switch(addr & 0xF0000000) { case 0x00000000: //ROM +#ifndef UNSAFE_OPTIMIZATIONS + if(isInvalidROM(addr)) + fatalError("read16", addr, "abort - out of range"); +#endif addr &= ROMADDMASK; addr >>= 1; data = CONV_RAMROM(rom[addr]); @@ -606,6 +667,10 @@ uInt32 Thumbulator::read16(uInt32 addr) return data; case 0x40000000: //RAM +#ifndef UNSAFE_OPTIMIZATIONS + if(isInvalidRAM(addr)) + fatalError("read16", addr, "abort - out of range"); +#endif addr &= RAMADDMASK; addr >>= 1; data = CONV_RAMROM(ram[addr]); @@ -641,7 +706,20 @@ uInt32 Thumbulator::read32(uInt32 addr) switch(addr & 0xF0000000) { case 0x00000000: //ROM +#ifndef UNSAFE_OPTIMIZATIONS + if(isInvalidROM(addr)) + fatalError("read32", addr, "abort - out of range"); +#endif + data = read16(addr+0); + data |= (uInt32(read16(addr+2))) << 16; + DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl); + return data; + case 0x40000000: //RAM +#ifndef UNSAFE_OPTIMIZATIONS + if(isInvalidRAM(addr)) + fatalError("read32", addr, "abort - out of range"); +#endif data = read16(addr+0); data |= (uInt32(read16(addr+2))) << 16; DO_DBUG(statusMsg << "read32(" << Base::HEX8 << addr << ")=" << Base::HEX8 << data << endl); diff --git a/src/emucore/Thumbulator.hxx b/src/emucore/Thumbulator.hxx index 33823f33f..6496bcbd6 100644 --- a/src/emucore/Thumbulator.hxx +++ b/src/emucore/Thumbulator.hxx @@ -228,7 +228,9 @@ class Thumbulator uInt32 read16(uInt32 addr); uInt32 read32(uInt32 addr); #ifndef UNSAFE_OPTIMIZATIONS - bool isProtected(uInt32 addr); + bool isInvalidROM(uInt32 addr); + bool isInvalidRAM(uInt32 addr); + bool isProtectedRAM(uInt32 addr); #endif void write16(uInt32 addr, uInt32 data); void write32(uInt32 addr, uInt32 data);