From c70740fcdfb58cffd4a3a474d290fbea9fc3aa1e Mon Sep 17 00:00:00 2001 From: Kelsi Date: Tue, 17 Mar 2026 21:29:09 -0700 Subject: [PATCH] feat: wire Warden funcList_ dispatchers and implement PacketHandler call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously initializeModule() read the 4 WardenFuncList function addresses from emulated memory, logged them, then discarded them — funcList_ was never populated, so tick(), generateRC4Keys(), and processCheckRequest() were permanently no-ops even when the Unicorn emulator successfully ran the module. Changes: - initializeModule() now wraps each non-null emulated function address in a std::function lambda that marshals args to/from emulated memory via emulator_->writeData/callFunction/freeMemory - generateRC4Keys: copies 4-byte seed to emulated space, calls function - unload: calls function with NULL (module saves own RC4 state) - tick: direct uint32_t(deltaMs) dispatch, returns emulated EAX - packetHandler: 2-arg variant for generic callers - Stores emulatedPacketHandlerAddr_ for full 4-arg call in processCheckRequest - processCheckRequest() now calls the emulated PacketHandler with the proper 4-argument stdcall convention: (data, size, responseOut, responseSizeOut), reads back the response size and bytes, returns them in responseOut - unload() resets emulatedPacketHandlerAddr_ to 0 for clean re-initialization - Remove dead no-op renderObjectiveTracker() (no call sites, superseded) --- include/game/warden_module.hpp | 1 + include/ui/game_screen.hpp | 1 - src/game/warden_module.cpp | 112 +++++++++++++++++++++++++++------ src/ui/game_screen.cpp | 6 +- 4 files changed, 94 insertions(+), 26 deletions(-) diff --git a/include/game/warden_module.hpp b/include/game/warden_module.hpp index bcea989f..e11bc4f9 100644 --- a/include/game/warden_module.hpp +++ b/include/game/warden_module.hpp @@ -140,6 +140,7 @@ private: size_t relocDataOffset_ = 0; // Offset into decompressedData_ where relocation data starts WardenFuncList funcList_; // Callback functions std::unique_ptr emulator_; // Cross-platform x86 emulator + uint32_t emulatedPacketHandlerAddr_ = 0; // Raw emulated VA for 4-arg PacketHandler call // Validation and loading steps bool verifyMD5(const std::vector& data, diff --git a/include/ui/game_screen.hpp b/include/ui/game_screen.hpp index 603aba7d..0e73c552 100644 --- a/include/ui/game_screen.hpp +++ b/include/ui/game_screen.hpp @@ -379,7 +379,6 @@ private: void renderGuildBankWindow(game::GameHandler& gameHandler); void renderAuctionHouseWindow(game::GameHandler& gameHandler); void renderDungeonFinderWindow(game::GameHandler& gameHandler); - void renderObjectiveTracker(game::GameHandler& gameHandler); void renderInstanceLockouts(game::GameHandler& gameHandler); void renderNameplates(game::GameHandler& gameHandler); void renderBattlegroundScore(game::GameHandler& gameHandler); diff --git a/src/game/warden_module.cpp b/src/game/warden_module.cpp index 9f577978..f93dc300 100644 --- a/src/game/warden_module.cpp +++ b/src/game/warden_module.cpp @@ -161,24 +161,53 @@ bool WardenModule::processCheckRequest(const std::vector& checkData, } try { - // Call module's PacketHandler - // void PacketHandler(uint8_t* checkData, size_t checkSize, - // uint8_t* responseOut, size_t* responseSizeOut) - LOG_INFO("WardenModule: Calling PacketHandler..."); + if (emulatedPacketHandlerAddr_ == 0) { + LOG_ERROR("WardenModule: PacketHandler address not set (module not fully initialized)"); + emulator_->freeMemory(checkDataAddr); + emulator_->freeMemory(responseAddr); + return false; + } - // For now, this is a placeholder - actual calling would depend on - // the module's exact function signature - LOG_WARNING("WardenModule: PacketHandler execution stubbed"); - LOG_INFO("WardenModule: Would call emulated function to process checks"); - LOG_INFO("WardenModule: This would generate REAL responses (not fakes!)"); + // Allocate uint32_t for responseSizeOut in emulated memory + uint32_t initialSize = 1024; + uint32_t responseSizeAddr = emulator_->writeData(&initialSize, sizeof(uint32_t)); + if (responseSizeAddr == 0) { + LOG_ERROR("WardenModule: Failed to allocate responseSizeAddr"); + emulator_->freeMemory(checkDataAddr); + emulator_->freeMemory(responseAddr); + return false; + } + + // Call: void PacketHandler(uint8_t* data, uint32_t size, + // uint8_t* responseOut, uint32_t* responseSizeOut) + LOG_INFO("WardenModule: Calling emulated PacketHandler..."); + emulator_->callFunction(emulatedPacketHandlerAddr_, { + checkDataAddr, + static_cast(checkData.size()), + responseAddr, + responseSizeAddr + }); + + // Read back response size and data + uint32_t responseSize = 0; + emulator_->readMemory(responseSizeAddr, &responseSize, sizeof(uint32_t)); + emulator_->freeMemory(responseSizeAddr); + + if (responseSize > 0 && responseSize <= 1024) { + responseOut.resize(responseSize); + if (!emulator_->readMemory(responseAddr, responseOut.data(), responseSize)) { + LOG_ERROR("WardenModule: Failed to read response data"); + responseOut.clear(); + } else { + LOG_INFO("WardenModule: PacketHandler wrote ", responseSize, " byte response"); + } + } else { + LOG_WARNING("WardenModule: PacketHandler returned invalid responseSize=", responseSize); + } - // Clean up emulator_->freeMemory(checkDataAddr); emulator_->freeMemory(responseAddr); - - // For now, return false to use fake responses - // Once we have a real module, we'd read the response from responseAddr - return false; + return !responseOut.empty(); } catch (const std::exception& e) { LOG_ERROR("WardenModule: Exception during PacketHandler: ", e.what()); @@ -240,6 +269,7 @@ void WardenModule::unload() { // Clear function pointers funcList_ = {}; + emulatedPacketHandlerAddr_ = 0; loaded_ = false; moduleData_.clear(); @@ -961,7 +991,12 @@ bool WardenModule::initializeModule() { } // Read WardenFuncList structure from emulated memory - // Structure has 4 function pointers (16 bytes) + // Structure has 4 function pointers (16 bytes): + // [0] generateRC4Keys(uint8_t* seed) + // [1] unload(uint8_t* rc4Keys) + // [2] packetHandler(uint8_t* data, uint32_t size, + // uint8_t* responseOut, uint32_t* responseSizeOut) + // [3] tick(uint32_t deltaMs) -> uint32_t uint32_t funcAddrs[4] = {}; if (emulator_->readMemory(result, funcAddrs, 16)) { char fb[4][32]; @@ -973,11 +1008,48 @@ bool WardenModule::initializeModule() { LOG_INFO("WardenModule: packetHandler: ", fb[2]); LOG_INFO("WardenModule: tick: ", fb[3]); - // Store function addresses for later use - // funcList_.generateRC4Keys = ... (would wrap emulator calls) - // funcList_.unload = ... - // funcList_.packetHandler = ... - // funcList_.tick = ... + // Wrap emulated function addresses into std::function dispatchers + WardenEmulator* emu = emulator_.get(); + + if (funcAddrs[0]) { + uint32_t addr = funcAddrs[0]; + funcList_.generateRC4Keys = [emu, addr](uint8_t* seed) { + // Warden RC4 seed is a fixed 4-byte value + uint32_t seedAddr = emu->writeData(seed, 4); + if (seedAddr) { + emu->callFunction(addr, {seedAddr}); + emu->freeMemory(seedAddr); + } + }; + } + + if (funcAddrs[1]) { + uint32_t addr = funcAddrs[1]; + funcList_.unload = [emu, addr]([[maybe_unused]] uint8_t* rc4Keys) { + emu->callFunction(addr, {0u}); // pass NULL; module saves its own state + }; + } + + if (funcAddrs[2]) { + // Store raw address for the 4-arg call in processCheckRequest + emulatedPacketHandlerAddr_ = funcAddrs[2]; + uint32_t addr = funcAddrs[2]; + // Simple 2-arg variant for generic callers (no response extraction) + funcList_.packetHandler = [emu, addr](uint8_t* data, size_t length) { + uint32_t dataAddr = emu->writeData(data, length); + if (dataAddr) { + emu->callFunction(addr, {dataAddr, static_cast(length)}); + emu->freeMemory(dataAddr); + } + }; + } + + if (funcAddrs[3]) { + uint32_t addr = funcAddrs[3]; + funcList_.tick = [emu, addr](uint32_t deltaMs) -> uint32_t { + return emu->callFunction(addr, {deltaMs}); + }; + } } LOG_INFO("WardenModule: Module fully initialized and ready!"); diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index ca5e263d..7b08a08d 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -22421,11 +22421,7 @@ void GameScreen::renderBgScoreboard(game::GameHandler& gameHandler) { ImGui::End(); } -// ─── Quest Objective Tracker (legacy stub — superseded by renderQuestObjectiveTracker) ─── -void GameScreen::renderObjectiveTracker(game::GameHandler&) { - // No-op: consolidated into renderQuestObjectiveTracker which renders the - // full-featured draggable tracker with context menus and item icons. -} + // ─── Book / Scroll / Note Window ────────────────────────────────────────────── void GameScreen::renderBookWindow(game::GameHandler& gameHandler) {