Description:
Add "memory patches" to the plugin either by natives or gamedata files that are read from a folder (gamedata/memorypatcher.games/), and restore them at any time. Mem patches that are added from gamedata/memorypatcher.games/ are automatically applied. Patches that are added by natives (MP_AddMemoryPatch or MP_AddMemoryPatchEx) also needs to be applied by using MP_Patch
"Preview":
Installation:
Quote:
memorypatcher.smx should be the only file required for the plugin to work, gamedata/memorypatcher.games/temp directory should be created automatically by plugin
Commands:
Quote:
sm_mp_patchall - z - Patch all existing memory patches sm_mp_restoreall - z - Restore all existing memory patches sm_mp_patch - z - Patch a single memory patch by siglabel sm_mp_restore - z - Restore a single memory patch by siglabel sm_mp_status - z - Print out status of existing memory patches sm_mp_refresh - z - Read from gamedata folder (gamedata/memorypatcher.games/)
"Signatures"
{
"CGameMovement::WalkMove"
{
"library" "server"
"windows" "\xF3\x0F\x59\xC0\xF3\x0F\x59\xD2\xF3\x0F\x59\xC9\xF3\x0F\x58\xD0\xF3\x0F\x58\xD1\x0F\x28\xC2\xF3\x0F\x51\xC0\xF3\x0F\x5E\xD8"
"linux" "\xF3\x0F\x10\xF0\x0F\x28\xC6\xF3\x0F\x51\xC6\xF3\x0F\x5E\xE8"
}
}
"Offsets"
{
"PatchOffset"
{
"windows" "31"
"linux" "27"
}
"PatchByteCount"
{
"windows" "42"
"linux" "15"
}
}
"Keys"
{
// If the amount of opcodes are less than the PatchByteCount, then it will just append the last opcode for the remaining bytes
// in this case it will append 41 NOPs after the first one for windows, 14 for linux
"opcodes_windows" "\x90"
"opcodes_linux" "\x90"
"siglabel" "CGameMovement::WalkMove"
}
}
}
memorypatcher.inc:
PHP Code:
#if defined _memorypatcher_included
#endinput
#endif
enum//AddMemoryPatchError
{
MP_PATCH_ADD_ERROR_EXCEEDED_OP_CODE_COUNT = -2, // Memory patch is too large
MP_PATCH_ADD_ERROR_PATCH_EXISTS = -1, // Memory patch already exists
MP_PATCH_ADD_ERROR_INVALID_TEMP_FILE = 0, // Should never happend, temp file could not be created (no permissions?)
MP_PATCH_ADD_SUCCESS = 1, // If memory patch was successfully added
}
enum//ApplyMemoryPatchError
{
MP_PATCH_APPLY_ERROR_NOT_FOUND = -4, // Memory patch sig label was not found
MP_PATCH_APPLY_ERROR_IS_PATCHED = -3, // Memory patch was already applied
MP_PATCH_APPLY_ERROR_UNKNOWN_ADDRESS = -2, // Could not find the sig
MP_PATCH_APPLY_ERROR_UNKNOWN_OFFSET = -1, // Should never happend, could not find offset in config file
MP_PATCH_APPLY_ERROR_UNKNOWN_COUNT = 0, // Should never happend, could not find patch byte count
MP_PATCH_APPLY_SUCCESS = 1 // If memory patch was successfully applied
}
enum//RestoreMemoryPatchError
{
MP_PATCH_RESTORE_ERROR_INDEX_NOT_FOUND = -2, // Should never happend, patch index was not found in stringmap
MP_PATCH_RESTORE_ERROR_NOT_FOUND = -1, // Memory patch sig label was not found
MP_PATCH_RESTORE_ERROR_IS_RESTORED = 0, // Memory patch was already restored
MP_PATCH_RESTORE_SUCCESS = 1 // If memory patch was successfully restored
}
/**
* Get server Operating System
*
* @return int ostype
*/
native int MP_GetServerOSType();
/**
* Add a memory patch which can be patched or restored at any time
*
* @param ostype which OS is this sig for (see OSType above)
* @param libtype which libtype is this sig for (see LIBType above)
* @param siglabel label of your sig
* @param sig function signature
* @param offset offset inside the function
* @param opcodes an array containing all opcodes you want to patch the function with
* @param patchbytecount amount of bytes to patch
* @return int memory patch error code (see MemoryPatchError above)
*/
native int MP_AddMemoryPatch(int ostype, int libtype, const char[] siglabel, char[] sig, int offset, int[] opcodes, int patchbytecount);
/**
* Add a memory patch which can be patched or restored at any time (Single OP code instead of array of opcodes)
*
* @param ostype which OS is this sig for (see OSType above)
* @param libtype which libtype is this sig for (see LIBType above)
* @param siglabel label of your sig
* @param sig function signature
* @param offset offset inside the function
* @param opcode the opcode you wanna patch with
* @param patchbytecount amount of bytes to patch
* @return int memory patch error code (see MemoryPatchError above)
*/
native int MP_AddMemoryPatchEx(int ostype, int libtype, const char[] siglabel, char[] sig, int offset, int opcode, int patchbytecount);
/**
* Remove a memory patch (this also restores it to its previous state automatically)
*
* @param siglabel label of your sig
* @return bool true if removed, false if not found
*/
native bool MP_RemoveMemoryPatch(const char[] siglabel);
/**
* Check if memory patch exists by label
*
* @param siglabel siglabel string
* @return bool true if exist
*/
native bool MP_MemoryPatchExists(const char[] siglabel);
/**
* Check if existing memory patch was patched
*
* @param siglabel siglabel string
* @return bool true if patched, false if not found or if not patched
*/
native bool MP_IsPatched(const char[] siglabel);
/**
* Patch all existing memory patches
*
* @return int amount patched
*/
native int MP_PatchAll();
/**
* Restores all patches to their original state
*
* @return int amount restored
*/
native int MP_RestoreAll();
/**
* Patch existing memory patch by sig label
*
* @return int patch error code (see ApplyMemoryPatchError above)
*/
native int MP_Patch(const char[] siglabel);
/**
* Restores existing memory patch by sig label
*
* @return bool true if restored, false if not found
*/
native bool MP_Restore(const char[] siglabel);
/**
* Returns amount of existing memory patches added to the plugin
*
* @return int memory patch count
*/
native int MP_GetMemoryPatchCount();
/**
* Returns amount of existing memory patches added to the plugin
*
* @return int memory patch count
*/
native int MP_GetMemoryPatchSigLabel(int index, char[] buffer, int maxlen);
/**
* AddMemoryPatch or AddMemoryPatchEx should be called here or later (This is called server_spawn event)
*
* @return void
*/
forward void MP_OnMemoryPatcherReady();
public KeyValues MP_GenerateGameDataKeyvalues(int ostype, int libtype, const char[] siglabel, char[] sig, int offset, int[] opcodes, int opcodecount)
{
KeyValues conf = new KeyValues("Games");
char[] szOPcodes = new char[opcodecount * 4 + 1]; // One OP code is 2 characters (NOP = 90) add 2 more characters to that '\x'
for (int i = 0; i < opcodecount; i++)
Format(szOPcodes[i * 4], opcodecount * 4, "\\x%x", opcodes[i]);
szOPcodes[opcodecount * 4] = '\0';
Extra:
As it stands in the gamedata template. You are not required to enter every single OP code if you're simply patching all the data with a single OP code, if the amount of bytes are less than PatchByteCount, it will just keep on patching using the most recent OP code found in the "opcodes_<os>" keyvalue