From ace0b9a0b319ccb714ae75346b38da03a59de1c9 Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 16 Feb 2026 17:09:44 +0100 Subject: [PATCH] Add "plugins details" command --- source/ShellCommands.cpp | 434 +++++++++++++++++- source/plugin/ButtonComboManager.cpp | 24 + source/plugin/ButtonComboManager.h | 10 +- source/plugin/PluginContainer.cpp | 11 + source/plugin/PluginContainer.h | 3 + source/utils/buttoncombo/ButtonComboUtils.cpp | 10 + source/utils/buttoncombo/ButtonComboUtils.h | 4 + source/utils/utils.cpp | 21 +- source/utils/utils.h | 2 + 9 files changed, 513 insertions(+), 6 deletions(-) diff --git a/source/ShellCommands.cpp b/source/ShellCommands.cpp index f9231c3..a8910a6 100644 --- a/source/ShellCommands.cpp +++ b/source/ShellCommands.cpp @@ -1,8 +1,14 @@ #include "ShellCommands.h" #include "globals.h" +#include "plugin/ButtonComboManager.h" +#include "plugin/FunctionData.h" +#include "plugin/HookData.h" #include "plugin/PluginContainer.h" #include "plugin/PluginData.h" +#include "plugin/SectionInfo.h" +#include "utils/StringTools.h" +#include "utils/utils.h" #include @@ -11,7 +17,327 @@ #include #include #include +#include +namespace { + std::string toString(WUPSButtonCombo_ComboType type) { + switch (type) { + case WUPS_BUTTON_COMBO_COMBO_TYPE_INVALID: + return "Invalid"; + case WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD: + return "Hold"; + case WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD_OBSERVER: + return "Hold (Observer)"; + case WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN: + return "Press Down"; + case WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN_OBSERVER: + return "Press Down (Observer)"; + } + return "invalid"; + } + + std::string toString(WUPSButtonCombo_ComboStatus type) { + switch (type) { + case WUPS_BUTTON_COMBO_COMBO_STATUS_INVALID_STATUS: + return "Invalid"; + case WUPS_BUTTON_COMBO_COMBO_STATUS_VALID: + return "Valid"; + case WUPS_BUTTON_COMBO_COMBO_STATUS_CONFLICT: + return "Conflict"; + } + return "Invalid"; + } + + + std::string toString(const function_replacement_library_type_t type) { + switch (type) { + case LIBRARY_AVM: + return "AVM"; + case LIBRARY_CAMERA: + return "CAMERA"; + case LIBRARY_COREINIT: + return "COREINIT"; + case LIBRARY_DC: + return "DC"; + case LIBRARY_DMAE: + return "DMAE"; + case LIBRARY_DRMAPP: + return "DRMAPP"; + case LIBRARY_ERREULA: + return "ERREULA"; + case LIBRARY_GX2: + return "GX2"; + case LIBRARY_H264: + return "H264"; + case LIBRARY_LZMA920: + return "LZMA920"; + case LIBRARY_MIC: + return "MIC"; + case LIBRARY_NFC: + return "NFC"; + case LIBRARY_NIO_PROF: + return "NIO_PROF"; + case LIBRARY_NLIBCURL: + return "NLIBCURL"; + case LIBRARY_NLIBNSS: + return "NLIBNSS"; + case LIBRARY_NLIBNSS2: + return "NLIBNSS2"; + case LIBRARY_NN_AC: + return "NN_AC"; + case LIBRARY_NN_ACP: + return "NN_ACP"; + case LIBRARY_NN_ACT: + return "NN_ACT"; + case LIBRARY_NN_AOC: + return "NN_AOC"; + case LIBRARY_NN_BOSS: + return "NN_BOSS"; + case LIBRARY_NN_CCR: + return "NN_CCR"; + case LIBRARY_NN_CMPT: + return "NN_CMPT"; + case LIBRARY_NN_DLP: + return "NN_DLP"; + case LIBRARY_NN_EC: + return "NN_EC"; + case LIBRARY_NN_FP: + return "NN_FP"; + case LIBRARY_NN_HAI: + return "NN_HAI"; + case LIBRARY_NN_HPAD: + return "NN_HPAD"; + case LIBRARY_NN_IDBE: + return "NN_IDBE"; + case LIBRARY_NN_NDM: + return "NN_NDM"; + case LIBRARY_NN_NETS2: + return "NN_NETS2"; + case LIBRARY_NN_NFP: + return "NN_NFP"; + case LIBRARY_NN_NIM: + return "NN_NIM"; + case LIBRARY_NN_OLV: + return "NN_OLV"; + case LIBRARY_NN_PDM: + return "NN_PDM"; + case LIBRARY_NN_SAVE: + return "NN_SAVE"; + case LIBRARY_NN_SL: + return "NN_SL"; + case LIBRARY_NN_SPM: + return "NN_SPM"; + case LIBRARY_NN_TEMP: + return "NN_TEMP"; + case LIBRARY_NN_UDS: + return "NN_UDS"; + case LIBRARY_NN_VCTL: + return "NN_VCTL"; + case LIBRARY_NSYSCCR: + return "NSYSCCR"; + case LIBRARY_NSYSHID: + return "NSYSHID"; + case LIBRARY_NSYSKBD: + return "NSYSKBD"; + case LIBRARY_NSYSNET: + return "NSYSNET"; + case LIBRARY_NSYSUHS: + return "NSYSUHS"; + case LIBRARY_NSYSUVD: + return "NSYSUVD"; + case LIBRARY_NTAG: + return "NTAG"; + case LIBRARY_PADSCORE: + return "PADSCORE"; + case LIBRARY_PROC_UI: + return "PROC_UI"; + case LIBRARY_SND_CORE: + return "SND_CORE"; + case LIBRARY_SND_USER: + return "SND_USER"; + case LIBRARY_SNDCORE2: + return "SNDCORE2"; + case LIBRARY_SNDUSER2: + return "SNDUSER2"; + case LIBRARY_SWKBD: + return "SWKBD"; + case LIBRARY_SYSAPP: + return "SYSAPP"; + case LIBRARY_TCL: + return "TCL"; + case LIBRARY_TVE: + return "TVE"; + case LIBRARY_UAC: + return "UAC"; + case LIBRARY_UAC_RPL: + return "UAC_RPL"; + case LIBRARY_USB_MIC: + return "USB_MIC"; + case LIBRARY_UVC: + return "UVC"; + case LIBRARY_UVD: + return "UVD"; + case LIBRARY_VPAD: + return "VPAD"; + case LIBRARY_VPADBASE: + return "VPADBASE"; + case LIBRARY_ZLIB125: + return "ZLIB125"; + case LIBRARY_OTHER: + return "OTHER"; + } + return "OTHER"; + } + + const char *getButtonChar(const WUPSButtonCombo_Buttons value) { + std::string combo; + if (value & WUPS_BUTTON_COMBO_BUTTON_A) { + return "A"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_B) { + return "B"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_X) { + return "X"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_Y) { + return "Y"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_L) { + return "L"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_R) { + return "R"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_ZL) { + return "ZL"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_ZR) { + return "ZR"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_UP) { + return "UP"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_DOWN) { + return "DOWN"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_LEFT) { + return "LEFT"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_RIGHT) { + return "RIGHT"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_STICK_L) { + return "STICK-L"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_STICK_R) { + return "STICK-R"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_PLUS) { + return "PLUS"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_MINUS) { + return "MINUS"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_TV) { + return "TV"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_RESERVED_BIT) { + return "RESERVED-BIT"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_1) { + return "1"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_2) { + return "2"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_C) { + return "C"; + } + if (value & WUPS_BUTTON_COMBO_BUTTON_Z) { + return "Z"; + } + return ""; + } + + std::string getComboAsString(const uint32_t value) { + char comboString[60] = {}; + + for (uint32_t i = 0; i < 32; i++) { + uint32_t bitMask = 1 << i; + if (value & bitMask) { + auto val = getButtonChar(static_cast(bitMask)); + if (val[0] != '\0') { + strcat(comboString, val); + strcat(comboString, "+"); + } + } + } + std::string res(comboString); + if (res.ends_with("+")) { + res.pop_back(); + } + return res; + } + + std::string getMaskAsString(WUPSButtonCombo_ControllerTypes controller_mask) { + if (controller_mask == WUPS_BUTTON_COMBO_CONTROLLER_NONE) { + return "NONE"; + } + if (controller_mask == WUPS_BUTTON_COMBO_CONTROLLER_ALL) { + return "ALL"; + } + // Optional: Check strictly for full groups if you prefer that over listing individual bits + if (controller_mask == WUPS_BUTTON_COMBO_CONTROLLER_VPAD) { + return "VPAD (All)"; + } + if (controller_mask == WUPS_BUTTON_COMBO_CONTROLLER_WPAD) { + return "WPAD (All)"; + } + std::vector parts; + + // VPADs + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_VPAD_0) parts.emplace_back("VPAD_0"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_VPAD_1) parts.emplace_back("VPAD_1"); + + // WPADs + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_0) parts.emplace_back("WPAD_0"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_1) parts.emplace_back("WPAD_1"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_2) parts.emplace_back("WPAD_2"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_3) parts.emplace_back("WPAD_3"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_4) parts.emplace_back("WPAD_4"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_5) parts.emplace_back("WPAD_5"); + if (controller_mask & WUPS_BUTTON_COMBO_CONTROLLER_WPAD_6) parts.emplace_back("WPAD_6"); + + + if (parts.empty()) { + return "UNKNOWN"; + } + + std::string result; + for (size_t i = 0; i < parts.size(); ++i) { + if (i > 0) { + result += " | "; + } + result += parts[i]; + } + + return result; + } + + bool isHoldCombo(WUPSButtonCombo_ComboType type) { + switch (type) { + case WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD: + case WUPS_BUTTON_COMBO_COMBO_TYPE_HOLD_OBSERVER: + return true; + case WUPS_BUTTON_COMBO_COMBO_TYPE_INVALID: + case WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN: + case WUPS_BUTTON_COMBO_COMBO_TYPE_PRESS_DOWN_OBSERVER: + return false; + } + return false; + } +} // namespace namespace ShellCommands { namespace { class ConsoleTable { @@ -164,7 +490,6 @@ namespace ShellCommands { table.Print(); } - void ListPlugins(int argc, char **argv) { bool showAll = false; if (argc > 1 && (std::string_view(argv[1]) == "-a" || std::string_view(argv[1]) == "--all")) { @@ -173,7 +498,7 @@ namespace ShellCommands { ConsoleTable table; - // Define Columns + table.AddColumn("Index", ConsoleTable::LEFT); table.AddColumn("Name", ConsoleTable::LEFT); table.AddColumn("Author", ConsoleTable::LEFT); table.AddColumn("Version", ConsoleTable::LEFT); @@ -184,13 +509,15 @@ namespace ShellCommands { table.AddColumn("Memory footprint", ConsoleTable::RIGHT); table.AddColumn("Heap usage", ConsoleTable::RIGHT); uint32_t totalSizeOther = 0; + uint32_t id = 0; for (const auto &plugin : gLoadedPlugins) { if (!showAll && !plugin.isLinkedAndLoaded()) { totalSizeOther += plugin.getMemoryFootprint(); + id++; continue; } - auto meta = plugin.getMetaInformation(); + auto &meta = plugin.getMetaInformation(); std::string heapUsage = "unknown"; if (const auto tracking = plugin.getTrackingMemoryAllocator()) { @@ -202,6 +529,7 @@ namespace ShellCommands { } std::vector rowData; + rowData.emplace_back(std::to_string(id)); rowData.emplace_back(meta.getName()); rowData.emplace_back(meta.getAuthor()); rowData.emplace_back(meta.getVersion()); @@ -213,6 +541,7 @@ namespace ShellCommands { rowData.emplace_back(heapUsage); table.AddRow(rowData); + id++; } if (totalSizeOther > 0 && !showAll) { @@ -231,12 +560,111 @@ namespace ShellCommands { table.Print(); } + void PluginDetails(std::optional idOpt) { + uint32_t id = 0; + for (const auto &plugin : gLoadedPlugins) { + if (idOpt) { + if (*idOpt != id) { + id++; + continue; + } + } + auto &meta = plugin.getMetaInformation(); + OSReport("\n"); + OSReport("Index: %d\n", id); + OSReport("Name: %s\n", meta.getName().c_str()); + OSReport("Description: %s\n", meta.getDescription().c_str()); + OSReport("Author: %s\n", meta.getAuthor().c_str()); + OSReport("Version: %s\n", meta.getVersion().c_str()); + OSReport("Build date: %s\n", meta.getBuildTimestamp().c_str()); + OSReport("Storage Id: %s\n", meta.getStorageId().c_str()); + OSReport("Active: %s\n", plugin.isLinkedAndLoaded() ? "Yes" : "No"); + OSReport("API: %s\n", meta.getWUPSVersion().toString().c_str()); + + const auto memoryFootprint = plugin.getMemoryFootprint(); + const auto pluginSize = plugin.getPluginDataCopy()->getBuffer().size_bytes(); + size_t textSize = 0; + size_t dataSize = 0; + + OSReport("Memory footprint: ~%s\n", BytesToHumanReadable(memoryFootprint).c_str()); + OSReport("\t- .wps: ~%s\n", BytesToHumanReadable(pluginSize).c_str()); + if (plugin.isLinkedAndLoaded()) { + textSize = plugin.getPluginLinkInformation().getTextMemory().size(); + dataSize = plugin.getPluginLinkInformation().getDataMemory().size(); + OSReport("\t- CODE: ~%s\n", BytesToHumanReadable(textSize).c_str()); + OSReport("\t- DATA: ~%s\n", BytesToHumanReadable(dataSize).c_str()); + } + const auto otherSize = memoryFootprint - pluginSize - textSize - dataSize; + OSReport("\t- Other: ~%s\n", BytesToHumanReadable(otherSize).c_str()); + OSReport("\n"); + const auto §ionInfoList = plugin.getPluginLinkInformation().getSectionInfoList(); + OSReport("Sections: %d\n", sectionInfoList.size()); + for (const auto §ionInfo : sectionInfoList) { + OSReport("\t- 0x%08X - 0x%08X %-15s %-11s\n", sectionInfo.second.getAddress(), sectionInfo.second.getAddress() + sectionInfo.second.getSize(), sectionInfo.first.c_str(), BytesToHumanReadable(sectionInfo.second.getSize()).c_str()); + } + OSReport("\n"); + + const auto &hookList = plugin.getPluginLinkInformation().getHookDataList(); + OSReport("WUPS Hooks: %d\n", hookList.size()); + for (const auto &hook : hookList) { + OSReport("\t- %p - %s\n", hook.getFunctionPointer(), hookNameToString(hook.getType()).c_str()); + } + OSReport("\n"); + const auto &buttonCombos = plugin.GetButtonComboData(); + OSReport("Button combos: %d\n", buttonCombos.size()); + for (const auto &combo : buttonCombos) { + OSReport("\t- \"%s\" \n", combo.label.c_str()); + OSReport("\t\tStatus: %s\n", toString(combo.status).c_str()); + OSReport("\t\tCallback: %p (%s)\n", combo.callbackOptions.callback, combo.callbackOptions.callback != nullptr ? getModuleAndSymbolName(reinterpret_cast(combo.callbackOptions.callback)).c_str() : ""); + OSReport("\t\tContext: %p\n", combo.callbackOptions.context); + OSReport("\t\tType: %s\n", toString(combo.buttonComboOptions.type).c_str()); + if (isHoldCombo(combo.buttonComboOptions.type)) { + OSReport("\t\tHold duration: %d\n", combo.buttonComboOptions.optionalHoldForXMs); + } + OSReport("\t\tCombo: %s\n", getComboAsString(combo.buttonComboOptions.basicCombo.combo).c_str()); + OSReport("\t\tController Mask: %s\n", getMaskAsString(combo.buttonComboOptions.basicCombo.controllerMask).c_str()); + } + OSReport("\n"); + const auto &functionPatches = plugin.getPluginLinkInformation().getFunctionDataList(); + OSReport("Function patches: %d\n", functionPatches.size()); + for (const auto &function : functionPatches) { + if (function.getPhysicalAddress() != nullptr) { + OSReport("\t- Hook: %p - PA: %p VA: %p\n", function.getReplaceAddress(), function.getPhysicalAddress(), function.getVirtualAddress()); + } else { + OSReport("\t- Hook: %p - %-9s - %s\n", function.getReplaceAddress(), toString(function.getLibrary()).c_str(), function.getName().c_str()); + } + } + + OSReport("\n"); + OSReport("Heap usage:\n"); + if (const auto tracking = plugin.getTrackingMemoryAllocator(); tracking != nullptr) { + if (const auto stats = tracking->GetHeapMemoryUsageSnapshot(); stats) { + OSReport("\t- Currently allocated: %s\n", BytesToHumanReadable(stats->currentAllocated).c_str()); + OSReport("\t- Peak allocated: %s\n", BytesToHumanReadable(stats->peakAllocated).c_str()); + OSReport("\t- Current allocations: %d\n", stats->allocationMap.size()); + OSReport("\t- Total allocations: %d\n", stats->allocCount); + OSReport("\t- Total frees: %d\n", stats->freeCount); + } + } else { + OSReport("\t Not tracked.\n"); + } + + OSReport("\n=================\n"); + + id++; + if (idOpt) { + break; + } + } + } + void Init() { sPluginGroup = std::make_unique("plugins", "Manage aroma plugins"); sPluginGroup->AddCommand("heap_usage", PrintHeapUsage, "Show current heap usage for tracked plugins"); sPluginGroup->AddRawCommand("list", ListPlugins, "Lists active plugins", "Usage: \"list -a\" to list all plugins"); + sPluginGroup->AddCommand("details", PluginDetails, "Shows details for plugins"); sPluginCmdHandle = sPluginGroup->Register(); } diff --git a/source/plugin/ButtonComboManager.cpp b/source/plugin/ButtonComboManager.cpp index e2134e6..a73aead 100644 --- a/source/plugin/ButtonComboManager.cpp +++ b/source/plugin/ButtonComboManager.cpp @@ -598,4 +598,28 @@ WUPSButtonCombo_Error ButtonComboManager::ExecuteForWrapper(const WUPSButtonComb uint32_t ButtonComboManager::getHandle() const { return *mHandle; +} + +std::vector ButtonComboManager::GetButtonCombos() const { + std::vector result; + for (auto &wrapper : mComboWrappers) { + ButtonComboInfo res; + char text[256] = {}; + WUPSButtonCombo_MetaOptionsOut meta = {text, sizeof(text)}; + if (wrapper.GetButtonComboCallback(res.callbackOptions) != WUPS_BUTTON_COMBO_ERROR_SUCCESS) { + continue; + } + if (wrapper.GetButtonComboInfoEx(res.buttonComboOptions) != WUPS_BUTTON_COMBO_ERROR_SUCCESS) { + continue; + } + if (wrapper.GetButtonComboMeta(meta) != WUPS_BUTTON_COMBO_ERROR_SUCCESS) { + continue; + } + if (wrapper.GetButtonComboStatus(res.status) != WUPS_BUTTON_COMBO_ERROR_SUCCESS) { + continue; + } + res.label = text; + result.push_back(res); + } + return result; } \ No newline at end of file diff --git a/source/plugin/ButtonComboManager.h b/source/plugin/ButtonComboManager.h index ceb3b3f..21813f2 100644 --- a/source/plugin/ButtonComboManager.h +++ b/source/plugin/ButtonComboManager.h @@ -10,12 +10,18 @@ class ButtonComboWrapper; +struct ButtonComboInfo { + std::string label; + WUPSButtonCombo_CallbackOptions callbackOptions; + WUPSButtonCombo_ButtonComboInfoEx buttonComboOptions; + WUPSButtonCombo_ComboStatus status; +}; + class ButtonComboManager { public: explicit ButtonComboManager(); ~ButtonComboManager(); - ButtonComboManager(const ButtonComboManager &) = delete; ButtonComboManager(ButtonComboManager &&src) noexcept; @@ -67,6 +73,8 @@ public: [[nodiscard]] uint32_t getHandle() const; + [[nodiscard]] std::vector GetButtonCombos() const; + private: std::forward_list mComboWrappers; std::unique_ptr mHandle = std::make_unique(); diff --git a/source/plugin/PluginContainer.cpp b/source/plugin/PluginContainer.cpp index b21ebce..4beea4d 100644 --- a/source/plugin/PluginContainer.cpp +++ b/source/plugin/PluginContainer.cpp @@ -1,5 +1,6 @@ #include "PluginContainer.h" +#include "plugin/ButtonComboManager.h" #include "plugin/FunctionData.h" #include "plugin/HookData.h" #include "plugin/PluginConfigData.h" @@ -8,6 +9,7 @@ #include "plugin/RelocationData.h" #include "plugin/SectionInfo.h" +#include "plugin/ButtonComboManager.h" #include "utils/buttoncombo/ButtonComboUtils.h" #include "utils/logger.h" #include "utils/storage/StorageUtils.h" @@ -135,6 +137,7 @@ void PluginContainer::InitButtonComboData() { } mButtonComboManagerHandle = ButtonComboUtils::API::Internal::CreateButtonComboData(); } + void PluginContainer::DeinitButtonComboData() { if (getMetaInformation().getWUPSVersion() < WUPSVersion(0, 8, 2)) { return; @@ -142,6 +145,14 @@ void PluginContainer::DeinitButtonComboData() { ButtonComboUtils::API::Internal::RemoveButtonComboData(mButtonComboManagerHandle); } + +std::vector PluginContainer::GetButtonComboData() const { + if (getMetaInformation().getWUPSVersion() < WUPSVersion(0, 8, 2)) { + return {}; + } + return ButtonComboUtils::API::Internal::GetButtonComboData(mButtonComboManagerHandle); +} + uint32_t PluginContainer::getButtonComboManagerHandle() const { return mButtonComboManagerHandle; } diff --git a/source/plugin/PluginContainer.h b/source/plugin/PluginContainer.h index b3e043e..5e917e5 100644 --- a/source/plugin/PluginContainer.h +++ b/source/plugin/PluginContainer.h @@ -27,6 +27,8 @@ #include #include + +struct ButtonComboInfo; class PluginData; class PluginContainer { @@ -67,6 +69,7 @@ public: void InitButtonComboData(); void DeinitButtonComboData(); + std::vector GetButtonComboData() const; [[nodiscard]] uint32_t getButtonComboManagerHandle() const; diff --git a/source/utils/buttoncombo/ButtonComboUtils.cpp b/source/utils/buttoncombo/ButtonComboUtils.cpp index e606870..afadc8d 100644 --- a/source/utils/buttoncombo/ButtonComboUtils.cpp +++ b/source/utils/buttoncombo/ButtonComboUtils.cpp @@ -24,6 +24,16 @@ namespace ButtonComboUtils::API { DEBUG_FUNCTION_LINE_WARN("Tried to remove ButtonComboManager by invalid handle: %08X", buttonComboManagerHandle); } } + + std::vector GetButtonComboData(uint32_t buttonComboManagerHandle) { + std::lock_guard lock(sButtonComboMutex); + for (auto &manager : sButtonComboManager) { + if (manager.getHandle() == buttonComboManagerHandle) { + return manager.GetButtonCombos(); + } + } + return {}; + } } // namespace Internal namespace { diff --git a/source/utils/buttoncombo/ButtonComboUtils.h b/source/utils/buttoncombo/ButtonComboUtils.h index aa3ae67..3c06f08 100644 --- a/source/utils/buttoncombo/ButtonComboUtils.h +++ b/source/utils/buttoncombo/ButtonComboUtils.h @@ -3,11 +3,15 @@ #include #include +#include + +struct ButtonComboInfo; namespace ButtonComboUtils::API { namespace Internal { uint32_t CreateButtonComboData(); void RemoveButtonComboData(uint32_t buttonComboManagerHandle); + std::vector GetButtonComboData(uint32_t buttonComboManagerHandle); } // namespace Internal WUPSButtonCombo_Error AddButtonCombo(void *identifier, diff --git a/source/utils/utils.cpp b/source/utils/utils.cpp index cc65988..77e5359 100644 --- a/source/utils/utils.cpp +++ b/source/utils/utils.cpp @@ -236,6 +236,23 @@ CaptureStackTrace(uint32_t maxDepth) { #define SC17_FindClosestSymbol ((uint32_t(*)(uint32_t addr, int32_t * outDistance, char *symbolNameBuffer, uint32_t symbolNameBufferLength, char *moduleNameBuffer, uint32_t moduleNameBufferLength))(0x101C400 + 0x1f934)) +std::string getModuleAndSymbolName(uint32_t addr) { + int distance = 0; + char moduleName[50] = {}; + char symbolName[256] = {}; + + if (SC17_FindClosestSymbol(addr, &distance, symbolName, sizeof(symbolName) - 1, moduleName, sizeof(moduleName) - 1) != 0) { + return string_format("0x%08X", addr); + } else { + moduleName[sizeof(moduleName) - 1] = '\0'; + symbolName[sizeof(symbolName) - 1] = '\0'; + return string_format("%s|%s+0x%X", + moduleName, + symbolName, + distance); + } +} + void PrintCapturedStackTrace(std::span trace) { if (trace.empty()) { DEBUG_FUNCTION_LINE_INFO("┌────────────────────── CAPTURED TRACE ──────────────────────┐"); @@ -248,8 +265,8 @@ void PrintCapturedStackTrace(std::span trace) { for (size_t i = 0; i < trace.size(); ++i) { uint32_t addr = trace[i]; int distance = 0; - char moduleName[100] = {}; - char symbolName[100] = {}; + char moduleName[50] = {}; + char symbolName[256] = {}; if (SC17_FindClosestSymbol(addr, &distance, symbolName, sizeof(symbolName) - 1, moduleName, sizeof(moduleName) - 1) != 0) { DEBUG_FUNCTION_LINE_INFO("│ [%02d] 0x%08X", i, addr); diff --git a/source/utils/utils.h b/source/utils/utils.h index 08fec0b..c227179 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -167,6 +167,8 @@ std::vector getNonBaseAromaPluginFilenames(std::string_view basePat std::vector CaptureStackTrace(uint32_t maxDepth); +std::string getModuleAndSymbolName(uint32_t addr); + void PrintCapturedStackTrace(std::span trace); std::string hookNameToString(wups_loader_hook_type_t type); \ No newline at end of file