Fix some common errors causing crashes when ROM sizes aren't what we expect (fixes #654).

This commit is contained in:
Stephen Anthony 2020-06-07 14:49:27 -02:30
parent edcf1d3c9d
commit 5f2fbc8618
26 changed files with 109 additions and 71 deletions

View File

@ -131,6 +131,15 @@ namespace BSPF
// Maximum size of a ROM that Stella can support // Maximum size of a ROM that Stella can support
inline constexpr size_t romMaxSize() { return 512_KB; } inline constexpr size_t romMaxSize() { return 512_KB; }
// Get next power of two greater than or equal to the given value
inline size_t nextPowerOfTwo(size_t size) {
if(size < 2) return 1;
size_t power2 = 1;
while(power2 < size)
power2 <<= 1;
return power2;
}
// Make 2D-arrays using std::array less verbose // Make 2D-arrays using std::array less verbose
template<typename T, size_t ROW, size_t COL> template<typename T, size_t ROW, size_t COL>
using array2D = std::array<std::array<T, COL>, ROW>; using array2D = std::array<std::array<T, COL>, ROW>;

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge0840::Cartridge0840(const ByteBuffer& image, size_t size, Cartridge0840::Cartridge0840(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 8_KB, md5, settings)
{ {
} }

View File

@ -21,38 +21,6 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size, Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 2_KB, md5, settings)
{ {
// Size can be a maximum of 2K
if(size > 2_KB)
size = 2_KB;
// Set image size to closest power-of-two for the given size
mySize = 1; myBankShift = 0;
while(mySize < size)
{
mySize <<= 1;
myBankShift++;
}
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
size_t bufSize = std::max<size_t>(mySize, System::PAGE_SIZE);
myImage = make_unique<uInt8[]>(bufSize);
std::fill_n(myImage.get(), bufSize, 0x02);
// Handle cases where ROM is smaller than the page size
// It's much easier to do it this way rather than changing the page size
if(mySize >= System::PAGE_SIZE)
{
// Directly copy the ROM image into the buffer
std::copy_n(image.get(), mySize, myImage.get());
}
else
{
// Manually 'mirror' the ROM image into the buffer
for(size_t i = 0; i < System::PAGE_SIZE; i += mySize)
std::copy_n(image.get(), mySize, myImage.get() + i);
mySize = System::PAGE_SIZE;
myBankShift = 6;
}
} }

View File

@ -22,7 +22,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size, Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, BSPF::nextPowerOfTwo(size), md5, settings)
{ {
myBankShift = BANK_SHIFT; myBankShift = BANK_SHIFT;
myRamSize = RAM_SIZE; myRamSize = RAM_SIZE;

View File

@ -22,7 +22,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3F::Cartridge3F(const ByteBuffer& image, size_t size, Cartridge3F::Cartridge3F(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, BSPF::nextPowerOfTwo(size), md5, settings)
{ {
myBankShift = BANK_SHIFT; myBankShift = BANK_SHIFT;
} }

View File

@ -21,6 +21,6 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge4K::Cartridge4K(const ByteBuffer& image, size_t size, Cartridge4K::Cartridge4K(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 4_KB, md5, settings)
{ {
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size, CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 256_KB, md5, settings)
{ {
} }

View File

@ -21,23 +21,19 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCV::CartridgeCV(const ByteBuffer& image, size_t size, CartridgeCV::CartridgeCV(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 2_KB, md5, settings)
{ {
myBankShift = BANK_SHIFT; myBankShift = BANK_SHIFT;
myRamSize = RAM_SIZE; myRamSize = RAM_SIZE;
myRamWpHigh = RAM_HIGH_WP; myRamWpHigh = RAM_HIGH_WP;
if(mySize == 4_KB) if(size == 4_KB)
{ {
// The game has something saved in the RAM // The game has something saved in the RAM
// Useful for MagiCard program listings // Useful for MagiCard program listings
// Allocate array for the ROM image
mySize = 2_KB;
myImage = make_unique<uInt8[]>(mySize);
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
std::copy_n(image.get() + mySize, mySize, myImage.get()); std::copy_n(image.get() + 2_KB, 2_KB, myImage.get());
myInitialRAM = make_unique<uInt8[]>(1_KB); myInitialRAM = make_unique<uInt8[]>(1_KB);
// Copy the RAM image into a buffer for use in reset() // Copy the RAM image into a buffer for use in reset()

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size, CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 128_KB, md5, settings)
{ {
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size, CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 8_KB, md5, settings)
{ {
myBankShift = BANK_SHIFT; myBankShift = BANK_SHIFT;
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size, CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 64_KB, md5, settings)
{ {
} }

View File

@ -15,20 +15,84 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================ //============================================================================
#include "Logger.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartEnhanced.hxx" #include "CartEnhanced.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size, CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) size_t bsSize, const string& md5,
: Cartridge(settings, md5), const Settings& settings)
mySize(size) : Cartridge(settings, md5)
{ {
// Allocate array for the ROM image (at least 64 bytzes) // ROMs are not always at the 'legal' size for their associated
myImage = make_unique<uInt8[]>(std::max(uInt32(mySize), uInt32(System::PAGE_SIZE))); // bankswitching scheme; here we deal with the differing sizes
if(size != bsSize)
{
// Is the ROM too large? If so, we cap it
if(size > bsSize)
{
ostringstream buf;
buf << "ROM larger than expected (" << size << " > " << bsSize << "), truncating\n";
Logger::info(buf.str());
// Copy the ROM image into my buffer size = bsSize;
std::copy_n(image.get(), mySize, myImage.get()); }
// Set image size to closest power-of-two for the given size
// This only applies for sizes less than the standard bank size
if(size < 4_KB)
{
mySize = 1; myBankShift = 0;
while(mySize < size)
{
mySize <<= 1;
myBankShift++;
}
}
else
mySize = size;
// Initialize ROM with all 0's, to fill areas that the ROM may not cover
size_t bufSize = std::max<size_t>(mySize, System::PAGE_SIZE);
myImage = make_unique<uInt8[]>(bufSize);
std::fill_n(myImage.get(), bufSize, 0);
// Handle cases where ROM is smaller than the page size
// It's much easier to do it this way rather than changing the page size
if(mySize >= System::PAGE_SIZE)
{
if(size < mySize)
{
ostringstream buf;
buf << "ROM smaller than expected (" << mySize << " > " << size
<< "), appending " << (mySize - size) << " bytes\n";
Logger::info(buf.str());
}
// TODO: should we mirror here too??
// Directly copy the ROM image into the buffer
std::copy_n(image.get(), mySize, myImage.get());
}
else
{
// Manually 'mirror' the ROM image into the buffer
for(size_t i = 0; i < System::PAGE_SIZE; i += mySize)
std::copy_n(image.get(), mySize, myImage.get() + i);
mySize = System::PAGE_SIZE;
myBankShift = 6;
}
}
else
{
mySize = size;
// Allocate array for the ROM image
myImage = make_unique<uInt8[]>(mySize);
// Copy the ROM image into my buffer
std::copy_n(image.get(), mySize, myImage.get());
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -42,10 +42,11 @@ class CartridgeEnhanced : public Cartridge
@param image Pointer to the ROM image @param image Pointer to the ROM image
@param size The size of the ROM image @param size The size of the ROM image
@param md5 The md5sum of the ROM image @param md5 The md5sum of the ROM image
@param bsSize The size specified by the bankswitching scheme
@param settings A reference to the various settings (read-only) @param settings A reference to the various settings (read-only)
*/ */
CartridgeEnhanced(const ByteBuffer& image, size_t size, const string& md5, CartridgeEnhanced(const ByteBuffer& image, size_t size, size_t bsSize,
const Settings& settings); const string& md5, const Settings& settings);
virtual ~CartridgeEnhanced() = default; virtual ~CartridgeEnhanced() = default;
public: public:

View File

@ -20,7 +20,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF0::CartridgeF0(const ByteBuffer& image, size_t size, CartridgeF0::CartridgeF0(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 64_KB, md5, settings)
{ {
} }

View File

@ -20,7 +20,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF4::CartridgeF4(const ByteBuffer& image, size_t size, CartridgeF4::CartridgeF4(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 32_KB, md5, settings)
{ {
} }

View File

@ -20,7 +20,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size, CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 16_KB, md5, settings)
{ {
} }

View File

@ -20,7 +20,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF8::CartridgeF8(const ByteBuffer& image, size_t size, CartridgeF8::CartridgeF8(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 8_KB, md5, settings)
{ {
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFA::CartridgeFA(const ByteBuffer& image, size_t size, CartridgeFA::CartridgeFA(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 12_KB, md5, settings)
{ {
myRamSize = RAM_SIZE; myRamSize = RAM_SIZE;
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size, CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, BSPF::nextPowerOfTwo(size), md5, settings)
{ {
} }

View File

@ -22,7 +22,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFE::CartridgeFE(const ByteBuffer& image, size_t size, CartridgeFE::CartridgeFE(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 8_KB, md5, settings)
{ {
myDirectPeek = false; myDirectPeek = false;
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeMDM::CartridgeMDM(const ByteBuffer& image, size_t size, CartridgeMDM::CartridgeMDM(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, BSPF::nextPowerOfTwo(size), md5, settings)
{ {
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeSB::CartridgeSB(const ByteBuffer& image, size_t size, CartridgeSB::CartridgeSB(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, BSPF::nextPowerOfTwo(size), md5, settings)
{ {
} }

View File

@ -21,7 +21,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeTVBoy::CartridgeTVBoy(const ByteBuffer& image, size_t size, CartridgeTVBoy::CartridgeTVBoy(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 512_KB, md5, settings)
{ {
} }

View File

@ -22,7 +22,7 @@
CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size, CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings, const string& md5, const Settings& settings,
bool swapHotspots) bool swapHotspots)
: CartridgeEnhanced(image, size, md5, settings), : CartridgeEnhanced(image, size, 8_KB, md5, settings),
mySwappedHotspots(swapHotspots) mySwappedHotspots(swapHotspots)
{ {
} }

View File

@ -23,10 +23,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size, CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 8_KB, md5, settings)
{ {
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
if (mySize == 8_KB + 3) if(size == 8_KB + 3)
{ {
// swap banks 2 & 3 of bad dump and correct size // swap banks 2 & 3 of bad dump and correct size
std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.get() + 1_KB * 2); std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.get() + 1_KB * 2);

View File

@ -23,7 +23,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeX07::CartridgeX07(const ByteBuffer& image, size_t size, CartridgeX07::CartridgeX07(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings) const string& md5, const Settings& settings)
: CartridgeEnhanced(image, size, md5, settings) : CartridgeEnhanced(image, size, 64_KB, md5, settings)
{ {
} }