initial commit

This commit is contained in:
Thomas Jentzsch 2021-10-09 23:28:28 +02:00
parent 3de04ae8cc
commit 2921bc29de
8 changed files with 102 additions and 100 deletions

View File

@ -49,6 +49,11 @@ class Cartridge : public Device
public:
using StartBankFromPropsFunc = std::function<int()>;
/**
Callback type for general cart messages
*/
using messageCallback = std::function<void(const string&)>;
// Maximum size of a ROM cart that Stella can support
static constexpr size_t maxSize() { return 512_KB; }
@ -136,6 +141,15 @@ class Cartridge : public Device
*/
virtual bool isPlusROM() const { return false; }
/**
Set the callback for displaying messages
*/
void setMessageCallback(const messageCallback& callback)
{
if(myMsgCallback == nullptr)
myMsgCallback = &callback;
}
#ifdef DEBUGGER_SUPPORT
/**
To be called at the start of each instruction.
@ -400,6 +414,9 @@ class Cartridge : public Device
// Total size of ROM access area (might include RAM too)
uInt32 myAccessSize;
// Callback to output messages
const messageCallback* myMsgCallback{nullptr};
private:
// The startup bank to use (where to look for the reset vector address)
uInt16 myStartBank{0};

View File

@ -24,15 +24,15 @@
CartridgeAR::CartridgeAR(const ByteBuffer& image, size_t size,
const string& md5, const Settings& settings)
: Cartridge(settings, md5),
mySize{std::max<size_t>(size, 8448)}
mySize{std::max<size_t>(size, LOAD_SIZE)}
{
// Create a load image buffer and copy the given image
myLoadImages = make_unique<uInt8[]>(mySize);
myNumberOfLoadImages = uInt8(mySize / 8448);
myNumberOfLoadImages = uInt8(mySize / LOAD_SIZE);
std::copy_n(image.get(), size, myLoadImages.get());
// Add header if image doesn't include it
if(size < 8448)
if(size < LOAD_SIZE)
std::copy_n(ourDefaultHeader.data(), ourDefaultHeader.size(),
myLoadImages.get() + myImage.size());
@ -91,7 +91,7 @@ uInt8 CartridgeAR::peek(uInt16 addr)
return myImage[(addr & 0x07FF) + myImageOffset[(addr & 0x0800) ? 1 : 0]];
// Is the "dummy" SC BIOS hotspot for reading a load being accessed?
if(((addr & 0x1FFF) == 0x1850) && (myImageOffset[1] == (3 << 11)))
if(((addr & 0x1FFF) == 0x1850) && (myImageOffset[1] == RAM_SIZE))
{
// Get load that's being accessed (BIOS places load number at 0x80)
uInt8 load = mySystem->peek(0x0080);
@ -133,7 +133,7 @@ uInt8 CartridgeAR::peek(uInt16 addr)
myImage[(addr & 0x07FF) + myImageOffset[0]] = myDataHoldRegister;
mySystem->setDirtyPage(addr);
}
else if(myImageOffset[1] != (3 << 11)) // Can't poke to ROM :-)
else if(myImageOffset[1] != (3 * BANK_SIZE)) // Can't poke to ROM :-)
{
myImage[(addr & 0x07FF) + myImageOffset[1]] = myDataHoldRegister;
mySystem->setDirtyPage(addr);
@ -180,7 +180,7 @@ bool CartridgeAR::poke(uInt16 addr, uInt8)
myImage[(addr & 0x07FF) + myImageOffset[0]] = myDataHoldRegister;
modified = true;
}
else if(myImageOffset[1] != (3 << 11)) // Can't poke to ROM :-)
else if(myImageOffset[1] != (3 * BANK_SIZE)) // Can't poke to ROM :-)
{
myImage[(addr & 0x07FF) + myImageOffset[1]] = myDataHoldRegister;
modified = true;
@ -227,72 +227,22 @@ bool CartridgeAR::bankConfiguration(uInt8 configuration)
// to happen. 0 = disabled, and the cart acts like ROM.)
// p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
// wanting to access the ROM for multiloads. Otherwise set to 1.
const uInt32 OFFSET_0[8] = {2 * BANK_SIZE, 0 * BANK_SIZE, 2 * BANK_SIZE, 0 * BANK_SIZE,
2 * BANK_SIZE, 1 * BANK_SIZE, 2 * BANK_SIZE, 1 * BANK_SIZE};
const uInt32 OFFSET_1[8] = {3 * BANK_SIZE, 3 * BANK_SIZE, 0 * BANK_SIZE, 2 * BANK_SIZE,
3 * BANK_SIZE, 3 * BANK_SIZE, 1 * BANK_SIZE, 2 * BANK_SIZE};
const int bankConfig = (configuration & 0b11100) >> 2;
myCurrentBank = configuration & 0x1F; // remember for the bank() method
myCurrentBank = configuration & 0b11111; // remember for the bank() method
// Handle ROM power configuration
myPower = !(configuration & 0x01);
myPower = !(configuration & 0b00001);
myWriteEnabled = configuration & 0x02;
myWriteEnabled = configuration & 0b00010;
switch((configuration >> 2) & 0x07)
{
case 0:
{
myImageOffset[0] = 2 << 11;
myImageOffset[1] = 3 << 11;
break;
}
myImageOffset[0] = OFFSET_0[bankConfig];
myImageOffset[1] = OFFSET_1[bankConfig];
case 1:
{
myImageOffset[0] = 0 ;
myImageOffset[1] = 3 << 11;
break;
}
case 2:
{
myImageOffset[0] = 2 << 11;
myImageOffset[1] = 0 ;
break;
}
case 3:
{
myImageOffset[0] = 0 ;
myImageOffset[1] = 2 << 11;
break;
}
case 4:
{
myImageOffset[0] = 2 << 11;
myImageOffset[1] = 3 << 11;
break;
}
case 5:
{
myImageOffset[0] = 1 << 11;
myImageOffset[1] = 3 << 11;
break;
}
case 6:
{
myImageOffset[0] = 2 << 11;
myImageOffset[1] = 1 << 11;
break;
}
case 7:
{
myImageOffset[0] = 1 << 11;
myImageOffset[1] = 2 << 11;
break;
}
}
return myBankChanged = true;
}
@ -314,16 +264,16 @@ void CartridgeAR::initializeROM()
ourDummyROMCode[281] = mySystem->randGenerator().next();
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
std::fill_n(myImage.begin() + (3<<11), 2_KB, 0x02);
std::fill_n(myImage.begin() + (RAM_SIZE), BANK_SIZE, 0x02);
// Copy the "dummy" Supercharger BIOS code into the ROM area
std::copy_n(ourDummyROMCode.data(), ourDummyROMCode.size(), myImage.data() + (3<<11));
std::copy_n(ourDummyROMCode.data(), ourDummyROMCode.size(), myImage.data() + (RAM_SIZE));
// Finally set 6502 vectors to point to initial load code at 0xF80A of BIOS
myImage[(3<<11) + 2044] = 0x0A;
myImage[(3<<11) + 2045] = 0xF8;
myImage[(3<<11) + 2046] = 0x0A;
myImage[(3<<11) + 2047] = 0xF8;
myImage[(RAM_SIZE) + BANK_SIZE - 4] = 0x0A;
myImage[(RAM_SIZE) + BANK_SIZE - 3] = 0xF8;
myImage[(RAM_SIZE) + BANK_SIZE - 2] = 0x0A;
myImage[(RAM_SIZE) + BANK_SIZE - 1] = 0xF8;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -340,40 +290,48 @@ uInt8 CartridgeAR::checksum(uInt8* s, uInt16 length)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeAR::loadIntoRAM(uInt8 load)
{
bool success = true;
uInt16 image;
// Scan through all of the loads to see if we find the one we're looking for
for(image = 0; image < myNumberOfLoadImages; ++image)
{
// Is this the correct load?
if(myLoadImages[(image * 8448) + myImage.size() + 5] == load)
if(myLoadImages[(image * LOAD_SIZE) + myImage.size() + 5] == load)
{
// Copy the load's header
std::copy_n(myLoadImages.get() + (image * 8448) + myImage.size(), myHeader.size(), myHeader.data());
std::copy_n(myLoadImages.get() + (image * LOAD_SIZE) + myImage.size(), myHeader.size(), myHeader.data());
// Verify the load's header
if(checksum(myHeader.data(), 8) != 0x55)
{
cerr << "WARNING: The Supercharger header checksum is invalid...\n";
(*myMsgCallback)("Supercharger load #" + std::to_string(load) + " done with hearder checksum error");
success = false;
}
// Load all of the pages from the load
bool invalidPageChecksumSeen = false;
for(uInt32 j = 0; j < myHeader[3]; ++j)
{
uInt32 bank = myHeader[16 + j] & 0x03;
uInt32 page = (myHeader[16 + j] >> 2) & 0x07;
uInt8* src = myLoadImages.get() + (image * 8448) + (j * 256);
uInt32 bank = myHeader[16 + j] & 0b00011;
uInt32 page = (myHeader[16 + j] & 0b11100) >> 2;
uInt8* src = myLoadImages.get() + (image * LOAD_SIZE) + (j * 256);
uInt8 sum = checksum(src, 256) + myHeader[16 + j] + myHeader[64 + j];
if(!invalidPageChecksumSeen && (sum != 0x55))
{
cerr << "WARNING: Some Supercharger page checksums are invalid...\n";
(*myMsgCallback)("Supercharger load #" + std::to_string(load) + " done with page #"
+ std::to_string(j) + " checksum error");
invalidPageChecksumSeen = true;
}
// Copy page to Supercharger RAM (don't allow a copy into ROM area)
if(bank < 3)
std::copy_n(src, 256, myImage.data() + (bank * 2048) + (page * 256));
std::copy_n(src, 256, myImage.data() + (bank * BANK_SIZE) + (page * 256));
}
success &= !invalidPageChecksumSeen;
// Copy the bank switching byte and starting address into the 2600's
// RAM for the "dummy" SC BIOS to access it
@ -382,6 +340,8 @@ void CartridgeAR::loadIntoRAM(uInt8 load)
mySystem->poke(0x80, myHeader[2]);
myBankChanged = true;
if(success)
(*myMsgCallback)("Supercharger load #" + std::to_string(load) + " done");
return;
}
}
@ -442,7 +402,7 @@ bool CartridgeAR::save(Serializer& out) const
// All of the 8448 byte loads associated with the game
// Note that the size of this array is myNumberOfLoadImages * 8448
out.putByteArray(myLoadImages.get(), myNumberOfLoadImages * 8448);
out.putByteArray(myLoadImages.get(), myNumberOfLoadImages * LOAD_SIZE);
// Indicates how many 8448 loads there are
out.putByte(myNumberOfLoadImages);
@ -487,7 +447,7 @@ bool CartridgeAR::load(Serializer& in)
// All of the 8448 byte loads associated with the game
// Note that the size of this array is myNumberOfLoadImages * 8448
in.getByteArray(myLoadImages.get(), myNumberOfLoadImages * 8448);
in.getByteArray(myLoadImages.get(), myNumberOfLoadImages * LOAD_SIZE);
// Indicates how many 8448 loads there are
myNumberOfLoadImages = in.getByte();

View File

@ -43,6 +43,11 @@ class CartridgeAR : public Cartridge
{
friend class CartridgeARWidget;
public:
static constexpr uInt32 BANK_SIZE = uInt32(2_KB);
static constexpr uInt32 RAM_SIZE = 3 * BANK_SIZE;
static constexpr uInt32 LOAD_SIZE = 8448;
public:
/**
Create a new cartridge using the specified image and size

View File

@ -71,7 +71,7 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
const ByteBuffer& image, size_t size, string& md5,
const string& propertiesType, Settings& settings)
const string& propertiesType, OSystem& osystem)
{
unique_ptr<Cartridge> cartridge;
Bankswitch::Type type = Bankswitch::nameToType(propertiesType),
@ -89,7 +89,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
// See if we should try to auto-detect the cartridge type
// If we ask for extended info, always do an autodetect
if(type == Bankswitch::Type::_AUTO || settings.getBool("rominfo"))
if(type == Bankswitch::Type::_AUTO || osystem.settings().getBool("rominfo"))
{
detectedType = CartDetector::autodetectType(image, size);
if(type != Bankswitch::Type::_AUTO && type != detectedType)
@ -111,7 +111,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 2*2_KB || size == 2*4_KB || size == 2*8_KB || size == 2*16_KB || size == 2*32_KB)
{
cartridge =
createFromMultiCart(image, size, 2, md5, detectedType, id, settings);
createFromMultiCart(image, size, 2, md5, detectedType, id, osystem);
buf << id;
}
else
@ -124,7 +124,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 4*2_KB || size == 4*4_KB || size == 4*8_KB || size == 4*16_KB)
{
cartridge =
createFromMultiCart(image, size, 4, md5, detectedType, id, settings);
createFromMultiCart(image, size, 4, md5, detectedType, id, osystem);
buf << id;
}
else
@ -137,7 +137,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 8*2_KB || size == 8*4_KB || size == 8*8_KB)
{
cartridge =
createFromMultiCart(image, size, 8, md5, detectedType, id, settings);
createFromMultiCart(image, size, 8, md5, detectedType, id, osystem);
buf << id;
}
else
@ -150,7 +150,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 16*2_KB || size == 16*4_KB || size == 16*8_KB)
{
cartridge =
createFromMultiCart(image, size, 16, md5, detectedType, id, settings);
createFromMultiCart(image, size, 16, md5, detectedType, id, osystem);
buf << id;
}
else
@ -163,7 +163,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 32*2_KB || size == 32*4_KB)
{
cartridge =
createFromMultiCart(image, size, 32, md5, detectedType, id, settings);
createFromMultiCart(image, size, 32, md5, detectedType, id, osystem);
buf << id;
}
else
@ -176,7 +176,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 64*2_KB || size == 64*4_KB)
{
cartridge =
createFromMultiCart(image, size, 64, md5, detectedType, id, settings);
createFromMultiCart(image, size, 64, md5, detectedType, id, osystem);
buf << id;
}
else
@ -189,7 +189,7 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
if(size == 128*2_KB || size == 128*4_KB)
{
cartridge =
createFromMultiCart(image, size, 128, md5, detectedType, id, settings);
createFromMultiCart(image, size, 128, md5, detectedType, id, osystem);
buf << id;
}
else
@ -198,11 +198,11 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
break;
case Bankswitch::Type::_MVC:
cartridge = make_unique<CartridgeMVC>(file.getPath(), size, md5, settings);
cartridge = make_unique<CartridgeMVC>(file.getPath(), size, md5, osystem.settings());
break;
default:
cartridge = createFromImage(image, size, detectedType, md5, settings);
cartridge = createFromImage(image, size, detectedType, md5, osystem);
break;
}
@ -219,8 +219,10 @@ unique_ptr<Cartridge> CartCreator::create(const FilesystemNode& file,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Cartridge>
CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size,
uInt32 numroms, string& md5, Bankswitch::Type type, string& id, Settings& settings)
uInt32 numroms, string& md5, Bankswitch::Type type, string& id, OSystem& osystem)
{
Settings& settings = osystem.settings();
// Get a piece of the larger image
uInt32 i = settings.getInt("romloadcount");
@ -250,14 +252,16 @@ CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size,
else /* default */
type = Bankswitch::Type::_4K;
return createFromImage(slice, size, type, md5, settings);
return createFromImage(slice, size, type, md5, osystem);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Cartridge>
CartCreator::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type,
const string& md5, Settings& settings)
const string& md5, OSystem& osystem)
{
Settings& settings = osystem.settings();
// We should know the cart's type by now so let's create it
switch(type)
{

View File

@ -21,6 +21,7 @@
class Cartridge;
class Properties;
class Settings;
class OSystem;
#include "Bankswitch.hxx"
#include "bspf.hxx"
@ -47,7 +48,7 @@ class CartCreator
*/
static unique_ptr<Cartridge> create(const FilesystemNode& file,
const ByteBuffer& image, size_t size, string& md5,
const string& dtype, Settings& settings);
const string& dtype, OSystem& osystem);
private:
/**
@ -67,7 +68,7 @@ class CartCreator
static unique_ptr<Cartridge>
createFromMultiCart(const ByteBuffer& image, size_t& size,
uInt32 numroms, string& md5, Bankswitch::Type type, string& id,
Settings& settings);
OSystem& osystem);
/**
Create a cartridge from the entire image pointer.
@ -82,7 +83,8 @@ class CartCreator
*/
static unique_ptr<Cartridge>
createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type,
const string& md5, Settings& settings);
const string& md5, OSystem& osystem);
private:
// Following constructors and assignment operators not supported

View File

@ -632,8 +632,17 @@ unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile, string&
// Now create the cartridge
string cartmd5 = md5;
const string& type = props.get(PropType::Cart_Type);
const Cartridge::messageCallback callback = [&os = *this](const string& msg)
{
bool devSettings = os.settings().getBool("dev.settings");
if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
os.frameBuffer().showTextMessage(msg);
};
unique_ptr<Cartridge> cart =
CartCreator::create(romfile, image, size, cartmd5, type, *mySettings);
CartCreator::create(romfile, image, size, cartmd5, type, *this);
cart->setMessageCallback(callback);
// Some properties may not have a name set; we can't leave it blank
if(props.get(PropType::Cart_Name) == EmptyString)

View File

@ -26,6 +26,7 @@
#include "Control.hxx"
#include "M6502.hxx"
#include "M6532.hxx"
#include "MediaFactory.hxx"
#include "TIA.hxx"
#include "ConsoleTiming.hxx"
#include "FrameManager.hxx"
@ -73,6 +74,7 @@ ProfilingRunner::ProfilingRunner(int argc, char* argv[])
}
}
myOSystem = MediaFactory::createOSystem();
mySettings.setValue("fastscbios", true);
}
@ -110,7 +112,7 @@ bool ProfilingRunner::runOne(const ProfilingRun& run)
string md5 = MD5::hash(image, size);
string type = "";
unique_ptr<Cartridge> cartridge = CartCreator::create(
imageFile, image, size, md5, type, mySettings);
imageFile, image, size, md5, type, *myOSystem);
if (!cartridge) {
cout << "ERROR: unable to determine cartridge type" << endl;

View File

@ -18,6 +18,8 @@
#ifndef PROFILING_RUNNER
#define PROFILING_RUNNER
class OSystem;
#include "bspf.hxx"
#include "Control.hxx"
#include "Switches.hxx"
@ -57,6 +59,7 @@ class ProfilingRunner {
vector<ProfilingRun> profilingRuns;
unique_ptr<OSystem> myOSystem;
Settings mySettings;
Properties myProps;