Commit d941ebca authored by Stephen Anthony's avatar Stephen Anthony
Browse files

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.
parent 5f91532d
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "Settings.hxx" #include "Settings.hxx"
#include "System.hxx" #include "System.hxx"
#include "MD5.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx" #include "Debugger.hxx"
#include "CartDebug.hxx" #include "CartDebug.hxx"
...@@ -32,6 +33,7 @@ Cartridge::Cartridge(const Settings& settings) ...@@ -32,6 +33,7 @@ Cartridge::Cartridge(const Settings& settings)
myStartBank(0), myStartBank(0),
myBankLocked(false) myBankLocked(false)
{ {
std::fill(myRWPRandomValues, myRWPRandomValues + 256, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
...@@ -77,6 +79,20 @@ void Cartridge::triggerReadFromWritePort(uInt16 address) ...@@ -77,6 +79,20 @@ void Cartridge::triggerReadFromWritePort(uInt16 address)
#endif #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) void Cartridge::createCodeAccessBase(uInt32 size)
{ {
......
...@@ -195,6 +195,28 @@ class Cartridge : public Device ...@@ -195,6 +195,28 @@ class Cartridge : public Device
*/ */
void triggerReadFromWritePort(uInt16 address); 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 Create an array that holds code-access information for every byte
of the ROM (indicated by 'size'). Note that this is only used by of the ROM (indicated by 'size'). Note that this is only used by
...@@ -260,6 +282,9 @@ class Cartridge : public Device ...@@ -260,6 +282,9 @@ class Cartridge : public Device
// by the debugger, when disassembling/dumping ROM. // by the debugger, when disassembling/dumping ROM.
bool myBankLocked; bool myBankLocked;
// Semi-random values to use when a read from write port occurs
uInt8 myRWPRandomValues[256];
// Contains various info about this cartridge // Contains various info about this cartridge
// This needs to be stored separately from child classes, since // This needs to be stored separately from child classes, since
// sometimes the information in both do not match // sometimes the information in both do not match
......
...@@ -27,6 +27,7 @@ CartridgeF8SC::CartridgeF8SC(const BytePtr& image, uInt32 size, ...@@ -27,6 +27,7 @@ CartridgeF8SC::CartridgeF8SC(const BytePtr& image, uInt32 size,
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
memcpy(myImage, image.get(), std::min(8192u, size)); memcpy(myImage, image.get(), std::min(8192u, size));
createCodeAccessBase(8192); createCodeAccessBase(8192);
createReadFromWritePortValues(myImage, 8192);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
...@@ -95,7 +96,7 @@ uInt8 CartridgeF8SC::peek(uInt16 address) ...@@ -95,7 +96,7 @@ uInt8 CartridgeF8SC::peek(uInt16 address)
if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes)
{ {
// Reading from the write port triggers an unwanted write // Reading from the write port triggers an unwanted write
uInt8 value = mySystem->getDataBusState(0xFF); uInt8 value = randomReadFromWritePortValue(address);
if(bankLocked()) if(bankLocked())
return value; return value;
......
...@@ -351,4 +351,21 @@ string hash(const FilesystemNode& node) ...@@ -351,4 +351,21 @@ string hash(const FilesystemNode& node)
return md5; 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 } // Namespace MD5
...@@ -44,6 +44,18 @@ string hash(const uInt8* buffer, uInt32 length); ...@@ -44,6 +44,18 @@ string hash(const uInt8* buffer, uInt32 length);
*/ */
string hash(const FilesystemNode& node); 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 } // Namespace MD5
#endif #endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment