Added 'CV+' bankswitching scheme.

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3253 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2016-01-23 17:58:00 +00:00
parent 821f22c205
commit 143b22baec
11 changed files with 697 additions and 7 deletions

View File

@ -18,7 +18,7 @@
- Added ability to specify the maximum range of movement for paddles
when using a mouse or digital device to emulate the paddle. This is
needed, since on a real console most paddle games use very little of
useful since on a real console most paddle games use very little of
the paddle range, and could result in moving the mouse onscreen with
nothing appearing to happen (when in effect it was as if you turned
a real paddle all the way to the end of the range). This eliminates
@ -39,6 +39,10 @@
ROM properties was being stored in the external file when it was
exactly the same as the internal entry.
* Added 'CV+' bankswitching scheme, developed by myself and LS_Dracon
(of AtariAge). This scheme contains RAM like the CV scheme, and
also switchable 2K ROM segments by writing to $3D.
* Added more C++11 updates all over the codebase, and ran Stella
through Coverity for the first time. I'm proud to say that Stella
now has a 0.00 defect rate!

View File

@ -3224,6 +3224,7 @@ Ms Pac-Man (Stella extended codes):
<tr><td>BFSC </td><td>CPUWIZ 256K + ram</td></tr>
<tr><td>CM &#185;</td><td>Spectravideo CompuMate </td></tr>
<tr><td>CV </td><td>Commavid extra ram </td></tr>
<tr><td>CV+ </td><td>Extended Commavid extra ram</td></tr>
<tr><td>DASH </td><td>Boulder Dash 2 </td></tr>
<tr><td>DF </td><td>CPUWIZ 128K </td></tr>
<tr><td>DFSC </td><td>CPUWIZ 128K + ram</td></tr>

View File

@ -0,0 +1,154 @@
//============================================================================
//
// 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-2016 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.
//
// $Id$
//============================================================================
#include "CartCVPlus.hxx"
#include "PopUpWidget.hxx"
#include "CartCVPlusWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCVPlusWidget::CartridgeCVPlusWidget(
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
int x, int y, int w, int h, CartridgeCVPlus& cart)
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
myCart(cart)
{
uInt32 size = cart.mySize;
ostringstream info;
info << "LS_Dracon CV+ cartridge, 1K RAM, 2-256 2K ROM\n"
<< "1024 bytes RAM @ $F000 - $F7FF\n"
<< " $F000 - $F3FF (R), $F400 - $F7FF (W)\n"
<< "2048 bytes ROM @ $F800 - $FFFF, by writing to $3D\n"
<< "Startup bank = " << cart.myStartBank << "\n";
int xpos = 10,
ypos = addBaseInformation(size, "LS_Dracon / Stephen Anthony",
info.str()) + myLineHeight;
VariantList items;
for(uInt16 i = 0; i < cart.bankCount(); ++i)
VarList::push_back(items, Variant(i).toString() + " ($3D)");
ostringstream label;
label << "Set bank ($F800 - $FFFF): ";
myBank =
new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("xxx ($3D) "),
myLineHeight, items, label.str(),
_font.getStringWidth(label.str()), kBankChanged);
myBank->setTarget(this);
addFocusWidget(myBank);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCVPlusWidget::loadConfig()
{
myBank->setSelectedIndex(myCart.myCurrentBank);
CartDebugWidget::loadConfig();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCVPlusWidget::handleCommand(CommandSender* sender,
int cmd, int data, int id)
{
if(cmd == kBankChanged)
{
myCart.unlockBank();
myCart.bank(myBank->getSelected());
myCart.lockBank();
invalidate();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeCVPlusWidget::bankState()
{
ostringstream& buf = buffer();
buf << "Bank = " << dec << myCart.myCurrentBank << ", hotspot = $3D";
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCVPlusWidget::saveOldState()
{
myOldState.internalram.clear();
for(uInt32 i = 0; i < this->internalRamSize();i++)
myOldState.internalram.push_back(myCart.myRAM[i]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCVPlusWidget::internalRamSize()
{
return 1024;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCVPlusWidget::internalRamRPort(int start)
{
return 0xF000 + start;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeCVPlusWidget::internalRamDescription()
{
ostringstream desc;
desc << "$F000 - $F3FF used for Read Access\n"
<< "$F400 - $F7FF used for Write Access";
return desc.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const ByteArray& CartridgeCVPlusWidget::internalRamOld(int start, int count)
{
myRamOld.clear();
for(int i = 0; i < count; i++)
myRamOld.push_back(myOldState.internalram[start + i]);
return myRamOld;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const ByteArray& CartridgeCVPlusWidget::internalRamCurrent(int start, int count)
{
myRamCurrent.clear();
for(int i = 0; i < count; i++)
myRamCurrent.push_back(myCart.myRAM[start + i]);
return myRamCurrent;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCVPlusWidget::internalRamSetValue(int addr, uInt8 value)
{
myCart.myRAM[addr] = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeCVPlusWidget::internalRamGetValue(int addr)
{
return myCart.myRAM[addr];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeCVPlusWidget::internalRamLabel(int addr)
{
CartDebug& dbg = instance().debugger().cartDebug();
return dbg.getLabel(addr + 0xF000, false);
}

View File

@ -0,0 +1,74 @@
//============================================================================
//
// 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-2016 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.
//
// $Id$
//============================================================================
#ifndef CARTRIDGECVPlus_WIDGET_HXX
#define CARTRIDGECVPlus_WIDGET_HXX
class CartridgeCVPlus;
class PopUpWidget;
#include "CartDebugWidget.hxx"
class CartridgeCVPlusWidget : public CartDebugWidget
{
public:
CartridgeCVPlusWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont,
int x, int y, int w, int h,
CartridgeCVPlus& cart);
virtual ~CartridgeCVPlusWidget() = default;
private:
CartridgeCVPlus& myCart;
PopUpWidget* myBank;
struct CartState {
ByteArray internalram;
};
CartState myOldState;
enum { kBankChanged = 'bkCH' };
private:
void loadConfig() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
string bankState() override;
void saveOldState() override;
// start of functions for Cartridge RAM tab
uInt32 internalRamSize() override;
uInt32 internalRamRPort(int start) override;
string internalRamDescription() override;
const ByteArray& internalRamOld(int start, int count) override;
const ByteArray& internalRamCurrent(int start, int count) override;
void internalRamSetValue(int addr, uInt8 value) override;
uInt8 internalRamGetValue(int addr) override;
string internalRamLabel(int addr) override;
// end of functions for Cartridge RAM tab
// Following constructors and assignment operators not supported
CartridgeCVPlusWidget() = delete;
CartridgeCVPlusWidget(const CartridgeCVPlusWidget&) = delete;
CartridgeCVPlusWidget(CartridgeCVPlusWidget&&) = delete;
CartridgeCVPlusWidget& operator=(const CartridgeCVPlusWidget&) = delete;
CartridgeCVPlusWidget& operator=(CartridgeCVPlusWidget&&) = delete;
};
#endif

View File

@ -46,12 +46,9 @@ CartridgeCVWidget::CartridgeCVWidget(
void CartridgeCVWidget::saveOldState()
{
myOldState.internalram.clear();
for(uInt32 i = 0; i < this->internalRamSize();i++)
{
myOldState.internalram.push_back(myCart.myRAM[i]);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCVWidget::internalRamSize()
@ -111,4 +108,3 @@ string CartridgeCVWidget::internalRamLabel(int addr)
CartDebug& dbg = instance().debugger().cartDebug();
return dbg.getLabel(addr + 0xF000, false);
}

View File

@ -33,6 +33,7 @@ MODULE_OBJS := \
src/debugger/gui/CartCMWidget.o \
src/debugger/gui/CartCTYWidget.o \
src/debugger/gui/CartCVWidget.o \
src/debugger/gui/CartCVPlusWidget.o \
src/debugger/gui/CartDASHWidget.o \
src/debugger/gui/CartDPCWidget.o \
src/debugger/gui/CartDPCPlusWidget.o \

View File

@ -34,6 +34,7 @@
#include "CartCM.hxx"
#include "CartCTY.hxx"
#include "CartCV.hxx"
#include "CartCVPlus.hxx"
#include "CartDASH.hxx"
#include "CartDPC.hxx"
#include "CartDPCPlus.hxx"
@ -207,6 +208,8 @@ unique_ptr<Cartridge> Cartridge::create(const BytePtr& img, uInt32 size,
cartridge = make_ptr<CartridgeCTY>(image, size, osystem);
else if(type == "CV")
cartridge = make_ptr<CartridgeCV>(image, size, settings);
else if(type == "CV+")
cartridge = make_ptr<CartridgeCVPlus>(image, size, settings);
else if(type == "DASH")
cartridge = make_ptr<CartridgeDASH>(image, size, settings);
else if(type == "DPC")
@ -372,7 +375,11 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
// Guess type based on size
const char* type = nullptr;
if((size % 8448) == 0 || size == 6144)
if(isProbablyCVPlus(image,size))
{
type = "CV+";
}
else if((size % 8448) == 0 || size == 6144)
{
type = "AR";
}
@ -698,6 +705,16 @@ bool Cartridge::isProbablyCV(const uInt8* image, uInt32 size)
return searchForBytes(image, size, signature[1], 3, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge::isProbablyCVPlus(const uInt8* 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+4, 24, signature, 12, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge::isProbablyDASH(const uInt8* image, uInt32 size)
{
@ -973,6 +990,7 @@ Cartridge::BankswitchType Cartridge::ourBSList[] = {
{ "BF", "BF (CPUWIZ 256K)" },
{ "BFSC", "BFSC (CPUWIZ 256K + ram)" },
{ "CV", "CV (Commavid extra ram)" },
{ "CV+", "CV+ (Extended Commavid)" },
{ "CM", "CM (SpectraVideo CompuMate)" },
{ "DASH", "DASH (Experimental)" },
{ "DF", "DF (CPUWIZ 128K)" },

View File

@ -194,7 +194,7 @@ class Cartridge : public Device
const char* type;
const char* desc;
};
enum { ourNumBSTypes = 45 };
enum { ourNumBSTypes = 46 };
static BankswitchType ourBSList[ourNumBSTypes];
protected:
@ -305,6 +305,11 @@ class Cartridge : public Device
*/
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
*/

248
src/emucore/CartCVPlus.cxx Normal file
View File

@ -0,0 +1,248 @@
//============================================================================
//
// 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-2016 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.
//
// $Id$
//============================================================================
#include <cstring>
#include "System.hxx"
#include "TIA.hxx"
#include "CartCVPlus.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCVPlus::CartridgeCVPlus(const uInt8* image, uInt32 size,
const Settings& settings)
: Cartridge(settings),
myImage(nullptr),
mySize(size),
myCurrentBank(0)
{
// Allocate array for the ROM image
myImage = make_ptr<uInt8[]>(mySize);
// Copy the ROM image into my buffer
memcpy(myImage.get(), image, mySize);
createCodeAccessBase(mySize + 1024);
// Remember startup bank
myStartBank = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCVPlus::reset()
{
// Initialize RAM
if(mySettings.getBool("ramrandom"))
for(uInt32 i = 0; i < 1024; ++i)
myRAM[i] = mySystem->randGenerator().next();
else
memset(myRAM, 0, 1024);
// We'll map the startup bank into the first segment upon reset
bank(myStartBank);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCVPlus::install(System& system)
{
mySystem = &system;
System::PageAccess access(this, System::PA_READWRITE);
// Set the page accessing methods for the hot spots (for 100% emulation
// we need to chain any accesses below 0x40 to the TIA. Our poke() method
// does this via mySystem->tiaPoke(...), at least until we come up with a
// cleaner way to do it).
for(uInt32 i = 0x00; i < 0x40; i += (1 << System::PAGE_SHIFT))
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
// Set the page accessing method for the RAM writing pages
access.directPeekBase = 0;
access.codeAccessBase = 0;
access.type = System::PA_WRITE;
for(uInt32 j = 0x1400; j < 0x1800; j += (1 << System::PAGE_SHIFT))
{
access.directPokeBase = &myRAM[j & 0x03FF];
access.codeAccessBase = &myCodeAccessBase[mySize + (j & 0x03FF)];
mySystem->setPageAccess(j >> System::PAGE_SHIFT, access);
}
// Set the page accessing method for the RAM reading pages
access.directPokeBase = 0;
access.type = System::PA_READ;
for(uInt32 k = 0x1000; k < 0x1400; k += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &myRAM[k & 0x03FF];
access.codeAccessBase = &myCodeAccessBase[mySize + (k & 0x03FF)];
mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
}
// Install pages for the startup bank into the first segment
bank(myStartBank);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeCVPlus::peek(uInt16 address)
{
if((address & 0x0FFF) < 0x0800) // Write port is at 0xF400 - 0xF800 (1024 bytes)
{ // Read port is handled in ::install()
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
if(bankLocked())
return value;
else
{
triggerReadFromWritePort(address);
return myRAM[address & 0x03FF] = value;
}
}
else
return myImage[(address & 0x07FF) + (myCurrentBank << 11)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeCVPlus::poke(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
// Switch banks if necessary
if(address == 0x003D)
bank(value);
// Pass the poke through to the TIA. In a real Atari, both the cart and the
// TIA see the address lines, and both react accordingly. In Stella, each
// 64-byte chunk of address space is "owned" by only one device. If we
// don't chain the poke to the TIA, then the TIA can't see it...
mySystem->tia().poke(address, value);
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeCVPlus::bank(uInt16 bank)
{
if(bankLocked()) return false;
// Make sure the bank they're asking for is reasonable
if((uInt32(bank) << 11) < mySize)
{
myCurrentBank = bank;
}
else
{
// Oops, the bank they're asking for isn't valid so let's wrap it
// around to a valid bank number
myCurrentBank = bank % (mySize >> 11);
}
cerr << "bank: " << myCurrentBank << endl;
uInt32 offset = myCurrentBank << 11;
// Setup the page access methods for the current bank
System::PageAccess access(this, System::PA_READ);
// Map ROM image into the system
for(uInt32 address = 0x1800; address < 0x2000;
address += (1 << System::PAGE_SHIFT))
{
access.directPeekBase = &myImage[offset + (address & 0x07FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x07FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
}
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeCVPlus::getBank() const
{
return myCurrentBank;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeCVPlus::bankCount() const
{
return mySize >> 11;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeCVPlus::patch(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
if(address < 0x0800)
{
// Normally, a write to the read port won't do anything
// However, the patch command is special in that ignores such
// cart restrictions
// The following will work for both reads and writes
myRAM[address & 0x03FF] = value;
}
else
myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value;
return myBankChanged = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeCVPlus::getImage(int& size) const
{
size = mySize;
return myImage.get();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeCVPlus::save(Serializer& out) const
{
try
{
out.putString(name());
out.putShort(myCurrentBank);
out.putByteArray(myRAM, 1024);
}
catch(...)
{
cerr << "ERROR: CartridgeCVPlus::save" << endl;
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeCVPlus::load(Serializer& in)
{
try
{
if(in.getString() != name())
return false;
myCurrentBank = in.getShort();
in.getByteArray(myRAM, 1024);
}
catch(...)
{
cerr << "ERROR: CartridgeCVPlus::load" << endl;
return false;
}
// Now, go to the current bank
bank(myCurrentBank);
return true;
}

188
src/emucore/CartCVPlus.hxx Normal file
View File

@ -0,0 +1,188 @@
//============================================================================
//
// 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-2016 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.
//
// $Id$
//============================================================================
#ifndef CARTRIDGECVPlus_HXX
#define CARTRIDGECVPlus_HXX
class System;
#include "bspf.hxx"
#include "Cart.hxx"
#ifdef DEBUGGER_SUPPORT
#include "CartCVPlusWidget.hxx"
#endif
/**
Cartridge class based on both Commavid and 3F/3E schemes:
Commavid (RAM):
$F000-$F3FF read from RAM
$F400-$F7FF write to RAM
3F/3E (ROM):
$F800-$FFFF ROM
In this bankswitching scheme the 2600's 4K cartridge
address space is broken into two 2K segments. The lower 2K
is RAM, as decribed above (same as CV/Commavid scheme).
To map ROM, the desired bank number of the upper 2K segment is
selected by storing its value into $3D.
@author Stephen Anthony, LS_Dracon
@version $Id$
*/
class CartridgeCVPlus : public Cartridge
{
friend class CartridgeCVPlusWidget;
public:
/**
Create a new cartridge using the specified image and size
@param image Pointer to the ROM image
@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);
virtual ~CartridgeCVPlus() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Install cartridge in the specified system. Invoked by the system
when the cartridge is attached to it.
@param system The system the device should install itself in
*/
void install(System& system) override;
/**
Install pages for the specified bank in the system.
@param bank The bank that should be installed in the system
*/
bool bank(uInt16 bank) override;
/**
Get the current bank.
*/
uInt16 getBank() const override;
/**
Query the number of banks supported by the cartridge.
*/
uInt16 bankCount() const override;
/**
Patch the cartridge ROM.
@param address The ROM address to patch
@param value The value to place into the address
@return Success or failure of the patch operation
*/
bool patch(uInt16 address, uInt8 value) override;
/**
Access the internal ROM image for this cartridge.
@param size Set to the size of the internal ROM image data
@return A pointer to the internal ROM image data
*/
const uInt8* getImage(int& size) const override;
/**
Save the current state of this cart to the given Serializer.
@param out The Serializer object to use
@return False on any errors, else true
*/
bool save(Serializer& out) const override;
/**
Load the current state of this cart from the given Serializer.
@param in The Serializer object to use
@return False on any errors, else true
*/
bool load(Serializer& in) override;
/**
Get a descriptor for the device name (used in error checking).
@return The name of the object
*/
string name() const override { return "CartridgeCV+"; }
#ifdef DEBUGGER_SUPPORT
/**
Get debugger widget responsible for accessing the inner workings
of the cart.
*/
CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, int x, int y, int w, int h) override
{
return new CartridgeCVPlusWidget(boss, lfont, nfont, x, y, w, h, *this);
}
#endif
public:
/**
Get the byte at the specified address
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@param address The address where the value should be stored
@param value The value to be stored at the address
@return True if the poke changed the device address space, else false
*/
bool poke(uInt16 address, uInt8 value) override;
private:
// Pointer to a dynamically allocated ROM image of the cartridge
unique_ptr<uInt8[]> myImage;
// The 1024 bytes of RAM
uInt8 myRAM[1024];
// Size of the ROM image
uInt32 mySize;
// Indicates which bank is currently active for the first segment
uInt16 myCurrentBank;
private:
// Following constructors and assignment operators not supported
CartridgeCVPlus() = delete;
CartridgeCVPlus(const CartridgeCVPlus&) = delete;
CartridgeCVPlus(CartridgeCVPlus&&) = delete;
CartridgeCVPlus& operator=(const CartridgeCVPlus&) = delete;
CartridgeCVPlus& operator=(CartridgeCVPlus&&) = delete;
};
#endif

View File

@ -15,6 +15,7 @@ MODULE_OBJS := \
src/emucore/CartCM.o \
src/emucore/CartCTY.o \
src/emucore/CartCV.o \
src/emucore/CartCVPlus.o \
src/emucore/CartDASH.o \
src/emucore/CartDPC.o \
src/emucore/CartDPCPlus.o \