Fix marker destruction: use CleanupEntity_ProcessAttachments (0x670d50)

The native high-level destructor counterpart to CreateEntityInstance_WithAttachment.
Properly detaches from render lists and scene graph before freeing memory,
fixing the delayed crash from dangling pointers in the per-frame render path.
This commit is contained in:
MarcelineVQ
2026-02-27 12:14:29 -08:00
parent ab6f5ea4b9
commit fe1bfdedb8
2 changed files with 16 additions and 5 deletions
+6 -4
View File
@@ -73,12 +73,14 @@ fn createEntityInstance(path: [*:0]const u8, pos: *[3]f32, facing: f32, flags: u
return if (result != 0) @ptrFromInt(result) else null;
}
/// DestroyWorldObjectAndRelease — __fastcall(ECX=obj), tail JMP.
fn destroyWorldObject(obj: *anyopaque) void {
/// CleanupEntity_ProcessAttachments — __fastcall(ECX=entity), no stack params.
/// High-level destructor: frees attachments, decrements refcount, dispatches
/// to type-specific cleanup (render detach + scene graph removal + heap free).
fn cleanupEntity(obj: *anyopaque) void {
asm volatile ("call *%[func]"
:
: [_] "{ecx}" (@intFromPtr(obj)),
[func] "r" (o.FN_DESTROY_WORLD_OBJECT),
[func] "r" (o.FN_CLEANUP_ENTITY),
: .{ .eax = true, .edx = true, .memory = true, .cc = true }
);
}
@@ -139,7 +141,7 @@ pub fn destroyTestMarker() void {
test_marker = null;
con.print("[markers] destroying marker...\n");
destroyWorldObject(marker);
cleanupEntity(marker);
con.print("[markers] marker destroyed\n");
}
+10 -1
View File
@@ -43,9 +43,18 @@ pub const FN_ALLOCATE_WORLD_OBJECT: usize = 0x006a0930;
/// DestroyWorldObjectAndRelease(object) — __fastcall, ECX=obj, no stack params.
/// Unlinks from world object list (+0x10/+0x14), calls virtual destructor, frees heap.
/// Ends with tail JMP to ReleaseToHeap — from caller's perspective, a normal return.
/// ONLY for objects on WENTITY heap (from AllocateAndInitializeWorldObject).
pub const FN_DESTROY_WORLD_OBJECT: usize = 0x006a0a70;
/// CleanupEntity_ProcessAttachments(entity) — __fastcall, ECX=entity, no stack params.
/// High-level destructor counterpart to CreateEntityInstance_WithAttachment.
/// Walks and frees attachment children, decrements refcount at +0x0E, then
/// dispatches to type-specific destructor based on flags at +0x8:
/// flag 0x8 (M2): destroyWorldEnvironment (0x6a6870) — scene graph removal + free
/// flag 0x40 (WMO): cleanupGameObject (0x6a67a0) — render detach + spatial unlink + free
/// Only actually frees when refcount reaches 0.
pub const FN_CLEANUP_ENTITY: usize = 0x00670d50;
/// DecrementReferenceCount(obj) — __fastcall, ECX=obj, no stack params.
/// Decrements ref count; when it reaches 0, calls virtual destructor to free.
pub const FN_DECREMENT_REFCOUNT: usize = 0x007103a0;