From cd275b7c51cf8ecbf33f620f0da9eb6ae5c3a464 Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Sat, 28 Feb 2026 22:15:09 +0100 Subject: [PATCH] Actually add offset_ptr.h to the repo --- include/dusk/offset_ptr.h | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 include/dusk/offset_ptr.h diff --git a/include/dusk/offset_ptr.h b/include/dusk/offset_ptr.h new file mode 100644 index 0000000000..3a940804c2 --- /dev/null +++ b/include/dusk/offset_ptr.h @@ -0,0 +1,67 @@ +#ifndef DUSK_OFFSET_PTR_H +#define DUSK_OFFSET_PTR_H + +#if TARGET_PC + +#include "global.h" +#include "endian.h" + +struct OffsetPtr { + // Top bit is used to store "already relocated" flag as a guard thing. + BE value; + + bool setBase(void* base); + bool isRelocated(); + + template + explicit operator T*() const { + s32 swapped = value; + if (swapped == 0) { + // This shouldn't be able to happen but the original offsetting code has the safeguard. + return nullptr; + } + + // Because we use the top (31st) bit as an "already relocated" flag, + // we need to make sure to check the 30th bit to see if we're actually negative. + // And cut off the 31st bit if we're supposed to be positive. + // Effective range this gives us is still like a gigabyte in both directions, + // so we'll be fine on that front. + s32 realOffset = (swapped & 0x4000'0000) ? swapped : (swapped & 0x7FFF'FFFF); + return (T*)POINTER_ADD(this, realOffset); + } +}; + +template +struct OffsetPtrT { + OffsetPtr value; + + bool setBase(void* base) { + return value.setBase(base); + } + bool isRelocated() { + return value.isRelocated(); + } + + T* operator->() { + return (T*) value; + } + + operator T*() const { + return (T*) value; + } + + template + explicit operator TOther*() const { + return (TOther*) value; + } +}; + + +#define OFFSET_PTR(T) OffsetPtrT +#define OFFSET_PTR_RAW OffsetPtr +#else +#define OFFSET_PTR(T) T* +#define OFFSET_PTR_RAW u32 +#endif + +#endif // DUSK_OFFSET_PTR_H