win32: fix new ramsearch
This commit is contained in:
parent
585cb80257
commit
197322bcf1
|
@ -44,27 +44,22 @@
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: cleanups :/
|
bool IsHardwareAddressValid(HWAddressType address)
|
||||||
static inline uint8* HardwareToSoftwareAddress(HWAddressType address)
|
|
||||||
{
|
{
|
||||||
if (!GameInfo || address < 0x0000 || address > 0xffff)
|
if (!GameInfo)
|
||||||
return NULL;
|
return false;
|
||||||
|
|
||||||
// for some reasons, it looks not so easy to return direct pointer.
|
if (address >= 0x0000 && address <= 0xffff)
|
||||||
// so we copy a part of RAM to a temporary buffer and return it.
|
return true;
|
||||||
static uint8 tempBuf[0x10000];
|
else
|
||||||
for (int i = 0; i <= 4 && (address+i) <= 0xffff; i++) {
|
return false;
|
||||||
tempBuf[address+i] = GetMem(address+i);
|
|
||||||
}
|
|
||||||
return &tempBuf[address];
|
|
||||||
}
|
}
|
||||||
|
#define INVALID_HARDWARE_ADDRESS ((HWAddressType) -1)
|
||||||
|
|
||||||
struct MemoryRegion
|
struct MemoryRegion
|
||||||
{
|
{
|
||||||
HWAddressType hardwareAddress; // hardware address of the start of this region
|
HWAddressType hardwareAddress; // hardware address of the start of this region
|
||||||
unsigned int size; // number of bytes to the end of this region
|
unsigned int size; // number of bytes to the end of this region
|
||||||
unsigned char* softwareAddress; // pointer to the start of the live emulator source values for this region
|
|
||||||
|
|
||||||
unsigned int virtualIndex; // index into s_prevValues, s_curValues, and s_numChanges, valid after being initialized in ResetMemoryRegions()
|
unsigned int virtualIndex; // index into s_prevValues, s_curValues, and s_numChanges, valid after being initialized in ResetMemoryRegions()
|
||||||
unsigned int itemIndex; // index into listbox items, valid when s_itemIndicesInvalid is false
|
unsigned int itemIndex; // index into listbox items, valid when s_itemIndicesInvalid is false
|
||||||
|
@ -105,65 +100,32 @@ void ResetMemoryRegions()
|
||||||
|
|
||||||
s_activeMemoryRegions.clear();
|
s_activeMemoryRegions.clear();
|
||||||
|
|
||||||
// use HardwareToSoftwareAddress to figure out what all the possible memory regions are,
|
// use IsHardwareAddressValid to figure out what all the possible memory regions are,
|
||||||
// split up wherever there's a discontinuity in the address in our software RAM.
|
// split up wherever there's a discontinuity in the address in our software RAM.
|
||||||
static const int regionSearchGranularity = 0x100; // if this is too small, we'll waste time (in this function only), but if any region in RAM isn't evenly divisible by this, we might crash.
|
static const int regionSearchGranularity = 1; // if this is too small, we'll waste time (in this function only), but if any region in RAM isn't evenly divisible by this, we might crash.
|
||||||
HWAddressType hwRegionStart = 0;
|
HWAddressType hwRegionStart = INVALID_HARDWARE_ADDRESS;
|
||||||
uint8* regionStart = NULL;
|
HWAddressType hwRegionEnd = INVALID_HARDWARE_ADDRESS;
|
||||||
uint8* regionEnd = NULL;
|
for(HWAddressType addr = 0; addr != 0x10000+regionSearchGranularity; addr += regionSearchGranularity)
|
||||||
for(HWAddressType addr = 0; addr != 0x10000000+regionSearchGranularity; addr += regionSearchGranularity)
|
|
||||||
{
|
{
|
||||||
uint8* swAddr = HardwareToSoftwareAddress(addr);
|
if (!IsHardwareAddressValid(addr)) {
|
||||||
if(regionEnd && swAddr != regionEnd+regionSearchGranularity)
|
|
||||||
{
|
|
||||||
// hit end of region
|
|
||||||
// check to see if it mirrors an existing one (in which case we discard it)
|
|
||||||
bool discard = false;
|
|
||||||
for(MemoryList::iterator iter = s_activeMemoryRegions.begin(); iter != s_activeMemoryRegions.end(); ++iter)
|
|
||||||
{
|
|
||||||
MemoryRegion& region = *iter;
|
|
||||||
if(region.softwareAddress == regionStart)
|
|
||||||
{
|
|
||||||
unsigned int size = regionSearchGranularity + (regionEnd - regionStart);
|
|
||||||
if(size <= region.size)
|
|
||||||
{
|
|
||||||
discard = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hwRegionStart += region.size;
|
|
||||||
regionStart += region.size;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: don't include ROM in our RAM search (it's too huge)
|
|
||||||
|
|
||||||
// create the region
|
// create the region
|
||||||
if(!discard)
|
if (hwRegionStart != INVALID_HARDWARE_ADDRESS && hwRegionEnd != INVALID_HARDWARE_ADDRESS) {
|
||||||
{
|
MemoryRegion region = { hwRegionStart, regionSearchGranularity + (hwRegionEnd - hwRegionStart) };
|
||||||
MemoryRegion region = { hwRegionStart, regionSearchGranularity + (regionEnd - regionStart), regionStart };
|
|
||||||
s_activeMemoryRegions.push_back(region);
|
s_activeMemoryRegions.push_back(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
hwRegionStart = 0;
|
hwRegionStart = INVALID_HARDWARE_ADDRESS;
|
||||||
regionStart = NULL;
|
hwRegionEnd = INVALID_HARDWARE_ADDRESS;
|
||||||
regionEnd = NULL;
|
|
||||||
}
|
}
|
||||||
if(swAddr)
|
else {
|
||||||
{
|
if (hwRegionStart != INVALID_HARDWARE_ADDRESS) {
|
||||||
if(regionStart)
|
|
||||||
{
|
|
||||||
// continue region
|
// continue region
|
||||||
regionEnd = swAddr;
|
hwRegionEnd = addr;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
// start new region
|
// start new region
|
||||||
hwRegionStart = addr;
|
hwRegionStart = addr;
|
||||||
regionStart = swAddr;
|
hwRegionEnd = addr;
|
||||||
regionEnd = swAddr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,7 +136,6 @@ void ResetMemoryRegions()
|
||||||
{
|
{
|
||||||
MemoryRegion& region = *iter;
|
MemoryRegion& region = *iter;
|
||||||
region.virtualIndex = nextVirtualIndex;
|
region.virtualIndex = nextVirtualIndex;
|
||||||
assert(((intptr_t)region.softwareAddress & 1) == 0 && "somebody needs to reimplement ReadValueAtSoftwareAddress()");
|
|
||||||
nextVirtualIndex = region.virtualIndex + region.size;
|
nextVirtualIndex = region.virtualIndex + region.size;
|
||||||
}
|
}
|
||||||
//assert(nextVirtualIndex <= MAX_RAM_SIZE);
|
//assert(nextVirtualIndex <= MAX_RAM_SIZE);
|
||||||
|
@ -223,7 +184,6 @@ int DeactivateRegion(MemoryRegion& region, MemoryList::iterator& iter, HWAddress
|
||||||
int eraseSize = (hardwareAddress + size) - region.hardwareAddress;
|
int eraseSize = (hardwareAddress + size) - region.hardwareAddress;
|
||||||
region.hardwareAddress += eraseSize;
|
region.hardwareAddress += eraseSize;
|
||||||
region.size -= eraseSize;
|
region.size -= eraseSize;
|
||||||
region.softwareAddress += eraseSize;
|
|
||||||
region.virtualIndex += eraseSize;
|
region.virtualIndex += eraseSize;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +198,7 @@ int DeactivateRegion(MemoryRegion& region, MemoryList::iterator& iter, HWAddress
|
||||||
{
|
{
|
||||||
// split region
|
// split region
|
||||||
int eraseSize = (hardwareAddress + size) - region.hardwareAddress;
|
int eraseSize = (hardwareAddress + size) - region.hardwareAddress;
|
||||||
MemoryRegion region2 = {region.hardwareAddress + eraseSize, region.size - eraseSize, region.softwareAddress + eraseSize, region.virtualIndex + eraseSize};
|
MemoryRegion region2 = {region.hardwareAddress + eraseSize, region.size - eraseSize, region.virtualIndex + eraseSize};
|
||||||
region.size = hardwareAddress - region.hardwareAddress;
|
region.size = hardwareAddress - region.hardwareAddress;
|
||||||
iter = s_activeMemoryRegions.insert(++iter, region2);
|
iter = s_activeMemoryRegions.insert(++iter, region2);
|
||||||
s_itemIndicesInvalid = TRUE;
|
s_itemIndicesInvalid = TRUE;
|
||||||
|
@ -298,7 +258,7 @@ void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr
|
||||||
unsigned int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType);
|
unsigned int startSkipSize = ((unsigned int)(sizeof(stepType) - region.hardwareAddress)) % sizeof(stepType);
|
||||||
|
|
||||||
|
|
||||||
unsigned char* sourceAddr = region.softwareAddress - region.virtualIndex;
|
HWAddressType hwSourceAddr = region.hardwareAddress - region.virtualIndex;
|
||||||
|
|
||||||
unsigned int indexStart = region.virtualIndex + startSkipSize;
|
unsigned int indexStart = region.virtualIndex + startSkipSize;
|
||||||
unsigned int indexEnd = region.virtualIndex + region.size;
|
unsigned int indexEnd = region.virtualIndex + region.size;
|
||||||
|
@ -307,9 +267,9 @@ void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr
|
||||||
{
|
{
|
||||||
for(unsigned int i = indexStart; i < indexEnd; i++)
|
for(unsigned int i = indexStart; i < indexEnd; i++)
|
||||||
{
|
{
|
||||||
if(s_curValues[i] != sourceAddr[i]) // if value changed
|
if(s_curValues[i] != ReadValueAtHardwareAddress(hwSourceAddr+i, 1)) // if value changed
|
||||||
{
|
{
|
||||||
s_curValues[i] = sourceAddr[i]; // update value
|
s_curValues[i] = ReadValueAtHardwareAddress(hwSourceAddr+i, 1); // update value
|
||||||
//if(s_numChanges[i] != 0xFFFF)
|
//if(s_numChanges[i] != 0xFFFF)
|
||||||
s_numChanges[i]++; // increase change count
|
s_numChanges[i]++; // increase change count
|
||||||
}
|
}
|
||||||
|
@ -338,10 +298,10 @@ void UpdateRegionT(const MemoryRegion& region, const MemoryRegion* nextRegionPtr
|
||||||
|
|
||||||
for(unsigned int i = indexStart, j = 0; i < lastIndexToRead; i++, j++)
|
for(unsigned int i = indexStart, j = 0; i < lastIndexToRead; i++, j++)
|
||||||
{
|
{
|
||||||
if(s_curValues[i] != sourceAddr[i]) // if value of this byte changed
|
if(s_curValues[i] != ReadValueAtHardwareAddress(hwSourceAddr+i, 1)) // if value of this byte changed
|
||||||
{
|
{
|
||||||
if(i < lastIndexToCopy)
|
if(i < lastIndexToCopy)
|
||||||
s_curValues[i] = sourceAddr[i]; // update value
|
s_curValues[i] = ReadValueAtHardwareAddress(hwSourceAddr+i, 1); // update value
|
||||||
for(int k = 0; k < sizeof(compareType); k++) // loop through the previous entries that contain this byte
|
for(int k = 0; k < sizeof(compareType); k++) // loop through the previous entries that contain this byte
|
||||||
{
|
{
|
||||||
if(i >= indexEnd+k)
|
if(i >= indexEnd+k)
|
||||||
|
@ -425,7 +385,6 @@ void ItemIndexToVirtualRegion(unsigned int itemIndex, MemoryRegion& virtualRegio
|
||||||
|
|
||||||
virtualRegion.size = sizeof(compareType);
|
virtualRegion.size = sizeof(compareType);
|
||||||
virtualRegion.hardwareAddress = region.hardwareAddress + bytesWithinRegion;
|
virtualRegion.hardwareAddress = region.hardwareAddress + bytesWithinRegion;
|
||||||
virtualRegion.softwareAddress = region.softwareAddress + bytesWithinRegion;
|
|
||||||
virtualRegion.virtualIndex = region.virtualIndex + bytesWithinRegion;
|
virtualRegion.virtualIndex = region.virtualIndex + bytesWithinRegion;
|
||||||
virtualRegion.itemIndex = itemIndex;
|
virtualRegion.itemIndex = itemIndex;
|
||||||
return;
|
return;
|
||||||
|
@ -948,55 +907,41 @@ bool IsSatisfied(int itemIndex)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int ReadValueAtSoftwareAddress(const unsigned char* address, unsigned int size, int byteSwapped = false)
|
unsigned int ReadValueAtSoftwareAddress(const unsigned char* address, unsigned int size)
|
||||||
{
|
{
|
||||||
unsigned int value = 0;
|
unsigned int value = 0;
|
||||||
if(!byteSwapped)
|
//if(!byteSwapped)
|
||||||
{
|
{
|
||||||
// assumes we're little-endian
|
// assumes we're little-endian
|
||||||
memcpy(&value, address, size);
|
memcpy(&value, address, size);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// byte-swap and convert to current endianness at the same time
|
|
||||||
for(unsigned int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
value <<= 8;
|
|
||||||
value |= *((unsigned char*)((intptr_t)address++^1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
void WriteValueAtSoftwareAddress(unsigned char* address, unsigned int value, unsigned int size, int byteSwapped = false)
|
void WriteValueAtSoftwareAddress(unsigned char* address, unsigned int value, unsigned int size)
|
||||||
{
|
{
|
||||||
if(!byteSwapped)
|
//if(!byteSwapped)
|
||||||
{
|
{
|
||||||
// assumes we're little-endian
|
// assumes we're little-endian
|
||||||
memcpy(address, &value, size);
|
memcpy(address, &value, size);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// write as big endian
|
|
||||||
for(int i = size-1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
address[i] = value & 0xFF;
|
|
||||||
value >>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
unsigned int ReadValueAtHardwareAddress(HWAddressType address, unsigned int size)
|
unsigned int ReadValueAtHardwareAddress(HWAddressType address, unsigned int size)
|
||||||
{
|
{
|
||||||
return ReadValueAtSoftwareAddress(HardwareToSoftwareAddress(address), size);
|
unsigned int value = 0;
|
||||||
|
|
||||||
|
// read as little endian
|
||||||
|
for(unsigned int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
value <<= 8;
|
||||||
|
value |= (IsHardwareAddressValid(address) ? GetMem(address) : 0);
|
||||||
|
address++;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
bool WriteValueAtHardwareAddress(HWAddressType address, unsigned int value, unsigned int size)
|
bool WriteValueAtHardwareAddress(HWAddressType address, unsigned int value, unsigned int size)
|
||||||
{
|
{
|
||||||
// FIXME: doesn't work for now. see HardwareToSoftwareAddress to know why.
|
// TODO: NYI
|
||||||
WriteValueAtSoftwareAddress(HardwareToSoftwareAddress(address), value, size);
|
return false;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool IsHardwareAddressValid(HWAddressType address)
|
|
||||||
{
|
|
||||||
return HardwareToSoftwareAddress(address) != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,13 @@
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
|
//TODO - we really need some kind of global platform-specific options api
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "drivers/win/main.h"
|
||||||
|
#include "drivers/win/ram_search.h"
|
||||||
|
#include "drivers/win/ramwatch.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static void (*SPreSave)(void);
|
static void (*SPreSave)(void);
|
||||||
|
@ -703,6 +710,9 @@ bool FCEUSS_Load(const char *fname)
|
||||||
SaveStateStatus[CurrentState]=1;
|
SaveStateStatus[CurrentState]=1;
|
||||||
}
|
}
|
||||||
delete st;
|
delete st;
|
||||||
|
#ifdef WIN32
|
||||||
|
Update_RAM_Search(); // Update_RAM_Watch() is also called.
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue