Fairly huge refactoring of the cart autodetection code.

This has been in patch form for about a year, and I'm finally
getting around to applying it.  Basically, we separate the Cart
class into 3 classes:
  - Cart: stuff specific to cartridge emulation
  - BSTypes: various bankswitch types, both as enum and strings
  - CartDetector: actual bankswitch auto-detection code

Also made more use of smart pointers, and added const in a few
more places.

I promise to get back to the phosphor stuff soon.  This is just
to clear my head a little.
This commit is contained in:
Stephen Anthony 2017-07-02 19:27:27 -02:30
parent 2e776b05b8
commit 9972af022a
100 changed files with 4842 additions and 4640 deletions

View File

@ -59,7 +59,7 @@
Debugger* Debugger::myStaticDebugger = nullptr;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const char* builtin_functions[][3] = {
static const char* const builtin_functions[][3] = {
// { "name", "definition", "help text" }
// left joystick:
@ -92,7 +92,7 @@ static const char* builtin_functions[][3] = {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Names are defined here, but processed in YaccParser
static const char* pseudo_registers[][2] = {
static const char* const pseudo_registers[][2] = {
// { "name", "help text" }
{ "_bank", "Currently selected bank" },

122
src/emucore/BSType.hxx Normal file
View File

@ -0,0 +1,122 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef BSTYPE_HXX
#define BSTYPE_HXX
#include "bspf.hxx"
// Currently supported bankswitch schemes
enum class BSType {
_AUTO, _0840, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1,
_64IN1, _128IN1, _2K, _3E, _3EPlus, _3F, _4A50,
_4K, _4KSC, _AR, _BF, _BFSC, _BUS, _CDF,
_CM, _CTY, _CV, _CVPlus, _DASH, _DF, _DFSC,
_DPC, _DPCPlus, _E0, _E7, _EF, _EFSC, _F0,
_F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA,
_FA2, _FE, _MC, _MDM, _SB, _UA, _WD,
_X07,
NumSchemes
};
// Info about the various bankswitch schemes, useful for displaying
// in GUI dropdown boxes, etc
struct BSDescription {
const char* const name;
const char* const desc;
};
static BSDescription BSList[int(BSType::NumSchemes)] = {
{ "AUTO", "Auto-detect" },
{ "0840", "0840 (8K ECONObank)" },
{ "2IN1", "2IN1 Multicart (4-32K)" },
{ "4IN1", "4IN1 Multicart (8-32K)" },
{ "8IN1", "8IN1 Multicart (16-64K)" },
{ "16IN1", "16IN1 Multicart (32-128K)" },
{ "32IN1", "32IN1 Multicart (64/128K)" },
{ "64IN1", "64IN1 Multicart (128/256K)" },
{ "128IN1", "128IN1 Multicart (256/512K)" },
{ "2K", "2K (64-2048 bytes Atari)" },
{ "3E", "3E (32K Tigervision)" },
{ "3E+", "3E+ (TJ modified DASH)" },
{ "3F", "3F (512K Tigervision)" },
{ "4A50", "4A50 (64K 4A50 + ram)" },
{ "4K", "4K (4K Atari)" },
{ "4KSC", "4KSC (CPUWIZ 4K + ram)" },
{ "AR", "AR (Supercharger)" },
{ "BF", "BF (CPUWIZ 256K)" },
{ "BFSC", "BFSC (CPUWIZ 256K + ram)" },
{ "BUS", "BUS (Bus Stuffing)" },
{ "CDF", "CDF (Chris, Darrell, Fred)" },
{ "CM", "CM (SpectraVideo CompuMate)" },
{ "CTY", "CTY (CDW - Chetiry)" },
{ "CV", "CV (Commavid extra ram)" },
{ "CV+", "CV+ (Extended Commavid)" },
{ "DASH", "DASH (Experimental)" },
{ "DF", "DF (CPUWIZ 128K)" },
{ "DFSC", "DFSC (CPUWIZ 128K + ram)" },
{ "DPC", "DPC (Pitfall II)" },
{ "DPC+", "DPC+ (Enhanced DPC)" },
{ "E0", "E0 (8K Parker Bros)" },
{ "E7", "E7 (16K M-network)" },
{ "EF", "EF (64K H. Runner)" },
{ "EFSC", "EFSC (64K H. Runner + ram)" },
{ "F0", "F0 (Dynacom Megaboy)" },
{ "F4", "F4 (32K Atari)" },
{ "F4SC", "F4SC (32K Atari + ram)" },
{ "F6", "F6 (16K Atari)" },
{ "F6SC", "F6SC (16K Atari + ram)" },
{ "F8", "F8 (8K Atari)" },
{ "F8SC", "F8SC (8K Atari + ram)" },
{ "FA", "FA (CBS RAM Plus)" },
{ "FA2", "FA2 (CBS RAM Plus 24/28K)" },
{ "FE", "FE (8K Decathlon)" },
{ "MC", "MC (C. Wilkson Megacart)" },
{ "MDM", "MDM (Menu Driven Megacart)" },
{ "SB", "SB (128-256K SUPERbank)" },
{ "UA", "UA (8K UA Ltd.)" },
{ "WD", "WD (Experimental)" },
{ "X07", "X07 (64K AtariAge)" }
};
class Bankswitch
{
public:
// Convert BSType enum to string
static string typeToName(BSType type) { return BSList[int(type)].name; }
// Convert string to BSType enum
static BSType nameToType(const string& name)
{
for(int i = 0; i < int(BSType::NumSchemes); ++i)
if(BSList[i].name == name)
return BSType(i);
return BSType::_AUTO;
}
private:
// Following constructors and assignment operators not supported
Bankswitch() = delete;
Bankswitch(const Bankswitch&) = delete;
Bankswitch(Bankswitch&&) = delete;
Bankswitch& operator=(const Bankswitch&) = delete;
Bankswitch& operator=(Bankswitch&&) = delete;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -43,25 +43,6 @@ class GuiObject;
class Cartridge : public Device
{
public:
/**
Create a new cartridge object allocated on the heap. The
type of cartridge created depends on the properties object.
@param image A pointer to the ROM image
@param size The size of the ROM image
@param md5 The md5sum for the given ROM image (can be updated)
@param dtype The detected bankswitch type of the ROM image
@param id Any extra info about the ROM (currently which part
of a multiload game is being accessed
@param system The osystem associated with the system
@param settings The settings associated with the system
@return Pointer to the new cartridge object allocated on the heap
*/
static unique_ptr<Cartridge>
create(const BytePtr& image, uInt32 size,
string& md5, string& dtype, string& id,
const OSystem& system, Settings& settings);
/**
Create a new cartridge
@ -71,16 +52,19 @@ class Cartridge : public Device
virtual ~Cartridge() = default;
/**
Query some information about this cartridge.
Set/query some information about this cartridge.
*/
static constexpr string& about() { return myAboutString; }
void setAbout(const string& about, const string& type, const string& id);
const string& about() const { return myAbout; }
const string& detectedType() const { return myDetectedType; }
const string& multiCartID() const { return myMultiCartID; }
/**
Save the internal (patched) ROM image.
@param out The output file stream to save the image
*/
bool saveROM(ofstream& out);
bool saveROM(ofstream& out) const;
/**
Lock/unlock bankswitching capability. The debugger will lock
@ -98,7 +82,7 @@ class Cartridge : public Device
@return The startup bank
*/
uInt16 startBank();
uInt16 startBank() const { return myStartBank; }
/**
Answer whether the bank has changed since the last time this
@ -188,15 +172,6 @@ class Cartridge : public Device
virtual CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, int x, int y, int w, int h) { return nullptr; }
// Info about the various bankswitch schemes, useful for displaying
// in GUI dropdown boxes, etc
struct BankswitchType {
const char* type;
const char* desc;
};
enum { ourNumBSTypes = 50 };
static BankswitchType ourBSList[ourNumBSTypes];
protected:
/**
Indicate that an illegal read from a write port has occurred.
@ -223,183 +198,6 @@ class Cartridge : public Device
*/
void initializeRAM(uInt8* arr, uInt32 size, uInt8 val = 0) const;
private:
/**
Get an image pointer and size for a ROM that is part of a larger,
multi-ROM image.
@param image A pointer to the ROM image
@param size The size of the ROM image
@param numroms The number of ROMs in the multicart
@param md5 The md5sum for the specific cart in the ROM image
@param id The ID for the specific cart in the ROM image
@param settings The settings associated with the system
@return The bankswitch type for the specific cart in the ROM image
*/
static string createFromMultiCart(const uInt8*& image, uInt32& size,
uInt32 numroms, string& md5, string& id, Settings& settings);
/**
Try to auto-detect the bankswitching type of the cartridge
@param image A pointer to the ROM image
@param size The size of the ROM image
@return The "best guess" for the cartridge type
*/
static string autodetectType(const uInt8* image, uInt32 size);
/**
Search the image for the specified byte signature
@param image A pointer to the ROM image
@param imagesize The size of the ROM image
@param signature The byte sequence to search for
@param sigsize The number of bytes in the signature
@param minhits The minimum number of times a signature is to be found
@return True if the signature was found at least 'minhits' time, else false
*/
static bool searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize,
uInt32 minhits);
/**
Returns true if the image is probably a SuperChip (128 bytes RAM)
Note: should be called only on ROMs with size multiple of 4K
*/
static bool isProbablySC(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a 4K SuperChip (128 bytes RAM)
*/
static bool isProbably4KSC(const uInt8* image, uInt32 size);
/**
Returns true if the image probably contains ARM code in the first 1K
*/
static bool isProbablyARM(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a 0840 bankswitching cartridge
*/
static bool isProbably0840(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a 3E bankswitching cartridge
*/
static bool isProbably3E(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a 3E+ bankswitching cartridge
*/
static bool isProbably3EPlus(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a 3F bankswitching cartridge
*/
static bool isProbably3F(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a 4A50 bankswitching cartridge
*/
static bool isProbably4A50(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a BF/BFSC bankswitching cartridge
*/
static bool isProbablyBF(const uInt8* image, uInt32 size, const char*& type);
/**
Returns true if the image is probably a BUS bankswitching cartridge
*/
static bool isProbablyBUS(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a CDF bankswitching cartridge
*/
static bool isProbablyCDF(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a CTY bankswitching cartridge
*/
static bool isProbablyCTY(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a CV bankswitching cartridge
*/
static bool isProbablyCV(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a CV+ bankswitching cartridge
*/
static bool isProbablyCVPlus(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a DASH bankswitching cartridge
*/
static bool isProbablyDASH(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a DF/DFSC bankswitching cartridge
*/
static bool isProbablyDF(const uInt8* image, uInt32 size, const char*& type);
/**
Returns true if the image is probably a DPC+ bankswitching cartridge
*/
static bool isProbablyDPCplus(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a E0 bankswitching cartridge
*/
static bool isProbablyE0(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a E7 bankswitching cartridge
*/
static bool isProbablyE7(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably an EF/EFSC bankswitching cartridge
*/
static bool isProbablyEF(const uInt8* image, uInt32 size, const char*& type);
/**
Returns true if the image is probably an F6 bankswitching cartridge
*/
static bool isProbablyF6(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably an FA2 bankswitching cartridge
*/
static bool isProbablyFA2(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably an FE bankswitching cartridge
*/
static bool isProbablyFE(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a MDM bankswitching cartridge
*/
static bool isProbablyMDM(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a SB bankswitching cartridge
*/
static bool isProbablySB(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably a UA bankswitching cartridge
*/
static bool isProbablyUA(const uInt8* image, uInt32 size);
/**
Returns true if the image is probably an X07 bankswitching cartridge
*/
static bool isProbablyX07(const uInt8* image, uInt32 size);
protected:
// Settings class for the application
const Settings& mySettings;
@ -419,8 +217,11 @@ class Cartridge : public Device
// by the debugger, when disassembling/dumping ROM.
bool myBankLocked;
// Contains info about this cartridge in string format
static string myAboutString;
// Contains various info about this cartridge
// This needs to be stored separately from child classes, since
// sometimes the information in both do not match
// (ie, detected type could be '2in1' while name of cart is '4K')
string myAbout, myDetectedType, myMultiCartID;
// Following constructors and assignment operators not supported
Cartridge() = delete;

View File

@ -19,12 +19,13 @@
#include "Cart0840.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge0840::Cartridge0840(const uInt8* image, uInt32 size, const Settings& settings)
Cartridge0840::Cartridge0840(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(8192u, size));
memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192);
// Remember startup bank

View File

@ -43,7 +43,7 @@ class Cartridge0840 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge0840(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge0840(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge0840() = default;
public:

View File

@ -19,7 +19,8 @@
#include "Cart2K.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge2K::Cartridge2K(const uInt8* image, uInt32 size, const Settings& settings)
Cartridge2K::Cartridge2K(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings)
{
// Size can be a maximum of 2K
@ -41,7 +42,7 @@ Cartridge2K::Cartridge2K(const uInt8* image, uInt32 size, const Settings& settin
memset(myImage.get(), 0x02, mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, size);
memcpy(myImage.get(), image.get(), size);
createCodeAccessBase(mySize);
// Set mask for accessing the image buffer

View File

@ -45,7 +45,7 @@ class Cartridge2K : public Cartridge
@param size The size of the ROM image (<= 2048 bytes)
@param settings A reference to the various settings (read-only)
*/
Cartridge2K(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge2K(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge2K() = default;
public:

View File

@ -20,7 +20,7 @@
#include "Cart3E.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3E::Cartridge3E(const uInt8* image, uInt32 size,
Cartridge3E::Cartridge3E(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
@ -30,7 +30,7 @@ Cartridge3E::Cartridge3E(const uInt8* image, uInt32 size,
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize + 32768);
// Remember startup bank

View File

@ -73,7 +73,7 @@ class Cartridge3E : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge3E(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge3E(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge3E() = default;
public:

View File

@ -20,7 +20,8 @@
#include "Cart3EPlus.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3EPlus::Cartridge3EPlus(const uInt8* image, uInt32 size, const Settings& settings)
Cartridge3EPlus::Cartridge3EPlus(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size)
{
@ -28,7 +29,7 @@ Cartridge3EPlus::Cartridge3EPlus(const uInt8* image, uInt32 size, const Settings
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize + RAM_TOTAL_SIZE);
// Remember startup bank (0 per spec, rather than last per 3E scheme).

View File

@ -53,7 +53,7 @@ class Cartridge3EPlus: public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge3EPlus(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge3EPlus(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge3EPlus() = default;
public:

View File

@ -20,7 +20,7 @@
#include "Cart3F.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge3F::Cartridge3F(const uInt8* image, uInt32 size,
Cartridge3F::Cartridge3F(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
@ -30,7 +30,7 @@ Cartridge3F::Cartridge3F(const uInt8* image, uInt32 size,
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize);
// Remember startup bank

View File

@ -50,7 +50,7 @@ class Cartridge3F : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge3F(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge3F(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge3F() = default;
public:

View File

@ -21,7 +21,7 @@
#include "Cart4A50.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge4A50::Cartridge4A50(const uInt8* image, uInt32 size,
Cartridge4A50::Cartridge4A50(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
@ -40,7 +40,7 @@ Cartridge4A50::Cartridge4A50(const uInt8* image, uInt32 size,
else if(size < 131072) size = 65536;
else size = 131072;
for(uInt32 slice = 0; slice < 131072 / size; ++slice)
memcpy(myImage + (slice*size), image, size);
memcpy(myImage + (slice*size), image.get(), size);
// We use System::PageAccess.codeAccessBase, but don't allow its use
// through a pointer, since the address space of 4A50 carts can change

View File

@ -58,7 +58,7 @@ class Cartridge4A50 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge4A50(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge4A50(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge4A50() = default;
public:

View File

@ -19,11 +19,12 @@
#include "Cart4K.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge4K::Cartridge4K(const uInt8* image, uInt32 size, const Settings& settings)
Cartridge4K::Cartridge4K(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(4096u, size));
memcpy(myImage, image.get(), std::min(4096u, size));
createCodeAccessBase(4096);
}

View File

@ -44,7 +44,7 @@ class Cartridge4K : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge4K(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge4K(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge4K() = default;
public:

View File

@ -19,11 +19,12 @@
#include "Cart4KSC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge4KSC::Cartridge4KSC(const uInt8* image, uInt32 size, const Settings& settings)
Cartridge4KSC::Cartridge4KSC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(4096u, size));
memcpy(myImage, image.get(), std::min(4096u, size));
createCodeAccessBase(4096);
}

View File

@ -42,7 +42,7 @@ class Cartridge4KSC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
Cartridge4KSC(const uInt8* image, uInt32 size, const Settings& settings);
Cartridge4KSC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~Cartridge4KSC() = default;
public:

View File

@ -20,7 +20,7 @@
#include "CartAR.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeAR::CartridgeAR(const uInt8* image, uInt32 size,
CartridgeAR::CartridgeAR(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(std::max(size, 8448u)),
@ -35,7 +35,7 @@ CartridgeAR::CartridgeAR(const uInt8* image, uInt32 size,
// Create a load image buffer and copy the given image
myLoadImages = make_ptr<uInt8[]>(mySize);
myNumberOfLoadImages = mySize / 8448;
memcpy(myLoadImages.get(), image, size);
memcpy(myLoadImages.get(), image.get(), size);
// Add header if image doesn't include it
if(size < 8448)

View File

@ -49,7 +49,7 @@ class CartridgeAR : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeAR(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeAR(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeAR() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartBF.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBF::CartridgeBF(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeBF::CartridgeBF(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(262144u, size));
memcpy(myImage, image.get(), std::min(262144u, size));
createCodeAccessBase(262144);
// Remember startup bank

View File

@ -45,7 +45,7 @@ class CartridgeBF : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeBF(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeBF(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeBF() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartBFSC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBFSC::CartridgeBFSC(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeBFSC::CartridgeBFSC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(262144u, size));
memcpy(myImage, image.get(), std::min(262144u, size));
createCodeAccessBase(262144);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeBFSC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeBFSC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeBFSC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeBFSC() = default;
public:

View File

@ -40,15 +40,15 @@
#define DIGITAL_AUDIO_ON ((myMode & 0xF0) == 0)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBUS::CartridgeBUS(const uInt8* image, uInt32 size,
const Settings& settings)
CartridgeBUS::CartridgeBUS(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySystemCycles(0),
myARMCycles(0),
myFractionalClocks(0.0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size));
memcpy(myImage, image.get(), std::min(32768u, size));
// even though the ROM is 32K, only 28K is accessible to the 6507
createCodeAccessBase(4096 * 7);

View File

@ -55,7 +55,7 @@ class CartridgeBUS : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeBUS(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeBUS(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeBUS() = default;
public:
@ -275,7 +275,7 @@ class CartridgeBUS : public Cartridge
// 0- = Packed Digital Sample
// F- = 3 Voice Music
uInt8 myMode;
uInt8 myFastJumpActive;
private:

View File

@ -40,7 +40,7 @@
#define DIGITAL_AUDIO_ON ((myMode & 0xF0) == 0)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCDF::CartridgeCDF(const uInt8* image, uInt32 size,
CartridgeCDF::CartridgeCDF(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myAudioCycles(0),
@ -48,7 +48,7 @@ CartridgeCDF::CartridgeCDF(const uInt8* image, uInt32 size,
myFractionalClocks(0.0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size));
memcpy(myImage, image.get(), std::min(32768u, size));
// even though the ROM is 32K, only 28K is accessible to the 6507
createCodeAccessBase(4096 * 7);

View File

@ -55,7 +55,7 @@ class CartridgeCDF : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeCDF(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeCDF(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeCDF() = default;
public:
@ -284,7 +284,7 @@ class CartridgeCDF : public Cartridge
// set to address of the JMP operand if last byte peeked was 4C
// *and* the next two bytes in ROM are 00 00
uInt16 myJMPoperandAddress;
TIA* myTIA;
uInt8 myFastJumpActive;

View File

@ -21,13 +21,14 @@
#include "CartCM.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCM::CartridgeCM(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeCM::CartridgeCM(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySWCHA(0xFF), // portA is all 1's
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(16384u, size));
memcpy(myImage, image.get(), std::min(16384u, size));
createCodeAccessBase(16384);
// On powerup, the last bank of ROM is enabled and RAM is disabled

View File

@ -116,7 +116,7 @@ class CartridgeCM : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeCM(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeCM(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeCM() = default;
public:

View File

@ -22,7 +22,8 @@
#include "CartCTY.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCTY::CartridgeCTY(const uInt8* image, uInt32 size, const OSystem& osystem)
CartridgeCTY::CartridgeCTY(const BytePtr& image, uInt32 size,
const OSystem& osystem)
: Cartridge(osystem.settings()),
myOSystem(osystem),
myOperationType(0),
@ -35,7 +36,7 @@ CartridgeCTY::CartridgeCTY(const uInt8* image, uInt32 size, const OSystem& osyst
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size));
memcpy(myImage, image.get(), std::min(32768u, size));
createCodeAccessBase(32768);
// Point to the first tune

View File

@ -119,7 +119,7 @@ class CartridgeCTY : public Cartridge
@param size The size of the ROM image
@param osystem A reference to the OSystem currently in use
*/
CartridgeCTY(const uInt8* image, uInt32 size, const OSystem& osystem);
CartridgeCTY(const BytePtr& image, uInt32 size, const OSystem& osystem);
virtual ~CartridgeCTY() = default;
public:

View File

@ -19,7 +19,7 @@
#include "CartCV.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCV::CartridgeCV(const uInt8* image, uInt32 size,
CartridgeCV::CartridgeCV(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size)
@ -27,7 +27,7 @@ CartridgeCV::CartridgeCV(const uInt8* image, uInt32 size,
if(mySize == 2048)
{
// Copy the ROM data into my buffer
memcpy(myImage, image, 2048);
memcpy(myImage, image.get(), 2048);
}
else if(mySize == 4096)
{
@ -35,11 +35,11 @@ CartridgeCV::CartridgeCV(const uInt8* image, uInt32 size,
// Useful for MagiCard program listings
// Copy the ROM data into my buffer
memcpy(myImage, image + 2048, 2048);
memcpy(myImage, image.get() + 2048, 2048);
// Copy the RAM image into a buffer for use in reset()
myInitialRAM = make_ptr<uInt8[]>(1024);
memcpy(myInitialRAM.get(), image, 1024);
memcpy(myInitialRAM.get(), image.get(), 1024);
}
createCodeAccessBase(2048+1024);
}

View File

@ -47,7 +47,7 @@ class CartridgeCV : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeCV(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeCV(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeCV() = default;
public:

View File

@ -20,7 +20,7 @@
#include "CartCVPlus.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCVPlus::CartridgeCVPlus(const uInt8* image, uInt32 size,
CartridgeCVPlus::CartridgeCVPlus(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
@ -30,7 +30,7 @@ CartridgeCVPlus::CartridgeCVPlus(const uInt8* image, uInt32 size,
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize + 1024);
// Remember startup bank

View File

@ -57,7 +57,7 @@ class CartridgeCVPlus : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeCVPlus(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeCVPlus(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeCVPlus() = default;
public:

View File

@ -20,7 +20,8 @@
#include "CartDASH.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDASH::CartridgeDASH(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeDASH::CartridgeDASH(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size)
{
@ -28,7 +29,7 @@ CartridgeDASH::CartridgeDASH(const uInt8* image, uInt32 size, const Settings& se
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize + RAM_TOTAL_SIZE);
// Remember startup bank (0 per spec, rather than last per 3E scheme).

View File

@ -135,7 +135,7 @@ class CartridgeDASH: public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeDASH(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeDASH(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeDASH() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartDF.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDF::CartridgeDF(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeDF::CartridgeDF(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(131072u, size));
memcpy(myImage, image.get(), std::min(131072u, size));
createCodeAccessBase(131072);
// Remember startup bank

View File

@ -45,7 +45,7 @@ class CartridgeDF : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeDF(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeDF(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeDF() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartDFSC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDFSC::CartridgeDFSC(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeDFSC::CartridgeDFSC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(131072u, size));
memcpy(myImage, image.get(), std::min(131072u, size));
createCodeAccessBase(131072);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeDFSC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeDFSC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeDFSC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeDFSC() = default;
public:

View File

@ -19,7 +19,7 @@
#include "CartDPC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDPC::CartridgeDPC(const uInt8* image, uInt32 size,
CartridgeDPC::CartridgeDPC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
@ -28,7 +28,7 @@ CartridgeDPC::CartridgeDPC(const uInt8* image, uInt32 size,
myCurrentBank(0)
{
// Make a copy of the entire image
memcpy(myImage, image, std::min(size, 8192u + 2048u + 256u));
memcpy(myImage, image.get(), std::min(size, 8192u + 2048u + 256u));
createCodeAccessBase(8192);
// Pointer to the program ROM (8K @ 0 byte offset)

View File

@ -49,7 +49,7 @@ class CartridgeDPC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeDPC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeDPC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeDPC() = default;
public:

View File

@ -24,7 +24,7 @@
#include "TIA.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size,
CartridgeDPCPlus::CartridgeDPCPlus(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myFastFetch(false),
@ -40,7 +40,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size,
mySize = std::min(size, 32768u);
if(mySize < 32768u)
memset(myImage, 0, 32768);
memcpy(myImage + (32768u - mySize), image, size);
memcpy(myImage + (32768u - mySize), image.get(), size);
createCodeAccessBase(4096 * 6);
// Pointer to the program ROM (24K @ 3072 byte offset; ignore first 3K)

View File

@ -53,7 +53,7 @@ class CartridgeDPCPlus : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeDPCPlus(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeDPCPlus(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeDPCPlus() = default;
public:

View File

@ -0,0 +1,958 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "bspf.hxx"
#include "Cart.hxx"
#include "Cart0840.hxx"
#include "Cart2K.hxx"
#include "Cart3E.hxx"
#include "Cart3EPlus.hxx"
#include "Cart3F.hxx"
#include "Cart4A50.hxx"
#include "Cart4K.hxx"
#include "Cart4KSC.hxx"
#include "CartAR.hxx"
#include "CartBUS.hxx"
#include "CartCDF.hxx"
#include "CartCM.hxx"
#include "CartCTY.hxx"
#include "CartCV.hxx"
#include "CartCVPlus.hxx"
#include "CartDASH.hxx"
#include "CartDPC.hxx"
#include "CartDPCPlus.hxx"
#include "CartE0.hxx"
#include "CartE7.hxx"
#include "CartEF.hxx"
#include "CartEFSC.hxx"
#include "CartBF.hxx"
#include "CartBFSC.hxx"
#include "CartDF.hxx"
#include "CartDFSC.hxx"
#include "CartF0.hxx"
#include "CartF4.hxx"
#include "CartF4SC.hxx"
#include "CartF6.hxx"
#include "CartF6SC.hxx"
#include "CartF8.hxx"
#include "CartF8SC.hxx"
#include "CartFA.hxx"
#include "CartFA2.hxx"
#include "CartFE.hxx"
#include "CartMC.hxx"
#include "CartMDM.hxx"
#include "CartSB.hxx"
#include "CartUA.hxx"
#include "CartWD.hxx"
#include "CartX07.hxx"
#include "MD5.hxx"
#include "Props.hxx"
#include "Settings.hxx"
#include "CartDetector.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Cartridge> CartDetector::create(const BytePtr& image, uInt32 size,
string& md5, const string& propertiesType, const OSystem& osystem)
{
unique_ptr<Cartridge> cartridge;
BSType type = Bankswitch::nameToType(propertiesType),
detectedType = type;
string id;
// Collect some info about the ROM
ostringstream buf;
// See if we should try to auto-detect the cartridge type
// If we ask for extended info, always do an autodetect
if(type == BSType::_AUTO || osystem.settings().getBool("rominfo"))
{
detectedType = autodetectType(image, size);
if(type != BSType::_AUTO && type != detectedType)
cerr << "Auto-detection not consistent: "
<< Bankswitch::typeToName(type) << ", "
<< Bankswitch::typeToName(detectedType) << endl;
type = detectedType;
buf << Bankswitch::typeToName(type) << "*";
}
else
buf << Bankswitch::typeToName(type);
// Check for multicart first; if found, get the correct part of the image
switch(type)
{
case BSType::_2IN1:
// Make sure we have a valid sized image
if(size == 2*2048 || size == 2*4096 || size == 2*8192 || size == 2*16384)
{
cartridge =
createFromMultiCart(image, size, 2, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
case BSType::_4IN1:
// Make sure we have a valid sized image
if(size == 4*2048 || size == 4*4096 || size == 4*8192)
{
cartridge =
createFromMultiCart(image, size, 4, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
case BSType::_8IN1:
// Make sure we have a valid sized image
if(size == 8*2048 || size == 8*4096 || size == 8*8192)
{
cartridge =
createFromMultiCart(image, size, 8, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
case BSType::_16IN1:
// Make sure we have a valid sized image
if(size == 16*2048 || size == 16*4096 || size == 16*8192)
{
cartridge =
createFromMultiCart(image, size, 16, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
case BSType::_32IN1:
// Make sure we have a valid sized image
if(size == 32*2048 || size == 32*4096)
{
cartridge =
createFromMultiCart(image, size, 32, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
case BSType::_64IN1:
// Make sure we have a valid sized image
if(size == 64*2048 || size == 64*4096)
{
cartridge =
createFromMultiCart(image, size, 64, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
case BSType::_128IN1:
// Make sure we have a valid sized image
if(size == 128*2048 || size == 128*4096)
{
cartridge =
createFromMultiCart(image, size, 128, md5, detectedType, id, osystem);
buf << id;
}
else
throw runtime_error("Invalid cart size for type '" +
Bankswitch::typeToName(type) + "'");
break;
default:
cartridge = createFromImage(image, size, detectedType, md5, osystem);
break;
}
if(size < 1024)
buf << " (" << size << "B) ";
else
buf << " (" << (size/1024) << "K) ";
cartridge->setAbout(buf.str(), Bankswitch::typeToName(type), id);
return cartridge;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Cartridge>
CartDetector::createFromMultiCart(const BytePtr& image, uInt32& size,
uInt32 numroms, string& md5, BSType type, string& id, const OSystem& osystem)
{
// Get a piece of the larger image
uInt32 i = osystem.settings().getInt("romloadcount");
size /= numroms;
BytePtr slice = make_ptr<uInt8[]>(size);
memcpy(slice.get(), image.get()+i*size, size);
// We need a new md5 and name
md5 = MD5::hash(slice, size);
ostringstream buf;
buf << " [G" << (i+1) << "]";
id = buf.str();
// Move to the next game the next time this ROM is loaded
osystem.settings().setValue("romloadcount", (i+1)%numroms);
if(size <= 2048) type = BSType::_2K;
else if(size == 4096) type = BSType::_4K;
else if(size == 8192) type = BSType::_F8;
else /* default */ type = BSType::_4K;
return createFromImage(slice, size, type, md5, osystem);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Cartridge>
CartDetector::createFromImage(const BytePtr& image, uInt32 size, BSType type,
const string& md5, const OSystem& osystem)
{
// We should know the cart's type by now so let's create it
switch(type)
{
case BSType::_0840:
return make_ptr<Cartridge0840>(image, size, osystem.settings());
case BSType::_2K:
return make_ptr<Cartridge2K>(image, size, osystem.settings());
case BSType::_3E:
return make_ptr<Cartridge3E>(image, size, osystem.settings());
case BSType::_3EPlus:
return make_ptr<Cartridge3EPlus>(image, size, osystem.settings());
case BSType::_3F:
return make_ptr<Cartridge3F>(image, size, osystem.settings());
case BSType::_4A50:
return make_ptr<Cartridge4A50>(image, size, osystem.settings());
case BSType::_4K:
return make_ptr<Cartridge4K>(image, size, osystem.settings());
case BSType::_4KSC:
return make_ptr<Cartridge4KSC>(image, size, osystem.settings());
case BSType::_AR:
return make_ptr<CartridgeAR>(image, size, osystem.settings());
case BSType::_BUS:
return make_ptr<CartridgeBUS>(image, size, osystem.settings());
case BSType::_CDF:
return make_ptr<CartridgeCDF>(image, size, osystem.settings());
case BSType::_CM:
return make_ptr<CartridgeCM>(image, size, osystem.settings());
case BSType::_CTY:
return make_ptr<CartridgeCTY>(image, size, osystem);
case BSType::_CV:
return make_ptr<CartridgeCV>(image, size, osystem.settings());
case BSType::_CVPlus:
return make_ptr<CartridgeCVPlus>(image, size, osystem.settings());
case BSType::_DASH:
return make_ptr<CartridgeDASH>(image, size, osystem.settings());
case BSType::_DPC:
return make_ptr<CartridgeDPC>(image, size, osystem.settings());
case BSType::_DPCPlus:
return make_ptr<CartridgeDPCPlus>(image, size, osystem.settings());
case BSType::_E0:
return make_ptr<CartridgeE0>(image, size, osystem.settings());
case BSType::_E7:
return make_ptr<CartridgeE7>(image, size, osystem.settings());
case BSType::_EF:
return make_ptr<CartridgeEF>(image, size, osystem.settings());
case BSType::_EFSC:
return make_ptr<CartridgeEFSC>(image, size, osystem.settings());
case BSType::_BF:
return make_ptr<CartridgeBF>(image, size, osystem.settings());
case BSType::_BFSC:
return make_ptr<CartridgeBFSC>(image, size, osystem.settings());
case BSType::_DF:
return make_ptr<CartridgeDF>(image, size, osystem.settings());
case BSType::_DFSC:
return make_ptr<CartridgeDFSC>(image, size, osystem.settings());
case BSType::_F0:
return make_ptr<CartridgeF0>(image, size, osystem.settings());
case BSType::_F4:
return make_ptr<CartridgeF4>(image, size, osystem.settings());
case BSType::_F4SC:
return make_ptr<CartridgeF4SC>(image, size, osystem.settings());
case BSType::_F6:
return make_ptr<CartridgeF6>(image, size, osystem.settings());
case BSType::_F6SC:
return make_ptr<CartridgeF6SC>(image, size, osystem.settings());
case BSType::_F8:
return make_ptr<CartridgeF8>(image, size, md5, osystem.settings());
case BSType::_F8SC:
return make_ptr<CartridgeF8SC>(image, size, osystem.settings());
case BSType::_FA:
return make_ptr<CartridgeFA>(image, size, osystem.settings());
case BSType::_FA2:
return make_ptr<CartridgeFA2>(image, size, osystem);
case BSType::_FE:
return make_ptr<CartridgeFE>(image, size, osystem.settings());
case BSType::_MC:
return make_ptr<CartridgeMC>(image, size, osystem.settings());
case BSType::_MDM:
return make_ptr<CartridgeMDM>(image, size, osystem.settings());
case BSType::_UA:
return make_ptr<CartridgeUA>(image, size, osystem.settings());
case BSType::_SB:
return make_ptr<CartridgeSB>(image, size, osystem.settings());
case BSType::_WD:
return make_ptr<CartridgeWD>(image, size, osystem.settings());
case BSType::_X07:
return make_ptr<CartridgeX07>(image, size, osystem.settings());
default:
return nullptr; // The remaining types have already been handled
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BSType CartDetector::autodetectType(const BytePtr& image, uInt32 size)
{
// Guess type based on size
BSType type = BSType::_AUTO;
if(isProbablyCVPlus(image,size))
{
type = BSType::_CVPlus;
}
else if((size % 8448) == 0 || size == 6144)
{
type = BSType::_AR;
}
else if(size < 2048) // Sub2K images
{
type = BSType::_2K;
}
else if((size == 2048) ||
(size == 4096 && memcmp(image.get(), image.get() + 2048, 2048) == 0))
{
type = isProbablyCV(image, size) ? BSType::_CV : BSType::_2K;
}
else if(size == 4096)
{
if(isProbablyCV(image, size))
type = BSType::_CV;
else if(isProbably4KSC(image, size))
type = BSType::_4KSC;
else
type = BSType::_4K;
}
else if(size == 8*1024) // 8K
{
// First check for *potential* F8
uInt8 signature[] = { 0x8D, 0xF9, 0x1F }; // STA $1FF9
bool f8 = searchForBytes(image.get(), size, signature, 3, 2);
if(isProbablySC(image, size))
type = BSType::_F8SC;
else if(memcmp(image.get(), image.get() + 4096, 4096) == 0)
type = BSType::_4K;
else if(isProbablyE0(image, size))
type = BSType::_E0;
else if(isProbably3E(image, size))
type = BSType::_3E;
else if(isProbably3F(image, size))
type = BSType::_3F;
else if(isProbablyUA(image, size))
type = BSType::_UA;
else if(isProbablyFE(image, size) && !f8)
type = BSType::_FE;
else if(isProbably0840(image, size))
type = BSType::_0840;
else
type = BSType::_F8;
}
else if(size == 8*1024 + 3) // 8195 bytes (Experimental)
{
type = BSType::_WD;
}
else if(size >= 10240 && size <= 10496) // ~10K - Pitfall2
{
type = BSType::_DPC;
}
else if(size == 12*1024) // 12K
{
type = BSType::_FA;
}
else if(size == 16*1024) // 16K
{
if(isProbablySC(image, size))
type = BSType::_F6SC;
else if(isProbablyE7(image, size))
type = BSType::_E7;
else if(isProbably3E(image, size))
type = BSType::_3E;
/* no known 16K 3F ROMS
else if(isProbably3F(image, size))
type = BSType::_3F;
*/
else
type = BSType::_F6;
}
else if(size == 24*1024 || size == 28*1024) // 24K & 28K
{
type = BSType::_FA2;
}
else if(size == 29*1024) // 29K
{
if(isProbablyARM(image, size))
type = BSType::_FA2;
else /*if(isProbablyDPCplus(image, size))*/
type = BSType::_DPCPlus;
}
else if(size == 32*1024) // 32K
{
if(isProbablySC(image, size))
type = BSType::_F4SC;
else if(isProbably3E(image, size))
type = BSType::_3E;
else if(isProbably3F(image, size))
type = BSType::_3F;
else if (isProbablyBUS(image, size))
type = BSType::_BUS;
else if (isProbablyCDF(image, size))
type = BSType::_CDF;
else if(isProbablyDPCplus(image, size))
type = BSType::_DPCPlus;
else if(isProbablyCTY(image, size))
type = BSType::_CTY;
else if(isProbablyFA2(image, size))
type = BSType::_FA2;
else
type = BSType::_F4;
}
else if(size == 64*1024) // 64K
{
if(isProbably3E(image, size))
type = BSType::_3E;
else if(isProbably3F(image, size))
type = BSType::_3F;
else if(isProbably4A50(image, size))
type = BSType::_4A50;
else if(isProbablyEF(image, size, type))
; // type has been set directly in the function
else if(isProbablyX07(image, size))
type = BSType::_X07;
else
type = BSType::_F0;
}
else if(size == 128*1024) // 128K
{
if(isProbably3E(image, size))
type = BSType::_3E;
else if(isProbablyDF(image, size, type))
; // type has been set directly in the function
else if(isProbably3F(image, size))
type = BSType::_3F;
else if(isProbably4A50(image, size))
type = BSType::_4A50;
else if(isProbablySB(image, size))
type = BSType::_SB;
else
type = BSType::_MC;
}
else if(size == 256*1024) // 256K
{
if(isProbably3E(image, size))
type = BSType::_3E;
else if(isProbablyBF(image, size, type))
; // type has been set directly in the function
else if(isProbably3F(image, size))
type = BSType::_3F;
else /*if(isProbablySB(image, size))*/
type = BSType::_SB;
}
else // what else can we do?
{
if(isProbably3E(image, size))
type = BSType::_3E;
else if(isProbably3F(image, size))
type = BSType::_3F;
else
type = BSType::_4K; // Most common bankswitching type
}
// Variable sized ROM formats are independent of image size and come last
if(isProbablyDASH(image, size))
type = BSType::_DASH;
else if(isProbably3EPlus(image, size))
type = BSType::_3EPlus;
else if(isProbablyMDM(image, size))
type = BSType::_MDM;
return type;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize,
uInt32 minhits)
{
uInt32 count = 0;
for(uInt32 i = 0; i < imagesize - sigsize; ++i)
{
uInt32 matches = 0;
for(uInt32 j = 0; j < sigsize; ++j)
{
if(image[i+j] == signature[j])
++matches;
else
break;
}
if(matches == sigsize)
{
++count;
i += sigsize; // skip past this signature 'window' entirely
}
if(count >= minhits)
break;
}
return (count >= minhits);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablySC(const BytePtr& image, uInt32 size)
{
// We assume a Superchip cart repeats the first 128 bytes for the second
// 128 bytes in the RAM area, which is the first 256 bytes of each 4K bank
const uInt8* ptr = image.get();
while(size)
{
if(memcmp(ptr, ptr + 128, 128) != 0)
return false;
ptr += 4096;
size -= 4096;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably4KSC(const BytePtr& image, uInt32 size)
{
// We check if the first 256 bytes are identical *and* if there's
// an "SC" signature for one of our larger SC types at 1FFA.
uInt8 first = image[0];
for(uInt32 i = 1; i < 256; ++i)
if(image[i] != first)
return false;
if((image[size-6]=='S') && (image[size-5]=='C'))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyARM(const BytePtr& image, uInt32 size)
{
// ARM code contains the following 'loader' patterns in the first 1K
// Thanks to Thomas Jentzsch of AtariAge for this advice
uInt8 signature[2][4] = {
{ 0xA0, 0xC1, 0x1F, 0xE0 },
{ 0x00, 0x80, 0x02, 0xE0 }
};
if(searchForBytes(image.get(), std::min(size, 1024u), signature[0], 4, 1))
return true;
else
return searchForBytes(image.get(), std::min(size, 1024u), signature[1], 4, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably0840(const BytePtr& image, uInt32 size)
{
// 0840 cart bankswitching is triggered by accessing addresses 0x0800
// or 0x0840 at least twice
uInt8 signature1[3][3] = {
{ 0xAD, 0x00, 0x08 }, // LDA $0800
{ 0xAD, 0x40, 0x08 }, // LDA $0840
{ 0x2C, 0x00, 0x08 } // BIT $0800
};
for(uInt32 i = 0; i < 3; ++i)
if(searchForBytes(image.get(), size, signature1[i], 3, 2))
return true;
uInt8 signature2[2][4] = {
{ 0x0C, 0x00, 0x08, 0x4C }, // NOP $0800; JMP ...
{ 0x0C, 0xFF, 0x0F, 0x4C } // NOP $0FFF; JMP ...
};
for(uInt32 i = 0; i < 2; ++i)
if(searchForBytes(image.get(), size, signature2[i], 4, 2))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably3E(const BytePtr& image, uInt32 size)
{
// 3E cart bankswitching is triggered by storing the bank number
// in address 3E using 'STA $3E', commonly followed by an
// immediate mode LDA
uInt8 signature[] = { 0x85, 0x3E, 0xA9, 0x00 }; // STA $3E; LDA #$00
return searchForBytes(image.get(), size, signature, 4, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably3EPlus(const BytePtr& image, uInt32 size)
{
// 3E+ cart is identified key 'TJ3E' in the ROM
uInt8 signature[] = { 'T', 'J', '3', 'E' };
return searchForBytes(image.get(), size, signature, 4, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably3F(const BytePtr& image, uInt32 size)
{
// 3F cart bankswitching is triggered by storing the bank number
// in address 3F using 'STA $3F'
// We expect it will be present at least 2 times, since there are
// at least two banks
uInt8 signature[] = { 0x85, 0x3F }; // STA $3F
return searchForBytes(image.get(), size, signature, 2, 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbably4A50(const BytePtr& image, uInt32 size)
{
// 4A50 carts store address $4A50 at the NMI vector, which
// in this scheme is always in the last page of ROM at
// $1FFA - $1FFB (at least this is true in rev 1 of the format)
if(image[size-6] == 0x50 && image[size-5] == 0x4A)
return true;
// Program starts at $1Fxx with NOP $6Exx or NOP $6Fxx?
if(((image[0xfffd] & 0x1f) == 0x1f) &&
(image[image[0xfffd] * 256 + image[0xfffc]] == 0x0c) &&
((image[image[0xfffd] * 256 + image[0xfffc] + 2] & 0xfe) == 0x6e))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyCTY(const BytePtr&, uInt32)
{
return false; // TODO - add autodetection
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyCV(const BytePtr& image, uInt32 size)
{
// CV RAM access occurs at addresses $f3ff and $f400
// These signatures are attributed to the MESS project
uInt8 signature[2][3] = {
{ 0x9D, 0xFF, 0xF3 }, // STA $F3FF.X
{ 0x99, 0x00, 0xF4 } // STA $F400.Y
};
if(searchForBytes(image.get(), size, signature[0], 3, 1))
return true;
else
return searchForBytes(image.get(), size, signature[1], 3, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyCVPlus(const BytePtr& image, uInt32)
{
// CV+ cart is identified key 'commavidplus' @ $04 in the ROM
// We inspect only this area to speed up the search
uInt8 signature[12] = { 'c', 'o', 'm', 'm', 'a', 'v', 'i', 'd',
'p', 'l', 'u', 's' };
return searchForBytes(image.get()+4, 24, signature, 12, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyDASH(const BytePtr& image, uInt32 size)
{
// DASH cart is identified key 'TJAD' in the ROM
uInt8 signature[] = { 'T', 'J', 'A', 'D' };
return searchForBytes(image.get(), size, signature, 4, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyDPCplus(const BytePtr& image, uInt32 size)
{
// DPC+ ARM code has 2 occurrences of the string DPC+
// Note: all Harmony/Melody custom drivers also contain the value
// 0x10adab1e (LOADABLE) if needed for future improvement
uInt8 signature[] = { 'D', 'P', 'C', '+' };
return searchForBytes(image.get(), size, signature, 4, 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyE0(const BytePtr& image, uInt32 size)
{
// E0 cart bankswitching is triggered by accessing addresses
// $FE0 to $FF9 using absolute non-indexed addressing
// To eliminate false positives (and speed up processing), we
// search for only certain known signatures
// Thanks to "stella@casperkitty.com" for this advice
// These signatures are attributed to the MESS project
uInt8 signature[8][3] = {
{ 0x8D, 0xE0, 0x1F }, // STA $1FE0
{ 0x8D, 0xE0, 0x5F }, // STA $5FE0
{ 0x8D, 0xE9, 0xFF }, // STA $FFE9
{ 0x0C, 0xE0, 0x1F }, // NOP $1FE0
{ 0xAD, 0xE0, 0x1F }, // LDA $1FE0
{ 0xAD, 0xE9, 0xFF }, // LDA $FFE9
{ 0xAD, 0xED, 0xFF }, // LDA $FFED
{ 0xAD, 0xF3, 0xBF } // LDA $BFF3
};
for(uInt32 i = 0; i < 8; ++i)
if(searchForBytes(image.get(), size, signature[i], 3, 1))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyE7(const BytePtr& image, uInt32 size)
{
// E7 cart bankswitching is triggered by accessing addresses
// $FE0 to $FE6 using absolute non-indexed addressing
// To eliminate false positives (and speed up processing), we
// search for only certain known signatures
// Thanks to "stella@casperkitty.com" for this advice
// These signatures are attributed to the MESS project
uInt8 signature[7][3] = {
{ 0xAD, 0xE2, 0xFF }, // LDA $FFE2
{ 0xAD, 0xE5, 0xFF }, // LDA $FFE5
{ 0xAD, 0xE5, 0x1F }, // LDA $1FE5
{ 0xAD, 0xE7, 0x1F }, // LDA $1FE7
{ 0x0C, 0xE7, 0x1F }, // NOP $1FE7
{ 0x8D, 0xE7, 0xFF }, // STA $FFE7
{ 0x8D, 0xE7, 0x1F } // STA $1FE7
};
for(uInt32 i = 0; i < 7; ++i)
if(searchForBytes(image.get(), size, signature[i], 3, 1))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyEF(const BytePtr& image, uInt32 size, BSType& type)
{
// Newer EF carts store strings 'EFEF' and 'EFSC' starting at address $FFF8
// This signature is attributed to "RevEng" of AtariAge
uInt8 efef[] = { 'E', 'F', 'E', 'F' };
uInt8 efsc[] = { 'E', 'F', 'S', 'C' };
if(searchForBytes(image.get()+size-8, 8, efef, 4, 1))
{
type = BSType::_EF;
return true;
}
else if(searchForBytes(image.get()+size-8, 8, efsc, 4, 1))
{
type = BSType::_EFSC;
return true;
}
// Otherwise, EF cart bankswitching switches banks by accessing addresses
// 0xFE0 to 0xFEF, usually with either a NOP or LDA
// It's likely that the code will switch to bank 0, so that's what is tested
bool isEF = false;
uInt8 signature[4][3] = {
{ 0x0C, 0xE0, 0xFF }, // NOP $FFE0
{ 0xAD, 0xE0, 0xFF }, // LDA $FFE0
{ 0x0C, 0xE0, 0x1F }, // NOP $1FE0
{ 0xAD, 0xE0, 0x1F } // LDA $1FE0
};
for(uInt32 i = 0; i < 4; ++i)
{
if(searchForBytes(image.get(), size, signature[i], 3, 1))
{
isEF = true;
break;
}
}
// Now that we know that the ROM is EF, we need to check if it's
// the SC variant
if(isEF)
{
type = isProbablySC(image, size) ? BSType::_EFSC : BSType::_EF;
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyBF(const BytePtr& image, uInt32 size, BSType& type)
{
// BF carts store strings 'BFBF' and 'BFSC' starting at address $FFF8
// This signature is attributed to "RevEng" of AtariAge
uInt8 bf[] = { 'B', 'F', 'B', 'F' };
uInt8 bfsc[] = { 'B', 'F', 'S', 'C' };
if(searchForBytes(image.get()+size-8, 8, bf, 4, 1))
{
type = BSType::_BF;
return true;
}
else if(searchForBytes(image.get()+size-8, 8, bfsc, 4, 1))
{
type = BSType::_BFSC;
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyBUS(const BytePtr& image, uInt32 size)
{
// BUS ARM code has 2 occurrences of the string BUS
// Note: all Harmony/Melody custom drivers also contain the value
// 0x10adab1e (LOADABLE) if needed for future improvement
uInt8 bus[] = { 'B', 'U', 'S'};
return searchForBytes(image.get(), size, bus, 3, 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyCDF(const BytePtr& image, uInt32 size)
{
// CDF ARM code has 3 occurrences of the string DPC+
// Note: all Harmony/Melody custom drivers also contain the value
// 0x10adab1e (LOADABLE) if needed for future improvement
uInt8 signature[] = { 'C', 'D', 'F' };
return searchForBytes(image.get(), size, signature, 3, 3);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyDF(const BytePtr& image, uInt32 size, BSType& type)
{
// BF carts store strings 'DFDF' and 'DFSC' starting at address $FFF8
// This signature is attributed to "RevEng" of AtariAge
uInt8 df[] = { 'D', 'F', 'D', 'F' };
uInt8 dfsc[] = { 'D', 'F', 'S', 'C' };
if(searchForBytes(image.get()+size-8, 8, df, 4, 1))
{
type = BSType::_DF;
return true;
}
else if(searchForBytes(image.get()+size-8, 8, dfsc, 4, 1))
{
type = BSType::_DFSC;
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyFA2(const BytePtr& image, uInt32)
{
// This currently tests only the 32K version of FA2; the 24 and 28K
// versions are easy, in that they're the only possibility with those
// file sizes
// 32K version has all zeros in 29K-32K area
for(uInt32 i = 29*1024; i < 32*1024; ++i)
if(image[i] != 0)
return false;
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyFE(const BytePtr& image, uInt32 size)
{
// FE bankswitching is very weird, but always seems to include a
// 'JSR $xxxx'
// These signatures are attributed to the MESS project
uInt8 signature[4][5] = {
{ 0x20, 0x00, 0xD0, 0xC6, 0xC5 }, // JSR $D000; DEC $C5
{ 0x20, 0xC3, 0xF8, 0xA5, 0x82 }, // JSR $F8C3; LDA $82
{ 0xD0, 0xFB, 0x20, 0x73, 0xFE }, // BNE $FB; JSR $FE73
{ 0x20, 0x00, 0xF0, 0x84, 0xD6 } // JSR $F000; STY $D6
};
for(uInt32 i = 0; i < 4; ++i)
if(searchForBytes(image.get(), size, signature[i], 5, 1))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyMDM(const BytePtr& image, uInt32 size)
{
// MDM cart is identified key 'MDMC' in the first 8K of ROM
uInt8 signature[] = { 'M', 'D', 'M', 'C' };
return searchForBytes(image.get(), std::min(size, 8192u), signature, 4, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablySB(const BytePtr& image, uInt32 size)
{
// SB cart bankswitching switches banks by accessing address 0x0800
uInt8 signature[2][3] = {
{ 0xBD, 0x00, 0x08 }, // LDA $0800,x
{ 0xAD, 0x00, 0x08 } // LDA $0800
};
if(searchForBytes(image.get(), size, signature[0], 3, 1))
return true;
else
return searchForBytes(image.get(), size, signature[1], 3, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyUA(const BytePtr& image, uInt32 size)
{
// UA cart bankswitching switches to bank 1 by accessing address 0x240
// using 'STA $240' or 'LDA $240'
uInt8 signature[3][3] = {
{ 0x8D, 0x40, 0x02 }, // STA $240
{ 0xAD, 0x40, 0x02 }, // LDA $240
{ 0xBD, 0x1F, 0x02 } // LDA $21F,X
};
for(uInt32 i = 0; i < 3; ++i)
if(searchForBytes(image.get(), size, signature[i], 3, 1))
return true;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyX07(const BytePtr& image, uInt32 size)
{
// X07 bankswitching switches to bank 0, 1, 2, etc by accessing address 0x08xd
uInt8 signature[6][3] = {
{ 0xAD, 0x0D, 0x08 }, // LDA $080D
{ 0xAD, 0x1D, 0x08 }, // LDA $081D
{ 0xAD, 0x2D, 0x08 }, // LDA $082D
{ 0x0C, 0x0D, 0x08 }, // NOP $080D
{ 0x0C, 0x1D, 0x08 }, // NOP $081D
{ 0x0C, 0x2D, 0x08 } // NOP $082D
};
for(uInt32 i = 0; i < 6; ++i)
if(searchForBytes(image.get(), size, signature[i], 3, 1))
return true;
return false;
}

View File

@ -0,0 +1,257 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef CARTRIDGE_DETECTOR_HXX
#define CARTRIDGE_DETECTOR_HXX
class Cartridge;
class Properties;
class OSystem;
#include "bspf.hxx"
#include "BSType.hxx"
#include "Settings.hxx"
/**
Auto-detect cart type based on various attributes (file size, signatures,
filenames, etc)
@author Stephen Anthony
*/
class CartDetector
{
public:
/**
Create a new cartridge object allocated on the heap. The
type of cartridge created depends on the properties object.
@param image A pointer to the ROM image
@param size The size of the ROM image
@param md5 The md5sum for the given ROM image (can be updated)
@param dtype The detected bankswitch type of the ROM image
@param system The osystem associated with the system
@return Pointer to the new cartridge object allocated on the heap
*/
static unique_ptr<Cartridge> create(const BytePtr& image, uInt32 size,
string& md5, const string& dtype, const OSystem& system);
private:
/**
Create a cartridge from a multi-cart image pointer; internally this
takes a slice of the ROM image ues that for the cartridge.
@param image A pointer to the complete ROM image
@param size The size of the ROM image slice
@param numroms The number of ROMs in the multicart
@param md5 The md5sum for the slice of the ROM image
@param type The detected type of the slice of the ROM image
@param id The ID for the slice of the ROM image
@param osystem The osystem associated with the system
@return Pointer to the new cartridge object allocated on the heap
*/
static unique_ptr<Cartridge>
createFromMultiCart(const BytePtr& image, uInt32& size,
uInt32 numroms, string& md5, BSType type, string& id,
const OSystem& osystem);
/**
Create a cartridge from the entire image pointer.
@param image A pointer to the complete ROM image
@param size The size of the ROM image
@param type The bankswitch type of the ROM image
@param md5 The md5sum for the ROM image
@param osystem The osystem associated with the system
@return Pointer to the new cartridge object allocated on the heap
*/
static unique_ptr<Cartridge>
createFromImage(const BytePtr& image, uInt32 size, BSType type,
const string& md5, const OSystem& osystem);
/**
Try to auto-detect the bankswitching type of the cartridge
@param image A pointer to the ROM image
@param size The size of the ROM image
@return The "best guess" for the cartridge type
*/
static BSType autodetectType(const BytePtr& image, uInt32 size);
/**
Search the image for the specified byte signature
@param image A pointer to the ROM image
@param imagesize The size of the ROM image
@param signature The byte sequence to search for
@param sigsize The number of bytes in the signature
@param minhits The minimum number of times a signature is to be found
@return True if the signature was found at least 'minhits' time, else false
*/
static bool searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize,
uInt32 minhits);
/**
Returns true if the image is probably a SuperChip (128 bytes RAM)
Note: should be called only on ROMs with size multiple of 4K
*/
static bool isProbablySC(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a 4K SuperChip (128 bytes RAM)
*/
static bool isProbably4KSC(const BytePtr& image, uInt32 size);
/**
Returns true if the image probably contains ARM code in the first 1K
*/
static bool isProbablyARM(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a 0840 bankswitching cartridge
*/
static bool isProbably0840(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a 3E bankswitching cartridge
*/
static bool isProbably3E(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a 3E+ bankswitching cartridge
*/
static bool isProbably3EPlus(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a 3F bankswitching cartridge
*/
static bool isProbably3F(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a 4A50 bankswitching cartridge
*/
static bool isProbably4A50(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a BF/BFSC bankswitching cartridge
*/
static bool isProbablyBF(const BytePtr& image, uInt32 size, BSType& type);
/**
Returns true if the image is probably a BUS bankswitching cartridge
*/
static bool isProbablyBUS(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a CDF bankswitching cartridge
*/
static bool isProbablyCDF(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a CTY bankswitching cartridge
*/
static bool isProbablyCTY(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a CV bankswitching cartridge
*/
static bool isProbablyCV(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a CV+ bankswitching cartridge
*/
static bool isProbablyCVPlus(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a DASH bankswitching cartridge
*/
static bool isProbablyDASH(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a DF/DFSC bankswitching cartridge
*/
static bool isProbablyDF(const BytePtr& image, uInt32 size, BSType& type);
/**
Returns true if the image is probably a DPC+ bankswitching cartridge
*/
static bool isProbablyDPCplus(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a E0 bankswitching cartridge
*/
static bool isProbablyE0(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a E7 bankswitching cartridge
*/
static bool isProbablyE7(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably an EF/EFSC bankswitching cartridge
*/
static bool isProbablyEF(const BytePtr& image, uInt32 size, BSType& type);
/**
Returns true if the image is probably an F6 bankswitching cartridge
*/
static bool isProbablyF6(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably an FA2 bankswitching cartridge
*/
static bool isProbablyFA2(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably an FE bankswitching cartridge
*/
static bool isProbablyFE(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a MDM bankswitching cartridge
*/
static bool isProbablyMDM(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a SB bankswitching cartridge
*/
static bool isProbablySB(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably a UA bankswitching cartridge
*/
static bool isProbablyUA(const BytePtr& image, uInt32 size);
/**
Returns true if the image is probably an X07 bankswitching cartridge
*/
static bool isProbablyX07(const BytePtr& image, uInt32 size);
private:
// Following constructors and assignment operators not supported
CartDetector() = delete;
CartDetector(const CartDetector&) = delete;
CartDetector(CartDetector&&) = delete;
CartDetector& operator=(const CartDetector&) = delete;
CartDetector& operator=(CartDetector&&) = delete;
};
#endif

View File

@ -19,11 +19,12 @@
#include "CartE0.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeE0::CartridgeE0(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeE0::CartridgeE0(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(8192u, size));
memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192);
}

View File

@ -53,7 +53,7 @@ class CartridgeE0 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeE0(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeE0(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeE0() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartE7.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeE7::CartridgeE7(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeE7::CartridgeE7(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentRAM(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(16384u, size));
memcpy(myImage, image.get(), std::min(16384u, size));
createCodeAccessBase(16384 + 2048);
// Remember startup bank

View File

@ -70,7 +70,7 @@ class CartridgeE7 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeE7(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeE7(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeE7() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartEF.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEF::CartridgeEF(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeEF::CartridgeEF(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(65536u, size));
memcpy(myImage, image.get(), std::min(65536u, size));
createCodeAccessBase(65536);
// Remember startup bank

View File

@ -48,7 +48,7 @@ class CartridgeEF : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeEF(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeEF(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeEF() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartEFSC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeEFSC::CartridgeEFSC(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeEFSC::CartridgeEFSC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(65536u, size));
memcpy(myImage, image.get(), std::min(65536u, size));
createCodeAccessBase(65536);
// Remember startup bank

View File

@ -48,7 +48,7 @@ class CartridgeEFSC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeEFSC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeEFSC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeEFSC() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartF0.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF0::CartridgeF0(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeF0::CartridgeF0(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(65536u, size));
memcpy(myImage, image.get(), std::min(65536u, size));
createCodeAccessBase(65536);
// Remember startup bank

View File

@ -45,7 +45,7 @@ class CartridgeF0 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF0(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeF0(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeF0() = default;
public:

View File

@ -20,12 +20,13 @@
#include "CartF4.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF4::CartridgeF4(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeF4::CartridgeF4(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size));
memcpy(myImage, image.get(), std::min(32768u, size));
createCodeAccessBase(32768);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeF4 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF4(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeF4(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeF4() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartF4SC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF4SC::CartridgeF4SC(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeF4SC::CartridgeF4SC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size));
memcpy(myImage, image.get(), std::min(32768u, size));
createCodeAccessBase(32768);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeF4SC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF4SC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeF4SC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeF4SC() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartF6.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF6::CartridgeF6(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeF6::CartridgeF6(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(16384u, size));
memcpy(myImage, image.get(), std::min(16384u, size));
createCodeAccessBase(16384);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeF6 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF6(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeF6(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeF6() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartF6SC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF6SC::CartridgeF6SC(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeF6SC::CartridgeF6SC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(16384u, size));
memcpy(myImage, image.get(), std::min(16384u, size));
createCodeAccessBase(16384);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeF6SC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF6SC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeF6SC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeF6SC() = default;
public:

View File

@ -19,13 +19,13 @@
#include "CartF8.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF8::CartridgeF8(const uInt8* image, uInt32 size, const string& md5,
CartridgeF8::CartridgeF8(const BytePtr& image, uInt32 size, const string& md5,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(8192u, size));
memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192);
// Normally bank 1 is the reset bank, unless we're dealing with ROMs

View File

@ -45,7 +45,7 @@ class CartridgeF8 : public Cartridge
@param md5 MD5sum of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF8(const uInt8* image, uInt32 size, const string& md5,
CartridgeF8(const BytePtr& image, uInt32 size, const string& md5,
const Settings& settings);
virtual ~CartridgeF8() = default;

View File

@ -19,12 +19,13 @@
#include "CartF8SC.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeF8SC::CartridgeF8SC(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeF8SC::CartridgeF8SC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(8192u, size));
memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeF8SC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeF8SC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeF8SC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeF8SC() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartFA.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFA::CartridgeFA(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeFA::CartridgeFA(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(12288u, size));
memcpy(myImage, image.get(), std::min(12288u, size));
createCodeAccessBase(12288);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeFA : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeFA(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeFA(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeFA() = default;
public:

View File

@ -21,7 +21,8 @@
#include "CartFA2.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osystem)
CartridgeFA2::CartridgeFA2(const BytePtr& image, uInt32 size,
const OSystem& osystem)
: Cartridge(osystem.settings()),
myOSystem(osystem),
mySize(28 * 1024),
@ -29,13 +30,14 @@ CartridgeFA2::CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osyst
myCurrentBank(0)
{
// 29/32K version of FA2 has valid data @ 1K - 29K
const uInt8* img_ptr = image.get();
if(size >= 29 * 1024)
image += 1024;
img_ptr += 1024;
else if(size < mySize)
mySize = size;
// Copy the ROM image into my buffer
memcpy(myImage, image, mySize);
memcpy(myImage, img_ptr, mySize);
createCodeAccessBase(mySize);
// Remember startup bank

View File

@ -52,7 +52,7 @@ class CartridgeFA2 : public Cartridge
@param size The size of the ROM image
@param osystem A reference to the OSystem currently in use
*/
CartridgeFA2(const uInt8* image, uInt32 size, const OSystem& osystem);
CartridgeFA2(const BytePtr& image, uInt32 size, const OSystem& osystem);
virtual ~CartridgeFA2() = default;
public:

View File

@ -19,14 +19,15 @@
#include "CartFE.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeFE::CartridgeFE(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeFE::CartridgeFE(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myLastAddress1(0),
myLastAddress2(0),
myLastAddressChanged(false)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(8192u, size));
memcpy(myImage, image.get(), std::min(8192u, size));
// We use System::PageAccess.codeAccessBase, but don't allow its use
// through a pointer, since the address space of FE carts can change

View File

@ -59,7 +59,7 @@ class CartridgeFE : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeFE(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeFE(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeFE() = default;
public:

View File

@ -28,7 +28,7 @@
// TODO (2010-10-03) - support CodeAccessBase functionality somehow
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeMC::CartridgeMC(const uInt8* image, uInt32 size,
CartridgeMC::CartridgeMC(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySlot3Locked(false)
@ -40,7 +40,7 @@ CartridgeMC::CartridgeMC(const uInt8* image, uInt32 size,
memset(myImage, 0, 131072);
// Copy the ROM image to the end of the ROM buffer
memcpy(myImage + 131072 - size, image, size);
memcpy(myImage + 131072 - size, image.get(), size);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -150,7 +150,7 @@ class CartridgeMC : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeMC(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeMC(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeMC() = default;
public:

View File

@ -19,7 +19,8 @@
#include "CartMDM.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeMDM::CartridgeMDM(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeMDM::CartridgeMDM(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
myCurrentBank(0),
@ -29,7 +30,7 @@ CartridgeMDM::CartridgeMDM(const uInt8* image, uInt32 size, const Settings& sett
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize);
// Remember startup bank

View File

@ -56,7 +56,7 @@ class CartridgeMDM : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeMDM(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeMDM(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeMDM() = default;
public:

View File

@ -19,7 +19,7 @@
#include "CartSB.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeSB::CartridgeSB(const uInt8* image, uInt32 size,
CartridgeSB::CartridgeSB(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(size),
@ -29,7 +29,7 @@ CartridgeSB::CartridgeSB(const uInt8* image, uInt32 size,
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
memcpy(myImage.get(), image.get(), mySize);
createCodeAccessBase(mySize);
// Remember startup bank

View File

@ -45,7 +45,7 @@ class CartridgeSB : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeSB(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeSB(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeSB() = default;
public:

View File

@ -19,12 +19,13 @@
#include "CartUA.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeUA::CartridgeUA(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeUA::CartridgeUA(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(8192u, size));
memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192);
// Remember startup bank

View File

@ -44,7 +44,7 @@ class CartridgeUA : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeUA(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeUA(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeUA() = default;
public:

View File

@ -21,7 +21,7 @@
#include "CartWD.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWD::CartridgeWD(const uInt8* image, uInt32 size,
CartridgeWD::CartridgeWD(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
mySize(std::min(8195u, size)),
@ -30,7 +30,7 @@ CartridgeWD::CartridgeWD(const uInt8* image, uInt32 size,
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, mySize);
memcpy(myImage, image.get(), mySize);
createCodeAccessBase(8192);
// Remember startup bank

View File

@ -73,7 +73,7 @@ class CartridgeWD : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeWD(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeWD(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeWD() = default;
public:

View File

@ -21,12 +21,13 @@
#include "CartX07.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeX07::CartridgeX07(const uInt8* image, uInt32 size, const Settings& settings)
CartridgeX07::CartridgeX07(const BytePtr& image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myCurrentBank(0)
{
// Copy the ROM image into my buffer
memcpy(myImage, image, std::min(65536u, size));
memcpy(myImage, image.get(), std::min(65536u, size));
createCodeAccessBase(65536);
// Remember startup bank

View File

@ -54,7 +54,7 @@ class CartridgeX07 : public Cartridge
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeX07(const uInt8* image, uInt32 size, const Settings& settings);
CartridgeX07(const BytePtr& image, uInt32 size, const Settings& settings);
virtual ~CartridgeX07() = default;
public:

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@
#include "FSNode.hxx"
#include "MD5.hxx"
#include "Cart.hxx"
#include "CartDetector.hxx"
#include "Settings.hxx"
#include "PropsSet.hxx"
#include "EventHandler.hxx"
@ -307,11 +308,10 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
// Create an instance of the 2600 game console
ostringstream buf;
string type, id;
try
{
closeConsole();
myConsole = openConsole(myRomFile, myRomMD5, type, id);
myConsole = openConsole(myRomFile, myRomMD5);
}
catch(const runtime_error& e)
{
@ -342,10 +342,12 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum,
if(showmessage)
{
const string& id = myConsole->cartridge().multiCartID();
if(id == "")
myFrameBuffer->showMessage("New console created");
else
myFrameBuffer->showMessage("Multicart " + type + ", loading ROM" + id);
myFrameBuffer->showMessage("Multicart " +
myConsole->cartridge().detectedType() + ", loading ROM" + id);
}
buf << "Game console created:" << endl
<< " ROM file: " << myRomFile.getShortPath() << endl << endl
@ -442,8 +444,8 @@ string OSystem::getROMInfo(const FilesystemNode& romfile)
unique_ptr<Console> console;
try
{
string md5, type, id;
console = openConsole(romfile, md5, type, id);
string md5;
console = openConsole(romfile, md5);
}
catch(const runtime_error& e)
{
@ -472,8 +474,8 @@ void OSystem::logMessage(const string& message, uInt8 level)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile,
string& md5, string& type, string& id)
unique_ptr<Console>
OSystem::openConsole(const FilesystemNode& romfile, string& md5)
{
unique_ptr<Console> console;
@ -498,9 +500,9 @@ unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile,
// Now create the cartridge
string cartmd5 = md5;
type = props.get(Cartridge_Type);
const string& type = props.get(Cartridge_Type);
unique_ptr<Cartridge> cart =
Cartridge::create(image, size, cartmd5, type, id, *this, *mySettings);
CartDetector::create(image, size, cartmd5, type, *this);
// It's possible that the cart created was from a piece of the image,
// and that the md5 (and hence the cart) has changed
@ -510,7 +512,7 @@ unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile,
{
// Cart md5 wasn't found, so we create a new props for it
props.set(Cartridge_MD5, cartmd5);
props.set(Cartridge_Name, props.get(Cartridge_Name)+id);
props.set(Cartridge_Name, props.get(Cartridge_Name)+cart->multiCartID());
myPropSet->insert(props, false);
}
}

View File

@ -531,13 +531,10 @@ class OSystem
@param romfile The file node of the ROM to use (contains path)
@param md5 The MD5sum of the ROM
@param type The bankswitch type of the ROM
@param id The additional id (if any) used by the ROM
@return The actual Console object, otherwise nullptr.
*/
unique_ptr<Console> openConsole(const FilesystemNode& romfile, string& md5,
string& type, string& id);
unique_ptr<Console> openConsole(const FilesystemNode& romfile, string& md5);
/**
Close and finalize any currently open console.

View File

@ -310,7 +310,7 @@ void Properties::printHeader()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* Properties::ourDefaultProperties[LastPropType] = {
const char* const Properties::ourDefaultProperties[LastPropType] = {
"", // Cartridge.MD5
"", // Cartridge.Manufacturer
"", // Cartridge.ModelNo
@ -335,7 +335,7 @@ const char* Properties::ourDefaultProperties[LastPropType] = {
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* Properties::ourPropertyNames[LastPropType] = {
const char* const Properties::ourPropertyNames[LastPropType] = {
"Cartridge.MD5",
"Cartridge.Manufacturer",
"Cartridge.ModelNo",

View File

@ -183,10 +183,10 @@ class Properties
string myProperties[LastPropType];
// List of default properties to use when none have been provided
static const char* ourDefaultProperties[LastPropType];
static const char* const ourDefaultProperties[LastPropType];
// The text strings associated with each property type
static const char* ourPropertyNames[LastPropType];
static const char* const ourPropertyNames[LastPropType];
};
#endif

View File

@ -4,6 +4,7 @@ MODULE_OBJS := \
src/emucore/AtariVox.o \
src/emucore/Booster.o \
src/emucore/Cart.o \
src/emucore/CartDetector.o \
src/emucore/Cart0840.o \
src/emucore/Cart2K.o \
src/emucore/Cart3E.o \

View File

@ -15,7 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "Cart.hxx"
#include "BSType.hxx"
#include "Console.hxx"
#include "MouseControl.hxx"
#include "Dialog.hxx"
@ -124,8 +124,8 @@ GameInfoDialog::GameInfoDialog(
"Type", kTextAlignLeft);
pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)");
items.clear();
for(int i = 0; i < Cartridge::ourNumBSTypes; ++i)
VarList::push_back(items, Cartridge::ourBSList[i].desc, Cartridge::ourBSList[i].type);
for(int i = 0; i < int(BSType::NumSchemes); ++i)
VarList::push_back(items, BSList[i].desc, BSList[i].name);
myType = new PopUpWidget(myTab, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myType);

View File

@ -17,7 +17,7 @@
#include "bspf.hxx"
#include "Cart.hxx"
#include "BSType.hxx"
#include "Control.hxx"
#include "Dialog.hxx"
#include "OSystem.hxx"
@ -54,8 +54,8 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font)
// Bankswitch type
new StaticTextWidget(this, font, xpos, ypos+1, lwidth, fontHeight,
"Bankswitch type", kTextAlignLeft);
for(int i = 0; i < Cartridge::ourNumBSTypes; ++i)
VarList::push_back(items, Cartridge::ourBSList[i].desc, Cartridge::ourBSList[i].type);
for(int i = 0; i < int(BSType::NumSchemes); ++i)
VarList::push_back(items, BSList[i].desc, BSList[i].name);
myBSType = new PopUpWidget(this, font, xpos+lwidth, ypos,
pwidth, lineHeight, items, "", 0, 0);
wid.push_back(myBSType);
@ -308,6 +308,6 @@ void GlobalPropsDialog::handleCommand(CommandSender* sender, int cmd,
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* GlobalPropsDialog::ourJoyState[10] = {
const char* const GlobalPropsDialog::ourJoyState[10] = {
"U", "D", "L", "R", "F", "U", "D", "L", "R", "F"
};

View File

@ -58,7 +58,7 @@ class GlobalPropsDialog : public Dialog, public CommandSender
CheckboxWidget* myHoldSelect;
CheckboxWidget* myHoldReset;
static const char* ourJoyState[10];
static const char* const ourJoyState[10];
private:
// Following constructors and assignment operators not supported

View File

@ -60,7 +60,7 @@ print OUTFILE " regenerated and the application recompiled.\n";
print OUTFILE "*/\n";
print OUTFILE "\n#define DEF_PROPS_SIZE " . $setsize;
print OUTFILE "\n\n";
print OUTFILE "static const char* DefProps[DEF_PROPS_SIZE][" . $typesize . "] = {\n";
print OUTFILE "static const char* const DefProps[DEF_PROPS_SIZE][" . $typesize . "] = {\n";
# Walk the hash map and print each item in order of md5sum
my $idx = 0;