updated WD bankswitching (incl. detection)

This commit is contained in:
thrust26 2019-10-16 22:05:33 +02:00
parent eb2fdd71ba
commit 0dbd505b9b
10 changed files with 105 additions and 82 deletions

View File

@ -104,6 +104,10 @@
* Disabled some developer options for 'Player settings'.
* Writes to RAM read ports are ignored now.
* Added Developer setting, which breaks on writes to read ports.
* Improved breakpoints to now consider the banks.
* Improved debugger's TIA display and zoom windows.
@ -131,6 +135,8 @@
* Enhanced UA bankswitching to support certain Brazilian carts.
* Fixed WD bankswitching
* Auto-detection of bankswitch scheme by file extension now includes
more human-readable formats (not restricted to DOS 3-char length).
See the documentation for the new names.

View File

@ -32,8 +32,7 @@ CartridgeWDWidget::CartridgeWDWidget(
"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"
"In the third (uppermost) segment the byte at $3FC is overwritten with 0.\n\n"
"64 bytes RAM @ $F000 - $F080\n"
" $F000 - $F03F (R), $F040 - $F07F (W)\n";
@ -41,24 +40,24 @@ CartridgeWDWidget::CartridgeWDWidget(
ypos = addBaseInformation(myCart.mySize, "Wickstead Design", info, 12) + 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, "0 ($30) [0,0,1,3]", 0);
VarList::push_back(items, "1 ($31) [0,1,2,3]", 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, "3 ($33) [7,4,2,3]", 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, "6 ($36) [2,3,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, "8 ($38) [0,0,1,3]", 8);
VarList::push_back(items, "9 ($39) [0,1,2,3]", 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);
VarList::push_back(items, "11 ($3B) [7,4,2,3]", 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) [2,3,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*]"),
_font.getStringWidth("15 ($3F) [6,0,5,1]"),
myLineHeight, items, "Set bank ",
_font.getStringWidth("Set bank "), kBankChanged);
myBank->setTarget(this);
@ -103,13 +102,11 @@ string CartridgeWDWidget::bankState()
ostringstream& buf = buffer();
static const char* const 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*]"
"[0,0,1,3]", "[0,1,2,3]", "[4,5,6,7]", "[7,4,2,3]",
"[0,0,6,7]", "[0,1,7,6]", "[2,3,4,5]", "[6,0,5,1]"
};
uInt16 bank = myCart.getBank();
buf << "Bank = " << std::dec << bank << ", segments = " << segments[bank];
buf << "Bank = " << std::dec << bank << ", segments = " << segments[bank & 0x7];
return buf.str();
}

View File

@ -136,7 +136,8 @@ Bankswitch::Description Bankswitch::BSList[int(Bankswitch::Type::NumSchemes)] =
{ "SB" , "SB (128-256K SUPERbank)" },
{ "UA" , "UA (8K UA Ltd.)" },
{ "UASW" , "UASW (8K UA swapped banks)" },
{ "WD" , "WD (Experimental)" },
{ "WD" , "WD (Pink Panther)" },
{ "WDSW" , "WDSW (Pink Panther, bad)" },
{ "X07" , "X07 (64K AtariAge)" },
#if defined(CUSTOM_ARM)
{ "CUSTOM" , "CUSTOM (ARM)" }
@ -222,6 +223,7 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = {
{ "UA" , Bankswitch::Type::_UA },
{ "UASW" , Bankswitch::Type::_UASW },
{ "WD" , Bankswitch::Type::_WD },
{ "WDSW" , Bankswitch::Type::_WDSW },
{ "X07" , Bankswitch::Type::_X07 }
};
@ -277,5 +279,6 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = {
{ "UA" , Bankswitch::Type::_UA },
{ "UASW" , Bankswitch::Type::_UASW },
{ "WD" , Bankswitch::Type::_WD },
{ "WDSW" , Bankswitch::Type::_WDSW },
{ "X07" , Bankswitch::Type::_X07 }
};

View File

@ -45,7 +45,7 @@ class Bankswitch
_DPC, _DPCP, _E0, _E7, _E78K, _EF, _EFSC,
_F0, _F4, _F4SC, _F6, _F6SC, _F8, _F8SC,
_FA, _FA2, _FE, _MDM, _SB, _UA, _UASW,
_WD, _X07,
_WD, _WDSW, _X07,
#ifdef CUSTOM_ARM
_CUSTOM,
#endif

View File

@ -327,6 +327,7 @@ CartDetector::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::
case Bankswitch::Type::_SB:
return make_unique<CartridgeSB>(image, size, md5, settings);
case Bankswitch::Type::_WD:
case Bankswitch::Type::_WDSW:
return make_unique<CartridgeWD>(image, size, md5, settings);
case Bankswitch::Type::_X07:
return make_unique<CartridgeX07>(image, size, md5, settings);
@ -395,12 +396,14 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
type = Bankswitch::Type::_0840;
else if(isProbablyE78K(image, size))
type = Bankswitch::Type::_E78K;
else if (isProbablyWD(image,size))
type = Bankswitch::Type::_WD;
else
type = Bankswitch::Type::_F8;
}
else if(size == 8_KB + 3) // 8195 bytes (Experimental)
{
type = Bankswitch::Type::_WD;
type = Bankswitch::Type::_WDSW;
}
else if(size >= 10_KB && size <= 10_KB + 256) // ~10K - Pitfall2
{
@ -985,6 +988,17 @@ bool CartDetector::isProbablyUA(const ByteBuffer& image, size_t size)
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyWD(const ByteBuffer& image, size_t size)
{
// WD cart bankswitching switches banks by accessing address 0x30..0x3f
uInt8 signature[1][3] = {
{ 0xA5, 0x39, 0x4C } // LDA $39, JMP
};
return searchForBytes(image.get(), size, signature[0], 3, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDetector::isProbablyX07(const ByteBuffer& image, size_t size)
{

View File

@ -245,11 +245,17 @@ class CartDetector
*/
static bool isProbablyUA(const ByteBuffer& image, size_t size);
/**
Returns true if the image is probably a Wickstead Design bankswitching cartridge
*/
static bool isProbablyWD(const ByteBuffer& image, size_t size);
/**
Returns true if the image is probably an X07 bankswitching cartridge
*/
static bool isProbablyX07(const ByteBuffer& image, size_t size);
private:
// Following constructors and assignment operators not supported
CartDetector() = delete;

View File

@ -30,6 +30,15 @@ CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size,
myCurrentBank(0)
{
// Copy the ROM image into my buffer
if (mySize == 8_KB + 3)
{
// swap slices 2 & 3
std::copy_n(image.get(), 1_KB * 2, myImage.begin());
std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.begin() + 1_KB * 2);
std::copy_n(image.get() + 1_KB * 2, 1_KB * 1, myImage.begin() + 1_KB * 3);
std::copy_n(image.get() + 1_KB * 4, 1_KB * 4, myImage.begin() + 1_KB * 4);
}
else
std::copy_n(image.get(), mySize, myImage.begin());
createCodeAccessBase(8_KB);
}
@ -154,10 +163,10 @@ bool CartridgeWD::bank(uInt16 bank)
myCurrentBank = bank;
segmentZero(ourBankOrg[bank].zero);
segmentOne(ourBankOrg[bank].one);
segmentTwo(ourBankOrg[bank].two);
segmentThree(ourBankOrg[bank].three, ourBankOrg[bank].map3bytes);
segmentZero(ourBankOrg[bank & 0x7].zero);
segmentOne(ourBankOrg[bank & 0x7].one);
segmentTwo(ourBankOrg[bank & 0x7].two);
segmentThree(ourBankOrg[bank & 0x7].three);
return myBankChanged = true;
}
@ -206,19 +215,14 @@ void CartridgeWD::segmentTwo(uInt8 slice)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeWD::segmentThree(uInt8 slice, bool map3bytes)
void CartridgeWD::segmentThree(uInt8 slice)
{
uInt16 offset = slice << 10;
// Make a copy of the address space pointed to by the slice
// Then map in the extra 3 bytes, if required
// Then overwrite one byte with 0
std::copy_n(myImage.begin()+offset, mySegment3.size(), mySegment3.begin());
if(mySize == 8_KB + 3 && map3bytes)
{
mySegment3[0x3FC] = myImage[0x2000+0];
mySegment3[0x3FD] = myImage[0x2000+1];
mySegment3[0x3FE] = myImage[0x2000+2];
}
mySegment3[0x3FC] = 0;
System::PageAccess access(this, System::PageAccessType::READ);
@ -305,21 +309,15 @@ bool CartridgeWD::load(Serializer& in)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeWD::BankOrg CartridgeWD::ourBankOrg[16] = {
{ 0, 0, 1, 2, false }, // Bank 0
{ 0, 1, 3, 2, false }, // Bank 1
{ 4, 5, 6, 7, false }, // Bank 2
{ 7, 4, 3, 2, false }, // Bank 3
{ 0, 0, 6, 7, false }, // Bank 4
{ 0, 1, 7, 6, false }, // Bank 5
{ 3, 2, 4, 5, false }, // Bank 6
{ 6, 0, 5, 1, false }, // Bank 7
{ 0, 0, 1, 2, false }, // Bank 8
{ 0, 1, 3, 2, false }, // Bank 9
{ 4, 5, 6, 7, false }, // Bank 10
{ 7, 4, 3, 2, false }, // Bank 11
{ 0, 0, 6, 7, true }, // Bank 12
{ 0, 1, 7, 6, true }, // Bank 13
{ 3, 2, 4, 5, true }, // Bank 14
{ 6, 0, 5, 1, true } // Bank 15
CartridgeWD::BankOrg CartridgeWD::ourBankOrg[8] = {
// 0 1 2 3 4 5 6 7
{ 0, 0, 1, 3 }, // Bank 0, 8 2 1 - 1 - - - -
{ 0, 1, 2, 3 }, // Bank 1, 9 1 1 1 1 - - - -
{ 4, 5, 6, 7 }, // Bank 2, 10 - - - - 1 1 1 1
{ 7, 4, 2, 3 }, // Bank 3, 11 - - 1 1 1 - - 1
{ 0, 0, 6, 7 }, // Bank 4, 12 2 - - - - - 1 1
{ 0, 1, 7, 6 }, // Bank 5, 13 1 1 - - - - 1 1
{ 2, 3, 4, 5 }, // Bank 6, 14 - - 1 1 1 1 - -
{ 6, 0, 5, 1 } // Bank 7, 15 1 1 - - - 1 1 -
// count 7 4 3 4 3 3 4 4
};

View File

@ -28,32 +28,24 @@ class System;
/**
This is the cartridge class for a "Wickstead Design" prototype cart.
The ROM is normally 8K, but sometimes has an extra 3 bytes appended,
to be mapped as described below. There is also 64 bytes of RAM.
The ROM has 64 bytes of RAM.
In this bankswitching scheme the 2600's 4K cartridge address space
is broken into four 1K segments. The desired arrangement of 1K slices
is selected by accessing $30 - $3F of TIA address space. The slices
are mapped into all 4 segments at once as follows:
$0030: 0,0,1,2
$0031: 0,1,3,2
$0032: 4,5,6,7
$0033: 7,4,3,2
$0034: 0,0,6,7
$0035: 0,1,7,6
$0036: 3,2,4,5
$0037: 6,0,5,1
$0038: 0,0,1,2
$0039: 0,1,3,2
$003A: 4,5,6,7
$003B: 7,4,3,2
$003C: 0,0,6,7*
$003D: 0,1,7,6*
$003E: 3,2,4,5*
$003F: 6,0,5,1*
$0030, $0038: 0,0,1,3
$0031, $0039: 0,1,2,3
$0032, $003A: 4,5,6,7
$0033, $003B: 7,4,2,3
In the last 4 cases, the extra 3 bytes of ROM past the 8K boundary are
mapped into $3FC - $3FE of the uppermost (third) segment.
$0034, $003C: 0,0,6,7
$0035, $003D: 0,1,7,6
$0036, $003E: 2,3,4,5
$0037, $003F: 6,0,5,1
In the uppermost (third) segment, the byte at $3FC is overwritten by 0.
The 64 bytes of RAM are accessible at $1000 - $103F (read port) and
$1040 - $107F (write port). Because the RAM takes 128 bytes of address
@ -204,16 +196,15 @@ class CartridgeWD : public Cartridge
/**
Install the specified slice for segment three.
Note that this method also takes care of mapping extra 3 bytes.
Note that this method also takes care of setting one byte to 0.
@param slice The slice to map into the segment
@param map3bytes Whether to map in an extra 3 bytes
*/
void segmentThree(uInt8 slice, bool map3bytes);
void segmentThree(uInt8 slice);
private:
// The 8K ROM image of the cartridge
std::array<uInt8, 8_KB + 3> myImage;
std::array<uInt8, 8_KB> myImage;
// Indicates the actual size of the ROM image (either 8K or 8K + 3)
size_t mySize;
@ -239,9 +230,8 @@ class CartridgeWD : public Cartridge
// The arrangement of banks to use on each hotspot read
struct BankOrg {
uInt8 zero, one, two, three;
bool map3bytes;
};
static BankOrg ourBankOrg[16];
static BankOrg ourBankOrg[8];
private:
// Following constructors and assignment operators not supported

View File

@ -25,7 +25,7 @@
regenerated and the application recompiled.
*/
#define DEF_PROPS_SIZE 3406
#define DEF_PROPS_SIZE 3407
static const char* const DefProps[DEF_PROPS_SIZE][21] = {
{ "000509d1ed2b8d30a9d94be1b3b5febb", "Greg Zumwalt", "", "Jungle Jane (2003) (Greg Zumwalt) (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@ -1179,7 +1179,7 @@ static const char* const DefProps[DEF_PROPS_SIZE][21] = {
{ "55ace3c775f42eb46f08bb1dca9114e7", "", "", "Shadow Keep (04-03-2003) (Andrew Towers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "55ef6ab2321ca0c3d369e63d59c059c8", "", "", "Pitfall! (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "55ef7b65066428367844342ed59f956c", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "56210a3b9ea6d5dd8f417a357ed8ca92", "Probe 2000, Roger Booth, Todd Marshall, Robbin Daniels, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype)", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "56210a3b9ea6d5dd8f417a357ed8ca92", "Probe 2000, Roger Booth, Todd Marshall, Robbin Daniels, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype, bad dump)", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "56300ed31fef018bd96768ccc982f7b4", "HES - Activision", "559", "Rad Action Pak - Kung-Fu Master, Freeway, Frostbite (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "5641c0ff707630d2dd829b26a9f2e98f", "Joystik", "", "Motocross (Joystik)", "AKA Motocross Racer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "5643ee916f7dc760148fca4db3aa7d10", "", "", "Moon Patrol (Genesis)", "Genesis controller (C is jump)", "Hack of Moon Patrol", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
@ -1343,6 +1343,7 @@ static const char* const DefProps[DEF_PROPS_SIZE][21] = {
{ "62921652f6634eb1a0940ed5489c7e18", "", "", "SCSIcide (V1.09) (2001) (Joe Grand)", "", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "" },
{ "62992392ea651a16aa724a92e4596ed6", "Eric Mooney", "", "Invaders by Erik Mooney (Beta) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "62d1f50219edf9a429a9f004c19f31b3", "JWDA, Todd Marshall", "", "Euro Gen (02-01-83) (JWDA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "62ee2b8f59e9cd6285bbdb674a952e8b", "Probe 2000, Roger Booth, Todd Marshall, Robbin Daniels, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype)", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "62f74a2736841191135514422b20382d", "", "", "Pharaoh's Curse (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "20", "YES", "" },
{ "62ffd175cac3f781ef6e4870136a2520", "", "", "2600 Digital Clock (V x.xx) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "63166867f75869a3592b7a94ea62d147", "", "", "Indy 500 (Hack) [a1]", "Hack of Indy 500", "Hack", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "", "", "" },

View File

@ -20368,6 +20368,14 @@
"Cart.MD5" "56210a3b9ea6d5dd8f417a357ed8ca92"
"Cart.Manufacturer" "Probe 2000, Roger Booth, Todd Marshall, Robbin Daniels, Jim Wickstead"
"Cart.ModelNo" "3152VC"
"Cart.Name" "Pursuit of the Pink Panther (Probe) (Prototype, bad dump)"
"Cart.Note" "AKA Adventures of the Pink Panther"
"Cart.Rarity" "Prototype"
""
"Cart.MD5" "62ee2b8f59e9cd6285bbdb674a952e8b"
"Cart.Manufacturer" "Probe 2000, Roger Booth, Todd Marshall, Robbin Daniels, Jim Wickstead"
"Cart.ModelNo" "3152VC"
"Cart.Name" "Pursuit of the Pink Panther (Probe) (Prototype)"
"Cart.Note" "AKA Adventures of the Pink Panther"
"Cart.Rarity" "Prototype"