From 3ee63178a79b457ef6fa5361227fcaddf6a95bf5 Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Fri, 14 Aug 2026 19:29:11 +0200 Subject: [PATCH 1/3] record object ghosts --- src/core/Ghost.lua | 38 ++++++++++++++++++++++++++++++++++---- src/views/Tools.lua | 7 +++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/core/Ghost.lua b/src/core/Ghost.lua index c9a6f293..878f7ea7 100644 --- a/src/core/Ghost.lua +++ b/src/core/Ghost.lua @@ -4,7 +4,9 @@ -- SPDX-License-Identifier: GPL-2.0-or-later -- -Ghost = {} +Ghost = { + object_address = 0 +} ---@class GhostFrame ---@field global_timer integer @@ -24,14 +26,21 @@ local frame = 0 local recording_base_frame = nil local last_global_timer = nil +local OBJECT_EXTRA_MAGIC = 0x4F424A54 +local non_mario_graphics = nil +local animation_switches = { } +local last_recorded_animation = nil + local OBJ_POSITION_OFFSET = 0x20 -local OBJ_ANIMATION_OFFSET = 0x38 +local OBJ_ANIMATION_ID_OFFSET = 0x38 +local OBJ_ANIMATION_OFFSET = 0x3C local OBJ_ANIMATION_TIMER_OFFSET = 0x40 local OBJ_PITCH_OFFSET = 0x1A local OBJ_YAW_OFFSET = 0x1C local OBJ_ROLL_OFFSET = 0x1E local function writebytes32(f, x) + if x == nil then error("lol", 2) end local b4 = string.char(x % 256) x = (x - x % 256) / 256 local b3 = string.char(x % 256) @@ -82,6 +91,19 @@ local function flush() writebytes32(file, value.roll) end + if non_mario_graphics then + writebytes32(file, OBJECT_EXTRA_MAGIC) + writebytes32(file, non_mario_graphics) + print("lol") + local count = 0 + for _ in pairs(animation_switches) do count = count + 1 end + writebytes32(file, count) + for k, v in pairs(animation_switches) do + writebytes32(file, k) + writebytes32(file, v) + end + end + file:close() return true @@ -99,7 +121,7 @@ function Ghost.update() end local address_source = Addresses[Settings.address_source_index] - local mario_obj = memory.readdword(address_source.mario_object_pointer) + local mario_obj = Ghost.object_address or memory.readdword(address_source.mario_object_pointer) local global_timer = memory.readdword(address_source.global_timer) if recording_base_frame == nil then @@ -116,9 +138,15 @@ function Ghost.update() x = memory.readdword(mario_obj + OBJ_POSITION_OFFSET), y = memory.readdword(mario_obj + OBJ_POSITION_OFFSET + 4), z = memory.readdword(mario_obj + OBJ_POSITION_OFFSET + 8), - animation_index = memory.readword(mario_obj + OBJ_ANIMATION_OFFSET), + animation_index = memory.readword(mario_obj + OBJ_ANIMATION_ID_OFFSET), animation_timer = memory.readword(mario_obj + OBJ_ANIMATION_TIMER_OFFSET) - 1, } + + local animation = memory.readdword(mario_obj + OBJ_ANIMATION_OFFSET) + if animation ~= last_recorded_animation then + last_recorded_animation = animation + animation_switches[#frames - 1] = animation + end end end @@ -153,6 +181,8 @@ function Ghost.start_recording() end is_recording = true + non_mario_graphics = Ghost.object_address and memory.readdword(Ghost.object_address + 0x14) or 0 + last_recorded_animation = nil return true end diff --git a/src/views/Tools.lua b/src/views/Tools.lua index 2af60ccd..acdef4fb 100644 --- a/src/views/Tools.lua +++ b/src/views/Tools.lua @@ -17,6 +17,7 @@ local UID = UIDProvider.allocate_once('Tools', function(enum_next) RngUse = enum_next(), RngValue = enum_next(4), Dump = enum_next(), + GhostObjectAddress = enum_next(), RecordGhost = enum_next(), WorldVisualizer = enum_next(), AutoFirsties = enum_next(), @@ -114,6 +115,12 @@ return { align_y = BreitbandGraphics.alignment.center, }) + Ghost.object_address = tonumber(ugui.textbox({ + uid = UID.GhostObjectAddress, + rectangle = grid_rect(4, GHOST_ROW, 4, 1), + text = string.format("%x", Ghost.object_address or 0), + }):gsub("[^%x]", ""), 16) + if ugui.button({ uid = UID.RecordGhost, rectangle = grid_rect(0, GHOST_ROW, 4, 1), From 3d76e87d36a2c7d5d1b5d673356b34273fda4dac Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Fri, 14 Aug 2026 23:17:24 +0200 Subject: [PATCH 2/3] add tooltip --- src/core/Locales.lua | 1 + src/res/lang/en_US.lua | 1 + src/res/lang/fr_FR.lua | 1 + src/views/Tools.lua | 1 + 4 files changed, 4 insertions(+) diff --git a/src/core/Locales.lua b/src/core/Locales.lua index 5ca974ea..705496fa 100644 --- a/src/core/Locales.lua +++ b/src/core/Locales.lua @@ -141,6 +141,7 @@ Locales = {} ---@field public TOOLS_RNG_USE_INDEX string ---@field public TOOLS_DUMPING string ---@field public TOOLS_GHOST string +---@field public TOOLS_GHOST_OBJECT_ADDRESS_TOOL_TIP string ---@field public TOOLS_GHOST_START string ---@field public TOOLS_GHOST_STOP string ---@field public TOOLS_GHOST_START_RECORDING_FAILED string diff --git a/src/res/lang/en_US.lua b/src/res/lang/en_US.lua index 1af699fe..407d917d 100644 --- a/src/res/lang/en_US.lua +++ b/src/res/lang/en_US.lua @@ -179,6 +179,7 @@ This action cannot be undone. TOOLS_RNG_USE_INDEX = 'Use Index', TOOLS_DUMPING = 'Dumping', TOOLS_GHOST = 'Ghost', + TOOLS_GHOST_OBJECT_ADDRESS_TOOL_TIP = 'Address of the object to record (e.g. 8033FF48). If 0, Mario is recorded.', TOOLS_GHOST_START = 'Start Recording', TOOLS_GHOST_STOP = 'Stop Recording', TOOLS_GHOST_START_RECORDING_FAILED = 'Failed to start ghost recording.', diff --git a/src/res/lang/fr_FR.lua b/src/res/lang/fr_FR.lua index 9ae834a7..508d49d9 100644 --- a/src/res/lang/fr_FR.lua +++ b/src/res/lang/fr_FR.lua @@ -178,6 +178,7 @@ Cette action est irréversible. TOOLS_DUMPING = 'Export', TOOLS_EXPERIMENTS = 'Expériences', TOOLS_GHOST = 'Fantôme', + TOOLS_GHOST_OBJECT_ADDRESS_TOOL_TIP = 'Adresse de l’objet à enregistrer (par exemple 8033FF48). Si 0, Mario est enregistré.', TOOLS_GHOST_START = 'Démarrer rec.', TOOLS_GHOST_STOP = 'Arrêter rec.', TOOLS_GHOST_START_RECORDING_FAILED = 'Échec du démarrage de l\'enregistrement fantôme.', diff --git a/src/views/Tools.lua b/src/views/Tools.lua index acdef4fb..81ec4647 100644 --- a/src/views/Tools.lua +++ b/src/views/Tools.lua @@ -119,6 +119,7 @@ return { uid = UID.GhostObjectAddress, rectangle = grid_rect(4, GHOST_ROW, 4, 1), text = string.format("%x", Ghost.object_address or 0), + tooltip = Locales.str('TOOLS_GHOST_OBJECT_ADDRESS_TOOL_TIP') }):gsub("[^%x]", ""), 16) if ugui.button({ From c17888e231a4e7963c12cbf4e8fcc009d9012082 Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:32:29 +0200 Subject: [PATCH 3/3] remove debug lines --- src/core/Ghost.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/Ghost.lua b/src/core/Ghost.lua index 878f7ea7..753375fb 100644 --- a/src/core/Ghost.lua +++ b/src/core/Ghost.lua @@ -40,7 +40,6 @@ local OBJ_YAW_OFFSET = 0x1C local OBJ_ROLL_OFFSET = 0x1E local function writebytes32(f, x) - if x == nil then error("lol", 2) end local b4 = string.char(x % 256) x = (x - x % 256) / 256 local b3 = string.char(x % 256) @@ -94,7 +93,6 @@ local function flush() if non_mario_graphics then writebytes32(file, OBJECT_EXTRA_MAGIC) writebytes32(file, non_mario_graphics) - print("lol") local count = 0 for _ in pairs(animation_switches) do count = count + 1 end writebytes32(file, count)