diff --git a/scripting/include/sourcescramble.inc b/scripting/include/sourcescramble.inc index 9ac5672..1ab7373 100644 --- a/scripting/include/sourcescramble.inc +++ b/scripting/include/sourcescramble.inc @@ -48,6 +48,15 @@ methodmap MemoryBlock < Handle { */ public native MemoryBlock(int size); + /** + * Disowns the associated memory block, allowing it to remain allocated even when the handle + * is deleted. Disowning the memory does not invalidate the handle. + * + * Only use this if you are certain that something else will free (or has freed) the memory + * block. + */ + public native void Disown(); + /** * Returns the address of the allocated memory block. */ @@ -94,7 +103,7 @@ static stock int GetNumberTypeByteSize(NumberType size) { case NumberType_Int32: return 4; } ThrowError("Unknown NumberType %d. Did the SourceMod developers add some new ones?", size); - return 1; + return 1; // maybe `return (1 << size);` ? } public Extension __ext_sourcescramble = { diff --git a/smsdk_config.h b/smsdk_config.h index 4bd3769..2c4a5ed 100644 --- a/smsdk_config.h +++ b/smsdk_config.h @@ -39,8 +39,8 @@ /* Basic information exposed publicly */ #define SMEXT_CONF_NAME "Source Scramble" -#define SMEXT_CONF_DESCRIPTION "Convenience functions to perform memory patching." -#define SMEXT_CONF_VERSION "0.3.4" +#define SMEXT_CONF_DESCRIPTION "Tools for working with memory." +#define SMEXT_CONF_VERSION "0.4.0" #define SMEXT_CONF_AUTHOR "nosoop" #define SMEXT_CONF_URL "https://github.com/nosoop/SMExt-SourceScramble" #define SMEXT_CONF_LOGTAG "sscramble" diff --git a/types/memblock.cpp b/types/memblock.cpp index c506cb8..97cbfd0 100644 --- a/types/memblock.cpp +++ b/types/memblock.cpp @@ -5,18 +5,19 @@ HandleType_t g_MemoryBlockType = 0; -class MemoryBlock { -public: - MemoryBlock(size_t size) { +struct MemoryBlock { + MemoryBlock(size_t size) : size{size}, disowned{false} { this->block = calloc(size, 1); - this->size = size; } ~MemoryBlock() { - free(this->block); + if (!disowned) { + free(this->block); + } } size_t size; + bool disowned; void* block; }; @@ -61,7 +62,7 @@ cell_t sm_MemoryBlockPropAddressGet(IPluginContext *pContext, const cell_t *para return pContext->ThrowNativeError("Invalid MemoryBlock handle %x (error %d)", hndl, err); } - return (uint32_t) pMemoryBlock->block; + return (uintptr_t) pMemoryBlock->block; } cell_t sm_MemoryBlockPropSizeGet(IPluginContext *pContext, const cell_t *params) { @@ -75,3 +76,16 @@ cell_t sm_MemoryBlockPropSizeGet(IPluginContext *pContext, const cell_t *params) return pMemoryBlock->size; } + +cell_t sm_MemoryBlockDisown(IPluginContext *pContext, const cell_t *params) { + Handle_t hndl = static_cast(params[1]); + + MemoryBlock *pMemoryBlock; + HandleError err; + if ((err = ReadMemoryBlockHandle(hndl, &pMemoryBlock)) != HandleError_None) { + return pContext->ThrowNativeError("Invalid MemoryBlock handle %x (error %d)", hndl, err); + } + + pMemoryBlock->disowned = true; + return 0; +} diff --git a/types/memblock.h b/types/memblock.h index 66917cf..ee313df 100644 --- a/types/memblock.h +++ b/types/memblock.h @@ -11,12 +11,14 @@ cell_t sm_MemoryBlockCreate(IPluginContext *pContext, const cell_t *params); cell_t sm_MemoryBlockPropAddressGet(IPluginContext *pContext, const cell_t *params); cell_t sm_MemoryBlockPropSizeGet(IPluginContext *pContext, const cell_t *params); +cell_t sm_MemoryBlockDisown(IPluginContext *pContext, const cell_t *params); const sp_nativeinfo_t g_MemoryBlockNatives[] = { { "MemoryBlock.MemoryBlock", sm_MemoryBlockCreate }, { "MemoryBlock.Address.get", sm_MemoryBlockPropAddressGet }, { "MemoryBlock.Size.get", sm_MemoryBlockPropSizeGet }, + { "MemoryBlock.Disown", sm_MemoryBlockDisown }, {NULL, NULL}, };