Improvements to E0 autodetection; now Swordquest Waterworld isn't

misdetected any more.

Optimizations in autodetect logic, thanks to suggestions from
Thomas Jentzsch.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1322 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2007-06-14 13:47:50 +00:00
parent c4fa58b38f
commit 317648f37d
4 changed files with 54 additions and 47 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Cart.cxx,v 1.33 2007-06-09 23:20:16 stephena Exp $
// $Id: Cart.cxx,v 1.34 2007-06-14 13:47:50 stephena Exp $
//============================================================================
#include <cassert>
@ -201,10 +201,10 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
type = "4K";
else if(isProbablyE0(image, size))
type = "E0";
else if(isProbably3F(image, size))
type = isProbably3E(image, size) ? "3E" : "3F";
else if(isProbably3E(image, size))
type = "3E";
else if(isProbably3F(image, size))
type = "3F";
else if(isProbablyUA(image, size))
type = "UA";
else if(isProbablyFE(image, size))
@ -230,10 +230,10 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
type = "F6SC";
else if(isProbablyE7(image, size))
type = "E7";
else if(isProbably3F(image, size))
type = isProbably3E(image, size) ? "3E" : "3F";
else if(isProbably3E(image, size))
type = "3E";
else if(isProbably3F(image, size))
type = "3F";
else
type = "F6";
}
@ -241,39 +241,39 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
{
if(isProbablySC(image, size))
type = "F4SC";
else if(isProbably3F(image, size))
type = isProbably3E(image, size) ? "3E" : "3F";
else if(isProbably3E(image, size))
type = "3E";
else if(isProbably3F(image, size))
type = "3F";
else
type = "F4";
}
else if(size == 65536) // 64K
{
// TODO - autodetect 4A50
if(isProbably3F(image, size))
type = isProbably3E(image, size) ? "3E" : "3F";
else if(isProbably3E(image, size))
if(isProbably3E(image, size))
type = "3E";
else if(isProbably3F(image, size))
type = "3F";
else
type = "MB";
}
else if(size == 131072) // 128K
{
// TODO - autodetect 4A50
if(isProbably3F(image, size))
type = isProbably3E(image, size) ? "3E" : "3F";
else if(isProbably3E(image, size))
if(isProbably3E(image, size))
type = "3E";
else if(isProbably3F(image, size))
type = "3F";
else
type = "MC";
}
else // what else can we do?
{
if(isProbably3F(image, size))
type = isProbably3E(image, size) ? "3E" : "3F";
else if(isProbably3E(image, size))
if(isProbably3E(image, size))
type = "3E";
else if(isProbably3F(image, size))
type = "3F";
else
type = "4K"; // Most common bankswitching type
}
@ -282,8 +282,9 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Cartridge::searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize)
bool Cartridge::searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize,
uInt32 minhits)
{
uInt32 count = 0;
for(uInt32 i = 0; i < imagesize - sigsize; ++i)
@ -297,10 +298,15 @@ int Cartridge::searchForBytes(const uInt8* image, uInt32 imagesize,
break;
}
if(matches == sigsize)
{
++count;
i += sigsize; // skip past this signature 'window' entirely
}
if(count >= minhits)
break;
}
return count;
return (count >= minhits);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -330,7 +336,7 @@ bool Cartridge::isProbably3F(const uInt8* image, uInt32 size)
// We expect it will be present at least 2 times, since there are
// at least two banks
uInt8 signature[] = { 0x85, 0x3F }; // STA $3F
return searchForBytes(image, size, signature, 2) > 1;
return searchForBytes(image, size, signature, 2, 2);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -340,30 +346,30 @@ bool Cartridge::isProbably3E(const uInt8* image, uInt32 size)
// in address 3E using 'STA $3E', commonly followed by an
// immediate mode LDA
uInt8 signature[] = { 0x85, 0x3E, 0xA9, 0x00 }; // STA $3E; LDA #$00
return searchForBytes(image, size, signature, 4) > 0;
return searchForBytes(image, size, signature, 4, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Cartridge::isProbablyE0(const uInt8* image, uInt32 size)
{
// E0 cart bankswitching is triggered by accessing addresses
// $FE0 to $FF7 using absolute non-indexed addressing
// So we search for the pattern 'LDA Fxxx' or 'STA Fxxx' in hex
// using the regex (AD|8D, E0-F7, xF)
// This must be present at least three times, since there are
// three segments to be initialized (and a few more so that more
// of the ROM is used)
// $FE0 to $FF9 using absolute non-indexed addressing
// To eliminate false positives (and speed up processing), we
// search for only certain known signatures
// Thanks to "stella@casperkitty.com" for this advice
uInt32 count = 0;
for(uInt32 i = 0; i < size - 2; ++i)
// These signatures are attributed to the MESS project
uInt8 signature[6][3] = {
{ 0x8D, 0xE0, 0x1F }, // STA $1FE0
{ 0x8D, 0xE0, 0x5F }, // STA $5FE0
{ 0x8D, 0xE9, 0xFF }, // STA $FFE9
{ 0xAD, 0xE9, 0xFF }, // LDA $FFE9
{ 0xAD, 0xED, 0xFF }, // LDA $FFED
{ 0xAD, 0xF3, 0xBF } // LDA $BFF3
};
for(uInt32 i = 0; i < 6; ++i)
{
uInt8 b1 = image[i], b2 = image[i+1], b3 = image[i+2];
if((b1 == 0xAD || b1 == 0x8D) &&
(b2 >= 0xE0 && b2 <= 0xF7) &&
(b3 & 0xF == 0xF))
{
if(++count > 4) return true;
}
if(searchForBytes(image, size, signature[i], 3, 1))
return true;
}
return false;
}
@ -409,7 +415,7 @@ bool Cartridge::isProbablyUA(const uInt8* image, uInt32 size)
// UA cart bankswitching switches to bank 1 by accessing address 0x240
// using 'STA $240'
uInt8 signature[] = { 0x8D, 0x40, 0x02 }; // STA $240
return searchForBytes(image, size, signature, 3) > 0;
return searchForBytes(image, size, signature, 3, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -421,10 +427,10 @@ bool Cartridge::isProbablyCV(const uInt8* image, uInt32 size)
{ 0x9D, 0xFF, 0xF3 }, // STA $F3FF
{ 0x99, 0x00, 0xF4 } // STA $F400
};
if(searchForBytes(image, size, signature[0], 3) > 0)
if(searchForBytes(image, size, signature[0], 3, 1))
return true;
else
return searchForBytes(image, size, signature[1], 3) > 0;
return searchForBytes(image, size, signature[1], 3, 1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -441,7 +447,7 @@ bool Cartridge::isProbablyFE(const uInt8* image, uInt32 size)
};
for(uInt32 i = 0; i < 4; ++i)
{
if(searchForBytes(image, size, signature[i], 5) > 0)
if(searchForBytes(image, size, signature[i], 5, 1))
return true;
}
return false;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Cart.hxx,v 1.18 2007-06-08 12:36:51 stephena Exp $
// $Id: Cart.hxx,v 1.19 2007-06-14 13:47:50 stephena Exp $
//============================================================================
#ifndef CARTRIDGE_HXX
@ -33,7 +33,7 @@ class Settings;
game and handles any bankswitching performed by the cartridge.
@author Bradford W. Mott
@version $Id: Cart.hxx,v 1.18 2007-06-08 12:36:51 stephena Exp $
@version $Id: Cart.hxx,v 1.19 2007-06-14 13:47:50 stephena Exp $
*/
class Cartridge : public Device
{
@ -140,11 +140,13 @@ class Cartridge : public Device
@param imagesize The size of the ROM image
@param signature The byte sequence to search for
@param sigsize The number of bytes in the signature
@param minhits The minimum number of times a signature is to be found
@return The number of times the signature was found
@return True if the signature was found at least 'minhits' time, else false
*/
static int searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize);
static bool searchForBytes(const uInt8* image, uInt32 imagesize,
const uInt8* signature, uInt32 sigsize,
uInt32 minhits);
/**
Returns true if the image is probably a SuperChip (256 bytes RAM)

View File

@ -1962,7 +1962,7 @@ static const char* DefProps[2722][21] = {
{ "bc3057a35319aae3a5cd87a203736abe", "CCE", "", "Time Warp (CCE) [!]", "", "", "", "", "", "", "", "", "", "", "", "", "30", "", "", "", "" },
{ "bc4cf38a4bee45752dc466c98ed7ad09", "Atari", "CX26136", "Solaris (1986) (Atari) (PAL) [!]", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "bc526185ad324241782dc68ba5d0540b", "", "", "Dodge Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "bc5389839857612cfabeb810ba7effdc", "Atari", "CX2671", "SwordQuest - Waterworld (1983) (Atari)", "", "Unbelievably Rare", "", "F8", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "bc5389839857612cfabeb810ba7effdc", "Atari", "CX2671", "SwordQuest - Waterworld (1983) (Atari)", "", "Unbelievably Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "bc6432cbed32c695658514c4eb41d905", "Manuel Polik", "", "Star Fire (MP) (2002) (PD)", "Won't work with Stella < V1.2", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "bc703ea6afb20bc089f04d8c9d79a2bd", "", "", "Gunfight 2600 - Not mergeable with Colbert wizardry... (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
{ "bc97d544f1d4834cc72bcc92a37b8c1b", "", "", "Sky Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

View File

@ -11487,7 +11487,6 @@
"Cartridge.ModelNo" "CX2671"
"Cartridge.Name" "SwordQuest - Waterworld (1983) (Atari)"
"Cartridge.Rarity" "Unbelievably Rare"
"Cartridge.Type" "F8"
""
"Cartridge.MD5" "bc97d544f1d4834cc72bcc92a37b8c1b"