Changed CartWD hotspots from $30 - $3F of the cart RAM area to the TIA area (I really need

to learn to read the specs more closely).  Changed hotspot change to trigger 3 cycles after
initiated instead of 3 address changes.

Added CartWDWidget debugger class, to view/change cart-specific functionality from within
the debugger.

Still TODO is CartWD patching.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3105 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-12-13 19:45:18 +00:00
parent c7fc207b13
commit 31ca88d283
6 changed files with 368 additions and 87 deletions

View File

@ -56,7 +56,7 @@ class CartDebugWidget : public Widget, public CommandSender
{ {
const int lwidth = _font.getStringWidth("Manufacturer: "), const int lwidth = _font.getStringWidth("Manufacturer: "),
fwidth = _w - lwidth - 20; fwidth = _w - lwidth - 20;
EditTextWidget* w = 0; EditTextWidget* w = nullptr;
ostringstream buf; ostringstream buf;
int x = 10, y = 10; int x = 10, y = 10;
@ -80,7 +80,7 @@ class CartDebugWidget : public Widget, public CommandSender
w->setEditable(false); w->setEditable(false);
y += myLineHeight + 4; y += myLineHeight + 4;
StringParser bs(desc, (fwidth - kScrollBarWidth) / myFontWidth); StringParser bs(desc, (fwidth - kScrollBarWidth) / myFontWidth - 4);
const StringList& sl = bs.stringList(); const StringList& sl = bs.stringList();
uInt32 lines = (uInt32)sl.size(); uInt32 lines = (uInt32)sl.size();
if(lines < 3) lines = 3; if(lines < 3) lines = 3;

View File

@ -0,0 +1,172 @@
//============================================================================
//
// 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-2014 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 "CartWD.hxx"
#include "PopUpWidget.hxx"
#include "CartWDWidget.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWDWidget::CartridgeWDWidget(
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
int x, int y, int w, int h, CartridgeWD& cart)
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
myCart(cart)
{
string info =
"This scheme has eight 1K slices, which can be mapped into four 1K "
"segments in various combinations. Each 'bank' selects a predefined "
"segment arrangement (indicated in square brackets)\n"
"The last four banks swap in an extra 3 bytes from above the 8K "
"cart boundary into the third (uppermost) segment at $3FC - $3FE\n\n"
"64 bytes RAM @ $F000 - $F080\n"
" $F000 - $F03F (R), $F040 - $F07F (W)\n";
int xpos = 10,
ypos = addBaseInformation(myCart.mySize, "Wickstead Design", info) + myLineHeight;
VariantList items;
VarList::push_back(items, "0 ($30) [0,0,1,2]", 0);
VarList::push_back(items, "1 ($31) [0,1,3,2]", 1);
VarList::push_back(items, "2 ($32) [4,5,6,7]", 2);
VarList::push_back(items, "3 ($33) [7,4,3,2]", 3);
VarList::push_back(items, "4 ($34) [0,0,6,7]", 4);
VarList::push_back(items, "5 ($35) [0,1,7,6]", 5);
VarList::push_back(items, "6 ($36) [3,2,4,5]", 6);
VarList::push_back(items, "7 ($37) [6,0,5,1]", 7);
VarList::push_back(items, "8 ($38) [0,0,1,2]", 8);
VarList::push_back(items, "9 ($39) [0,1,3,2]", 9);
VarList::push_back(items, "10 ($3A) [4,5,6,7]", 10);
VarList::push_back(items, "11 ($3B) [7,4,3,2]", 11);
VarList::push_back(items, "12 ($3C) [0,0,6,7*]", 12);
VarList::push_back(items, "13 ($3D) [0,1,7,6*]", 13);
VarList::push_back(items, "14 ($3E) [3,2,4,5*]", 14);
VarList::push_back(items, "15 ($3F) [6,0,5,1*]", 15);
myBank = new PopUpWidget(boss, _font, xpos, ypos-2,
_font.getStringWidth("15 ($3F) [6,0,5,1*]"),
myLineHeight, items, "Set bank: ",
_font.getStringWidth("Set bank: "), kBankChanged);
myBank->setTarget(this);
addFocusWidget(myBank);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWDWidget::saveOldState()
{
myOldState.internalram.clear();
for(uInt32 i = 0; i < internalRamSize(); ++i)
myOldState.internalram.push_back(myCart.myRAM[i]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWDWidget::loadConfig()
{
myBank->setSelectedIndex(myCart.getBank());
CartDebugWidget::loadConfig();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWDWidget::handleCommand(CommandSender* sender,
int cmd, int data, int id)
{
if(cmd == kBankChanged)
{
myCart.unlockBank();
myCart.bank(myBank->getSelected());
myCart.lockBank();
invalidate();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeWDWidget::bankState()
{
ostringstream& buf = buffer();
static const char* segments[] = {
"[0,0,1,2]", "[0,1,3,2]", "[4,5,6,7]", "[7,4,3,2]",
"[0,0,6,7]", "[0,1,7,6]", "[3,2,4,5]", "[6,0,5,1]",
"[0,0,1,2]", "[0,1,3,2]", "[4,5,6,7]", "[7,4,3,2]",
"[0,0,6,7*]", "[0,1,7,6*]", "[3,2,4,5*]", "[6,0,5,1*]"
};
uInt16 bank = myCart.getBank();
buf << "Bank = " << dec << bank << ", segments = " << segments[bank];
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeWDWidget::internalRamSize()
{
return 64;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeWDWidget::internalRamRPort(int start)
{
return 0xF000 + start;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeWDWidget::internalRamDescription()
{
ostringstream desc;
desc << "$F000 - $F03F used for Read Access\n"
<< "$F040 - $F07F used for Write Access";
return desc.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const ByteArray& CartridgeWDWidget::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& CartridgeWDWidget::internalRamCurrent(int start, int count)
{
myRamCurrent.clear();
for(int i = 0; i < count; ++i)
myRamCurrent.push_back(myCart.myRAM[start + i]);
return myRamCurrent;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWDWidget::internalRamSetValue(int addr, uInt8 value)
{
myCart.myRAM[addr] = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeWDWidget::internalRamGetValue(int addr)
{
return myCart.myRAM[addr];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeWDWidget::internalRamLabel(int addr)
{
CartDebug& dbg = instance().debugger().cartDebug();
return dbg.getLabel(addr + 0xF000, false);
}

View File

@ -0,0 +1,66 @@
//============================================================================
//
// 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-2014 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 CARTRIDGEWD_WIDGET_HXX
#define CARTRIDGEWD_WIDGET_HXX
class CartridgeWD;
class PopUpWidget;
#include "CartDebugWidget.hxx"
class CartridgeWDWidget : public CartDebugWidget
{
public:
CartridgeWDWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont,
int x, int y, int w, int h,
CartridgeWD& cart);
virtual ~CartridgeWDWidget() { }
void saveOldState();
void loadConfig();
void handleCommand(CommandSender* sender, int cmd, int data, int id);
string bankState();
// start of functions for Cartridge RAM tab
uInt32 internalRamSize();
uInt32 internalRamRPort(int start);
string internalRamDescription();
const ByteArray& internalRamOld(int start, int count);
const ByteArray& internalRamCurrent(int start, int count);
void internalRamSetValue(int addr, uInt8 value);
uInt8 internalRamGetValue(int addr);
string internalRamLabel(int addr);
// end of functions for Cartridge RAM tab
private:
CartridgeWD& myCart;
PopUpWidget* myBank;
struct CartState {
ByteArray internalram;
};
CartState myOldState;
enum { kBankChanged = 'bkCH' };
};
#endif

View File

@ -57,6 +57,7 @@ MODULE_OBJS := \
src/debugger/gui/CartMDMWidget.o \ src/debugger/gui/CartMDMWidget.o \
src/debugger/gui/CartSBWidget.o \ src/debugger/gui/CartSBWidget.o \
src/debugger/gui/CartUAWidget.o \ src/debugger/gui/CartUAWidget.o \
src/debugger/gui/CartWDWidget.o \
src/debugger/gui/CartX07Widget.o \ src/debugger/gui/CartX07Widget.o \
src/debugger/gui/JoystickWidget.o \ src/debugger/gui/JoystickWidget.o \
src/debugger/gui/PaddleWidget.o \ src/debugger/gui/PaddleWidget.o \

View File

@ -19,16 +19,19 @@
#include <cstring> #include <cstring>
#include "TIA.hxx"
#include "M6502.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartWD.hxx" #include "CartWD.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWD::CartridgeWD(const uInt8* image, uInt32 size, CartridgeWD::CartridgeWD(const uInt8* image, uInt32 size,
const Settings& settings) const Settings& settings)
: Cartridge(settings) : Cartridge(settings),
mySize(BSPF_min(8195u, size))
{ {
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
memcpy(myImage, image, BSPF_min(8192u, size)); memcpy(myImage, image, mySize);
createCodeAccessBase(8192); createCodeAccessBase(8192);
// Remember startup bank // Remember startup bank
@ -50,6 +53,9 @@ void CartridgeWD::reset()
else else
memset(myRAM, 0, 64); memset(myRAM, 0, 64);
myCyclesAtBankswitchInit = 0;
myPendingBank = 0xF0; // one more than the allowable bank #
// Setup segments to some default slices // Setup segments to some default slices
bank(myStartBank); bank(myStartBank);
} }
@ -59,34 +65,29 @@ void CartridgeWD::install(System& system)
{ {
mySystem = &system; mySystem = &system;
System::PageAccess access(this, System::PA_READ); // Set the page accessing method for the RAM reading pages
System::PageAccess read(this, System::PA_READ);
for(uInt32 k = 0x1000; k < 0x1040; k += (1 << System::PAGE_SHIFT))
{
read.directPeekBase = &myRAM[k & 0x003F];
read.codeAccessBase = &myCodeAccessBase[k & 0x003F];
mySystem->setPageAccess(k >> System::PAGE_SHIFT, read);
}
// Set the page accessing method for the RAM writing pages // Set the page accessing method for the RAM writing pages
access.type = System::PA_WRITE; System::PageAccess write(this, System::PA_WRITE);
for(uInt32 j = 0x1040; j < 0x1080; j += (1 << System::PAGE_SHIFT)) for(uInt32 j = 0x1040; j < 0x1080; j += (1 << System::PAGE_SHIFT))
{ {
access.directPokeBase = &myRAM[j & 0x003F]; write.directPokeBase = &myRAM[j & 0x003F];
access.codeAccessBase = &myCodeAccessBase[0x80 + (j & 0x003F)]; write.codeAccessBase = &myCodeAccessBase[j & 0x003F];
mySystem->setPageAccess(j >> System::PAGE_SHIFT, access); mySystem->setPageAccess(j >> System::PAGE_SHIFT, write);
} }
// Set the page accessing method for the RAM reading pages // Set the page accessing methods for the hot spots
// The first 48 bytes map directly to RAM // These mirror the TIA addresses, so accesses must be chained
access.directPeekBase = access.directPokeBase = 0; System::PageAccess hotspot(this, System::PA_READWRITE);
access.type = System::PA_READ; for(uInt32 i = 0x30; i < 0x40; i += (1 << System::PAGE_SHIFT))
for(uInt32 k = 0x1000; k < 0x1030; k += (1 << System::PAGE_SHIFT)) mySystem->setPageAccess(i >> System::PAGE_SHIFT, hotspot);
{
access.directPeekBase = &myRAM[k & 0x003F];
access.codeAccessBase = &myCodeAccessBase[k & 0x003F];
mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
}
access.directPeekBase = access.directPokeBase = 0;
// The last 16 bytes are hotspots, so they're handled separately
for(uInt32 k = 0x1030; k < 0x1040; k += (1 << System::PAGE_SHIFT))
{
access.codeAccessBase = &myCodeAccessBase[k & 0x003F];
mySystem->setPageAccess(k >> System::PAGE_SHIFT, access);
}
// Setup segments to some default slices // Setup segments to some default slices
bank(myStartBank); bank(myStartBank);
@ -94,18 +95,38 @@ void CartridgeWD::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeWD::peek(uInt16 address) uInt8 CartridgeWD::peek(uInt16 address)
{
// Is it time to do an actual bankswitch?
if(myPendingBank != 0xF0 && !bankLocked() &&
mySystem->cycles() > (myCyclesAtBankswitchInit + 3))
{
bank(myPendingBank);
myPendingBank = 0xF0;
}
if(!(address & 0x1000)) // Hotspots below 0x1000 are also TIA addresses
{
// Hotspots at $30 - $3F
// Note that a hotspot read triggers a bankswitch after at least 3 cycles
// have passed, so we only initiate the switch here
if(!bankLocked())
{
myCyclesAtBankswitchInit = mySystem->cycles();
myPendingBank = address & 0x000F;
if(!mySystem->autodetectMode())
cerr << "BS init: " << dec << myPendingBank << " @ " << dec << mySystem->cycles() << endl;
}
return mySystem->tia().peek(address);
}
else
{ {
uInt16 peekAddress = address; uInt16 peekAddress = address;
address &= 0x0FFF; address &= 0x0FFF;
if(address < 0x0040) // RAM read port if(address < 0x0040) // RAM read port
{ return myRAM[address];
// Hotspots at $30 - $3F
bank(address & 0x000F);
// Read from RAM
return myRAM[address & 0x003F];
}
else if(address < 0x0080) // RAM write port else if(address < 0x0080) // RAM write port
{ {
// Reading from the write port @ $1040 - $107F triggers an unwanted write // Reading from the write port @ $1040 - $107F triggers an unwanted write
@ -119,19 +140,26 @@ uInt8 CartridgeWD::peek(uInt16 address)
return myRAM[address & 0x003F] = value; return myRAM[address & 0x003F] = value;
} }
} }
else if(address < 0x0400)
return myImage[myOffset[0] + (address & 0x03FF)];
else if(address < 0x0800)
return myImage[myOffset[1] + (address & 0x03FF)];
else if(address < 0x0C00)
return myImage[myOffset[2] + (address & 0x03FF)];
else
return mySegment3[address & 0x03FF];
}
// NOTE: This does not handle reading from ROM, however, this return 0; // We'll never reach this
// function should never be called for ROM because of the
// way page accessing has been setup
return 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeWD::poke(uInt16 address, uInt8) bool CartridgeWD::poke(uInt16 address, uInt8 value)
{ {
// NOTE: This does not handle writing to RAM, however, this // Only TIA writes will reach here
// function should never be called for RAM because of the if(!(address & 0x1000))
// way page accessing has been setup return mySystem->tia().poke(address, value);
else
return false; return false;
} }
@ -147,13 +175,15 @@ bool CartridgeWD::bank(uInt16 bank)
segmentTwo(ourBankOrg[bank].two); segmentTwo(ourBankOrg[bank].two);
segmentThree(ourBankOrg[bank].three, ourBankOrg[bank].map3bytes); segmentThree(ourBankOrg[bank].three, ourBankOrg[bank].map3bytes);
if(!mySystem->autodetectMode())
cerr << "BS done: " << dec << myCurrentBank << " @ " << dec << mySystem->cycles() << endl;
return myBankChanged = true; return myBankChanged = true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWD::segmentZero(uInt8 slice) void CartridgeWD::segmentZero(uInt8 slice)
{ {
cerr << "segmentZero : slice " << (int)slice << endl;
uInt16 offset = slice << 10; uInt16 offset = slice << 10;
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
@ -161,54 +191,51 @@ cerr << "segmentZero : slice " << (int)slice << endl;
for(uInt32 address = 0x1080; address < 0x1400; for(uInt32 address = 0x1080; address < 0x1400;
address += (1 << System::PAGE_SHIFT)) address += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
myOffset[0] = offset;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWD::segmentOne(uInt8 slice) void CartridgeWD::segmentOne(uInt8 slice)
{ {
cerr << "segmentOne : slice " << (int)slice << endl;
uInt16 offset = slice << 10; uInt16 offset = slice << 10;
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1400; address < 0x1800; for(uInt32 address = 0x1400; address < 0x1800;
address += (1 << System::PAGE_SHIFT)) address += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
myOffset[1] = offset;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWD::segmentTwo(uInt8 slice) void CartridgeWD::segmentTwo(uInt8 slice)
{ {
cerr << "segmentTwo : slice " << (int)slice << endl;
uInt16 offset = slice << 10; uInt16 offset = slice << 10;
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
for(uInt32 address = 0x1800; address < 0x1C00; for(uInt32 address = 0x1800; address < 0x1C00;
address += (1 << System::PAGE_SHIFT)) address += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &myImage[offset + (address & 0x03FF)];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
myOffset[2] = offset;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWD::segmentThree(uInt8 slice, bool map3bytes) void CartridgeWD::segmentThree(uInt8 slice, bool map3bytes)
{ {
cerr << "segmentThree: slice " << (int)slice << endl;
uInt16 offset = slice << 10; uInt16 offset = slice << 10;
// Make a copy of the address space pointed to by the slice // Make a copy of the address space pointed to by the slice
// Then map in the extra 3 bytes, if required // Then map in the extra 3 bytes, if required
memcpy(mySegment3, myImage+offset, 1024); memcpy(mySegment3, myImage+offset, 1024);
if(map3bytes) if(mySize == 8195 && map3bytes)
{ {
mySegment3[0x3FC] = myImage[0x2000+0]; mySegment3[0x3FC] = myImage[0x2000+0];
mySegment3[0x3FD] = myImage[0x2000+1]; mySegment3[0x3FD] = myImage[0x2000+1];
@ -220,10 +247,10 @@ cerr << "segmentThree: slice " << (int)slice << endl;
for(uInt32 address = 0x1C00; address < 0x2000; for(uInt32 address = 0x1C00; address < 0x2000;
address += (1 << System::PAGE_SHIFT)) address += (1 << System::PAGE_SHIFT))
{ {
access.directPeekBase = &mySegment3[address & 0x03FF];
access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)]; access.codeAccessBase = &myCodeAccessBase[offset + (address & 0x03FF)];
mySystem->setPageAccess(address >> System::PAGE_SHIFT, access); mySystem->setPageAccess(address >> System::PAGE_SHIFT, access);
} }
myOffset[3] = offset;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -235,7 +262,7 @@ uInt16 CartridgeWD::getBank() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeWD::bankCount() const uInt16 CartridgeWD::bankCount() const
{ {
return 8; return 16;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -247,7 +274,7 @@ bool CartridgeWD::patch(uInt16 address, uInt8 value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeWD::getImage(int& size) const const uInt8* CartridgeWD::getImage(int& size) const
{ {
size = 8195; size = mySize;
return myImage; return myImage;
} }
@ -259,6 +286,8 @@ bool CartridgeWD::save(Serializer& out) const
out.putString(name()); out.putString(name());
out.putShort(myCurrentBank); out.putShort(myCurrentBank);
out.putByteArray(myRAM, 64); out.putByteArray(myRAM, 64);
out.putInt(myCyclesAtBankswitchInit);
out.putShort(myPendingBank);
} }
catch(...) catch(...)
{ {
@ -279,6 +308,8 @@ bool CartridgeWD::load(Serializer& in)
myCurrentBank = in.getShort(); myCurrentBank = in.getShort();
in.getByteArray(myRAM, 64); in.getByteArray(myRAM, 64);
myCyclesAtBankswitchInit = in.getInt();
myPendingBank = in.getShort();
bank(myCurrentBank); bank(myCurrentBank);
} }
@ -293,20 +324,20 @@ bool CartridgeWD::load(Serializer& in)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWD::BankOrg CartridgeWD::ourBankOrg[16] = { CartridgeWD::BankOrg CartridgeWD::ourBankOrg[16] = {
{ 0, 0, 1, 2, false }, { 0, 0, 1, 2, false }, // Bank 0
{ 0, 1, 3, 2, false }, { 0, 1, 3, 2, false }, // Bank 1
{ 4, 5, 6, 7, false }, { 4, 5, 6, 7, false }, // Bank 2
{ 7, 4, 3, 2, false }, { 7, 4, 3, 2, false }, // Bank 3
{ 0, 0, 6, 7, false }, { 0, 0, 6, 7, false }, // Bank 4
{ 0, 1, 7, 6, false }, { 0, 1, 7, 6, false }, // Bank 5
{ 3, 2, 4, 5, false }, { 3, 2, 4, 5, false }, // Bank 6
{ 6, 0, 5, 1, false }, { 6, 0, 5, 1, false }, // Bank 7
{ 0, 0, 1, 2, false }, { 0, 0, 1, 2, false }, // Bank 8
{ 0, 1, 3, 2, false }, { 0, 1, 3, 2, false }, // Bank 9
{ 4, 5, 6, 7, false }, { 4, 5, 6, 7, false }, // Bank 10
{ 7, 4, 3, 2, false }, { 7, 4, 3, 2, false }, // Bank 11
{ 0, 0, 6, 7, true }, { 0, 0, 6, 7, true }, // Bank 12
{ 0, 1, 7, 6, true }, { 0, 1, 7, 6, true }, // Bank 13
{ 3, 2, 4, 5, true }, { 3, 2, 4, 5, true }, // Bank 14
{ 6, 0, 5, 1, true } { 6, 0, 5, 1, true } // Bank 15
}; };

View File

@ -25,7 +25,7 @@ class System;
#include "bspf.hxx" #include "bspf.hxx"
#include "Cart.hxx" #include "Cart.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
// #include "CartWDWidget.hxx" #include "CartWDWidget.hxx"
#endif #endif
/** /**
@ -34,7 +34,7 @@ class System;
to be mapped as described below. There is also 64 bytes of RAM. to be mapped as described below. There is also 64 bytes of RAM.
In this bankswitching scheme the 2600's 4K cartridge address space In this bankswitching scheme the 2600's 4K cartridge address space
is broken into four 1K segments. The desired arrangement of 1K slices is broken into four 1K segments. The desired arrangement of 1K slices
is selected by accessing $30 - $FF of the first segment. The slices is selected by accessing $30 - $3F of TIA address space. The slices
are mapped into all 4 segments at once as follows: are mapped into all 4 segments at once as follows:
$0030: 0,0,1,2 $0030: 0,0,1,2
@ -47,7 +47,7 @@ class System;
$0037: 6,0,5,1 $0037: 6,0,5,1
$0038: 0,0,1,2 $0038: 0,0,1,2
$0039: 0,1,3,2 $0039: 0,1,3,2
$003A: 4,5,6,8 $003A: 4,5,6,7
$003B: 7,4,3,2 $003B: 7,4,3,2
$003C: 0,0,6,7* $003C: 0,0,6,7*
$003D: 0,1,7,6* $003D: 0,1,7,6*
@ -58,9 +58,8 @@ class System;
mapped into $3FC - $3FE of the uppermost (third) segment. mapped into $3FC - $3FE of the uppermost (third) segment.
The 64 bytes of RAM are accessible at $1000 - $103F (read port) and The 64 bytes of RAM are accessible at $1000 - $103F (read port) and
$1040 - $107F (write port). Note that all the hotspots are in the $1040 - $107F (write port). Because the RAM takes 128 bytes of address
read port of RAM. Because the RAM takes 128 bytes of address space, space, the range $1000 - $107F of segment 0 ROM will never be available.
the range $1000 - $107F of segment 0 ROM will never be available.
@author Stephen Anthony @author Stephen Anthony
*/ */
@ -162,7 +161,7 @@ class CartridgeWD : public Cartridge
CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont, CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, int x, int y, int w, int h) const GUI::Font& nfont, int x, int y, int w, int h)
{ {
return nullptr;//new CartridgeWDWidget(boss, lfont, nfont, x, y, w, h, *this); return new CartridgeWDWidget(boss, lfont, nfont, x, y, w, h, *this);
} }
#endif #endif
@ -218,6 +217,9 @@ class CartridgeWD : public Cartridge
// Indicates which bank is currently active // Indicates which bank is currently active
uInt16 myCurrentBank; uInt16 myCurrentBank;
// Indicates the actual size of the ROM image (either 8K or 8K + 3)
uInt32 mySize;
// The 8K ROM image of the cartridge // The 8K ROM image of the cartridge
uInt8 myImage[8195]; uInt8 myImage[8195];
@ -227,6 +229,15 @@ class CartridgeWD : public Cartridge
// The 1K ROM mirror of segment 3 (sometimes contains extra 3 bytes) // The 1K ROM mirror of segment 3 (sometimes contains extra 3 bytes)
uInt8 mySegment3[1024]; uInt8 mySegment3[1024];
// Indicates the offset for each of the four segments
uInt16 myOffset[4];
// Indicates the cycle at which a bankswitch was initiated
uInt32 myCyclesAtBankswitchInit;
// Indicates the bank we wish to switch to in the future
uInt16 myPendingBank;
// The arrangement of banks to use on each hotspot read // The arrangement of banks to use on each hotspot read
struct BankOrg { struct BankOrg {
uInt8 zero, one, two, three; uInt8 zero, one, two, three;