Add convenience logic for "offset" to Address definitions in GameConf (#580)

Allows for the last "read" offset for an Address to instead be "offset", which doesn't deref the addr pointer after applying the offset
Shortens the necessary coding to get a particular Address inside a function (old: store offset in a separate GameConf Offsets entry, apply the offset to the Address in SP)
This commit is contained in:
FlaminSarge 2017-10-28 04:11:32 -07:00 committed by Asher Baker
parent 4bab834716
commit c3b25e54f8
2 changed files with 27 additions and 7 deletions

View File

@ -323,6 +323,7 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
m_Address[0] = '\0';
m_AddressSignature[0] = '\0';
m_AddressReadCount = 0;
m_AddressLastIsOffset = false;
strncopy(m_Address, name, sizeof(m_Address));
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
@ -430,10 +431,18 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
}
}
} else if (m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS || m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ) {
if (strcmp(key, "read") == 0) {
if (strcmp(key, "read") == 0 || strcmp(key, "offset") == 0) {
int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
if (m_AddressReadCount < limit)
if (m_AddressLastIsOffset)
{
logger->LogError("[SM] Error parsing Address \"%s\", 'offset' entry must be the last entry (gameconf \"%s\")", m_Address, m_CurFile);
}
else if (m_AddressReadCount < limit)
{
if (strcmp(key, "offset") == 0)
{
m_AddressLastIsOffset = true;
}
m_AddressRead[m_AddressReadCount] = atoi(value);
m_AddressReadCount++;
}
@ -637,7 +646,7 @@ SMCResult CGameConfig::ReadSMC_LeavingSection(const SMCStates *states)
if (m_Address[0] != '\0' && m_AddressSignature[0] != '\0')
{
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead, m_AddressLastIsOffset);
m_Addresses.replace(m_Address, addrConf);
}
@ -997,12 +1006,17 @@ bool CGameConfig::GetAddress(const char *key, void **retaddr)
int offset = addrConf.read[i];
//NULLs in the middle of an indirection chain are bad, end NULL is ok
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
*retaddr = NULL;
return false;
}
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
//If lastIsOffset is set and this is the last iteration of the loop, don't deref
if (addrConf.lastIsOffset && i == addrConf.readCount-1) {
addr = reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(addr) + offset);
} else {
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
}
}
*retaddr = addr;
@ -1014,13 +1028,17 @@ static inline unsigned minOf(unsigned a, unsigned b)
return a <= b ? a : b;
}
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read)
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset)
{
unsigned readLimit = minOf(readCount, sizeof(this->read) / sizeof(this->read[0]));
strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
this->readCount = readLimit;
memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
//For safety: if the readLimit isn't the same as the readCount, then the
//last read value was definitely discarded, so lastIsOffset should be ignored
this->lastIsOffset = readLimit < readCount ? false : lastIsOffset;
}
SendProp *CGameConfig::GetSendProp(const char *key)

View File

@ -103,8 +103,9 @@ private:
char signatureName[64];
int readCount;
int read[8];
bool lastIsOffset;
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read, bool lastIsOffset);
AddressConf() {}
};
@ -113,6 +114,7 @@ private:
char m_AddressSignature[64];
int m_AddressReadCount;
int m_AddressRead[8];
bool m_AddressLastIsOffset;
StringHashMap<AddressConf> m_Addresses;
const char *m_pEngine;
const char *m_pBaseEngine;