Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion smsdk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
/* Basic information exposed publicly */
#define SMEXT_CONF_NAME "Source Scramble"
#define SMEXT_CONF_DESCRIPTION "Tools for working with memory."
#define SMEXT_CONF_VERSION "0.8.1"
#define SMEXT_CONF_VERSION "0.8.3"
#define SMEXT_CONF_AUTHOR "nosoop"
#define SMEXT_CONF_URL "https://github.com/nosoop/SMExt-SourceScramble"
#define SMEXT_CONF_LOGTAG "sscramble"
Expand Down
58 changes: 40 additions & 18 deletions types/mempatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,52 +29,56 @@ class MemoryPatch {
for (auto bit : info.vecPatch) {
this->vecPatch.push_back(bit);
}

for (auto bit : info.vecVerify) {
this->vecVerify.push_back(bit);
}

for (auto bit : info.vecPreserve) {
this->vecPreserve.push_back(bit);
}

// ignore offset if address is bad
this->pAddress = pAddress ? pAddress + (info.offset) : 0;
}

bool Enable() {
if (vecRestore.size() > 0) {
// already patched, disregard
return false;
}

if (!this->Verify()) {
return false;
}
ByteVectorRead(vecRestore, (uint8_t*) pAddress, vecPatch.size());

SourceHook::SetMemAccess((void*) this->pAddress, vecPatch.size() * sizeof(uint8_t),
SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC);
ByteVectorWrite(vecPatch, (uint8_t*) pAddress);


ByteVectorRead(vecRestore, (uint8_t*)pAddress, vecPatch.size());

SourceHook::SetMemAccess((void*)this->pAddress, vecPatch.size() * sizeof(uint8_t),
SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC);
ByteVectorWrite(vecPatch, (uint8_t*)pAddress);

for (size_t i = 0; i < vecPatch.size(); i++) {
uint8_t preserveBits = 0;
if (i < vecPreserve.size()) {
preserveBits = vecPreserve[i];
}
*((uint8_t*) pAddress + i) = (vecPatch[i] & ~preserveBits) | (vecRestore[i] & preserveBits);
*((uint8_t*)pAddress + i) = (vecPatch[i] & ~preserveBits) | (vecRestore[i] & preserveBits);
}

return true;
}

void Disable() {
if (vecRestore.size() == 0) {
// no memory to restore, fug
return;
}
ByteVectorWrite(vecRestore, (uint8_t*) pAddress);

ByteVectorWrite(vecRestore, (uint8_t*)pAddress);
vecRestore.clear();
}

bool Verify() {
if (!pAddress) {
return false;
Expand All @@ -94,10 +98,11 @@ class MemoryPatch {
}
return true;
}

~MemoryPatch() {
this->Disable();
}

uintptr_t pAddress;
ByteVector vecPatch, vecRestore, vecVerify, vecPreserve;
};
Expand Down Expand Up @@ -131,13 +136,30 @@ cell_t sm_MemoryPatchLoadFromConfig(IPluginContext *pContext, const cell_t *para
if (!pConfig) {
return pContext->ThrowNativeError("Invalid game config handle %x (error %d)", hndl, err);
}

void* addr;
if (!pConfig->GetMemSig(info.signature.c_str(), &addr)) {
if (!pConfig->GetMemSig(info.signature.c_str(), &addr) || addr == NULL) {
return pContext->ThrowNativeError("Failed to locate signature for '%s' (mempatch '%s')", info.signature.c_str(), name);
}


if (info.vecPatch.empty()) {
return pContext->ThrowNativeError("Invalid patch configuration: section 'patch' is empty for patch '%s'", name);
}

if (std::equal(info.vecPatch.begin(), info.vecPatch.end(), (uint8_t*)addr)) {
// The bytes in the binary file already match the patch,
// we inform the user that his patch is redundant,
// we tell them to check the patch.
// In this case, as a rule, section `verify` is missing.
smutils->LogError(myself,
"Patch '%s' is redundant. Binary already contains the patch bytes. "
"Check patch data or perhaps it was applied by a different plugin?",
name
);
}

MemoryPatch *pMemoryPatch = new MemoryPatch((uintptr_t) addr, info);

return g_pHandleSys->CreateHandle(g_MemoryPatchType, pMemoryPatch,
pContext->GetIdentity(), myself->GetIdentity(), NULL);
}
Expand Down
1 change: 1 addition & 0 deletions userconf/mempatches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ SMCResult MemPatchGameConfig::ReadSMC_LeavingSection(const SMCStates *states) {
case PState_Runtime:
// pop section info
g_ParseState = PState_Root;

m_MemPatchInfoMap.insert(g_CurrentSection.c_str(), g_CurrentPatchInfo);

g_CurrentPatchInfo = nullptr;
Expand Down
Loading