From 3de3fdf7414c6bd5228152b552dbbe73bb11dba4 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Sun, 31 May 2026 19:48:35 +0800 Subject: [PATCH 01/11] Add a simple memory search of exist value in the pause screen By Gemini of Android Studio. Test game: Comic Party Portable Related to #21651 --- CMakeLists.txt | 2 + Core/CwCheat.cpp | 3 + UI/MemoryScanner.cpp | 316 ++++++++++++++++++++++++++++++ UI/MemoryScanner.h | 90 +++++++++ UI/PauseScreen.cpp | 4 + UI/UI.vcxproj | 4 +- UI/UI.vcxproj.filters | 8 +- UWP/UI_UWP/UI_UWP.vcxproj | 4 +- UWP/UI_UWP/UI_UWP.vcxproj.filters | 8 +- android/jni/Android.mk | 1 + 10 files changed, 436 insertions(+), 4 deletions(-) create mode 100644 UI/MemoryScanner.cpp create mode 100644 UI/MemoryScanner.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9736b0347bd8..d037a591a2c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1633,6 +1633,8 @@ list(APPEND NativeAppSource UI/IAPScreen.h UI/MainScreen.h UI/MainScreen.cpp + UI/MemoryScanner.h + UI/MemoryScanner.cpp UI/GameBrowser.h UI/GameBrowser.cpp UI/MiscScreens.h diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 597ea5d4e3b5..c8e18f2b4468 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -12,6 +12,7 @@ #include "Core/CoreTiming.h" #include "Core/CoreParameter.h" #include "Core/CwCheat.h" +#include "UI/MemoryScanner.h" #include "Core/Config.h" #include "Core/MemMapHelpers.h" #include "Core/MIPS/MIPS.h" @@ -327,6 +328,8 @@ void hleCheat(u64 userdata, int cyclesLate) { g_Config.bReloadCheats = false; } cheatEngine->Run(); + + g_MemoryScanner.Update(); } CWCheatEngine::CWCheatEngine(std::string_view gameID) : gameID_(gameID) { diff --git a/UI/MemoryScanner.cpp b/UI/MemoryScanner.cpp new file mode 100644 index 000000000000..8f09495bd676 --- /dev/null +++ b/UI/MemoryScanner.cpp @@ -0,0 +1,316 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include +#include +#include "UI/MemoryScanner.h" +#include "Common/UI/Context.h" +#include "Common/UI/UIScreen.h" +#include "Common/UI/View.h" +#include "Common/UI/ViewGroup.h" +#include "Common/UI/ScrollView.h" +#include "Common/UI/PopupScreens.h" +#include "Common/Data/Text/I18n.h" +#include "Core/MemMap.h" +#include "Core/System.h" +#include "Common/StringUtils.h" + +MemoryScanner g_MemoryScanner; + +void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { + results_.clear(); + uint32_t val = 0; + try { + val = (uint32_t)std::stoul(filter, nullptr, 0); + } catch (...) { + return; + } + + uint32_t startAddr = 0x08000000; + uint32_t endAddr = startAddr + Memory::g_MemorySize; + + for (uint32_t addr = startAddr; addr < endAddr; ) { + bool match = false; + switch (type) { + case ScanValueType::U8: + if (Memory::Read_U8(addr) == (uint8_t)val) match = true; + addr += 1; + break; + case ScanValueType::U16: + if (addr + 2 <= endAddr && Memory::Read_U16(addr) == (uint16_t)val) match = true; + addr += 1; + break; + case ScanValueType::U32: + if (addr + 4 <= endAddr && Memory::Read_U32(addr) == (uint32_t)val) match = true; + addr += 1; + break; + } + + if (match) { + results_.emplace_back(addr - 1, type); + if (results_.size() > 1000) break; + } + } + firstScanDone_ = true; +} + +void MemoryScanner::NextScan(ScanValueType type, const std::string &filter) { + uint32_t val = 0; + try { + val = (uint32_t)std::stoul(filter, nullptr, 0); + } catch (...) { + return; + } + + std::vector nextResults; + for (const auto &res : results_) { + bool match = false; + switch (type) { + case ScanValueType::U8: + if (Memory::Read_U8(res.address) == (uint8_t)val) match = true; + break; + case ScanValueType::U16: + if (Memory::Read_U16(res.address) == (uint16_t)val) match = true; + break; + case ScanValueType::U32: + if (Memory::Read_U32(res.address) == (uint32_t)val) match = true; + break; + } + + if (match) { + nextResults.push_back(res); + } + } + results_ = std::move(nextResults); +} + +void MemoryScanner::Clear() { + results_.clear(); + firstScanDone_ = false; +} + +void MemoryScanner::Update() { + for (auto &res : results_) { + if (res.locked) { + switch (res.type) { + case ScanValueType::U8: + Memory::Write_U8((uint8_t)res.lockValue, res.address); + break; + case ScanValueType::U16: + Memory::Write_U16((uint16_t)res.lockValue, res.address); + break; + case ScanValueType::U32: + Memory::Write_U32(res.lockValue, res.address); + break; + } + } + } +} + +void MemoryScanner::SetLocked(size_t index, bool locked) { + if (index < results_.size()) { + results_[index].locked = locked; + if (results_[index].locked) { + // Capture current value to lock it to. + switch (results_[index].type) { + case ScanValueType::U8: + results_[index].lockValue = Memory::Read_U8(results_[index].address); + break; + case ScanValueType::U16: + results_[index].lockValue = Memory::Read_U16(results_[index].address); + break; + case ScanValueType::U32: + results_[index].lockValue = Memory::Read_U32(results_[index].address); + break; + } + } + } +} + +MemoryScannerScreen::MemoryScannerScreen(Path gamePath) : UIDialogScreen(), gamePath_(std::move(gamePath)), resultsList_(nullptr) { +} + +MemoryScannerScreen::~MemoryScannerScreen() = default; + +void MemoryScannerScreen::CreateViews() { + using namespace UI; + + auto di = GetI18NCategory(I18NCat::DIALOG); + + root_ = new LinearLayout(ORIENT_VERTICAL); + + root_->Add(new ItemHeader("Memory Scanner")); + + searchValueEdit_ = root_->Add(new TextEdit(g_MemoryScanner.searchValue, "Value to search", "Enter value", new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + searchValueEdit_->OnTextChange.Add([this](EventParams &e) { + g_MemoryScanner.searchValue = searchValueEdit_->GetText(); + }); + + LinearLayout *typeRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); + typeRow->Add(new TextView("Value Type: ", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); + + typeRow->Add(new Choice("8-bit"))->OnClick.Add([](EventParams &) { g_MemoryScanner.valueType = ScanValueType::U8; }); + typeRow->Add(new Choice("16-bit"))->OnClick.Add([](EventParams &) { g_MemoryScanner.valueType = ScanValueType::U16; }); + typeRow->Add(new Choice("32-bit"))->OnClick.Add([](EventParams &) { g_MemoryScanner.valueType = ScanValueType::U32; }); + + LinearLayout *buttonRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); + buttonRow->Add(new Button("First Scan"))->OnClick.Handle(this, &MemoryScannerScreen::OnFirstScan); + buttonRow->Add(new Button("Next Scan"))->OnClick.Handle(this, &MemoryScannerScreen::OnNextScan); + buttonRow->Add(new Button("Clear"))->OnClick.Handle(this, &MemoryScannerScreen::OnClear); + + countText_ = root_->Add(new TextView("Results: 0", new LinearLayoutParams(Margins(10, 10)))); + countText_->SetShadow(true); + countText_->SetBig(true); + + root_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, 0.0f, 1.0f))) + ->Add(resultsList_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + + root_->Add(new Button(di->T("Back")))->OnClick.Add([this](EventParams &) { TriggerFinish(DR_BACK); }); + + if (g_MemoryScanner.HasScanDone()) { + RebuildResultsList(); + } +} + +void MemoryScannerScreen::update() { + UIScreen::update(); + if (countText_) { + const auto &results = g_MemoryScanner.GetResults(); + countText_->SetText(StringFromFormat("Results: %d", (int)results.size())); + } + if (resultsList_) { + resultsList_->SetVisibility(g_MemoryScanner.HasScanDone() ? UI::V_VISIBLE : UI::V_GONE); + } + + // Update live values in the list. + for (size_t i = 0; i < valueChoices_.size(); ++i) { + uint32_t addr = resultAddresses_[i]; + ScanValueType type = resultTypes_[i]; + std::string valStr; + switch (type) { + case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + valueChoices_[i]->SetText(valStr); + } +} + +void MemoryScannerScreen::RebuildResultsList() { + if (!resultsList_) + return; + using namespace UI; + resultsList_->Clear(); + valueChoices_.clear(); + resultAddresses_.clear(); + resultTypes_.clear(); + + auto &results = g_MemoryScanner.GetResults(); + + if (results.empty()) + return; + + LinearLayout *header = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + auto *addrHeader = header->Add(new TextView("Address", new LinearLayoutParams(200.0f, WRAP_CONTENT))); + addrHeader->SetShadow(true); + addrHeader->SetPadding(Margins(16, 0)); + auto *valHeader = header->Add(new TextView("Value", new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); + valHeader->SetShadow(true); + valHeader->SetPadding(Margins(16, 0)); + auto *lockHeader = header->Add(new TextView("Lock", new LinearLayoutParams(100.0f, WRAP_CONTENT))); + lockHeader->SetShadow(true); + lockHeader->SetPadding(Margins(16, 0)); + + int count = 0; + for (size_t i = 0; i < results.size(); ++i) { + LinearLayout *row = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + uint32_t addr = results[i].address; + ScanValueType type = results[i].type; + + row->Add(new Choice(StringFromFormat("0x%08X", addr), new LinearLayoutParams(200.0f, WRAP_CONTENT))); + + std::string valStr; + switch (type) { + case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + + Choice *valChoice = row->Add(new Choice(valStr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); + valChoice->OnClick.Add([this, addr, type](EventParams &e) { + OnValueClick(addr, type); + }); + valueChoices_.push_back(valChoice); + resultAddresses_.push_back(addr); + resultTypes_.push_back(type); + + auto *lockCheck = row->Add(new CheckBox(&results[i].locked, "", "", new LinearLayoutParams(100.0f, WRAP_CONTENT))); + lockCheck->OnClick.Add([i](EventParams &e) { + g_MemoryScanner.SetLocked(i, g_MemoryScanner.GetResults()[i].locked); + }); + + if (++count > 100) break; // Limit UI items + } +} + +void MemoryScannerScreen::OnFirstScan(UI::EventParams &e) { + g_MemoryScanner.FirstScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); + RebuildResultsList(); +} + +void MemoryScannerScreen::OnNextScan(UI::EventParams &e) { + if (g_MemoryScanner.HasScanDone()) { + g_MemoryScanner.NextScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); + RebuildResultsList(); + } +} + +void MemoryScannerScreen::OnClear(UI::EventParams &e) { + g_MemoryScanner.Clear(); + RebuildResultsList(); +} + +void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { + std::string currentVal; + switch (type) { + case ScanValueType::U8: currentVal = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: currentVal = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: currentVal = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + + UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, "Edit Value", [addr, type](const std::string &value, bool ok) { + if (ok) { + try { + auto val = (uint32_t)std::stoul(value, nullptr, 0); + switch (type) { + case ScanValueType::U8: Memory::Write_U8((uint8_t)val, addr); break; + case ScanValueType::U16: Memory::Write_U16((uint16_t)val, addr); break; + case ScanValueType::U32: Memory::Write_U32(val, addr); break; + } + + // Also update lock value if locked. + for (auto &res : g_MemoryScanner.GetResults()) { + if (res.address == addr && res.type == type && res.locked) { + res.lockValue = val; + } + } + } catch (...) { + // Ignore invalid input. + } + } + }); +} diff --git a/UI/MemoryScanner.h b/UI/MemoryScanner.h new file mode 100644 index 000000000000..2facf5fecad0 --- /dev/null +++ b/UI/MemoryScanner.h @@ -0,0 +1,90 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include +#include + +#include "Common/File/Path.h" +#include "Common/UI/UIScreen.h" +#include "Common/UI/View.h" +#include "Common/UI/ViewGroup.h" + +enum class ScanValueType { + U8, + U16, + U32, +}; + +struct ScanResult { + ScanResult(uint32_t addr = 0, ScanValueType t = ScanValueType::U8) + : address(addr), type(t) {} + uint32_t address; + ScanValueType type; + bool locked = false; + uint32_t lockValue = 0; +}; + +class MemoryScanner { +public: + void FirstScan(ScanValueType type, const std::string &filter); + void NextScan(ScanValueType type, const std::string &filter); + void Clear(); + void Update(); + void SetLocked(size_t index, bool locked); + + [[nodiscard]] const std::vector &GetResults() const { return results_; } + std::vector &GetResults() { return results_; } + [[nodiscard]] bool HasScanDone() const { return firstScanDone_; } + + ScanValueType valueType = ScanValueType::U32; + std::string searchValue = "0"; + +private: + std::vector results_; + bool firstScanDone_ = false; +}; + +extern MemoryScanner g_MemoryScanner; + +class MemoryScannerScreen : public UIDialogScreen { +public: + MemoryScannerScreen(Path gamePath); + ~MemoryScannerScreen() override; + + void CreateViews() override; + void update() override; + void RebuildResultsList(); + + [[nodiscard]] const char *tag() const override { return "MemoryScanner"; } + +private: + void OnFirstScan(UI::EventParams &e); + void OnNextScan(UI::EventParams &e); + void OnClear(UI::EventParams &e); + void OnValueClick(uint32_t addr, ScanValueType type); + + Path gamePath_; + + UI::TextView *countText_ = nullptr; + UI::TextEdit *searchValueEdit_ = nullptr; + UI::LinearLayout *resultsList_ = nullptr; + std::vector valueChoices_; + std::vector resultAddresses_; + std::vector resultTypes_; +}; diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 802145d6c28e..620b787592e3 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -56,6 +56,7 @@ #include "GPU/GPUState.h" #include "UI/EmuScreen.h" +#include "UI/MemoryScanner.h" #include "UI/PauseScreen.h" #include "UI/GameSettingsScreen.h" #include "UI/ReportScreen.h" @@ -676,6 +677,9 @@ void GamePauseScreen::CreateViews() { rightColumnItems->Add(new Choice(pa->T("Cheats"), ImageID("I_CHEAT")))->OnClick.Add([this](UI::EventParams &e) { screenManager()->push(new CwCheatScreen(gamePath_)); }); + rightColumnItems->Add(new Choice("Memory Scanner", ImageID("I_CHEAT")))->OnClick.Add([this](UI::EventParams &e) { + screenManager()->push(new MemoryScannerScreen(gamePath_)); + }); } // TODO, also might be nice to show overall compat rating here? diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index 2af2cbc0ffeb..8829b29268b5 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -59,6 +59,7 @@ + @@ -118,6 +119,7 @@ + @@ -369,4 +371,4 @@ - \ No newline at end of file + diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 0eeb5cd6f5e3..84ed70d5c24e 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -16,6 +16,9 @@ Screens + + Screens + Screens @@ -166,6 +169,9 @@ Screens + + Screens + Screens @@ -312,4 +318,4 @@ {fda6bc55-1386-4650-a274-44fac9605ea3} - \ No newline at end of file + diff --git a/UWP/UI_UWP/UI_UWP.vcxproj b/UWP/UI_UWP/UI_UWP.vcxproj index c19ec713beb9..03178d7ce696 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj +++ b/UWP/UI_UWP/UI_UWP.vcxproj @@ -124,6 +124,7 @@ + @@ -182,6 +183,7 @@ + @@ -215,4 +217,4 @@ - \ No newline at end of file + diff --git a/UWP/UI_UWP/UI_UWP.vcxproj.filters b/UWP/UI_UWP/UI_UWP.vcxproj.filters index 9b7d575aaa54..a298a51f82f2 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj.filters +++ b/UWP/UI_UWP/UI_UWP.vcxproj.filters @@ -88,6 +88,9 @@ Screens + + Screens + Screens @@ -228,6 +231,9 @@ Screens + + Screens + Screens @@ -285,4 +291,4 @@ {38b8413d-438d-4197-9db8-7bd123fc7431} - \ No newline at end of file + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6c86d25454c5..c70db4c98a83 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -946,6 +946,7 @@ LOCAL_SRC_FILES := \ $(SRC)/UI/RemoteISOScreen.cpp \ $(SRC)/UI/ReportScreen.cpp \ $(SRC)/UI/PauseScreen.cpp \ + $(SRC)/UI/MemoryScanner.cpp \ $(SRC)/UI/SavedataScreen.cpp \ $(SRC)/UI/Store.cpp \ $(SRC)/UI/SystemInfoScreen.cpp \ From 91ece485586d960c316ad332247636e64408a281 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Sun, 31 May 2026 22:06:35 +0800 Subject: [PATCH 02/11] Add lang files Fix 8-bit/16-bit/32 bit --- UI/MemoryScanner.cpp | 55 +++++++++++++++++++++++++----------- assets/lang/ar_AE.ini | 16 +++++++++++ assets/lang/az_AZ.ini | 16 +++++++++++ assets/lang/be_BY.ini | 16 +++++++++++ assets/lang/bg_BG.ini | 16 +++++++++++ assets/lang/ca_ES.ini | 16 +++++++++++ assets/lang/cz_CZ.ini | 16 +++++++++++ assets/lang/da_DK.ini | 16 +++++++++++ assets/lang/de_DE.ini | 16 +++++++++++ assets/lang/dr_ID.ini | 16 +++++++++++ assets/lang/en_US.ini | 16 +++++++++++ assets/lang/es_ES.ini | 16 +++++++++++ assets/lang/es_LA.ini | 16 +++++++++++ assets/lang/fa_IR.ini | 16 +++++++++++ assets/lang/fi_FI.ini | 16 +++++++++++ assets/lang/fr_FR.ini | 16 +++++++++++ assets/lang/gl_ES.ini | 16 +++++++++++ assets/lang/gr_EL.ini | 16 +++++++++++ assets/lang/he_IL.ini | 16 +++++++++++ assets/lang/he_IL_invert.ini | 16 +++++++++++ assets/lang/hr_HR.ini | 16 +++++++++++ assets/lang/hu_HU.ini | 16 +++++++++++ assets/lang/id_ID.ini | 16 +++++++++++ assets/lang/it_IT.ini | 16 +++++++++++ assets/lang/ja_JP.ini | 16 +++++++++++ assets/lang/jv_ID.ini | 16 +++++++++++ assets/lang/ko_KR.ini | 16 +++++++++++ assets/lang/ku_SO.ini | 16 +++++++++++ assets/lang/lo_LA.ini | 16 +++++++++++ assets/lang/lt-LT.ini | 16 +++++++++++ assets/lang/ms_MY.ini | 16 +++++++++++ assets/lang/nl_NL.ini | 16 +++++++++++ assets/lang/no_NO.ini | 16 +++++++++++ assets/lang/pl_PL.ini | 16 +++++++++++ assets/lang/pt_BR.ini | 16 +++++++++++ assets/lang/pt_PT.ini | 16 +++++++++++ assets/lang/ro_RO.ini | 16 +++++++++++ assets/lang/ru_RU.ini | 16 +++++++++++ assets/lang/sv_SE.ini | 16 +++++++++++ assets/lang/tg_PH.ini | 16 +++++++++++ assets/lang/th_TH.ini | 16 +++++++++++ assets/lang/tr_TR.ini | 16 +++++++++++ assets/lang/uk_UA.ini | 16 +++++++++++ assets/lang/vi_VN.ini | 16 +++++++++++ assets/lang/zh_CN.ini | 16 +++++++++++ assets/lang/zh_TW.ini | 16 +++++++++++ 46 files changed, 759 insertions(+), 16 deletions(-) diff --git a/UI/MemoryScanner.cpp b/UI/MemoryScanner.cpp index 8f09495bd676..18ece33b88b7 100644 --- a/UI/MemoryScanner.cpp +++ b/UI/MemoryScanner.cpp @@ -24,6 +24,7 @@ #include "Common/UI/ViewGroup.h" #include "Common/UI/ScrollView.h" #include "Common/UI/PopupScreens.h" +#include "Common/UI/TabHolder.h" #include "Common/Data/Text/I18n.h" #include "Core/MemMap.h" #include "Core/System.h" @@ -150,29 +151,35 @@ void MemoryScannerScreen::CreateViews() { using namespace UI; auto di = GetI18NCategory(I18NCat::DIALOG); + auto se = GetI18NCategory(I18NCat::SEARCH); root_ = new LinearLayout(ORIENT_VERTICAL); - root_->Add(new ItemHeader("Memory Scanner")); + root_->Add(new ItemHeader(se->T("Memory Scanner"))); - searchValueEdit_ = root_->Add(new TextEdit(g_MemoryScanner.searchValue, "Value to search", "Enter value", new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + searchValueEdit_ = root_->Add(new TextEdit(g_MemoryScanner.searchValue, se->T("Value to search"), se->T("Enter value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); searchValueEdit_->OnTextChange.Add([this](EventParams &e) { g_MemoryScanner.searchValue = searchValueEdit_->GetText(); }); LinearLayout *typeRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); - typeRow->Add(new TextView("Value Type: ", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); - - typeRow->Add(new Choice("8-bit"))->OnClick.Add([](EventParams &) { g_MemoryScanner.valueType = ScanValueType::U8; }); - typeRow->Add(new Choice("16-bit"))->OnClick.Add([](EventParams &) { g_MemoryScanner.valueType = ScanValueType::U16; }); - typeRow->Add(new Choice("32-bit"))->OnClick.Add([](EventParams &) { g_MemoryScanner.valueType = ScanValueType::U32; }); + typeRow->Add(new TextView(se->T("Value Type"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); + + ChoiceStrip *typeStrip = typeRow->Add(new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); + typeStrip->AddChoice(se->T("8-bit")); + typeStrip->AddChoice(se->T("16-bit")); + typeStrip->AddChoice(se->T("32-bit")); + typeStrip->SetSelection((int)g_MemoryScanner.valueType, false); + typeStrip->OnChoice.Add([](EventParams &e) { + g_MemoryScanner.valueType = (ScanValueType)e.a; + }); LinearLayout *buttonRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); - buttonRow->Add(new Button("First Scan"))->OnClick.Handle(this, &MemoryScannerScreen::OnFirstScan); - buttonRow->Add(new Button("Next Scan"))->OnClick.Handle(this, &MemoryScannerScreen::OnNextScan); - buttonRow->Add(new Button("Clear"))->OnClick.Handle(this, &MemoryScannerScreen::OnClear); + buttonRow->Add(new Button(se->T("First Scan")))->OnClick.Handle(this, &MemoryScannerScreen::OnFirstScan); + buttonRow->Add(new Button(se->T("Next Scan")))->OnClick.Handle(this, &MemoryScannerScreen::OnNextScan); + buttonRow->Add(new Button(di->T("Clear")))->OnClick.Handle(this, &MemoryScannerScreen::OnClear); - countText_ = root_->Add(new TextView("Results: 0", new LinearLayoutParams(Margins(10, 10)))); + countText_ = root_->Add(new TextView(se->T("Results: 0"), new LinearLayoutParams(Margins(10, 10)))); countText_->SetShadow(true); countText_->SetBig(true); @@ -190,7 +197,8 @@ void MemoryScannerScreen::update() { UIScreen::update(); if (countText_) { const auto &results = g_MemoryScanner.GetResults(); - countText_->SetText(StringFromFormat("Results: %d", (int)results.size())); + auto se = GetI18NCategory(I18NCat::SEARCH); + countText_->SetText(StringFromFormat(se->T_cstr("Results: %d"), (int)results.size())); } if (resultsList_) { resultsList_->SetVisibility(g_MemoryScanner.HasScanDone() ? UI::V_VISIBLE : UI::V_GONE); @@ -214,6 +222,7 @@ void MemoryScannerScreen::RebuildResultsList() { if (!resultsList_) return; using namespace UI; + auto se = GetI18NCategory(I18NCat::SEARCH); resultsList_->Clear(); valueChoices_.clear(); resultAddresses_.clear(); @@ -225,13 +234,16 @@ void MemoryScannerScreen::RebuildResultsList() { return; LinearLayout *header = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - auto *addrHeader = header->Add(new TextView("Address", new LinearLayoutParams(200.0f, WRAP_CONTENT))); + auto *addrHeader = header->Add(new TextView(se->T("Address"), new LinearLayoutParams(200.0f, WRAP_CONTENT))); addrHeader->SetShadow(true); addrHeader->SetPadding(Margins(16, 0)); - auto *valHeader = header->Add(new TextView("Value", new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); + auto *valHeader = header->Add(new TextView(se->T("Value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); valHeader->SetShadow(true); valHeader->SetPadding(Margins(16, 0)); - auto *lockHeader = header->Add(new TextView("Lock", new LinearLayoutParams(100.0f, WRAP_CONTENT))); + auto *typeHeader = header->Add(new TextView(se->T("Value Type"), new LinearLayoutParams(150.0f, WRAP_CONTENT))); + typeHeader->SetShadow(true); + typeHeader->SetPadding(Margins(16, 0)); + auto *lockHeader = header->Add(new TextView(se->T("Lock"), new LinearLayoutParams(100.0f, WRAP_CONTENT))); lockHeader->SetShadow(true); lockHeader->SetPadding(Margins(16, 0)); @@ -258,6 +270,16 @@ void MemoryScannerScreen::RebuildResultsList() { resultAddresses_.push_back(addr); resultTypes_.push_back(type); + std::string typeStr; + switch (type) { + case ScanValueType::U8: typeStr = se->T("8-bit"); break; + case ScanValueType::U16: typeStr = se->T("16-bit"); break; + case ScanValueType::U32: typeStr = se->T("32-bit"); break; + } + auto *typeView = row->Add(new TextView(typeStr, new LinearLayoutParams(150.0f, WRAP_CONTENT))); + typeView->SetShadow(true); + typeView->SetPadding(Margins(16, 0)); + auto *lockCheck = row->Add(new CheckBox(&results[i].locked, "", "", new LinearLayoutParams(100.0f, WRAP_CONTENT))); lockCheck->OnClick.Add([i](EventParams &e) { g_MemoryScanner.SetLocked(i, g_MemoryScanner.GetResults()[i].locked); @@ -292,7 +314,8 @@ void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { case ScanValueType::U32: currentVal = StringFromFormat("%u", Memory::Read_U32(addr)); break; } - UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, "Edit Value", [addr, type](const std::string &value, bool ok) { + auto se = GetI18NCategory(I18NCat::SEARCH); + UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, se->T("Edit Value"), [addr, type](const std::string &value, bool ok) { if (ok) { try { auto val = (uint32_t)std::stoul(value, nullptr, 0); diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index bb192ba9089d..2cb9587fc897 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -412,6 +412,7 @@ Are you sure you want to delete the file? = Are you sure you want to delete the Are you sure you want to exit? = Are you sure you want to exit? Auto = تلقائي Back = ‎رجوع +Clear = Clear Bottom Center = Bottom center Bottom Left = Bottom left Bottom Right = Bottom right @@ -1307,6 +1308,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = ‎خطأ في الإتصال diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 837b93b953d1..5c728dcfc0b0 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Bu dəyişim üçün PPSSPP Channel: = Kanal: Choose PPSSPP save folder = PPSSPP qorunuş qovluğunu seçin Confirm Overwrite = Veriləni əvəzləmək istəyirsiniz? +Clear = Clear Confirm Save = Bu veriləni qorumaq istəyirsiniz? ConfirmLoad = Bu verilən yüklənsin? ConnectingAP = Giriş nöqtəsinə qoşulur.\nBuyurun, gözləyin... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = '%1' görə quruluşların süzgəclənişi Find settings = Quruluşları tap No settings matched '%1' = '%1' ilə uyğun quruluşlar tapılmadı Search term = Axtarış termini +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Qoşuluş yanlışı diff --git a/assets/lang/be_BY.ini b/assets/lang/be_BY.ini index 93b76d553709..5e30d259bb61 100644 --- a/assets/lang/be_BY.ini +++ b/assets/lang/be_BY.ini @@ -415,6 +415,7 @@ Channel: = Канал: Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Do you want to overwrite the data? +Clear = Clear Confirm Save = Do you want to save this data? ConfirmLoad = Load this data? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1538,6 +1539,21 @@ Find settings = Налады пошуку Filter = Фільтр Clear filter = Ачысціць фільтр Search term = Пошукавы тэрмін +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [UI Elements] %1 button = %1 кнопка diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index b194e9d71cc8..f321fe7f954b 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Искате ли да презапишете данните? +Clear = Clear Confirm Save = Искате ли да запазите данните? ConfirmLoad = Зареди тези данни? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Грешка при свързването diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 4d35ece24d6c..d464b1223bdd 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Canvar aquesta configuració Channel: = Canal: Choose PPSSPP save folder = Tria la carpeta de guardat de PPSSPP. Confirm Overwrite = Vols sobreescriure les dades? +Clear = Clear Confirm Save = Vols guardar les dades? ConfirmLoad = Vols carregar les dades? ConnectingAP = Connectant al punt d'accés.\nPer favor espera... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Paràmetres de filtrat per '%1' Find settings = Paràmetres de cerca No settings matched '%1' = Cap paràmetre coincideix '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Error de connexió diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index ada38878128c..d5fc52fc31c9 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Zvolit složku pro ukládání dat PPSSPP Confirm Overwrite = Chcete tato data přepsat?? +Clear = Clear Confirm Save = Chcete tato data uložit? ConfirmLoad = Načíst tyto data? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Chyba připojení diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index d70675d1f447..e634ce88090c 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Vælg hvilken folder PPSSPP gemmer i Confirm Overwrite = Vil du overskrive dette data? +Clear = Clear Confirm Save = Vil du gemme dette data? ConfirmLoad = Hent dette data? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Forbindelsesfejl diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index a01db48faee1..01b427883b2e 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -413,6 +413,7 @@ Center Right = Mitte rechts Changing this setting requires PPSSPP to restart. = Das Ändern dieser Einstellung erfordert einen Neustart von PPSSPP. Channel: = Kanal: Choose PPSSPP save folder = Wähle den PPSSPP-Speicherordner +Clear = Löschen Confirm Overwrite = Willst du die Daten überschreiben? Confirm Save = Willst du diese Daten speichern? ConfirmLoad = Diese Daten laden? @@ -1298,6 +1299,21 @@ Filtering settings by '%1' = Gefiltert nach '%1' Find settings = Einstellungen suchen No settings matched '%1' = Keine Übereinstimmungen mit '%1' Search term = Suchbegriff +Memory Scanner = Speicher-Scanner +Value to search = Suchwert +Enter value = Wert eingeben +Value Type = Werttyp +8-bit = 8-Bit +16-bit = 16-Bit +32-bit = 32-Bit +First Scan = Erster Scan +Next Scan = Nächster Scan +Results: %d = Ergebnisse: %d +Results: 0 = Ergebnisse: 0 +Address = Adresse +Value = Wert +Lock = Sperren +Edit Value = Wert bearbeiten [Store] Connection Error = Verbindungsfehler diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 870df3a4b6c5..835d86e49a11 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Eda na ciapa dipasi toppo' te' data? +Clear = Clear Confirm Save = Madoangki' annai te' data? ConfirmLoad = Bukka'mi te' data? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Connection error diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index a2c2c53ee640..46d079eecf81 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -438,6 +438,7 @@ Center Right = Center right Channel: = Channel: Changing this setting requires PPSSPP to restart. = Changing this setting requires PPSSPP to restart. Choose PPSSPP save folder = Choose PPSSPP save folder +Clear = Clear Confirm Overwrite = Do you want to overwrite the data? Confirm Save = Do you want to save this data? ConfirmLoad = Load this data? @@ -1569,6 +1570,21 @@ Find settings = Find settings Filter = Filter Clear filter = Clear filter Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [UI Elements] %1 button = %1 button diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index f5e7b6ee1f6b..332975c092fb 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -415,6 +415,7 @@ Center Right = Centrado derecho Changing this setting requires PPSSPP to restart. = Para cambiar esta configuración es necesario reiniciar PPSSPP.\n¿Desea reiniciar ahora? Channel: = Canal: Choose PPSSPP save folder = Elige la carpeta de guardado de PPSSPP. +Clear = Limpiar Confirm Overwrite = ¿Quieres sobreescribir los datos? Confirm Save = ¿Deseas guardar estos datos? ConfirmLoad = ¿Deseas cargar estos datos guardados? @@ -1300,6 +1301,21 @@ Filtering settings by '%1' = Filtrado de ajustes por '%1' Find settings = Ajustes de búsqueda No settings matched '%1' = No se han encontrado ajustes para '%1' Search term = Buscar término +Memory Scanner = Escáner de memoria +Value to search = Valor a buscar +Enter value = Introducir valor +Value Type = Tipo de valor +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = Primer escaneo +Next Scan = Siguiente escaneo +Results: %d = Resultados: %d +Results: 0 = Resultados: 0 +Address = Dirección +Value = Valor +Lock = Bloquear +Edit Value = Editar valor [Store] Connection Error = Error de conexión diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index fdf0c6c5d079..e942544968e6 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -404,6 +404,7 @@ Are you sure you want to delete the file? = ¿Estás seguro de que quieres borra Are you sure you want to exit? = ¿Estás seguro de que quieres salir? Auto = Auto Back = Atrás +Clear = Limpiar Bottom Center = Abajo centrado Bottom Left = Abajo izquierda Bottom Right = Abajo derecha @@ -1301,6 +1302,21 @@ Filtering settings by '%1' = Configuraciones de filtracion por '%1' Find settings = Encontrar configuración No settings matched '%1' = Ninguna configuración coincide '%1' Search term = Buscar termino +Memory Scanner = Escáner de memoria +Value to search = Valor a buscar +Enter value = Introducir valor +Value Type = Tipo de valor +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = Primer escaneo +Next Scan = Siguiente escaneo +Results: %d = Resultados: %d +Results: 0 = Resultados: 0 +Address = Dirección +Value = Valor +Lock = Bloquear +Edit Value = Editar valor [Store] Connection Error = Error de conexión diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 4bde39d3463f..0c4fdb8ec14f 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = تغییر رابط گراف Channel: = کانال: Choose PPSSPP save folder = انتخاب پوشه برای PPSSSPP Confirm Overwrite = ‎آیا می خواهید که داده‌ها را بازنویسی کنید؟ +Clear = Clear Confirm Save = ‎آیا می خواهید که این داده را ذخیره نمایید؟ ConfirmLoad = ‎بارگیری این داده؟ ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = فیلتر کردن تنظیمات با '%1' Find settings = یافتن تنظیمات No settings matched '%1' = هیچ تنظیماتی با '%1' مطابقت ندارد Search term = عبارت جستجو +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = خطای اتصال diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index eabc310cd21f..b9899423794c 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Tämän asetuksen muuttamine Channel: = Kanava: Choose PPSSPP save folder = Valitse PPSSPP:n tallennuskansio Confirm Overwrite = Haluatko ylikirjoittaa tiedot? +Clear = Clear Confirm Save = Haluatko tallentaa nämä tiedot? ConfirmLoad = Ladataanko nämä tiedot? ConnectingAP = Yhdistetään tukiasemaan.\nOdota hetki... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Suodatetaan asetuksia hakusanalla '%1' Find settings = Etsi asetuksia No settings matched '%1' = Ei löytynyt asetuksia hakusanalla '%1' Search term = Hakusana +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Yhteysvirhe diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 1c61b7280bf8..a7385f60feff 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -438,6 +438,7 @@ Center Right = Au centre à droite Changing this setting requires PPSSPP to restart. = La modification de ce paramètre nécessite le redémarrage de PPSSPP. Redémarrer maintenant ? Channel: = Canal : Choose PPSSPP save folder = Veuillez choisir le dossier de sauvegarde de PPSSPP. +Clear = Effacer Confirm Overwrite = Voulez-vous écraser les données ? Confirm Save = Voulez-vous sauvegarder les données ? ConfirmLoad = Charger ces données ? @@ -1566,6 +1567,21 @@ Filtering settings by '%1' = Filtrer les paramètres par « %1 » Find settings = Accéder aux paramètres No settings matched '%1' = Aucun paramètre ne correspond à « %1 » Search term = Terme de recherche +Memory Scanner = Scanneur de mémoire +Value to search = Valeur à rechercher +Enter value = Entrer la valeur +Value Type = Type de valeur +8-bit = 8 bits +16-bit = 16 bits +32-bit = 32 bits +First Scan = Premier scan +Next Scan = Scan suivant +Results: %d = Résultats : %d +Results: 0 = Résultats : 0 +Address = Adresse +Value = Valeur +Lock = Bloquer +Edit Value = Modifier la valeur [UI Elements] %1 button = %1 bouton diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index c61bac47afbd..1a870f6353a5 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Elixe a carpeta de gardado de PPSSPP. Confirm Overwrite = Desexas sobreescribir os datos? +Clear = Clear Confirm Save = Desexas gardar estes datos? ConfirmLoad = Desexas cargar estes datos gardados? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Erro de conexión diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 80743c9060b4..0ad7000cd538 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Επιλογή φακέλου αποθήκευσης PPSSPP Confirm Overwrite = ΑΝΤΙΚΑΤΑΣΤΑΣΗ ΔΕΔΟΜΕΝΩΝ; +Clear = Clear Confirm Save = ΑΠΟΘΗΚΕΥΣΗ ΔΕΔΟΜΕΝΩΝ; ConfirmLoad = ΦΟΡΤΩΣΗ ΔΕΔΟΜΕΝΩΝ; ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Σφάλμα σύνδεσης diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index d1598c727833..f1f5a7a842b6 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = ?ולא םינותנ בתכשל הצור +Clear = Clear Confirm Save = ?ולא םינותנ רומשל הצור ConfirmLoad = ?ולא םינותנ ןועטל הצור ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Connection error diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 5e08433a6070..3636549fbf9b 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = ?ולא םינותנ בתכשל הצור +Clear = Clear Confirm Save = ?ולא םינותנ רומשל הצור ConfirmLoad = ?ולא םינותנ ןועטל הצור ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Connection error diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 8ab11f19f49a..be7979e4094b 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Promjena ove postavke zahtij Channel: = Channel: Choose PPSSPP save folder = Izaberi PPSSPP save mapu Confirm Overwrite = Želite li pisati preko podataka? +Clear = Clear Confirm Save = Želiš li spremiti ovu datu? ConfirmLoad = Učitaj ovu datu? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Pogreška u spajanju diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 91574ba6752f..735dc027c451 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = A grafikai parancs-pufferel Channel: = Csatorna: Choose PPSSPP save folder = PPSSPP mentési mappa kiválasztása Confirm Overwrite = Biztosan felülírod? +Clear = Clear Confirm Save = Elmented? ConfirmLoad = Betöltöd ezt a mentést? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Beállítások szűrése erre: '%1' Find settings = Beállítások keresése No settings matched '%1' = Nincs megfelelő találat erre: '%1' Search term = Keresett kifejezés +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Kapcsolódási hiba diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 4554527ba3c2..5372494419de 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Mengubah pengaturan ini meme Channel: = Saluran: Choose PPSSPP save folder = Pilih berkas simpanan PPSSPP Confirm Overwrite = Apakah anda ingin menimpa data? +Clear = Clear Confirm Save = Apakah anda ingin menyimpan data ini? ConfirmLoad = Muat data ini? ConnectingAP = Menghubungkan ke titik akses.\nHarap tunggu... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Pengaturan Pemfilteran oleh '%1' Find settings = Temukan pengaturan No settings matched '%1' = Tidak ada pengaturan yang cocok dengan '%1' Search term = Istilah pencarian +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Kesalahan pada koneksi diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 3e42a0bcb7e8..a9fc25a68256 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -414,6 +414,7 @@ Center Right = Al centro a destra Changing this setting requires PPSSPP to restart. = La modifica di questa impostazione richiede il riavvio di PPSSPP. Channel: = Canale: Choose PPSSPP save folder = Scegli la cartella di salvataggio PPSSPP +Clear = Pulisci Confirm Overwrite = Vuoi sovrascrivere i dati? Confirm Save = Vuoi salvare questi dati? ConfirmLoad = Caricare questi dati? @@ -1302,6 +1303,21 @@ Filtering settings by '%1' = Impostazioni filtro per '%1' Find settings = Ricerca impostazioni No settings matched '%1' = Nessuna impostazione con corrispondenza: '%1' Search term = Cerca termine +Memory Scanner = Scanner di memoria +Value to search = Valore da cercare +Enter value = Inserisci valore +Value Type = Tipo di valore +8-bit = 8 bit +16-bit = 16 bit +32-bit = 32 bit +First Scan = Prima scansione +Next Scan = Scansione successiva +Results: %d = Risultati: %d +Results: 0 = Risultati: 0 +Address = Indirizzo +Value = Valore +Lock = Blocca +Edit Value = Modifica valore [Store] Connection Error = Errore di connessione diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index d9805bdae80c..d71adff6befa 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -414,6 +414,7 @@ Center Right = 右中央 Changing this setting requires PPSSPP to restart. = この設定を変更するには、PPSSPPを再起動する必要があります。 Channel: = Channel: Choose PPSSPP save folder = PPSSPPのセーブ用フォルダを選択する +Clear = クリア Confirm Overwrite = データを上書きしますか? Confirm Save = データをセーブしますか? ConfirmLoad = データをロードしますか? @@ -1299,6 +1300,21 @@ Find settings = メニュー内の設定項目の検索 Filter = 検索する文字(ここをクリック) Clear filter = 検索文字のクリア Search term = 検索語 +Memory Scanner = メモリスキャナー +Value to search = 検索する値 +Enter value = 値を入力 +Value Type = 値の型 +8-bit = 8ビット +16-bit = 16ビット +32-bit = 32ビット +First Scan = 初回スキャン +Next Scan = 次のスキャン +Results: %d = 結果: %d +Results: 0 = 結果: 0 +Address = アドレス +Value = 値 +Lock = 固定 +Edit Value = 値の編集 [Store] Connection Error = 接続エラー diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index bae709408c2a..651725b42c20 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Peleh folder penyimpenan PPSSPP Confirm Overwrite = Njenengan arep Panganggoan data iki? +Clear = Clear Confirm Save = Njenengan arep nyimpen data iki? ConfirmLoad = Mbukak data iki? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Galat koneksi diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 700f0a77066c..39b7744676e9 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -414,6 +414,7 @@ Center Right = 중앙 오른쪽 Channel: = 채널: Changing this setting requires PPSSPP to restart. = 이 설정을 변경하려면 PPSSPP를 다시 시작해야 합니다. Choose PPSSPP save folder = PPSSPP 저장 폴더 선택 +Clear = 지움 Confirm Overwrite = 데이터를 덮어쓰겠습니까? Confirm Save = 이 데이터를 저장할까요? ConfirmLoad = 이 데이터를 불러오겠습니까? @@ -1538,6 +1539,21 @@ Find settings = 찾기 설정 Filter = 필터 Clear filter = 필터 지움 Search term = 검색어 +Memory Scanner = 메모리 스캐너 +Value to search = 검색할 값 +Enter value = 값 입력 +Value Type = 값 유형 +8-bit = 8비트 +16-bit = 16비트 +32-bit = 32비트 +First Scan = 첫 번째 스캔 +Next Scan = 다음 스캔 +Results: %d = 결과: %d +Results: 0 = 결과: 0 +Address = 주소 +Value = 값 +Lock = 고정 +Edit Value = 값 편집 [UI Elements] %1 button = %1 버튼 diff --git a/assets/lang/ku_SO.ini b/assets/lang/ku_SO.ini index 5f8ea73409be..ef0754b5bad8 100644 --- a/assets/lang/ku_SO.ini +++ b/assets/lang/ku_SO.ini @@ -429,6 +429,7 @@ Channel: = کەناڵ: Changing this setting requires PPSSPP to restart. = PPSSPP گۆڕینی ئەم ڕێکخستنە پێویستی بە هەیە کە دووبارە دەستپێبکاتەوە. Choose PPSSPP save folder = هەڵبژێرە PPSSPP فۆڵدەری خەزن کردنی Confirm Overwrite = دەتەوێت زانیاریەکان دووبارە بنووسیتەوە لەسەر هەمان شوێن؟ +Clear = Clear Confirm Save = ئایا دەتەوێت زانیاریەکان خەزن بکەیت؟ ConfirmLoad = ئەم زانیاریانا لۆد ئەکەیت؟ ConnectingAP = پەیوەندی ئەکەین بە خاڵی دەست بە یەک گەستن.\nتکایە بووەستە... @@ -1552,6 +1553,21 @@ Find settings = Find settings Filter = فلتەر کردن Clear filter = لابردنی فلتەر Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [UI Elements] %1 button = %1 button diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 65ceaefbb5d7..92580ab9e200 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -498,6 +498,7 @@ SavingFailed = ບໍ່ສາມາດບັນທຶກຂໍ້ມູນ. Search = Search seconds, 0:off = ວິນາທີ, 0 = ປິດ Select = ເລືອກ +Clear = Clear Settings = Settings Shift = ປ່ຽນ Show in folder = ສະແດງໃນໂຟນເດີ້ @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = ການເຊື່ອມຕໍ່ລົ້ມເຫຼວ diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index eb55dcca266a..4325cdb472ce 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Pasirinkite PPSSPP išsaugojimo aplanką Confirm Overwrite = Ar norite perrašyti šitus duomenis? +Clear = Clear Confirm Save = Ar norite išsaugoti šitus duomenis? ConfirmLoad = Ar krauti šitus duomenis? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Prisijungimo klaida diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index b404f11ec629..d461a5d0f73b 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Anda hendak menulis ganti data ini? +Clear = Clear Confirm Save = Anda hendak simpan data ini? ConfirmLoad = Muatkan data ini? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Kesalahan Sambungan diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 23567e00be9a..ca211b31e1e7 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = PPSSPP-opslagmap selecteren Confirm Overwrite = Wilt u de opgeslagen data overschrijven? +Clear = Clear Confirm Save = Wilt u deze data opslaan? ConfirmLoad = Wilt u deze data laden? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Verbindingsfout diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index ab21b7a95b60..2c5e4f8f315e 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Choose PPSSPP save folder Confirm Overwrite = Do you want to overwrite the data? +Clear = Clear Confirm Save = Do you want to save this data? ConfirmLoad = Load this data? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Søkeuttrykk +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Tilkoblingsfeil diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 06962d68ea21..bc9e649259a4 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Zmiana tego ustawienia wymag Channel: = Kanał: Choose PPSSPP save folder = Wybierz folder do zapisu stanów PPSSPP Confirm Overwrite = Czy chcesz nadpisać te dane? +Clear = Clear Confirm Save = Czy chcesz zapisać te dane? ConfirmLoad = Wczytać te dane? ConnectingAP = Łączenie do punktu dostępowego.\nProszę czekać... @@ -1307,6 +1308,21 @@ Filtering settings by '%1' = Wyszukiwanie ustawień '%1' Find settings = Szukaj ustawień No settings matched '%1' = Brak wyników dla '%1' Search term = Wyszukaj frazę +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Błąd połączenia diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index a4eb698d7f92..ccf00ae13c05 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -438,6 +438,7 @@ Center Right = A direita do centro Channel: = Canal: Changing this setting requires PPSSPP to restart. = Mudar esta configuração requer que o PPSSPP reinicie. Choose PPSSPP save folder = Escolha a pasta de salvamento do PPSSPP +Clear = Limpar Confirm Overwrite = Você quer sobrescrever os dados? Confirm Save = Você quer salvar estes dados? ConfirmLoad = Carregar estes dados? @@ -1569,6 +1570,21 @@ Find settings = Achar configurações Filter = Filtro Clear filter = Limpar filtro Search term = Procurar termo +Memory Scanner = Escâner de memória +Value to search = Valor para procurar +Enter value = Digite o valor +Value Type = Tipo de valor +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = Primeiro escaneamento +Next Scan = Próximo escaneamento +Results: %d = Resultados: %d +Results: 0 = Resultados: 0 +Address = Endereço +Value = Valor +Lock = Bloquear +Edit Value = Editar valor [UI Elements] %1 button = %1 botão diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index bde2c0a51b22..d67e1b19bd73 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -439,6 +439,7 @@ Changing this setting requires PPSSPP to restart. = A alteração desta definiç Channel: = Canal: Choose PPSSPP save folder = Escolhe a pasta de salvamento da PPSSPP Confirm Overwrite = Queres sobrescrever os dados? +Clear = Clear Confirm Save = Queres guardar estes dados? ConfirmLoad = Carregar estes dados? ConnectingAP = A conectar ao ponto de acesso.\nPor favor espere... @@ -1563,6 +1564,21 @@ Find settings = Encontrar definições Filter = Filtro Clear filter = Limpar filtro Search term = Termo de pesquisa +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [UI Elements] %1 button = Botão %1 diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index dc6d4f1cd85e..7e2d239995e7 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -416,6 +416,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Alege folder pt. salvări PPSSPP Confirm Overwrite = Vrei să suprascrii datele? +Clear = Clear Confirm Save = Vrei să savezi datele? ConfirmLoad = Incarcă datele acestea? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1300,6 +1301,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Eroare de conexiune diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 7178870c16ae..5c7b1b0473d1 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -414,6 +414,7 @@ Center Right = В центре справа Changing this setting requires PPSSPP to restart. = Изменение этого параметра требует перезапуска PPSSPP. Channel: = Канал: Choose PPSSPP save folder = Выбрать папку с сохранениями +Clear = Очистить Confirm Overwrite = Вы хотите перезаписать данные? Confirm Save = Вы уверены, что хотите сохранить данные? ConfirmLoad = Загрузить эти данные? @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Сортировка настроек по '%1' Find settings = Поиск настроек No settings matched '%1' = Нет настроек, содержащих '%1' Search term = Поисковый запрос +Memory Scanner = Сканер памяти +Value to search = Искомое значение +Enter value = Введите значение +Value Type = Тип значения +8-bit = 8 бит +16-bit = 16 бит +32-bit = 32 бита +First Scan = Первое сканирование +Next Scan = След. сканирование +Results: %d = Результатов: %d +Results: 0 = Результатов: 0 +Address = Адрес +Value = Значение +Lock = Фиксация +Edit Value = Изменить значение [Store] Connection Error = Ошибка подключения diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 4460c4c2febe..67d3037e96ff 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Att ändra denna inställnin Channel: = Kanal: Choose PPSSPP save folder = Välj mapp att spara i Confirm Overwrite = Vill du skriva över datan? +Clear = Clear Confirm Save = Vill du spara denna data? ConfirmLoad = Läs in denna data? ConnectingAP = Ansluter till accesspunkten.\nVänta... @@ -1300,6 +1301,21 @@ Filtering settings by '%1' = Filtrerar inställningar efter '%1' Find settings = Sök inställningar No settings matched '%1' = Inga inställningar matchade '%1' Search term = Sökterm +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Uppkopplingsfel diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index a82c7b58195d..a9fe6ab027d5 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -416,6 +416,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Piliin ang PPSSPP save folder Confirm Overwrite = Nais mo bang patungan ang datos? +Clear = Clear Confirm Save = Nais mo bang i-save ang datos? ConfirmLoad = Nais mo bang i-load ang datos? ConnectingAP = Kumokonekta na sa access point.\nSandali lamang... @@ -1302,6 +1303,21 @@ Filtering settings by '%1' = Pag-filter ng mga setting sa pamamagitan ng '%1' Find settings = Hanapin ang setting No settings matched '%1' = Walang tumugma na mga setting na may kinalaman sa '%1' Search term = Kataga sa paghahanap +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = May error sa Koneksyon. diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 0b806ec06c94..79b9ded66b3f 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -420,6 +420,7 @@ Are you sure you want to delete the file? = คุณแน่ใจนะ ว Are you sure you want to exit? = คุณแน่ใจนะ ว่าต้องการออกเกม? Auto = อัตโนมัติ Back = ย้อนกลับ +Clear = ล้าง Bottom Center = มุมล่างกลางจอ Bottom Left = มุมล่างซ้ายจอ Bottom Right = มุมล่างขวาจอ @@ -1321,6 +1322,21 @@ Filtering settings by '%1' = ตัวกรองการตั้งค่า Find settings = ค้นหาตัวเลือกตั้งค่า No settings matched '%1' = ไม่มีตั้งค่าที่ตรงกันกับ '%1' Search term = คำที่ต้องการค้นหา +Memory Scanner = ตัวสแกนหน่วยความจำ +Value to search = ค่าที่ต้องการค้นหา +Enter value = ใส่ค่า +Value Type = ประเภทของค่า +8-bit = 8-บิต +16-bit = 16-บิต +32-bit = 32-บิต +First Scan = สแกนครั้งแรก +Next Scan = สแกนถัดไป +Results: %d = ผลลัพธ์: %d +Results: 0 = ผลลัพธ์: 0 +Address = ที่อยู่ +Value = ค่า +Lock = ล็อค +Edit Value = แก้ไขค่า [Store] Connection Error = การเชื่อมต่อล้มเหลว diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index ef8f3960aaf6..252075fbb8e5 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -417,6 +417,7 @@ Changing this setting requires PPSSPP to restart. = Bu ayarın değiştirilmesi, Channel: = Kanal: Choose PPSSPP save folder = PPSSPP kayıt klasörünü seç Confirm Overwrite = Verinin üstüne yazmak istiyor musunuz? +Clear = Clear Confirm Save = Bu veriyi kaydetmek istiyor musunuz? ConfirmLoad = Veriyi yüklemek istiyor musunuz? ConnectingAP = Erişim noktasına bağlanılıyor.\nLütfen bekleyin.... @@ -1300,6 +1301,21 @@ Filtering settings by '%1' = Ayarlar '%1' için filtreleniyor Find settings = Ayarları Ara No settings matched '%1' = '%1' ile eşleşen ayar yok Search term = Arama Terimi +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Bağlantı Hatası diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index d3b876b103fe..a0d1d5b4fc6d 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Зміна буфериза Channel: = Канал: Choose PPSSPP save folder = Виберіть папку для збереження Confirm Overwrite = Ви хочете перезаписати дані? +Clear = Clear Confirm Save = Ви впевнені, що хочете зберегти дані? ConfirmLoad = Завантажити ці дані? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Фільтрування налаштувань з Find settings = Запитані налаштування No settings matched '%1' = No settings matched '%1' Search term = Пошуковий термін +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Помилка підключення diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index 60587210ac09..a963e96133a7 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -415,6 +415,7 @@ Changing this setting requires PPSSPP to restart. = Changing this setting requir Channel: = Channel: Choose PPSSPP save folder = Chọn thư mục save của PPSSPP Confirm Overwrite = Bạn có muốn ghi đè lên dữ liệu này không? +Clear = Clear Confirm Save = Bạn có muốn save dữ liệu này không? ConfirmLoad = Load dữ liệu này? ConnectingAP = Connecting to the access point.\nPlease wait... @@ -1299,6 +1300,21 @@ Filtering settings by '%1' = Filtering settings by '%1' Find settings = Find settings No settings matched '%1' = No settings matched '%1' Search term = Search term +Memory Scanner = Memory Scanner +Value to search = Value to search +Enter value = Enter value +Value Type = Value Type +8-bit = 8-bit +16-bit = 16-bit +32-bit = 32-bit +First Scan = First Scan +Next Scan = Next Scan +Results: %d = Results: %d +Results: 0 = Results: 0 +Address = Address +Value = Value +Lock = Lock +Edit Value = Edit Value [Store] Connection Error = Lỗi kết nối diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index ce2e0b02c848..65cc17e86df5 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -414,6 +414,7 @@ Center Right = 右中间 Changing this setting requires PPSSPP to restart. = 此项设置更改需要PPSSPP重启。 Channel: = 信道: Choose PPSSPP save folder = 选择PPSSPP存档的文件夹 +Clear = 清除 Confirm Overwrite = 您要覆盖这个存档吗? Confirm Save = 您要保存到这个存档吗? ConfirmLoad = 您要载入这个存档吗? @@ -1552,6 +1553,21 @@ Filter = 搜索设置 Clear filter = 结束搜索 No settings matched '%1' = 没有找到名为“%1”的设置 Search term = 搜索关键词 +Memory Scanner = 内存扫描器 +Value to search = 搜索数值 +Enter value = 输入数值 +Value Type = 数值类型 +8-bit = 8位 +16-bit = 16位 +32-bit = 32位 +First Scan = 首次扫描 +Next Scan = 再次扫描 +Results: %d = 结果数:%d +Results: 0 = 结果数:0 +Address = 地址 +Value = 数值 +Lock = 锁定 +Edit Value = 修改数值 [VR] % of native FoV = 原生视角的% diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 93ddf851e65d..a831eb90652f 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -414,6 +414,7 @@ Center Right = 正右 Changing this setting requires PPSSPP to restart. = 變更此設定需要重新啟動 PPSSPP。 Channel: = 頻道: Choose PPSSPP save folder = 選擇 PPSSPP 存檔資料夾 +Clear = 清除 Confirm Overwrite = 要覆寫這個存檔的資料嗎? Confirm Save = 要儲存這個存檔的資料嗎? ConfirmLoad = 要載入這個存檔的資料嗎? @@ -1538,6 +1539,21 @@ Find settings = 尋找設定 Filter = 篩選器 Clear filter = 清除篩選器 Search term = 搜尋詞彙 +Memory Scanner = 記憶體掃描器 +Value to search = 搜尋數值 +Enter value = 輸入數值 +Value Type = 數值類型 +8-bit = 8位元 +16-bit = 16位元 +32-bit = 32位元 +First Scan = 首次掃描 +Next Scan = 再次掃描 +Results: %d = 結果數:%d +Results: 0 = 結果數:0 +Address = 位址 +Value = 數值 +Lock = 鎖定 +Edit Value = 修改數值 [UI Elements] %1 button = %1 按鈕 From eb9bb46607d5dbac561c7d5c43b4e0cb42e9541e Mon Sep 17 00:00:00 2001 From: sum2012 Date: Sun, 31 May 2026 22:21:37 +0800 Subject: [PATCH 03/11] Add transate of Memory Scanner --- UI/PauseScreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 620b787592e3..521d2252407f 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -471,6 +471,7 @@ void GamePauseScreen::CreateViews() { auto nw = GetI18NCategory(I18NCat::NETWORKING); auto di = GetI18NCategory(I18NCat::DIALOG); auto co = GetI18NCategory(I18NCat::CONTROLS); + auto se = GetI18NCategory(I18NCat::SEARCH); root_ = new LinearLayout(portrait ? ORIENT_VERTICAL : ORIENT_HORIZONTAL); @@ -677,7 +678,7 @@ void GamePauseScreen::CreateViews() { rightColumnItems->Add(new Choice(pa->T("Cheats"), ImageID("I_CHEAT")))->OnClick.Add([this](UI::EventParams &e) { screenManager()->push(new CwCheatScreen(gamePath_)); }); - rightColumnItems->Add(new Choice("Memory Scanner", ImageID("I_CHEAT")))->OnClick.Add([this](UI::EventParams &e) { + rightColumnItems->Add(new Choice(se->T("Memory Scanner"), ImageID("I_CHEAT")))->OnClick.Add([this](UI::EventParams &e) { screenManager()->push(new MemoryScannerScreen(gamePath_)); }); } From 5712c75772816fb09c4d595e84e9f5bd434120a2 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Sun, 31 May 2026 23:56:40 +0800 Subject: [PATCH 04/11] Try to fix headless --- CMakeLists.txt | 6 +- Core/Core.vcxproj | 8 +- Core/Core.vcxproj.filters | 26 +++- Core/CwCheat.cpp | 2 +- Core/MemoryScanner.cpp | 136 ++++++++++++++++++ Core/MemoryScanner.h | 59 ++++++++ UI/MemoryScannerScreen.cpp | 214 ++++++++++++++++++++++++++++ UI/MemoryScannerScreen.h | 54 +++++++ UI/PauseScreen.cpp | 2 +- UI/UI.vcxproj | 4 +- UI/UI.vcxproj.filters | 4 +- UWP/CoreUWP/CoreUWP.vcxproj | 4 +- UWP/CoreUWP/CoreUWP.vcxproj.filters | 4 +- UWP/UI_UWP/UI_UWP.vcxproj | 4 +- UWP/UI_UWP/UI_UWP.vcxproj.filters | 4 +- android/jni/Android.mk | 3 +- libretro/Makefile.common | 1 + 17 files changed, 510 insertions(+), 25 deletions(-) create mode 100644 Core/MemoryScanner.cpp create mode 100644 Core/MemoryScanner.h create mode 100644 UI/MemoryScannerScreen.cpp create mode 100644 UI/MemoryScannerScreen.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d037a591a2c4..8ec45798729c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1633,8 +1633,8 @@ list(APPEND NativeAppSource UI/IAPScreen.h UI/MainScreen.h UI/MainScreen.cpp - UI/MemoryScanner.h - UI/MemoryScanner.cpp + UI/MemoryScannerScreen.h + UI/MemoryScannerScreen.cpp UI/GameBrowser.h UI/GameBrowser.cpp UI/MiscScreens.h @@ -2174,6 +2174,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/KeyMapDefaults.h Core/LuaContext.cpp Core/LuaContext.h + Core/MemoryScanner.cpp + Core/MemoryScanner.h Core/RetroAchievements.h Core/RetroAchievements.cpp Core/TiltEventProcessor.h diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 9a5aef32ec05..7ba98733dd38 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -546,7 +546,8 @@ - + + @@ -1053,7 +1054,8 @@ - + + @@ -1308,4 +1310,4 @@ - \ No newline at end of file + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 2cd01b785327..c9ab82d07e37 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -303,12 +303,21 @@ Debugger + + Core + Core Core + + Core + + + Core + Core @@ -339,9 +348,6 @@ HLE\Kernel - - Core - ELF @@ -1593,6 +1599,9 @@ Core + + Core + Core @@ -1602,6 +1611,12 @@ Core + + Core + + + Core + Core @@ -1629,9 +1644,6 @@ HLE\Kernel - - Core - ELF @@ -2278,4 +2290,4 @@ Ext - \ No newline at end of file + diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index c8e18f2b4468..4cf7e44a1d4c 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -12,7 +12,7 @@ #include "Core/CoreTiming.h" #include "Core/CoreParameter.h" #include "Core/CwCheat.h" -#include "UI/MemoryScanner.h" +#include "Core/MemoryScanner.h" #include "Core/Config.h" #include "Core/MemMapHelpers.h" #include "Core/MIPS/MIPS.h" diff --git a/Core/MemoryScanner.cpp b/Core/MemoryScanner.cpp new file mode 100644 index 000000000000..16c86fc39a28 --- /dev/null +++ b/Core/MemoryScanner.cpp @@ -0,0 +1,136 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include +#include + +#include "Core/MemoryScanner.h" +#include "Core/MemMap.h" +#include "Core/System.h" +#include "Common/StringUtils.h" + +MemoryScanner g_MemoryScanner; + +void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { + results_.clear(); + uint32_t val = 0; + try { + val = (uint32_t)std::stoul(filter, nullptr, 0); + } catch (...) { + return; + } + + uint32_t startAddr = 0x08000000; + uint32_t endAddr = startAddr + Memory::g_MemorySize; + + for (uint32_t addr = startAddr; addr < endAddr; ) { + bool match = false; + switch (type) { + case ScanValueType::U8: + if (Memory::Read_U8(addr) == (uint8_t)val) match = true; + addr += 1; + break; + case ScanValueType::U16: + if (addr + 2 <= endAddr && Memory::Read_U16(addr) == (uint16_t)val) match = true; + addr += 1; + break; + case ScanValueType::U32: + if (addr + 4 <= endAddr && Memory::Read_U32(addr) == (uint32_t)val) match = true; + addr += 1; + break; + } + + if (match) { + results_.emplace_back(addr - 1, type); + if (results_.size() > 1000) break; + } + } + firstScanDone_ = true; +} + +void MemoryScanner::NextScan(ScanValueType type, const std::string &filter) { + uint32_t val = 0; + try { + val = (uint32_t)std::stoul(filter, nullptr, 0); + } catch (...) { + return; + } + + std::vector nextResults; + for (const auto &res : results_) { + bool match = false; + switch (type) { + case ScanValueType::U8: + if (Memory::Read_U8(res.address) == (uint8_t)val) match = true; + break; + case ScanValueType::U16: + if (Memory::Read_U16(res.address) == (uint16_t)val) match = true; + break; + case ScanValueType::U32: + if (Memory::Read_U32(res.address) == (uint32_t)val) match = true; + break; + } + + if (match) { + nextResults.push_back(res); + } + } + results_ = std::move(nextResults); +} + +void MemoryScanner::Clear() { + results_.clear(); + firstScanDone_ = false; +} + +void MemoryScanner::Update() { + for (auto &res : results_) { + if (res.locked) { + switch (res.type) { + case ScanValueType::U8: + Memory::Write_U8((uint8_t)res.lockValue, res.address); + break; + case ScanValueType::U16: + Memory::Write_U16((uint16_t)res.lockValue, res.address); + break; + case ScanValueType::U32: + Memory::Write_U32(res.lockValue, res.address); + break; + } + } + } +} + +void MemoryScanner::SetLocked(size_t index, bool locked) { + if (index < results_.size()) { + results_[index].locked = locked; + if (results_[index].locked) { + // Capture current value to lock it to. + switch (results_[index].type) { + case ScanValueType::U8: + results_[index].lockValue = Memory::Read_U8(results_[index].address); + break; + case ScanValueType::U16: + results_[index].lockValue = Memory::Read_U16(results_[index].address); + break; + case ScanValueType::U32: + results_[index].lockValue = Memory::Read_U32(results_[index].address); + break; + } + } + } +} diff --git a/Core/MemoryScanner.h b/Core/MemoryScanner.h new file mode 100644 index 000000000000..9ea3190d3893 --- /dev/null +++ b/Core/MemoryScanner.h @@ -0,0 +1,59 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include +#include +#include + +enum class ScanValueType { + U8, + U16, + U32, +}; + +struct ScanResult { + ScanResult(uint32_t addr = 0, ScanValueType t = ScanValueType::U8) + : address(addr), type(t) {} + uint32_t address; + ScanValueType type; + bool locked = false; + uint32_t lockValue = 0; +}; + +class MemoryScanner { +public: + void FirstScan(ScanValueType type, const std::string &filter); + void NextScan(ScanValueType type, const std::string &filter); + void Clear(); + void Update(); + void SetLocked(size_t index, bool locked); + + [[nodiscard]] const std::vector &GetResults() const { return results_; } + std::vector &GetResults() { return results_; } + [[nodiscard]] bool HasScanDone() const { return firstScanDone_; } + + ScanValueType valueType = ScanValueType::U32; + std::string searchValue = "0"; + +private: + std::vector results_; + bool firstScanDone_ = false; +}; + +extern MemoryScanner g_MemoryScanner; diff --git a/UI/MemoryScannerScreen.cpp b/UI/MemoryScannerScreen.cpp new file mode 100644 index 000000000000..0f400036e565 --- /dev/null +++ b/UI/MemoryScannerScreen.cpp @@ -0,0 +1,214 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include +#include +#include "UI/MemoryScannerScreen.h" +#include "Common/UI/Context.h" +#include "Common/UI/UIScreen.h" +#include "Common/UI/View.h" +#include "Common/UI/ViewGroup.h" +#include "Common/UI/ScrollView.h" +#include "Common/UI/PopupScreens.h" +#include "Common/UI/TabHolder.h" +#include "Common/Data/Text/I18n.h" +#include "Core/MemMap.h" +#include "Core/System.h" +#include "Common/StringUtils.h" + +MemoryScannerScreen::MemoryScannerScreen(Path gamePath) : UIDialogScreen(), gamePath_(std::move(gamePath)), resultsList_(nullptr) { +} + +MemoryScannerScreen::~MemoryScannerScreen() = default; + +void MemoryScannerScreen::CreateViews() { + using namespace UI; + + auto di = GetI18NCategory(I18NCat::DIALOG); + auto se = GetI18NCategory(I18NCat::SEARCH); + + root_ = new LinearLayout(ORIENT_VERTICAL); + + root_->Add(new ItemHeader(se->T("Memory Scanner"))); + + searchValueEdit_ = root_->Add(new TextEdit(g_MemoryScanner.searchValue, se->T("Value to search"), se->T("Enter value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + searchValueEdit_->OnTextChange.Add([this](EventParams &e) { + g_MemoryScanner.searchValue = searchValueEdit_->GetText(); + }); + + LinearLayout *typeRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); + typeRow->Add(new TextView(se->T("Value Type"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); + + ChoiceStrip *typeStrip = typeRow->Add(new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); + typeStrip->AddChoice(se->T("8-bit")); + typeStrip->AddChoice(se->T("16-bit")); + typeStrip->AddChoice(se->T("32-bit")); + typeStrip->SetSelection((int)g_MemoryScanner.valueType, false); + typeStrip->OnChoice.Add([](EventParams &e) { + g_MemoryScanner.valueType = (ScanValueType)e.a; + }); + + LinearLayout *buttonRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); + buttonRow->Add(new Button(se->T("First Scan")))->OnClick.Handle(this, &MemoryScannerScreen::OnFirstScan); + buttonRow->Add(new Button(se->T("Next Scan")))->OnClick.Handle(this, &MemoryScannerScreen::OnNextScan); + buttonRow->Add(new Button(di->T("Clear")))->OnClick.Handle(this, &MemoryScannerScreen::OnClear); + + countText_ = root_->Add(new TextView(se->T("Results: 0"), new LinearLayoutParams(Margins(10, 10)))); + countText_->SetShadow(true); + countText_->SetBig(true); + + root_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, 0.0f, 1.0f))) + ->Add(resultsList_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + + root_->Add(new Button(di->T("Back")))->OnClick.Add([this](EventParams &) { TriggerFinish(DR_BACK); }); + + if (g_MemoryScanner.HasScanDone()) { + RebuildResultsList(); + } +} + +void MemoryScannerScreen::update() { + UIScreen::update(); + if (countText_) { + const auto &results = g_MemoryScanner.GetResults(); + auto se = GetI18NCategory(I18NCat::SEARCH); + countText_->SetText(StringFromFormat(se->T_cstr("Results: %d"), (int)results.size())); + } + if (resultsList_) { + resultsList_->SetVisibility(g_MemoryScanner.HasScanDone() ? UI::V_VISIBLE : UI::V_GONE); + } + + // Update live values in the list. + for (size_t i = 0; i < valueChoices_.size(); ++i) { + uint32_t addr = resultAddresses_[i]; + ScanValueType type = resultTypes_[i]; + std::string valStr; + switch (type) { + case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + valueChoices_[i]->SetText(valStr); + } +} + +void MemoryScannerScreen::RebuildResultsList() { + if (!resultsList_) + return; + using namespace UI; + auto se = GetI18NCategory(I18NCat::SEARCH); + resultsList_->Clear(); + valueChoices_.clear(); + resultAddresses_.clear(); + resultTypes_.clear(); + + auto &results = g_MemoryScanner.GetResults(); + + if (results.empty()) + return; + + LinearLayout *header = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + auto *addrHeader = header->Add(new TextView(se->T("Address"), new LinearLayoutParams(200.0f, WRAP_CONTENT))); + addrHeader->SetShadow(true); + addrHeader->SetPadding(Margins(16, 0)); + auto *valHeader = header->Add(new TextView(se->T("Value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); + valHeader->SetShadow(true); + valHeader->SetPadding(Margins(16, 0)); + auto *lockHeader = header->Add(new TextView(se->T("Lock"), new LinearLayoutParams(100.0f, WRAP_CONTENT))); + lockHeader->SetShadow(true); + lockHeader->SetPadding(Margins(16, 0)); + + int count = 0; + for (size_t i = 0; i < results.size(); ++i) { + LinearLayout *row = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + uint32_t addr = results[i].address; + ScanValueType type = results[i].type; + + row->Add(new Choice(StringFromFormat("0x%08X", addr), new LinearLayoutParams(200.0f, WRAP_CONTENT))); + + std::string valStr; + switch (type) { + case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + + Choice *valChoice = row->Add(new Choice(valStr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); + valChoice->OnClick.Add([this, addr, type](EventParams &e) { + OnValueClick(addr, type); + }); + valueChoices_.push_back(valChoice); + resultAddresses_.push_back(addr); + resultTypes_.push_back(type); + + auto *lockCheck = row->Add(new CheckBox(&results[i].locked, "", "", new LinearLayoutParams(100.0f, WRAP_CONTENT))); + lockCheck->OnClick.Add([i](EventParams &e) { + g_MemoryScanner.SetLocked(i, g_MemoryScanner.GetResults()[i].locked); + }); + + if (++count > 100) break; // Limit UI items + } +} + +void MemoryScannerScreen::OnFirstScan(UI::EventParams &e) { + g_MemoryScanner.FirstScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); + RebuildResultsList(); +} + +void MemoryScannerScreen::OnNextScan(UI::EventParams &e) { + if (g_MemoryScanner.HasScanDone()) { + g_MemoryScanner.NextScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); + RebuildResultsList(); + } +} + +void MemoryScannerScreen::OnClear(UI::EventParams &e) { + g_MemoryScanner.Clear(); + RebuildResultsList(); +} + +void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { + std::string currentVal; + switch (type) { + case ScanValueType::U8: currentVal = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: currentVal = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: currentVal = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + + auto se = GetI18NCategory(I18NCat::SEARCH); + UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, se->T("Edit Value"), [addr, type](const std::string &value, bool ok) { + if (ok) { + try { + auto val = (uint32_t)std::stoul(value, nullptr, 0); + switch (type) { + case ScanValueType::U8: Memory::Write_U8((uint8_t)val, addr); break; + case ScanValueType::U16: Memory::Write_U16((uint16_t)val, addr); break; + case ScanValueType::U32: Memory::Write_U32(val, addr); break; + } + + // Also update lock value if locked. + for (auto &res : g_MemoryScanner.GetResults()) { + if (res.address == addr && res.type == type && res.locked) { + res.lockValue = val; + } + } + } catch (...) { + // Ignore invalid input. + } + } + }); +} diff --git a/UI/MemoryScannerScreen.h b/UI/MemoryScannerScreen.h new file mode 100644 index 000000000000..7843fd8033b6 --- /dev/null +++ b/UI/MemoryScannerScreen.h @@ -0,0 +1,54 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include +#include + +#include "Common/File/Path.h" +#include "Common/UI/UIScreen.h" +#include "Common/UI/View.h" +#include "Common/UI/ViewGroup.h" +#include "Core/MemoryScanner.h" + +class MemoryScannerScreen : public UIDialogScreen { +public: + MemoryScannerScreen(Path gamePath); + ~MemoryScannerScreen() override; + + void CreateViews() override; + void update() override; + void RebuildResultsList(); + + [[nodiscard]] const char *tag() const override { return "MemoryScanner"; } + +private: + void OnFirstScan(UI::EventParams &e); + void OnNextScan(UI::EventParams &e); + void OnClear(UI::EventParams &e); + void OnValueClick(uint32_t addr, ScanValueType type); + + Path gamePath_; + + UI::TextView *countText_ = nullptr; + UI::TextEdit *searchValueEdit_ = nullptr; + UI::LinearLayout *resultsList_ = nullptr; + std::vector valueChoices_; + std::vector resultAddresses_; + std::vector resultTypes_; +}; diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 521d2252407f..400aeeac5a34 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -56,7 +56,7 @@ #include "GPU/GPUState.h" #include "UI/EmuScreen.h" -#include "UI/MemoryScanner.h" +#include "UI/MemoryScannerScreen.h" #include "UI/PauseScreen.h" #include "UI/GameSettingsScreen.h" #include "UI/ReportScreen.h" diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index 8829b29268b5..0f07a94f8c55 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -59,7 +59,7 @@ - + @@ -119,7 +119,7 @@ - + diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 84ed70d5c24e..b5820afecb00 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -16,7 +16,7 @@ Screens - + Screens @@ -169,7 +169,7 @@ Screens - + Screens diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index dadb1715b22a..3d3ca9cb1817 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -94,6 +94,7 @@ + @@ -366,6 +367,7 @@ + @@ -1035,4 +1037,4 @@ - \ No newline at end of file + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 211b5a941091..817e0e198fc1 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -9,6 +9,7 @@ + @@ -422,6 +423,7 @@ + @@ -688,4 +690,4 @@ - \ No newline at end of file + diff --git a/UWP/UI_UWP/UI_UWP.vcxproj b/UWP/UI_UWP/UI_UWP.vcxproj index 03178d7ce696..0c85439a4153 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj +++ b/UWP/UI_UWP/UI_UWP.vcxproj @@ -124,7 +124,7 @@ - + @@ -183,7 +183,7 @@ - + diff --git a/UWP/UI_UWP/UI_UWP.vcxproj.filters b/UWP/UI_UWP/UI_UWP.vcxproj.filters index a298a51f82f2..42e755ddf0a4 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj.filters +++ b/UWP/UI_UWP/UI_UWP.vcxproj.filters @@ -88,7 +88,7 @@ Screens - + Screens @@ -231,7 +231,7 @@ Screens - + Screens diff --git a/android/jni/Android.mk b/android/jni/Android.mk index c70db4c98a83..60c5f3103bc1 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -619,6 +619,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/KeyMap.cpp \ $(SRC)/Core/KeyMapDefaults.cpp \ $(SRC)/Core/LuaContext.cpp \ + $(SRC)/Core/MemoryScanner.cpp \ $(SRC)/Core/Loaders.cpp \ $(SRC)/Core/PSPLoaders.cpp \ $(SRC)/Core/FileLoaders/CachingFileLoader.cpp \ @@ -946,7 +947,7 @@ LOCAL_SRC_FILES := \ $(SRC)/UI/RemoteISOScreen.cpp \ $(SRC)/UI/ReportScreen.cpp \ $(SRC)/UI/PauseScreen.cpp \ - $(SRC)/UI/MemoryScanner.cpp \ + $(SRC)/UI/MemoryScannerScreen.cpp \ $(SRC)/UI/SavedataScreen.cpp \ $(SRC)/UI/Store.cpp \ $(SRC)/UI/SystemInfoScreen.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 6bdb4effac48..ddcf0491470d 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -716,6 +716,7 @@ SOURCES_CXX += \ $(EXTDIR)/jpge/jpge.cpp \ $(COREDIR)/AVIDump.cpp \ $(COREDIR)/Config.cpp \ + $(COREDIR)/MemoryScanner.cpp \ $(COREDIR)/ConfigSettings.cpp \ $(COREDIR)/ControlMapper.cpp \ $(COREDIR)/Core.cpp \ From aff09557ae1368360467d7fbdcda8c0810161bda Mon Sep 17 00:00:00 2001 From: sum2012 Date: Mon, 1 Jun 2026 00:25:28 +0800 Subject: [PATCH 05/11] Forget remove these file. --- UI/MemoryScanner.cpp | 339 ------------------------------------------- UI/MemoryScanner.h | 90 ------------ 2 files changed, 429 deletions(-) delete mode 100644 UI/MemoryScanner.cpp delete mode 100644 UI/MemoryScanner.h diff --git a/UI/MemoryScanner.cpp b/UI/MemoryScanner.cpp deleted file mode 100644 index 18ece33b88b7..000000000000 --- a/UI/MemoryScanner.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include -#include -#include "UI/MemoryScanner.h" -#include "Common/UI/Context.h" -#include "Common/UI/UIScreen.h" -#include "Common/UI/View.h" -#include "Common/UI/ViewGroup.h" -#include "Common/UI/ScrollView.h" -#include "Common/UI/PopupScreens.h" -#include "Common/UI/TabHolder.h" -#include "Common/Data/Text/I18n.h" -#include "Core/MemMap.h" -#include "Core/System.h" -#include "Common/StringUtils.h" - -MemoryScanner g_MemoryScanner; - -void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { - results_.clear(); - uint32_t val = 0; - try { - val = (uint32_t)std::stoul(filter, nullptr, 0); - } catch (...) { - return; - } - - uint32_t startAddr = 0x08000000; - uint32_t endAddr = startAddr + Memory::g_MemorySize; - - for (uint32_t addr = startAddr; addr < endAddr; ) { - bool match = false; - switch (type) { - case ScanValueType::U8: - if (Memory::Read_U8(addr) == (uint8_t)val) match = true; - addr += 1; - break; - case ScanValueType::U16: - if (addr + 2 <= endAddr && Memory::Read_U16(addr) == (uint16_t)val) match = true; - addr += 1; - break; - case ScanValueType::U32: - if (addr + 4 <= endAddr && Memory::Read_U32(addr) == (uint32_t)val) match = true; - addr += 1; - break; - } - - if (match) { - results_.emplace_back(addr - 1, type); - if (results_.size() > 1000) break; - } - } - firstScanDone_ = true; -} - -void MemoryScanner::NextScan(ScanValueType type, const std::string &filter) { - uint32_t val = 0; - try { - val = (uint32_t)std::stoul(filter, nullptr, 0); - } catch (...) { - return; - } - - std::vector nextResults; - for (const auto &res : results_) { - bool match = false; - switch (type) { - case ScanValueType::U8: - if (Memory::Read_U8(res.address) == (uint8_t)val) match = true; - break; - case ScanValueType::U16: - if (Memory::Read_U16(res.address) == (uint16_t)val) match = true; - break; - case ScanValueType::U32: - if (Memory::Read_U32(res.address) == (uint32_t)val) match = true; - break; - } - - if (match) { - nextResults.push_back(res); - } - } - results_ = std::move(nextResults); -} - -void MemoryScanner::Clear() { - results_.clear(); - firstScanDone_ = false; -} - -void MemoryScanner::Update() { - for (auto &res : results_) { - if (res.locked) { - switch (res.type) { - case ScanValueType::U8: - Memory::Write_U8((uint8_t)res.lockValue, res.address); - break; - case ScanValueType::U16: - Memory::Write_U16((uint16_t)res.lockValue, res.address); - break; - case ScanValueType::U32: - Memory::Write_U32(res.lockValue, res.address); - break; - } - } - } -} - -void MemoryScanner::SetLocked(size_t index, bool locked) { - if (index < results_.size()) { - results_[index].locked = locked; - if (results_[index].locked) { - // Capture current value to lock it to. - switch (results_[index].type) { - case ScanValueType::U8: - results_[index].lockValue = Memory::Read_U8(results_[index].address); - break; - case ScanValueType::U16: - results_[index].lockValue = Memory::Read_U16(results_[index].address); - break; - case ScanValueType::U32: - results_[index].lockValue = Memory::Read_U32(results_[index].address); - break; - } - } - } -} - -MemoryScannerScreen::MemoryScannerScreen(Path gamePath) : UIDialogScreen(), gamePath_(std::move(gamePath)), resultsList_(nullptr) { -} - -MemoryScannerScreen::~MemoryScannerScreen() = default; - -void MemoryScannerScreen::CreateViews() { - using namespace UI; - - auto di = GetI18NCategory(I18NCat::DIALOG); - auto se = GetI18NCategory(I18NCat::SEARCH); - - root_ = new LinearLayout(ORIENT_VERTICAL); - - root_->Add(new ItemHeader(se->T("Memory Scanner"))); - - searchValueEdit_ = root_->Add(new TextEdit(g_MemoryScanner.searchValue, se->T("Value to search"), se->T("Enter value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - searchValueEdit_->OnTextChange.Add([this](EventParams &e) { - g_MemoryScanner.searchValue = searchValueEdit_->GetText(); - }); - - LinearLayout *typeRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); - typeRow->Add(new TextView(se->T("Value Type"), new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); - - ChoiceStrip *typeStrip = typeRow->Add(new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT))); - typeStrip->AddChoice(se->T("8-bit")); - typeStrip->AddChoice(se->T("16-bit")); - typeStrip->AddChoice(se->T("32-bit")); - typeStrip->SetSelection((int)g_MemoryScanner.valueType, false); - typeStrip->OnChoice.Add([](EventParams &e) { - g_MemoryScanner.valueType = (ScanValueType)e.a; - }); - - LinearLayout *buttonRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); - buttonRow->Add(new Button(se->T("First Scan")))->OnClick.Handle(this, &MemoryScannerScreen::OnFirstScan); - buttonRow->Add(new Button(se->T("Next Scan")))->OnClick.Handle(this, &MemoryScannerScreen::OnNextScan); - buttonRow->Add(new Button(di->T("Clear")))->OnClick.Handle(this, &MemoryScannerScreen::OnClear); - - countText_ = root_->Add(new TextView(se->T("Results: 0"), new LinearLayoutParams(Margins(10, 10)))); - countText_->SetShadow(true); - countText_->SetBig(true); - - root_->Add(new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, 0.0f, 1.0f))) - ->Add(resultsList_ = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - - root_->Add(new Button(di->T("Back")))->OnClick.Add([this](EventParams &) { TriggerFinish(DR_BACK); }); - - if (g_MemoryScanner.HasScanDone()) { - RebuildResultsList(); - } -} - -void MemoryScannerScreen::update() { - UIScreen::update(); - if (countText_) { - const auto &results = g_MemoryScanner.GetResults(); - auto se = GetI18NCategory(I18NCat::SEARCH); - countText_->SetText(StringFromFormat(se->T_cstr("Results: %d"), (int)results.size())); - } - if (resultsList_) { - resultsList_->SetVisibility(g_MemoryScanner.HasScanDone() ? UI::V_VISIBLE : UI::V_GONE); - } - - // Update live values in the list. - for (size_t i = 0; i < valueChoices_.size(); ++i) { - uint32_t addr = resultAddresses_[i]; - ScanValueType type = resultTypes_[i]; - std::string valStr; - switch (type) { - case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; - case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; - case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; - } - valueChoices_[i]->SetText(valStr); - } -} - -void MemoryScannerScreen::RebuildResultsList() { - if (!resultsList_) - return; - using namespace UI; - auto se = GetI18NCategory(I18NCat::SEARCH); - resultsList_->Clear(); - valueChoices_.clear(); - resultAddresses_.clear(); - resultTypes_.clear(); - - auto &results = g_MemoryScanner.GetResults(); - - if (results.empty()) - return; - - LinearLayout *header = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - auto *addrHeader = header->Add(new TextView(se->T("Address"), new LinearLayoutParams(200.0f, WRAP_CONTENT))); - addrHeader->SetShadow(true); - addrHeader->SetPadding(Margins(16, 0)); - auto *valHeader = header->Add(new TextView(se->T("Value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); - valHeader->SetShadow(true); - valHeader->SetPadding(Margins(16, 0)); - auto *typeHeader = header->Add(new TextView(se->T("Value Type"), new LinearLayoutParams(150.0f, WRAP_CONTENT))); - typeHeader->SetShadow(true); - typeHeader->SetPadding(Margins(16, 0)); - auto *lockHeader = header->Add(new TextView(se->T("Lock"), new LinearLayoutParams(100.0f, WRAP_CONTENT))); - lockHeader->SetShadow(true); - lockHeader->SetPadding(Margins(16, 0)); - - int count = 0; - for (size_t i = 0; i < results.size(); ++i) { - LinearLayout *row = resultsList_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - uint32_t addr = results[i].address; - ScanValueType type = results[i].type; - - row->Add(new Choice(StringFromFormat("0x%08X", addr), new LinearLayoutParams(200.0f, WRAP_CONTENT))); - - std::string valStr; - switch (type) { - case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; - case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; - case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; - } - - Choice *valChoice = row->Add(new Choice(valStr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); - valChoice->OnClick.Add([this, addr, type](EventParams &e) { - OnValueClick(addr, type); - }); - valueChoices_.push_back(valChoice); - resultAddresses_.push_back(addr); - resultTypes_.push_back(type); - - std::string typeStr; - switch (type) { - case ScanValueType::U8: typeStr = se->T("8-bit"); break; - case ScanValueType::U16: typeStr = se->T("16-bit"); break; - case ScanValueType::U32: typeStr = se->T("32-bit"); break; - } - auto *typeView = row->Add(new TextView(typeStr, new LinearLayoutParams(150.0f, WRAP_CONTENT))); - typeView->SetShadow(true); - typeView->SetPadding(Margins(16, 0)); - - auto *lockCheck = row->Add(new CheckBox(&results[i].locked, "", "", new LinearLayoutParams(100.0f, WRAP_CONTENT))); - lockCheck->OnClick.Add([i](EventParams &e) { - g_MemoryScanner.SetLocked(i, g_MemoryScanner.GetResults()[i].locked); - }); - - if (++count > 100) break; // Limit UI items - } -} - -void MemoryScannerScreen::OnFirstScan(UI::EventParams &e) { - g_MemoryScanner.FirstScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); - RebuildResultsList(); -} - -void MemoryScannerScreen::OnNextScan(UI::EventParams &e) { - if (g_MemoryScanner.HasScanDone()) { - g_MemoryScanner.NextScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); - RebuildResultsList(); - } -} - -void MemoryScannerScreen::OnClear(UI::EventParams &e) { - g_MemoryScanner.Clear(); - RebuildResultsList(); -} - -void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { - std::string currentVal; - switch (type) { - case ScanValueType::U8: currentVal = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; - case ScanValueType::U16: currentVal = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; - case ScanValueType::U32: currentVal = StringFromFormat("%u", Memory::Read_U32(addr)); break; - } - - auto se = GetI18NCategory(I18NCat::SEARCH); - UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, se->T("Edit Value"), [addr, type](const std::string &value, bool ok) { - if (ok) { - try { - auto val = (uint32_t)std::stoul(value, nullptr, 0); - switch (type) { - case ScanValueType::U8: Memory::Write_U8((uint8_t)val, addr); break; - case ScanValueType::U16: Memory::Write_U16((uint16_t)val, addr); break; - case ScanValueType::U32: Memory::Write_U32(val, addr); break; - } - - // Also update lock value if locked. - for (auto &res : g_MemoryScanner.GetResults()) { - if (res.address == addr && res.type == type && res.locked) { - res.lockValue = val; - } - } - } catch (...) { - // Ignore invalid input. - } - } - }); -} diff --git a/UI/MemoryScanner.h b/UI/MemoryScanner.h deleted file mode 100644 index 2facf5fecad0..000000000000 --- a/UI/MemoryScanner.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2012- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -#include -#include - -#include "Common/File/Path.h" -#include "Common/UI/UIScreen.h" -#include "Common/UI/View.h" -#include "Common/UI/ViewGroup.h" - -enum class ScanValueType { - U8, - U16, - U32, -}; - -struct ScanResult { - ScanResult(uint32_t addr = 0, ScanValueType t = ScanValueType::U8) - : address(addr), type(t) {} - uint32_t address; - ScanValueType type; - bool locked = false; - uint32_t lockValue = 0; -}; - -class MemoryScanner { -public: - void FirstScan(ScanValueType type, const std::string &filter); - void NextScan(ScanValueType type, const std::string &filter); - void Clear(); - void Update(); - void SetLocked(size_t index, bool locked); - - [[nodiscard]] const std::vector &GetResults() const { return results_; } - std::vector &GetResults() { return results_; } - [[nodiscard]] bool HasScanDone() const { return firstScanDone_; } - - ScanValueType valueType = ScanValueType::U32; - std::string searchValue = "0"; - -private: - std::vector results_; - bool firstScanDone_ = false; -}; - -extern MemoryScanner g_MemoryScanner; - -class MemoryScannerScreen : public UIDialogScreen { -public: - MemoryScannerScreen(Path gamePath); - ~MemoryScannerScreen() override; - - void CreateViews() override; - void update() override; - void RebuildResultsList(); - - [[nodiscard]] const char *tag() const override { return "MemoryScanner"; } - -private: - void OnFirstScan(UI::EventParams &e); - void OnNextScan(UI::EventParams &e); - void OnClear(UI::EventParams &e); - void OnValueClick(uint32_t addr, ScanValueType type); - - Path gamePath_; - - UI::TextView *countText_ = nullptr; - UI::TextEdit *searchValueEdit_ = nullptr; - UI::LinearLayout *resultsList_ = nullptr; - std::vector valueChoices_; - std::vector resultAddresses_; - std::vector resultTypes_; -}; From e2047de7f1831e8f2528d4a0b3de88aae6fa1f0b Mon Sep 17 00:00:00 2001 From: sum2012 Date: Mon, 1 Jun 2026 20:29:18 +0800 Subject: [PATCH 06/11] Restrict the search to the main executable's data section --- Core/HLE/sceKernelModule.cpp | 17 ++++++++++++++++- Core/HLE/sceKernelModule.h | 1 + Core/MemoryScanner.cpp | 11 +++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 7f36b7e1bf46..b902e3b9f045 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -431,6 +431,7 @@ struct SceKernelSMOption { static int actionAfterModule; static std::set loadedModules; +static SceUID g_mainModuleID = 0; // STATE END ////////////////////////////////////////////////////////////////////////// @@ -441,7 +442,7 @@ static void __KernelModuleInit() void __KernelModuleDoState(PointerWrap &p) { - auto s = p.Section("sceKernelModule", 1, 2); + auto s = p.Section("sceKernelModule", 1, 3); if (!s) return; @@ -451,6 +452,9 @@ void __KernelModuleDoState(PointerWrap &p) if (s >= 2) { Do(p, loadedModules); } + if (s >= 3) { + Do(p, g_mainModuleID); + } if (p.mode == p.MODE_READ) { u32 error; @@ -473,6 +477,7 @@ void __KernelModuleDoState(PointerWrap &p) void __KernelModuleShutdown() { loadedModules.clear(); + g_mainModuleID = 0; MIPSAnalyst::Reset(); HLEPlugins::Unload(); } @@ -1712,6 +1717,7 @@ bool KernelModuleIsKernelMode(SceUID uid) { void __KernelLoadReset() { // Wipe kernel here, loadexec should reset the entire system + g_mainModuleID = 0; if (__KernelIsRunning()) { u32 error; while (!loadedModules.empty()) { @@ -1776,6 +1782,10 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str size_t size = fileData.size(); PSPModule *module = __KernelLoadModule(fileData.data(), size, 0, filename, error_string); + if (module) { + g_mainModuleID = module->GetUID(); + } + if (!module || module->isFake) { if (module) { module->Cleanup(); @@ -1848,6 +1858,7 @@ bool __KernelLoadGEDump(std::string_view base_filename, std::string *error_strin memset(&module->nm, 0, sizeof(module->nm)); module->isFake = true; module->nm.entry_addr = codeStartAddr; + g_mainModuleID = module->GetUID(); module->nm.gp_value = -1; SceUID threadID = __KernelSetupRootThread(module->GetUID(), (int)base_filename.size(), base_filename.data(), 0x20, 0x1000, 0); @@ -2416,6 +2427,10 @@ u32 sceKernelFindModuleByUID(u32 uid) return hleLogInfo(Log::sceModule, module->modulePtr.ptr); } +SceUID __KernelGetMainModuleId() { + return g_mainModuleID; +} + u32 sceKernelFindModuleByName(const char *name) { u32 error; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 13af5ef5efe6..b0c33672536a 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -234,6 +234,7 @@ SceUID KernelLoadModule(const std::string &filename, std::string *error_string); int __KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, SceKernelSMOption *smoption, bool *needsWait); u32 __KernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus); u32 sceKernelFindModuleByUID(u32 uid); +SceUID __KernelGetMainModuleId(); void Register_ModuleMgrForUser(); void Register_ModuleMgrForKernel(); diff --git a/Core/MemoryScanner.cpp b/Core/MemoryScanner.cpp index 16c86fc39a28..83654661b079 100644 --- a/Core/MemoryScanner.cpp +++ b/Core/MemoryScanner.cpp @@ -21,6 +21,7 @@ #include "Core/MemoryScanner.h" #include "Core/MemMap.h" #include "Core/System.h" +#include "Core/HLE/sceKernelModule.h" #include "Common/StringUtils.h" MemoryScanner g_MemoryScanner; @@ -37,6 +38,16 @@ void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { uint32_t startAddr = 0x08000000; uint32_t endAddr = startAddr + Memory::g_MemorySize; + SceUID mainModuleID = __KernelGetMainModuleId(); + if (mainModuleID != 0) { + u32 error; + auto *mainModule = kernelObjects.Get(mainModuleID, error); + if (mainModule) { + startAddr = mainModule->GetDataAddr(); + endAddr = startAddr + mainModule->nm.data_size + mainModule->nm.bss_size; + } + } + for (uint32_t addr = startAddr; addr < endAddr; ) { bool match = false; switch (type) { From f80b57c3970d0af6763383cbbacc281109fb258f Mon Sep 17 00:00:00 2001 From: sum2012 Date: Mon, 1 Jun 2026 22:19:11 +0800 Subject: [PATCH 07/11] Add support muti tab Not tested for muti lock The code has avoid duplicate address. Set default 16-bit mode. --- Core/MemoryScanner.cpp | 61 +++++++++++++++++++-- Core/MemoryScanner.h | 26 +++++++-- UI/MemoryScannerScreen.cpp | 105 +++++++++++++++++++++++++++---------- 3 files changed, 158 insertions(+), 34 deletions(-) diff --git a/Core/MemoryScanner.cpp b/Core/MemoryScanner.cpp index 83654661b079..89a5438ac430 100644 --- a/Core/MemoryScanner.cpp +++ b/Core/MemoryScanner.cpp @@ -24,7 +24,7 @@ #include "Core/HLE/sceKernelModule.h" #include "Common/StringUtils.h" -MemoryScanner g_MemoryScanner; +MemoryScannerManager g_MemoryScanner; void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { results_.clear(); @@ -126,10 +126,13 @@ void MemoryScanner::Update() { } } -void MemoryScanner::SetLocked(size_t index, bool locked) { +bool MemoryScanner::SetLocked(size_t index, bool locked) { if (index < results_.size()) { - results_[index].locked = locked; - if (results_[index].locked) { + if (locked) { + if (g_MemoryScanner.HasLockedAddress(results_[index].address, this, index)) { + results_[index].locked = false; + return false; + } // Capture current value to lock it to. switch (results_[index].type) { case ScanValueType::U8: @@ -143,5 +146,55 @@ void MemoryScanner::SetLocked(size_t index, bool locked) { break; } } + results_[index].locked = locked; + return true; + } + return false; +} + +MemoryScannerManager::MemoryScannerManager() { + scanners_.push_back(new MemoryScanner()); +} + +void MemoryScannerManager::Update() { + for (auto scanner : scanners_) { + scanner->Update(); + } +} + +void MemoryScannerManager::SetActiveIndex(int index) { + if (index >= 0 && index < (int)scanners_.size()) { + activeScanner_ = index; + } +} + +bool MemoryScannerManager::HasLockedAddress(uint32_t addr, const MemoryScanner *excludeScanner, size_t excludeIndex) const { + for (auto scanner : scanners_) { + const auto &results = scanner->GetResults(); + for (size_t i = 0; i < results.size(); ++i) { + if (scanner == excludeScanner && i == excludeIndex) + continue; + if (results[i].locked && results[i].address == addr) + return true; + } + } + return false; +} + +void MemoryScannerManager::AddScanner() { + scanners_.push_back(new MemoryScanner()); + activeScanner_ = (int)scanners_.size() - 1; +} + +void MemoryScannerManager::RemoveScanner(int index) { + if (scanners_.size() <= 1) { + return; + } + if (index >= 0 && index < (int)scanners_.size()) { + delete scanners_[index]; + scanners_.erase(scanners_.begin() + index); + if (activeScanner_ >= (int)scanners_.size()) { + activeScanner_ = (int)scanners_.size() - 1; + } } } diff --git a/Core/MemoryScanner.h b/Core/MemoryScanner.h index 9ea3190d3893..45c08c1d55af 100644 --- a/Core/MemoryScanner.h +++ b/Core/MemoryScanner.h @@ -42,13 +42,13 @@ class MemoryScanner { void NextScan(ScanValueType type, const std::string &filter); void Clear(); void Update(); - void SetLocked(size_t index, bool locked); + bool SetLocked(size_t index, bool locked); [[nodiscard]] const std::vector &GetResults() const { return results_; } std::vector &GetResults() { return results_; } [[nodiscard]] bool HasScanDone() const { return firstScanDone_; } - ScanValueType valueType = ScanValueType::U32; + ScanValueType valueType = ScanValueType::U16; std::string searchValue = "0"; private: @@ -56,4 +56,24 @@ class MemoryScanner { bool firstScanDone_ = false; }; -extern MemoryScanner g_MemoryScanner; +class MemoryScannerManager { +public: + MemoryScannerManager(); + void Update(); + + MemoryScanner *GetActive() { return scanners_[activeScanner_]; } + int GetActiveIndex() const { return activeScanner_; } + void SetActiveIndex(int index); + + bool HasLockedAddress(uint32_t addr, const MemoryScanner *excludeScanner, size_t excludeIndex) const; + + void AddScanner(); + void RemoveScanner(int index); + int GetCount() const { return (int)scanners_.size(); } + +private: + std::vector scanners_; + int activeScanner_ = 0; +}; + +extern MemoryScannerManager g_MemoryScanner; diff --git a/UI/MemoryScannerScreen.cpp b/UI/MemoryScannerScreen.cpp index 0f400036e565..c4e43d0ef726 100644 --- a/UI/MemoryScannerScreen.cpp +++ b/UI/MemoryScannerScreen.cpp @@ -45,9 +45,40 @@ void MemoryScannerScreen::CreateViews() { root_->Add(new ItemHeader(se->T("Memory Scanner"))); - searchValueEdit_ = root_->Add(new TextEdit(g_MemoryScanner.searchValue, se->T("Value to search"), se->T("Enter value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); - searchValueEdit_->OnTextChange.Add([this](EventParams &e) { - g_MemoryScanner.searchValue = searchValueEdit_->GetText(); + LinearLayout *tabRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + ChoiceStrip *tabs = tabRow->Add(new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(1.0f))); + for (int i = 0; i < g_MemoryScanner.GetCount(); ++i) { + tabs->AddChoice(StringFromFormat("%d", i + 1)); + } + // Make all choices in the ChoiceStrip expand equally. + for (int i = 0; i < tabs->GetNumSubviews(); ++i) { + View *v = tabs->GetViewByIndex(i); + if (v) { + v->ReplaceLayoutParams(new LinearLayoutParams(1.0f)); + } + } + tabs->SetSelection(g_MemoryScanner.GetActiveIndex(), false); + tabs->OnChoice.Add([this](EventParams &e) { + g_MemoryScanner.SetActiveIndex((int)e.a); + RecreateViews(); + }); + + tabRow->Add(new Button("+", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Add([this](EventParams &e) { + g_MemoryScanner.AddScanner(); + RecreateViews(); + }); + if (g_MemoryScanner.GetCount() > 1) { + tabRow->Add(new Button("-", new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT)))->OnClick.Add([this](EventParams &e) { + g_MemoryScanner.RemoveScanner(g_MemoryScanner.GetActiveIndex()); + RecreateViews(); + }); + } + + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + + searchValueEdit_ = root_->Add(new TextEdit(scanner->searchValue, se->T("Value to search"), se->T("Enter value"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT))); + searchValueEdit_->OnTextChange.Add([scanner, this](EventParams &e) { + scanner->searchValue = searchValueEdit_->GetText(); }); LinearLayout *typeRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); @@ -57,9 +88,9 @@ void MemoryScannerScreen::CreateViews() { typeStrip->AddChoice(se->T("8-bit")); typeStrip->AddChoice(se->T("16-bit")); typeStrip->AddChoice(se->T("32-bit")); - typeStrip->SetSelection((int)g_MemoryScanner.valueType, false); - typeStrip->OnChoice.Add([](EventParams &e) { - g_MemoryScanner.valueType = (ScanValueType)e.a; + typeStrip->SetSelection((int)scanner->valueType, false); + typeStrip->OnChoice.Add([scanner](EventParams &e) { + scanner->valueType = (ScanValueType)e.a; }); LinearLayout *buttonRow = root_->Add(new LinearLayout(ORIENT_HORIZONTAL)); @@ -76,33 +107,41 @@ void MemoryScannerScreen::CreateViews() { root_->Add(new Button(di->T("Back")))->OnClick.Add([this](EventParams &) { TriggerFinish(DR_BACK); }); - if (g_MemoryScanner.HasScanDone()) { + if (scanner->HasScanDone()) { RebuildResultsList(); } } void MemoryScannerScreen::update() { UIScreen::update(); + MemoryScanner *scanner = g_MemoryScanner.GetActive(); if (countText_) { - const auto &results = g_MemoryScanner.GetResults(); + const auto &results = scanner->GetResults(); auto se = GetI18NCategory(I18NCat::SEARCH); countText_->SetText(StringFromFormat(se->T_cstr("Results: %d"), (int)results.size())); } if (resultsList_) { - resultsList_->SetVisibility(g_MemoryScanner.HasScanDone() ? UI::V_VISIBLE : UI::V_GONE); + resultsList_->SetVisibility(scanner->HasScanDone() ? UI::V_VISIBLE : UI::V_GONE); } // Update live values in the list. - for (size_t i = 0; i < valueChoices_.size(); ++i) { - uint32_t addr = resultAddresses_[i]; - ScanValueType type = resultTypes_[i]; - std::string valStr; - switch (type) { - case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; - case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; - case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + // Only update if the UI is in sync with the current scanner results. + const auto &results = scanner->GetResults(); + if (valueChoices_.size() == std::min((size_t)100, results.size())) { + for (size_t i = 0; i < valueChoices_.size(); ++i) { + uint32_t addr = resultAddresses_[i]; + ScanValueType type = resultTypes_[i]; + std::string valStr; + switch (type) { + case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; + case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; + case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + } + valueChoices_[i]->SetText(valStr); } - valueChoices_[i]->SetText(valStr); + } else if (scanner->HasScanDone()) { + // If out of sync, trigger a rebuild. + RebuildResultsList(); } } @@ -116,7 +155,8 @@ void MemoryScannerScreen::RebuildResultsList() { resultAddresses_.clear(); resultTypes_.clear(); - auto &results = g_MemoryScanner.GetResults(); + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + auto &results = scanner->GetResults(); if (results.empty()) return; @@ -156,8 +196,11 @@ void MemoryScannerScreen::RebuildResultsList() { resultTypes_.push_back(type); auto *lockCheck = row->Add(new CheckBox(&results[i].locked, "", "", new LinearLayoutParams(100.0f, WRAP_CONTENT))); - lockCheck->OnClick.Add([i](EventParams &e) { - g_MemoryScanner.SetLocked(i, g_MemoryScanner.GetResults()[i].locked); + lockCheck->OnClick.Add([scanner, i](EventParams &e) { + if (!scanner->SetLocked(i, scanner->GetResults()[i].locked)) { + auto se = GetI18NCategory(I18NCat::SEARCH); + g_OSD.Show(OSDType::MESSAGE_ERROR, se->T("Address already locked"), 3.0f); + } }); if (++count > 100) break; // Limit UI items @@ -165,19 +208,21 @@ void MemoryScannerScreen::RebuildResultsList() { } void MemoryScannerScreen::OnFirstScan(UI::EventParams &e) { - g_MemoryScanner.FirstScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + scanner->FirstScan(scanner->valueType, scanner->searchValue); RebuildResultsList(); } void MemoryScannerScreen::OnNextScan(UI::EventParams &e) { - if (g_MemoryScanner.HasScanDone()) { - g_MemoryScanner.NextScan(g_MemoryScanner.valueType, g_MemoryScanner.searchValue); + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + if (scanner->HasScanDone()) { + scanner->NextScan(scanner->valueType, scanner->searchValue); RebuildResultsList(); } } void MemoryScannerScreen::OnClear(UI::EventParams &e) { - g_MemoryScanner.Clear(); + g_MemoryScanner.GetActive()->Clear(); RebuildResultsList(); } @@ -200,8 +245,14 @@ void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { case ScanValueType::U32: Memory::Write_U32(val, addr); break; } - // Also update lock value if locked. - for (auto &res : g_MemoryScanner.GetResults()) { + // Also update lock value if locked in ALL scanners. + // For simplicity, we can just iterate all results in the active one, or ALL scanners if we want it global. + // The requirement "add/remove tab for a search" suggests independent searches, but locking might be expected to be global if it's the same address. + // Actually, if it's the same address, it will be updated by the scanner that has it locked. + // If multiple scanners have it locked to different values, it will flicker. + // Let's just update the current scanner's results. + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + for (auto &res : scanner->GetResults()) { if (res.address == addr && res.type == type && res.locked) { res.lockValue = val; } From 6599b956ba71525133a01457750793cfffe23038 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Tue, 2 Jun 2026 04:25:57 +0800 Subject: [PATCH 08/11] allow lock in all tab --- Core/MemoryScanner.h | 3 +++ UI/MemoryScannerScreen.cpp | 29 +++++++++++++++++++++-------- assets/lang/ar_AE.ini | 1 + assets/lang/az_AZ.ini | 1 + assets/lang/be_BY.ini | 1 + assets/lang/bg_BG.ini | 1 + assets/lang/ca_ES.ini | 1 + assets/lang/cz_CZ.ini | 1 + assets/lang/da_DK.ini | 1 + assets/lang/de_DE.ini | 1 + assets/lang/dr_ID.ini | 1 + assets/lang/en_US.ini | 1 + assets/lang/es_ES.ini | 1 + assets/lang/es_LA.ini | 1 + assets/lang/fa_IR.ini | 1 + assets/lang/fi_FI.ini | 1 + assets/lang/fr_FR.ini | 1 + assets/lang/gl_ES.ini | 1 + assets/lang/gr_EL.ini | 1 + assets/lang/he_IL.ini | 1 + assets/lang/he_IL_invert.ini | 1 + assets/lang/hr_HR.ini | 1 + assets/lang/hu_HU.ini | 1 + assets/lang/id_ID.ini | 1 + assets/lang/it_IT.ini | 1 + assets/lang/ja_JP.ini | 1 + assets/lang/jv_ID.ini | 1 + assets/lang/ko_KR.ini | 1 + assets/lang/ku_SO.ini | 1 + assets/lang/lo_LA.ini | 1 + assets/lang/lt-LT.ini | 1 + assets/lang/ms_MY.ini | 1 + assets/lang/nl_NL.ini | 1 + assets/lang/no_NO.ini | 1 + assets/lang/pl_PL.ini | 1 + assets/lang/pt_BR.ini | 1 + assets/lang/pt_PT.ini | 1 + assets/lang/ro_RO.ini | 1 + assets/lang/ru_RU.ini | 1 + assets/lang/sv_SE.ini | 1 + assets/lang/tg_PH.ini | 1 + assets/lang/th_TH.ini | 1 + assets/lang/tr_TR.ini | 1 + assets/lang/uk_UA.ini | 1 + assets/lang/vi_VN.ini | 1 + assets/lang/zh_CN.ini | 1 + assets/lang/zh_TW.ini | 1 + 47 files changed, 69 insertions(+), 8 deletions(-) diff --git a/Core/MemoryScanner.h b/Core/MemoryScanner.h index 45c08c1d55af..ebc8419d78ff 100644 --- a/Core/MemoryScanner.h +++ b/Core/MemoryScanner.h @@ -65,6 +65,9 @@ class MemoryScannerManager { int GetActiveIndex() const { return activeScanner_; } void SetActiveIndex(int index); + bool IsAddressLocked(uint32_t addr) const { + return HasLockedAddress(addr, nullptr, (size_t)-1); + } bool HasLockedAddress(uint32_t addr, const MemoryScanner *excludeScanner, size_t excludeIndex) const; void AddScanner(); diff --git a/UI/MemoryScannerScreen.cpp b/UI/MemoryScannerScreen.cpp index c4e43d0ef726..0f4d121ec18c 100644 --- a/UI/MemoryScannerScreen.cpp +++ b/UI/MemoryScannerScreen.cpp @@ -227,6 +227,25 @@ void MemoryScannerScreen::OnClear(UI::EventParams &e) { } void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { + auto se = GetI18NCategory(I18NCat::SEARCH); + + // Global Respect: If the address is locked in ANY tab, we should be careful. + // If it's locked in the CURRENT tab, we allow editing but must update the lock value. + // If it's locked in ANOTHER tab, we should block it to respect that lock. + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + bool lockedHere = false; + for (const auto &res : scanner->GetResults()) { + if (res.address == addr && res.locked) { + lockedHere = true; + break; + } + } + + if (!lockedHere && g_MemoryScanner.IsAddressLocked(addr)) { + g_OSD.Show(OSDType::MESSAGE_ERROR, se->T("Address locked in another tab"), 3.0f); + return; + } + std::string currentVal; switch (type) { case ScanValueType::U8: currentVal = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; @@ -234,7 +253,6 @@ void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { case ScanValueType::U32: currentVal = StringFromFormat("%u", Memory::Read_U32(addr)); break; } - auto se = GetI18NCategory(I18NCat::SEARCH); UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, se->T("Edit Value"), [addr, type](const std::string &value, bool ok) { if (ok) { try { @@ -245,15 +263,10 @@ void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { case ScanValueType::U32: Memory::Write_U32(val, addr); break; } - // Also update lock value if locked in ALL scanners. - // For simplicity, we can just iterate all results in the active one, or ALL scanners if we want it global. - // The requirement "add/remove tab for a search" suggests independent searches, but locking might be expected to be global if it's the same address. - // Actually, if it's the same address, it will be updated by the scanner that has it locked. - // If multiple scanners have it locked to different values, it will flicker. - // Let's just update the current scanner's results. + // Also update lock value if locked in the active scanner. MemoryScanner *scanner = g_MemoryScanner.GetActive(); for (auto &res : scanner->GetResults()) { - if (res.address == addr && res.type == type && res.locked) { + if (res.address == addr && res.locked) { res.lockValue = val; } } diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 2cb9587fc897..f69902d3b7a7 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -1323,6 +1323,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = العنوان مقفل في تبويب آخر [Store] Connection Error = ‎خطأ في الإتصال diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 5c728dcfc0b0..6d7ebb920bd0 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Ünvan başqa tabda kilidlənib [Store] Connection Error = Qoşuluş yanlışı diff --git a/assets/lang/be_BY.ini b/assets/lang/be_BY.ini index 5e30d259bb61..ae2031180379 100644 --- a/assets/lang/be_BY.ini +++ b/assets/lang/be_BY.ini @@ -1554,6 +1554,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Адрас заблакаваны ў іншай укладцы [UI Elements] %1 button = %1 кнопка diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index f321fe7f954b..db5bb00da38c 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Адресът е заключен в друг раздел [Store] Connection Error = Грешка при свързването diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index d464b1223bdd..c3275a748759 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adreça bloquejada en una altra pestanya [Store] Connection Error = Error de connexió diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index d5fc52fc31c9..73a2d5c0c9b4 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adresa je uzamčena v jiné kartě [Store] Connection Error = Chyba připojení diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index e634ce88090c..d2a94cce46a1 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adressen er låst i en anden fane [Store] Connection Error = Forbindelsesfejl diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index 01b427883b2e..e777b58b7202 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1314,6 +1314,7 @@ Address = Adresse Value = Wert Lock = Sperren Edit Value = Wert bearbeiten +Address locked in another tab = Adresse in einem anderen Tab gesperrt [Store] Connection Error = Verbindungsfehler diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 835d86e49a11..3e28a11e01f4 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Alamat terkunci di tab lain [Store] Connection Error = Connection error diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 46d079eecf81..00cb3e09402d 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -1585,6 +1585,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Address locked in another tab [UI Elements] %1 button = %1 button diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 332975c092fb..07b1eab0a8f1 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1316,6 +1316,7 @@ Address = Dirección Value = Valor Lock = Bloquear Edit Value = Editar valor +Address locked in another tab = Dirección bloqueada en otra pestaña [Store] Connection Error = Error de conexión diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index e942544968e6..d369f7c5a3db 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1317,6 +1317,7 @@ Address = Dirección Value = Valor Lock = Bloquear Edit Value = Editar valor +Address locked in another tab = Dirección bloqueada en otra pestaña [Store] Connection Error = Error de conexión diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 0c4fdb8ec14f..c876236584a9 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = آدرس در تب دیگری قفل شده است [Store] Connection Error = خطای اتصال diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index b9899423794c..b5dd52c3af96 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Osoite on lukittu toisessa välilehdessä [Store] Connection Error = Yhteysvirhe diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index a7385f60feff..d7dad837a318 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1582,6 +1582,7 @@ Address = Adresse Value = Valeur Lock = Bloquer Edit Value = Modifier la valeur +Address locked in another tab = Adresse verrouillée dans un autre onglet [UI Elements] %1 button = %1 bouton diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 1a870f6353a5..097259a84638 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Enderezo bloqueado noutra lapela [Store] Connection Error = Erro de conexión diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 0ad7000cd538..083d56bf39b4 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Η διεύθυνση είναι κλειδωμένη σε άλλη καρτέλα [Store] Connection Error = Σφάλμα σύνδεσης diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index f1f5a7a842b6..ad96ee7f3f53 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = הכתובת נעולה בלשונית אחרת [Store] Connection Error = Connection error diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 3636549fbf9b..e61e8eafffe9 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = הכתובת נעולה בלשונית אחרת [Store] Connection Error = Connection error diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index be7979e4094b..b53db6bd9d1d 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adresa je zaključana u drugoj kartici [Store] Connection Error = Pogreška u spajanju diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 735dc027c451..f61ac76410d6 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Cím zárolva egy másik lapon [Store] Connection Error = Kapcsolódási hiba diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 5372494419de..2f43f51fa239 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Alamat terkunci di tab lain [Store] Connection Error = Kesalahan pada koneksi diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index a9fc25a68256..a85b826fbc4e 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1318,6 +1318,7 @@ Address = Indirizzo Value = Valore Lock = Blocca Edit Value = Modifica valore +Address locked in another tab = Indirizzo bloccato in un'altra scheda [Store] Connection Error = Errore di connessione diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index d71adff6befa..fd7a11331704 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1315,6 +1315,7 @@ Address = アドレス Value = 値 Lock = 固定 Edit Value = 値の編集 +Address locked in another tab = アドレスは別のタブでロックされています [Store] Connection Error = 接続エラー diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 651725b42c20..80111a5addb3 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Alamat dikunci ing tab liyane [Store] Connection Error = Galat koneksi diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 39b7744676e9..24d36c403326 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1554,6 +1554,7 @@ Address = 주소 Value = 값 Lock = 고정 Edit Value = 값 편집 +Address locked in another tab = 주소가 다른 탭에서 잠겨 있습니다 [UI Elements] %1 button = %1 버튼 diff --git a/assets/lang/ku_SO.ini b/assets/lang/ku_SO.ini index ef0754b5bad8..cdbff3bba1fa 100644 --- a/assets/lang/ku_SO.ini +++ b/assets/lang/ku_SO.ini @@ -1568,6 +1568,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = ناونیشانەکە لە تابێکی تردا قفڵ کراوە [UI Elements] %1 button = %1 button diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 92580ab9e200..4bd98d8eceff 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = ທີ່ຢູ່ຖືກລັອກຢູ່ໃນແທັບອື່ນ [Store] Connection Error = ການເຊື່ອມຕໍ່ລົ້ມເຫຼວ diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 4325cdb472ce..f68c6e1b0989 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adresas užrakintas kitoje kortelėje [Store] Connection Error = Prisijungimo klaida diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index d461a5d0f73b..6b2fa8a382b8 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Alamat dikunci dalam tab lain [Store] Connection Error = Kesalahan Sambungan diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index ca211b31e1e7..0bfde77331ce 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adres vergrendeld in een another tabblad [Store] Connection Error = Verbindingsfout diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 2c5e4f8f315e..b183ab42aa36 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adressen er låst i en annen fane [Store] Connection Error = Tilkoblingsfeil diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index bc9e649259a4..1bea8eec6f33 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1323,6 +1323,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adres zablokowany w innej karcie [Store] Connection Error = Błąd połączenia diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index ccf00ae13c05..1d38c8a735a1 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -1585,6 +1585,7 @@ Address = Endereço Value = Valor Lock = Bloquear Edit Value = Editar valor +Address locked in another tab = Endereço bloqueado em outra aba [UI Elements] %1 button = %1 botão diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index d67e1b19bd73..ffa4ce0b8dd9 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -1579,6 +1579,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Endereço bloqueado noutro separador [UI Elements] %1 button = Botão %1 diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 7e2d239995e7..1561ec9b152a 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1316,6 +1316,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adresa este blocată în altă filă [Store] Connection Error = Eroare de conexiune diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 5c7b1b0473d1..66aa0b70a624 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1315,6 +1315,7 @@ Address = Адрес Value = Значение Lock = Фиксация Edit Value = Изменить значение +Address locked in another tab = Адрес заблокирован в другой вкладке [Store] Connection Error = Ошибка подключения diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 67d3037e96ff..287caf69de07 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1316,6 +1316,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adressen är låst i en annan flik [Store] Connection Error = Uppkopplingsfel diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index a9fe6ab027d5..029db1f236b5 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1318,6 +1318,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Naka-lock ang address sa ibang tab [Store] Connection Error = May error sa Koneksyon. diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 79b9ded66b3f..5832c117af13 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1337,6 +1337,7 @@ Address = ที่อยู่ Value = ค่า Lock = ล็อค Edit Value = แก้ไขค่า +Address locked in another tab = ที่อยู่นี้ถูกล็อกอยู่ในแท็บอื่น [Store] Connection Error = การเชื่อมต่อล้มเหลว diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 252075fbb8e5..2cafc3194307 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1316,6 +1316,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Adres başka bir sekmede kilitli [Store] Connection Error = Bağlantı Hatası diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index a0d1d5b4fc6d..54c25a0c52e0 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Адреса заблокована в іншій вкладці [Store] Connection Error = Помилка підключення diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index a963e96133a7..e7b8d75babc6 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1315,6 +1315,7 @@ Address = Address Value = Value Lock = Lock Edit Value = Edit Value +Address locked in another tab = Địa chỉ bị khóa trong một tab khác [Store] Connection Error = Lỗi kết nối diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 65cc17e86df5..2ed76679ae85 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1568,6 +1568,7 @@ Address = 地址 Value = 数值 Lock = 锁定 Edit Value = 修改数值 +Address locked in another tab = 地址已在另一个标签页中锁定 [VR] % of native FoV = 原生视角的% diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index a831eb90652f..94ddc24365f0 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1554,6 +1554,7 @@ Address = 位址 Value = 數值 Lock = 鎖定 Edit Value = 修改數值 +Address locked in another tab = 地址已在另一個分頁中鎖定 [UI Elements] %1 button = %1 按鈕 From 39b036fef0a326ee27cf52b7844984fac017b293 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Thu, 4 Jun 2026 21:49:59 +0800 Subject: [PATCH 09/11] Add float support allow .* such as "12.*" --- Core/MemoryScanner.cpp | 115 ++++++++++++++++++++++++++++++++++++- Core/MemoryScanner.h | 7 ++- UI/MemoryScannerScreen.cpp | 39 +++++++++---- 3 files changed, 145 insertions(+), 16 deletions(-) diff --git a/Core/MemoryScanner.cpp b/Core/MemoryScanner.cpp index 89a5438ac430..ed91197b158a 100644 --- a/Core/MemoryScanner.cpp +++ b/Core/MemoryScanner.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "Core/MemoryScanner.h" #include "Core/MemMap.h" @@ -26,11 +27,71 @@ MemoryScannerManager g_MemoryScanner; +struct FloatRange { + float lower = 0.0f; + float upper = 0.0f; + bool valid = false; + + [[nodiscard]] bool Match(float val) const { + if (!valid) return false; + if (lower <= upper) { + return val >= lower && val < upper; + } else { + // Negative range: e.g. lower = -12, upper = -13 + return val <= lower && val > upper; + } + } +}; + +static FloatRange ParseFloatRange(const std::string &filter) { + FloatRange range; + if (filter.size() < 2 || filter.substr(filter.size() - 2) != ".*") { + return range; + } + std::string prefix = filter.substr(0, filter.size() - 2); + if (prefix.empty()) return range; + if (prefix == "-") return range; + + try { + range.lower = std::stof(prefix); + float inc = 1.0f; + size_t dotPos = prefix.find('.'); + if (dotPos != std::string::npos) { + size_t digits = prefix.size() - dotPos - 1; + inc = powf(0.1f, (float)digits); + } + if (prefix[0] == '-') { + range.upper = range.lower - inc; + } else { + range.upper = range.lower + inc; + } + range.valid = true; + } catch (...) { + } + return range; +} + void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { results_.clear(); uint32_t val = 0; + float fval = 0.0f; + FloatRange frange; + bool isWildcard = false; try { - val = (uint32_t)std::stoul(filter, nullptr, 0); + if (type == ScanValueType::FLOAT) { + if (filter.size() >= 2 && filter.substr(filter.size() - 2) == ".*") { + frange = ParseFloatRange(filter); + if (frange.valid) { + isWildcard = true; + } else { + return; + } + } else { + fval = std::stof(filter); + } + } else { + val = (uint32_t)std::stoul(filter, nullptr, 0); + } } catch (...) { return; } @@ -63,6 +124,17 @@ void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { if (addr + 4 <= endAddr && Memory::Read_U32(addr) == (uint32_t)val) match = true; addr += 1; break; + case ScanValueType::FLOAT: + if (addr + 4 <= endAddr) { + float v = Memory::Read_Float(addr); + if (isWildcard) { + if (frange.Match(v)) match = true; + } else { + if (v == fval) match = true; + } + } + addr += 1; + break; } if (match) { @@ -75,8 +147,24 @@ void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { void MemoryScanner::NextScan(ScanValueType type, const std::string &filter) { uint32_t val = 0; + float fval = 0.0f; + FloatRange frange; + bool isWildcard = false; try { - val = (uint32_t)std::stoul(filter, nullptr, 0); + if (type == ScanValueType::FLOAT) { + if (filter.size() >= 2 && filter.substr(filter.size() - 2) == ".*") { + frange = ParseFloatRange(filter); + if (frange.valid) { + isWildcard = true; + } else { + return; + } + } else { + fval = std::stof(filter); + } + } else { + val = (uint32_t)std::stoul(filter, nullptr, 0); + } } catch (...) { return; } @@ -94,6 +182,16 @@ void MemoryScanner::NextScan(ScanValueType type, const std::string &filter) { case ScanValueType::U32: if (Memory::Read_U32(res.address) == (uint32_t)val) match = true; break; + case ScanValueType::FLOAT: + { + float v = Memory::Read_Float(res.address); + if (isWildcard) { + if (frange.Match(v)) match = true; + } else { + if (v == fval) match = true; + } + } + break; } if (match) { @@ -121,6 +219,13 @@ void MemoryScanner::Update() { case ScanValueType::U32: Memory::Write_U32(res.lockValue, res.address); break; + case ScanValueType::FLOAT: + { + float f; + memcpy(&f, &res.lockValue, 4); + Memory::Write_Float(f, res.address); + } + break; } } } @@ -144,6 +249,12 @@ bool MemoryScanner::SetLocked(size_t index, bool locked) { case ScanValueType::U32: results_[index].lockValue = Memory::Read_U32(results_[index].address); break; + case ScanValueType::FLOAT: + { + float f = Memory::Read_Float(results_[index].address); + memcpy(&results_[index].lockValue, &f, 4); + } + break; } } results_[index].locked = locked; diff --git a/Core/MemoryScanner.h b/Core/MemoryScanner.h index ebc8419d78ff..c6b97607ef5b 100644 --- a/Core/MemoryScanner.h +++ b/Core/MemoryScanner.h @@ -25,6 +25,7 @@ enum class ScanValueType { U8, U16, U32, + FLOAT, }; struct ScanResult { @@ -62,17 +63,17 @@ class MemoryScannerManager { void Update(); MemoryScanner *GetActive() { return scanners_[activeScanner_]; } - int GetActiveIndex() const { return activeScanner_; } + [[nodiscard]] int GetActiveIndex() const { return activeScanner_; } void SetActiveIndex(int index); - bool IsAddressLocked(uint32_t addr) const { + [[nodiscard]] bool IsAddressLocked(uint32_t addr) const { return HasLockedAddress(addr, nullptr, (size_t)-1); } bool HasLockedAddress(uint32_t addr, const MemoryScanner *excludeScanner, size_t excludeIndex) const; void AddScanner(); void RemoveScanner(int index); - int GetCount() const { return (int)scanners_.size(); } + [[nodiscard]] int GetCount() const { return (int)scanners_.size(); } private: std::vector scanners_; diff --git a/UI/MemoryScannerScreen.cpp b/UI/MemoryScannerScreen.cpp index 0f4d121ec18c..39bbe1da87f9 100644 --- a/UI/MemoryScannerScreen.cpp +++ b/UI/MemoryScannerScreen.cpp @@ -88,6 +88,7 @@ void MemoryScannerScreen::CreateViews() { typeStrip->AddChoice(se->T("8-bit")); typeStrip->AddChoice(se->T("16-bit")); typeStrip->AddChoice(se->T("32-bit")); + typeStrip->AddChoice(se->T("Float")); typeStrip->SetSelection((int)scanner->valueType, false); typeStrip->OnChoice.Add([scanner](EventParams &e) { scanner->valueType = (ScanValueType)e.a; @@ -136,6 +137,7 @@ void MemoryScannerScreen::update() { case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + case ScanValueType::FLOAT: valStr = StringFromFormat("%f", Memory::Read_Float(addr)); break; } valueChoices_[i]->SetText(valStr); } @@ -185,6 +187,7 @@ void MemoryScannerScreen::RebuildResultsList() { case ScanValueType::U8: valStr = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; case ScanValueType::U16: valStr = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; case ScanValueType::U32: valStr = StringFromFormat("%u", Memory::Read_U32(addr)); break; + case ScanValueType::FLOAT: valStr = StringFromFormat("%f", Memory::Read_Float(addr)); break; } Choice *valChoice = row->Add(new Choice(valStr, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 1.0f))); @@ -251,23 +254,37 @@ void MemoryScannerScreen::OnValueClick(uint32_t addr, ScanValueType type) { case ScanValueType::U8: currentVal = StringFromFormat("%d", (int)Memory::Read_U8(addr)); break; case ScanValueType::U16: currentVal = StringFromFormat("%d", (int)Memory::Read_U16(addr)); break; case ScanValueType::U32: currentVal = StringFromFormat("%u", Memory::Read_U32(addr)); break; + case ScanValueType::FLOAT: currentVal = StringFromFormat("%f", Memory::Read_Float(addr)); break; } UI::AskForInput(screenManager(), NON_EPHEMERAL_TOKEN, nullptr, se->T("Edit Value"), [addr, type](const std::string &value, bool ok) { if (ok) { try { - auto val = (uint32_t)std::stoul(value, nullptr, 0); - switch (type) { - case ScanValueType::U8: Memory::Write_U8((uint8_t)val, addr); break; - case ScanValueType::U16: Memory::Write_U16((uint16_t)val, addr); break; - case ScanValueType::U32: Memory::Write_U32(val, addr); break; - } + if (type == ScanValueType::FLOAT) { + float fval = std::stof(value); + Memory::Write_Float(fval, addr); + + // Also update lock value if locked in the active scanner. + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + for (auto &res : scanner->GetResults()) { + if (res.address == addr && res.locked) { + memcpy(&res.lockValue, &fval, 4); + } + } + } else { + auto val = (uint32_t)std::stoul(value, nullptr, 0); + switch (type) { + case ScanValueType::U8: Memory::Write_U8((uint8_t)val, addr); break; + case ScanValueType::U16: Memory::Write_U16((uint16_t)val, addr); break; + case ScanValueType::U32: Memory::Write_U32(val, addr); break; + } - // Also update lock value if locked in the active scanner. - MemoryScanner *scanner = g_MemoryScanner.GetActive(); - for (auto &res : scanner->GetResults()) { - if (res.address == addr && res.locked) { - res.lockValue = val; + // Also update lock value if locked in the active scanner. + MemoryScanner *scanner = g_MemoryScanner.GetActive(); + for (auto &res : scanner->GetResults()) { + if (res.address == addr && res.locked) { + res.lockValue = val; + } } } } catch (...) { From 8d137aee926b483e5454a87ed6d322f691bd09d8 Mon Sep 17 00:00:00 2001 From: sum2012 Date: Thu, 4 Jun 2026 21:51:28 +0800 Subject: [PATCH 10/11] Forget update lang --- assets/lang/ar_AE.ini | 1 + assets/lang/az_AZ.ini | 1 + assets/lang/be_BY.ini | 1 + assets/lang/bg_BG.ini | 1 + assets/lang/ca_ES.ini | 1 + assets/lang/cz_CZ.ini | 1 + assets/lang/da_DK.ini | 1 + assets/lang/de_DE.ini | 1 + assets/lang/dr_ID.ini | 1 + assets/lang/en_US.ini | 1 + assets/lang/es_ES.ini | 1 + assets/lang/es_LA.ini | 1 + assets/lang/fa_IR.ini | 1 + assets/lang/fi_FI.ini | 1 + assets/lang/fr_FR.ini | 1 + assets/lang/gl_ES.ini | 1 + assets/lang/gr_EL.ini | 1 + assets/lang/he_IL.ini | 1 + assets/lang/hr_HR.ini | 1 + assets/lang/hu_HU.ini | 1 + assets/lang/id_ID.ini | 1 + assets/lang/it_IT.ini | 1 + assets/lang/ja_JP.ini | 1 + assets/lang/jv_ID.ini | 1 + assets/lang/ko_KR.ini | 1 + assets/lang/ku_SO.ini | 1 + assets/lang/lo_LA.ini | 1 + assets/lang/lt-LT.ini | 1 + assets/lang/ms_MY.ini | 1 + assets/lang/nl_NL.ini | 1 + assets/lang/no_NO.ini | 1 + assets/lang/pl_PL.ini | 1 + assets/lang/pt_BR.ini | 1 + assets/lang/pt_PT.ini | 1 + assets/lang/ro_RO.ini | 1 + assets/lang/ru_RU.ini | 1 + assets/lang/sv_SE.ini | 1 + assets/lang/tg_PH.ini | 1 + assets/lang/th_TH.ini | 1 + assets/lang/tr_TR.ini | 1 + assets/lang/uk_UA.ini | 1 + assets/lang/vi_VN.ini | 1 + assets/lang/zh_CN.ini | 1 + assets/lang/zh_TW.ini | 1 + 44 files changed, 44 insertions(+) diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index f69902d3b7a7..176f58a821c4 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -1315,6 +1315,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 6d7ebb920bd0..4c5200d88183 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Üzgü First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/be_BY.ini b/assets/lang/be_BY.ini index ae2031180379..b23dd66536a7 100644 --- a/assets/lang/be_BY.ini +++ b/assets/lang/be_BY.ini @@ -1546,6 +1546,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Дробавы лік First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index db5bb00da38c..67c44d37fa0c 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index c3275a748759..6f10b83b7413 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Flotant First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 73a2d5c0c9b4..e90988cf2bf2 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index d2a94cce46a1..38f79c67ee21 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index e777b58b7202..95917c0dcdf2 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1306,6 +1306,7 @@ Value Type = Werttyp 8-bit = 8-Bit 16-bit = 16-Bit 32-bit = 32-Bit +Float = Float First Scan = Erster Scan Next Scan = Nächster Scan Results: %d = Ergebnisse: %d diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 3e28a11e01f4..f120bc98309f 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 00cb3e09402d..f64a82fd1fe0 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -1577,6 +1577,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 07b1eab0a8f1..73fc13b5664c 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1308,6 +1308,7 @@ Value Type = Tipo de valor 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Flotante First Scan = Primer escaneo Next Scan = Siguiente escaneo Results: %d = Resultados: %d diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index d369f7c5a3db..61ddad0ee2d5 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1309,6 +1309,7 @@ Value Type = Tipo de valor 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Flotante First Scan = Primer escaneo Next Scan = Siguiente escaneo Results: %d = Resultados: %d diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index c876236584a9..ae922b8f50a1 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index b5dd52c3af96..a93987bdc18a 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index d7dad837a318..093df057c9f3 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1574,6 +1574,7 @@ Value Type = Type de valeur 8-bit = 8 bits 16-bit = 16 bits 32-bit = 32 bits +Float = Float First Scan = Premier scan Next Scan = Scan suivant Results: %d = Résultats : %d diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 097259a84638..dab4444e1602 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Flotante First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 083d56bf39b4..b252e7389ac2 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index ad96ee7f3f53..56cb7bc4feb3 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index b53db6bd9d1d..80458b5cc858 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index f61ac76410d6..eb1e250d1d0a 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 2f43f51fa239..12e3585b579b 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index a85b826fbc4e..577296ee534b 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1310,6 +1310,7 @@ Value Type = Tipo di valore 8-bit = 8 bit 16-bit = 16 bit 32-bit = 32 bit +Float = Float First Scan = Prima scansione Next Scan = Scansione successiva Results: %d = Risultati: %d diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index fd7a11331704..9b4406fe4480 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1307,6 +1307,7 @@ Value Type = 値の型 8-bit = 8ビット 16-bit = 16ビット 32-bit = 32ビット +Float = 浮動小数点 First Scan = 初回スキャン Next Scan = 次のスキャン Results: %d = 結果: %d diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 80111a5addb3..69e49c6da5f5 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 24d36c403326..19334d171a4a 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1546,6 +1546,7 @@ Value Type = 값 유형 8-bit = 8비트 16-bit = 16비트 32-bit = 32비트 +Float = 부동소수점 First Scan = 첫 번째 스캔 Next Scan = 다음 스캔 Results: %d = 결과: %d diff --git a/assets/lang/ku_SO.ini b/assets/lang/ku_SO.ini index cdbff3bba1fa..5d6c6b15750b 100644 --- a/assets/lang/ku_SO.ini +++ b/assets/lang/ku_SO.ini @@ -1560,6 +1560,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 4bd98d8eceff..282d2db82298 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index f68c6e1b0989..890751cc3453 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 6b2fa8a382b8..00efeda2bfa5 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 0bfde77331ce..2fa8505a74ec 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index b183ab42aa36..89da45cd9c07 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 1bea8eec6f33..f05501d5594d 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1315,6 +1315,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Zmiennoprzecinkowe First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 1d38c8a735a1..16c7c584ded2 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -1577,6 +1577,7 @@ Value Type = Tipo de valor 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Flutuante First Scan = Primeiro escaneamento Next Scan = Próximo escaneamento Results: %d = Resultados: %d diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index ffa4ce0b8dd9..61019a42f123 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -1571,6 +1571,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Flutuante First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 1561ec9b152a..d2e3d06ac219 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1308,6 +1308,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 66aa0b70a624..c0b65078fca1 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1307,6 +1307,7 @@ Value Type = Тип значения 8-bit = 8 бит 16-bit = 16 бит 32-bit = 32 бита +Float = Дробное число First Scan = Первое сканирование Next Scan = След. сканирование Results: %d = Результатов: %d diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 287caf69de07..26fe2ae95b5b 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1308,6 +1308,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index 029db1f236b5..ddf7e062bbf5 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1310,6 +1310,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 5832c117af13..14775776b8c3 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1329,6 +1329,7 @@ Value Type = ประเภทของค่า 8-bit = 8-บิต 16-bit = 16-บิต 32-bit = 32-บิต +Float = ทศนิยม First Scan = สแกนครั้งแรก Next Scan = สแกนถัดไป Results: %d = ผลลัพธ์: %d diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 2cafc3194307..0cf0ecf45054 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1308,6 +1308,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 54c25a0c52e0..20eaff9b7dc5 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Дробове число First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index e7b8d75babc6..efc4d0e43edc 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1307,6 +1307,7 @@ Value Type = Value Type 8-bit = 8-bit 16-bit = 16-bit 32-bit = 32-bit +Float = Float First Scan = First Scan Next Scan = Next Scan Results: %d = Results: %d diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 2ed76679ae85..1a7241c946c0 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1560,6 +1560,7 @@ Value Type = 数值类型 8-bit = 8位 16-bit = 16位 32-bit = 32位 +Float = 浮点数 First Scan = 首次扫描 Next Scan = 再次扫描 Results: %d = 结果数:%d diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 94ddc24365f0..e60686e50564 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1546,6 +1546,7 @@ Value Type = 數值類型 8-bit = 8位元 16-bit = 16位元 32-bit = 32位元 +Float = 浮點數 First Scan = 首次掃描 Next Scan = 再次掃描 Results: %d = 結果數:%d From e5c2a4e406226e25ab18f11966113a7a6bd4bb8a Mon Sep 17 00:00:00 2001 From: sum2012 Date: Wed, 24 Jun 2026 20:03:28 +0800 Subject: [PATCH 11/11] Revert Restrict the search to the main executable's data section Do not work for unknown reason --- Core/HLE/sceKernelModule.cpp | 17 +---------------- Core/HLE/sceKernelModule.h | 1 - Core/MemoryScanner.cpp | 11 ----------- 3 files changed, 1 insertion(+), 28 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index b902e3b9f045..7f36b7e1bf46 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -431,7 +431,6 @@ struct SceKernelSMOption { static int actionAfterModule; static std::set loadedModules; -static SceUID g_mainModuleID = 0; // STATE END ////////////////////////////////////////////////////////////////////////// @@ -442,7 +441,7 @@ static void __KernelModuleInit() void __KernelModuleDoState(PointerWrap &p) { - auto s = p.Section("sceKernelModule", 1, 3); + auto s = p.Section("sceKernelModule", 1, 2); if (!s) return; @@ -452,9 +451,6 @@ void __KernelModuleDoState(PointerWrap &p) if (s >= 2) { Do(p, loadedModules); } - if (s >= 3) { - Do(p, g_mainModuleID); - } if (p.mode == p.MODE_READ) { u32 error; @@ -477,7 +473,6 @@ void __KernelModuleDoState(PointerWrap &p) void __KernelModuleShutdown() { loadedModules.clear(); - g_mainModuleID = 0; MIPSAnalyst::Reset(); HLEPlugins::Unload(); } @@ -1717,7 +1712,6 @@ bool KernelModuleIsKernelMode(SceUID uid) { void __KernelLoadReset() { // Wipe kernel here, loadexec should reset the entire system - g_mainModuleID = 0; if (__KernelIsRunning()) { u32 error; while (!loadedModules.empty()) { @@ -1782,10 +1776,6 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str size_t size = fileData.size(); PSPModule *module = __KernelLoadModule(fileData.data(), size, 0, filename, error_string); - if (module) { - g_mainModuleID = module->GetUID(); - } - if (!module || module->isFake) { if (module) { module->Cleanup(); @@ -1858,7 +1848,6 @@ bool __KernelLoadGEDump(std::string_view base_filename, std::string *error_strin memset(&module->nm, 0, sizeof(module->nm)); module->isFake = true; module->nm.entry_addr = codeStartAddr; - g_mainModuleID = module->GetUID(); module->nm.gp_value = -1; SceUID threadID = __KernelSetupRootThread(module->GetUID(), (int)base_filename.size(), base_filename.data(), 0x20, 0x1000, 0); @@ -2427,10 +2416,6 @@ u32 sceKernelFindModuleByUID(u32 uid) return hleLogInfo(Log::sceModule, module->modulePtr.ptr); } -SceUID __KernelGetMainModuleId() { - return g_mainModuleID; -} - u32 sceKernelFindModuleByName(const char *name) { u32 error; diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index b0c33672536a..13af5ef5efe6 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -234,7 +234,6 @@ SceUID KernelLoadModule(const std::string &filename, std::string *error_string); int __KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnValueAddr, SceKernelSMOption *smoption, bool *needsWait); u32 __KernelStopUnloadSelfModuleWithOrWithoutStatus(u32 exitCode, u32 argSize, u32 argp, u32 statusAddr, u32 optionAddr, bool WithStatus); u32 sceKernelFindModuleByUID(u32 uid); -SceUID __KernelGetMainModuleId(); void Register_ModuleMgrForUser(); void Register_ModuleMgrForKernel(); diff --git a/Core/MemoryScanner.cpp b/Core/MemoryScanner.cpp index ed91197b158a..f58ab61fa939 100644 --- a/Core/MemoryScanner.cpp +++ b/Core/MemoryScanner.cpp @@ -22,7 +22,6 @@ #include "Core/MemoryScanner.h" #include "Core/MemMap.h" #include "Core/System.h" -#include "Core/HLE/sceKernelModule.h" #include "Common/StringUtils.h" MemoryScannerManager g_MemoryScanner; @@ -99,16 +98,6 @@ void MemoryScanner::FirstScan(ScanValueType type, const std::string &filter) { uint32_t startAddr = 0x08000000; uint32_t endAddr = startAddr + Memory::g_MemorySize; - SceUID mainModuleID = __KernelGetMainModuleId(); - if (mainModuleID != 0) { - u32 error; - auto *mainModule = kernelObjects.Get(mainModuleID, error); - if (mainModule) { - startAddr = mainModule->GetDataAddr(); - endAddr = startAddr + mainModule->nm.data_size + mainModule->nm.bss_size; - } - } - for (uint32_t addr = startAddr; addr < endAddr; ) { bool match = false; switch (type) {