diff --git a/indirection.inc b/indirection.inc index 7158362..bbdb73e 100644 --- a/indirection.inc +++ b/indirection.inc @@ -139,6 +139,9 @@ enum E_INDIRECTION E_INDIRECTION_CLAIM, // Called by `Indirect_Claim`. E_INDIRECTION_RELEASE, // Called by `Indirect_Release`. E_INDIRECTION_METADATA, // Only used by end-users. + E_INDIRECTION_TAG, // Save the encoded parameters tag of this callback. + E_INDIRECTION_OWNER, // Attach the function to players etc. + E_INDIRECTION_NEXT // Next pointer in a generic list of callbacks. } stock @@ -147,11 +150,25 @@ stock INDIRECTION_DATA = 0, INDIRECTION_TAG = 0; +// Constant offsets for assembly. +const + E_INDIRECTION_ALWAYS_NULL__ = _:E_INDIRECTION_ALWAYS_NULL * cellbytes, + E_INDIRECTION_HANDER__ = _:E_INDIRECTION_HANDER * cellbytes, + E_INDIRECTION_CLAIM__ = _:E_INDIRECTION_CLAIM * cellbytes, + E_INDIRECTION_RELEASE__ = _:E_INDIRECTION_RELEASE * cellbytes, + E_INDIRECTION_METADATA__ = _:E_INDIRECTION_METADATA * cellbytes, + E_INDIRECTION_TAG__ = _:E_INDIRECTION_TAG * cellbytes, + E_INDIRECTION_OWNER__ = _:E_INDIRECTION_OWNER * cellbytes, + E_INDIRECTION_NEXT__ = _:E_INDIRECTION_NEXT * cellbytes, + E_INDIRECTION__ = _:E_INDIRECTION * cellbytes; + stock const INDIRECTION_NAUGHT = 0; static stock - gsCodSize = 0; // The size of `COD`. + gsCodSize = 0, // The size of `COD`. + gsKnownOwnedCallbacks = 0, + gsFakeE_INDIRECTION[E_INDIRECTION]; #if !defined YSI_MAX_STRING #define YSI_MAX_STRING (144) @@ -321,7 +338,6 @@ stock Indirect_Call__(meta, GLOBAL_TAG_TYPES:...) { const cells0 = 4 * cellbytes; const cells1 = -1 * cellbytes; - const cells2 = 1 * cellbytes; const cells3 = 1 * cellbytes; const cells4 = 2 * cellbytes; static @@ -367,7 +383,7 @@ stock Indirect_Call__(meta, GLOBAL_TAG_TYPES:...) if (!INDIRECTION_DATA) { // Get the function at `func - COD + 4`. - #emit CONST.pri cells2 + #emit CONST.pri E_INDIRECTION_HANDER__ #emit ADD #emit LOAD.I // Call it, passing `func` as a proper pointer, NOT skipping `PROC`. @@ -667,7 +683,6 @@ stock Indirect_Array(func, tag, const params[], size = sizeof (params)) #endif const cells1 = 5 * cellbytes; const cells2 = 6 * cellbytes; - const cells3 = 1 * cellbytes; const cells4 = 1 * cellbytes; const cells5 = 2 * cellbytes; static @@ -733,7 +748,7 @@ stock Indirect_Array(func, tag, const params[], size = sizeof (params)) #emit STOR.alt INDIRECTION_DATA // Get the function at `func - COD + 4`. #emit LOAD.pri INDIRECTION_DATA - #emit ADD.C cells3 + #emit ADD.C E_INDIRECTION_HANDER__ #emit LOAD.I // Call it, passing `func` as a proper pointer, NOT skipping `PROC`. #emit SCTRL 6 @@ -788,6 +803,258 @@ stock Indirect_Array(func, tag, const params[], size = sizeof (params)) return 0; } +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer with attached Nextdata. + * + * Gets extra data from the pointer. + * + *//*------------------------------------------------------------------------**/ + +stock Indirect_GetNext_(func) +{ + if (func >= gsCodSize) + { + // Get the data at `func - COD`. + #emit LOAD.S.pri func + #emit LOAD.alt gsCodSize + #emit SUB + #emit MOVE.alt + #emit LOAD.I + #emit STOR.S.pri func + if (func) + { + // Probably a string. + return 0; + } + {} + // I'm relying on `alt` not changing here... + // Get the function at `func - COD + 16`. + #emit CONST.pri E_INDIRECTION_NEXT__ + #emit ADD + #emit LOAD.I + #emit RETN + } + return 0; +} +#define Indirect_GetNext(%0) Indirect_GetNext_(_:%0) + +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer to attach Nextdata to. + * The Nextdata. + *//*------------------------------------------------------------------------**/ + +stock Indirect_SetNext_(func, data) +{ + if (func >= gsCodSize) + { + // Get the data at `func - COD`. + #emit LOAD.S.pri func + #emit LOAD.alt gsCodSize + #emit SUB + #emit MOVE.alt + #emit LOAD.I + #emit STOR.S.pri func + if (func) + { + // Probably a string. + return false; + } + {} + // I'm relying on `alt` not changing here... + // Get the function at `func - COD + 16`. + #emit CONST.pri E_INDIRECTION_NEXT__ + #emit ADD + #emit LOAD.S.alt data + #emit XCHG + #emit STOR.I + return true; + } + return false; +} +#define Indirect_SetNext(%0,%1) Indirect_SetNext_(_:(%0),%1) + +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer with a tag. + * + * Gets the tag of the pointer. + * + *//*------------------------------------------------------------------------**/ + +stock Indirect_GetTag_(func) +{ + if (func >= gsCodSize) + { + // Get the data at `func - COD`. + #emit LOAD.S.pri func + #emit LOAD.alt gsCodSize + #emit SUB + #emit MOVE.alt + #emit LOAD.I + #emit STOR.S.pri func + if (func) + { + // Probably a string. + return 0; + } + {} + // I'm relying on `alt` not changing here... + // Get the function at `func - COD + 16`. + #emit CONST.pri E_INDIRECTION_TAG__ + #emit ADD + #emit LOAD.I + #emit RETN + } + return 0; +} +#define Indirect_GetTag(%0) Indirect_GetTag_(_:%0) + +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer to attach a tag to. + * The tag. + *//*------------------------------------------------------------------------**/ + +stock bool:Indirect_SetTag_(func, tag) +{ + if (func >= gsCodSize) + { + // Get the data at `func - COD`. + #emit LOAD.S.pri func + #emit LOAD.alt gsCodSize + #emit SUB + #emit MOVE.alt + #emit LOAD.I + #emit STOR.S.pri func + if (func) + { + // Probably a string. + return false; + } + {} + // I'm relying on `alt` not changing here... + // Get the function at `func - COD + 16`. + #emit CONST.pri E_INDIRECTION_TAG__ + #emit ADD + #emit LOAD.S.alt tag + #emit XCHG + #emit STOR.I + return true; + } + return false; +} +#define Indirect_SetTag(%0,%1) Indirect_SetTag_(_:(%0),%1) + +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer with an owner. + * + * Gets the owner of the pointer. + * + *//*------------------------------------------------------------------------**/ + +stock Indirect_GetOwner_(func) +{ + if (func >= gsCodSize) + { + // Get the data at `func - COD`. + #emit LOAD.S.pri func + #emit LOAD.alt gsCodSize + #emit SUB + #emit MOVE.alt + #emit LOAD.I + #emit STOR.S.pri func + if (func) + { + // Probably a string. + return 0; + } + {} + // I'm relying on `alt` not changing here... + // Get the function at `func - COD + 16`. + #emit CONST.pri E_INDIRECTION_OWNER__ + #emit ADD + #emit LOAD.I + #emit RETN + } + return 0; +} +#define Indirect_GetOwner(%0) Indirect_GetOwner_(_:%0) + +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer to claim with owner. + * + * Replaces the default CLAIM function so this is called instead, then + * forwards to the original. + * + *//*------------------------------------------------------------------------**/ + +#define CALL@Indirect_EBCClaim_%8() Indirect_EBCClaim_%8(gsFakeE_INDIRECTION) + +static stock Indirect_EBCClaim_(func[E_INDIRECTION]) +{ + // Reset the claim pointer. + func[E_INDIRECTION_CLAIM] = func[E_INDIRECTION_NEXT]; + // Add this callback to the list of known callbacks. + func[E_INDIRECTION_NEXT] = gsKnownOwnedCallbacks; + gsKnownOwnedCallbacks = ref(func[E_INDIRECTION_NEXT]); + // Re-claim the function using the original pointer. + #emit LOAD.S.alt func + // Reset the frame. + #emit POP.pri + #emit SCTRL 5 + // Perfect call forward. + #emit CONST.pri E_INDIRECTION_CLAIM__ + #emit ADD + #emit LOAD.I + #emit SCTRL 6 +} + +/*-------------------------------------------------------------------------*//** + * indirection + * The function pointer to attach an owner to. + * The owner. + *//*------------------------------------------------------------------------**/ + +stock Indirect_SetOwner_(func, owner) +{ + if (func >= gsCodSize) + { + // Get the data at `func - COD`. + #emit LOAD.S.pri func + #emit LOAD.alt gsCodSize + #emit SUB + #emit MOVE.alt + #emit LOAD.I + #emit STOR.S.pri func + if (func) + { + // Probably a string. + return false; + } + {} + #emit STOR.S.alt func + if (ReadAmxMemory(func + E_INDIRECTION_NEXT__)) + { + // Can't use this list pointer to save the owner. + return false; + } + // Store the owner. + WriteAmxMemory(func + E_INDIRECTION_OWNER__, owner), + // Change the claim pointer to our internal one, so we add it to the + // list if this is ever claimed. + owner = ReadAmxMemory(func + E_INDIRECTION_CLAIM__), + WriteAmxMemory(func + E_INDIRECTION_NEXT__, owner), + WriteAmxMemory(func + E_INDIRECTION_CLAIM__, _:addressof (Indirect_EBCClaim_)); + return true; + } + return false; +} +#define Indirect_SetOwner(%0,%1) Indirect_SetOwner_(_:(%0),%1) + /*-------------------------------------------------------------------------*//** * indirection * The function pointer with attached metadata. @@ -798,7 +1065,6 @@ stock Indirect_Array(func, tag, const params[], size = sizeof (params)) stock Indirect_GetMeta_(func) { - const cells0 = 4 * cellbytes; if (func >= gsCodSize) { // Get the data at `func - COD`. @@ -816,7 +1082,7 @@ stock Indirect_GetMeta_(func) {} // I'm relying on `alt` not changing here... // Get the function at `func - COD + 16`. - #emit CONST.pri cells0 + #emit CONST.pri E_INDIRECTION_METADATA__ #emit ADD #emit LOAD.I #emit RETN @@ -833,7 +1099,6 @@ stock Indirect_GetMeta_(func) stock Indirect_SetMeta_(func, data) { - const cells0 = 4 * cellbytes; if (func >= gsCodSize) { // Get the data at `func - COD`. @@ -846,19 +1111,21 @@ stock Indirect_SetMeta_(func, data) if (func) { // Probably a string. - return; + return false; } {} // I'm relying on `alt` not changing here... // Get the function at `func - COD + 16`. - #emit CONST.pri cells0 + #emit CONST.pri E_INDIRECTION_METADATA__ #emit ADD #emit LOAD.S.alt data #emit XCHG #emit STOR.I + return true; } + return false; } -#define Indirect_SetMeta(%0) Indirect_SetMeta_(_:%0) +#define Indirect_SetMeta(%0,%1) Indirect_SetMeta_(_:(%0),%1) /*-------------------------------------------------------------------------*//** * indirection @@ -897,7 +1164,7 @@ stock Indirect_Claim_(func) #emit POP.pri #emit SCTRL 5 // Get the function at `func - COD + 8`. - #emit CONST.pri 8 + #emit CONST.pri E_INDIRECTION_CLAIM__ #emit ADD #emit LOAD.I #emit SCTRL 6 @@ -920,7 +1187,6 @@ stock Indirect_Claim_(func) stock Indirect_Release_(func) { - const cells0 = 3 * cellbytes; if (func >= gsCodSize) { // Get the data at `func - COD`. @@ -944,7 +1210,7 @@ stock Indirect_Release_(func) #emit POP.pri #emit SCTRL 5 // Get the function at `func - COD + 12`. - #emit CONST.pri cells0 + #emit CONST.pri E_INDIRECTION_RELEASE__ #emit ADD #emit LOAD.I #emit SCTRL 6