win32: fix new ramsearch

This commit is contained in:
gocha 2009-10-08 08:06:45 +00:00
parent 585cb80257
commit 197322bcf1
2 changed files with 55 additions and 100 deletions

View File

@ -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;
} }

View File

@ -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