mirror of https://github.com/stella-emu/stella.git
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:
parent
c7fc207b13
commit
31ca88d283
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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 \
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -95,44 +96,71 @@ void CartridgeWD::install(System& system)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt8 CartridgeWD::peek(uInt16 address)
|
uInt8 CartridgeWD::peek(uInt16 address)
|
||||||
{
|
{
|
||||||
uInt16 peekAddress = address;
|
// Is it time to do an actual bankswitch?
|
||||||
address &= 0x0FFF;
|
if(myPendingBank != 0xF0 && !bankLocked() &&
|
||||||
|
mySystem->cycles() > (myCyclesAtBankswitchInit + 3))
|
||||||
|
{
|
||||||
|
bank(myPendingBank);
|
||||||
|
myPendingBank = 0xF0;
|
||||||
|
}
|
||||||
|
|
||||||
if(address < 0x0040) // RAM read port
|
if(!(address & 0x1000)) // Hotspots below 0x1000 are also TIA addresses
|
||||||
{
|
{
|
||||||
// Hotspots at $30 - $3F
|
// Hotspots at $30 - $3F
|
||||||
bank(address & 0x000F);
|
// Note that a hotspot read triggers a bankswitch after at least 3 cycles
|
||||||
|
// have passed, so we only initiate the switch here
|
||||||
// Read from RAM
|
if(!bankLocked())
|
||||||
return myRAM[address & 0x003F];
|
|
||||||
}
|
|
||||||
else if(address < 0x0080) // RAM write port
|
|
||||||
{
|
|
||||||
// Reading from the write port @ $1040 - $107F triggers an unwanted write
|
|
||||||
uInt8 value = mySystem->getDataBusState(0xFF);
|
|
||||||
|
|
||||||
if(bankLocked())
|
|
||||||
return value;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
triggerReadFromWritePort(peekAddress);
|
myCyclesAtBankswitchInit = mySystem->cycles();
|
||||||
return myRAM[address & 0x003F] = value;
|
myPendingBank = address & 0x000F;
|
||||||
|
|
||||||
|
if(!mySystem->autodetectMode())
|
||||||
|
cerr << "BS init: " << dec << myPendingBank << " @ " << dec << mySystem->cycles() << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return mySystem->tia().peek(address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uInt16 peekAddress = address;
|
||||||
|
address &= 0x0FFF;
|
||||||
|
|
||||||
|
if(address < 0x0040) // RAM read port
|
||||||
|
return myRAM[address];
|
||||||
|
else if(address < 0x0080) // RAM write port
|
||||||
|
{
|
||||||
|
// Reading from the write port @ $1040 - $107F triggers an unwanted write
|
||||||
|
uInt8 value = mySystem->getDataBusState(0xFF);
|
||||||
|
|
||||||
|
if(bankLocked())
|
||||||
|
return value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
triggerReadFromWritePort(peekAddress);
|
||||||
|
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);
|
||||||
return false;
|
else
|
||||||
|
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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue