diff options
Diffstat (limited to 'sourcemod/scripting/include/glib')
| -rw-r--r-- | sourcemod/scripting/include/glib/addressutils.inc | 54 | ||||
| -rw-r--r-- | sourcemod/scripting/include/glib/assertutils.inc | 61 | ||||
| -rw-r--r-- | sourcemod/scripting/include/glib/memutils.inc | 232 |
3 files changed, 347 insertions, 0 deletions
diff --git a/sourcemod/scripting/include/glib/addressutils.inc b/sourcemod/scripting/include/glib/addressutils.inc new file mode 100644 index 0000000..bbe8f14 --- /dev/null +++ b/sourcemod/scripting/include/glib/addressutils.inc @@ -0,0 +1,54 @@ +#if defined _addressutils_included +#endinput +#endif +#define _addressutils_included + +methodmap AddressBase +{ + property Address Address + { + public get() { return view_as<Address>(this); } + } +} + +//-==Operator overloadings +stock Address operator+(Address l, int r) +{ + return l + view_as<Address>(r); +} + +stock Address operator+(int l, Address r) +{ + return view_as<Address>(l) + r; +} + +stock Address operator-(Address l, int r) +{ + return l - view_as<Address>(r); +} + +stock Address operator-(int l, Address r) +{ + return view_as<Address>(l) - r; +} + +stock Address operator*(Address l, int r) +{ + return l * view_as<Address>(r); +} + +stock Address operator*(int l, Address r) +{ + return view_as<Address>(l) * r; +} + +stock Address operator/(Address l, int r) +{ + return l / view_as<Address>(r); +} + +stock Address operator/(int l, Address r) +{ + return view_as<Address>(l) / r; +} +//Operator overloadings==-
\ No newline at end of file diff --git a/sourcemod/scripting/include/glib/assertutils.inc b/sourcemod/scripting/include/glib/assertutils.inc new file mode 100644 index 0000000..83cd90d --- /dev/null +++ b/sourcemod/scripting/include/glib/assertutils.inc @@ -0,0 +1,61 @@ +#if defined _assertutils_included +#endinput +#endif +#define _assertutils_included + +/* Compile time settings for this include. Should be defined before including this file. +* #define ASSERTUTILS_DISABLE //Disables all assertions +* #define ASSERTUTILS_FAILSTATE_FUNC //Define the name of the function that should be called when assertion is hit +*/ + +#if !defined SNAME +#define __SNAME "" +#else +#define __SNAME SNAME +#endif + +#define ASSERT_FMT_STRING_LEN 512 + +#if defined ASSERTUTILS_DISABLE + +#define ASSERT(%1)%2; +#define ASSERT_MSG(%1,%2)%3; +#define ASSERT_FMT(%1,%2)%3; +#define ASSERT_FINAL(%1)%2; +#define ASSERT_FINAL_MSG(%1,%2)%3; + +#elseif defined ASSERTUTILS_FAILSTATE_FUNC + +#define ASSERT(%1) if(!(%1)) ASSERTUTILS_FAILSTATE_FUNC(__SNAME..."Assertion failed: \""...#%1..."\"") +#define ASSERT_MSG(%1,%2) if(!(%1)) ASSERTUTILS_FAILSTATE_FUNC(__SNAME...%2) +#define ASSERT_FMT(%1,%2) if(!(%1)) ASSERTUTILS_FAILSTATE_FUNC(__SNAME...%2) +#define ASSERT_FINAL(%1) if(!(%1)) SetFailState(__SNAME..."Assertion failed: \""...#%1..."\"") +#define ASSERT_FINAL_MSG(%1,%2) if(!(%1)) SetFailState(__SNAME...%2) + +#else + +#define ASSERT(%1) if(!(%1)) SetFailState(__SNAME..."Assertion failed: \""...#%1..."\"") +#define ASSERT_MSG(%1,%2) if(!(%1)) SetFailState(__SNAME...%2) +#define ASSERT_FMT(%1,%2) if(!(%1)) SetFailState(__SNAME...%2) +#define ASSERT_FINAL(%1) ASSERT(%1) +#define ASSERT_FINAL_MSG(%1,%2) ASSERT_MSG(%1,%2) + +#endif + +// Might be redundant as default ASSERT_MSG accept format arguments just fine. +#if 0 +stock void ASSERT_FMT(bool result, char[] fmt, any ...) +{ +#if !defined ASSERTUTILS_DISABLE + if(!result) + { + char buff[ASSERT_FMT_STRING_LEN]; + VFormat(buff, sizeof(buff), fmt, 3); + + SetFailState(__SNAME..."%s", buff); + } +#endif +} +#endif + +#undef ASSERT_FMT_STRING_LEN
\ No newline at end of file diff --git a/sourcemod/scripting/include/glib/memutils.inc b/sourcemod/scripting/include/glib/memutils.inc new file mode 100644 index 0000000..5813d92 --- /dev/null +++ b/sourcemod/scripting/include/glib/memutils.inc @@ -0,0 +1,232 @@ +#if defined _memutils_included +#endinput +#endif +#define _memutils_included + +#include "glib/assertutils" +#include "glib/addressutils" + +/* Compile time settings for this include. Should be defined before including this file. +* #define MEMUTILS_PLUGINENDCALL //This should be defined if main plugin has OnPluginEnd() forward used. +*/ + +#define MEM_LEN_SAFE_THRESHOLD 2000 + +//-==PatchHandling methodmap +static StringMap gPatchStack; + +methodmap PatchHandler < AddressBase +{ + public PatchHandler(Address addr) + { + ASSERT(addr != Address_Null); + + if(!gPatchStack) + gPatchStack = new StringMap(); + + return view_as<PatchHandler>(addr); + } + + property any Any + { + public get() { return view_as<any>(this); } + } + + public void Save(int len) + { + ASSERT(gPatchStack); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + len++; + + int[] arr = new int[len]; + arr[0] = len; + + for(int i = 0; i < len - 1; i++) + arr[i + 1] = LoadFromAddress(this.Address + i, NumberType_Int8); + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + gPatchStack.SetArray(buff, arr, len); + } + + public void PatchNSave(int len, char byte = 0x90) + { + ASSERT(gPatchStack); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + len++; + + int[] arr = new int[len]; + arr[0] = len; + + for(int i = 0; i < len - 1; i++) + { + arr[i + 1] = LoadFromAddress(this.Address + i, NumberType_Int8); + StoreToAddress(this.Address + i, byte, NumberType_Int8); + } + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + gPatchStack.SetArray(buff, arr, len); + } + + public void PatchNSaveSeq(const char[] data, int len) + { + ASSERT(gPatchStack); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + len++; + + int[] arr = new int[len]; + arr[0] = len; + + for(int i = 0; i < len - 1; i++) + { + arr[i + 1] = LoadFromAddress(this.Address + i, NumberType_Int8); + StoreToAddress(this.Address + i, data[i], NumberType_Int8); + } + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + gPatchStack.SetArray(buff, arr, len); + } + + public void Restore() + { + if(!gPatchStack) + return; + + char buff[32]; + IntToString(this.Any, buff, sizeof(buff)); + + int arrSize[1]; + if(!gPatchStack.GetArray(buff, arrSize, sizeof(arrSize))) + return; + + int[] arr = new int[arrSize[0]]; + gPatchStack.GetArray(buff, arr, arrSize[0]); + gPatchStack.Remove(buff); + + for(int i = 0; i < arrSize[0] - 1; i++) + StoreToAddress(this.Address + i, arr[i + 1], NumberType_Int8); + + if(gPatchStack.Size == 0) + delete gPatchStack; + } +} + +public void OnPluginEnd() +{ + if(gPatchStack) + { + StringMapSnapshot sms = gPatchStack.Snapshot(); + char buff[32]; + Address addr; + + for(int i = 0; i < sms.Length; i++) + { + sms.GetKey(i, buff, sizeof(buff)); + addr = view_as<Address>(StringToInt(buff)); + view_as<PatchHandler>(addr).Restore(); + } + } + +#if defined MEMUTILS_PLUGINENDCALL + OnPluginEnd_MemUtilsRedefined(); +#endif +} +#undef OnPluginEnd +#if defined MEMUTILS_PLUGINENDCALL +#define OnPluginEnd OnPluginEnd_MemUtilsRedefined +#else +#define OnPluginEnd OnPluginEnd_Redifined(){}\ +void MEMUTILS_INCLUDE_WARNING_OnPluginEnd_REDIFINITION +#endif +//PatchHandling methodmap==- + +//-==Other util functions +stock int LoadStringFromAddress(Address addr, char[] buff, int length) +{ + int i; + for(i = 0; i < length && (buff[i] = LoadFromAddress(addr + i, NumberType_Int8)) != '\0'; i++) { } + buff[i == length ? i - 1 : i] = '\0'; + return i; +} + +stock void DumpOnAddress(Address addr, int len, int columns = 10) +{ + char buff[128], buff2[128]; + + ASSERT(addr != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + Format(buff, sizeof(buff), "[0x%08X]", addr); + char chr; + for(int i = 0; i < len; i++) + { + chr = LoadFromAddress(addr + i, NumberType_Int8); + Format(buff, sizeof(buff), "%s %02X", buff, chr); + Format(buff2, sizeof(buff2), "%s%c", buff2, (chr > ' ' && chr != 0x7F && chr != 0xFF ? chr : '.')); + if(i % columns == columns - 1) + { + PrintToServer(__SNAME..."%s %s", buff, buff2); + Format(buff, sizeof(buff), "[0x%08X]", addr + i); + buff2[0] = '\0'; + } + } + + if((len - 1) % columns != columns - 1) + PrintToServer(__SNAME..."%s %s", buff, buff2); +} + +//NO OVERLAPPING!! +stock void MoveBytes(Address from, Address to, int len, char replace_with = 0x90) +{ + ASSERT(from != Address_Null); + ASSERT(to != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + ASSERT(to < from || to > from + len); + + if(from == to) + return; + + for(int i = 0; i < len; i++) + { + StoreToAddress(to + i, LoadFromAddress(from + i, NumberType_Int8), NumberType_Int8); + StoreToAddress(from + i, replace_with, NumberType_Int8); + } +} + +stock void CutNCopyBytes(Address from, Address to, int len, char replace_with = 0x90) +{ + ASSERT(from != Address_Null); + ASSERT(to != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + if(from == to) + return; + + int[] arr = new int[len]; + + for(int i = 0; i < len; i++) + { + arr[i] = LoadFromAddress(from + i, NumberType_Int8); + StoreToAddress(from + i, replace_with, NumberType_Int8); + } + + for(int i = 0; i < len; i++) + StoreToAddress(to + i, arr[i], NumberType_Int8); +} + +stock void PatchArea(Address addr, int len, char byte = 0x90) +{ + ASSERT(addr != Address_Null); + ASSERT(len > 0 && len < MEM_LEN_SAFE_THRESHOLD); + + for(int i = 0; i < len; i++) + StoreToAddress(addr + i, byte, NumberType_Int8); +} +//Other util functions==- + +#undef MEM_LEN_SAFE_THRESHOLD
\ No newline at end of file |
