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