Attribute Macro relocate

Source
#[relocate]
Expand description

Relocates an address using Skyrim runtime-specific relocation IDs.

The #[relocate] attribute macro enables dynamic resolution of a pointer using relocation IDs for Skyrim Special Edition (SE), Anniversary Edition (AE), and optionally VR. It injects code to resolve the address at runtime and execute user-provided logic through a closure, passing the resolved pointer as an argument.

§Attributes

AttributeTypeRequiredDescription
cast_as&strYesThe type to cast the resolved pointer to (e.g., "*mut bool", "*mut T").
default&strYesThe fallback value returned if resolution fails (e.g., "false", None).
deref_onceboolNoIf specified, the casted pointer will be dereferenced once(by read_unaligned).
id.seu64YesRelocation ID for Skyrim Special Edition.
id.aeu64YesRelocation ID for Skyrim Anniversary Edition.
id.vru64NoRelocation ID for Skyrim VR. Defaults to se if omitted.

If deref_once is specified and the cast_as type is a multi-level pointer (e.g., *mut *mut T), the macro will automatically strip one level and define a helper type alias DerefType:

type DerefType = *mut T;

This type alias can then be used as the parameter type in the closure.

§Function Body

The function body must be a single closure of the form:

|as_type: AsType| { ... }

where AsType is either the raw casted pointer or the dereferenced value, depending on deref_once.

If resolution fails, the default value will be returned instead (parsed as a Rust expression).

§Examples

§Without deref_once

#[commonlibsse_ng_derive_internal::relocate(
    cast_as = "*mut EntryPoint",
    default = "None",
    id(se = 675707, ae = 368994)
)]
#[inline]
fn entry_points(entry_point: ENTRY_POINT) -> Option<NonNull<EntryPoint>> {
    |as_type| unsafe { NonNull::new(as_type.add(entry_point as usize)) }
}

§With deref_once and pointed pointer(e.g. GetSingleton)

#[commonlibsse_ng_derive_internal::relocate(
    cast_as = "*mut *mut INIPrefSettingCollection",
    default = "None",
    deref_once,
    id(se = 524557, ae = 411155)
)]
pub fn get_singleton() -> Option<&'static INIPrefSettingCollection> {
    |deref_type: DerefType| unsafe { deref_type.as_ref() }
}

§Notes

  • cast_as must be a valid Rust type (pointer types encouraged for safety).
  • deref_once is especially useful for singletons and global pointers.
  • This pattern avoids boilerplate and enables declarative relocation definitions.

§See Also

  • #[relocate_fn] — relocate and invoke a function with arguments instead of reading a pointer.