Added new approach for values used when reading from the write port.

Previously these values were from whatever was on the databus, but new testing
indicates that they are semi-random (ie, random, but with some pattern).

The new code bases the values in part on the md5sum of the ROM (for randomization),
but also pre-generates a set number of values (for a pattern).

Currently only F8SC scheme is implemented.  The remainder will be done once
we test this one.
This commit is contained in:
Stephen Anthony 2018-12-08 18:05:05 -03:30
parent 5f91532d95
commit d941ebca09
5 changed files with 72 additions and 1 deletions

View File

@ -17,6 +17,7 @@
#include "Settings.hxx"
#include "System.hxx"
#include "MD5.hxx"
#ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx"
#include "CartDebug.hxx"
@ -32,6 +33,7 @@ Cartridge::Cartridge(const Settings& settings)
myStartBank(0),
myBankLocked(false)
{
std::fill(myRWPRandomValues, myRWPRandomValues + 256, 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -77,6 +79,20 @@ void Cartridge::triggerReadFromWritePort(uInt16 address)
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge::createReadFromWritePortValues(const uInt8* image, uInt32 size)
{
Random rand(MD5::hashToInt(image, size));
for(uInt32 i = 0; i < 256; ++i)
myRWPRandomValues[i] = rand.next();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Cartridge::randomReadFromWritePortValue(uInt16 address) const
{
return myRWPRandomValues[address & 0xFF];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Cartridge::createCodeAccessBase(uInt32 size)
{

View File

@ -195,6 +195,28 @@ class Cartridge : public Device
*/
void triggerReadFromWritePort(uInt16 address);
/**
Creates an array of semi-random values to use for returning when a
read from the write port happens. Currently, these values are based in
part on the md5sum of the ROM, so this method needs to be called to
calculate that information. If the method isn't called, then the values
used will be 0.
@param image The cart ROM data
@param size The size of ROM data
*/
void createReadFromWritePortValues(const uInt8* image, uInt32 size);
/**
Return a random value to use when a read from the write port happens.
This functionality is placed in a method, so we can change
implementations as required.
@param address The address of the illegal read
@return A random value somehow associated with the given address
*/
uInt8 randomReadFromWritePortValue(uInt16 address) const;
/**
Create an array that holds code-access information for every byte
of the ROM (indicated by 'size'). Note that this is only used by
@ -260,6 +282,9 @@ class Cartridge : public Device
// by the debugger, when disassembling/dumping ROM.
bool myBankLocked;
// Semi-random values to use when a read from write port occurs
uInt8 myRWPRandomValues[256];
// Contains various info about this cartridge
// This needs to be stored separately from child classes, since
// sometimes the information in both do not match

View File

@ -27,6 +27,7 @@ CartridgeF8SC::CartridgeF8SC(const BytePtr& image, uInt32 size,
// Copy the ROM image into my buffer
memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192);
createReadFromWritePortValues(myImage, 8192);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -95,7 +96,7 @@ uInt8 CartridgeF8SC::peek(uInt16 address)
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
{
// Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF);
uInt8 value = randomReadFromWritePortValue(address);
if(bankLocked())
return value;

View File

@ -351,4 +351,21 @@ string hash(const FilesystemNode& node)
return md5;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 hashToInt(const uInt8* buffer, uInt32 length)
{
MD5_CTX context;
uInt8 md5[16];
MD5Init(&context);
MD5Update(&context, buffer, length);
MD5Final(md5, &context);
auto toInt = [](uInt8* arr, uInt32 i) {
return uInt32((arr[i] << 24) + (arr[i+1] << 16) + (arr[i+2] << 8) + arr[i+3]);
};
return toInt(md5, 0) ^ toInt(md5, 4) ^ toInt(md5, 8) ^ toInt(md5, 12);
}
} // Namespace MD5

View File

@ -44,6 +44,18 @@ string hash(const uInt8* buffer, uInt32 length);
*/
string hash(const FilesystemNode& node);
/**
Get the MD5 Message-Digest of the specified message with the
given length. The digest consists of 32 hexadecimal digits,
but here we will get the 4 32-bit integers that make up the
digest and XOR them, resulting in one 32-bit value.
@param buffer The message to compute the digest of
@param length The length of the message
@return The 32-bit integer representing the digest
*/
uInt32 hashToInt(const uInt8* buffer, uInt32 length);
} // Namespace MD5
#endif