From 7a682ce7bbb9131a5f927e2e15d54cad09c5e127 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 19 Jul 2020 22:01:10 +0800 Subject: [PATCH 01/95] My mods todate --- .vscode/c_cpp_properties.json | 14 +- .vscode/settings.json | 14 +- Makefile | 8 +- icon.jpg | Bin 26790 -> 12541 bytes include/guis/gui_cheats.hpp | 126 +- include/guis/gui_cheats.hpp1 | 92 + include/helpers/memory_dump.hpp | 14 +- include/types.h | 97 +- source/guis/gui_cheats.cpp | 3330 +++++++++++++++++++++++++------ source/guis/note | 159 ++ source/guis/pointer_search.cpp1 | 288 +++ source/guis/pointer_search.cpp2 | 319 +++ source/helpers/diff | 59 + source/helpers/dmntcht.c | 1 + source/helpers/memory_dump.cpp | 167 +- source/helpers/save.cpp | 309 +-- source/main.cpp | 163 +- 17 files changed, 4205 insertions(+), 955 deletions(-) create mode 100644 include/guis/gui_cheats.hpp1 create mode 100644 source/guis/note create mode 100644 source/guis/pointer_search.cpp1 create mode 100644 source/guis/pointer_search.cpp2 create mode 100644 source/helpers/diff diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index b1f2c7f7..6898775e 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,10 +4,11 @@ "name": "DKP Aarch64", "includePath": [ "${workspaceFolder}/**", - "${DEVKITPRO}/devkitA64/include/**", - "${DEVKITPRO}/devkitA64/aarch64-none-elf/include/**", - "${DEVKITPRO}/libnx/include/**", - "${DEVKITPRO}/portlibs/switch/include/**" + "${workspaceFolder}/include/**", + "F:/devkitPro/devkitA64/include/**", + "F:/devkitPro/devkitA64/aarch64-none-elf/include/**", + "F:/devkitPro/libnx/include/**", + "F:/devkitPro/portlibs/switch/include/**" ], "defines": [ "DEBUG", @@ -15,10 +16,11 @@ "__SWITCH__", "VERSION_STRING=\"3.1.0\"" ], - "compilerPath": "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++", + "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", "cppStandard": "c++17", - "intelliSenseMode": "gcc-x64" + "intelliSenseMode": "gcc-x64", + "compilerArgs": [] } ], "version": 4 diff --git a/.vscode/settings.json b/.vscode/settings.json index c700cfd7..82ff87b2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -70,6 +70,16 @@ "thread": "cpp", "typeindex": "cpp", "typeinfo": "cpp", - "valarray": "cpp" - } + "valarray": "cpp", + "any": "cpp", + "ranges": "cpp", + "variant": "cpp", + "bit": "cpp", + "compare": "cpp", + "concepts": "cpp", + "stop_token": "cpp", + "numbers": "cpp", + "span": "cpp" + }, + "C_Cpp.default.includePath": ["include"] } \ No newline at end of file diff --git a/Makefile b/Makefile index cea1c8a4..823ea9ba 100644 --- a/Makefile +++ b/Makefile @@ -31,12 +31,12 @@ include $(DEVKITPRO)/libnx/switch_rules # - /default_icon.jpg #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 -VERSION_MINOR := 1 +VERSION_MINOR := 5 VERSION_MICRO := 0 -NIGHTLY := 1 +NIGHTLY := -APP_TITLE := EdiZon -APP_AUTHOR := WerWolv +APP_TITLE := EdiZon SE +APP_AUTHOR := Tomvita ifeq ($(NIGHTLY), 1) APP_VERSION := ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO} - Nightly diff --git a/icon.jpg b/icon.jpg index 857de7f3ed2a461a68eb994dc286c66292cbb18d..725c0b84f884ef0a57b32c4cecdd8d545a734ffd 100644 GIT binary patch literal 12541 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 sEW@u@4|ndY5JcB%E74r1q2?XbpQYW literal 26790 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 diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 461f70ae..f44d65f8 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -7,13 +7,19 @@ #include #include #include - +#include #include "helpers/debugger.hpp" #include "helpers/memory_dump.hpp" #include "helpers/dmntcht.h" +enum +{ + FORMAT_DEC, + FORMAT_HEX +} m_searchValueFormat = FORMAT_DEC; -class GuiCheats : public Gui { +class GuiCheats : public Gui +{ public: GuiCheats(); @@ -27,31 +33,107 @@ class GuiCheats : public Gui { private: Debugger *m_debugger; - u8 m_ramBuffer[0x10 * 14] = { 0 }; - color_t m_memory[1024] = { 0 }; + u8 m_ramBuffer[0x10 * 14] = {0}; + color_t m_memory[1024] = {0}; u8 m_selectedEntry = 0; - + u8 m_searchValueIndex = 0; + u32 m_addresslist_offset = 0; + searchValue_t m_searchValue[2]; - enum { FORMAT_DEC, FORMAT_HEX } m_searchValueFormat = FORMAT_DEC; - enum { CHEATS, CANDIDATES } m_menuLocation = CHEATS; - enum { SEARCH_NONE, SEARCH_TYPE, SEARCH_MODE, SEARCH_REGION, SEARCH_VALUE } m_searchMenuLocation = SEARCH_NONE; + enum + { + CHEATS, + CANDIDATES + } m_menuLocation = CHEATS; + enum + { + SEARCH_NONE, + SEARCH_TYPE, + SEARCH_MODE, + SEARCH_REGION, + SEARCH_VALUE, + SEARCH_editRAM, + SEARCH_POINTER + } m_searchMenuLocation = SEARCH_NONE; + searchType_t m_searchType = SEARCH_TYPE_NONE; searchMode_t m_searchMode = SEARCH_MODE_NONE; searchRegion_t m_searchRegion = SEARCH_REGION_NONE; std::vector m_memoryInfo; + std::vector m_targetmemInfos; + MemoryDump *m_memoryDump; + MemoryDump *m_memoryDump1; + MemoryDump *m_memoryDumpBookmark; + MemoryDump *m_AttributeDumpBookmark; + MemoryDump *m_pointeroffsetDump; + MemoryDump *m_dataDump; + u64 m_target = 0; + u64 m_numoffset = 3; + u64 m_max_source = 200; + u64 m_max_depth = 2; + u64 m_max_range = 0x300; + u64 m_low_main_heap_addr = 0x100000000; + u64 m_high_main_heap_addr = 0x10000000000; + std::map m_frozenAddresses; bool m_cheatsPresent = false; bool m_sysmodulePresent = false; + bool m_editRAM = false; + bool m_nothingchanged = false; u64 m_addressSpaceBaseAddr = 0x00; + u64 m_addressSpaceSize = 0x00; u64 m_heapBaseAddr = 0x00; u64 m_mainBaseAddr = 0x00; - + u64 m_EditorBaseAddr = 0x00; + u8 m_addressmod = 0; + time_t m_Time1; + struct helperinfo_t + { + u64 address; + u64 size; + u64 count; + }; + struct sourceinfo_t + { + u64 foffset; + u64 offset; + }; + +#define MAX_NUM_SOURCE_POINTER 200 // bound check for debugging; +#define MAX_POINTER_DEPTH 6 // up to 4 seems OK with forward only search took 94s. 215s for big dump +#define MAX_POINTER_RANGE 0x2000 +#define MAX_POINTER_TARGET 3 + bool m_forwardonly = false; + bool m_forwarddump = false; // reduce from 138 to 26 + + struct pointer_chain_t + { + u64 depth; + u64 offset[MAX_POINTER_DEPTH + 1]; // offset to address pointed by pointer + // below is for debugging can consider removing; + u64 fileoffset[MAX_POINTER_DEPTH + 1]; // offset to the file that has the address where the pointer was stored in this instance for debugging + }; + struct bookmark_t + { + char label[18]; + searchType_t type; + pointer_chain_t pointer; + }; + pointer_chain_t m_hitcount; + + // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); + // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); + // void pointersearch(u64 targetaddress, MemoryDump **displayDump, MemoryDump **dataDump, pointer_chain_t pointerchain); + void pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain); + void pointercheck(); + void startpointersearch(u64 targetaddress); //, MemoryDump **displayDump); + void searchpointer(u64 address, u64 depth, u64 range, pointer_chain_t pointerchain); u64 m_heapSize = 0; u64 m_mainSize = 0; @@ -62,24 +144,26 @@ class GuiCheats : public Gui { void drawSearchRAMMenu(); + void drawEditRAMMenu(); + void drawSearchPointerMenu(); void searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, - searchValue_t searchValue2, searchType_t searchType, - searchMode_t searchMode, searchRegion_t searchRegion, - MemoryDump **displayDump, std::vector memInfos); + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); void searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, - searchValue_t searchValue2, searchType_t searchType, - searchMode_t searchMode, MemoryDump **displayDump); + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, MemoryDump **displayDump); void searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, - searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos); - + searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos); void searchMemoryValuesSecondary(Debugger *debugger, searchType_t searchType, - searchMode_t searchMode, searchRegion_t searchRegion, - MemoryDump **displayDump, std::vector memInfos); + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); - void searchMemoryValuesTertiary(Debugger *debugger, searchType_t searchType, - searchMode_t searchMode, searchRegion_t searchRegion, - MemoryDump **displayDump, std::vector memInfos); + void searchMemoryValuesTertiary(Debugger *debugger, searchValue_t searchValue1, + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); }; diff --git a/include/guis/gui_cheats.hpp1 b/include/guis/gui_cheats.hpp1 new file mode 100644 index 00000000..b6c7b455 --- /dev/null +++ b/include/guis/gui_cheats.hpp1 @@ -0,0 +1,92 @@ +#pragma once + +#include "guis/gui.hpp" +#include "types.h" + +#include +#include +#include +#include +#include +#include "helpers/debugger.hpp" +#include "helpers/memory_dump.hpp" + +#include "helpers/dmntcht.h" + enum { FORMAT_DEC, FORMAT_HEX } m_searchValueFormat = FORMAT_DEC; + +class GuiCheats : public Gui { + +public: + GuiCheats(); + ~GuiCheats(); + + void update(); + void draw(); + void onInput(u32 kdown); + void onTouch(touchPosition &touch); + void onGesture(touchPosition startPosition, touchPosition endPosition, bool finish); + +private: + Debugger *m_debugger; + u8 m_ramBuffer[0x10 * 14] = { 0 }; + color_t m_memory[1024] = { 0 }; + + u8 m_selectedEntry = 0; + u8 m_searchValueIndex = 0; + u8 m_addresslist_offset = 0; + + searchValue_t m_searchValue[2]; + + enum { CHEATS, CANDIDATES } m_menuLocation = CHEATS; + enum { SEARCH_NONE, SEARCH_TYPE, SEARCH_MODE, SEARCH_REGION, SEARCH_VALUE } m_searchMenuLocation = SEARCH_NONE; + + searchType_t m_searchType = SEARCH_TYPE_NONE; + searchMode_t m_searchMode = SEARCH_MODE_NONE; + searchRegion_t m_searchRegion = SEARCH_REGION_NONE; + + std::vector m_memoryInfo; + MemoryDump *m_memoryDump; + MemoryDump *m_memoryDump1; + MemoryDump *m_memoryDumpBookmark; + + + std::map m_frozenAddresses; + + bool m_cheatsPresent = false; + bool m_sysmodulePresent = false; + + u64 m_addressSpaceBaseAddr = 0x00; + u64 m_heapBaseAddr = 0x00; + u64 m_mainBaseAddr = 0x00; + + u64 m_heapSize = 0; + u64 m_mainSize = 0; + + u8 m_buildID[0x20]; + + DmntCheatEntry *m_cheats; + u64 m_cheatCnt; + + void drawSearchRAMMenu(); + + void searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); + + void searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, MemoryDump **displayDump); + + void searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, + searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos); + + + void searchMemoryValuesSecondary(Debugger *debugger, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); + + void searchMemoryValuesTertiary(Debugger *debugger, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); +}; diff --git a/include/helpers/memory_dump.hpp b/include/helpers/memory_dump.hpp index 6e7e562a..c201fb6a 100644 --- a/include/helpers/memory_dump.hpp +++ b/include/helpers/memory_dump.hpp @@ -4,25 +4,27 @@ #include #include - -class MemoryDump { +extern bool print_details; +class MemoryDump +{ public: MemoryDump(std::string filePath, DumpType dumpType, bool discardFile); ~MemoryDump(); void setBaseAddresses(u64 addrSpaceBase, u64 heapBase, u64 mainBase, u64 heapSize, u64 mainSize); void setSearchParams(searchType_t searchDataType, searchMode_t searchMode, searchRegion_t searchRegion, searchValue_t searchValue1, searchValue_t searchValue2); - + void setPointerSearchParams(u64 max_depth, u64 numoffset, u64 maxrange, u8 buildID[0x20]); void addData(u8 *buffer, size_t bufferSize); size_t size(); void clear(); int getData(u64 addr, void *buffer, size_t bufferSize); + int putData(u64 addr, void *buffer, size_t bufferSize); u8 operator[](u64 index); - data_header_t getDumpInfo(); + data_header_t getDumpInfo(); - void setDumpType(enum DumpType dumpType); + void setDumpType(enum DumpType dumpType); void flushBuffer(); private: @@ -30,7 +32,7 @@ class MemoryDump { std::string m_filePath; std::vector m_data; - data_header_t m_dataHeader; + data_header_t m_dataHeader; bool isFileOpen(); void writeHeader(); diff --git a/include/types.h b/include/types.h index 3dd59cba..78ddce63 100644 --- a/include/types.h +++ b/include/types.h @@ -5,26 +5,30 @@ typedef union { u32 color_abgr; - struct { + struct + { u8 r, g, b, a; }; } color_t; -typedef enum { +typedef enum +{ IMAGE_MODE_RGB24, IMAGE_MODE_RGBA32, IMAGE_MODE_BGR24, IMAGE_MODE_ABGR32 } ImageMode; -typedef enum { +typedef enum +{ ALIGNED_LEFT, ALIGNED_CENTER, ALIGNED_RIGHT } TextAlignment; -typedef struct { +typedef struct +{ u8 magic[4]; // 'fFNT' int version; // 1 u16 npages; @@ -32,11 +36,13 @@ typedef struct { u8 baseline; } ffnt_header_t; -typedef struct { +typedef struct +{ u32 size, offset; } ffnt_pageentry_t; -typedef struct { +typedef struct +{ u32 pos[0x100]; u8 widths[0x100]; u8 heights[0x100]; @@ -45,36 +51,40 @@ typedef struct { s8 posY[0x100]; } ffnt_pagehdr_t; -typedef struct { +typedef struct +{ ffnt_pagehdr_t hdr; u8 data[]; } ffnt_page_t; -typedef struct { +typedef struct +{ u8 width, height; s8 posX, posY, advance, pitch; - const u8* data; + const u8 *data; } glyph_t; -typedef struct{ +typedef struct +{ u64 addr; u8 type; } PACKED ramAddr_t; - typedef union { +typedef union { u8 _u8; - s8 _s8; - u16 _u16; - s16 _s16; - u32 _u32; - s32 _s32; - u64 _u64; + s8 _s8; + u16 _u16; + s16 _s16; + u32 _u32; + s32 _s32; + u64 _u64; s64 _s64; float _f32; double _f64; } searchValue_t; -typedef enum { +typedef enum +{ SEARCH_TYPE_NONE = -1, SEARCH_TYPE_UNSIGNED_8BIT, SEARCH_TYPE_SIGNED_8BIT, @@ -89,22 +99,25 @@ typedef enum { SEARCH_TYPE_POINTER } searchType_t; -typedef enum { +typedef enum +{ SEARCH_MODE_NONE = -1, SEARCH_MODE_EQ, SEARCH_MODE_NEQ, SEARCH_MODE_GT, - SEARCH_MODE_GTE, + SEARCH_MODE_DIFFA, SEARCH_MODE_LT, - SEARCH_MODE_LTE, + SEARCH_MODE_SAMEA, SEARCH_MODE_RANGE, SEARCH_MODE_SAME, SEARCH_MODE_DIFF, SEARCH_MODE_INC, - SEARCH_MODE_DEC + SEARCH_MODE_DEC, + SEARCH_MODE_POINTER } searchMode_t; -typedef enum { +typedef enum +{ SEARCH_REGION_NONE = -1, SEARCH_REGION_HEAP, SEARCH_REGION_MAIN, @@ -112,20 +125,32 @@ typedef enum { SEARCH_REGION_RAM } searchRegion_t; -typedef enum DumpType { UNDEFINED = '-', ADDR = 'A', DATA = 'D' } DumpType; - -typedef struct DataHeader { - u32 magic; // EDZN 0x4E5A4445 (Reversed for LE) - char dumpType; // '-' (0x2D) for not set yet, 'A' (0x41) for addresses, 'D' (0x44) for data - u32 dataSize; // Size of data - searchType_t searchDataType; - searchMode_t searchMode; - searchRegion_t searchRegion; - searchValue_t searchValue[2]; - u64 heapBaseAddress; +typedef enum DumpType +{ + UNDEFINED = '-', + ADDR = 'A', + DATA = 'D', + HELPER = 'H', + POINTER = 'P' +} DumpType; + +typedef struct DataHeader +{ + u32 magic; // EDZN 0x4E5A4445 (Reversed for LE) + char dumpType; // '-' (0x2D) for not set yet, 'A' (0x41) for addresses, 'D' (0x44) for data + u32 dataSize; // Size of data + searchType_t searchDataType; + searchMode_t searchMode; + searchRegion_t searchRegion; + searchValue_t searchValue[2]; + u64 heapBaseAddress; u64 heapSize; u64 mainBaseAddress; u64 mainSize; u64 addrSpaceBaseAddress; - u8 endOfHeader; // '@' - Signals the end of the header -} __attribute__((packed)) data_header_t; \ No newline at end of file + u64 max_depth; + u64 numoffset; + u64 maxrange; + u8 buildID[0x20]; + u8 endOfHeader; // '@' - Signals the end of the header +} __attribute__((packed)) data_header_t; \ No newline at end of file diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 7d733f94..d9137d66 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -11,23 +11,25 @@ #include "edizon_logo_bin.h" +#define MAX_BUFFER_SIZE 0x1000000 // increase size for faster speed -static const std::vector dataTypes = { "u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr" }; -static const std::vector dataTypeSizes = { 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8 }; -static const std::vector dataTypeMaxValues = { std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; -static const std::vector dataTypeMinValues = { std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min() }; +static const std::vector dataTypes = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr"}; +static const std::vector dataTypeSizes = {1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8}; +static const std::vector dataTypeMaxValues = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; +static const std::vector dataTypeMinValues = {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()}; static std::string titleNameStr, tidStr, pidStr, buildIDStr; static u32 cheatListOffset = 0; -static bool _isAddressFrozen(uintptr_t ); -static std::string _getAddressDisplayString(u64 , Debugger *debugger, searchType_t searchType); +static bool _isAddressFrozen(uintptr_t); +static std::string _getAddressDisplayString(u64, Debugger *debugger, searchType_t searchType); static std::string _getValueDisplayString(searchValue_t searchValue, searchType_t searchType); static void _moveLonelyCheats(u8 *buildID, u64 titleID); static bool _wrongCheatsPresent(u8 *buildID, u64 titleID); -GuiCheats::GuiCheats() : Gui() { +GuiCheats::GuiCheats() : Gui() +{ // Check if dmnt:cht is running and we're not on sxos m_sysmodulePresent = isServiceRunning("dmnt:cht") && !(isServiceRunning("tx") && !isServiceRunning("rnx")); @@ -35,6 +37,10 @@ GuiCheats::GuiCheats() : Gui() { m_debugger = new Debugger(); m_cheats = nullptr; m_memoryDump = nullptr; + // start mod bookmark; + m_memoryDumpBookmark = nullptr; + m_memoryDump1 = nullptr; + m_pointeroffsetDump = nullptr; m_searchValue[0]._u64 = 0; m_searchValue[1]._u64 = 0; @@ -44,7 +50,8 @@ GuiCheats::GuiCheats() : Gui() { m_cheatCnt = 0; - if (!m_sysmodulePresent) return; + if (!m_sysmodulePresent) + return; dmntchtInitialize(); dmntchtForceOpenCheatProcess(); @@ -53,67 +60,107 @@ GuiCheats::GuiCheats() : Gui() { dmntchtGetCheatProcessMetadata(&metadata); m_addressSpaceBaseAddr = metadata.address_space_extents.base; + m_addressSpaceSize = metadata.address_space_extents.size; m_heapBaseAddr = metadata.heap_extents.base; m_mainBaseAddr = metadata.main_nso_extents.base; + m_EditorBaseAddr = m_heapBaseAddr; m_heapSize = metadata.heap_extents.size; m_mainSize = metadata.main_nso_extents.size; + if (m_mainBaseAddr < m_heapBaseAddr) + { + m_low_main_heap_addr = m_mainBaseAddr; + m_high_main_heap_addr = m_heapBaseAddr + m_heapSize; + } + else + { + m_low_main_heap_addr = m_heapBaseAddr; + m_high_main_heap_addr = m_mainBaseAddr + m_mainSize; + } + memcpy(m_buildID, metadata.main_nso_build_id, 0x20); _moveLonelyCheats(m_buildID, m_debugger->getRunningApplicationTID()); dmntchtGetCheatCount(&m_cheatCnt); - if (m_cheatCnt > 0) { + if (m_cheatCnt > 0) + { m_cheats = new DmntCheatEntry[m_cheatCnt]; dmntchtGetCheats(m_cheats, m_cheatCnt, 0, &m_cheatCnt); - } else if (_wrongCheatsPresent(m_buildID, m_debugger->getRunningApplicationTID())) + } + else if (_wrongCheatsPresent(m_buildID, m_debugger->getRunningApplicationTID())) m_cheatsPresent = true; u64 frozenAddressCnt = 0; dmntchtGetFrozenAddressCount(&frozenAddressCnt); - if (frozenAddressCnt != 0) { + if (frozenAddressCnt != 0) + { DmntFrozenAddressEntry frozenAddresses[frozenAddressCnt]; dmntchtGetFrozenAddresses(frozenAddresses, frozenAddressCnt, 0, nullptr); for (u16 i = 0; i < frozenAddressCnt; i++) - m_frozenAddresses.insert({ frozenAddresses[i].address, frozenAddresses[i].value.value }); - + m_frozenAddresses.insert({frozenAddresses[i].address, frozenAddresses[i].value.value}); } - - MemoryInfo meminfo = { 0 }; + + MemoryInfo meminfo = {0}; u64 lastAddr = 0; - do { + do + { lastAddr = meminfo.addr; meminfo = m_debugger->queryMemory(meminfo.addr + meminfo.size); m_memoryInfo.push_back(meminfo); } while (lastAddr < meminfo.addr + meminfo.size); - for (MemoryInfo meminfo : m_memoryInfo) { + for (MemoryInfo meminfo : m_memoryInfo) + { if (m_mainBaseAddr == 0x00 && (meminfo.type == MemType_CodeStatic)) m_mainBaseAddr = meminfo.addr; - for (u64 addrOffset = meminfo.addr; addrOffset < meminfo.addr + meminfo.size; addrOffset += 0x20000000) { - switch(meminfo.type) { - case MemType_CodeStatic: - case MemType_CodeMutable: m_memory[addrOffset / 0x20000000] = Gui::makeColor(0xFF, 0x00, 0x00, 0xFF); break; - case MemType_SharedMem: m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x00, 0xFF, 0x00, 0xFF); break; - case MemType_Heap: m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x00, 0x00, 0xFF, 0xFF); break; - case MemType_KernelStack: - case MemType_ThreadLocal: m_memory[addrOffset / 0x20000000] = Gui::makeColor(0xFF, 0xFF, 0x00, 0xFF); break; - case MemType_Unmapped: break; - default: m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x80, 0x80, 0x80, 0xFF); break; + for (u64 addrOffset = meminfo.addr; addrOffset < meminfo.addr + meminfo.size; addrOffset += 0x20000000) + { + switch (meminfo.type) + { + case MemType_CodeStatic: + case MemType_CodeMutable: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0xFF, 0x00, 0x00, 0xFF); + break; + case MemType_SharedMem: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x00, 0xFF, 0x00, 0xFF); + break; + case MemType_Heap: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x00, 0x00, 0xFF, 0xFF); + break; + case MemType_KernelStack: + case MemType_ThreadLocal: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0xFF, 0xFF, 0x00, 0xFF); + break; + case MemType_Unmapped: + break; + default: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x80, 0x80, 0x80, 0xFF); + break; } } } + //BM Begin pointer search init + + // MemoryDump *m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, false); + // m_pointeroffsetDump->setPointerSearchParams(m_max_depth, m_numoffset, m_max_range, m_buildID); + m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::UNDEFINED, false); + // start mod make list of memory found toggle between current find and bookmark + m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, false); + m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, false); + // end mod - if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDump->getDumpInfo().heapBaseAddress != m_heapBaseAddr) { + if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDump->getDumpInfo().heapBaseAddress != m_heapBaseAddr) + { m_memoryDump->clear(); remove(EDIZON_DIR "/memdump2.dat"); @@ -123,25 +170,51 @@ GuiCheats::GuiCheats() : Gui() { m_searchRegion = SEARCH_REGION_NONE; m_searchValue[0]._u64 = 0; m_searchValue[1]._u64 = 0; - } else { + } + else + { m_searchType = m_memoryDump->getDumpInfo().searchDataType; m_searchRegion = m_memoryDump->getDumpInfo().searchRegion; + m_searchMode = m_memoryDump->getDumpInfo().searchMode; m_searchValue[0] = m_memoryDump->getDumpInfo().searchValue[0]; m_searchValue[1] = m_memoryDump->getDumpInfo().searchValue[1]; } - + m_memoryDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + // start mod bookmark + + if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDumpBookmark->getDumpInfo().heapBaseAddress != m_heapBaseAddr) + { + m_memoryDumpBookmark->clear(); + m_AttributeDumpBookmark->clear(); + delete m_memoryDumpBookmark; + delete m_AttributeDumpBookmark; + m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, true); + m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, true); + m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + m_AttributeDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + // m_memoryDumpBookmark->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); + } + else + m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + // end mod std::stringstream ss; - if (m_debugger->getRunningApplicationTID() != 0) { + + // check this + printf("%s\n", "before part"); + if (m_debugger->getRunningApplicationTID() != 0) + { if (Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName().length() < 24) ss << Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName(); else ss << Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName().substr(0, 21) << "..."; titleNameStr = ss.str(); ss.str(""); - } else titleNameStr = "Unknown title name!"; - + } + else + titleNameStr = "Unknown title name!"; + printf("%s\n", "after part"); ss << "TID: " << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); tidStr = ss.str(); ss.str(""); @@ -153,7 +226,7 @@ GuiCheats::GuiCheats() : Gui() { ss << "BID: "; for (u8 i = 0; i < 8; i++) ss << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; - + buildIDStr = ss.str(); if (m_cheatCnt == 0) @@ -164,62 +237,76 @@ GuiCheats::GuiCheats() : Gui() { appletSetMediaPlaybackState(true); } -GuiCheats::~GuiCheats() { +GuiCheats::~GuiCheats() +{ - if (m_debugger != nullptr) { + if (m_debugger != nullptr) + { delete m_debugger; } - if (m_memoryDump != nullptr) - delete m_memoryDump; + if (m_memoryDump1 != nullptr) + delete m_memoryDump1; + + if (m_memoryDumpBookmark != nullptr) + delete m_memoryDumpBookmark; if (m_cheats != nullptr) delete[] m_cheats; - if (m_sysmodulePresent) { + if (m_sysmodulePresent) + { dmntchtExit(); } setLedState(false); appletSetMediaPlaybackState(false); + + printf("%s\n", "~GuiCheats()"); } -void GuiCheats::update() { +void GuiCheats::update() +{ Gui::update(); } -void GuiCheats::draw() { +void GuiCheats::draw() +{ static u32 splashCnt = 0; std::stringstream ss; Gui::beginDraw(); - #if SPLASH_ENABLED +#if SPLASH_ENABLED - if (!Gui::g_splashDisplayed) { - Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x5D, 0x4F, 0x4E, 0xFF)); - Gui::drawImage(Gui::g_framebuffer_width / 2 - 128, Gui::g_framebuffer_height / 2 - 128, 256, 256, edizon_logo_bin, IMAGE_MODE_BGR24); + if (!Gui::g_splashDisplayed) + { + Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x5D, 0x4F, 0x4E, 0xFF)); + Gui::drawImage(Gui::g_framebuffer_width / 2 - 128, Gui::g_framebuffer_height / 2 - 128, 256, 256, edizon_logo_bin, IMAGE_MODE_BGR24); - if (splashCnt++ >= 70) - Gui::g_splashDisplayed = true; + if (splashCnt++ >= 70) + Gui::g_splashDisplayed = true; - Gui::endDraw(); - return; - } + Gui::endDraw(); + return; + } - #endif +#endif Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, currTheme.backgroundColor); Gui::drawRectangle((u32)((Gui::g_framebuffer_width - 1220) / 2), Gui::g_framebuffer_height - 73, 1220, 1, currTheme.textColor); - if (m_debugger->getRunningApplicationPID() == 0) { + if (m_debugger->getRunningApplicationPID() == 0) + { Gui::drawTextAligned(fontHuge, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 - 100, currTheme.textColor, "\uE12C", ALIGNED_CENTER); Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2, currTheme.textColor, "A title needs to be running in the background to use the RAM editor. \n Please launch an application and try again.", ALIGNED_CENTER); Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E1 Back", ALIGNED_RIGHT); Gui::endDraw(); return; - } else if (!m_sysmodulePresent) { + } + else if (!m_sysmodulePresent) + { Gui::drawTextAligned(fontHuge, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 - 100, currTheme.textColor, "\uE142", ALIGNED_CENTER); Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2, currTheme.textColor, "EdiZon depends on Atmosphere's dmnt:cht service which doesn't seem to be \n running on this device. Please install a supported CFW to \n use the cheat engine.", ALIGNED_CENTER); Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E1 Back", ALIGNED_RIGHT); @@ -227,50 +314,72 @@ void GuiCheats::draw() { return; } - if (m_memoryDump->size() == 0) { - if (m_frozenAddresses.size() != 0) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Frozen es \uE0E3 Search RAM \uE0E1 Back", ALIGNED_RIGHT); + if (m_menuLocation == CHEATS) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + else if (m_memoryDump1 == nullptr) + { + if (m_memoryDump->size() == 0) + { + if (m_frozenAddresses.size() != 0) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Frozen es \uE0E3 Search RAM \uE0E1 Quit", ALIGNED_RIGHT); + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E3 Search RAM \uE0E1 Quit", ALIGNED_RIGHT); + // Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 E4 \uE0E5 E5 \uE0E6 E6 \uE0E7 E7 \uE0E8 E8 \uE0E9 E9 \uE0EA EA \uE0EF EF \uE0F0 F0 \uE0F1 F1 \uE0F2 F2 \uE0F3 F3 \uE0F4 F4 \uE0F5 F5 ", ALIGNED_RIGHT); + // Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E1 E1 \uE0E0 E0 \uE0E1 E1 \uE0E2 E2 \uE0E3 E3 \uE0D9 D9 \uE0DA DA \uE0DF DF \uE0F0 F0 \uE0F6 F6 \uE0F7 F7 \uE0F8 F8 \uE0F9 F9 \uE0FA FA ", ALIGNED_RIGHT); + } else - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E3 Search RAM \uE0E1 Back", ALIGNED_RIGHT); - } else { - if (m_memoryDump->size() > 0) { - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Reset search \uE0E3 Search again \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Back", ALIGNED_RIGHT); + { + if (m_memoryDump->size() > 0) + { + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0F0 Reset search \uE0E3 Search again \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); + } + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Reset search \uE0E1 Quit", ALIGNED_RIGHT); } - else - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Reset search \uE0E1 Back", ALIGNED_RIGHT); + } + else + { + if (m_memoryDumpBookmark->size() > 0) + { + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM label \uE0E3 Add Cheat \uE0F0 Delete BM \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); + } + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E1 Quit", ALIGNED_RIGHT); } Gui::drawRectangle(256, 50, Gui::g_framebuffer_width - 256, 206, currTheme.separatorColor); + // Don't draw icon if (m_debugger->getRunningApplicationTID() != 0) Gui::drawImage(0, 0, 256, 256, Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleIcon(), IMAGE_MODE_RGB24); - else + else Gui::drawRectangle(0, 0, 256, 256, Gui::makeColor(0x00, 0x00, 0xFF, 0xFF)); - Gui::drawRectangle(660, 65, 20, 20, Gui::makeColor(0xFF, 0x00, 0x00, 0xFF)); // Code - Gui::drawRectangle(660, 85, 20, 20, Gui::makeColor(0x00, 0xFF, 0x00, 0xFF)); // Shared Memory - Gui::drawRectangle(660, 105, 20, 20, Gui::makeColor(0x00, 0x00, 0xFF, 0xFF)); // Heap - Gui::drawRectangle(660, 125, 20, 20, Gui::makeColor(0xFF, 0xFF, 0x00, 0xFF)); // Stack - Gui::drawRectangle(660, 145, 20, 20, Gui::makeColor(0x80, 0x80, 0x80, 0xFF)); // Others + Gui::drawRectangle(660, 65, 20, 20, Gui::makeColor(0xFF, 0x00, 0x00, 0xFF)); // Code + Gui::drawRectangle(660, 85, 20, 20, Gui::makeColor(0x00, 0xFF, 0x00, 0xFF)); // Shared Memory + Gui::drawRectangle(660, 105, 20, 20, Gui::makeColor(0x00, 0x00, 0xFF, 0xFF)); // Heap + Gui::drawRectangle(660, 125, 20, 20, Gui::makeColor(0xFF, 0xFF, 0x00, 0xFF)); // Stack + Gui::drawRectangle(660, 145, 20, 20, Gui::makeColor(0x80, 0x80, 0x80, 0xFF)); // Others - Gui::drawTextAligned(font14, 700, 62, currTheme.textColor, "Code", ALIGNED_LEFT); - Gui::drawTextAligned(font14, 700, 82, currTheme.textColor, "Shared Memory", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 700, 62, currTheme.textColor, "Code", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 700, 82, currTheme.textColor, "Shared Memory", ALIGNED_LEFT); Gui::drawTextAligned(font14, 700, 102, currTheme.textColor, "Heap", ALIGNED_LEFT); Gui::drawTextAligned(font14, 700, 122, currTheme.textColor, "Stack", ALIGNED_LEFT); Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); - ss.str(""); - ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(16) << std::hex << m_addressSpaceBaseAddr; - Gui::drawTextAligned(font14, 900, 75, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr + m_addressSpaceSize; + Gui::drawTextAligned(font14, 900, 75, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); - ss << "HEAP : 0x" << std::uppercase << std::setfill('0') << std::setw(16) << std::hex << m_heapBaseAddr; - Gui::drawTextAligned(font14, 900, 105, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + ss << "HEAP : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr; + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr + m_heapSize; + Gui::drawTextAligned(font14, 900, 105, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); - ss << "MAIN : 0x" << std::uppercase << std::setfill('0') << std::setw(16) << std::hex << m_mainBaseAddr; + ss << "MAIN : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr; + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr + m_mainSize; Gui::drawTextAligned(font14, 900, 135, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); - Gui::drawRectangle(256, 50, 394, 137, COLOR_WHITE); Gui::drawTextAligned(font20, 280, 70, COLOR_BLACK, titleNameStr.c_str(), ALIGNED_LEFT); @@ -278,83 +387,141 @@ void GuiCheats::draw() { Gui::drawTextAligned(font14, 290, 130, COLOR_BLACK, pidStr.c_str(), ALIGNED_LEFT); Gui::drawTextAligned(font14, 290, 150, COLOR_BLACK, buildIDStr.c_str(), ALIGNED_LEFT); - if ((Account::g_activeUser.uid[0] != 0) && (Account::g_activeUser.uid[1] != 0)) { + if ((Account::g_activeUser.uid[0] != 0) && (Account::g_activeUser.uid[1] != 0)) + { ss.str(""); ss << Account::g_accounts[Account::g_activeUser]->getUserName() << " [ " << std::hex << (Account::g_activeUser.uid[1]) << " " << (Account::g_activeUser.uid[0]) << " ]"; Gui::drawTextAligned(font20, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); } - if (m_cheatCnt > 0) { + if (m_cheatCnt > 0) + { Gui::drawRectangle(50, 256, 650, 46 + std::min(static_cast(m_cheatCnt), 8U) * 40, currTheme.textColor); Gui::drawTextAligned(font14, 375, 262, currTheme.backgroundColor, "Cheats", ALIGNED_CENTER); Gui::drawShadow(50, 256, 650, 46 + std::min(static_cast(m_cheatCnt), 8U) * 40); - for (u8 line = cheatListOffset; line < 8 + cheatListOffset; line++) { - if (line >= m_cheatCnt) break; + for (u8 line = cheatListOffset; line < 8 + cheatListOffset; line++) + { + if (line >= m_cheatCnt) + break; ss.str(""); ss << "\uE070 " << m_cheats[line].definition.readable_name; Gui::drawRectangle(52, 300 + (line - cheatListOffset) * 40, 646, 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); Gui::drawTextAligned(font14, 70, 305 + (line - cheatListOffset) * 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); - - if (!m_cheats[line].enabled) { + + if (!m_cheats[line].enabled) + { color_t highlightColor = currTheme.highlightColor; highlightColor.a = 0xFF; Gui::drawRectangled(74, 313 + (line - cheatListOffset) * 40, 10, 10, (m_selectedEntry == line && m_menuLocation == CHEATS) ? highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); } } - } else if (m_cheatsPresent && m_memoryDump->size() == 0) - Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Cheats for this game present but title version or region doesn't match!", ALIGNED_CENTER); - + } + else if (m_cheatsPresent && m_memoryDump->size() == 0) + Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Cheats for this game present but title version or region doesn't match!", ALIGNED_CENTER); - if (m_memoryDump->getDumpInfo().dumpType == DumpType::DATA) { - if (m_memoryDump->size() > 0) { + if (m_memoryDump->getDumpInfo().dumpType == DumpType::DATA) + { + if (m_memoryDump->size() > 0) + { Gui::drawRectangle(Gui::g_framebuffer_width - 552, 256, 500, 366, currTheme.textColor); Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, "Found candidates", ALIGNED_CENTER); Gui::drawShadow(Gui::g_framebuffer_width - 552, 256, 500, 366 * 40); Gui::drawRectangle(Gui::g_framebuffer_width - 550, 300, 496, 320, currTheme.separatorColor); - ss.str(""); ss << (static_cast(m_memoryDump->size()) / (0x100000)) << "MB dumped"; Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 302, 450, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); } - } else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { - if (m_memoryDump->size() > 0) { - Gui::drawRectangle(Gui::g_framebuffer_width - 552, 256, 500, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40, currTheme.textColor); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, "Found candidates", ALIGNED_CENTER); - Gui::drawShadow(Gui::g_framebuffer_width - 552, 256, 500, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40); + } + else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + if (m_memoryDump->size() > 0) + { + if (m_memoryDump1 == nullptr) + { + Gui::drawRectangle(Gui::g_framebuffer_width - 552, 256, 500, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40, currTheme.textColor); + ss.str(""); + ss << "Found candidates " << std::dec << (((m_menuLocation == CANDIDATES) ? m_selectedEntry : 0) + m_addresslist_offset + 1) << " / " << std::dec << ((m_memoryDump->size() / sizeof(u64))); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, ss.str().c_str(), ALIGNED_CENTER); + Gui::drawShadow(Gui::g_framebuffer_width - 552, 256, 500, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40); + } + else + { + Gui::drawRectangle(Gui::g_framebuffer_width - 557, 256, 549, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40, currTheme.textColor); + ss.str(""); + ss << " Book Marks " << std::dec << (((m_menuLocation == CANDIDATES) ? m_selectedEntry : 0) + m_addresslist_offset + 1) << " / " << std::dec << ((m_memoryDump->size() / sizeof(u64))); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, ss.str().c_str(), ALIGNED_CENTER); + // Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, "Book Marks", ALIGNED_CENTER); + Gui::drawShadow(Gui::g_framebuffer_width - 557, 256, 549, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40); + } } + // mod start memory line offset + + if (m_memoryDump1 == nullptr) + for (u8 line = 0; line < 8; line++) + { + if ((line + m_addresslist_offset) >= (m_memoryDump->size() / sizeof(u64))) + break; + + ss.str(""); + + if (line < 8) // && (m_memoryDump->size() / sizeof(u64)) != 8) + { + u64 address = 0; + m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + // candidate display + if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().heapBaseAddress) << " ]"; + else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + ss << "[ MAIN + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().mainBaseAddress) << " ]"; + else + ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().addrSpaceBaseAddress) << " ]"; + + ss << " ( " << _getAddressDisplayString(address, m_debugger, (searchType_t)m_searchType) << " )"; + + if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) + ss << " \uE130"; + } + else + ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; - for (u8 line = 0; line < 8; line++) { - if (line >= (m_memoryDump->size() / sizeof(u64))) break; + Gui::drawRectangle(Gui::g_framebuffer_width - 550, 300 + line * 40, 496, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 530, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + } + else // Book mark screen + for (u8 line = 0; line < 8; line++) + { + if ((line + m_addresslist_offset) >= (m_memoryDump->size() / sizeof(u64))) + break; - ss.str(""); + ss.str(""); - if (line < 7 && (m_memoryDump->size() / sizeof(u64)) != 8) { - u64 address = 0; - m_memoryDump->getData(line * sizeof(u64), &address, sizeof(u64)); + bookmark_t bookmark; + if (line < 8) // && (m_memoryDump->size() / sizeof(u64)) != 8) + { + u64 address = 0; + m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + m_AttributeDumpBookmark->getData((line + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // bookmark display - if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) - ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().heapBaseAddress) << " ]"; - else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) - ss << "[ MAIN + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().mainBaseAddress) << " ]"; - else - ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().addrSpaceBaseAddress) << " ]"; + ss << "[0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << "]"; //<< std::left << std::setfill(' ') << std::setw(18) << bookmark.label << - ss << " ( " << _getAddressDisplayString(address, m_debugger, (searchType_t)m_searchType) << " )"; + ss << " ( " << _getAddressDisplayString(address, m_debugger, (searchType_t)bookmark.type) << " )"; - if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) - ss << " \uE130"; - } - else - ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; + if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) + ss << " \uE130"; + } + else + ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; - Gui::drawRectangle(Gui::g_framebuffer_width - 550, 300 + line * 40, 496, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 530, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); - } + Gui::drawRectangle(Gui::g_framebuffer_width - 555, 300 + line * 40, 545, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 545, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, bookmark.label, ALIGNED_LEFT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 340, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + } } Gui::drawShadow(0, 0, Gui::g_framebuffer_width, 256); @@ -364,152 +531,352 @@ void GuiCheats::draw() { Gui::drawRectangle(256 + x, 0, 2, 50, m_memory[x]); drawSearchRAMMenu(); - + drawEditRAMMenu(); + drawSearchPointerMenu(); Gui::endDraw(); } +// BM2 -void GuiCheats::drawSearchRAMMenu() { +void GuiCheats::drawSearchPointerMenu() +{ + if (m_searchMenuLocation != SEARCH_POINTER) + return; static u32 cursorBlinkCnt = 0; u32 strWidth = 0; std::stringstream ss; - if (m_searchMenuLocation == SEARCH_NONE) return; - Gui::drawRectangled(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x00, 0x00, 0x00, 0xA0)); Gui::drawRectangle(50, 50, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.backgroundColor); Gui::drawRectangle(100, 135, Gui::g_framebuffer_width - 200, 1, currTheme.textColor); - Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Search Memory"); + Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Search Pointer"); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, + "Set the parameters of your pointer search. You can keep the time require within reasonable range by trading off between \n" + "max depth, max range and max source. The impact of these setting to the time taken to complete the search will largely \n" + "depends on the game itself too. Dump forward only assume pointer pointing to larger address is forward which may not be.", + ALIGNED_CENTER); + + //Gui::drawRectangle(300, 250, Gui::g_framebuffer_width - 600, 80, currTheme.separatorColor); + // Gui::drawRectangle(300, 327, Gui::g_framebuffer_width - 600, 3, currTheme.textColor); + // m_max_depth = 2; + // m_max_range = 0x300; + // m_max_source = 200; + + // if (m_searchValueFormat == FORMAT_DEC) + // ss << _getValueDisplayString(m_searchValue[0], m_searchType); + // else if (m_searchValueFormat == FORMAT_HEX) + + Gui::drawText(font20, 310, 165, currTheme.textColor, "Max Depth"); + ss.str(""); + ss << std::uppercase << std::dec << m_max_depth; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 620, 165, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 0) + Gui::drawRectangled(622 + strWidth, 165, 3, 35, currTheme.highlightColor); + + Gui::drawText(font20, 310, 225, currTheme.textColor, "Max Range"); + ss.str(""); + ss << "0x" << std::uppercase << std::hex << m_max_range; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 620, 225, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 1) + Gui::drawRectangled(622 + strWidth, 225, 3, 35, currTheme.highlightColor); + + Gui::drawText(font20, 310, 285, currTheme.textColor, "Max Source"); + ss.str(""); + ss << std::uppercase << std::dec << m_max_source; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 620, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 2) + Gui::drawRectangled(622 + strWidth, 285, 3, 35, currTheme.highlightColor); + Gui::drawText(font20, 310, 345, currTheme.textColor, "Target Address"); + ss.str(""); + ss << "0x" << std::uppercase << std::hex << m_EditorBaseAddr; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 620, 345, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 3) + Gui::drawRectangled(622 + strWidth, 345, 3, 35, currTheme.highlightColor); + + Gui::drawText(font20, 310, 405, currTheme.textColor, "Dump Forward only"); + ss.str(""); + if (m_forwarddump) + ss << "YES"; + else + ss << "NO"; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 620, 405, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 4) + Gui::drawRectangled(622 + strWidth, 405, 3, 35, currTheme.highlightColor); + + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0EF Start Search \uE0E1 Back \uE0E0 Edit", ALIGNED_RIGHT); + + // if (m_selectedEntry == 3) + // Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 155, 345, 310, 90, currTheme.highlightColor); + + // if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) + // { + // Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedColor); + // Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.backgroundColor, "Search Now!", ALIGNED_CENTER); + // } + // else + // { + // Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedButtonColor); + // Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.separatorColor, "Search Now!", ALIGNED_CENTER); + // } + + // break; + // case SEARCH_NONE: + // break; +} + +void GuiCheats::drawEditRAMMenu() +{ + static u32 cursorBlinkCnt = 0; + u32 strWidth = 0; + std::stringstream ss; + + if (m_searchMenuLocation != SEARCH_editRAM) // need + return; + + Gui::drawRectangled(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x00, 0x00, 0x00, 0xA0)); + + Gui::drawRectangle(50, 50, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.backgroundColor); + Gui::drawRectangle(100, 135, Gui::g_framebuffer_width - 200, 1, currTheme.textColor); + Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Edit Memory"); Gui::drawTextAligned(font20, 100, 160, currTheme.textColor, "\uE149 \uE0A4", ALIGNED_LEFT); Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, 160, currTheme.textColor, "\uE0A5 \uE14A", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, 260, 160, m_searchMenuLocation == SEARCH_TYPE ? currTheme.selectedColor : currTheme.textColor, "U8", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 510, 160, m_searchMenuLocation == SEARCH_MODE ? currTheme.selectedColor : currTheme.textColor, "U16", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 760, 160, m_searchMenuLocation == SEARCH_REGION ? currTheme.selectedColor : currTheme.textColor, "u32", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "u64", ALIGNED_CENTER); + + // strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + // ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().heapBaseAddress) << " ]"; + // std::stringstream ss; + // + // dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + // address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry -1 - (m_selectedEntry div 5))*4; + // m_selectedEntry = (m_EditorBaseAddr % 10) / 4 + 11; + u64 addr = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20; + u32 out; + + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + ss.str(""); + ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << " ]"; + Gui::drawText(font24, 520, 70, currTheme.textColor, ss.str().c_str()); + // Next to display the value in the selected type now is u32 in hex + ss.str(""); + dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; + Gui::drawText(font24, 820, 70, currTheme.textColor, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); //ss.str().c_str() + + for (u8 i = 0; i < 40; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(88 + (i % 5) * 225, 235 + (i / 5) * 50, 225, 50, m_searchMode == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + if ((i % 5) != 0) + { + Gui::drawRectangled(93 + (i % 5) * 225, 240 + (i / 5) * 50, 215, 40, currTheme.separatorColor); + ss.str(""); + dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; + Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + addr += 4; + } + else + { + ss.str(""); + ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr) << " ]"; + Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } + } +} - Gui::drawTextAligned(font20, 260, 160, m_searchMenuLocation == SEARCH_TYPE ? currTheme.selectedColor : currTheme.textColor, "TYPE", ALIGNED_CENTER); - Gui::drawTextAligned(font20, 510, 160, m_searchMenuLocation == SEARCH_MODE ? currTheme.selectedColor : currTheme.textColor, "MODE", ALIGNED_CENTER); - Gui::drawTextAligned(font20, 760, 160, m_searchMenuLocation == SEARCH_REGION ? currTheme.selectedColor : currTheme.textColor, "REGION", ALIGNED_CENTER); - Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "VALUE", ALIGNED_CENTER); - - static const char* const typeNames[] = { "u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "flt", "dbl", "void*" }; - static const char* const modeNames[] = { "==", "!=", ">", ">=", "<", "<=", "A..B", "SAME", "DIFF", "+ +", "- -" }; - static const char* const regionNames[] = { "HEAP", "MAIN", "HEAP + MAIN", "RAM" }; +void GuiCheats::drawSearchRAMMenu() +{ + static u32 cursorBlinkCnt = 0; + u32 strWidth = 0; + std::stringstream ss; - switch (m_searchMenuLocation) { - case SEARCH_TYPE: - for (u8 i = 0; i < 11; i++) { - if (m_selectedEntry == i) - Gui::drawRectangled(356 + (i / 2) * 100, 220 + (i % 2) * 100, 90, 90, m_searchType == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + if (m_searchMenuLocation == SEARCH_NONE) + return; - Gui::drawRectangled(361 + (i / 2) * 100, 225 + (i % 2) * 100, 80, 80, currTheme.separatorColor); - Gui::drawTextAligned(font20, 400 + (i / 2) * 100, 250 + (i % 2) * 100, currTheme.textColor, typeNames[i], ALIGNED_CENTER); - } + Gui::drawRectangled(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x00, 0x00, 0x00, 0xA0)); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the data type of the value you’re searching here. The prefix [u] means unsigned (positive integers), [s] means \n" - "signed (positive and negative integers), [flt] is for floating point numbers (rational numbers), [dbl] is for double (bigger \n" - "rational numbers) and [void*] stands for pointer (link to another memory ) which is useful for creating cheats. The \n" - "number that follows is the number of bits used in memory which determines the maximum value. Choose the data type that \n" - "best fits for the type of data you’re looking for.", ALIGNED_CENTER); + Gui::drawRectangle(50, 50, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.backgroundColor); + Gui::drawRectangle(100, 135, Gui::g_framebuffer_width - 200, 1, currTheme.textColor); + Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Search Memory"); - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, 100, 160, currTheme.textColor, "\uE149 \uE0A4", ALIGNED_LEFT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, 160, currTheme.textColor, "\uE0A5 \uE14A", ALIGNED_RIGHT); - break; - case SEARCH_MODE: - for (u8 i = 0; i < 11; i++) { - if (m_selectedEntry == i) - Gui::drawRectangled(356 + (i / 2) * 100, 220 + (i % 2) * 100, 90, 90, m_searchMode == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + Gui::drawTextAligned(font20, 260, 160, m_searchMenuLocation == SEARCH_TYPE ? currTheme.selectedColor : currTheme.textColor, "TYPE", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 510, 160, m_searchMenuLocation == SEARCH_MODE ? currTheme.selectedColor : currTheme.textColor, "MODE", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 760, 160, m_searchMenuLocation == SEARCH_REGION ? currTheme.selectedColor : currTheme.textColor, "REGION", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "VALUE", ALIGNED_CENTER); + + static const char *const typeNames[] = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "flt", "dbl", "void*"}; + static const char *const modeNames[] = {"==", "!=", ">", "StateB", "<", "StateA", "A..B", "SAME", "DIFF", "+ +", "- -", "PTR"}; + static const char *const regionNames[] = {"HEAP", "MAIN", "HEAP + MAIN", "RAM"}; + + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + for (u8 i = 0; i < 11; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(356 + (i / 2) * 100, 220 + (i % 2) * 100, 90, 90, m_searchType == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + + Gui::drawRectangled(361 + (i / 2) * 100, 225 + (i % 2) * 100, 80, 80, currTheme.separatorColor); + Gui::drawTextAligned(font20, 400 + (i / 2) * 100, 250 + (i % 2) * 100, currTheme.textColor, typeNames[i], ALIGNED_CENTER); + } - Gui::drawRectangled(361 + (i / 2) * 100, 225 + (i % 2) * 100, 80, 80, currTheme.separatorColor); - Gui::drawTextAligned(font20, 400 + (i / 2) * 100, 250 + (i % 2) * 100, currTheme.textColor, modeNames[i], ALIGNED_CENTER); - } + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the data type of the value you’re searching here. The prefix [u] means unsigned (positive integers), [s] means \n" + "signed (positive and negative integers), [flt] is for floating point numbers (rational numbers), [dbl] is for double (bigger \n" + "rational numbers) and [void*] stands for pointer (link to another memory ) which is useful for creating cheats. The \n" + "number that follows is the number of bits used in memory which determines the maximum value. Choose the data type that \n" + "best fits for the type of data you’re looking for.", + ALIGNED_CENTER); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the mode you want to use for finding values. With these modes EdiZon will search for values that are equal to [==], \n" - "not equal to [!=], greater than [>], greater than or equal to [>=], less than [<], or less than or equal to [<=] the value \n" - "that you input. [A : B] allows you to set a (min : max) range of values, SAME and DIFF search allows you to find values that \n" - "stayed the same or changed since the last search, [+ +] and [- -] checks for values that increased or decreased since the \n" - "previous search.", ALIGNED_CENTER); - - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - break; - case SEARCH_REGION: - for (u8 i = 0; i < 4; i++) { - if (m_selectedEntry == i) - Gui::drawRectangled((Gui::g_framebuffer_width / 2) - 155, 215 + i * 70, 310, 70, m_searchRegion == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - Gui::drawRectangled((Gui::g_framebuffer_width / 2) - 150, 220 + i * 70, 300, 60, currTheme.separatorColor); - Gui::drawTextAligned(font20, (Gui::g_framebuffer_width / 2), 235 + i * 70, currTheme.textColor, regionNames[i], ALIGNED_CENTER); - } + break; + case SEARCH_MODE: + for (u8 i = 0; i < 12; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(356 + (i / 2) * 100, 220 + (i % 2) * 100, 90, 90, m_searchMode == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + Gui::drawRectangled(361 + (i / 2) * 100, 225 + (i % 2) * 100, 80, 80, currTheme.separatorColor); + Gui::drawTextAligned(font20, 400 + (i / 2) * 100, 250 + (i % 2) * 100, currTheme.textColor, modeNames[i], ALIGNED_CENTER); + } - Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the memory region you want to search in. HEAP contains dynamically allocated values and will be where the majority of \n" - "values worth changing will be found. MAIN contains global variables and instructions for game operation. You may find some \n" - "values here but it’s mainly for finding pointers to HEAP values or changing game code. RAM will search the entirety of the Games \n" - "used memory including memory shared memory and resources. Should only be used as a final resort as this will be extremely slow. \n", ALIGNED_CENTER); - - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - break; - case SEARCH_VALUE: - Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the value you want to search for. The value(s) you enter here will depend on what options you've chosen in the \n" - "first three sections. Either it's the exact integer you want to search for, a floating point number or even two values that \n" - "will be used as range.", ALIGNED_CENTER); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the mode you want to use for finding values. With these modes EdiZon will search for values that are equal to [==], \n" + "not equal to [!=], greater than [>], greater than or equal to [>=], less than [<], or less than or equal to [<=] the value \n" + "that you input. [A : B] allows you to set a (min : max) range of values, SAME and DIFF search allows you to find values that \n" + "stayed the same or changed since the last search, [+ +] and [- -] checks for values that increased or decreased since the \n" + "previous search.", + ALIGNED_CENTER); + + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + break; + case SEARCH_REGION: + for (u8 i = 0; i < 4; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled((Gui::g_framebuffer_width / 2) - 155, 215 + i * 70, 310, 70, m_searchRegion == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + + Gui::drawRectangled((Gui::g_framebuffer_width / 2) - 150, 220 + i * 70, 300, 60, currTheme.separatorColor); + Gui::drawTextAligned(font20, (Gui::g_framebuffer_width / 2), 235 + i * 70, currTheme.textColor, regionNames[i], ALIGNED_CENTER); + } - //Gui::drawRectangle(300, 250, Gui::g_framebuffer_width - 600, 80, currTheme.separatorColor); - Gui::drawRectangle(300, 327, Gui::g_framebuffer_width - 600, 3, currTheme.textColor); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the memory region you want to search in. HEAP contains dynamically allocated values and will be where the majority of \n" + "values worth changing will be found. MAIN contains global variables and instructions for game operation. You may find some \n" + "values here but it’s mainly for finding pointers to HEAP values or changing game code. RAM will search the entirety of the Games \n" + "used memory including memory shared memory and resources. Should only be used as a final resort as this will be extremely slow. \n", + ALIGNED_CENTER); + + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + break; + case SEARCH_VALUE: + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the value you want to search for. The value(s) you enter here will depend on what options you've chosen in the \n" + "first three sections. Either it's the exact integer you want to search for, a floating point number or even two values that \n" + "will be used as range.", + ALIGNED_CENTER); + + //Gui::drawRectangle(300, 250, Gui::g_framebuffer_width - 600, 80, currTheme.separatorColor); + Gui::drawRectangle(300, 327, Gui::g_framebuffer_width - 600, 3, currTheme.textColor); + if (m_searchValueFormat == FORMAT_DEC) + ss << _getValueDisplayString(m_searchValue[0], m_searchType); + else if (m_searchValueFormat == FORMAT_HEX) + ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u64; + + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 310, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + + // Start Mod for search Range display + if (cursorBlinkCnt++ % 20 > 10 && m_selectedEntry == 0 && (m_searchValueIndex == 0)) + Gui::drawRectangled(312 + strWidth, 285, 3, 35, currTheme.highlightColor); + + if (m_searchMode == SEARCH_MODE_RANGE) + { + ss.str(""); if (m_searchValueFormat == FORMAT_DEC) - ss << _getValueDisplayString(m_searchValue[0], m_searchType); + ss << _getValueDisplayString(m_searchValue[1], m_searchType); else if (m_searchValueFormat == FORMAT_HEX) - ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u64; - + ss << "0x" << std::uppercase << std::hex << m_searchValue[1]._u64; Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); - Gui::drawTextAligned(font20, 310, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font20, 650, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + } - if (cursorBlinkCnt++ % 20 > 10 && m_selectedEntry == 0) - Gui::drawRectangled(312 + strWidth, 285, 3, 35, currTheme.highlightColor); + if (cursorBlinkCnt++ % 20 > 10 && m_selectedEntry == 0 && (m_searchValueIndex == 1)) + Gui::drawRectangled(652 + strWidth, 285, 3, 35, currTheme.highlightColor); + // End Mod - if (m_searchValueFormat == FORMAT_DEC) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E2 Hexadecimal view \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - else if (m_searchValueFormat == FORMAT_HEX) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E2 Decimal view \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - - if (m_selectedEntry == 1) - Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 155, 345, 310, 90, currTheme.highlightColor); - - if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) { - Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedColor); - Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.backgroundColor, "Search Now!", ALIGNED_CENTER); - } - else { - Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedButtonColor); - Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.separatorColor, "Search Now!", ALIGNED_CENTER); - } - + if (m_searchValueFormat == FORMAT_DEC) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E2 Hexadecimal view \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + else if (m_searchValueFormat == FORMAT_HEX) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E2 Decimal view \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - break; - case SEARCH_NONE: break; + if (m_selectedEntry == 1) + Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 155, 345, 310, 90, currTheme.highlightColor); + + if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) + { + Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedColor); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.backgroundColor, "Search Now!", ALIGNED_CENTER); + } + else + { + Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedButtonColor); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.separatorColor, "Search Now!", ALIGNED_CENTER); + } + + break; + case SEARCH_NONE: + break; } } -void GuiCheats::onInput(u32 kdown) { - if (kdown & KEY_B) { +void GuiCheats::onInput(u32 kdown) +{ + if (kdown & KEY_B) + { - if (m_searchMenuLocation == SEARCH_NONE) { - Gui::g_nextGui = GUI_MAIN; + if (m_searchMenuLocation == SEARCH_NONE) + { + // Gui::g_nextGui = GUI_MAIN; + Gui::g_requestExit = true; return; } - else if (m_searchMenuLocation == SEARCH_TYPE) { + else if (m_searchMenuLocation == SEARCH_POINTER) + { + m_searchMenuLocation = SEARCH_NONE; + } + else if (m_searchMenuLocation == SEARCH_editRAM) + { + m_searchMenuLocation = SEARCH_NONE; + } + else if (m_searchMenuLocation == SEARCH_TYPE) + { if (m_searchType != SEARCH_TYPE_NONE && m_memoryDump->size() == 0) m_searchType = SEARCH_TYPE_NONE; - else + else m_searchMenuLocation = SEARCH_NONE; } - else if (m_searchMenuLocation == SEARCH_MODE) { + else if (m_searchMenuLocation == SEARCH_MODE) + { if (m_searchMode != SEARCH_MODE_NONE) m_searchMode = SEARCH_MODE_NONE; - else + else m_searchMenuLocation = SEARCH_NONE; } - else if (m_searchMenuLocation == SEARCH_REGION) { + else if (m_searchMenuLocation == SEARCH_REGION) + { if (m_searchRegion != SEARCH_REGION_NONE && m_memoryDump->size() == 0) m_searchRegion = SEARCH_REGION_NONE; - else + else m_searchMenuLocation = SEARCH_NONE; } else if (m_searchMenuLocation == SEARCH_VALUE) @@ -519,141 +886,332 @@ void GuiCheats::onInput(u32 kdown) { if (m_debugger->getRunningApplicationPID() == 0) return; - if (m_searchMenuLocation == SEARCH_NONE) { - if (kdown & KEY_UP) { - if (m_selectedEntry > 0) - m_selectedEntry--; + if (m_searchMenuLocation == SEARCH_POINTER) + { + if (kdown & KEY_UP) + { + if (m_selectedEntry > 0) + m_selectedEntry--; + } - if (m_menuLocation == CHEATS) - if (m_selectedEntry == cheatListOffset && cheatListOffset > 0) - cheatListOffset--; + if (kdown & KEY_DOWN) + { + if (m_selectedEntry < 4) + m_selectedEntry++; + } + + if (kdown & KEY_R) + { + if (m_selectedEntry == 0 && m_max_depth < MAX_POINTER_DEPTH) + { + m_max_depth++; } - - if (kdown & KEY_DOWN) { - if (m_menuLocation == CANDIDATES) { - if (m_selectedEntry < 7 && m_selectedEntry < ((m_memoryDump->size() / sizeof(u64)) - 1)) - m_selectedEntry++; - } else { - if (m_selectedEntry < (m_cheatCnt - 1)) - m_selectedEntry++; + else if (m_selectedEntry == 1 && m_max_range < MAX_POINTER_RANGE) + { + m_max_range += 0x100; + } + else if (m_selectedEntry == 2 && m_max_source < MAX_NUM_SOURCE_POINTER) + { + m_max_source += 10; + } + else if (m_selectedEntry == 4) + { + m_forwarddump = !m_forwarddump; + }; + } - if (m_selectedEntry == (cheatListOffset + 7) && cheatListOffset < (m_cheatCnt - 8)) - cheatListOffset++; - } + if (kdown & KEY_L) + { + if (m_selectedEntry == 0 && m_max_depth > 2) + { + m_max_depth--; + } + else if (m_selectedEntry == 1 && m_max_range > 0x100) + { + m_max_range -= 0x100; + } + else if (m_selectedEntry == 2 && m_max_source > 20) + { + m_max_source -= 10; + }; + } + } + + if (m_searchMenuLocation == SEARCH_NONE) + { + if (kdown & KEY_UP) + { + if (m_selectedEntry > 0) + m_selectedEntry--; + + if (m_menuLocation == CHEATS) + if (m_selectedEntry == cheatListOffset && cheatListOffset > 0) + cheatListOffset--; + } + + if (kdown & KEY_DOWN) // + { + if (m_menuLocation == CANDIDATES) + { + if (m_selectedEntry < 7 && m_selectedEntry + m_addresslist_offset < ((m_memoryDump->size() / sizeof(u64)) - 1)) + m_selectedEntry++; } + else + { + if (m_selectedEntry < (m_cheatCnt - 1)) + m_selectedEntry++; - if (m_memoryDump->size() > 0) { - if (kdown & KEY_LEFT) - if (m_cheatCnt > 0) { - m_menuLocation = CHEATS; - m_selectedEntry = 0; - cheatListOffset = 0; - } + if (m_selectedEntry == (cheatListOffset + 7) && cheatListOffset < (m_cheatCnt - 8)) + cheatListOffset++; + } + } + // start mod + if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS) + { + // m_searchMenuLocation = SEARCH_editRAM; + // printf("L Stick pressed, start pointer search *************\n"); + // startpointersearch(m_heapBaseAddr + 80, 10, 0x800, 3); + // printf("done pointer search ********************************\n"); + // printf("making a dump for pointers"); + // GuiCheats::searchMemoryAddressesPrimary(m_debugger, m_searchValue[0], m_searchValue[1], SEARCH_TYPE_UNSIGNED_64BIT, SEARCH_MODE_RANGE, SEARCH_REGION_HEAP_AND_MAIN, &m_memoryDump, m_memoryInfo); + + // m_menuLocation = CANDIDATES; + m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; + m_searchMode = SEARCH_MODE_POINTER; + m_searchRegion = SEARCH_REGION_HEAP_AND_MAIN; + m_searchMenuLocation = SEARCH_VALUE; + m_selectedEntry = 1; + m_searchValue[0]._u64 = 0x1000000000; + m_searchValue[1]._u64 = 0x8000000000; + } - if (kdown & KEY_RIGHT) { - m_menuLocation = CANDIDATES; + if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS) + { + printf("start checking pointer\n"); + (new Snackbar("Adding address from cheat not supported yet"))->show(); + // pointercheck(); disable for now; + } + // end mod + + if (m_memoryDump->size() > 0) + { + if (kdown & KEY_LEFT) + if (m_cheatCnt > 0) + { + m_menuLocation = CHEATS; m_selectedEntry = 0; cheatListOffset = 0; } - } - if (m_menuLocation == CANDIDATES) { /* Candidates menu */ - if (m_memoryDump->size() > 0) { - if (kdown & KEY_X && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { - u64 address = 0; - m_memoryDump->getData(m_selectedEntry * sizeof(u64), &address, sizeof(u64)); - if (!_isAddressFrozen(address)) { - u64 outValue; + if (kdown & KEY_RIGHT) + { + m_menuLocation = CANDIDATES; + m_selectedEntry = 0; + cheatListOffset = 0; + } + } - if (R_SUCCEEDED(dmntchtEnableFrozenAddress(address, dataTypeSizes[m_searchType], &outValue))) { + if (m_menuLocation == CANDIDATES) + { /* Candidates menu */ + if (m_memoryDump->size() > 0) + { + if (kdown & KEY_X && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + + if (!_isAddressFrozen(address)) + { + u64 outValue; + if (m_memoryDump1 == nullptr) + { + if (R_SUCCEEDED(dmntchtEnableFrozenAddress(address, dataTypeSizes[m_searchType], &outValue))) + { (new Snackbar("Froze variable!"))->show(); - m_frozenAddresses.insert({ address, outValue }); + m_frozenAddresses.insert({address, outValue}); } else (new Snackbar("Failed to freeze variable!"))->show(); } - else { - if (R_SUCCEEDED(dmntchtDisableFrozenAddress(address))) { - (new Snackbar("Unfroze variable!"))->show(); - m_frozenAddresses.erase(address); + else + { + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + if (R_SUCCEEDED(dmntchtEnableFrozenAddress(address, dataTypeSizes[bookmark.type], &outValue))) + { + (new Snackbar("Froze variable!"))->show(); + m_frozenAddresses.insert({address, outValue}); } else - (new Snackbar("Failed to unfreeze variable!"))->show(); + (new Snackbar("Failed to freeze variable!"))->show(); } } - - if (kdown & KEY_A && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { - u64 address = 0; - m_memoryDump->getData(m_selectedEntry * sizeof(u64), &address, sizeof(u64)); - - if (m_selectedEntry < 7) { - char input[16]; - char initialString[21]; - - strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); - if (Gui::requestKeyboardInput("Enter value", "Enter a value that should get written at this .", initialString, SwkbdType::SwkbdType_NumPad, input, 15)) { - if(m_searchType == SEARCH_TYPE_FLOAT_32BIT) { - auto value = static_cast(std::atof(input)); - m_debugger->writeMemory(&value, sizeof(value), address); - } else if(m_searchType == SEARCH_TYPE_FLOAT_64BIT) { - auto value = std::atof(input); - m_debugger->writeMemory(&value, sizeof(value), address); - } else if(m_searchType != SEARCH_TYPE_NONE) { - auto value = std::atol(input); - m_debugger->writeMemory((void*)&value, dataTypeSizes[m_searchType], address); - } - } + else + { + if (R_SUCCEEDED(dmntchtDisableFrozenAddress(address))) + { + (new Snackbar("Unfroze variable!"))->show(); + m_frozenAddresses.erase(address); } - else if ((m_memoryDump->size() / sizeof(u64)) < 25) { - std::vector options; - options.clear(); - - std::stringstream ss; - for (u32 i = 7; i < (m_memoryDump->size() / sizeof(u64)); i++) { //TODO: i? - m_memoryDump->getData(m_selectedEntry * sizeof(u64), &address, sizeof(u64)); - ss.str(""); - ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; - - ss << " (" << _getAddressDisplayString(address, m_debugger, m_searchType); + else + (new Snackbar("Failed to unfreeze variable!"))->show(); + } + } + // add bookmark + if (kdown & KEY_PLUS && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); // prompt for label + printf("%s\n", "PLUS key pressed"); + } + // add bookmark end + // show memory editor + // BM1 + if (kdown & KEY_RSTICK && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_searchMenuLocation = SEARCH_editRAM; + m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; + } + if ((kdown & KEY_LSTICK) && (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR)) + { + printf("start pointer search ....................\n"); + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + printf("Address %lx \n\n\n", m_EditorBaseAddr); + m_Time1 = time(NULL); + // m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); + m_searchValue[0]._u64 = m_EditorBaseAddr - 0x800; + m_searchValue[1]._u64 = m_EditorBaseAddr; + startpointersearch(m_EditorBaseAddr); + printf("done pointer search \n"); + printf("Time taken =%d\n", time(NULL) - m_Time1); + + // m_EditorBaseAddr = static_cast(std::stoul(input, nullptr, 16)); + // m_searchMenuLocation = SEARCH_editRAM; + // m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; + } + // end + if (kdown & KEY_A && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + searchType_t savetype = m_searchType; + if (m_memoryDump1 != nullptr) + { + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + m_searchType = bookmark.type; + } - options.push_back(ss.str()); - printf("%s\n", ss.str().c_str()); + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + + if (m_selectedEntry < 8) + { + char input[16]; + char initialString[21]; + // start mod address content edit Hex option + + // + strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + if (Gui::requestKeyboardInput("Enter value", "Enter a value that should get written at this .", initialString, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, input, 18)) + { + if (m_searchValueFormat == FORMAT_HEX) + { + auto value = static_cast(std::stoul(input, nullptr, 16)); + m_debugger->writeMemory(&value, sizeof(value), address); } + else if (m_searchType == SEARCH_TYPE_FLOAT_32BIT) + { + auto value = static_cast(std::atof(input)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_64BIT) + { + auto value = std::atof(input); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType != SEARCH_TYPE_NONE) + { + auto value = std::atol(input); + m_debugger->writeMemory((void *)&value, dataTypeSizes[m_searchType], address); + } + } + } + else if ((m_memoryDump->size() / sizeof(u64)) < 25) + { + std::vector options; + options.clear(); + + std::stringstream ss; + for (u32 i = 7; i < (m_memoryDump->size() / sizeof(u64)); i++) + { //TODO: i? + m_memoryDump->getData(m_selectedEntry * sizeof(u64), &address, sizeof(u64)); + ss.str(""); + ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + + ss << " (" << _getAddressDisplayString(address, m_debugger, m_searchType); + + options.push_back(ss.str()); + printf("%s\n", ss.str().c_str()); + } - (new ListSelector("Edit value at ", "\uE0E0 Edit value \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { - if (k & KEY_A) { - char input[16]; - char initialString[21]; - u64 selectedAddress; - - m_memoryDump->getData((selectedItem + 7) * sizeof(u64), &selectedAddress, sizeof(u64)); - - strcpy(initialString, _getAddressDisplayString(selectedAddress, m_debugger, m_searchType).c_str()); - - if (Gui::requestKeyboardInput("Enter value", "Enter a value for which the game's memory should be searched.", initialString, SwkbdType::SwkbdType_NumPad, input, 15)) { - u64 value = atol(input); - if (value > dataTypeMaxValues[m_searchType] || value < dataTypeMinValues[m_searchType]) { - (new Snackbar("Entered value isn't inside the range of this data type. Please enter a different value."))->show(); - return; - } - - m_memoryDump->getData((m_selectedEntry) * sizeof(u64), &selectedAddress, sizeof(u64)); - m_debugger->pokeMemory(dataTypeSizes[m_searchType], selectedAddress, value); - } - } - })->show(); - } else (new Snackbar("Too many addresses! Narrow down the selection before editing."))->show(); + (new ListSelector("Edit value at ", "\uE0E0 Edit value \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { + if (k & KEY_A) + { + char input[16]; + char initialString[21]; + u64 selectedAddress; + + m_memoryDump->getData((selectedItem + 7) * sizeof(u64), &selectedAddress, sizeof(u64)); + + strcpy(initialString, _getAddressDisplayString(selectedAddress, m_debugger, m_searchType).c_str()); + + if (Gui::requestKeyboardInput("Enter value", "Enter a value for which the game's memory should be searched.", initialString, SwkbdType::SwkbdType_NumPad, input, 15)) + { + u64 value = atol(input); + if (value > dataTypeMaxValues[m_searchType] || value < dataTypeMinValues[m_searchType]) + { + (new Snackbar("Entered value isn't inside the range of this data type. Please enter a different value."))->show(); + return; + } + + m_memoryDump->getData((m_selectedEntry) * sizeof(u64), &selectedAddress, sizeof(u64)); + m_debugger->pokeMemory(dataTypeSizes[m_searchType], selectedAddress, value); + } + } + }) + ->show(); } + else + (new Snackbar("Too many addresses! Narrow down the selection before editing."))->show(); + + m_searchType = savetype; // restore value } - } else { /* Cheats menu */ - if (kdown & KEY_A) { - if (m_cheatCnt == 0) return; + } + } + else + { /* Cheats menu */ + if (kdown & KEY_A) + { + if (m_cheatCnt == 0) + return; dmntchtToggleCheat(m_cheats[m_selectedEntry].cheat_id); u64 cheatCnt = 0; dmntchtGetCheatCount(&cheatCnt); - if (cheatCnt > 0) { + if (cheatCnt > 0) + { delete[] m_cheats; m_cheats = new DmntCheatEntry[cheatCnt]; dmntchtGetCheats(m_cheats, cheatCnt, 0, &m_cheatCnt); @@ -661,15 +1219,26 @@ void GuiCheats::onInput(u32 kdown) { } } - if (kdown & KEY_MINUS) { - if (m_memoryDump->size() == 0) { + if (kdown & KEY_MINUS) + { + //make sure not using bookmark m_searchType + if (m_memoryDump1 != nullptr) + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + } + m_addresslist_offset = 0; + // end mod + if (m_memoryDump->size() == 0) + { std::vector options; - + if (m_frozenAddresses.size() == 0) return; std::stringstream ss; - for (auto [addr, value] : m_frozenAddresses) { + for (auto [addr, value] : m_frozenAddresses) + { ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr - m_addressSpaceBaseAddr) << " ] "; ss << "( " << std::dec << value << " )"; options.push_back(ss.str()); @@ -677,191 +1246,498 @@ void GuiCheats::onInput(u32 kdown) { } (new ListSelector("Frozen Addresses", "\uE0E0 Unfreeze \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { - if (k & KEY_A) { - auto itr = m_frozenAddresses.begin(); - std::advance(itr, selectedItem); - - dmntchtDisableFrozenAddress(itr->first); - m_frozenAddresses.erase(itr->first); - } - })->show(); - } else { + if (k & KEY_A) + { + auto itr = m_frozenAddresses.begin(); + std::advance(itr, selectedItem); + + dmntchtDisableFrozenAddress(itr->first); + m_frozenAddresses.erase(itr->first); + } + }) + ->show(); + } + else + { m_memoryDump->clear(); remove(EDIZON_DIR "/memdump1.dat"); + remove(EDIZON_DIR "/memdump1a.dat"); remove(EDIZON_DIR "/memdump2.dat"); remove(EDIZON_DIR "/memdump3.dat"); - m_searchType = SEARCH_TYPE_NONE; - m_searchMode = SEARCH_MODE_NONE; - m_searchRegion = SEARCH_REGION_NONE; - m_searchValue[0]._u64 = 0; - m_searchValue[1]._u64 = 0; + // m_searchType = SEARCH_TYPE_NONE; + // m_searchMode = SEARCH_MODE_NONE; + // m_searchRegion = SEARCH_REGION_NONE; + // m_searchValue[0]._u64 = 0; + // m_searchValue[1]._u64 = 0; m_menuLocation = CHEATS; } } + // start mod KEY_PLUS + // if (kdown & KEY_PLUS) { + // printf("%s\n","PLUS key pressed"); + // printf("%s\n",titleNameStr.c_str()); + // printf("%s\n",tidStr.c_str()); + // printf("%s\n",buildIDStr.c_str()); + // Gui::g_nextGui = GUI_MAIN; + // return; + // } + if (kdown & KEY_R) + { + if (m_searchValueFormat == FORMAT_HEX) + m_searchValueFormat = FORMAT_DEC; + else + m_searchValueFormat = FORMAT_HEX; + if (m_searchValueFormat == FORMAT_HEX) + printf("%s\n", "HEX"); + printf("%s\n", "R key pressed"); + } + if (kdown & KEY_L) //toggle bookmark view bookmark : (m_memoryDump1 != nullptr) + { + if (m_memoryDump1 == nullptr) + { + m_memoryDump1 = m_memoryDump; + m_memoryDump = m_memoryDumpBookmark; + m_addresslist_offset = 0; + //consider to remove later + if (m_searchType == SEARCH_TYPE_NONE) + m_searchType = SEARCH_TYPE_UNSIGNED_32BIT; // to make sure not blank + // end + // (new Snackbar("Switch to bookmark List!"))->show(); + printf("%s\n", "Bookmark"); + } + else + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + // (new Snackbar("Switch to Normal List!"))->show(); + } + printf("%s\n", "L key pressed"); + if (m_menuLocation == CANDIDATES) + m_selectedEntry = 0; + } + if (kdown & KEY_ZR) + { + m_addresslist_offset += 8; + if (m_addresslist_offset >= (m_memoryDump->size() / sizeof(u64))) + m_addresslist_offset -= 8; + if (m_selectedEntry + m_addresslist_offset + 1 > (m_memoryDump->size() / sizeof(u64))) + m_selectedEntry = (m_memoryDump->size() / sizeof(u64)) % 8 - 1; + // printf("%s\n", "ZR key pressed"); + } + + if (kdown & KEY_ZL) + { + if (m_addresslist_offset >= 8) + m_addresslist_offset -= 8; + // printf("%s\n", "ZL key pressed"); + } + + // End Mod + if (kdown & KEY_Y) + { + if (m_searchMenuLocation == SEARCH_NONE) + { + if (m_memoryDump1 != nullptr) + { // in bookmark mode + m_searchMenuLocation = SEARCH_POINTER; + // (new Snackbar("Searching pointer "))->show(); + } + else if (m_searchMode == SEARCH_MODE_NONE) + { + m_searchMenuLocation = SEARCH_MODE; + // m_selectedEntry = m_searchType == SEARCH_TYPE_NONE ? 0 : m_searchType; + } + else + m_searchMenuLocation = SEARCH_VALUE; + // auto toggle between stateA and stateB + if (m_searchMode == SEARCH_MODE_DIFFA) + { + m_searchMode = SEARCH_MODE_SAMEA; + m_selectedEntry = 1; + } + else if (m_searchMode == SEARCH_MODE_SAMEA) + { + m_searchMode = SEARCH_MODE_DIFFA; + m_selectedEntry = 1; + } + else + m_selectedEntry = 0; - if (kdown & KEY_Y) { - if (m_searchMenuLocation == SEARCH_NONE) { - m_searchMenuLocation = SEARCH_TYPE; - m_selectedEntry = m_searchType == SEARCH_TYPE_NONE ? 0 : m_searchType; cheatListOffset = 0; } + printf("%s\n", "Y key pressed"); + printf("%s\n", titleNameStr.c_str()); + printf("%s\n", tidStr.c_str()); + printf("%s\n", buildIDStr.c_str()); + //make sure not using bookmark + if (m_memoryDump1 != nullptr) + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + } + m_addresslist_offset = 0; + // end mod } } - else { + else + { if ((m_searchMenuLocation == SEARCH_TYPE && m_searchType == SEARCH_TYPE_NONE) || (m_searchMenuLocation == SEARCH_MODE && m_searchMode == SEARCH_MODE_NONE) || (m_searchMenuLocation == SEARCH_REGION && m_searchRegion == SEARCH_REGION_NONE) || - (m_searchMenuLocation == SEARCH_VALUE)) { - if (kdown & KEY_UP) { - switch (m_searchMenuLocation) { - case SEARCH_TYPE: [[fallthrough]] - case SEARCH_MODE: - if (m_selectedEntry % 2 == 1) - m_selectedEntry--; - break; - case SEARCH_REGION: - if (m_selectedEntry > 0) - m_selectedEntry--; - break; - case SEARCH_VALUE: - m_selectedEntry = 0; - break; - case SEARCH_NONE: break; + (m_searchMenuLocation == SEARCH_VALUE) || + (m_searchMenuLocation == SEARCH_editRAM)) + { + if (kdown & KEY_UP) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry % 2 == 1) + m_selectedEntry--; + break; + case SEARCH_REGION: + if (m_selectedEntry > 0) + m_selectedEntry--; + break; + case SEARCH_VALUE: + m_selectedEntry = 0; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need UP + if (m_selectedEntry > 4) + m_selectedEntry -= 5; + else + { + m_EditorBaseAddr -= 0x10; + } + + break; } } - if (kdown & KEY_DOWN) { - switch (m_searchMenuLocation) { - case SEARCH_TYPE: [[fallthrough]] - case SEARCH_MODE: - if ((m_selectedEntry + 1) < 10 && m_selectedEntry % 2 == 0) - m_selectedEntry++; - break; - case SEARCH_REGION: - if (m_selectedEntry < 3) - m_selectedEntry++; - break; - case SEARCH_VALUE: - if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) - m_selectedEntry = 1; - break; - case SEARCH_NONE: break; + if (kdown & KEY_DOWN) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if ((m_selectedEntry + 1) < 12 && m_selectedEntry % 2 == 0) + m_selectedEntry++; + break; + case SEARCH_REGION: + if (m_selectedEntry < 3) + m_selectedEntry++; + break; + case SEARCH_VALUE: + if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) + m_selectedEntry = 1; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need DOWN + if (m_selectedEntry < 35) + m_selectedEntry += 5; + else + { + m_EditorBaseAddr += 0x10; + } + + break; } } - if (kdown & KEY_LEFT) { - switch (m_searchMenuLocation) { - case SEARCH_TYPE: [[fallthrough]] - case SEARCH_MODE: - if (m_selectedEntry >= 2) - m_selectedEntry -= 2; - break; - case SEARCH_REGION: - break; - case SEARCH_VALUE: - break; - case SEARCH_NONE: break; + if (kdown & KEY_LEFT) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry >= 2) + m_selectedEntry -= 2; + break; + case SEARCH_REGION: + break; + case SEARCH_VALUE: + if (m_searchValueIndex == 1) + m_searchValueIndex--; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need LEFT + if (m_selectedEntry % 5 > 1) + m_selectedEntry--; + break; } } - if (kdown & KEY_RIGHT) { - switch (m_searchMenuLocation) { - case SEARCH_TYPE: [[fallthrough]] - case SEARCH_MODE: - if (m_selectedEntry <= 8) - m_selectedEntry += 2; - break; - case SEARCH_REGION: - break; - case SEARCH_VALUE: - break; - case SEARCH_NONE: break; + if (kdown & KEY_RIGHT) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry <= 9) + m_selectedEntry += 2; + break; + case SEARCH_REGION: + break; + case SEARCH_VALUE: + if (m_searchValueIndex == 0 && m_searchMode == SEARCH_MODE_RANGE) + m_searchValueIndex++; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need RIGHT + if (m_selectedEntry % 5 < 4) + m_selectedEntry++; + break; } } - if (kdown & KEY_A) { - if (m_searchMenuLocation == SEARCH_TYPE) + if (m_searchMenuLocation == SEARCH_editRAM) + { + if (kdown & KEY_PLUS) + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + printf("%s\n", "PLUS key pressed"); + } + if (kdown & KEY_ZR) + { + m_EditorBaseAddr += 0x80; + } + if (kdown & KEY_ZL) + { + m_EditorBaseAddr -= 0x80; + } + if (kdown & KEY_R) + { + m_addressmod++; + m_addressmod = m_addressmod % 4; + } + if (kdown & KEY_L) + { + m_addressmod--; + m_addressmod = m_addressmod % 4; + } + if (kdown & KEY_X) + { + if (m_searchValueFormat == FORMAT_DEC) + m_searchValueFormat = FORMAT_HEX; + else + m_searchValueFormat = FORMAT_DEC; + } + if (kdown & KEY_Y) // BM9 + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + std::stringstream ss; + ss << "0x" << std::uppercase << std::hex << address; + char input[16]; + if (Gui::requestKeyboardInput("Enter Address", "Enter Address to add to bookmark .", ss.str(), SwkbdType_QWERTY, input, 18)) + { + address = static_cast(std::stoul(input, nullptr, 16)); + + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + } + } + } + + // inc and dec search value + if ((kdown & KEY_ZR) && (m_searchMenuLocation == SEARCH_VALUE) && (m_searchType == SEARCH_TYPE_UNSIGNED_32BIT)) + { + m_searchValue[0]._u32++; + m_selectedEntry = 1; + }; + if ((kdown & KEY_ZL) && (m_searchMenuLocation == SEARCH_VALUE) && (m_searchType == SEARCH_TYPE_UNSIGNED_32BIT)) + { + m_searchValue[0]._u32--; + m_selectedEntry = 1; + }; + + if (kdown & KEY_A) + { + if (m_searchMenuLocation == SEARCH_editRAM) + { // BM3 + // EditRAM routine + // to update to use L and R to select type and display it on the top line + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + char input[16]; + char initialString[21]; + strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + if (Gui::requestKeyboardInput("Enter value", "Enter a value that should get written at this .", initialString, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, input, 18)) + { + if (m_searchValueFormat == FORMAT_HEX) + { + auto value = static_cast(std::stoul(input, nullptr, 16)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_32BIT) + { + auto value = static_cast(std::atof(input)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_64BIT) + { + auto value = std::atof(input); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType != SEARCH_TYPE_NONE) + { + auto value = std::atol(input); + m_debugger->writeMemory((void *)&value, dataTypeSizes[m_searchType], address); + } + } + } + else if (m_searchMenuLocation == SEARCH_TYPE) m_searchType = static_cast(m_selectedEntry); else if (m_searchMenuLocation == SEARCH_REGION) m_searchRegion = static_cast(m_selectedEntry); else if (m_searchMenuLocation == SEARCH_MODE) m_searchMode = static_cast(m_selectedEntry); - else if (m_searchMenuLocation == SEARCH_VALUE) { - if (m_selectedEntry == 0) { + else if (m_searchMenuLocation == SEARCH_VALUE) + { + if (m_selectedEntry == 0) + { + m_selectedEntry = 1; char str[0x21]; - Gui::requestKeyboardInput("Enter the value you want to search for", "Based on your previously chosen options, EdiZon will expect different input here.", "", m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); - - if (std::string(str) == "") return; - - if (m_searchValueFormat == FORMAT_HEX) { - m_searchValue[0]._u64 = static_cast(std::stoul(str, nullptr, 16)); - } else { - switch(m_searchType) { - case SEARCH_TYPE_UNSIGNED_8BIT: - m_searchValue[0]._u8 = static_cast(std::stoul(str, nullptr, 0)); - break; - case SEARCH_TYPE_UNSIGNED_16BIT: - m_searchValue[0]._u16 = static_cast(std::stoul(str, nullptr, 0)); - break; - case SEARCH_TYPE_UNSIGNED_32BIT: - m_searchValue[0]._u32 = static_cast(std::stoul(str, nullptr, 0)); - break; - case SEARCH_TYPE_UNSIGNED_64BIT: - m_searchValue[0]._u64 = static_cast(std::stoul(str, nullptr, 0)); - break; - case SEARCH_TYPE_SIGNED_8BIT: - m_searchValue[0]._s8 = static_cast(std::stol(str, nullptr, 0)); - break; - case SEARCH_TYPE_SIGNED_16BIT: - m_searchValue[0]._s16 = static_cast(std::stol(str, nullptr, 0)); - break; - case SEARCH_TYPE_SIGNED_32BIT: - m_searchValue[0]._s32 = static_cast(std::stol(str, nullptr, 0)); - break; - case SEARCH_TYPE_SIGNED_64BIT: - m_searchValue[0]._s64 = static_cast(std::stol(str, nullptr, 0)); - break; - case SEARCH_TYPE_FLOAT_32BIT: - m_searchValue[0]._f32 = static_cast(std::stof(str)); - break; - case SEARCH_TYPE_FLOAT_64BIT: - m_searchValue[0]._f64 = static_cast(std::stod(str)); - break; - case SEARCH_TYPE_POINTER: - m_searchValue[0]._u64 = static_cast(std::stol(str)); - break; - case SEARCH_TYPE_NONE: break; + // Start Mod keep previous value + // End Mod + if ((m_searchValue[m_searchValueIndex]._u32 > 10) || (m_searchValueFormat == FORMAT_HEX)) + { + Gui::requestKeyboardInput("Enter the value you want to search for", "Based on your previously chosen options, EdiZon will expect different input here.", _getValueDisplayString(m_searchValue[m_searchValueIndex], m_searchType), m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); + } + else + { + Gui::requestKeyboardInput("Enter the value you want to search for", "Based on your previously chosen options, EdiZon will expect different input here.", "", m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); + } + if (std::string(str) == "") + return; + + if (m_searchValueFormat == FORMAT_HEX) + { + m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stoul(str, nullptr, 16)); + } + else + { + switch (m_searchType) + { + case SEARCH_TYPE_UNSIGNED_8BIT: + m_searchValue[m_searchValueIndex]._u8 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_16BIT: + m_searchValue[m_searchValueIndex]._u16 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_32BIT: + m_searchValue[m_searchValueIndex]._u32 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_64BIT: + m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_8BIT: + m_searchValue[m_searchValueIndex]._s8 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_16BIT: + m_searchValue[m_searchValueIndex]._s16 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_32BIT: + m_searchValue[m_searchValueIndex]._s32 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_64BIT: + m_searchValue[m_searchValueIndex]._s64 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_FLOAT_32BIT: + m_searchValue[m_searchValueIndex]._f32 = static_cast(std::stof(str)); + break; + case SEARCH_TYPE_FLOAT_64BIT: + m_searchValue[m_searchValueIndex]._f64 = static_cast(std::stod(str)); + break; + case SEARCH_TYPE_POINTER: + m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stol(str)); + break; + case SEARCH_TYPE_NONE: + break; } } - } else if (m_selectedEntry == 1) { + } + else if (m_selectedEntry == 1) + { (new MessageBox("Traversing title memory.\n \nThis may take a while...", MessageBox::NONE))->show(); requestDraw(); - + overclockSystem(true); - if (m_searchMode == SEARCH_MODE_SAME || m_searchMode == SEARCH_MODE_DIFF || m_searchMode == SEARCH_MODE_INC || m_searchMode == SEARCH_MODE_DEC) { - if (m_memoryDump->size() == 0) { + if (m_searchMode == SEARCH_MODE_POINTER) + m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; + + if (m_searchMode == SEARCH_MODE_SAME || m_searchMode == SEARCH_MODE_DIFF || m_searchMode == SEARCH_MODE_INC || m_searchMode == SEARCH_MODE_DEC || m_searchMode == SEARCH_MODE_DIFFA || m_searchMode == SEARCH_MODE_SAMEA) + { + if (m_memoryDump->size() == 0) + { delete m_memoryDump; GuiCheats::searchMemoryValuesPrimary(m_debugger, m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); - } else if (m_memoryDump->getDumpInfo().dumpType == DumpType::DATA) { + printf("%s%lx\n", "Dump Size = ", m_memoryDump->size()); + } + else if (m_memoryDump->getDumpInfo().dumpType == DumpType::DATA) + { + printf("%s%lx\n", "Dump Size = ", m_memoryDump->size()); GuiCheats::searchMemoryValuesSecondary(m_debugger, m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); delete m_memoryDump; - remove(EDIZON_DIR "/memdump1.dat"); rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); - + printf("%s\n", "renaming"); m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); - } else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { - GuiCheats::searchMemoryValuesTertiary(m_debugger, m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); } - } else { - if (m_memoryDump->size() == 0) { + else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + GuiCheats::searchMemoryValuesTertiary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + delete m_memoryDump; + remove(EDIZON_DIR "/memdump1.dat"); + remove(EDIZON_DIR "/memdump1a.dat"); + rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); + remove(EDIZON_DIR "/datadump2.dat"); + rename(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); + // rename B to A + remove(EDIZON_DIR "/datadumpA.dat"); + rename(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat"); + remove(EDIZON_DIR "/datadumpB.dat"); + rename(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + } + } + else + { + if (m_memoryDump->size() == 0) + { delete m_memoryDump; GuiCheats::searchMemoryAddressesPrimary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); - } else { + } + else + { + m_nothingchanged = false; GuiCheats::searchMemoryAddressesSecondary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, &m_memoryDump); + if (m_nothingchanged == false) + { + remove(EDIZON_DIR "/memdump1a.dat"); // remove old helper + rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); // rename new helper to current helper + } } } @@ -870,14 +1746,16 @@ void GuiCheats::onInput(u32 kdown) { Gui::g_currMessageBox->hide(); m_searchMenuLocation = SEARCH_NONE; - m_searchMode = SEARCH_MODE_NONE; + // m_searchMode = SEARCH_MODE_NONE; } } } } - if (kdown & KEY_X) { - if (m_searchMenuLocation == SEARCH_VALUE) { + if (kdown & KEY_X) + { + if (m_searchMenuLocation == SEARCH_VALUE) + { if (m_searchValueFormat == FORMAT_DEC) m_searchValueFormat = FORMAT_HEX; else @@ -885,60 +1763,71 @@ void GuiCheats::onInput(u32 kdown) { } } - if (kdown & KEY_L) { - if (m_searchMenuLocation == SEARCH_VALUE) { + if (kdown & KEY_L) + { + if (m_searchMenuLocation == SEARCH_VALUE) + { m_searchMenuLocation = SEARCH_REGION; m_selectedEntry = m_searchRegion == SEARCH_REGION_NONE ? 0 : static_cast(m_searchRegion); } - else if (m_searchMenuLocation == SEARCH_REGION) { + else if (m_searchMenuLocation == SEARCH_REGION) + { m_searchMenuLocation = SEARCH_MODE; m_selectedEntry = m_searchMode == SEARCH_MODE_NONE ? 0 : static_cast(m_searchMode); } - else if (m_searchMenuLocation == SEARCH_MODE) { + else if (m_searchMenuLocation == SEARCH_MODE) + { m_searchMenuLocation = SEARCH_TYPE; m_selectedEntry = m_searchType == SEARCH_TYPE_NONE ? 0 : static_cast(m_searchType); } } - if (kdown & KEY_R) { - if (m_searchMenuLocation == SEARCH_TYPE) { + if (kdown & KEY_R) + { + if (m_searchMenuLocation == SEARCH_TYPE) + { m_searchMenuLocation = SEARCH_MODE; m_selectedEntry = m_searchMode == SEARCH_MODE_NONE ? 0 : static_cast(m_searchMode); } - else if (m_searchMenuLocation == SEARCH_MODE) { + else if (m_searchMenuLocation == SEARCH_MODE) + { m_searchMenuLocation = SEARCH_REGION; m_selectedEntry = m_searchRegion == SEARCH_REGION_NONE ? 0 : static_cast(m_searchRegion); } - else if (m_searchMenuLocation == SEARCH_REGION) { + else if (m_searchMenuLocation == SEARCH_REGION) + { m_searchMenuLocation = SEARCH_VALUE; m_selectedEntry = 0; + m_searchValueIndex = 0; } } - } } -void GuiCheats::onTouch(touchPosition &touch) { - +void GuiCheats::onTouch(touchPosition &touch) +{ } -void GuiCheats::onGesture(touchPosition startPosition, touchPosition endPosition, bool finish) { - +void GuiCheats::onGesture(touchPosition startPosition, touchPosition endPosition, bool finish) +{ } - -static bool _isAddressFrozen(uintptr_t address) { +static bool _isAddressFrozen(uintptr_t address) +{ DmntFrozenAddressEntry *es; u64 Cnt = 0; bool frozen = false; dmntchtGetFrozenAddressCount(&Cnt); - if (Cnt != 0) { + if (Cnt != 0) + { es = new DmntFrozenAddressEntry[Cnt]; dmntchtGetFrozenAddresses(es, Cnt, 0, nullptr); - for (u64 i = 0; i < Cnt; i++) { - if (es[i].address == address) { + for (u64 i = 0; i < Cnt; i++) + { + if (es[i].address == address) + { frozen = true; break; } @@ -948,13 +1837,21 @@ static bool _isAddressFrozen(uintptr_t address) { return frozen; } -static std::string _getAddressDisplayString(u64 address, Debugger *debugger, searchType_t searchType) { +static std::string _getAddressDisplayString(u64 address, Debugger *debugger, searchType_t searchType) +{ std::stringstream ss; searchValue_t searchValue; searchValue._u64 = debugger->peekMemory(address); - - switch(searchType) { + // start mod for address content display + if (m_searchValueFormat == FORMAT_HEX) + ss << "0x" << std::uppercase << std::hex << searchValue._u64; + else + { + + // end mod + switch (searchType) + { case SEARCH_TYPE_UNSIGNED_8BIT: ss << std::dec << static_cast(searchValue._u8); break; @@ -988,16 +1885,26 @@ static std::string _getAddressDisplayString(u64 address, Debugger *debugger, sea case SEARCH_TYPE_POINTER: ss << std::dec << searchValue._u64; break; - case SEARCH_TYPE_NONE: break; + case SEARCH_TYPE_NONE: + break; + } } return ss.str(); } -static std::string _getValueDisplayString(searchValue_t searchValue, searchType_t searchType) { +static std::string _getValueDisplayString(searchValue_t searchValue, searchType_t searchType) +{ std::stringstream ss; - switch(searchType) { + if (m_searchValueFormat == FORMAT_HEX) + { + ss << "0x" << std::uppercase << std::hex << searchValue._u64; + } + else + { + switch (searchType) + { case SEARCH_TYPE_UNSIGNED_8BIT: ss << std::dec << static_cast(searchValue._u8); break; @@ -1033,27 +1940,51 @@ static std::string _getValueDisplayString(searchValue_t searchValue, searchType_ case SEARCH_TYPE_POINTER: ss << std::dec << searchValue._u64; break; - case SEARCH_TYPE_NONE: break; + case SEARCH_TYPE_NONE: + break; + } } return ss.str(); } - -void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) { +// read +void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ (*displayDump) = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, true); (*displayDump)->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); (*displayDump)->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory + MemoryDump *newdataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); + MemoryDump *newstringDump = new MemoryDump(EDIZON_DIR "/stringdump.dat", DumpType::DATA, true); // to del when not needed + + helperinfo_t helperinfo; + helperinfo.count = 0; + bool ledOn = false; - for (MemoryInfo meminfo : memInfos) { + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time primary search", unixTime1); + // printf("main %lx main end %lx heap %lx heap end %lx \n",m_mainBaseAddr, m_mainBaseAddr+m_mainSize, m_heapBaseAddr, m_heapBaseAddr+m_heapSize); + for (MemoryInfo meminfo : memInfos) + { + + // printf("%s%p", "meminfo.addr, ", meminfo.addr); + // printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); + // printf("%s%p", ", meminfo.size, ", meminfo.size); + // printf("%s%lx", ", meminfo.type, ", meminfo.type); + // printf("%s%lx", ", meminfo.attr, ", meminfo.attr); + // printf("%s%lx", ", meminfo.perm, ", meminfo.perm); + // printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); + // printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) - continue; + continue; else if (searchRegion == SEARCH_REGION_MAIN && - (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && - (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) continue; @@ -1062,74 +1993,148 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s ledOn = !ledOn; u64 offset = 0; - u64 bufferSize = 0x10000; + u64 bufferSize = MAX_BUFFER_SIZE; // consider to increase from 10k to 1M (not a big problem) u8 *buffer = new u8[bufferSize]; - while (offset < meminfo.size) { - + while (offset < meminfo.size) + { + if (meminfo.size - offset < bufferSize) bufferSize = meminfo.size - offset; debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); - searchValue_t realValue = { 0 }; - for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) { + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { u64 address = meminfo.addr + offset + i; memset(&realValue, 0, 8); memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); - switch(searchMode) { - case SEARCH_MODE_EQ: - if (realValue._s64 == searchValue1._s64) { - (*displayDump)->addData((u8*)&address, sizeof(u64)); + switch (searchMode) + { + case SEARCH_MODE_EQ: + if (realValue._s64 == searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_NEQ: + if (realValue._s64 != searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_GT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 > searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; } - break; - case SEARCH_MODE_NEQ: - if (realValue._s64 != searchValue1._s64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); - break; - case SEARCH_MODE_GT: - if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { - if (realValue._s64 > searchValue1._s64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); - } else { - if (realValue._u64 > searchValue1._u64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); + } + else + { + if (realValue._u64 > searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; } - break; - case SEARCH_MODE_GTE: - if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { - if (realValue._s64 >= searchValue1._s64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); - } else { - if (realValue._u64 >= searchValue1._u64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); + } + break; + case SEARCH_MODE_DIFFA: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 >= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; } - break; - case SEARCH_MODE_LT: - if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { - if (realValue._s64 < searchValue1._s64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); - } else { - if (realValue._u64 < searchValue1._u64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); + } + else + { + if (realValue._u64 >= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; } - break; - case SEARCH_MODE_LTE: - if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { - if (realValue._s64 <= searchValue1._s64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); - } else { - if (realValue._u64 <= searchValue1._u64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); + } + break; + case SEARCH_MODE_LT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 < searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 < searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_SAMEA: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 <= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 <= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; } - break; - case SEARCH_MODE_RANGE: - if (realValue._s64 >= searchValue1._s64 && realValue._s64 <= searchValue2._s64) - (*displayDump)->addData((u8*)&address, sizeof(u64)); - break; + } + break; + case SEARCH_MODE_RANGE: + if (realValue._s64 >= searchValue1._s64 && realValue._s64 <= searchValue2._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&realValue, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainBaseAddr + m_mainSize))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapBaseAddr + m_heapSize)))) + { + if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) + break; + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&realValue, sizeof(u64)); + helperinfo.count++; + // printf("%lx,%lx\n",address,realValue); + char st[25]; // replace the printf + snprintf(st, 25, "'%lx,'%lx\n", address, realValue); // + newstringDump->addData((u8 *)&st, sizeof(st)); // + } + break; } } + // helper info write must be before inc + if (helperinfo.count != 0) + { + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + // printf("address 0x%lx ", helperinfo.address); + // printf("size %ld ", helperinfo.size); + // printf("count %ld type %d \n ", helperinfo.count, meminfo.type); + helperinfo.count = 0; + } // must be after write + offset += bufferSize; } @@ -1138,128 +2143,348 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s setLedState(false); + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + (*displayDump)->flushBuffer(); + newdataDump->flushBuffer(); + helperDump->flushBuffer(); + delete helperDump; + delete newdataDump; + newstringDump->flushBuffer(); // temp + delete newstringDump; // } +// -void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, MemoryDump **displayDump) { +void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, MemoryDump **displayDump) +{ MemoryDump *newDump = new MemoryDump(EDIZON_DIR "/memdump2.dat", DumpType::ADDR, true); bool ledOn = false; + //begin + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time Secondary search", unixTime1); + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // this is for file access going for 1M + u8 *buffer = new u8[bufferSize]; + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, false); // has address, size, count for fetching buffer from memory + MemoryDump *newhelperDump = new MemoryDump(EDIZON_DIR "/memdump3a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory + MemoryDump *newdataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); + MemoryDump *debugdump1 = new MemoryDump(EDIZON_DIR "/debugdump1.dat", DumpType::HELPER, true); + if (helperDump->size() == 0) + { + (new Snackbar("Helper file not found !"))->show(); + return; + } + else + { + // helper integrity check + printf("start helper integrity check address secondary \n"); + u32 helpercount = 0; + helperinfo_t helperinfo; + for (u64 i = 0; i < helperDump->size(); i += sizeof(helperinfo)) + { + helperDump->getData(i, &helperinfo, sizeof(helperinfo)); + helpercount += helperinfo.count; + } + if (helpercount != (*displayDump)->size() / sizeof(u64)) + { + printf("Integrity problem with helper file helpercount = %d memdumpsize = %d \n", helpercount, (*displayDump)->size() / sizeof(u64)); + (new Snackbar("Helper integrity check failed !"))->show(); + return; + } + printf("end helper integrity check address secondary \n"); + // end helper integrity check - for (size_t i = 0; i < ((*displayDump)->size() / sizeof(u64)); i++) { - searchValue_t value = { 0 }; - u64 address = 0; - (*displayDump)->getData(i * sizeof(u64), &address, sizeof(u64)); - - debugger->readMemory(&value, dataTypeSizes[searchType], address); + std::stringstream Message; + Message << "Traversing title memory.\n \nThis may take a while... secondary search\nTime " << (unixTime1 - time(NULL)) << " total " << (*displayDump)->size(); + (new MessageBox(Message.str(), MessageBox::NONE))->show(); + requestDraw(); + } - if (i % 50 == 0) { - setLedState(ledOn); - ledOn = !ledOn; - } + u8 *ram_buffer = new u8[bufferSize]; + u64 helper_offset = 0; + helperinfo_t helperinfo; + helperinfo_t newhelperinfo; + newhelperinfo.count = 0; + + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); // helper_offset+=sizeof(helperinfo) + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + // helper init end + while (offset < (*displayDump)->size()) + { + if ((*displayDump)->size() - offset < bufferSize) + bufferSize = (*displayDump)->size() - offset; + (*displayDump)->getData(offset, buffer, bufferSize); // BM4 + + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + if (helperinfo.count == 0) + { + if (newhelperinfo.count != 0) + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + // printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + // printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + // printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + helper_offset += sizeof(helperinfo); + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + } + searchValue_t value = {0}; + searchValue_t testing = {0}; // temp + u64 address = 0; + + address = *reinterpret_cast(&buffer[i]); //(*displayDump)->getData(i * sizeof(u64), &address, sizeof(u64)); + + memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); // extrat from buffer instead of making call + helperinfo.count--; // each fetch dec + // testing = value; // temp + // debugger->readMemory(&value, dataTypeSizes[searchType], address); + // if (testing._u64 != value._u64) + // { + // printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + // printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + // printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + // printf("%s%lx\n", "address ", address); + // printf("%s%lx\n", "testing._u64 ", testing._u64); + // printf("%s%lx\n", "value ", value); + // printf("%s%lx\n", " address - helperinfo.address ", address - helperinfo.address); + // printf("%s%lx\n", " * (ram_buffer + address - helperinfo.address) ", *(ram_buffer + address - helperinfo.address)); + // printf("%s%lx\n", " * (&ram_buffer[ address - helperinfo.address]) ", *(&ram_buffer[address - helperinfo.address])); + // printf("%s%lx\n", " (ram_buffer + address - helperinfo.address) ", (ram_buffer + address - helperinfo.address)); + // printf("%s%lx\n", " (&ram_buffer[ address - helperinfo.address]) ", (&ram_buffer[address - helperinfo.address])); + // printf("%s%lx\n", " helperinfo.size - address + helperinfo.address ", helperinfo.size - address + helperinfo.address); + // // debugdump1->addData((u8 *)&ram_buffer, helperinfo.size); + // // debugger->readMemory(ram_buffer, 0x50, address); + // // debugdump2->addData((u8 *)&ram_buffer, 0x50); + // // + // // delete debugdump2; + // } + + if (i % 50000 == 0) + { + setLedState(ledOn); + ledOn = !ledOn; + } - switch(searchMode) { + switch (searchMode) + { case SEARCH_MODE_EQ: if (value._s64 == searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_NEQ: if (value._s64 != searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_GT: if (value._s64 > searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; - case SEARCH_MODE_GTE: + case SEARCH_MODE_DIFFA: if (value._s64 >= searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_LT: if (value._s64 < searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; - case SEARCH_MODE_LTE: + case SEARCH_MODE_SAMEA: if (value._s64 <= searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_RANGE: if (value._s64 >= searchValue1._s64 && value._s64 <= searchValue2._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); // add here + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize + if ((value._s64 >= m_mainBaseAddr && value._s64 <= (m_mainBaseAddr + m_mainSize)) || (value._s64 >= m_heapBaseAddr && value._s64 <= (m_heapBaseAddr + m_heapSize))) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_SAME: if (value._s64 == searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_DIFF: if (value._s64 != searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_INC: if (value._s64 > searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_DEC: if (value._s64 < searchValue1._s64) - newDump->addData((u8*)&address, sizeof(u64)); + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_NONE: break; - case SEARCH_MODE_NONE: break; + } } + printf("%d of %d done \n", offset, (*displayDump)->size()); // maybe consider message box this info + offset += bufferSize; } - if (newDump->size() > 0) { + if (newhelperinfo.count != 0) // take care of the last one + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + // printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + // printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + // printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + //end + newDump->flushBuffer(); + newhelperDump->flushBuffer(); + newdataDump->flushBuffer(); + + if (newDump->size() > 0) + { + // delete m_memoryDump; + // remove(EDIZON_DIR "/memdump1.dat"); + // rename(EDIZON_DIR "/memdump2.dat", EDIZON_DIR "/memdump2.dat"); (*displayDump)->clear(); (*displayDump)->setSearchParams(searchType, searchMode, (*displayDump)->getDumpInfo().searchRegion, searchValue1, searchValue2); (*displayDump)->setDumpType(DumpType::ADDR); - for (size_t i = 0; i < (newDump->size() / sizeof(u64)); i++) { - u64 address = 0; - - newDump->getData(i * sizeof(u64), &address, sizeof(u64)); - (*displayDump)->addData((u8*)&address, sizeof(u64)); - } + // begin copy + offset = 0; + bufferSize = MAX_BUFFER_SIZE; //0x1000000; // match what was created before + printf("%s%lx\n", "bufferSize ", bufferSize); // printf + while (offset < newDump->size()) + { + if (newDump->size() - offset < bufferSize) + bufferSize = newDump->size() - offset; + newDump->getData(offset, buffer, bufferSize); + (*displayDump)->addData(buffer, bufferSize); + offset += bufferSize; + } + // end copy - (*displayDump)->flushBuffer(); - } else { + (*displayDump)->flushBuffer(); + } + else + { (new Snackbar("None of values changed to the entered one!"))->show(); + m_nothingchanged = true; } setLedState(false); - delete newDump; + delete newhelperDump; + delete helperDump; + delete debugdump1; + delete newdataDump; + delete[] buffer; + delete[] ram_buffer; remove(EDIZON_DIR "/memdump2.dat"); + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time secondary search ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); } -void GuiCheats::searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) { +/////////////////////////////////////////////// +// read +void GuiCheats::searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ bool ledOn = false; searchValue_t zeroValue; zeroValue._u64 = 0; - + // printf("%s\n", "searchMemoryValuesPrimary"); + // printf("%s\n", titleNameStr.c_str()); + // printf("%s\n", tidStr.c_str()); + // printf("%s\n", buildIDStr.c_str()); + // printf("%s%lx\n", "m_addressSpaceBaseAddr ", m_addressSpaceBaseAddr); + // printf("%s%lx\n", "m_heapBaseAddr ", m_heapBaseAddr); + // printf("%s%lx\n", "m_mainBaseAddr ", m_mainBaseAddr); + // printf("%s%lx\n", "m_heapSize ", m_heapSize); + // printf("%s%lx\n", "m_mainSize ", m_mainSize); + // printf("%s%X1\n", "searchType ", searchType); + // printf("%s%X1\n", "searchMode ", searchMode); + // printf("%s%X1\n", "searchRegion ", searchRegion); + (new Snackbar("Dumping memory"))->show(); (*displayDump) = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::DATA, true); (*displayDump)->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); - (*displayDump)->setSearchParams(searchType, searchMode, searchRegion, { 0 }, { 0 }); + (*displayDump)->setSearchParams(searchType, searchMode, searchRegion, {0}, {0}); + // start time + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time ", unixTime1); - for (MemoryInfo meminfo : memInfos) { + for (MemoryInfo meminfo : memInfos) + { if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) - continue; + continue; else if (searchRegion == SEARCH_REGION_MAIN && - (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && - (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) continue; setLedState(ledOn); ledOn = !ledOn; + // printf("%s%lx\n", "meminfo.size ", meminfo.size); + // printf("%s%lx\n", "meminfo.addr ", meminfo.addr); + // printf("%s%lx\n", "meminfo.type ", meminfo.type); + // printf("%s%lx\n", "meminfo.perm ", meminfo.perm); u64 offset = 0; - u64 bufferSize = 0x40000; + u64 bufferSize = MAX_BUFFER_SIZE; // hack increase from 40K to 1M u8 *buffer = new u8[bufferSize]; - while (offset < meminfo.size) { - + while (offset < meminfo.size) + { + if (meminfo.size - offset < bufferSize) bufferSize = meminfo.size - offset; @@ -1273,126 +2498,920 @@ void GuiCheats::searchMemoryValuesPrimary(Debugger *debugger, searchType_t searc } setLedState(false); + (*displayDump)->flushBuffer(); + // end time + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); } -void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) { +//////////////////////////////////////////////////// +void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ bool ledOn = false; + searchValue_t oldValue = {0}; // check if needed + searchValue_t newValue = {0}; - MemoryDump *newMemDump = new MemoryDump(EDIZON_DIR "/memdump2.dat", DumpType::DATA, true); + MemoryDump *newMemDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); // Store Current value MemoryDump *addrDump = new MemoryDump(EDIZON_DIR "/memdump3.dat", DumpType::ADDR, true); - u64 dumpOffset = 0; + addrDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + addrDump->setSearchParams(searchType, searchMode, searchRegion, {0}, {0}); + + // work in progress + // if (searchMode == SEARCH_MODE_DIFFA) + MemoryDump *valueDumpA = new MemoryDump(EDIZON_DIR "/datadumpA.dat", DumpType::DATA, true); // file to put A + MemoryDump *valueDumpB = new MemoryDump(EDIZON_DIR "/datadumpB.dat", DumpType::DATA, true); // file to put B + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) + { + (new Snackbar("Creating state B"))->show(); + } + // end work in progress - for (MemoryInfo meminfo : memInfos) { + u64 dumpoffset = 0; // file offset need to be for whole session + + // start time + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time second search ", unixTime1); + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::ADDR, true); // has address, size, count for fetching buffer from memory + helperinfo_t helperinfo; + + for (MemoryInfo meminfo : memInfos) + { if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) - continue; + continue; else if (searchRegion == SEARCH_REGION_MAIN && - (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && - (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) continue; setLedState(ledOn); ledOn = !ledOn; - + printf("%s%lx\n", "meminfo.size ", meminfo.size); + printf("%s%lx\n", "meminfo.addr ", meminfo.addr); + printf("%s%lx\n", "meminfo.type ", meminfo.type); + printf("%s%lx\n", "meminfo.perm ", meminfo.perm); u64 offset = 0; - u64 bufferSize = 0x40000; + u64 bufferSize = MAX_BUFFER_SIZE; // hack increase from 40K to 1M u8 *buffer = new u8[bufferSize]; - while (offset < meminfo.size) { - + u8 *filebuffer = new u8[bufferSize]; //added filebuffer matching memory buffer memory buffer could be smaller, let's see if that is too much + u64 addr = meminfo.addr; + + // start count + helperinfo.count = 0; + + while (offset < meminfo.size) + { + setLedState(ledOn); + ledOn = !ledOn; + if (meminfo.size - offset < bufferSize) bufferSize = meminfo.size - offset; debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); - newMemDump->addData(buffer, bufferSize); + // printf("%s\n", "readmemory OK "); + // printf("%s%lx\n", "dumpoffset ", dumpoffset); + // printf("%s%lx\n", "bufferSize ", bufferSize); + // printf("%s%lx\n", "displayDump ", displayDump); + // print_details = true; + (*displayDump)->getData(dumpoffset, filebuffer, bufferSize); + // print_details = false; + // printf("%s\n", "readdata OK "); + + for (u64 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + switch (dataTypeSizes[searchType]) + { + case 1: + newValue._u8 = *reinterpret_cast(&buffer[i]); + oldValue._u8 = *reinterpret_cast(&filebuffer[i]); + case 2: + newValue._u16 = *reinterpret_cast(&buffer[i]); + oldValue._u16 = *reinterpret_cast(&filebuffer[i]); + case 4: + newValue._u32 = *reinterpret_cast(&buffer[i]); + oldValue._u32 = *reinterpret_cast(&filebuffer[i]); + case 8: + newValue._u64 = *reinterpret_cast(&buffer[i]); + oldValue._u64 = *reinterpret_cast(&filebuffer[i]); + } + switch (searchMode) + { + case SEARCH_MODE_SAME: + if (newValue._u64 == oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_DIFF: + if (newValue._u64 != oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_SAMEA: + case SEARCH_MODE_DIFFA: + if (newValue._u64 != oldValue._u64) + { + // (new Snackbar("Creating state A (previsou) and state B (current) "))->show(); + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); // Keep compatibility with other mode + valueDumpA->addData((u8 *)&oldValue, sizeof(u64)); // save state A + valueDumpB->addData((u8 *)&newValue, sizeof(u64)); // save state B + helperinfo.count++; + } + break; + case SEARCH_MODE_INC: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (newValue._s64 > oldValue._s64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (newValue._u64 > oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_DEC: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (newValue._s64 < oldValue._s64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (newValue._u64 < oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + break; + } + addr += dataTypeSizes[searchType]; + } + // end compare + // helper info write must be before inc + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + if (helperinfo.count != 0) + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + helperinfo.count = 0; // must be after write + // end offset += bufferSize; + dumpoffset += bufferSize; + + printf("%s%lx\n", "offset ", offset); + printf("%s%lx\n", "dumpoffset ", dumpoffset); } delete[] buffer; + delete[] filebuffer; } - + newMemDump->flushBuffer(); + addrDump->flushBuffer(); + helperDump->flushBuffer(); + valueDumpA->flushBuffer(); + valueDumpB->flushBuffer(); + delete newMemDump; // this should close these two files + delete addrDump; + delete helperDump; + delete valueDumpA; + delete valueDumpB; + + // old maybe useless stuff to delete later // Bigger buffers - for (u64 addr = 0; addr < std::min((*displayDump)->size(), newMemDump->size()); addr += dataTypeSizes[searchType]) { - searchValue_t oldValue = { 0 }; - searchValue_t newValue = { 0 }; - (*displayDump)->getData(addr, &oldValue, dataTypeSizes[searchType]); - newMemDump->getData(addr, &newValue, dataTypeSizes[searchType]); + // for (u64 addr = 0; addr < std::min((*displayDump)->size(), newMemDump->size()); addr += dataTypeSizes[searchType]) + // { + // searchValue_t oldValue = {0}; + // searchValue_t newValue = {0}; + // (*displayDump)->getData(addr, &oldValue, dataTypeSizes[searchType]); + // newMemDump->getData(addr, &newValue, dataTypeSizes[searchType]); + // } - if (addr % 500 == 0) { - setLedState(ledOn); - ledOn = !ledOn; + setLedState(false); + + // end time second search + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time second search", unixTime2); + printf("%s%ld\n", "Total Time in decimal seconds ", unixTime2 - unixTime1); +} + +void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ + MemoryDump *oldvalueDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); //file with previous value + MemoryDump *newvalueDump = new MemoryDump(EDIZON_DIR "/datadump4.dat", DumpType::DATA, true); // file to put new value + + //work in progress + // if (searchMode == SEARCH_MODE_SAMEA) + MemoryDump *valueDumpA = new MemoryDump(EDIZON_DIR "/datadumpA.dat", DumpType::DATA, false); // file to get A + MemoryDump *newvalueDumpA = new MemoryDump(EDIZON_DIR "/datadumpAa.dat", DumpType::DATA, true); // file to put new A + MemoryDump *valueDumpB = new MemoryDump(EDIZON_DIR "/datadumpB.dat", DumpType::DATA, false); // file to get B + MemoryDump *newvalueDumpB = new MemoryDump(EDIZON_DIR "/datadumpBa.dat", DumpType::DATA, true); // file to put new B + bool no_existing_dump = false; + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) + { + if (valueDumpA->size() == oldvalueDump->size()) + { + delete oldvalueDump; + oldvalueDump = valueDumpA; + } + else + { + // delete valueDumpB; + // valueDumpB = oldvalueDump; + no_existing_dump = true; + printf("no existing dump \n"); + if (searchMode == SEARCH_MODE_SAMEA) + return; + } + } + + // create a A and B file valueDumpA and newvalueDumpA ?? to keep track of A B; + //end work in progress + MemoryDump *newDump = new MemoryDump(EDIZON_DIR "/memdump3.dat", DumpType::ADDR, true); //file to put new candidates + newDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + newDump->setSearchParams(searchType, searchMode, searchRegion, {0}, {0}); + bool ledOn = false; + //begin + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time Tertiary search", unixTime1); + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // this is for file access going for 1M + bool have_oldvalue = false; + u8 *buffer = new u8[bufferSize]; + u8 *valuebuffer = new u8[bufferSize]; + u8 *valueBbuffer = new u8[bufferSize]; + + // BM7 + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::ADDR, false); // has address, size, count for fetching buffer from memory + MemoryDump *newhelperDump = new MemoryDump(EDIZON_DIR "/memdump3a.dat", DumpType::ADDR, true); // has address, size, count for fetching buffer from memory + if (helperDump->size() == 0) + { + (new Snackbar("Helper file not found !"))->show(); + return; + } + + // helper integrity check + if (true) + { + printf("start helper integrity check value tertiary \n"); + u32 helpercount = 0; + helperinfo_t helperinfo; + for (u64 i = 0; i < helperDump->size(); i += sizeof(helperinfo)) + { + helperDump->getData(i, &helperinfo, sizeof(helperinfo)); + helpercount += helperinfo.count; } + if (helpercount != (*displayDump)->size() / sizeof(u64)) + { + printf("Integrity problem with helper file helpercount = %d memdumpsize = %d \n", helpercount, (*displayDump)->size() / sizeof(u64)); + (new Snackbar("Helper integrity check failed !"))->show(); + return; + } + printf("end helper integrity check value tertiary \n"); + } + // end helper integrity check + + u8 *ram_buffer = new u8[bufferSize]; + u64 helper_offset = 0; + helperinfo_t helperinfo; + helperinfo_t newhelperinfo; + newhelperinfo.count = 0; + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); // helper_offset+=sizeof(helperinfo) + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + printf("%s%lx\n", "helper_offset ", helper_offset); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + // helper init end + + if (oldvalueDump->size() == (*displayDump)->size()) + { + printf("%s\n", "Found old value"); + have_oldvalue = true; + } + else + { + (new Snackbar("previous value file not found !"))->show(); + return; /* code */ + } + + searchValue_t value = {0}; + searchValue_t oldvalue = {0}; + searchValue_t Bvalue = {0}; + + u64 address = 0; + while (offset < (*displayDump)->size()) + { + + if ((*displayDump)->size() - offset < bufferSize) + bufferSize = (*displayDump)->size() - offset; + + (*displayDump)->getData(offset, buffer, bufferSize); // BM6 + if (have_oldvalue) + oldvalueDump->getData(offset, valuebuffer, bufferSize); + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) //read in data A and B + { + if (no_existing_dump == false) + valueDumpB->getData(offset, valueBbuffer, bufferSize); + } + + printf("%s\n", "buffer loaded"); + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + if (helperinfo.count == 0) + { + if (newhelperinfo.count != 0) + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + newhelperinfo.count = 0; + }; + helper_offset += sizeof(helperinfo); + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + printf("%s%lx\n", "helper_offset ", helper_offset); + } + + address = *reinterpret_cast(&buffer[i]); + oldvalue._u64 = *reinterpret_cast(&valuebuffer[i]); + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) //read in data A and B + { + if (no_existing_dump == false) + Bvalue._u64 = *reinterpret_cast(&valueBbuffer[i]); + } - switch(searchMode) { + // fetch value from buffer + // ram_buffer + i == &ram_buffer[i] + // value._u64 = 0; + memset(&value, 0, 8); + memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); + helperinfo.count--; + + // searchValue_t *foobar = reinterpret_cast(ram_buffer + (address - helperinfo.address)) + //_u32 bar = (*foobar)._u32; + //(reinterpret_cast(ram_buffer + (address - helperinfo.address)))._u32 + + // debugger->readMemory(&value, dataTypeSizes[searchType], address); + + if (i % 10000 == 0) + { + setLedState(ledOn); + ledOn = !ledOn; + } + + switch (searchMode) + { case SEARCH_MODE_SAME: - if (newValue._u64 == oldValue._u64) - addrDump->addData((u8*)&addr, sizeof(u64)); + if (value._s64 == oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_SAMEA: + if (no_existing_dump) + { + printf("this shouldn't happen\n"); + if (value._s64 != Bvalue._s64) //change + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&value, sizeof(u64)); + // newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); + newhelperinfo.count++; + } + } + else if (value._s64 == oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); //create new file and later rename to A, need this new file for size of A to be in sync + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFFA: //need to be same as B + if (no_existing_dump) + { + if (value._s64 != oldvalue._s64) // change + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&value, sizeof(u64)); + // newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); + newhelperinfo.count++; + } + } + else if (value._s64 == Bvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_DIFF: - if (newValue._u64 != oldValue._u64) - addrDump->addData((u8*)&addr, sizeof(u64)); + if (value._s64 != oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } break; case SEARCH_MODE_INC: - if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { - if (newValue._s64 > oldValue._s64) - (*displayDump)->addData((u8*)&addr, sizeof(u64)); - } else { - if (newValue._u64 > oldValue._u64) - (*displayDump)->addData((u8*)&addr, sizeof(u64)); + if (value._s64 > oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; } break; case SEARCH_MODE_DEC: - if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { - if (newValue._s64 < oldValue._s64) - (*displayDump)->addData((u8*)&addr, sizeof(u64)); - } else { - if (newValue._u64 < oldValue._u64) - (*displayDump)->addData((u8*)&addr, sizeof(u64)); + if (value._s64 < oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; } break; + case SEARCH_MODE_NONE: + break; + } } + offset += bufferSize; + // update newhelperinfo + + printf("%s%lx%s%lx\n", "(*displayDump)->size() ", (*displayDump)->size(), "Offset ", offset); + } + + if (newhelperinfo.count != 0) // need to take care of the last one + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + newhelperinfo.count = 0; + }; + newDump->flushBuffer(); + newvalueDump->flushBuffer(); + //end + // should just rename the file ?? + if (newDump->size() > 0) + { + printf("%s%lx\n", "newDump->size() ", newDump->size()); + } + else + { + (new Snackbar("None of values changed to the entered one!"))->show(); } setLedState(false); -} + delete[] ram_buffer; + delete[] valuebuffer; + delete[] valueBbuffer; + delete[] buffer; + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time Tertiary search ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + + newvalueDump->flushBuffer(); + newDump->flushBuffer(); + newhelperDump->flushBuffer(); + newvalueDumpA->flushBuffer(); + newvalueDumpB->flushBuffer(); + + delete newvalueDump; + delete newDump; + delete newhelperDump; + delete newvalueDumpA; + delete newvalueDumpB; -void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) { - MemoryDump *newMemDump = new MemoryDump(EDIZON_DIR "/memdump2.dat", DumpType::DATA, true); - MemoryDump *addrDump = new MemoryDump(EDIZON_DIR "/memdump3.dat", DumpType::ADDR, true); - u64 dumpOffset = 0; + delete oldvalueDump; //needed to close the file + delete helperDump; + delete valueDumpB; - for (MemoryInfo meminfo : memInfos) { - if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) - continue; - else if (searchRegion == SEARCH_REGION_MAIN && - (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) - continue; - else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && - (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) - continue; - else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) - continue; + printf("Done Tertiary \n"); + // remove(EDIZON_DIR "/memdump3.dat"); +} +// here + +void GuiCheats::pointercheck() +{ + printf("checking pointer...\n"); + m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, false); + if (m_pointeroffsetDump->size() > 0) + { u64 offset = 0; - u64 bufferSize = 0x40000; + u64 bufferSize = MAX_BUFFER_SIZE; u8 *buffer = new u8[bufferSize]; - while (offset < meminfo.size) { - - if (meminfo.size - offset < bufferSize) - bufferSize = meminfo.size - offset; + pointer_chain_t pointer_chain; + while (offset < m_pointeroffsetDump->size()) + { + if (m_pointeroffsetDump->size() - offset < bufferSize) + bufferSize = m_pointeroffsetDump->size() - offset; + m_pointeroffsetDump->getData(offset, buffer, bufferSize); + for (u64 i = 0; i < bufferSize; i += sizeof(pointer_chain_t)) + { + pointer_chain_t pointer_chain = *reinterpret_cast(&buffer[i]); + u64 nextaddress = m_mainBaseAddr; + printf("main[%lx]", nextaddress); + // m_debugger->readMemory(&nextaddress, sizeof(u64), ( m_mainBaseAddr+ pointer_chain.offset[pointer_chain.depth])); + // printf("(&lx)", nextaddress); + for (int z = pointer_chain.depth; z >= 0; z--) + { + printf("+%lx z=%d ", pointer_chain.offset[z], z); + nextaddress += pointer_chain.offset[z]; + printf("[%lx]", nextaddress); + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + printf("(%lx)", nextaddress); + } + printf("\n\n"); + } + offset += bufferSize; + } + delete[] buffer; + } + else + { + printf("no saved poiters\n"); + } +} - debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); - (*displayDump)->addData(buffer, bufferSize); +void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDump, MemoryDump **dataDump, pointer_chain_t pointerchain) +{ + m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); // pointed targets is in this file + m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, true); // create file but maybe later just open it + pointer_chain_t pointerchain; + printf("check point 1\n"); + pointerchain.depth = 0; + try + { + pointersearch(targetaddress, pointerchain); //&m_memoryDump, &m_dataDump, + } + catch (...) + { + printf("Caught an exception\n"); + } + // add some rubbish just for testing + // char st[250]; // replace the printf + // snprintf(st, 250, "Just for testing ====="); // + // m_pointeroffsetDump->addData((u8 *)&st, sizeof(st)); // - offset += bufferSize; + m_pointeroffsetDump->flushBuffer(); + delete m_pointeroffsetDump; +} + +void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain) //MemoryDump **displayDump, MemoryDump **dataDump, +{ + // printf("target address = %lx depth = %d \n", targetaddress, pointerchain.depth); + + // printf("check point 1a\n"); + if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainBaseAddr + m_mainSize))) + { + printf("\ntarget reached!=========================\n"); + printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); + // pointerchain.depth++; + // pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; + // // save pointerchain + pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; + m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); + m_pointeroffsetDump->flushBuffer(); // is this useful? + printf("main"); + for (int z = pointerchain.depth; z >= 0; z--) + printf("+%lx z=%d ", pointerchain.offset[z], z); + printf("\n\n"); + // printf("\nsize=%d\n", sizeof(pointer_chain_t)); + return; // consider don't return to find more + }; + + if (pointerchain.depth == m_max_depth) + { + // printf("max pointer depth reached\n\n"); + return; + } + + // printf("\n starting pointer search for address = %lx at depth %d ", targetaddress, pointerchain.depth); + u64 offset = 0; + u64 thefileoffset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; + u8 *buffer = new u8[bufferSize]; + u64 distance; + u64 minimum = m_max_range; // a large number to start + std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers + sourceinfo_t sourceinfo; + // std::vector distances; + + while (offset < m_dataDump->size()) + { + if (m_dataDump->size() - offset < bufferSize) + bufferSize = m_dataDump->size() - offset; + // printf("checkpoint 2\n"); + m_dataDump->getData(offset, buffer, bufferSize); // BM4 + bool writeback = false; + // printf("checkpoint 3\n"); + // return; // just to check + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + u64 pointedaddress = *reinterpret_cast(&buffer[i]); + if (targetaddress >= pointedaddress) + { + distance = targetaddress - pointedaddress; + if (distance < minimum) + { + // minimum = distance; + // sources.clear(); + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + sources.push_back(sourceinfo); + thefileoffset = offset + i; + // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop + // writeback = true; // + } + else if (distance == minimum) + { + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + sources.push_back(sourceinfo); + // sources.push_back(offset + i); + thefileoffset = offset + i; + // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop + // writeback = true; // + // pointerchain.fileoffset[pointerchain.depth] = offset + i; + // pointerchain.offset[pointerchain.depth] = distance; + } + } + if (sources.size() > m_max_source) + break; } + if (sources.size() > m_max_source) + break; + // if (writeback) + // { + // m_dataDump->putData(offset, buffer, bufferSize); + // m_dataDump->flushBuffer(); + // } + offset += bufferSize; + } + delete[] buffer; // release memory use for the search of sources + + // Now we have fileoffsets stored in sources to repeat this process + // printf("memory scan completed offset is %lx at depth %lx\n\n", minimum, pointerchain.depth); + // pointerchain.offset[pointerchain.depth] = minimum; + pointerchain.depth++; + + // printf("**Found %d sources \n", sources.size()); + for (sourceinfo_t sourceinfo : sources) + { + // targetaddress = 0x1000; + // printf("size of memorydump is %lx ", m_memoryDump1->size()); // I swapped the bookmark + //m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + u64 newtargetaddress; + m_memoryDump1->getData(sourceinfo.foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte + + // u64 checkaddress; // debug use + // m_dataDump->getData(foffset, &checkaddress, sizeof(u64)); //double check it for debug purpose + // printf("fileoffset = %lx thefileoffset =%lx new target address is %lx old target was %lx\n", sourceinfo.foffset, thefileoffset, newtargetaddress, targetaddress); + if (m_forwardonly) + { + if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainBaseAddr + m_mainSize)))) + { + pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; + pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; + pointersearch(newtargetaddress, pointerchain); + } + } + else + { + /* code */ + pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; + pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; + pointersearch(newtargetaddress, pointerchain); + } + } - delete[] buffer; + return; + + // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); + + // printf("depth is %d new address is %lx offset is %lx code offset is %lx \n", pointerchain.depth, address, pointerchain.fileoffset[pointerchain.depth], pointerchain.offset[pointerchain.depth]); + // if (address < m_mainBaseAddr + m_mainSize) + // { + // printf("target reached!"); + // printf("final offset is %lx \n", address - m_mainBaseAddr); + // pointerchain.depth++; + // pointerchain.offset[pointerchain.depth] = address - m_mainBaseAddr; + // // save pointerchain + // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); + // return; +} +// change address to new one + +// printf("not found \n"); +// return; + +// m_targetmemInfos.clear(); +// m_target = address; +// m_max_depth = depth; +// m_max_range = range; +// m_numoffset = num; + +// std::vector mainInfos; +// mainInfos.clear(); +// m_low_main_heap_addr = 0x100000000000; +// m_high_main_heap_addr = 0; + +// for (MemoryInfo meminfo : m_memoryInfo) +// { +// // if (m_searchRegion == SEARCH_REGION_RAM) +// // if ((meminfo.perm & Perm_Rw) != Perm_Rw) continue; else +// if (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable) +// continue; + +// if (meminfo.addr < m_low_main_heap_addr) +// m_low_main_heap_addr = meminfo.addr; + +// if ((meminfo.addr + meminfo.size) > m_high_main_heap_addr) +// m_high_main_heap_addr = (meminfo.addr + meminfo.size); + +// m_targetmemInfos.push_back(meminfo); + +// if (meminfo.type == MemType_CodeWritable || meminfo.type == MemType_CodeMutable) +// { +// mainInfos.push_back(meminfo); +// // +// printf("%s%p", "meminfo.addr, ", meminfo.addr); +// printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); +// printf("%s%p", ", meminfo.size, ", meminfo.size); +// printf("%s%lx", ", meminfo.type, ", meminfo.type); +// printf("%s%lx", ", meminfo.attr, ", meminfo.attr); +// printf("%s%lx", ", meminfo.perm, ", meminfo.perm); +// printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); +// printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); +// // +// } +// } + +// m_Time1 = time(NULL); +// printf("searching pointer for address %lx\n Range %lx .. %lx ", m_target, m_low_main_heap_addr, m_high_main_heap_addr); +// for (u8 i = 0; i < 20; i++) +// m_hitcount.offset[i] = 0; + +// for (MemoryInfo meminfo : mainInfos) +// { +// if (meminfo.addr < m_mainBaseAddr) +// continue; +// pointer_chain_t ptrchain; +// ptrchain.offset[0] = meminfo.addr - m_mainBaseAddr; +// ptrchain.depth = 0; +// printf("offset %lx \n ", ptrchain.offset[0]); +// // +// printf("%s%p", "meminfo.addr, ", meminfo.addr); +// printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); +// printf("%s%p", ", meminfo.size, ", meminfo.size); +// printf("%s%lx", ", meminfo.type, ", meminfo.type); +// printf("%s%lx", ", meminfo.attr, ", meminfo.attr); +// printf("%s%lx", ", meminfo.perm, ", meminfo.perm); +// printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); +// printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); +// // +// // return; +// printf("Top level meminfo.addr %lx\n time= %d\n", meminfo.addr, time(NULL) - m_Time1); +// searchpointer(meminfo.addr, meminfo.size / sizeof(u64), meminfo.size, ptrchain); +// // +// printf("hit count depth"); +// for (u8 i = 0; i < 20; i++) +// printf("%d= %d ", i, m_hitcount.offset[i]); + +void GuiCheats::searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain) //assumed range don't extend beyond a segment, need to make seperate call to cover multi segment +{ + // using global to reduce overhead + // use separate function if need to get rid of range in the passed variable // u64 m_max_depth; used in first call + // u64 m_target; + // u64 m_numoffset; + // u64 m_max_range; + // u64 m_low_main_heap_addr; The lowerst of main or heap start + // u64 m_high_main_heap_addr; The highest + // printf("in function current depth is %d @@@@@@@@@@@@@@@@@@@@@\n", depth); + // return; + m_hitcount.offset[pointerchain.depth]++; + + if (address <= m_target && m_target <= address + range) + { + printf("found ========================="); + pointerchain.offset[pointerchain.depth] = m_target - address; + pointerchain.depth++; + m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); + // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); + printf("found at depth %d\n", pointerchain.depth); + return; } + if (depth == 0) + { + // printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + return; + // printf("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); + } + pointerchain.depth++; // for all call + depth--; // for all call + // u8 *buffer = new u8[range]; + u32 num = m_numoffset; + u32 nextrange; + u64 nextaddress; + // u32 endaddress = address + range; + // printf("I am at 1"); + u64 bufferSize = MAX_BUFFER_SIZE; + if (range < bufferSize) + bufferSize = range; + u8 *buffer = new u8[bufferSize]; + // printf("I am at 2"); + for (MemoryInfo meminfo : m_targetmemInfos) // a shorten list that has only the real targets + { + if (address < meminfo.addr) + { + // printf("I am at 4"); + return; // address not accessible} + } + if (address > meminfo.addr + meminfo.size) + { + // printf("I am at 5, address =%lx meminfo.addr = %1x, meminfo.size =%1x \n", address, meminfo.addr, meminfo.size); + continue; // next segment + } + u64 offset = 0; + u64 segmentend = meminfo.addr + meminfo.size; + // printf("I am at 3\n"); + while (address + offset < segmentend) + { + if (segmentend - (address + offset) < bufferSize) + bufferSize = segmentend - (address + offset); + + // printf("reading address %lx bufferSize %lx meminfo.addr is %lx meminfo.size is %lx ", (address + offset), bufferSize, meminfo.addr, meminfo.size); + // printf("Time since last update %d \n", time(NULL) - m_Time1); // printf("Top level meminfo.addr %lx\n time= %d\n", meminfo.addr, time(NULL) - m_Time1); + // return; + m_debugger->readMemory(buffer, bufferSize, (address + offset)); + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) //for (u64 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + nextaddress = *reinterpret_cast(&buffer[i]); + // printf("nextaddress = %lx \n", nextaddress); + if ((nextaddress >= m_low_main_heap_addr) && (nextaddress <= m_high_main_heap_addr)) + { + // printf("found ptr === %lx ======================================= pointerchain.depth is %d ==============offset+i is %d \n",nextaddress, pointerchain.depth, offset + i); + pointerchain.offset[pointerchain.depth] = offset + i; // per call + searchpointer(nextaddress, depth, m_max_range, pointerchain); + num--; + if (num == 0) + { + // printf("not found returning &&&&&&&&&&&&&&&&&&&&\n\n"); + return; + } + } + range -= sizeof(u64); + if (range == 0) + return; + } + + offset += bufferSize; + } + } + delete[] buffer; } /** @@ -1416,18 +3435,20 @@ void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchType_t sear * Matches should be stored as [MEMADDR][DUMPADDR] for fast comparing later on */ -static void _moveLonelyCheats(u8 *buildID, u64 titleID) { +static void _moveLonelyCheats(u8 *buildID, u64 titleID) +{ std::stringstream lonelyCheatPath; std::stringstream realCheatPath; - + std::stringstream buildIDStr; - for (u8 i = 0; i < 8; i++) + for (u8 i = 0; i < 8; i++) buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; lonelyCheatPath << EDIZON_DIR "/cheats/" << buildIDStr.str() << ".txt"; - if (access(lonelyCheatPath.str().c_str(), F_OK) == 0) { + if (access(lonelyCheatPath.str().c_str(), F_OK) == 0) + { realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << titleID; mkdir(realCheatPath.str().c_str(), 0777); realCheatPath << "/cheats/"; @@ -1441,7 +3462,8 @@ static void _moveLonelyCheats(u8 *buildID, u64 titleID) { } } -static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) { +static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) +{ std::stringstream ss; ss << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << titleID << "/cheats/"; @@ -1450,8 +3472,8 @@ static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) { return false; bool cheatsFolderEmpty = std::filesystem::is_empty(ss.str()); - - for (u8 i = 0; i < 8; i++) + + for (u8 i = 0; i < 8; i++) ss << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; ss << ".txt"; diff --git a/source/guis/note b/source/guis/note new file mode 100644 index 00000000..37411953 --- /dev/null +++ b/source/guis/note @@ -0,0 +1,159 @@ +create new variable : m_searchValueIndex +m_searchValueIndex = 0 + +define key LEFT and Key RIGHT if (m_searchMenuIndex == SEARCH_VALUE && m_searchMode == SEARCH_MODE_RANGE) +RIGHT +if (m_searchValueIndex==0) m_searchValueIndex++; +LEFT +if (m_searchValueIndex==1) m_searchValueIndex--; + +display m_searchValue[1] if (m_searchMode == SEARCH_MODE_RANGE) + +change Key_A action to +m_searchValue[m_searchValueIndex]= + +m_searchMenuLocation = SEARCH_editRAM; + +|| m_searchMenuLocation = SEARCH_editRAM + +m_searchMenuLocation == SEARCH_editRAM + +m_editRAM + +//toggle bookmark view bookmark : (m_memoryDump1 != nullptr) +Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 E4 \uE0E5 E5 \uE0E6 E6 \uE0E7 E7 \uE0E8 E8 \uE0E9 E9 \uE0EA EA \uE0EF EF \uE0F0 F0 \uE0F1 F1 \uE0F2 F2 \uE0F3 F3 \uE0F4 F4 \uE0F5 F5 ", ALIGNED_RIGHT); + } + + first dump 82s + second dump 51s with 12,582,901 hits + rename not working + +search 0 130 seconds file size 4G +search 100 + + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::ADDR, false); // has address, size, count for fetching buffer from memory + MemoryDump *newhelperDump = new MemoryDump(EDIZON_DIR "/memdump3a.dat", DumpType::ADDR, true); // has address, size, count for fetching buffer from memory + if (helperDump->size() == 0) + { + (new Snackbar("Helper file not found !"))->show(); + return; + } + u8 *ram_buffer = new u8[bufferSize]; + u64 helper_offset = 0; + helperinfo_t helperinfo; + helperinfo_t newhelperinfo; + newhelperinfo.count = 0; + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); // helper_offset+=sizeof(helperinfo) + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); //debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + // helper init end + + // inner loop start + if (helperinfo.count == 0) + { + helper_offset += sizeof(helperinfo); + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); + debugger->readMemory(&ram_buffer, helperinfo.size, helperinfo.address); + } + + // Value extraction + // value._u64 = 0; // not needed + memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); + helperinfo.count--; // each fetch dec + + // inc when add to new dump + newhelperinfo.count++;} + +// store newhelperinfo + if (newhelperinfo.count != 0) + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + + // clean up + delete newhelperDump; + delete helperDump; + delete[] ram_buffer; +//////////////////////////////////////////////// + + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::ADDR, true); // has address, size, count for fetching buffer from memory + helperinfo_t helperinfo; + + // start count + helperinfo.count = 0; + + // inc must watch { + helperinfo.count++;} + + // end compare + // helper info write must be before inc + if (helperinfo.count != 0) + { + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + helperinfo.count = 0; // must be after write + // end + } + + delete helperDump; + + + + +//////////////////// pointer search scratch pad + // BM 10 need the while construct from other routine maybe can embed into the for momoryinfo loop + + debugger->readMemory(buffer, range, address); + for (u64 offset = 0; offset < range; i += sizeof(u64)) + { + // if (inrange(*(buffer + offset), nextrange)) + + // check inrange + nextaddress = *(buffer + offset); + // nextrange = maxrange; // maybe don't need this + + + // BM11 + // if not inrange + continue; + // if inrange + { + searchpointer(nextaddress, depth--, nextrange, maxrange, pointerchain.addoffset(offset)); + num--; + if (num == 0) + break; + } +/////////////////// change log DIFFA and SAMEA +added extra condition for value search +if (m_searchMode == SEARCH_MODE_SAME || m_searchMode == SEARCH_MODE_DIFF || m_searchMode == SEARCH_MODE_INC || m_searchMode == SEARCH_MODE_DEC || m_searchMode == SEARCH_MODE_DIFFA || m_searchMode == SEARCH_MODE_SAMEA ) + +added extra file + if (searchMode == SEARCH_MODE_DIFFA) + MemoryDump *newvalueDumpA = new MemoryDump(EDIZON_DIR "/datadumpA.dat", DumpType::DATA, true); // file to put A + + if (searchMode == SEARCH_MODE_SAMEA) + MemoryDump *newvalueDumpA = new MemoryDump(EDIZON_DIR "/datadumpA.dat", DumpType::DATA, false); // file to get A + + case SEARCH_MODE_DIFFA: + if (newValue._u64 != oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldValue, sizeof(u64)); // save old value + helperinfo.count++; + } + break; + + + NEED to do the renaming from B to A \ No newline at end of file diff --git a/source/guis/pointer_search.cpp1 b/source/guis/pointer_search.cpp1 new file mode 100644 index 00000000..2ef03a90 --- /dev/null +++ b/source/guis/pointer_search.cpp1 @@ -0,0 +1,288 @@ +#include "guis/gui_cheats.hpp" + +#include +#include +#include + +#include +#include + +#include "helpers/util.h" + +#include "edizon_logo_bin.h" + +// Debugger *debugger, MemoryDump **displayDump, std::vector memInfos + +// first call make range the whole main R/W segments ; +// golbal m_offsetDump +#define MAX_BUFFER_SIZE 0x1000000 +MemoryDump *m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); // has address, size, count for fetching buffer from memory +// m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); +m_pointeroffsetDump->setPointerSearchParams(m_max_depth, m_numoffset, m_maxrange); + +//BM Begin pointer search init + +MemoryDump *m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, false); +// m_pointeroffsetDump->setPointerSearchParams(m_max_depth, m_numoffset, m_maxrange, m_buildID); + +GuiCheats::searchpointer(u64 address, u64 depth, u64 range, pointer_chain_t pointerchain) +{ + //to move to global + // u64 m_target; + // u64 m_max_depth; + // u64 m_numoffset; + // u64 m_maxrange; + + // need buffersize define from other routine; + + if (address <= m_target && m_target <= address + range) + { + pointerchain.offset[pointerchain.depth] = m_target - address; + pointerchain.depth++; + m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); + // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); + return true; + } + else if (depth == 0) + { + return false + } + else + { + u8 *buffer = new u8[range]; + u32 num = m_numoffset; + u32 nextrange; + u32 nextaddress; + u32 endaddress = address + range; + + u64 bufferSize = MAX_BUFFER_SIZE; + if (range < bufferSize) + bufferSize = range; + u8 *buffer = new u8[bufferSize]; + + for (MemoryInfo meminfo : m_targetmemInfos) // a shorten list that has only the real targets + { + if (address < meminfo.addr) + return; // address not accessible + if (address > meminfo.addr + meminfo.size) + break; // next segment + u64 offset = address; + u64 segmentend = meminfo.addr + meminfo.size; + while (offset < segmentend) + { + if (segmentend - offset < bufferSize) + bufferSize = segmentend - offset; + debugger->readMemory(buffer, bufferSize, offset); + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[u64]) + { + nextaddress = *(buffer + i); + pointerchain.offset[pointerchain.depth] = offset - address; + pointerchain.depth++; + searchpointer(nextaddress, depth--, m_maxrange, pointerchain); + num--; + if (num == 0) + break; + } + + offset += bufferSize; + } + } + delete[] buffer; + } +} + +typedef struct +{ + u64 addr; ///< Base address. + u64 size; ///< Size. + u32 type; ///< Memory type (see lower 8 bits of \ref MemoryState). + u32 attr; ///< Memory attributes (see \ref MemoryAttribute). + u32 perm; ///< Memory permissions (see \ref Permission). + u32 device_refcount; ///< Device reference count. + u32 ipc_refcount; ///< IPC reference count. + u32 padding; ///< Padding. +} MemoryInfo; +m_memoryInfo for (MemoryInfo meminfo : memInfos) +{ + printf("%s%lx\n", "meminfo.addr ", meminfo.addr); + printf("%s%lx\n", "meminfo.size ", meminfo.size); + printf("%s%lx\n", "meminfo.type ", meminfo.type); + printf("%s%lx\n", "meminfo.attr ", meminfo.attr); + printf("%s%lx\n", "meminfo.perm ", meminfo.perm); + printf("%s%lx\n", "meminfo.device_refcount ", meminfo.device_refcount); + printf("%s%lx\n", "meminfo.ipc_refcount ", meminfo.ipc_refcount); +} + +(*displayDump) = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, true); +(*displayDump)->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); +(*displayDump)->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); + +MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory +helperinfo_t helperinfo; +helperinfo.count = 0; + +bool ledOn = false; + +time_t unixTime1 = time(NULL); +printf("%s%lx\n", "Start Time primary search", unixTime1); +// +for (MemoryInfo meminfo : memInfos) +{ + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + + setLedState(ledOn); + ledOn = !ledOn; + + u64 offset = 0; + u64 bufferSize = 0x1000000; // consider to increase from 10k to 1M (not a big problem) + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + + debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + u64 address = meminfo.addr + offset + i; + memset(&realValue, 0, 8); + memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + + switch (searchMode) + { + case SEARCH_MODE_EQ: + if (realValue._s64 == searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_NEQ: + if (realValue._s64 != searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_GT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 > searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 > searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_GTE: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 >= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 >= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_LT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 < searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 < searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_LTE: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 <= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 <= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_RANGE: + if (realValue._s64 >= searchValue1._s64 && realValue._s64 <= searchValue2._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + } + } + + // helper info write must be before inc + if (helperinfo.count != 0) + { + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + helperinfo.count = 0; + } // must be after write + + offset += bufferSize; + } + + delete[] buffer; +} +// +setLedState(false); + +time_t unixTime2 = time(NULL); +printf("%s%lx\n", "Stop Time ", unixTime2); +printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + +(*displayDump)->flushBuffer(); +delete helperDump; +} +// \ No newline at end of file diff --git a/source/guis/pointer_search.cpp2 b/source/guis/pointer_search.cpp2 new file mode 100644 index 00000000..c0b92214 --- /dev/null +++ b/source/guis/pointer_search.cpp2 @@ -0,0 +1,319 @@ +#include "guis/gui_cheats.hpp" + +#include +#include +#include + +#include +#include + +#include "helpers/util.h" + +#include "edizon_logo_bin.h" + +// Debugger *debugger, MemoryDump **displayDump, std::vector memInfos + +// first call make range the whole main R/W segments ; +// golbal m_offsetDump +#define MAX_BUFFER_SIZE 0x1000000 +MemoryDump *m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); // has address, size, count for fetching buffer from memory +// m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); +m_pointeroffsetDump->setPointerSearchParams(m_max_depth, m_numoffset, m_maxrange); + +//BM Begin pointer search init + +MemoryDump *m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, false); +// m_pointeroffsetDump->setPointerSearchParams(m_max_depth, m_numoffset, m_maxrange, m_buildID); + +GuiCheats::startpointersearch(u64 address, u64 depth, u64 range, u64 num) +{ + m_target = address; + m_numoffset = num; + m_maxrange = range; + m_max_depth = depth; + m_low_main_heap_addr = ; //The lowerst of main or heap start + m_high_main_heap_addr= ; The highest + m_targetmemInfos.clear(); + for (MemoryInfo meminfo : m_memInfos) //need to fine tune + { + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + m_targetmemInfos.push_back(meminfo); + } + pointer_chain_t ptrchain; + ptrchain.depth = 0; + searchpointer +} + +GuiCheats::searchpointer(u64 address, u64 depth, u64 range, pointer_chain_t pointerchain) //assumed range don't extend beyond a segment, need to make seperate call to cover multi segment +{ + // using global to reduce overhead + // use separate function if need to get rid of range in the passed variable // u64 m_max_depth; used in first call + // u64 m_target; + // u64 m_numoffset; + // u64 m_maxrange; + // u64 m_low_main_heap_addr; The lowerst of main or heap start + // u64 m_high_main_heap_addr; The highest + + if (address <= m_target && m_target <= address + range) + { + pointerchain.offset[pointerchain.depth] = m_target - address; + pointerchain.depth++; + m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); + // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); + return true; + } + else if (depth == 0) + { + return false + } + else + { + u8 *buffer = new u8[range]; + u32 num = m_numoffset; + u32 nextrange; + u32 nextaddress; + u32 endaddress = address + range; + + u64 bufferSize = MAX_BUFFER_SIZE; + if (range < bufferSize) + bufferSize = range; + u8 *buffer = new u8[bufferSize]; + + for (MemoryInfo meminfo : m_targetmemInfos) // a shorten list that has only the real targets + { + if (address < meminfo.addr) + return; // address not accessible + if (address > meminfo.addr + meminfo.size) + break; // next segment + u64 offset = address; + u64 segmentend = meminfo.addr + meminfo.size; + while (offset < segmentend) + { + if (segmentend - offset < bufferSize) + bufferSize = segmentend - offset; + debugger->readMemory(buffer, bufferSize, offset); + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[u64]) + { + nextaddress = *(buffer + i); + if (nextaddress >= m_low_main_heap_addr && nextaddress <= m_high_main_heap_addr) + { + pointerchain.offset[pointerchain.depth] = offset - address; + pointerchain.depth++; + searchpointer(nextaddress, depth--, m_maxrange, pointerchain); + num--; + if (num == 0) + break; + } + } + + offset += bufferSize; + } + } + delete[] buffer; + } +} + +typedef struct +{ + u64 addr; ///< Base address. + u64 size; ///< Size. + u32 type; ///< Memory type (see lower 8 bits of \ref MemoryState). + u32 attr; ///< Memory attributes (see \ref MemoryAttribute). + u32 perm; ///< Memory permissions (see \ref Permission). + u32 device_refcount; ///< Device reference count. + u32 ipc_refcount; ///< IPC reference count. + u32 padding; ///< Padding. +} MemoryInfo; +m_memoryInfo for (MemoryInfo meminfo : memInfos) +{ + printf("%s%lx\n", "meminfo.addr ", meminfo.addr); + printf("%s%lx\n", "meminfo.size ", meminfo.size); + printf("%s%lx\n", "meminfo.type ", meminfo.type); + printf("%s%lx\n", "meminfo.attr ", meminfo.attr); + printf("%s%lx\n", "meminfo.perm ", meminfo.perm); + printf("%s%lx\n", "meminfo.device_refcount ", meminfo.device_refcount); + printf("%s%lx\n", "meminfo.ipc_refcount ", meminfo.ipc_refcount); +} + +(*displayDump) = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, true); +(*displayDump)->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); +(*displayDump)->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); + +MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory +helperinfo_t helperinfo; +helperinfo.count = 0; + +bool ledOn = false; + +time_t unixTime1 = time(NULL); +printf("%s%lx\n", "Start Time primary search", unixTime1); +// +for (MemoryInfo meminfo : memInfos) +{ + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + + setLedState(ledOn); + ledOn = !ledOn; + + u64 offset = 0; + u64 bufferSize = 0x1000000; // consider to increase from 10k to 1M (not a big problem) + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + + debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + u64 address = meminfo.addr + offset + i; + memset(&realValue, 0, 8); + memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + + switch (searchMode) + { + case SEARCH_MODE_EQ: + if (realValue._s64 == searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_NEQ: + if (realValue._s64 != searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_GT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 > searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 > searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_GTE: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 >= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 >= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_LT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 < searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 < searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_LTE: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 <= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 <= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_RANGE: + if (realValue._s64 >= searchValue1._s64 && realValue._s64 <= searchValue2._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + } + } + + // helper info write must be before inc + if (helperinfo.count != 0) + { + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + helperinfo.count = 0; + } // must be after write + + offset += bufferSize; + } + + delete[] buffer; +} +// +setLedState(false); + +time_t unixTime2 = time(NULL); +printf("%s%lx\n", "Stop Time ", unixTime2); +printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + +(*displayDump)->flushBuffer(); +delete helperDump; +} +// \ No newline at end of file diff --git a/source/helpers/diff b/source/helpers/diff new file mode 100644 index 00000000..05ff33fe --- /dev/null +++ b/source/helpers/diff @@ -0,0 +1,59 @@ +Comparing files save.cpp and SAVE1.CPP +***** save.cpp +#include "helpers/debugger.hpp" +using json = nlohmann::json; +***** SAVE1.CPP +#include "helpers/debugger.hpp" + +using json = nlohmann::json; +***** + +***** save.cpp + FsSaveDataInfo info; + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; + rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. +***** SAVE1.CPP + FsSaveDataInfo info; + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; + u64 runningid = l_debugger->getRunningApplicationPID(); + + rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. +***** + +***** save.cpp + return MAKERESULT(Module_Libnx, LibnxError_NotFound); + + for (; R_SUCCEEDED(rc) && total_entries > 0; +***** SAVE1.CPP + return MAKERESULT(Module_Libnx, LibnxError_NotFound); + for (; R_SUCCEEDED(rc) && total_entries > 0; +***** + +***** save.cpp + { + if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationTID())) // +hacked to get only the running title + { +***** SAVE1.CPP + { + if (runningid == 0) + { + if (info.save_data_type == FsSaveDataType_Account) // hacked to get only the running title if using cheat engine + { + saveInfoList.push_back(info); + } + } + if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationPID())) // +hacked to get only the running title if using cheat engine + { +***** + +***** save.cpp + saveInfoList.push_back(info); + } +***** SAVE1.CPP + saveInfoList.push_back(info); + printf("has hit for title\n"); + } +***** + diff --git a/source/helpers/dmntcht.c b/source/helpers/dmntcht.c index 716a23ab..3bdd4f05 100644 --- a/source/helpers/dmntcht.c +++ b/source/helpers/dmntcht.c @@ -30,6 +30,7 @@ void _dmntchtCleanup(void) { serviceClose(&g_dmntchtSrv); } + Service* dmntchtGetServiceSession(void) { return &g_dmntchtSrv; } diff --git a/source/helpers/memory_dump.cpp b/source/helpers/memory_dump.cpp index 40b554a1..b5fe8336 100644 --- a/source/helpers/memory_dump.cpp +++ b/source/helpers/memory_dump.cpp @@ -1,10 +1,28 @@ #include "helpers/memory_dump.hpp" #include +// +// #include "guis/gui_cheats.hpp" -#define BUFFER_SIZE 0x10000 +// #include +// #include +// #include -MemoryDump::MemoryDump(std::string filePath, DumpType dumpType, bool discardFile) : m_filePath(filePath) { - m_dataHeader = { 0 }; +#include +// #include + +// #include "helpers/util.h" + +// #include "edizon_logo_bin.h" +// + + +#define BUFFER_SIZE 0x500000 // file buffer size test increase from 1M to 2M gets 10% improvement + +bool print_details = false; + +MemoryDump::MemoryDump(std::string filePath, DumpType dumpType, bool discardFile) : m_filePath(filePath) +{ + m_dataHeader = {0}; m_dataHeader.magic = 0x4E5A4445; m_dataHeader.endOfHeader = '@'; @@ -16,41 +34,50 @@ MemoryDump::MemoryDump(std::string filePath, DumpType dumpType, bool discardFile m_dumpFile = fopen(filePath.c_str(), "r"); - if (m_dumpFile == nullptr) { + if (m_dumpFile == nullptr) + { m_dumpFile = fopen(filePath.c_str(), "w+b"); MemoryDump::writeHeader(); - } else { + } + else + { fclose(m_dumpFile); - if (discardFile) { + if (discardFile) + { m_dumpFile = fopen(filePath.c_str(), "w+b"); MemoryDump::writeHeader(); - } else { + } + else + { m_dumpFile = fopen(filePath.c_str(), "r+b"); fseek(m_dumpFile, 0, SEEK_END); size_t fileSize = ftell(m_dumpFile); - if (fileSize >= sizeof(DataHeader)) { + if (fileSize >= sizeof(DataHeader)) + { fseek(m_dumpFile, 0, SEEK_SET); fread(&m_dataHeader, sizeof(m_dataHeader), 1, m_dumpFile); } } - } m_data.reserve(BUFFER_SIZE); } -MemoryDump::~MemoryDump() { - if (isFileOpen()) { +MemoryDump::~MemoryDump() +{ + if (isFileOpen()) + { MemoryDump::flushBuffer(); fclose(m_dumpFile); } } -void MemoryDump::setBaseAddresses(u64 addrSpaceBase, u64 heapBase, u64 mainBase, u64 heapSize, u64 mainSize) { +void MemoryDump::setBaseAddresses(u64 addrSpaceBase, u64 heapBase, u64 mainBase, u64 heapSize, u64 mainSize) +{ m_dataHeader.addrSpaceBaseAddress = addrSpaceBase; m_dataHeader.heapBaseAddress = heapBase; m_dataHeader.mainBaseAddress = mainBase; @@ -61,7 +88,8 @@ void MemoryDump::setBaseAddresses(u64 addrSpaceBase, u64 heapBase, u64 mainBase, MemoryDump::writeHeader(); } -void MemoryDump::setSearchParams(searchType_t searchDataType, searchMode_t searchMode, searchRegion_t searchRegion, searchValue_t searchValue1, searchValue_t searchValue2) { +void MemoryDump::setSearchParams(searchType_t searchDataType, searchMode_t searchMode, searchRegion_t searchRegion, searchValue_t searchValue1, searchValue_t searchValue2) +{ m_dataHeader.searchDataType = searchDataType; m_dataHeader.searchMode = searchMode; m_dataHeader.searchRegion = searchRegion; @@ -71,39 +99,59 @@ void MemoryDump::setSearchParams(searchType_t searchDataType, searchMode_t searc MemoryDump::writeHeader(); } -void MemoryDump::addData(u8 *buffer, size_t dataSize) { - if ((m_data.size() + dataSize) < BUFFER_SIZE) { +void MemoryDump::setPointerSearchParams(u64 max_depth, u64 numoffset, u64 maxrange, u8 buildID[0x20]) +{ + m_dataHeader.max_depth = max_depth; + m_dataHeader.numoffset = numoffset; + m_dataHeader.maxrange = maxrange; + memcpy(&m_dataHeader.buildID, buildID, 0x20); + MemoryDump::writeHeader(); +} + +void MemoryDump::addData(u8 *buffer, size_t dataSize) +{ + if ((m_data.size() + dataSize) < BUFFER_SIZE) + { std::copy(buffer, buffer + dataSize, std::back_inserter(m_data)); - } else if (dataSize <= BUFFER_SIZE) { - if (isFileOpen()) { + } + else if (dataSize <= BUFFER_SIZE) + { + if (isFileOpen()) + { MemoryDump::flushBuffer(); std::copy(buffer, buffer + dataSize, std::back_inserter(m_data)); } - } else { - if (isFileOpen()) { - fseek(m_dumpFile, 0, SEEK_END); + } + else + { + if (isFileOpen()) + { MemoryDump::flushBuffer(); + fseek(m_dumpFile, 0, SEEK_END); // read shouldn't this come after flushbuffer?? fwrite(buffer, sizeof(u8), dataSize, m_dumpFile); m_dataHeader.dataSize += dataSize; - MemoryDump::writeHeader(); + MemoryDump::writeHeader(); // Maybe implement this section directly to avoid extra flashbuffer, seek, writeheader } } } -size_t MemoryDump::size() { +size_t MemoryDump::size() +{ MemoryDump::flushBuffer(); return m_dataHeader.dataSize; } -void MemoryDump::clear() { +void MemoryDump::clear() +{ m_data.clear(); m_dataHeader.dataSize = 0; m_dataHeader.dumpType = DumpType::UNDEFINED; - if (isFileOpen()) { + if (isFileOpen()) + { fclose(m_dumpFile); m_dumpFile = nullptr; } @@ -112,21 +160,52 @@ void MemoryDump::clear() { MemoryDump::writeHeader(); } -int MemoryDump::getData(u64 addr, void *buffer, size_t bufferSize) { - if (!isFileOpen()) return 1; - +int MemoryDump::getData(u64 addr, void *buffer, size_t bufferSize) +{ + if (!isFileOpen()) + { + // if (print_details) + // printf("%s\n", "file not open"); + return 1; + } MemoryDump::flushBuffer(); - + // if (print_details) + // printf("%s\n", "flush buffer OK"); fseek(m_dumpFile, sizeof(struct DataHeader) + addr, SEEK_SET); + // if (print_details) + // printf("%s\n", "fseek OK"); fread(buffer, sizeof(u8), bufferSize, m_dumpFile); + // if (print_details) + // printf("%s\n", "read OK"); + return 0; +} +int MemoryDump::putData(u64 addr, void *buffer, size_t bufferSize) +{ + if (!isFileOpen()) + { + // if (print_details) + // printf("%s\n", "file not open"); + return 1; + } + MemoryDump::flushBuffer(); + // if (print_details) + // printf("%s\n", "flush buffer OK"); + fseek(m_dumpFile, sizeof(struct DataHeader) + addr, SEEK_SET); + // if (print_details) + // printf("%s\n", "fseek OK"); + fwrite(buffer, sizeof(u8), bufferSize, m_dumpFile); + // if (print_details) + // printf("%s\n", "read OK"); return 0; } -u8 MemoryDump::operator[](u64 index) { +u8 MemoryDump::operator[](u64 index) +{ u8 data = 0; - if (!isFileOpen()) return 0; + if (!isFileOpen()) + return 0; MemoryDump::flushBuffer(); @@ -136,12 +215,15 @@ u8 MemoryDump::operator[](u64 index) { return data; } -bool MemoryDump::isFileOpen() { +bool MemoryDump::isFileOpen() +{ return m_dumpFile != nullptr; } -void MemoryDump::flushBuffer() { - if (m_data.size() > 0 && isFileOpen()) { +void MemoryDump::flushBuffer() +{ + if (m_data.size() > 0 && isFileOpen()) + { fseek(m_dumpFile, 0, SEEK_END); fwrite(&m_data[0], sizeof(u8), m_data.size(), m_dumpFile); @@ -153,23 +235,30 @@ void MemoryDump::flushBuffer() { } } -void MemoryDump::writeHeader() { - if (isFileOpen()) { +void MemoryDump::writeHeader() +{ + if (isFileOpen()) + { fseek(m_dumpFile, 0, SEEK_SET); fwrite(&m_dataHeader, sizeof(m_dataHeader), 1, m_dumpFile); fflush(m_dumpFile); } } -data_header_t MemoryDump::getDumpInfo() { +data_header_t MemoryDump::getDumpInfo() +{ return m_dataHeader; } -void MemoryDump::setDumpType(DumpType dumpType) { - if (m_dataHeader.dumpType != UNDEFINED) { +void MemoryDump::setDumpType(DumpType dumpType) +{ + if (m_dataHeader.dumpType != UNDEFINED) + { m_dataHeader.dumpType = dumpType; MemoryDump::clear(); - } else { + } + else + { m_dataHeader.dumpType = dumpType; MemoryDump::writeHeader(); } diff --git a/source/helpers/save.cpp b/source/helpers/save.cpp index f4a2da59..098302f7 100644 --- a/source/helpers/save.cpp +++ b/source/helpers/save.cpp @@ -6,72 +6,81 @@ #include "helpers/account.hpp" #include "helpers/title.hpp" +#include "helpers/debugger.hpp" using json = nlohmann::json; -s32 deleteDirRecursively(const char *path, bool isSave) { +s32 deleteDirRecursively(const char *path, bool isSave) +{ DIR *d = opendir(path); - size_t path_len = strlen(path); - s32 r = -1; + size_t path_len = strlen(path); + s32 r = -1; - if (d) { - struct dirent *p; + if (d) + { + struct dirent *p; - r = 0; + r = 0; - while (!r && (p=readdir(d))) { - s32 r2 = -1; - char *buf; - size_t len; + while (!r && (p = readdir(d))) + { + s32 r2 = -1; + char *buf; + size_t len; - /* Skip the names "." and ".." as we don't want to recurse on them. */ - if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { - continue; - } - - len = path_len + strlen(p->d_name) + 2; - buf = new char[len]; - - if (buf) { - struct stat statbuf; + /* Skip the names "." and ".." as we don't want to recurse on them. */ + if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) + { + continue; + } - snprintf(buf, len, "%s/%s", path, p->d_name); + len = path_len + strlen(p->d_name) + 2; + buf = new char[len]; - if (!stat(buf, &statbuf)) { - if (S_ISDIR(statbuf.st_mode)) - r2 = deleteDirRecursively(buf, isSave); - else - r2 = unlink(buf); - } + if (buf) + { + struct stat statbuf; - delete[] buf; - } + snprintf(buf, len, "%s/%s", path, p->d_name); - r = r2; + if (!stat(buf, &statbuf)) + { + if (S_ISDIR(statbuf.st_mode)) + r2 = deleteDirRecursively(buf, isSave); + else + r2 = unlink(buf); } - closedir(d); - } + delete[] buf; + } - if (!r) - r = rmdir(path); + r = r2; + } + closedir(d); + } - if (isSave && R_FAILED(fsdevCommitDevice(SAVE_DEV))) { - printf("Committing failed.\n"); - return -3; - } + if (!r) + r = rmdir(path); - return r; + if (isSave && R_FAILED(fsdevCommitDevice(SAVE_DEV))) + { + printf("Committing failed.\n"); + return -3; + } + + return r; } -bool doesFolderExist(const char *path) { +bool doesFolderExist(const char *path) +{ struct stat sb; - + return stat(path, &sb) == 0 && S_ISDIR(sb.st_mode); } -bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject, const char* injectFolder, bool fromBatch, std::string backupName) { +bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject, const char *injectFolder, bool fromBatch, std::string backupName) +{ std::stringstream ss; std::string folder_path(EDIZON_DIR); @@ -81,11 +90,12 @@ bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject std::stringstream metadata_user_id; std::stringstream metadata_title_id; - if (!fromBatch) { + if (!fromBatch) + { folder_path += "/saves/"; mkdir(folder_path.c_str(), 0700); - ss << folder_path << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID)*2) - << std::hex << titleID << "/"; + ss << folder_path << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID) * 2) + << std::hex << titleID << "/"; mkdir(ss.str().c_str(), 0700); std::string titleName = ss.str(); @@ -97,12 +107,12 @@ bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject else ss << backupName << "/"; } - else { + else + { folder_path += "/batch_saves/"; mkdir(folder_path.c_str(), 0700); ss << folder_path << backupName << "/"; - mkdir(ss.str().c_str(), 0700); u64 userIDH = userID.uid[1]; @@ -111,11 +121,12 @@ bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject ss << std::setfill('0') << std::uppercase << std::hex << userIDH << std::setfill('0') << std::uppercase << std::hex << userIDL << "/"; mkdir(ss.str().c_str(), 0700); - ss << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID)*2) - << std::hex << titleID << "/"; + ss << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID) * 2) + << std::hex << titleID << "/"; } - if(doesFolderExist(ss.str().c_str())) return false; + if (doesFolderExist(ss.str().c_str())) + return false; strcpy(ptr, ss.str().c_str()); mkdir(ptr, 0700); @@ -123,62 +134,76 @@ bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject u64 userIDH = userID.uid[1]; u64 userIDL = userID.uid[0]; - metadata_user_id << std::setfill('0') << std::uppercase << std::hex << userIDH; - metadata_user_id << std::setfill('0') << std::uppercase << std::hex << userIDL; + metadata_user_id << std::setfill('0') << std::uppercase << std::hex << userIDH; + metadata_user_id << std::setfill('0') << std::uppercase << std::hex << userIDL; metadata["user_id"] = metadata_user_id.str(); metadata["user_name"] = Account::g_accounts[userID]->getUserName(); - metadata_title_id << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID)*2) << std::hex << titleID; + metadata_title_id << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID) * 2) << std::hex << titleID; metadata["title_id"] = metadata_title_id.str(); metadata["title_name"] = Title::g_titles[titleID]->getTitleName(); metadata["title_version"] = Title::g_titles[titleID]->getTitleVersion(); metadata_string = metadata.dump(4); - - metadata_file.open (ss.str() + "edizon_save_metadata.json"); + metadata_file.open(ss.str() + "edizon_save_metadata.json"); metadata_file << metadata_string << "\n"; metadata_file.close(); return true; } -Result _getSaveList(std::vector & saveInfoList) { - Result rc=0; +Result _getSaveList(std::vector &saveInfoList) +{ + Result rc = 0; FsSaveDataInfoReader iterator; - s64 total_entries=0; + s64 total_entries = 0; FsSaveDataInfo info; + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; + u64 runningid = l_debugger->getRunningApplicationPID(); - rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User);//See libnx fs.h. - if (R_FAILED(rc)) { + rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. + if (R_FAILED(rc)) + { printf("fsOpenSaveDataIterator() failed: 0x%x\n", rc); return rc; } - rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries);//See libnx fs.h. + rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries); //See libnx fs.h. if (R_FAILED(rc)) return rc; if (total_entries == 0) return MAKERESULT(Module_Libnx, LibnxError_NotFound); - for (; R_SUCCEEDED(rc) && total_entries > 0; - rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries)) { - if (info.save_data_type == FsSaveDataType_Account) { + rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries)) + { + if (runningid == 0) + { + if (info.save_data_type == FsSaveDataType_Account) // hacked to get only the running title if using cheat engine + { + saveInfoList.push_back(info); + } + } + if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationPID())) // hacked to get only the running title if using cheat engine + { saveInfoList.push_back(info); + printf("has hit for title\n"); } } fsSaveDataInfoReaderClose(&iterator); - + delete l_debugger; return 0; } -Result mountSaveByTitleAccountIDs(const u64 titleID, const AccountUid userID, FsFileSystem& tmpfs) { +Result mountSaveByTitleAccountIDs(const u64 titleID, const AccountUid userID, FsFileSystem &tmpfs) +{ Result rc = 0; - rc = fsOpen_SaveData(&tmpfs, titleID, userID);//See also libnx fs.h. - if (R_FAILED(rc)) { + rc = fsOpen_SaveData(&tmpfs, titleID, userID); //See also libnx fs.h. + if (R_FAILED(rc)) + { printf("fsMount_SaveData() failed: 0x%x\n", rc); fsdevUnmountDevice(SAVE_DEV); fsFsClose(&tmpfs); @@ -186,41 +211,45 @@ Result mountSaveByTitleAccountIDs(const u64 titleID, const AccountUid userID, Fs } s32 ret = fsdevMountDevice(SAVE_DEV, tmpfs); - if (ret == -1) { + if (ret == -1) + { printf("fsdevMountDevice() failed.\n"); rc = ret; } return rc; } -s32 isDirectory(const char *path) { - struct stat statbuf; +s32 isDirectory(const char *path) +{ + struct stat statbuf; - if (stat(path, &statbuf) != 0) - return 0; + if (stat(path, &statbuf) != 0) + return 0; - return S_ISDIR(statbuf.st_mode); + return S_ISDIR(statbuf.st_mode); } -s32 cpFile(std::string srcPath, std::string dstPath) { - FILE* src = fopen(srcPath.c_str(), "rb"); - FILE* dst = fopen(dstPath.c_str(), "wb+"); +s32 cpFile(std::string srcPath, std::string dstPath) +{ + FILE *src = fopen(srcPath.c_str(), "rb"); + FILE *dst = fopen(dstPath.c_str(), "wb+"); if (src == nullptr || dst == nullptr) - return - 1; + return -1; fseek(src, 0, SEEK_END); rewind(src); size_t size; - char* buf = new char[0x50000]; + char *buf = new char[0x50000]; u64 offset = 0; size_t slashpos = srcPath.rfind("/"); std::string name = srcPath.substr(slashpos + 1, srcPath.length() - slashpos - 1); - while ((size = fread(buf, 1, 0x50000, src)) > 0) { - fwrite(buf, 1, size, dst); - offset += size; + while ((size = fread(buf, 1, 0x50000, src)) > 0) + { + fwrite(buf, 1, size, dst); + offset += size; } delete[] buf; @@ -230,9 +259,10 @@ s32 cpFile(std::string srcPath, std::string dstPath) { return 0; } -s32 copyAllSave(const char * path, bool isInject, const char exInjDir[0x100]) { - DIR* dir; - struct dirent* ent; +s32 copyAllSave(const char *path, bool isInject, const char exInjDir[0x100]) +{ + DIR *dir; + struct dirent *ent; char filenameSave[0x100]; char filenameSD[0x100]; @@ -248,13 +278,17 @@ s32 copyAllSave(const char * path, bool isInject, const char exInjDir[0x100]) { else dir = opendir(filenameSave); - if (dir == nullptr) { + if (dir == nullptr) + { printf("Failed to open dir: %s\n", isInject ? filenameSD : filenameSave); return -1; } - else { - while ((ent = readdir(dir))) { - if (strcmp(ent->d_name, "edizon_save_metadata.json") == 0) continue; + else + { + while ((ent = readdir(dir))) + { + if (strcmp(ent->d_name, "edizon_save_metadata.json") == 0) + continue; char filename[0x100]; @@ -268,29 +302,40 @@ s32 copyAllSave(const char * path, bool isInject, const char exInjDir[0x100]) { strcpy(filenameSD, exInjDir); strcat(filenameSD, filename); - if (isDirectory(isInject ? filenameSD : filenameSave)) { - if (isInject) { - mkdir(filenameSave, 0700); - if (R_FAILED(fsdevCommitDevice(SAVE_DEV))) - printf("Failed to commit directory %s.", filenameSave); - } else - mkdir(filenameSD, 0700); - s32 res = copyAllSave(filename, isInject, exInjDir); - if (res != 0) - return res; - } else { + if (isDirectory(isInject ? filenameSD : filenameSave)) + { + if (isInject) + { + mkdir(filenameSave, 0700); + if (R_FAILED(fsdevCommitDevice(SAVE_DEV))) + printf("Failed to commit directory %s.", filenameSave); + } + else + mkdir(filenameSD, 0700); + s32 res = copyAllSave(filename, isInject, exInjDir); + if (res != 0) + return res; + } + else + { printf("Copying %s... ", filename); - if (isInject) { + if (isInject) + { cpFile(std::string(filenameSD), std::string(filenameSave)); - if (R_SUCCEEDED(fsdevCommitDevice(SAVE_DEV))) { // Thx yellows8 - printf("committed.\n"); - } else { - printf("fsdevCommitDevice() failed...\n"); - return -2; + if (R_SUCCEEDED(fsdevCommitDevice(SAVE_DEV))) + { // Thx yellows8 + printf("committed.\n"); + } + else + { + printf("fsdevCommitDevice() failed...\n"); + return -2; } - } else { + } + else + { cpFile(std::string(filenameSave), std::string(filenameSD)); printf("\n"); } @@ -301,24 +346,28 @@ s32 copyAllSave(const char * path, bool isInject, const char exInjDir[0x100]) { } } -s32 backupSave(u64 titleID, AccountUid userID, bool fromBatch, std::string backupName) { +s32 backupSave(u64 titleID, AccountUid userID, bool fromBatch, std::string backupName) +{ FsFileSystem fs; s32 res = 0; - if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) { + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { printf("Failed to mount save.\n"); return 1; } char *ptr = new char[0x100]; - if(!makeExInjDir(ptr, titleID, userID, false, nullptr, fromBatch, backupName)) { + if (!makeExInjDir(ptr, titleID, userID, false, nullptr, fromBatch, backupName)) + { fsdevUnmountDevice(SAVE_DEV); delete[] ptr; return 2; } - if (ptr == nullptr) { + if (ptr == nullptr) + { printf("makeExInjDir failed.\n"); fsdevUnmountDevice(SAVE_DEV); delete[] ptr; @@ -333,16 +382,19 @@ s32 backupSave(u64 titleID, AccountUid userID, bool fromBatch, std::string backu return res; } -s32 restoreSave(u64 titleID, AccountUid userID, const char* path) { +s32 restoreSave(u64 titleID, AccountUid userID, const char *path) +{ FsFileSystem fs; s32 res = 0; - if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) { + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { printf("Failed to mount save.\n"); return 1; } - if (path == nullptr) { + if (path == nullptr) + { printf("makeExInjDir failed.\n"); fsdevUnmountDevice(SAVE_DEV); return 2; @@ -350,7 +402,8 @@ s32 restoreSave(u64 titleID, AccountUid userID, const char* path) { res = deleteDirRecursively("save:/", true); - if (!res) { + if (!res) + { printf("Deleting save:/ failed: %d.\n", res); return 3; } @@ -362,11 +415,13 @@ s32 restoreSave(u64 titleID, AccountUid userID, const char* path) { return res; } -s32 loadSaveFile(std::vector *buffer, size_t *length, u64 titleID, AccountUid userID, const char *path) { +s32 loadSaveFile(std::vector *buffer, size_t *length, u64 titleID, AccountUid userID, const char *path) +{ FsFileSystem fs; size_t size; - if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) { + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { printf("Failed to mount save.\n"); fsdevUnmountDevice(SAVE_DEV); fsFsClose(&fs); @@ -378,10 +433,10 @@ s32 loadSaveFile(std::vector *buffer, size_t *length, u64 titleID, AccountUi strcpy(filePath, "save:/"); strcat(filePath, path); - FILE *file = fopen(filePath, "rb"); - if (file == nullptr) { + if (file == nullptr) + { printf("Failed to open file.\n"); fsdevUnmountDevice(SAVE_DEV); fsFsClose(&fs); @@ -392,7 +447,8 @@ s32 loadSaveFile(std::vector *buffer, size_t *length, u64 titleID, AccountUi size = ftell(file); rewind(file); - if (size <= 0) { + if (size <= 0) + { printf("File reading failed. File length is %zu.\n", size); fclose(file); fsdevUnmountDevice(SAVE_DEV); @@ -411,10 +467,12 @@ s32 loadSaveFile(std::vector *buffer, size_t *length, u64 titleID, AccountUi return 0; } -s32 storeSaveFile(u8 *buffer, size_t length, u64 titleID, AccountUid userID, const char *path) { +s32 storeSaveFile(u8 *buffer, size_t length, u64 titleID, AccountUid userID, const char *path) +{ FsFileSystem fs; - if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) { + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { printf("Failed to mount save.\n"); fsdevUnmountDevice(SAVE_DEV); fsFsClose(&fs); @@ -426,10 +484,10 @@ s32 storeSaveFile(u8 *buffer, size_t length, u64 titleID, AccountUid userID, con strcpy(filePath, "save:/"); strcat(filePath, path); - FILE *file = fopen(filePath, "wb"); - if (file == nullptr) { + if (file == nullptr) + { printf("Failed to open file.\n"); fsdevUnmountDevice(SAVE_DEV); fsFsClose(&fs); @@ -439,7 +497,8 @@ s32 storeSaveFile(u8 *buffer, size_t length, u64 titleID, AccountUid userID, con fwrite(buffer, length, 1, file); fclose(file); - if (R_FAILED(fsdevCommitDevice(SAVE_DEV))) { + if (R_FAILED(fsdevCommitDevice(SAVE_DEV))) + { printf("Committing failed.\n"); return -3; } diff --git a/source/main.cpp b/source/main.cpp index 64664518..6d909ad1 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -24,22 +24,23 @@ #include "helpers/util.h" #include "helpers/config.hpp" -#define LONG_PRESS_DELAY 2 -#define LONG_PRESS_ACTIVATION_DELAY 300 +#define LONG_PRESS_DELAY 2 +#define LONG_PRESS_ACTIVATION_DELAY 300 -char* g_edizonPath; +char *g_edizonPath; static int debugOutputFile; static bool updateThreadRunning = false; static Mutex mutexCurrGui; -static Gui* currGui = nullptr; +static Gui *currGui = nullptr; static s64 inputTicker = 0; static u32 kheld = 0, kheldOld = 0; static u32 kdown = 0; -void initTitles() { +void initTitles() +{ std::vector saveInfoList; _getSaveList(saveInfoList); @@ -52,34 +53,41 @@ void initTitles() { AccountUid userIDs[userCount]; accountListAllUsers(userIDs, userCount, &foundUserCount); - for (auto saveInfo : saveInfoList) { + for (auto saveInfo : saveInfoList) + { bool accountPresent = false; for (s32 i = 0; i < foundUserCount; i++) if (userIDs[i] == saveInfo.uid) accountPresent = true; - if (!accountPresent) continue; + if (!accountPresent) + continue; if (Title::g_titles.find(saveInfo.application_id) == Title::g_titles.end()) Title::g_titles.insert({(u64)saveInfo.application_id, new Title(saveInfo)}); Title::g_titles[saveInfo.application_id]->addUserID(saveInfo.uid); - if (Account::g_accounts.find(saveInfo.uid) == Account::g_accounts.end()) { - Account *account = new Account(saveInfo.uid); + if (Account::g_accounts.find(saveInfo.uid) == Account::g_accounts.end()) + { + Account *account = new Account(saveInfo.uid); - if (!account->isInitialized()) { + if (!account->isInitialized()) + { delete account; continue; } Account::g_accounts.insert(std::make_pair(static_cast(saveInfo.uid), account)); } + // break; //hack } } -void update() { - while (updateThreadRunning) { +void update() +{ + while (updateThreadRunning) + { auto begin = std::chrono::steady_clock::now(); mutexLock(&mutexCurrGui); @@ -87,14 +95,17 @@ void update() { currGui->update(); mutexUnlock(&mutexCurrGui); - if (kheld & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN)) inputTicker++; - else inputTicker = 0; + if (kheld & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN)) + inputTicker++; + else + inputTicker = 0; svcSleepThread(1.0E6 - std::chrono::duration(std::chrono::steady_clock::now() - begin).count()); } } -void createFolders() { +void createFolders() +{ printf(EDIZON_DIR "/saves\n"); mkdir("/switch", 0777); mkdir(EDIZON_DIR "", 0777); @@ -107,12 +118,14 @@ void createFolders() { mkdir(EDIZON_DIR "/editor/scripts/lib/python3.5", 0777); } -void requestDraw() { +void requestDraw() +{ if (currGui != nullptr) currGui->draw(); } -void serviceInitialize() { +void serviceInitialize() +{ setsysInitialize(); socketInitializeDefault(); nsInitialize(); @@ -138,7 +151,8 @@ void serviceInitialize() { accountGetLastOpenedUser(&Account::g_activeUser); } -void serviceExit() { +void serviceExit() +{ setsysExit(); socketExit(); nsExit(); @@ -155,15 +169,16 @@ void serviceExit() { curl_global_cleanup(); close(debugOutputFile); - } -void redirectStdio() { +void redirectStdio() +{ nxlinkStdio(); debugOutputFile = open(EDIZON_DIR "/EdiZon.log", O_APPEND | O_WRONLY); - if (debugOutputFile >= 0) { + if (debugOutputFile >= 0) + { fflush(stdout); dup2(debugOutputFile, STDOUT_FILENO); fflush(stderr); @@ -171,7 +186,8 @@ void redirectStdio() { } } -int main(int argc, char** argv) { +int main(int argc, char **argv) +{ void *haddr; serviceInitialize(); @@ -193,7 +209,14 @@ int main(int argc, char** argv) { Config::readConfig(); - Gui::g_nextGui = GUI_MAIN; + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; + if (l_debugger->getRunningApplicationPID() != 0) + { + Gui::g_splashDisplayed = true; + Gui::g_nextGui = GUI_CHEATS; + } + else + Gui::g_nextGui = GUI_MAIN; if (isServiceRunning("tx") && !isServiceRunning("rnx") && !Config::getConfig()->hideSX) Gui::g_nextGui = GUI_TX_WARNING; @@ -206,63 +229,72 @@ int main(int argc, char** argv) { updateThreadRunning = true; std::thread updateThread(update); - - while (appletMainLoop()) { + while (appletMainLoop()) + { hidScanInput(); kheld = hidKeysHeld(CONTROLLER_P1_AUTO); kdown = hidKeysDown(CONTROLLER_P1_AUTO); - if (Gui::g_nextGui != GUI_INVALID) { + if (Gui::g_nextGui != GUI_INVALID) + { mutexLock(&mutexCurrGui); - if (currGui != nullptr) { + if (currGui != nullptr) + { delete currGui; currGui = nullptr; } - do { + do + { gui_t nextGuiStart = Gui::g_nextGui; - switch (Gui::g_nextGui) { - case GUI_MAIN: - currGui = new GuiMain(); - break; - case GUI_EDITOR: - currGui = new GuiEditor(); - break; - case GUI_TX_WARNING: - currGui = new GuiTXWarning(); - break; - case GUI_CHEATS: - currGui = new GuiCheats(); - break; - case GUI_GUIDE: - currGui = new GuiGuide(); - break; - case GUI_ABOUT: - currGui = new GuiAbout(); - break; - - case GUI_INVALID: [[fallthrough]] - default: break; + switch (Gui::g_nextGui) + { + case GUI_MAIN: + currGui = new GuiMain(); + break; + case GUI_EDITOR: + currGui = new GuiEditor(); + break; + case GUI_TX_WARNING: + currGui = new GuiTXWarning(); + break; + case GUI_CHEATS: + currGui = new GuiCheats(); + break; + case GUI_GUIDE: + currGui = new GuiGuide(); + break; + case GUI_ABOUT: + currGui = new GuiAbout(); + break; + + case GUI_INVALID: + [[fallthrough]] default : break; } if (nextGuiStart == Gui::g_nextGui) Gui::g_nextGui = GUI_INVALID; - } while(Gui::g_nextGui != GUI_INVALID); + } while (Gui::g_nextGui != GUI_INVALID); mutexUnlock(&mutexCurrGui); } - if (currGui != nullptr) { + if (currGui != nullptr) + { currGui->draw(); - if (Gui::g_splashDisplayed) { - if (inputTicker > LONG_PRESS_ACTIVATION_DELAY && (inputTicker % LONG_PRESS_DELAY) == 0) { + if (Gui::g_splashDisplayed) + { + if (inputTicker > LONG_PRESS_ACTIVATION_DELAY && (inputTicker % LONG_PRESS_DELAY) == 0) + { if (Gui::g_currMessageBox != nullptr) Gui::g_currMessageBox->onInput(kheld); else if (Gui::g_currListSelector != nullptr) Gui::g_currListSelector->onInput(kheld); else currGui->onInput(kheld); - } else if (kdown || hidKeysUp(CONTROLLER_P1_AUTO)) { + } + else if (kdown || hidKeysUp(CONTROLLER_P1_AUTO)) + { if (Gui::g_currMessageBox != nullptr) Gui::g_currMessageBox->onInput(kdown); else if (Gui::g_currListSelector != nullptr) @@ -273,7 +305,8 @@ int main(int argc, char** argv) { } } - if (kheld != kheldOld) { + if (kheld != kheldOld) + { inputTicker = 0; } @@ -286,11 +319,13 @@ int main(int argc, char** argv) { if (touchCount > 0) hidTouchRead(&touchPosCurr, 0); - if(touchCount > 0 && touchCountOld == 0) + if (touchCount > 0 && touchCountOld == 0) hidTouchRead(&touchPosStart, 0); - if (abs(static_cast(touchPosStart.px - touchPosCurr.px)) < 10 && abs(static_cast(touchPosStart.py - touchPosCurr.py)) < 10) { - if (touchCount == 0 && touchCountOld > 0) { + if (abs(static_cast(touchPosStart.px - touchPosCurr.px)) < 10 && abs(static_cast(touchPosStart.py - touchPosCurr.py)) < 10) + { + if (touchCount == 0 && touchCountOld > 0) + { touchHappend = true; if (Gui::g_currMessageBox != nullptr) @@ -300,7 +335,9 @@ int main(int argc, char** argv) { else currGui->onTouch(touchPosCurr); } - } else if (touchCount > 0) { + } + else if (touchCount > 0) + { if (Gui::g_currMessageBox != nullptr) Gui::g_currMessageBox->onGesture(touchPosStart, touchPosCurr, false); else if (Gui::g_currListSelector != nullptr) @@ -309,7 +346,8 @@ int main(int argc, char** argv) { currGui->onGesture(touchPosStart, touchPosCurr, false); } - if (touchCount == 0 && touchCountOld > 0 && !touchHappend) { + if (touchCount == 0 && touchCountOld > 0 && !touchHappend) + { if (Gui::g_currMessageBox != nullptr) Gui::g_currMessageBox->onGesture(touchPosStart, touchPosCurr, true); else if (Gui::g_currListSelector != nullptr) @@ -324,7 +362,8 @@ int main(int argc, char** argv) { kheldOld = kheld; - if (Gui::g_requestExit) { + if (Gui::g_requestExit) + { if (Gui::g_currMessageBox == nullptr) break; } From 3188b73ae03be923c5574053471dc6cdb2ace161 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 19 Jul 2020 23:04:18 +0800 Subject: [PATCH 02/95] fixed the typo TID vs PID --- source/guis/gui_cheats.cpp | 2 +- source/helpers/save.cpp | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index d9137d66..0e34e92d 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -885,7 +885,7 @@ void GuiCheats::onInput(u32 kdown) if (m_debugger->getRunningApplicationPID() == 0) return; - +// BM1 if (m_searchMenuLocation == SEARCH_POINTER) { if (kdown & KEY_UP) diff --git a/source/helpers/save.cpp b/source/helpers/save.cpp index 098302f7..e12c25d5 100644 --- a/source/helpers/save.cpp +++ b/source/helpers/save.cpp @@ -7,7 +7,6 @@ #include "helpers/account.hpp" #include "helpers/title.hpp" #include "helpers/debugger.hpp" - using json = nlohmann::json; s32 deleteDirRecursively(const char *path, bool isSave) @@ -160,9 +159,7 @@ Result _getSaveList(std::vector &saveInfoList) FsSaveDataInfoReader iterator; s64 total_entries = 0; FsSaveDataInfo info; - Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; - u64 runningid = l_debugger->getRunningApplicationPID(); - + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. if (R_FAILED(rc)) { @@ -175,20 +172,17 @@ Result _getSaveList(std::vector &saveInfoList) return rc; if (total_entries == 0) return MAKERESULT(Module_Libnx, LibnxError_NotFound); + for (; R_SUCCEEDED(rc) && total_entries > 0; rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries)) { - if (runningid == 0) + if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationTID())) // hacked to get only the running title { - if (info.save_data_type == FsSaveDataType_Account) // hacked to get only the running title if using cheat engine - { - saveInfoList.push_back(info); - } + saveInfoList.push_back(info); } - if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationPID())) // hacked to get only the running title if using cheat engine + else if ((info.save_data_type == FsSaveDataType_Account) && (l_debugger->getRunningApplicationTID() == 0)) // hacked to get only the running title { saveInfoList.push_back(info); - printf("has hit for title\n"); } } From dfb27b6f3d10281977f438d21a78666550c238cc Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 20 Jul 2020 09:46:09 +0800 Subject: [PATCH 03/95] go --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 823ea9ba..322a6906 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 0 +VERSION_MICRO := 2 NIGHTLY := APP_TITLE := EdiZon SE From 90df6cc6cb33666710b28892489cd2802853c341 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 20 Jul 2020 09:46:38 +0800 Subject: [PATCH 04/95] go --- source/guis/gui_cheats.cpp | 4 +- source/guis/gui_cheats.cpp1 | 3309 +++++++++++++++++++++++++++++++++++ source/guis/gui_main.cpp | 2 +- source/helpers/diff | 32 +- source/helpers/save.cpp | 2 +- source/helpers/save.cpp2 | 508 ++++++ source/main.cpp | 2 +- source/main.cpp1 | 357 ++++ 8 files changed, 4195 insertions(+), 21 deletions(-) create mode 100644 source/guis/gui_cheats.cpp1 create mode 100644 source/helpers/save.cpp2 create mode 100644 source/main.cpp1 diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 0e34e92d..0558b69d 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -885,7 +885,7 @@ void GuiCheats::onInput(u32 kdown) if (m_debugger->getRunningApplicationPID() == 0) return; -// BM1 + if (m_searchMenuLocation == SEARCH_POINTER) { if (kdown & KEY_UP) @@ -3227,7 +3227,7 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc pointersearch(newtargetaddress, pointerchain); } } - + return; // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); diff --git a/source/guis/gui_cheats.cpp1 b/source/guis/gui_cheats.cpp1 new file mode 100644 index 00000000..1e85aa0e --- /dev/null +++ b/source/guis/gui_cheats.cpp1 @@ -0,0 +1,3309 @@ +#include "guis/gui_cheats.hpp" + +#include +#include +#include + +#include +#include + +#include "helpers/util.h" + +#include "edizon_logo_bin.h" + +#define MAX_BUFFER_SIZE 0x1000000 // increase size for faster speed + +static const std::vector dataTypes = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr"}; +static const std::vector dataTypeSizes = {1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8}; +static const std::vector dataTypeMaxValues = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; +static const std::vector dataTypeMinValues = {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()}; + +static std::string titleNameStr, tidStr, pidStr, buildIDStr; + +static u32 cheatListOffset = 0; + +static bool _isAddressFrozen(uintptr_t); +static std::string _getAddressDisplayString(u64, Debugger *debugger, searchType_t searchType); +static std::string _getValueDisplayString(searchValue_t searchValue, searchType_t searchType); +static void _moveLonelyCheats(u8 *buildID, u64 titleID); +static bool _wrongCheatsPresent(u8 *buildID, u64 titleID); + +GuiCheats::GuiCheats() : Gui() +{ + + // Check if dmnt:cht is running and we're not on sxos + m_sysmodulePresent = isServiceRunning("dmnt:cht") && !(isServiceRunning("tx") && !isServiceRunning("rnx")); + + m_debugger = new Debugger(); + m_cheats = nullptr; + m_memoryDump = nullptr; + // start mod bookmark; + m_memoryDumpBookmark = nullptr; + m_memoryDump1 = nullptr; + m_pointeroffsetDump = nullptr; + + m_searchValue[0]._u64 = 0; + m_searchValue[1]._u64 = 0; + m_searchType = SEARCH_TYPE_NONE; + m_searchMode = SEARCH_MODE_NONE; + m_searchRegion = SEARCH_REGION_NONE; + + m_cheatCnt = 0; + + if (!m_sysmodulePresent) + return; + + dmntchtInitialize(); + dmntchtForceOpenCheatProcess(); + + DmntCheatProcessMetadata metadata; + dmntchtGetCheatProcessMetadata(&metadata); + + m_addressSpaceBaseAddr = metadata.address_space_extents.base; + m_addressSpaceSize = metadata.address_space_extents.size; + m_heapBaseAddr = metadata.heap_extents.base; + m_mainBaseAddr = metadata.main_nso_extents.base; + m_EditorBaseAddr = m_heapBaseAddr; + + m_heapSize = metadata.heap_extents.size; + m_mainSize = metadata.main_nso_extents.size; + + if (m_mainBaseAddr < m_heapBaseAddr) + { + m_low_main_heap_addr = m_mainBaseAddr; + m_high_main_heap_addr = m_heapBaseAddr + m_heapSize; + } + else + { + m_low_main_heap_addr = m_heapBaseAddr; + m_high_main_heap_addr = m_mainBaseAddr + m_mainSize; + } + + memcpy(m_buildID, metadata.main_nso_build_id, 0x20); + + _moveLonelyCheats(m_buildID, m_debugger->getRunningApplicationTID()); + + dmntchtGetCheatCount(&m_cheatCnt); + + if (m_cheatCnt > 0) + { + m_cheats = new DmntCheatEntry[m_cheatCnt]; + dmntchtGetCheats(m_cheats, m_cheatCnt, 0, &m_cheatCnt); + } + else if (_wrongCheatsPresent(m_buildID, m_debugger->getRunningApplicationTID())) + m_cheatsPresent = true; + + u64 frozenAddressCnt = 0; + dmntchtGetFrozenAddressCount(&frozenAddressCnt); + + if (frozenAddressCnt != 0) + { + DmntFrozenAddressEntry frozenAddresses[frozenAddressCnt]; + dmntchtGetFrozenAddresses(frozenAddresses, frozenAddressCnt, 0, nullptr); + + for (u16 i = 0; i < frozenAddressCnt; i++) + m_frozenAddresses.insert({frozenAddresses[i].address, frozenAddresses[i].value.value}); + } + + MemoryInfo meminfo = {0}; + u64 lastAddr = 0; + + do + { + lastAddr = meminfo.addr; + meminfo = m_debugger->queryMemory(meminfo.addr + meminfo.size); + + m_memoryInfo.push_back(meminfo); + } while (lastAddr < meminfo.addr + meminfo.size); + + for (MemoryInfo meminfo : m_memoryInfo) + { + if (m_mainBaseAddr == 0x00 && (meminfo.type == MemType_CodeStatic)) + m_mainBaseAddr = meminfo.addr; + + for (u64 addrOffset = meminfo.addr; addrOffset < meminfo.addr + meminfo.size; addrOffset += 0x20000000) + { + switch (meminfo.type) + { + case MemType_CodeStatic: + case MemType_CodeMutable: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0xFF, 0x00, 0x00, 0xFF); + break; + case MemType_SharedMem: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x00, 0xFF, 0x00, 0xFF); + break; + case MemType_Heap: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x00, 0x00, 0xFF, 0xFF); + break; + case MemType_KernelStack: + case MemType_ThreadLocal: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0xFF, 0xFF, 0x00, 0xFF); + break; + case MemType_Unmapped: + break; + default: + m_memory[addrOffset / 0x20000000] = Gui::makeColor(0x80, 0x80, 0x80, 0xFF); + break; + } + } + } + + //BM Begin pointer search init + + // MemoryDump *m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, false); + // m_pointeroffsetDump->setPointerSearchParams(m_max_depth, m_numoffset, m_maxrange, m_buildID); + + m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::UNDEFINED, false); + // start mod make list of memory found toggle between current find and bookmark + m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, false); + m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, false); + // end mod + + if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDump->getDumpInfo().heapBaseAddress != m_heapBaseAddr) + { + m_memoryDump->clear(); + + remove(EDIZON_DIR "/memdump2.dat"); + remove(EDIZON_DIR "/memdump3.dat"); + + m_searchType = SEARCH_TYPE_NONE; + m_searchRegion = SEARCH_REGION_NONE; + m_searchValue[0]._u64 = 0; + m_searchValue[1]._u64 = 0; + } + else + { + m_searchType = m_memoryDump->getDumpInfo().searchDataType; + m_searchRegion = m_memoryDump->getDumpInfo().searchRegion; + m_searchMode = m_memoryDump->getDumpInfo().searchMode; + m_searchValue[0] = m_memoryDump->getDumpInfo().searchValue[0]; + m_searchValue[1] = m_memoryDump->getDumpInfo().searchValue[1]; + } + + m_memoryDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + + // start mod bookmark + + if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDumpBookmark->getDumpInfo().heapBaseAddress != m_heapBaseAddr) + { + m_memoryDumpBookmark->clear(); + m_AttributeDumpBookmark->clear(); + delete m_memoryDumpBookmark; + delete m_AttributeDumpBookmark; + m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, true); + m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, true); + m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + m_AttributeDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + // m_memoryDumpBookmark->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); + } + else + m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + // end mod + std::stringstream ss; + + // check this + printf("%s\n", "before part"); + if (m_debugger->getRunningApplicationTID() != 0) + { + if (Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName().length() < 24) + ss << Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName(); + else + ss << Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName().substr(0, 21) << "..."; + titleNameStr = ss.str(); + ss.str(""); + } + else + titleNameStr = "Unknown title name!"; + printf("%s\n", "after part"); + ss << "TID: " << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + tidStr = ss.str(); + ss.str(""); + + ss << "PID: " << std::dec << m_debugger->getRunningApplicationPID(); + pidStr = ss.str(); + ss.str(""); + + ss << "BID: "; + for (u8 i = 0; i < 8; i++) + ss << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + + buildIDStr = ss.str(); + + if (m_cheatCnt == 0) + m_menuLocation = CANDIDATES; + if (m_memoryDump->size() == 0) + m_menuLocation = CHEATS; + + appletSetMediaPlaybackState(true); +} + +GuiCheats::~GuiCheats() +{ + + if (m_debugger != nullptr) + { + delete m_debugger; + } + + if (m_memoryDump1 != nullptr) + delete m_memoryDump1; + + if (m_memoryDumpBookmark != nullptr) + delete m_memoryDumpBookmark; + + if (m_cheats != nullptr) + delete[] m_cheats; + + if (m_sysmodulePresent) + { + dmntchtExit(); + } + + setLedState(false); + appletSetMediaPlaybackState(false); + + printf("%s\n", "~GuiCheats()"); +} + +void GuiCheats::update() +{ + Gui::update(); +} + +void GuiCheats::draw() +{ + static u32 splashCnt = 0; + std::stringstream ss; + + Gui::beginDraw(); + +#if SPLASH_ENABLED + + if (!Gui::g_splashDisplayed) + { + Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x5D, 0x4F, 0x4E, 0xFF)); + Gui::drawImage(Gui::g_framebuffer_width / 2 - 128, Gui::g_framebuffer_height / 2 - 128, 256, 256, edizon_logo_bin, IMAGE_MODE_BGR24); + + if (splashCnt++ >= 70) + Gui::g_splashDisplayed = true; + + Gui::endDraw(); + return; + } + +#endif + + Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, currTheme.backgroundColor); + + Gui::drawRectangle((u32)((Gui::g_framebuffer_width - 1220) / 2), Gui::g_framebuffer_height - 73, 1220, 1, currTheme.textColor); + + if (m_debugger->getRunningApplicationPID() == 0) + { + Gui::drawTextAligned(fontHuge, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 - 100, currTheme.textColor, "\uE12C", ALIGNED_CENTER); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2, currTheme.textColor, "A title needs to be running in the background to use the RAM editor. \n Please launch an application and try again.", ALIGNED_CENTER); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E1 Back", ALIGNED_RIGHT); + Gui::endDraw(); + return; + } + else if (!m_sysmodulePresent) + { + Gui::drawTextAligned(fontHuge, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 - 100, currTheme.textColor, "\uE142", ALIGNED_CENTER); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2, currTheme.textColor, "EdiZon depends on Atmosphere's dmnt:cht service which doesn't seem to be \n running on this device. Please install a supported CFW to \n use the cheat engine.", ALIGNED_CENTER); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E1 Back", ALIGNED_RIGHT); + Gui::endDraw(); + return; + } + + if (m_memoryDump1 == nullptr) + { + if (m_memoryDump->size() == 0) + { + if (m_frozenAddresses.size() != 0) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Frozen es \uE0E3 Search RAM \uE0E1 Back", ALIGNED_RIGHT); + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E3 Search RAM \uE0E1 Back", ALIGNED_RIGHT); + // Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 E4 \uE0E5 E5 \uE0E6 E6 \uE0E7 E7 \uE0E8 E8 \uE0E9 E9 \uE0EA EA \uE0EF EF \uE0F0 F0 \uE0F1 F1 \uE0F2 F2 \uE0F3 F3 \uE0F4 F4 \uE0F5 F5 ", ALIGNED_RIGHT); + // Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E1 E1 \uE0E0 E0 \uE0E1 E1 \uE0E2 E2 \uE0E3 E3 \uE0D9 D9 \uE0DA DA \uE0DF DF \uE0F0 F0 \uE0F6 F6 \uE0F7 F7 \uE0F8 F8 \uE0F9 F9 \uE0FA FA ", ALIGNED_RIGHT); + } + else + { + if (m_memoryDump->size() > 0) + { + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0F0 Reset search \uE0E3 Search again \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Back", ALIGNED_RIGHT); + } + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Reset search \uE0E1 Back", ALIGNED_RIGHT); + } + } + else + { + if (m_memoryDumpBookmark->size() > 0) + { + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM label \uE0E3 Delete BM \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Back", ALIGNED_RIGHT); + } + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E1 Back", ALIGNED_RIGHT); + } + + Gui::drawRectangle(256, 50, Gui::g_framebuffer_width - 256, 206, currTheme.separatorColor); + + // Don't draw icon + if (m_debugger->getRunningApplicationTID() != 0) + Gui::drawImage(0, 0, 256, 256, Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleIcon(), IMAGE_MODE_RGB24); + else + Gui::drawRectangle(0, 0, 256, 256, Gui::makeColor(0x00, 0x00, 0xFF, 0xFF)); + + Gui::drawRectangle(660, 65, 20, 20, Gui::makeColor(0xFF, 0x00, 0x00, 0xFF)); // Code + Gui::drawRectangle(660, 85, 20, 20, Gui::makeColor(0x00, 0xFF, 0x00, 0xFF)); // Shared Memory + Gui::drawRectangle(660, 105, 20, 20, Gui::makeColor(0x00, 0x00, 0xFF, 0xFF)); // Heap + Gui::drawRectangle(660, 125, 20, 20, Gui::makeColor(0xFF, 0xFF, 0x00, 0xFF)); // Stack + Gui::drawRectangle(660, 145, 20, 20, Gui::makeColor(0x80, 0x80, 0x80, 0xFF)); // Others + + Gui::drawTextAligned(font14, 700, 62, currTheme.textColor, "Code", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 700, 82, currTheme.textColor, "Shared Memory", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 700, 102, currTheme.textColor, "Heap", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 700, 122, currTheme.textColor, "Stack", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); + + ss.str(""); + ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr + m_addressSpaceSize; + Gui::drawTextAligned(font14, 900, 75, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + ss.str(""); + ss << "HEAP : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr; + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr + m_heapSize; + Gui::drawTextAligned(font14, 900, 105, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + ss.str(""); + ss << "MAIN : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr; + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr + m_mainSize; + Gui::drawTextAligned(font14, 900, 135, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + + Gui::drawRectangle(256, 50, 394, 137, COLOR_WHITE); + + Gui::drawTextAligned(font20, 280, 70, COLOR_BLACK, titleNameStr.c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font14, 290, 110, COLOR_BLACK, tidStr.c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font14, 290, 130, COLOR_BLACK, pidStr.c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font14, 290, 150, COLOR_BLACK, buildIDStr.c_str(), ALIGNED_LEFT); + + if ((Account::g_activeUser.uid[0] != 0) && (Account::g_activeUser.uid[1] != 0)) + { + ss.str(""); + ss << Account::g_accounts[Account::g_activeUser]->getUserName() << " [ " << std::hex << (Account::g_activeUser.uid[1]) << " " << (Account::g_activeUser.uid[0]) << " ]"; + Gui::drawTextAligned(font20, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } + + if (m_cheatCnt > 0) + { + Gui::drawRectangle(50, 256, 650, 46 + std::min(static_cast(m_cheatCnt), 8U) * 40, currTheme.textColor); + Gui::drawTextAligned(font14, 375, 262, currTheme.backgroundColor, "Cheats", ALIGNED_CENTER); + Gui::drawShadow(50, 256, 650, 46 + std::min(static_cast(m_cheatCnt), 8U) * 40); + + for (u8 line = cheatListOffset; line < 8 + cheatListOffset; line++) + { + if (line >= m_cheatCnt) + break; + + ss.str(""); + ss << "\uE070 " << m_cheats[line].definition.readable_name; + + Gui::drawRectangle(52, 300 + (line - cheatListOffset) * 40, 646, 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); + Gui::drawTextAligned(font14, 70, 305 + (line - cheatListOffset) * 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + + if (!m_cheats[line].enabled) + { + color_t highlightColor = currTheme.highlightColor; + highlightColor.a = 0xFF; + + Gui::drawRectangled(74, 313 + (line - cheatListOffset) * 40, 10, 10, (m_selectedEntry == line && m_menuLocation == CHEATS) ? highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); + } + } + } + else if (m_cheatsPresent && m_memoryDump->size() == 0) + Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Cheats for this game present but title version or region doesn't match!", ALIGNED_CENTER); + + if (m_memoryDump->getDumpInfo().dumpType == DumpType::DATA) + { + if (m_memoryDump->size() > 0) + { + Gui::drawRectangle(Gui::g_framebuffer_width - 552, 256, 500, 366, currTheme.textColor); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, "Found candidates", ALIGNED_CENTER); + Gui::drawShadow(Gui::g_framebuffer_width - 552, 256, 500, 366 * 40); + Gui::drawRectangle(Gui::g_framebuffer_width - 550, 300, 496, 320, currTheme.separatorColor); + + ss.str(""); + ss << (static_cast(m_memoryDump->size()) / (0x100000)) << "MB dumped"; + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 302, 450, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } + } + else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + if (m_memoryDump->size() > 0) + { + if (m_memoryDump1 == nullptr) + { + Gui::drawRectangle(Gui::g_framebuffer_width - 552, 256, 500, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40, currTheme.textColor); + ss.str(""); + ss << "Found candidates " << std::dec << (((m_menuLocation == CANDIDATES) ? m_selectedEntry : 0) + m_addresslist_offset + 1) << " / " << std::dec << ((m_memoryDump->size() / sizeof(u64))); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, ss.str().c_str(), ALIGNED_CENTER); + Gui::drawShadow(Gui::g_framebuffer_width - 552, 256, 500, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40); + } + else + { + Gui::drawRectangle(Gui::g_framebuffer_width - 557, 256, 549, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40, currTheme.textColor); + ss.str(""); + ss << " Book Marks " << std::dec << (((m_menuLocation == CANDIDATES) ? m_selectedEntry : 0) + m_addresslist_offset + 1) << " / " << std::dec << ((m_memoryDump->size() / sizeof(u64))); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, ss.str().c_str(), ALIGNED_CENTER); + // Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 302, 262, currTheme.backgroundColor, "Book Marks", ALIGNED_CENTER); + Gui::drawShadow(Gui::g_framebuffer_width - 557, 256, 549, 46 + std::min(static_cast(m_memoryDump->size() / sizeof(u64)), 8U) * 40); + } + } + // mod start memory line offset + + if (m_memoryDump1 == nullptr) + for (u8 line = 0; line < 8; line++) + { + if ((line + m_addresslist_offset) >= (m_memoryDump->size() / sizeof(u64))) + break; + + ss.str(""); + + if (line < 8) // && (m_memoryDump->size() / sizeof(u64)) != 8) + { + u64 address = 0; + m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + // candidate display + if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().heapBaseAddress) << " ]"; + else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + ss << "[ MAIN + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().mainBaseAddress) << " ]"; + else + ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().addrSpaceBaseAddress) << " ]"; + + ss << " ( " << _getAddressDisplayString(address, m_debugger, (searchType_t)m_searchType) << " )"; + + if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) + ss << " \uE130"; + } + else + ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; + + Gui::drawRectangle(Gui::g_framebuffer_width - 550, 300 + line * 40, 496, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 530, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + } + else // Book mark screen + for (u8 line = 0; line < 8; line++) + { + if ((line + m_addresslist_offset) >= (m_memoryDump->size() / sizeof(u64))) + break; + + ss.str(""); + + bookmark_t bookmark; + if (line < 8) // && (m_memoryDump->size() / sizeof(u64)) != 8) + { + u64 address = 0; + m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + m_AttributeDumpBookmark->getData((line + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // bookmark display + + ss << "[0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << "]"; //<< std::left << std::setfill(' ') << std::setw(18) << bookmark.label << + + ss << " ( " << _getAddressDisplayString(address, m_debugger, (searchType_t)bookmark.type) << " )"; + + if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) + ss << " \uE130"; + } + else + ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; + + Gui::drawRectangle(Gui::g_framebuffer_width - 555, 300 + line * 40, 545, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 545, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, bookmark.label, ALIGNED_LEFT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 340, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + } + } + + Gui::drawShadow(0, 0, Gui::g_framebuffer_width, 256); + Gui::drawShadow(256, 50, Gui::g_framebuffer_width, 136); + + for (u16 x = 0; x < 1024; x++) + Gui::drawRectangle(256 + x, 0, 2, 50, m_memory[x]); + + drawSearchRAMMenu(); + drawEditRAMMenu(); + Gui::endDraw(); +} +// BM2 +void GuiCheats::drawEditRAMMenu() +{ + static u32 cursorBlinkCnt = 0; + u32 strWidth = 0; + std::stringstream ss; + + if (m_searchMenuLocation != SEARCH_editRAM) // need + return; + + Gui::drawRectangled(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x00, 0x00, 0x00, 0xA0)); + + Gui::drawRectangle(50, 50, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.backgroundColor); + Gui::drawRectangle(100, 135, Gui::g_framebuffer_width - 200, 1, currTheme.textColor); + Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Edit Memory"); + Gui::drawTextAligned(font20, 100, 160, currTheme.textColor, "\uE149 \uE0A4", ALIGNED_LEFT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, 160, currTheme.textColor, "\uE0A5 \uE14A", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, 260, 160, m_searchMenuLocation == SEARCH_TYPE ? currTheme.selectedColor : currTheme.textColor, "U8", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 510, 160, m_searchMenuLocation == SEARCH_MODE ? currTheme.selectedColor : currTheme.textColor, "U16", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 760, 160, m_searchMenuLocation == SEARCH_REGION ? currTheme.selectedColor : currTheme.textColor, "u32", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "u64", ALIGNED_CENTER); + + // strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + // ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().heapBaseAddress) << " ]"; + // std::stringstream ss; + // + // dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + // address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry -1 - (m_selectedEntry div 5))*4; + // m_selectedEntry = (m_EditorBaseAddr % 10) / 4 + 11; + u64 addr = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20; + u32 out; + + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + ss.str(""); + ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << " ]"; + Gui::drawText(font24, 520, 70, currTheme.textColor, ss.str().c_str()); + // Next to display the value in the selected type now is u32 in hex + ss.str(""); + dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; + Gui::drawText(font24, 820, 70, currTheme.textColor, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); //ss.str().c_str() + + for (u8 i = 0; i < 40; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(88 + (i % 5) * 225, 235 + (i / 5) * 50, 225, 50, m_searchMode == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + if ((i % 5) != 0) + { + Gui::drawRectangled(93 + (i % 5) * 225, 240 + (i / 5) * 50, 215, 40, currTheme.separatorColor); + ss.str(""); + dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; + Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + addr += 4; + } + else + { + ss.str(""); + ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr) << " ]"; + Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } + } +} + +void GuiCheats::drawSearchRAMMenu() +{ + static u32 cursorBlinkCnt = 0; + u32 strWidth = 0; + std::stringstream ss; + + if (m_searchMenuLocation == SEARCH_NONE) + return; + + Gui::drawRectangled(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x00, 0x00, 0x00, 0xA0)); + + Gui::drawRectangle(50, 50, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.backgroundColor); + Gui::drawRectangle(100, 135, Gui::g_framebuffer_width - 200, 1, currTheme.textColor); + Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Search Memory"); + + Gui::drawTextAligned(font20, 100, 160, currTheme.textColor, "\uE149 \uE0A4", ALIGNED_LEFT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, 160, currTheme.textColor, "\uE0A5 \uE14A", ALIGNED_RIGHT); + + Gui::drawTextAligned(font20, 260, 160, m_searchMenuLocation == SEARCH_TYPE ? currTheme.selectedColor : currTheme.textColor, "TYPE", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 510, 160, m_searchMenuLocation == SEARCH_MODE ? currTheme.selectedColor : currTheme.textColor, "MODE", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 760, 160, m_searchMenuLocation == SEARCH_REGION ? currTheme.selectedColor : currTheme.textColor, "REGION", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "VALUE", ALIGNED_CENTER); + + static const char *const typeNames[] = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "flt", "dbl", "void*"}; + static const char *const modeNames[] = {"==", "!=", ">", "StateB", "<", "StateA", "A..B", "SAME", "DIFF", "+ +", "- -", "PTR"}; + static const char *const regionNames[] = {"HEAP", "MAIN", "HEAP + MAIN", "RAM"}; + + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + for (u8 i = 0; i < 11; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(356 + (i / 2) * 100, 220 + (i % 2) * 100, 90, 90, m_searchType == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + + Gui::drawRectangled(361 + (i / 2) * 100, 225 + (i % 2) * 100, 80, 80, currTheme.separatorColor); + Gui::drawTextAligned(font20, 400 + (i / 2) * 100, 250 + (i % 2) * 100, currTheme.textColor, typeNames[i], ALIGNED_CENTER); + } + + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the data type of the value you’re searching here. The prefix [u] means unsigned (positive integers), [s] means \n" + "signed (positive and negative integers), [flt] is for floating point numbers (rational numbers), [dbl] is for double (bigger \n" + "rational numbers) and [void*] stands for pointer (link to another memory ) which is useful for creating cheats. The \n" + "number that follows is the number of bits used in memory which determines the maximum value. Choose the data type that \n" + "best fits for the type of data you’re looking for.", + ALIGNED_CENTER); + + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + + break; + case SEARCH_MODE: + for (u8 i = 0; i < 12; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(356 + (i / 2) * 100, 220 + (i % 2) * 100, 90, 90, m_searchMode == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + + Gui::drawRectangled(361 + (i / 2) * 100, 225 + (i % 2) * 100, 80, 80, currTheme.separatorColor); + Gui::drawTextAligned(font20, 400 + (i / 2) * 100, 250 + (i % 2) * 100, currTheme.textColor, modeNames[i], ALIGNED_CENTER); + } + + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the mode you want to use for finding values. With these modes EdiZon will search for values that are equal to [==], \n" + "not equal to [!=], greater than [>], greater than or equal to [>=], less than [<], or less than or equal to [<=] the value \n" + "that you input. [A : B] allows you to set a (min : max) range of values, SAME and DIFF search allows you to find values that \n" + "stayed the same or changed since the last search, [+ +] and [- -] checks for values that increased or decreased since the \n" + "previous search.", + ALIGNED_CENTER); + + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + break; + case SEARCH_REGION: + for (u8 i = 0; i < 4; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled((Gui::g_framebuffer_width / 2) - 155, 215 + i * 70, 310, 70, m_searchRegion == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + + Gui::drawRectangled((Gui::g_framebuffer_width / 2) - 150, 220 + i * 70, 300, 60, currTheme.separatorColor); + Gui::drawTextAligned(font20, (Gui::g_framebuffer_width / 2), 235 + i * 70, currTheme.textColor, regionNames[i], ALIGNED_CENTER); + } + + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the memory region you want to search in. HEAP contains dynamically allocated values and will be where the majority of \n" + "values worth changing will be found. MAIN contains global variables and instructions for game operation. You may find some \n" + "values here but it’s mainly for finding pointers to HEAP values or changing game code. RAM will search the entirety of the Games \n" + "used memory including memory shared memory and resources. Should only be used as a final resort as this will be extremely slow. \n", + ALIGNED_CENTER); + + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + break; + case SEARCH_VALUE: + Gui::drawTextAligned(font14, Gui::g_framebuffer_width / 2, 500, currTheme.textColor, "Set the value you want to search for. The value(s) you enter here will depend on what options you've chosen in the \n" + "first three sections. Either it's the exact integer you want to search for, a floating point number or even two values that \n" + "will be used as range.", + ALIGNED_CENTER); + + //Gui::drawRectangle(300, 250, Gui::g_framebuffer_width - 600, 80, currTheme.separatorColor); + Gui::drawRectangle(300, 327, Gui::g_framebuffer_width - 600, 3, currTheme.textColor); + if (m_searchValueFormat == FORMAT_DEC) + ss << _getValueDisplayString(m_searchValue[0], m_searchType); + else if (m_searchValueFormat == FORMAT_HEX) + ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u64; + + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 310, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + + // Start Mod for search Range display + if (cursorBlinkCnt++ % 20 > 10 && m_selectedEntry == 0 && (m_searchValueIndex == 0)) + Gui::drawRectangled(312 + strWidth, 285, 3, 35, currTheme.highlightColor); + + if (m_searchMode == SEARCH_MODE_RANGE) + { + ss.str(""); + if (m_searchValueFormat == FORMAT_DEC) + ss << _getValueDisplayString(m_searchValue[1], m_searchType); + else if (m_searchValueFormat == FORMAT_HEX) + ss << "0x" << std::uppercase << std::hex << m_searchValue[1]._u64; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 650, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + } + + if (cursorBlinkCnt++ % 20 > 10 && m_selectedEntry == 0 && (m_searchValueIndex == 1)) + Gui::drawRectangled(652 + strWidth, 285, 3, 35, currTheme.highlightColor); + // End Mod + + if (m_searchValueFormat == FORMAT_DEC) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E2 Hexadecimal view \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + else if (m_searchValueFormat == FORMAT_HEX) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E2 Decimal view \uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); + + if (m_selectedEntry == 1) + Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 155, 345, 310, 90, currTheme.highlightColor); + + if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) + { + Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedColor); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.backgroundColor, "Search Now!", ALIGNED_CENTER); + } + else + { + Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 150, 350, 300, 80, currTheme.selectedButtonColor); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 375, currTheme.separatorColor, "Search Now!", ALIGNED_CENTER); + } + + break; + case SEARCH_NONE: + break; + } +} + +void GuiCheats::onInput(u32 kdown) +{ + if (kdown & KEY_B) + { + + if (m_searchMenuLocation == SEARCH_NONE) + { + // Gui::g_nextGui = GUI_MAIN; + Gui::g_requestExit = true; + return; + } + else if (m_searchMenuLocation == SEARCH_editRAM) + { + m_searchMenuLocation = SEARCH_NONE; + } + else if (m_searchMenuLocation == SEARCH_TYPE) + { + if (m_searchType != SEARCH_TYPE_NONE && m_memoryDump->size() == 0) + m_searchType = SEARCH_TYPE_NONE; + else + m_searchMenuLocation = SEARCH_NONE; + } + else if (m_searchMenuLocation == SEARCH_MODE) + { + if (m_searchMode != SEARCH_MODE_NONE) + m_searchMode = SEARCH_MODE_NONE; + else + m_searchMenuLocation = SEARCH_NONE; + } + else if (m_searchMenuLocation == SEARCH_REGION) + { + if (m_searchRegion != SEARCH_REGION_NONE && m_memoryDump->size() == 0) + m_searchRegion = SEARCH_REGION_NONE; + else + m_searchMenuLocation = SEARCH_NONE; + } + else if (m_searchMenuLocation == SEARCH_VALUE) + m_searchMenuLocation = SEARCH_NONE; + } + + if (m_debugger->getRunningApplicationPID() == 0) + return; + + if (m_searchMenuLocation == SEARCH_NONE) + { + if (kdown & KEY_UP) + { + if (m_selectedEntry > 0) + m_selectedEntry--; + + if (m_menuLocation == CHEATS) + if (m_selectedEntry == cheatListOffset && cheatListOffset > 0) + cheatListOffset--; + } + + if (kdown & KEY_DOWN) // + { + if (m_menuLocation == CANDIDATES) + { + if (m_selectedEntry < 7 && m_selectedEntry + m_addresslist_offset < ((m_memoryDump->size() / sizeof(u64)) - 1)) + m_selectedEntry++; + } + else + { + if (m_selectedEntry < (m_cheatCnt - 1)) + m_selectedEntry++; + + if (m_selectedEntry == (cheatListOffset + 7) && cheatListOffset < (m_cheatCnt - 8)) + cheatListOffset++; + } + } + // start mod + if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS) + { + // m_searchMenuLocation = SEARCH_editRAM; + // printf("L Stick pressed, start pointer search *************\n"); + // startpointersearch(m_heapBaseAddr + 80, 10, 0x800, 3); + // printf("done pointer search ********************************\n"); + // printf("making a dump for pointers"); + // GuiCheats::searchMemoryAddressesPrimary(m_debugger, m_searchValue[0], m_searchValue[1], SEARCH_TYPE_UNSIGNED_64BIT, SEARCH_MODE_RANGE, SEARCH_REGION_HEAP_AND_MAIN, &m_memoryDump, m_memoryInfo); + + // m_menuLocation = CANDIDATES; + m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; + m_searchMode = SEARCH_MODE_POINTER; + m_searchRegion = SEARCH_REGION_HEAP_AND_MAIN; + m_searchMenuLocation = SEARCH_VALUE; + m_selectedEntry = 1; + m_searchValue[0]._u64 = 0x1000000000; + m_searchValue[1]._u64 = 0x8000000000; + } + + if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS) + { + printf("start checking pointer\n"); + pointercheck(); + } + // end mod + + if (m_memoryDump->size() > 0) + { + if (kdown & KEY_LEFT) + if (m_cheatCnt > 0) + { + m_menuLocation = CHEATS; + m_selectedEntry = 0; + cheatListOffset = 0; + } + + if (kdown & KEY_RIGHT) + { + m_menuLocation = CANDIDATES; + m_selectedEntry = 0; + cheatListOffset = 0; + } + } + + if (m_menuLocation == CANDIDATES) + { /* Candidates menu */ + if (m_memoryDump->size() > 0) + { + if (kdown & KEY_X && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + + if (!_isAddressFrozen(address)) + { + u64 outValue; + if (m_memoryDump1 == nullptr) + { + if (R_SUCCEEDED(dmntchtEnableFrozenAddress(address, dataTypeSizes[m_searchType], &outValue))) + { + (new Snackbar("Froze variable!"))->show(); + m_frozenAddresses.insert({address, outValue}); + } + else + (new Snackbar("Failed to freeze variable!"))->show(); + } + else + { + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + if (R_SUCCEEDED(dmntchtEnableFrozenAddress(address, dataTypeSizes[bookmark.type], &outValue))) + { + (new Snackbar("Froze variable!"))->show(); + m_frozenAddresses.insert({address, outValue}); + } + else + (new Snackbar("Failed to freeze variable!"))->show(); + } + } + else + { + if (R_SUCCEEDED(dmntchtDisableFrozenAddress(address))) + { + (new Snackbar("Unfroze variable!"))->show(); + m_frozenAddresses.erase(address); + } + else + (new Snackbar("Failed to unfreeze variable!"))->show(); + } + } + // add bookmark + if (kdown & KEY_PLUS && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); // prompt for label + printf("%s\n", "PLUS key pressed"); + } + // add bookmark end + // show memory editor + // BM1 + if (kdown & KEY_RSTICK && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_searchMenuLocation = SEARCH_editRAM; + m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; + } + if ((kdown & KEY_LSTICK) && (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR)) + { + printf("start pointer search ....................\n"); + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + printf("Address %lx \n\n\n", m_EditorBaseAddr); + m_Time1 = time(NULL); + // m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); + m_searchValue[0]._u64 = m_EditorBaseAddr - 0x800; + m_searchValue[1]._u64 = m_EditorBaseAddr; + startpointersearch(m_EditorBaseAddr); + printf("done pointer search \n"); + printf("Time taken =%d\n", time(NULL) - m_Time1); + + // m_EditorBaseAddr = static_cast(std::stoul(input, nullptr, 16)); + // m_searchMenuLocation = SEARCH_editRAM; + // m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; + } + // end + if (kdown & KEY_A && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + + if (m_selectedEntry < 8) + { + char input[16]; + char initialString[21]; + // start mod address content edit Hex option + + // + strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + if (Gui::requestKeyboardInput("Enter value", "Enter a value that should get written at this .", initialString, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, input, 18)) + { + if (m_searchValueFormat == FORMAT_HEX) + { + auto value = static_cast(std::stoul(input, nullptr, 16)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_32BIT) + { + auto value = static_cast(std::atof(input)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_64BIT) + { + auto value = std::atof(input); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType != SEARCH_TYPE_NONE) + { + auto value = std::atol(input); + m_debugger->writeMemory((void *)&value, dataTypeSizes[m_searchType], address); + } + } + } + else if ((m_memoryDump->size() / sizeof(u64)) < 25) + { + std::vector options; + options.clear(); + + std::stringstream ss; + for (u32 i = 7; i < (m_memoryDump->size() / sizeof(u64)); i++) + { //TODO: i? + m_memoryDump->getData(m_selectedEntry * sizeof(u64), &address, sizeof(u64)); + ss.str(""); + ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + + ss << " (" << _getAddressDisplayString(address, m_debugger, m_searchType); + + options.push_back(ss.str()); + printf("%s\n", ss.str().c_str()); + } + + (new ListSelector("Edit value at ", "\uE0E0 Edit value \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { + if (k & KEY_A) + { + char input[16]; + char initialString[21]; + u64 selectedAddress; + + m_memoryDump->getData((selectedItem + 7) * sizeof(u64), &selectedAddress, sizeof(u64)); + + strcpy(initialString, _getAddressDisplayString(selectedAddress, m_debugger, m_searchType).c_str()); + + if (Gui::requestKeyboardInput("Enter value", "Enter a value for which the game's memory should be searched.", initialString, SwkbdType::SwkbdType_NumPad, input, 15)) + { + u64 value = atol(input); + if (value > dataTypeMaxValues[m_searchType] || value < dataTypeMinValues[m_searchType]) + { + (new Snackbar("Entered value isn't inside the range of this data type. Please enter a different value."))->show(); + return; + } + + m_memoryDump->getData((m_selectedEntry) * sizeof(u64), &selectedAddress, sizeof(u64)); + m_debugger->pokeMemory(dataTypeSizes[m_searchType], selectedAddress, value); + } + } + }) + ->show(); + } + else + (new Snackbar("Too many addresses! Narrow down the selection before editing."))->show(); + } + } + } + else + { /* Cheats menu */ + if (kdown & KEY_A) + { + if (m_cheatCnt == 0) + return; + + dmntchtToggleCheat(m_cheats[m_selectedEntry].cheat_id); + u64 cheatCnt = 0; + + dmntchtGetCheatCount(&cheatCnt); + if (cheatCnt > 0) + { + delete[] m_cheats; + m_cheats = new DmntCheatEntry[cheatCnt]; + dmntchtGetCheats(m_cheats, cheatCnt, 0, &m_cheatCnt); + } + } + } + + if (kdown & KEY_MINUS) + { + //make sure not using bookmark m_searchType + if (m_memoryDump1 != nullptr) + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + } + m_addresslist_offset = 0; + // end mod + if (m_memoryDump->size() == 0) + { + std::vector options; + + if (m_frozenAddresses.size() == 0) + return; + + std::stringstream ss; + for (auto [addr, value] : m_frozenAddresses) + { + ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr - m_addressSpaceBaseAddr) << " ] "; + ss << "( " << std::dec << value << " )"; + options.push_back(ss.str()); + ss.str(""); + } + + (new ListSelector("Frozen Addresses", "\uE0E0 Unfreeze \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { + if (k & KEY_A) + { + auto itr = m_frozenAddresses.begin(); + std::advance(itr, selectedItem); + + dmntchtDisableFrozenAddress(itr->first); + m_frozenAddresses.erase(itr->first); + } + }) + ->show(); + } + else + { + m_memoryDump->clear(); + remove(EDIZON_DIR "/memdump1.dat"); + remove(EDIZON_DIR "/memdump1a.dat"); + remove(EDIZON_DIR "/memdump2.dat"); + remove(EDIZON_DIR "/memdump3.dat"); + + // m_searchType = SEARCH_TYPE_NONE; + // m_searchMode = SEARCH_MODE_NONE; + // m_searchRegion = SEARCH_REGION_NONE; + // m_searchValue[0]._u64 = 0; + // m_searchValue[1]._u64 = 0; + + m_menuLocation = CHEATS; + } + } + // start mod KEY_PLUS + // if (kdown & KEY_PLUS) { + // printf("%s\n","PLUS key pressed"); + // printf("%s\n",titleNameStr.c_str()); + // printf("%s\n",tidStr.c_str()); + // printf("%s\n",buildIDStr.c_str()); + // Gui::g_nextGui = GUI_MAIN; + // return; + // } + if (kdown & KEY_R) + { + if (m_searchValueFormat == FORMAT_HEX) + m_searchValueFormat = FORMAT_DEC; + else + m_searchValueFormat = FORMAT_HEX; + if (m_searchValueFormat == FORMAT_HEX) + printf("%s\n", "HEX"); + printf("%s\n", "R key pressed"); + } + if (kdown & KEY_L) //toggle bookmark view bookmark : (m_memoryDump1 != nullptr) + { + if (m_memoryDump1 == nullptr) + { + m_memoryDump1 = m_memoryDump; + m_memoryDump = m_memoryDumpBookmark; + m_addresslist_offset = 0; + //consider to remove later + if (m_searchType == SEARCH_TYPE_NONE) + m_searchType = SEARCH_TYPE_UNSIGNED_32BIT; // to make sure not blank + // end + // (new Snackbar("Switch to bookmark List!"))->show(); + printf("%s\n", "Bookmark"); + } + else + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + // (new Snackbar("Switch to Normal List!"))->show(); + } + printf("%s\n", "L key pressed"); + } + if (kdown & KEY_ZR) + { + m_addresslist_offset += 8; + if (m_addresslist_offset >= (m_memoryDump->size() / sizeof(u64))) + m_addresslist_offset -= 8; + if (m_selectedEntry + m_addresslist_offset + 1 > (m_memoryDump->size() / sizeof(u64))) + m_selectedEntry = (m_memoryDump->size() / sizeof(u64)) % 8 - 1; + // printf("%s\n", "ZR key pressed"); + } + + if (kdown & KEY_ZL) + { + if (m_addresslist_offset >= 8) + m_addresslist_offset -= 8; + // printf("%s\n", "ZL key pressed"); + } + + // End Mod + if (kdown & KEY_Y) + { + if (m_searchMenuLocation == SEARCH_NONE) + { + if (m_searchMode == SEARCH_MODE_NONE) + { + m_searchMenuLocation = SEARCH_MODE; + // m_selectedEntry = m_searchType == SEARCH_TYPE_NONE ? 0 : m_searchType; + } + else + m_searchMenuLocation = SEARCH_VALUE; + // auto toggle between stateA and stateB + if (m_searchMode == SEARCH_MODE_DIFFA) + { + m_searchMode = SEARCH_MODE_SAMEA; + m_selectedEntry = 1; + } + else if (m_searchMode == SEARCH_MODE_SAMEA) + { + m_searchMode = SEARCH_MODE_DIFFA; + m_selectedEntry = 1; + } + else + m_selectedEntry = 0; + + cheatListOffset = 0; + } + printf("%s\n", "Y key pressed"); + printf("%s\n", titleNameStr.c_str()); + printf("%s\n", tidStr.c_str()); + printf("%s\n", buildIDStr.c_str()); + //make sure not using bookmark + if (m_memoryDump1 != nullptr) + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + } + m_addresslist_offset = 0; + // end mod + } + } + else + { + if ((m_searchMenuLocation == SEARCH_TYPE && m_searchType == SEARCH_TYPE_NONE) || + (m_searchMenuLocation == SEARCH_MODE && m_searchMode == SEARCH_MODE_NONE) || + (m_searchMenuLocation == SEARCH_REGION && m_searchRegion == SEARCH_REGION_NONE) || + (m_searchMenuLocation == SEARCH_VALUE) || + (m_searchMenuLocation == SEARCH_editRAM)) + { + if (kdown & KEY_UP) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry % 2 == 1) + m_selectedEntry--; + break; + case SEARCH_REGION: + if (m_selectedEntry > 0) + m_selectedEntry--; + break; + case SEARCH_VALUE: + m_selectedEntry = 0; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need UP + if (m_selectedEntry > 4) + m_selectedEntry -= 5; + else + { + m_EditorBaseAddr -= 0x10; + } + + break; + } + } + + if (kdown & KEY_DOWN) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if ((m_selectedEntry + 1) < 12 && m_selectedEntry % 2 == 0) + m_selectedEntry++; + break; + case SEARCH_REGION: + if (m_selectedEntry < 3) + m_selectedEntry++; + break; + case SEARCH_VALUE: + if (m_searchType != SEARCH_TYPE_NONE && m_searchMode != SEARCH_MODE_NONE && m_searchRegion != SEARCH_REGION_NONE) + m_selectedEntry = 1; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need DOWN + if (m_selectedEntry < 35) + m_selectedEntry += 5; + else + { + m_EditorBaseAddr += 0x10; + } + + break; + } + } + + if (kdown & KEY_LEFT) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry >= 2) + m_selectedEntry -= 2; + break; + case SEARCH_REGION: + break; + case SEARCH_VALUE: + if (m_searchValueIndex == 1) + m_searchValueIndex--; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need LEFT + if (m_selectedEntry % 5 > 1) + m_selectedEntry--; + break; + } + } + + if (kdown & KEY_RIGHT) + { + switch (m_searchMenuLocation) + { + case SEARCH_TYPE: + [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry <= 9) + m_selectedEntry += 2; + break; + case SEARCH_REGION: + break; + case SEARCH_VALUE: + if (m_searchValueIndex == 0 && m_searchMode == SEARCH_MODE_RANGE) + m_searchValueIndex++; + break; + case SEARCH_NONE: + break; + case SEARCH_editRAM: // need RIGHT + if (m_selectedEntry % 5 < 4) + m_selectedEntry++; + break; + } + } + + if (m_searchMenuLocation == SEARCH_editRAM) + { + if (kdown & KEY_PLUS) + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + printf("%s\n", "PLUS key pressed"); + } + if (kdown & KEY_ZR) + { + m_EditorBaseAddr += 0x80; + } + if (kdown & KEY_ZL) + { + m_EditorBaseAddr -= 0x80; + } + if (kdown & KEY_R) + { + m_addressmod++; + m_addressmod = m_addressmod % 4; + } + if (kdown & KEY_L) + { + m_addressmod--; + m_addressmod = m_addressmod % 4; + } + if (kdown & KEY_X) + { + if (m_searchValueFormat == FORMAT_DEC) + m_searchValueFormat = FORMAT_HEX; + else + m_searchValueFormat = FORMAT_DEC; + } + if (kdown & KEY_Y) // BM9 + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + std::stringstream ss; + ss << "0x" << std::uppercase << std::hex << address; + char input[16]; + if (Gui::requestKeyboardInput("Enter Address", "Enter Address to add to bookmark .", ss.str(), SwkbdType_QWERTY, input, 18)) + { + address = static_cast(std::stoul(input, nullptr, 16)); + + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + } + } + } + + // inc and dec search value + if ((kdown & KEY_ZR) && (m_searchMenuLocation == SEARCH_VALUE) && (m_searchType == SEARCH_TYPE_UNSIGNED_32BIT)) + { + m_searchValue[0]._u32++; + m_selectedEntry = 1; + }; + if ((kdown & KEY_ZL) && (m_searchMenuLocation == SEARCH_VALUE) && (m_searchType == SEARCH_TYPE_UNSIGNED_32BIT)) + { + m_searchValue[0]._u32--; + m_selectedEntry = 1; + }; + + if (kdown & KEY_A) + { + if (m_searchMenuLocation == SEARCH_editRAM) + { // BM3 + // EditRAM routine + // to update to use L and R to select type and display it on the top line + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + char input[16]; + char initialString[21]; + strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + if (Gui::requestKeyboardInput("Enter value", "Enter a value that should get written at this .", initialString, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, input, 18)) + { + if (m_searchValueFormat == FORMAT_HEX) + { + auto value = static_cast(std::stoul(input, nullptr, 16)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_32BIT) + { + auto value = static_cast(std::atof(input)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_64BIT) + { + auto value = std::atof(input); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType != SEARCH_TYPE_NONE) + { + auto value = std::atol(input); + m_debugger->writeMemory((void *)&value, dataTypeSizes[m_searchType], address); + } + } + } + else if (m_searchMenuLocation == SEARCH_TYPE) + m_searchType = static_cast(m_selectedEntry); + else if (m_searchMenuLocation == SEARCH_REGION) + m_searchRegion = static_cast(m_selectedEntry); + else if (m_searchMenuLocation == SEARCH_MODE) + m_searchMode = static_cast(m_selectedEntry); + else if (m_searchMenuLocation == SEARCH_VALUE) + { + if (m_selectedEntry == 0) + { + m_selectedEntry = 1; + char str[0x21]; + // Start Mod keep previous value + // End Mod + if ((m_searchValue[m_searchValueIndex]._u32 > 10) || (m_searchValueFormat == FORMAT_HEX)) + { + Gui::requestKeyboardInput("Enter the value you want to search for", "Based on your previously chosen options, EdiZon will expect different input here.", _getValueDisplayString(m_searchValue[m_searchValueIndex], m_searchType), m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); + } + else + { + Gui::requestKeyboardInput("Enter the value you want to search for", "Based on your previously chosen options, EdiZon will expect different input here.", "", m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); + } + if (std::string(str) == "") + return; + + if (m_searchValueFormat == FORMAT_HEX) + { + m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stoul(str, nullptr, 16)); + } + else + { + switch (m_searchType) + { + case SEARCH_TYPE_UNSIGNED_8BIT: + m_searchValue[m_searchValueIndex]._u8 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_16BIT: + m_searchValue[m_searchValueIndex]._u16 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_32BIT: + m_searchValue[m_searchValueIndex]._u32 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_64BIT: + m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_8BIT: + m_searchValue[m_searchValueIndex]._s8 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_16BIT: + m_searchValue[m_searchValueIndex]._s16 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_32BIT: + m_searchValue[m_searchValueIndex]._s32 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_64BIT: + m_searchValue[m_searchValueIndex]._s64 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_FLOAT_32BIT: + m_searchValue[m_searchValueIndex]._f32 = static_cast(std::stof(str)); + break; + case SEARCH_TYPE_FLOAT_64BIT: + m_searchValue[m_searchValueIndex]._f64 = static_cast(std::stod(str)); + break; + case SEARCH_TYPE_POINTER: + m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stol(str)); + break; + case SEARCH_TYPE_NONE: + break; + } + } + } + else if (m_selectedEntry == 1) + { + (new MessageBox("Traversing title memory.\n \nThis may take a while...", MessageBox::NONE))->show(); + requestDraw(); + + overclockSystem(true); + + if (m_searchMode == SEARCH_MODE_POINTER) + m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; + + if (m_searchMode == SEARCH_MODE_SAME || m_searchMode == SEARCH_MODE_DIFF || m_searchMode == SEARCH_MODE_INC || m_searchMode == SEARCH_MODE_DEC || m_searchMode == SEARCH_MODE_DIFFA || m_searchMode == SEARCH_MODE_SAMEA) + { + if (m_memoryDump->size() == 0) + { + delete m_memoryDump; + GuiCheats::searchMemoryValuesPrimary(m_debugger, m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + printf("%s%lx\n", "Dump Size = ", m_memoryDump->size()); + } + else if (m_memoryDump->getDumpInfo().dumpType == DumpType::DATA) + { + printf("%s%lx\n", "Dump Size = ", m_memoryDump->size()); + GuiCheats::searchMemoryValuesSecondary(m_debugger, m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + delete m_memoryDump; + remove(EDIZON_DIR "/memdump1.dat"); + rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + printf("%s\n", "renaming"); + m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); + } + else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + GuiCheats::searchMemoryValuesTertiary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + delete m_memoryDump; + remove(EDIZON_DIR "/memdump1.dat"); + remove(EDIZON_DIR "/memdump1a.dat"); + rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); + remove(EDIZON_DIR "/datadump2.dat"); + rename(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); + // rename B to A + remove(EDIZON_DIR "/datadumpA.dat"); + rename(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat"); + remove(EDIZON_DIR "/datadumpB.dat"); + rename(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + } + } + else + { + if (m_memoryDump->size() == 0) + { + delete m_memoryDump; + GuiCheats::searchMemoryAddressesPrimary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + } + else + { + m_nothingchanged = false; + GuiCheats::searchMemoryAddressesSecondary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, &m_memoryDump); + if (m_nothingchanged == false) + { + remove(EDIZON_DIR "/memdump1a.dat"); // remove old helper + rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); // rename new helper to current helper + } + } + } + + overclockSystem(false); + + Gui::g_currMessageBox->hide(); + + m_searchMenuLocation = SEARCH_NONE; + // m_searchMode = SEARCH_MODE_NONE; + } + } + } + } + + if (kdown & KEY_X) + { + if (m_searchMenuLocation == SEARCH_VALUE) + { + if (m_searchValueFormat == FORMAT_DEC) + m_searchValueFormat = FORMAT_HEX; + else + m_searchValueFormat = FORMAT_DEC; + } + } + + if (kdown & KEY_L) + { + if (m_searchMenuLocation == SEARCH_VALUE) + { + m_searchMenuLocation = SEARCH_REGION; + m_selectedEntry = m_searchRegion == SEARCH_REGION_NONE ? 0 : static_cast(m_searchRegion); + } + else if (m_searchMenuLocation == SEARCH_REGION) + { + m_searchMenuLocation = SEARCH_MODE; + m_selectedEntry = m_searchMode == SEARCH_MODE_NONE ? 0 : static_cast(m_searchMode); + } + else if (m_searchMenuLocation == SEARCH_MODE) + { + m_searchMenuLocation = SEARCH_TYPE; + m_selectedEntry = m_searchType == SEARCH_TYPE_NONE ? 0 : static_cast(m_searchType); + } + } + + if (kdown & KEY_R) + { + if (m_searchMenuLocation == SEARCH_TYPE) + { + m_searchMenuLocation = SEARCH_MODE; + m_selectedEntry = m_searchMode == SEARCH_MODE_NONE ? 0 : static_cast(m_searchMode); + } + else if (m_searchMenuLocation == SEARCH_MODE) + { + m_searchMenuLocation = SEARCH_REGION; + m_selectedEntry = m_searchRegion == SEARCH_REGION_NONE ? 0 : static_cast(m_searchRegion); + } + else if (m_searchMenuLocation == SEARCH_REGION) + { + m_searchMenuLocation = SEARCH_VALUE; + m_selectedEntry = 0; + m_searchValueIndex = 0; + } + } + } +} + +void GuiCheats::onTouch(touchPosition &touch) +{ +} + +void GuiCheats::onGesture(touchPosition startPosition, touchPosition endPosition, bool finish) +{ +} +static bool _isAddressFrozen(uintptr_t address) +{ + DmntFrozenAddressEntry *es; + u64 Cnt = 0; + bool frozen = false; + + dmntchtGetFrozenAddressCount(&Cnt); + + if (Cnt != 0) + { + es = new DmntFrozenAddressEntry[Cnt]; + dmntchtGetFrozenAddresses(es, Cnt, 0, nullptr); + + for (u64 i = 0; i < Cnt; i++) + { + if (es[i].address == address) + { + frozen = true; + break; + } + } + } + + return frozen; +} + +static std::string _getAddressDisplayString(u64 address, Debugger *debugger, searchType_t searchType) +{ + std::stringstream ss; + + searchValue_t searchValue; + searchValue._u64 = debugger->peekMemory(address); + // start mod for address content display + if (m_searchValueFormat == FORMAT_HEX) + ss << "0x" << std::uppercase << std::hex << searchValue._u64; + else + { + + // end mod + switch (searchType) + { + case SEARCH_TYPE_UNSIGNED_8BIT: + ss << std::dec << static_cast(searchValue._u8); + break; + case SEARCH_TYPE_UNSIGNED_16BIT: + ss << std::dec << static_cast(searchValue._u16); + break; + case SEARCH_TYPE_UNSIGNED_32BIT: + ss << std::dec << static_cast(searchValue._u32); + break; + case SEARCH_TYPE_UNSIGNED_64BIT: + ss << std::dec << static_cast(searchValue._u64); + break; + case SEARCH_TYPE_SIGNED_8BIT: + ss << std::dec << static_cast(searchValue._s8); + break; + case SEARCH_TYPE_SIGNED_16BIT: + ss << std::dec << static_cast(searchValue._s16); + break; + case SEARCH_TYPE_SIGNED_32BIT: + ss << std::dec << static_cast(searchValue._s32); + break; + case SEARCH_TYPE_SIGNED_64BIT: + ss << std::dec << static_cast(searchValue._s64); + break; + case SEARCH_TYPE_FLOAT_32BIT: + ss << std::dec << searchValue._f32; + break; + case SEARCH_TYPE_FLOAT_64BIT: + ss << std::dec << searchValue._f64; + break; + case SEARCH_TYPE_POINTER: + ss << std::dec << searchValue._u64; + break; + case SEARCH_TYPE_NONE: + break; + } + } + + return ss.str(); +} + +static std::string _getValueDisplayString(searchValue_t searchValue, searchType_t searchType) +{ + std::stringstream ss; + + if (m_searchValueFormat == FORMAT_HEX) + { + ss << "0x" << std::uppercase << std::hex << searchValue._u64; + } + else + { + switch (searchType) + { + case SEARCH_TYPE_UNSIGNED_8BIT: + ss << std::dec << static_cast(searchValue._u8); + break; + case SEARCH_TYPE_UNSIGNED_16BIT: + ss << std::dec << static_cast(searchValue._u16); + break; + case SEARCH_TYPE_UNSIGNED_32BIT: + ss << std::dec << static_cast(searchValue._u32); + break; + case SEARCH_TYPE_UNSIGNED_64BIT: + ss << std::dec << static_cast(searchValue._u64); + break; + case SEARCH_TYPE_SIGNED_8BIT: + ss << std::dec << static_cast(searchValue._s8); + break; + case SEARCH_TYPE_SIGNED_16BIT: + ss << std::dec << static_cast(searchValue._s16); + break; + case SEARCH_TYPE_SIGNED_32BIT: + ss << std::dec << static_cast(searchValue._s32); + break; + case SEARCH_TYPE_SIGNED_64BIT: + ss << std::dec << static_cast(searchValue._s64); + break; + case SEARCH_TYPE_FLOAT_32BIT: + ss.precision(15); + ss << std::dec << searchValue._f32; + break; + case SEARCH_TYPE_FLOAT_64BIT: + ss.precision(15); + ss << std::dec << searchValue._f64; + break; + case SEARCH_TYPE_POINTER: + ss << std::dec << searchValue._u64; + break; + case SEARCH_TYPE_NONE: + break; + } + } + + return ss.str(); +} +// read +void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ + (*displayDump) = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, true); + (*displayDump)->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + (*displayDump)->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); + + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory + MemoryDump *newdataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); + MemoryDump *newstringDump = new MemoryDump(EDIZON_DIR "/stringdump.dat", DumpType::DATA, true); // to del when not needed + + helperinfo_t helperinfo; + helperinfo.count = 0; + + bool ledOn = false; + + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time primary search", unixTime1); + // printf("main %lx main end %lx heap %lx heap end %lx \n",m_mainBaseAddr, m_mainBaseAddr+m_mainSize, m_heapBaseAddr, m_heapBaseAddr+m_heapSize); + for (MemoryInfo meminfo : memInfos) + { + + // printf("%s%p", "meminfo.addr, ", meminfo.addr); + // printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); + // printf("%s%p", ", meminfo.size, ", meminfo.size); + // printf("%s%lx", ", meminfo.type, ", meminfo.type); + // printf("%s%lx", ", meminfo.attr, ", meminfo.attr); + // printf("%s%lx", ", meminfo.perm, ", meminfo.perm); + // printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); + // printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); + + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + + setLedState(ledOn); + ledOn = !ledOn; + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // consider to increase from 10k to 1M (not a big problem) + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + + debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + u64 address = meminfo.addr + offset + i; + memset(&realValue, 0, 8); + memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + + switch (searchMode) + { + case SEARCH_MODE_EQ: + if (realValue._s64 == searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_NEQ: + if (realValue._s64 != searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_GT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 > searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 > searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_DIFFA: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 >= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 >= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_LT: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 < searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 < searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_SAMEA: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (realValue._s64 <= searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (realValue._u64 <= searchValue1._u64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_RANGE: + if (realValue._s64 >= searchValue1._s64 && realValue._s64 <= searchValue2._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&realValue, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainBaseAddr + m_mainSize))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapBaseAddr + m_heapSize)))) + { + if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) + break; + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&realValue, sizeof(u64)); + helperinfo.count++; + // printf("%lx,%lx\n",address,realValue); + char st[25]; // replace the printf + snprintf(st, 25, "'%lx,'%lx\n", address, realValue); // + newstringDump->addData((u8 *)&st, sizeof(st)); // + } + break; + } + } + + // helper info write must be before inc + if (helperinfo.count != 0) + { + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + // printf("address 0x%lx ", helperinfo.address); + // printf("size %ld ", helperinfo.size); + // printf("count %ld type %d \n ", helperinfo.count, meminfo.type); + helperinfo.count = 0; + } // must be after write + + offset += bufferSize; + } + + delete[] buffer; + } + + setLedState(false); + + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + + (*displayDump)->flushBuffer(); + newdataDump->flushBuffer(); + helperDump->flushBuffer(); + delete helperDump; + delete newdataDump; + newstringDump->flushBuffer(); // temp + delete newstringDump; // +} +// + +void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, MemoryDump **displayDump) +{ + MemoryDump *newDump = new MemoryDump(EDIZON_DIR "/memdump2.dat", DumpType::ADDR, true); + bool ledOn = false; + //begin + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time Secondary search", unixTime1); + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // this is for file access going for 1M + u8 *buffer = new u8[bufferSize]; + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, false); // has address, size, count for fetching buffer from memory + MemoryDump *newhelperDump = new MemoryDump(EDIZON_DIR "/memdump3a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory + MemoryDump *newdataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); + MemoryDump *debugdump1 = new MemoryDump(EDIZON_DIR "/debugdump1.dat", DumpType::HELPER, true); + if (helperDump->size() == 0) + { + (new Snackbar("Helper file not found !"))->show(); + return; + } + else + { + // helper integrity check + printf("start helper integrity check address secondary \n"); + u32 helpercount = 0; + helperinfo_t helperinfo; + for (u64 i = 0; i < helperDump->size(); i += sizeof(helperinfo)) + { + helperDump->getData(i, &helperinfo, sizeof(helperinfo)); + helpercount += helperinfo.count; + } + if (helpercount != (*displayDump)->size() / sizeof(u64)) + { + printf("Integrity problem with helper file helpercount = %d memdumpsize = %d \n", helpercount, (*displayDump)->size() / sizeof(u64)); + (new Snackbar("Helper integrity check failed !"))->show(); + return; + } + printf("end helper integrity check address secondary \n"); + // end helper integrity check + + std::stringstream Message; + Message << "Traversing title memory.\n \nThis may take a while... secondary search\nTime " << (unixTime1 - time(NULL)) << " total " << (*displayDump)->size(); + (new MessageBox(Message.str(), MessageBox::NONE))->show(); + requestDraw(); + } + + u8 *ram_buffer = new u8[bufferSize]; + u64 helper_offset = 0; + helperinfo_t helperinfo; + helperinfo_t newhelperinfo; + newhelperinfo.count = 0; + + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); // helper_offset+=sizeof(helperinfo) + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + // helper init end + while (offset < (*displayDump)->size()) + { + if ((*displayDump)->size() - offset < bufferSize) + bufferSize = (*displayDump)->size() - offset; + (*displayDump)->getData(offset, buffer, bufferSize); // BM4 + + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + if (helperinfo.count == 0) + { + if (newhelperinfo.count != 0) + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + // printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + // printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + // printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + helper_offset += sizeof(helperinfo); + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + } + searchValue_t value = {0}; + searchValue_t testing = {0}; // temp + u64 address = 0; + + address = *reinterpret_cast(&buffer[i]); //(*displayDump)->getData(i * sizeof(u64), &address, sizeof(u64)); + + memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); // extrat from buffer instead of making call + helperinfo.count--; // each fetch dec + // testing = value; // temp + // debugger->readMemory(&value, dataTypeSizes[searchType], address); + // if (testing._u64 != value._u64) + // { + // printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + // printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + // printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + // printf("%s%lx\n", "address ", address); + // printf("%s%lx\n", "testing._u64 ", testing._u64); + // printf("%s%lx\n", "value ", value); + // printf("%s%lx\n", " address - helperinfo.address ", address - helperinfo.address); + // printf("%s%lx\n", " * (ram_buffer + address - helperinfo.address) ", *(ram_buffer + address - helperinfo.address)); + // printf("%s%lx\n", " * (&ram_buffer[ address - helperinfo.address]) ", *(&ram_buffer[address - helperinfo.address])); + // printf("%s%lx\n", " (ram_buffer + address - helperinfo.address) ", (ram_buffer + address - helperinfo.address)); + // printf("%s%lx\n", " (&ram_buffer[ address - helperinfo.address]) ", (&ram_buffer[address - helperinfo.address])); + // printf("%s%lx\n", " helperinfo.size - address + helperinfo.address ", helperinfo.size - address + helperinfo.address); + // // debugdump1->addData((u8 *)&ram_buffer, helperinfo.size); + // // debugger->readMemory(ram_buffer, 0x50, address); + // // debugdump2->addData((u8 *)&ram_buffer, 0x50); + // // + // // delete debugdump2; + // } + + if (i % 50000 == 0) + { + setLedState(ledOn); + ledOn = !ledOn; + } + + switch (searchMode) + { + case SEARCH_MODE_EQ: + if (value._s64 == searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_NEQ: + if (value._s64 != searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_GT: + if (value._s64 > searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFFA: + if (value._s64 >= searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_LT: + if (value._s64 < searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_SAMEA: + if (value._s64 <= searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_RANGE: + if (value._s64 >= searchValue1._s64 && value._s64 <= searchValue2._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); // add here + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize + if ((value._s64 >= m_mainBaseAddr && value._s64 <= (m_mainBaseAddr + m_mainSize)) || (value._s64 >= m_heapBaseAddr && value._s64 <= (m_heapBaseAddr + m_heapSize))) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_SAME: + if (value._s64 == searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFF: + if (value._s64 != searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_INC: + if (value._s64 > searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DEC: + if (value._s64 < searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_NONE: + break; + } + } + printf("%d of %d done \n", offset, (*displayDump)->size()); // maybe consider message box this info + offset += bufferSize; + } + + if (newhelperinfo.count != 0) // take care of the last one + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + // printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + // printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + // printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + //end + newDump->flushBuffer(); + newhelperDump->flushBuffer(); + newdataDump->flushBuffer(); + + if (newDump->size() > 0) + { + // delete m_memoryDump; + // remove(EDIZON_DIR "/memdump1.dat"); + // rename(EDIZON_DIR "/memdump2.dat", EDIZON_DIR "/memdump2.dat"); + (*displayDump)->clear(); + (*displayDump)->setSearchParams(searchType, searchMode, (*displayDump)->getDumpInfo().searchRegion, searchValue1, searchValue2); + (*displayDump)->setDumpType(DumpType::ADDR); + + // begin copy + offset = 0; + bufferSize = MAX_BUFFER_SIZE; //0x1000000; // match what was created before + printf("%s%lx\n", "bufferSize ", bufferSize); // printf + while (offset < newDump->size()) + { + if (newDump->size() - offset < bufferSize) + bufferSize = newDump->size() - offset; + newDump->getData(offset, buffer, bufferSize); + (*displayDump)->addData(buffer, bufferSize); + offset += bufferSize; + } + // end copy + + (*displayDump)->flushBuffer(); + } + else + { + (new Snackbar("None of values changed to the entered one!"))->show(); + m_nothingchanged = true; + } + + setLedState(false); + delete newDump; + delete newhelperDump; + delete helperDump; + delete debugdump1; + delete newdataDump; + delete[] buffer; + delete[] ram_buffer; + + remove(EDIZON_DIR "/memdump2.dat"); + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time secondary search ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); +} + +/////////////////////////////////////////////// +// read +void GuiCheats::searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ + bool ledOn = false; + + searchValue_t zeroValue; + zeroValue._u64 = 0; + // printf("%s\n", "searchMemoryValuesPrimary"); + // printf("%s\n", titleNameStr.c_str()); + // printf("%s\n", tidStr.c_str()); + // printf("%s\n", buildIDStr.c_str()); + // printf("%s%lx\n", "m_addressSpaceBaseAddr ", m_addressSpaceBaseAddr); + // printf("%s%lx\n", "m_heapBaseAddr ", m_heapBaseAddr); + // printf("%s%lx\n", "m_mainBaseAddr ", m_mainBaseAddr); + // printf("%s%lx\n", "m_heapSize ", m_heapSize); + // printf("%s%lx\n", "m_mainSize ", m_mainSize); + // printf("%s%X1\n", "searchType ", searchType); + // printf("%s%X1\n", "searchMode ", searchMode); + // printf("%s%X1\n", "searchRegion ", searchRegion); + (new Snackbar("Dumping memory"))->show(); + (*displayDump) = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::DATA, true); + (*displayDump)->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + (*displayDump)->setSearchParams(searchType, searchMode, searchRegion, {0}, {0}); + // start time + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time ", unixTime1); + + for (MemoryInfo meminfo : memInfos) + { + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + + setLedState(ledOn); + ledOn = !ledOn; + // printf("%s%lx\n", "meminfo.size ", meminfo.size); + // printf("%s%lx\n", "meminfo.addr ", meminfo.addr); + // printf("%s%lx\n", "meminfo.type ", meminfo.type); + // printf("%s%lx\n", "meminfo.perm ", meminfo.perm); + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // hack increase from 40K to 1M + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + + debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + (*displayDump)->addData(buffer, bufferSize); + + offset += bufferSize; + } + + delete[] buffer; + } + + setLedState(false); + (*displayDump)->flushBuffer(); + // end time + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); +} + +//////////////////////////////////////////////////// +void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ + bool ledOn = false; + searchValue_t oldValue = {0}; // check if needed + searchValue_t newValue = {0}; + + MemoryDump *newMemDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); // Store Current value + MemoryDump *addrDump = new MemoryDump(EDIZON_DIR "/memdump3.dat", DumpType::ADDR, true); + addrDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + addrDump->setSearchParams(searchType, searchMode, searchRegion, {0}, {0}); + + // work in progress + // if (searchMode == SEARCH_MODE_DIFFA) + MemoryDump *valueDumpA = new MemoryDump(EDIZON_DIR "/datadumpA.dat", DumpType::DATA, true); // file to put A + MemoryDump *valueDumpB = new MemoryDump(EDIZON_DIR "/datadumpB.dat", DumpType::DATA, true); // file to put B + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) + { + (new Snackbar("Creating state B"))->show(); + } + // end work in progress + + u64 dumpoffset = 0; // file offset need to be for whole session + + // start time + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time second search ", unixTime1); + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::ADDR, true); // has address, size, count for fetching buffer from memory + helperinfo_t helperinfo; + + for (MemoryInfo meminfo : memInfos) + { + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + + setLedState(ledOn); + ledOn = !ledOn; + printf("%s%lx\n", "meminfo.size ", meminfo.size); + printf("%s%lx\n", "meminfo.addr ", meminfo.addr); + printf("%s%lx\n", "meminfo.type ", meminfo.type); + printf("%s%lx\n", "meminfo.perm ", meminfo.perm); + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // hack increase from 40K to 1M + u8 *buffer = new u8[bufferSize]; + u8 *filebuffer = new u8[bufferSize]; //added filebuffer matching memory buffer memory buffer could be smaller, let's see if that is too much + u64 addr = meminfo.addr; + + // start count + helperinfo.count = 0; + + while (offset < meminfo.size) + { + setLedState(ledOn); + ledOn = !ledOn; + + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + + debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + // printf("%s\n", "readmemory OK "); + // printf("%s%lx\n", "dumpoffset ", dumpoffset); + // printf("%s%lx\n", "bufferSize ", bufferSize); + // printf("%s%lx\n", "displayDump ", displayDump); + // print_details = true; + (*displayDump)->getData(dumpoffset, filebuffer, bufferSize); + // print_details = false; + // printf("%s\n", "readdata OK "); + + for (u64 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + switch (dataTypeSizes[searchType]) + { + case 1: + newValue._u8 = *reinterpret_cast(&buffer[i]); + oldValue._u8 = *reinterpret_cast(&filebuffer[i]); + case 2: + newValue._u16 = *reinterpret_cast(&buffer[i]); + oldValue._u16 = *reinterpret_cast(&filebuffer[i]); + case 4: + newValue._u32 = *reinterpret_cast(&buffer[i]); + oldValue._u32 = *reinterpret_cast(&filebuffer[i]); + case 8: + newValue._u64 = *reinterpret_cast(&buffer[i]); + oldValue._u64 = *reinterpret_cast(&filebuffer[i]); + } + switch (searchMode) + { + case SEARCH_MODE_SAME: + if (newValue._u64 == oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_DIFF: + if (newValue._u64 != oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + break; + case SEARCH_MODE_SAMEA: + case SEARCH_MODE_DIFFA: + if (newValue._u64 != oldValue._u64) + { + // (new Snackbar("Creating state A (previsou) and state B (current) "))->show(); + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); // Keep compatibility with other mode + valueDumpA->addData((u8 *)&oldValue, sizeof(u64)); // save state A + valueDumpB->addData((u8 *)&newValue, sizeof(u64)); // save state B + helperinfo.count++; + } + break; + case SEARCH_MODE_INC: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (newValue._s64 > oldValue._s64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (newValue._u64 > oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + break; + case SEARCH_MODE_DEC: + if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) + { + if (newValue._s64 < oldValue._s64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + else + { + if (newValue._u64 < oldValue._u64) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + } + break; + } + addr += dataTypeSizes[searchType]; + } + // end compare + // helper info write must be before inc + helperinfo.address = meminfo.addr + offset; + helperinfo.size = bufferSize; + if (helperinfo.count != 0) + helperDump->addData((u8 *)&helperinfo, sizeof(helperinfo)); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + helperinfo.count = 0; // must be after write + // end + + offset += bufferSize; + dumpoffset += bufferSize; + + printf("%s%lx\n", "offset ", offset); + printf("%s%lx\n", "dumpoffset ", dumpoffset); + } + + delete[] buffer; + delete[] filebuffer; + } + newMemDump->flushBuffer(); + addrDump->flushBuffer(); + helperDump->flushBuffer(); + valueDumpA->flushBuffer(); + valueDumpB->flushBuffer(); + delete newMemDump; // this should close these two files + delete addrDump; + delete helperDump; + delete valueDumpA; + delete valueDumpB; + + // old maybe useless stuff to delete later + // Bigger buffers + // for (u64 addr = 0; addr < std::min((*displayDump)->size(), newMemDump->size()); addr += dataTypeSizes[searchType]) + // { + // searchValue_t oldValue = {0}; + // searchValue_t newValue = {0}; + // (*displayDump)->getData(addr, &oldValue, dataTypeSizes[searchType]); + // newMemDump->getData(addr, &newValue, dataTypeSizes[searchType]); + // } + + setLedState(false); + + // end time second search + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time second search", unixTime2); + printf("%s%ld\n", "Total Time in decimal seconds ", unixTime2 - unixTime1); +} + +void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ + MemoryDump *oldvalueDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); //file with previous value + MemoryDump *newvalueDump = new MemoryDump(EDIZON_DIR "/datadump4.dat", DumpType::DATA, true); // file to put new value + + //work in progress + // if (searchMode == SEARCH_MODE_SAMEA) + MemoryDump *valueDumpA = new MemoryDump(EDIZON_DIR "/datadumpA.dat", DumpType::DATA, false); // file to get A + MemoryDump *newvalueDumpA = new MemoryDump(EDIZON_DIR "/datadumpAa.dat", DumpType::DATA, true); // file to put new A + MemoryDump *valueDumpB = new MemoryDump(EDIZON_DIR "/datadumpB.dat", DumpType::DATA, false); // file to get B + MemoryDump *newvalueDumpB = new MemoryDump(EDIZON_DIR "/datadumpBa.dat", DumpType::DATA, true); // file to put new B + bool no_existing_dump = false; + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) + { + if (valueDumpA->size() == oldvalueDump->size()) + { + delete oldvalueDump; + oldvalueDump = valueDumpA; + } + else + { + // delete valueDumpB; + // valueDumpB = oldvalueDump; + no_existing_dump = true; + printf("no existing dump \n"); + if (searchMode == SEARCH_MODE_SAMEA) + return; + } + } + + // create a A and B file valueDumpA and newvalueDumpA ?? to keep track of A B; + //end work in progress + MemoryDump *newDump = new MemoryDump(EDIZON_DIR "/memdump3.dat", DumpType::ADDR, true); //file to put new candidates + newDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + newDump->setSearchParams(searchType, searchMode, searchRegion, {0}, {0}); + bool ledOn = false; + //begin + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time Tertiary search", unixTime1); + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // this is for file access going for 1M + bool have_oldvalue = false; + u8 *buffer = new u8[bufferSize]; + u8 *valuebuffer = new u8[bufferSize]; + u8 *valueBbuffer = new u8[bufferSize]; + + // BM7 + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::ADDR, false); // has address, size, count for fetching buffer from memory + MemoryDump *newhelperDump = new MemoryDump(EDIZON_DIR "/memdump3a.dat", DumpType::ADDR, true); // has address, size, count for fetching buffer from memory + if (helperDump->size() == 0) + { + (new Snackbar("Helper file not found !"))->show(); + return; + } + + // helper integrity check + if (true) + { + printf("start helper integrity check value tertiary \n"); + u32 helpercount = 0; + helperinfo_t helperinfo; + for (u64 i = 0; i < helperDump->size(); i += sizeof(helperinfo)) + { + helperDump->getData(i, &helperinfo, sizeof(helperinfo)); + helpercount += helperinfo.count; + } + if (helpercount != (*displayDump)->size() / sizeof(u64)) + { + printf("Integrity problem with helper file helpercount = %d memdumpsize = %d \n", helpercount, (*displayDump)->size() / sizeof(u64)); + (new Snackbar("Helper integrity check failed !"))->show(); + return; + } + printf("end helper integrity check value tertiary \n"); + } + // end helper integrity check + + u8 *ram_buffer = new u8[bufferSize]; + u64 helper_offset = 0; + helperinfo_t helperinfo; + helperinfo_t newhelperinfo; + newhelperinfo.count = 0; + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); // helper_offset+=sizeof(helperinfo) + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + printf("%s%lx\n", "helper_offset ", helper_offset); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + // helper init end + + if (oldvalueDump->size() == (*displayDump)->size()) + { + printf("%s\n", "Found old value"); + have_oldvalue = true; + } + else + { + (new Snackbar("previous value file not found !"))->show(); + return; /* code */ + } + + searchValue_t value = {0}; + searchValue_t oldvalue = {0}; + searchValue_t Bvalue = {0}; + + u64 address = 0; + while (offset < (*displayDump)->size()) + { + + if ((*displayDump)->size() - offset < bufferSize) + bufferSize = (*displayDump)->size() - offset; + + (*displayDump)->getData(offset, buffer, bufferSize); // BM6 + if (have_oldvalue) + oldvalueDump->getData(offset, valuebuffer, bufferSize); + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) //read in data A and B + { + if (no_existing_dump == false) + valueDumpB->getData(offset, valueBbuffer, bufferSize); + } + + printf("%s\n", "buffer loaded"); + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + if (helperinfo.count == 0) + { + if (newhelperinfo.count != 0) + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + newhelperinfo.count = 0; + }; + helper_offset += sizeof(helperinfo); + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + printf("%s%lx\n", "helper_offset ", helper_offset); + } + + address = *reinterpret_cast(&buffer[i]); + oldvalue._u64 = *reinterpret_cast(&valuebuffer[i]); + if ((searchMode == SEARCH_MODE_SAMEA) || (searchMode == SEARCH_MODE_DIFFA)) //read in data A and B + { + if (no_existing_dump == false) + Bvalue._u64 = *reinterpret_cast(&valueBbuffer[i]); + } + + // fetch value from buffer + // ram_buffer + i == &ram_buffer[i] + // value._u64 = 0; + memset(&value, 0, 8); + memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); + helperinfo.count--; + + // searchValue_t *foobar = reinterpret_cast(ram_buffer + (address - helperinfo.address)) + //_u32 bar = (*foobar)._u32; + //(reinterpret_cast(ram_buffer + (address - helperinfo.address)))._u32 + + // debugger->readMemory(&value, dataTypeSizes[searchType], address); + + if (i % 10000 == 0) + { + setLedState(ledOn); + ledOn = !ledOn; + } + + switch (searchMode) + { + case SEARCH_MODE_SAME: + if (value._s64 == oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_SAMEA: + if (no_existing_dump) + { + printf("this shouldn't happen\n"); + if (value._s64 != Bvalue._s64) //change + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&value, sizeof(u64)); + // newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); + newhelperinfo.count++; + } + } + else if (value._s64 == oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); //create new file and later rename to A, need this new file for size of A to be in sync + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFFA: //need to be same as B + if (no_existing_dump) + { + if (value._s64 != oldvalue._s64) // change + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&value, sizeof(u64)); + // newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); + newhelperinfo.count++; + } + } + else if (value._s64 == Bvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newvalueDumpA->addData((u8 *)&oldvalue, sizeof(u64)); + newvalueDumpB->addData((u8 *)&Bvalue, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFF: + if (value._s64 != oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_INC: + if (value._s64 > oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DEC: + if (value._s64 < oldvalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newvalueDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_NONE: + break; + } + } + + offset += bufferSize; + // update newhelperinfo + + printf("%s%lx%s%lx\n", "(*displayDump)->size() ", (*displayDump)->size(), "Offset ", offset); + } + + if (newhelperinfo.count != 0) // need to take care of the last one + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + newhelperinfo.count = 0; + }; + newDump->flushBuffer(); + newvalueDump->flushBuffer(); + //end + // should just rename the file ?? + if (newDump->size() > 0) + { + printf("%s%lx\n", "newDump->size() ", newDump->size()); + } + else + { + (new Snackbar("None of values changed to the entered one!"))->show(); + } + + setLedState(false); + delete[] ram_buffer; + delete[] valuebuffer; + delete[] valueBbuffer; + delete[] buffer; + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time Tertiary search ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + + newvalueDump->flushBuffer(); + newDump->flushBuffer(); + newhelperDump->flushBuffer(); + newvalueDumpA->flushBuffer(); + newvalueDumpB->flushBuffer(); + + delete newvalueDump; + delete newDump; + delete newhelperDump; + delete newvalueDumpA; + delete newvalueDumpB; + + delete oldvalueDump; //needed to close the file + delete helperDump; + delete valueDumpB; + + printf("Done Tertiary \n"); + // remove(EDIZON_DIR "/memdump3.dat"); +} + +// here + +void GuiCheats::pointercheck() +{ + printf("checking pointer...\n"); + m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, false); + if (m_pointeroffsetDump->size() > 0) + { + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; + u8 *buffer = new u8[bufferSize]; + pointer_chain_t pointer_chain; + while (offset < m_pointeroffsetDump->size()) + { + if (m_pointeroffsetDump->size() - offset < bufferSize) + bufferSize = m_pointeroffsetDump->size() - offset; + m_pointeroffsetDump->getData(offset, buffer, bufferSize); + for (u64 i = 0; i < bufferSize; i += sizeof(pointer_chain_t)) + { + pointer_chain_t pointer_chain = *reinterpret_cast(&buffer[i]); + u64 nextaddress = m_mainBaseAddr; + printf("main[%lx]", nextaddress); + // m_debugger->readMemory(&nextaddress, sizeof(u64), ( m_mainBaseAddr+ pointer_chain.offset[pointer_chain.depth])); + // printf("(&lx)", nextaddress); + for (int z = pointer_chain.depth; z >= 0; z--) + { + printf("+%lx z=%d ", pointer_chain.offset[z], z); + nextaddress += pointer_chain.offset[z]; + printf("[%lx]", nextaddress); + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + printf("(%lx)", nextaddress); + } + printf("\n\n"); + } + offset += bufferSize; + } + delete[] buffer; + } + else + { + printf("no saved poiters\n"); + } +} + +void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDump, MemoryDump **dataDump, pointer_chain_t pointerchain) +{ + m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); // pointed targets is in this file + m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, true); // create file but maybe later just open it + pointer_chain_t pointerchain; + printf("check point 1\n"); + pointerchain.depth = 0; + try + { + pointersearch(targetaddress, pointerchain); //&m_memoryDump, &m_dataDump, + } + catch (...) + { + printf("Caught an exception\n"); + } + // add some rubbish just for testing + // char st[250]; // replace the printf + // snprintf(st, 250, "Just for testing ====="); // + // m_pointeroffsetDump->addData((u8 *)&st, sizeof(st)); // + + m_pointeroffsetDump->flushBuffer(); + delete m_pointeroffsetDump; +} + +void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain) //MemoryDump **displayDump, MemoryDump **dataDump, +{ + // printf("target address = %lx depth = %d \n", targetaddress, pointerchain.depth); + + // printf("check point 1a\n"); + if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainBaseAddr + m_mainSize))) + { + printf("\ntarget reached!=========================\n"); + printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); + // pointerchain.depth++; + // pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; + // // save pointerchain + pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; + m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); + m_pointeroffsetDump->flushBuffer(); // is this useful? + printf("main"); + for (int z = pointerchain.depth; z >= 0; z--) + printf("+%lx z=%d ", pointerchain.offset[z], z); + printf("\n\n"); + // printf("\nsize=%d\n", sizeof(pointer_chain_t)); + return; // consider don't return to find more + }; + + if (pointerchain.depth == MAX_POINTER_DEPTH) + { + // printf("max pointer depth reached\n\n"); + return; + } + + // printf("\n starting pointer search for address = %lx at depth %d ", targetaddress, pointerchain.depth); + u64 offset = 0; + u64 thefileoffset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; + u8 *buffer = new u8[bufferSize]; + u64 distance; + u64 minimum = MAX_POINTER_RANGE; // a large number to start + std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers + sourceinfo_t sourceinfo; + // std::vector distances; + + while (offset < m_dataDump->size()) + { + if (m_dataDump->size() - offset < bufferSize) + bufferSize = m_dataDump->size() - offset; + // printf("checkpoint 2\n"); + m_dataDump->getData(offset, buffer, bufferSize); // BM4 + bool writeback = false; + // printf("checkpoint 3\n"); + // return; // just to check + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + u64 pointedaddress = *reinterpret_cast(&buffer[i]); + if (targetaddress >= pointedaddress) + { + distance = targetaddress - pointedaddress; + if (distance < minimum) + { + // minimum = distance; + // sources.clear(); + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + sources.push_back(sourceinfo); + thefileoffset = offset + i; + // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop + // writeback = true; // + } + else if (distance == minimum) + { + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + sources.push_back(sourceinfo); + // sources.push_back(offset + i); + thefileoffset = offset + i; + // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop + // writeback = true; // + // pointerchain.fileoffset[pointerchain.depth] = offset + i; + // pointerchain.offset[pointerchain.depth] = distance; + } + } + } + // if (writeback) + // { + // m_dataDump->putData(offset, buffer, bufferSize); + // m_dataDump->flushBuffer(); + // } + offset += bufferSize; + } + delete[] buffer; // release memory use for the search of sources + + // Now we have fileoffsets stored in sources to repeat this process + // printf("memory scan completed offset is %lx at depth %lx\n\n", minimum, pointerchain.depth); + // pointerchain.offset[pointerchain.depth] = minimum; + pointerchain.depth++; + + // printf("**Found %d sources \n", sources.size()); + for (sourceinfo_t sourceinfo : sources) + { + // targetaddress = 0x1000; + // printf("size of memorydump is %lx ", m_memoryDump1->size()); // I swapped the bookmark + //m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + u64 newtargetaddress; + m_memoryDump1->getData(sourceinfo.foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte + + // u64 checkaddress; // debug use + // m_dataDump->getData(foffset, &checkaddress, sizeof(u64)); //double check it for debug purpose + // printf("fileoffset = %lx thefileoffset =%lx new target address is %lx old target was %lx\n", sourceinfo.foffset, thefileoffset, newtargetaddress, targetaddress); + if (m_forwardonly) + { + if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainBaseAddr + m_mainSize)))) + { + pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; + pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; + pointersearch(newtargetaddress, pointerchain); + } + } + else + { + /* code */ + pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; + pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; + pointersearch(newtargetaddress, pointerchain); + } + } + + return; + + // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); + + // printf("depth is %d new address is %lx offset is %lx code offset is %lx \n", pointerchain.depth, address, pointerchain.fileoffset[pointerchain.depth], pointerchain.offset[pointerchain.depth]); + // if (address < m_mainBaseAddr + m_mainSize) + // { + // printf("target reached!"); + // printf("final offset is %lx \n", address - m_mainBaseAddr); + // pointerchain.depth++; + // pointerchain.offset[pointerchain.depth] = address - m_mainBaseAddr; + // // save pointerchain + // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); + // return; +} +// change address to new one + +// printf("not found \n"); +// return; + +// m_targetmemInfos.clear(); +// m_target = address; +// m_max_depth = depth; +// m_maxrange = range; +// m_numoffset = num; + +// std::vector mainInfos; +// mainInfos.clear(); +// m_low_main_heap_addr = 0x100000000000; +// m_high_main_heap_addr = 0; + +// for (MemoryInfo meminfo : m_memoryInfo) +// { +// // if (m_searchRegion == SEARCH_REGION_RAM) +// // if ((meminfo.perm & Perm_Rw) != Perm_Rw) continue; else +// if (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable) +// continue; + +// if (meminfo.addr < m_low_main_heap_addr) +// m_low_main_heap_addr = meminfo.addr; + +// if ((meminfo.addr + meminfo.size) > m_high_main_heap_addr) +// m_high_main_heap_addr = (meminfo.addr + meminfo.size); + +// m_targetmemInfos.push_back(meminfo); + +// if (meminfo.type == MemType_CodeWritable || meminfo.type == MemType_CodeMutable) +// { +// mainInfos.push_back(meminfo); +// // +// printf("%s%p", "meminfo.addr, ", meminfo.addr); +// printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); +// printf("%s%p", ", meminfo.size, ", meminfo.size); +// printf("%s%lx", ", meminfo.type, ", meminfo.type); +// printf("%s%lx", ", meminfo.attr, ", meminfo.attr); +// printf("%s%lx", ", meminfo.perm, ", meminfo.perm); +// printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); +// printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); +// // +// } +// } + +// m_Time1 = time(NULL); +// printf("searching pointer for address %lx\n Range %lx .. %lx ", m_target, m_low_main_heap_addr, m_high_main_heap_addr); +// for (u8 i = 0; i < 20; i++) +// m_hitcount.offset[i] = 0; + +// for (MemoryInfo meminfo : mainInfos) +// { +// if (meminfo.addr < m_mainBaseAddr) +// continue; +// pointer_chain_t ptrchain; +// ptrchain.offset[0] = meminfo.addr - m_mainBaseAddr; +// ptrchain.depth = 0; +// printf("offset %lx \n ", ptrchain.offset[0]); +// // +// printf("%s%p", "meminfo.addr, ", meminfo.addr); +// printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); +// printf("%s%p", ", meminfo.size, ", meminfo.size); +// printf("%s%lx", ", meminfo.type, ", meminfo.type); +// printf("%s%lx", ", meminfo.attr, ", meminfo.attr); +// printf("%s%lx", ", meminfo.perm, ", meminfo.perm); +// printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); +// printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); +// // +// // return; +// printf("Top level meminfo.addr %lx\n time= %d\n", meminfo.addr, time(NULL) - m_Time1); +// searchpointer(meminfo.addr, meminfo.size / sizeof(u64), meminfo.size, ptrchain); +// // +// printf("hit count depth"); +// for (u8 i = 0; i < 20; i++) +// printf("%d= %d ", i, m_hitcount.offset[i]); + +void GuiCheats::searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain) //assumed range don't extend beyond a segment, need to make seperate call to cover multi segment +{ + // using global to reduce overhead + // use separate function if need to get rid of range in the passed variable // u64 m_max_depth; used in first call + // u64 m_target; + // u64 m_numoffset; + // u64 m_maxrange; + // u64 m_low_main_heap_addr; The lowerst of main or heap start + // u64 m_high_main_heap_addr; The highest + // printf("in function current depth is %d @@@@@@@@@@@@@@@@@@@@@\n", depth); + // return; + m_hitcount.offset[pointerchain.depth]++; + + if (address <= m_target && m_target <= address + range) + { + printf("found ========================="); + pointerchain.offset[pointerchain.depth] = m_target - address; + pointerchain.depth++; + m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); + // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); + printf("found at depth %d\n", pointerchain.depth); + return; + } + if (depth == 0) + { + // printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); + return; + // printf("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); + } + pointerchain.depth++; // for all call + depth--; // for all call + // u8 *buffer = new u8[range]; + u32 num = m_numoffset; + u32 nextrange; + u64 nextaddress; + // u32 endaddress = address + range; + // printf("I am at 1"); + u64 bufferSize = MAX_BUFFER_SIZE; + if (range < bufferSize) + bufferSize = range; + u8 *buffer = new u8[bufferSize]; + // printf("I am at 2"); + for (MemoryInfo meminfo : m_targetmemInfos) // a shorten list that has only the real targets + { + if (address < meminfo.addr) + { + // printf("I am at 4"); + return; // address not accessible} + } + if (address > meminfo.addr + meminfo.size) + { + // printf("I am at 5, address =%lx meminfo.addr = %1x, meminfo.size =%1x \n", address, meminfo.addr, meminfo.size); + continue; // next segment + } + u64 offset = 0; + u64 segmentend = meminfo.addr + meminfo.size; + // printf("I am at 3\n"); + while (address + offset < segmentend) + { + if (segmentend - (address + offset) < bufferSize) + bufferSize = segmentend - (address + offset); + + // printf("reading address %lx bufferSize %lx meminfo.addr is %lx meminfo.size is %lx ", (address + offset), bufferSize, meminfo.addr, meminfo.size); + // printf("Time since last update %d \n", time(NULL) - m_Time1); // printf("Top level meminfo.addr %lx\n time= %d\n", meminfo.addr, time(NULL) - m_Time1); + // return; + m_debugger->readMemory(buffer, bufferSize, (address + offset)); + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) //for (u64 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + nextaddress = *reinterpret_cast(&buffer[i]); + // printf("nextaddress = %lx \n", nextaddress); + if ((nextaddress >= m_low_main_heap_addr) && (nextaddress <= m_high_main_heap_addr)) + { + // printf("found ptr === %lx ======================================= pointerchain.depth is %d ==============offset+i is %d \n",nextaddress, pointerchain.depth, offset + i); + pointerchain.offset[pointerchain.depth] = offset + i; // per call + searchpointer(nextaddress, depth, m_max_range, pointerchain); + num--; + if (num == 0) + { + // printf("not found returning &&&&&&&&&&&&&&&&&&&&\n\n"); + return; + } + } + range -= sizeof(u64); + if (range == 0) + return; + } + + offset += bufferSize; + } + } + delete[] buffer; +} + +/** + * Primary: + * Initial full memory dump regardless of type + * Differentiate between different regions and types + * + * Secondary: + * Second full memory dump regardless of type + * Differentiate between regions and types. (both fix now) + * + * Compare both memory dumps based on type and mode + * Store match addresses into additional file + * Matches should be stored as [MEMADDR][DUMPADDR] for fast comparing later on + * + * Tertiary (Loop infinitely): + * Iterate over match addrs file + * Compare value in memory at [MEMADDR] with value in second memory dump at [DUMPADDR] + * Store match addresses into file (displayDump) + * Dump all values from changed addresses into a file + * Matches should be stored as [MEMADDR][DUMPADDR] for fast comparing later on + */ + +static void _moveLonelyCheats(u8 *buildID, u64 titleID) +{ + std::stringstream lonelyCheatPath; + std::stringstream realCheatPath; + + std::stringstream buildIDStr; + + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; + + lonelyCheatPath << EDIZON_DIR "/cheats/" << buildIDStr.str() << ".txt"; + + if (access(lonelyCheatPath.str().c_str(), F_OK) == 0) + { + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << titleID; + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << "/cheats/"; + mkdir(realCheatPath.str().c_str(), 0777); + + realCheatPath << buildIDStr.str() << ".txt"; + + rename(lonelyCheatPath.str().c_str(), realCheatPath.str().c_str()); + + (new MessageBox("A new cheat has been added for this title. \n Please restart the game to start using it.", MessageBox::OKAY))->show(); + } +} + +static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) +{ + std::stringstream ss; + + ss << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << titleID << "/cheats/"; + + if (!std::filesystem::exists(ss.str())) + return false; + + bool cheatsFolderEmpty = std::filesystem::is_empty(ss.str()); + + for (u8 i = 0; i < 8; i++) + ss << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; + ss << ".txt"; + + bool realCheatDoesExist = std::filesystem::exists(ss.str()); + + return !(cheatsFolderEmpty || realCheatDoesExist); +} diff --git a/source/guis/gui_main.cpp b/source/guis/gui_main.cpp index 5a79386b..79a300a5 100644 --- a/source/guis/gui_main.cpp +++ b/source/guis/gui_main.cpp @@ -19,7 +19,7 @@ static s64 xOffset, xOffsetNext; static bool finishedDrawing = true; static s64 startOffset = 0; - + static color_t arrowColor; GuiMain::GuiMain() : Gui() { diff --git a/source/helpers/diff b/source/helpers/diff index 05ff33fe..6e60b8a5 100644 --- a/source/helpers/diff +++ b/source/helpers/diff @@ -1,40 +1,35 @@ -Comparing files save.cpp and SAVE1.CPP +Comparing files save.cpp and SAVE.CPP1 ***** save.cpp #include "helpers/debugger.hpp" + using json = nlohmann::json; -***** SAVE1.CPP +***** SAVE.CPP1 #include "helpers/debugger.hpp" - using json = nlohmann::json; ***** ***** save.cpp - FsSaveDataInfo info; - Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; - rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. -***** SAVE1.CPP FsSaveDataInfo info; Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; u64 runningid = l_debugger->getRunningApplicationPID(); + rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. +***** SAVE.CPP1 + FsSaveDataInfo info; + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. ***** ***** save.cpp return MAKERESULT(Module_Libnx, LibnxError_NotFound); - for (; R_SUCCEEDED(rc) && total_entries > 0; -***** SAVE1.CPP +***** SAVE.CPP1 return MAKERESULT(Module_Libnx, LibnxError_NotFound); + for (; R_SUCCEEDED(rc) && total_entries > 0; ***** ***** save.cpp - { - if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationTID())) // -hacked to get only the running title - { -***** SAVE1.CPP { if (runningid == 0) { @@ -46,14 +41,19 @@ hacked to get only the running title if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationPID())) // hacked to get only the running title if using cheat engine { +***** SAVE.CPP1 + { + if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationTID())) // +hacked to get only the running title + { ***** ***** save.cpp saveInfoList.push_back(info); + printf("has hit for title\n"); } -***** SAVE1.CPP +***** SAVE.CPP1 saveInfoList.push_back(info); - printf("has hit for title\n"); } ***** diff --git a/source/helpers/save.cpp b/source/helpers/save.cpp index e12c25d5..5edc6eb3 100644 --- a/source/helpers/save.cpp +++ b/source/helpers/save.cpp @@ -183,7 +183,7 @@ Result _getSaveList(std::vector &saveInfoList) else if ((info.save_data_type == FsSaveDataType_Account) && (l_debugger->getRunningApplicationTID() == 0)) // hacked to get only the running title { saveInfoList.push_back(info); - } + } } fsSaveDataInfoReaderClose(&iterator); diff --git a/source/helpers/save.cpp2 b/source/helpers/save.cpp2 new file mode 100644 index 00000000..aff537f4 --- /dev/null +++ b/source/helpers/save.cpp2 @@ -0,0 +1,508 @@ +#include "helpers/save.hpp" + +#include +#include +#include + +#include "helpers/account.hpp" +#include "helpers/title.hpp" +#include "helpers/debugger.hpp" +using json = nlohmann::json; + +s32 deleteDirRecursively(const char *path, bool isSave) +{ + DIR *d = opendir(path); + size_t path_len = strlen(path); + s32 r = -1; + + if (d) + { + struct dirent *p; + + r = 0; + + while (!r && (p = readdir(d))) + { + s32 r2 = -1; + char *buf; + size_t len; + + /* Skip the names "." and ".." as we don't want to recurse on them. */ + if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) + { + continue; + } + + len = path_len + strlen(p->d_name) + 2; + buf = new char[len]; + + if (buf) + { + struct stat statbuf; + + snprintf(buf, len, "%s/%s", path, p->d_name); + + if (!stat(buf, &statbuf)) + { + if (S_ISDIR(statbuf.st_mode)) + r2 = deleteDirRecursively(buf, isSave); + else + r2 = unlink(buf); + } + + delete[] buf; + } + + r = r2; + } + + closedir(d); + } + + if (!r) + r = rmdir(path); + + if (isSave && R_FAILED(fsdevCommitDevice(SAVE_DEV))) + { + printf("Committing failed.\n"); + return -3; + } + + return r; +} + +bool doesFolderExist(const char *path) +{ + struct stat sb; + + return stat(path, &sb) == 0 && S_ISDIR(sb.st_mode); +} + +bool makeExInjDir(char ptr[0x100], u64 titleID, AccountUid userID, bool isInject, const char *injectFolder, bool fromBatch, std::string backupName) +{ + std::stringstream ss; + std::string folder_path(EDIZON_DIR); + + json metadata; + std::string metadata_string; + std::ofstream metadata_file; + std::stringstream metadata_user_id; + std::stringstream metadata_title_id; + + if (!fromBatch) + { + folder_path += "/saves/"; + mkdir(folder_path.c_str(), 0700); + ss << folder_path << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID) * 2) + << std::hex << titleID << "/"; + mkdir(ss.str().c_str(), 0700); + + std::string titleName = ss.str(); + titleName += Title::g_titles[titleID]->getTitleName(); + fclose(fopen(titleName.c_str(), "ab+")); + + if (isInject) + ss << injectFolder << "/"; + else + ss << backupName << "/"; + } + else + { + folder_path += "/batch_saves/"; + mkdir(folder_path.c_str(), 0700); + ss << folder_path << backupName << "/"; + + mkdir(ss.str().c_str(), 0700); + + u64 userIDH = userID.uid[1]; + u64 userIDL = userID.uid[0]; + + ss << std::setfill('0') << std::uppercase << std::hex << userIDH << std::setfill('0') << std::uppercase << std::hex << userIDL << "/"; + mkdir(ss.str().c_str(), 0700); + + ss << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID) * 2) + << std::hex << titleID << "/"; + } + + if (doesFolderExist(ss.str().c_str())) + return false; + strcpy(ptr, ss.str().c_str()); + mkdir(ptr, 0700); + + metadata.clear(); + + u64 userIDH = userID.uid[1]; + u64 userIDL = userID.uid[0]; + metadata_user_id << std::setfill('0') << std::uppercase << std::hex << userIDH; + metadata_user_id << std::setfill('0') << std::uppercase << std::hex << userIDL; + metadata["user_id"] = metadata_user_id.str(); + + metadata["user_name"] = Account::g_accounts[userID]->getUserName(); + + metadata_title_id << std::uppercase << std::setfill('0') << std::setw(sizeof(titleID) * 2) << std::hex << titleID; + metadata["title_id"] = metadata_title_id.str(); + + metadata["title_name"] = Title::g_titles[titleID]->getTitleName(); + metadata["title_version"] = Title::g_titles[titleID]->getTitleVersion(); + metadata_string = metadata.dump(4); + + metadata_file.open(ss.str() + "edizon_save_metadata.json"); + metadata_file << metadata_string << "\n"; + metadata_file.close(); + + return true; +} + +Result _getSaveList(std::vector &saveInfoList) +{ + Result rc = 0; + FsSaveDataInfoReader iterator; + s64 total_entries = 0; + FsSaveDataInfo info; + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; + rc = fsOpenSaveDataInfoReader(&iterator, FsSaveDataSpaceId_User); //See libnx fs.h. + if (R_FAILED(rc)) + { + printf("fsOpenSaveDataIterator() failed: 0x%x\n", rc); + return rc; + } + + rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries); //See libnx fs.h. + if (R_FAILED(rc)) + return rc; + if (total_entries == 0) + return MAKERESULT(Module_Libnx, LibnxError_NotFound); + + for (; R_SUCCEEDED(rc) && total_entries > 0; + rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries)) + { + // if (l_debugger->getRunningApplicationPID() == 0) + // { + // if (info.save_data_type == FsSaveDataType_Account) // hacked to get only the running title if using cheat engine + // { + // saveInfoList.push_back(info); + // } + // } else + if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationPID())) // hacked to get only the running title if using cheat engine + { + saveInfoList.push_back(info); + printf("has hit for title\n"); + } + } + + fsSaveDataInfoReaderClose(&iterator); + delete l_debugger; + return 0; +} + +Result mountSaveByTitleAccountIDs(const u64 titleID, const AccountUid userID, FsFileSystem &tmpfs) +{ + Result rc = 0; + + rc = fsOpen_SaveData(&tmpfs, titleID, userID); //See also libnx fs.h. + if (R_FAILED(rc)) + { + printf("fsMount_SaveData() failed: 0x%x\n", rc); + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&tmpfs); + return rc; + } + + s32 ret = fsdevMountDevice(SAVE_DEV, tmpfs); + if (ret == -1) + { + printf("fsdevMountDevice() failed.\n"); + rc = ret; + } + return rc; +} + +s32 isDirectory(const char *path) +{ + struct stat statbuf; + + if (stat(path, &statbuf) != 0) + return 0; + + return S_ISDIR(statbuf.st_mode); +} + +s32 cpFile(std::string srcPath, std::string dstPath) +{ + FILE *src = fopen(srcPath.c_str(), "rb"); + FILE *dst = fopen(dstPath.c_str(), "wb+"); + + if (src == nullptr || dst == nullptr) + return -1; + + fseek(src, 0, SEEK_END); + rewind(src); + + size_t size; + char *buf = new char[0x50000]; + + u64 offset = 0; + size_t slashpos = srcPath.rfind("/"); + std::string name = srcPath.substr(slashpos + 1, srcPath.length() - slashpos - 1); + while ((size = fread(buf, 1, 0x50000, src)) > 0) + { + fwrite(buf, 1, size, dst); + offset += size; + } + + delete[] buf; + fclose(src); + fclose(dst); + + return 0; +} + +s32 copyAllSave(const char *path, bool isInject, const char exInjDir[0x100]) +{ + DIR *dir; + struct dirent *ent; + + char filenameSave[0x100]; + char filenameSD[0x100]; + + strcpy(filenameSave, "save:/"); + strcat(filenameSave, path); + + strcpy(filenameSD, exInjDir); + strcat(filenameSD, path); + + if (isInject) + dir = opendir(filenameSD); + else + dir = opendir(filenameSave); + + if (dir == nullptr) + { + printf("Failed to open dir: %s\n", isInject ? filenameSD : filenameSave); + return -1; + } + else + { + while ((ent = readdir(dir))) + { + if (strcmp(ent->d_name, "edizon_save_metadata.json") == 0) + continue; + + char filename[0x100]; + + strcpy(filename, path); + strcat(filename, "/"); + strcat(filename, ent->d_name); + + strcpy(filenameSave, "save:/"); + strcat(filenameSave, filename); + + strcpy(filenameSD, exInjDir); + strcat(filenameSD, filename); + + if (isDirectory(isInject ? filenameSD : filenameSave)) + { + if (isInject) + { + mkdir(filenameSave, 0700); + if (R_FAILED(fsdevCommitDevice(SAVE_DEV))) + printf("Failed to commit directory %s.", filenameSave); + } + else + mkdir(filenameSD, 0700); + s32 res = copyAllSave(filename, isInject, exInjDir); + if (res != 0) + return res; + } + else + { + printf("Copying %s... ", filename); + + if (isInject) + { + cpFile(std::string(filenameSD), std::string(filenameSave)); + + if (R_SUCCEEDED(fsdevCommitDevice(SAVE_DEV))) + { // Thx yellows8 + printf("committed.\n"); + } + else + { + printf("fsdevCommitDevice() failed...\n"); + return -2; + } + } + else + { + cpFile(std::string(filenameSave), std::string(filenameSD)); + printf("\n"); + } + } + } + closedir(dir); + return 0; + } +} + +s32 backupSave(u64 titleID, AccountUid userID, bool fromBatch, std::string backupName) +{ + FsFileSystem fs; + s32 res = 0; + + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { + printf("Failed to mount save.\n"); + return 1; + } + + char *ptr = new char[0x100]; + + if (!makeExInjDir(ptr, titleID, userID, false, nullptr, fromBatch, backupName)) + { + fsdevUnmountDevice(SAVE_DEV); + delete[] ptr; + return 2; + } + + if (ptr == nullptr) + { + printf("makeExInjDir failed.\n"); + fsdevUnmountDevice(SAVE_DEV); + delete[] ptr; + return 3; + } + + res = copyAllSave("", false, ptr); + fsdevUnmountDevice(SAVE_DEV); + + delete[] ptr; + + return res; +} + +s32 restoreSave(u64 titleID, AccountUid userID, const char *path) +{ + FsFileSystem fs; + s32 res = 0; + + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { + printf("Failed to mount save.\n"); + return 1; + } + + if (path == nullptr) + { + printf("makeExInjDir failed.\n"); + fsdevUnmountDevice(SAVE_DEV); + return 2; + } + + res = deleteDirRecursively("save:/", true); + + if (!res) + { + printf("Deleting save:/ failed: %d.\n", res); + return 3; + } + + res = copyAllSave("", true, path); + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + + return res; +} + +s32 loadSaveFile(std::vector *buffer, size_t *length, u64 titleID, AccountUid userID, const char *path) +{ + FsFileSystem fs; + size_t size; + + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { + printf("Failed to mount save.\n"); + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + return -1; + } + + char filePath[0x100]; + + strcpy(filePath, "save:/"); + strcat(filePath, path); + + FILE *file = fopen(filePath, "rb"); + + if (file == nullptr) + { + printf("Failed to open file.\n"); + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + return -2; + } + + fseek(file, 0, SEEK_END); + size = ftell(file); + rewind(file); + + if (size <= 0) + { + printf("File reading failed. File length is %zu.\n", size); + fclose(file); + fsdevUnmountDevice(SAVE_DEV); + return -3; + } + + buffer->reserve(size); + fread(&(*buffer)[0], size, 1, file); + fclose(file); + + *length = size; + + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + + return 0; +} + +s32 storeSaveFile(u8 *buffer, size_t length, u64 titleID, AccountUid userID, const char *path) +{ + FsFileSystem fs; + + if (R_FAILED(mountSaveByTitleAccountIDs(titleID, userID, fs))) + { + printf("Failed to mount save.\n"); + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + return -1; + } + + char filePath[0x100]; + + strcpy(filePath, "save:/"); + strcat(filePath, path); + + FILE *file = fopen(filePath, "wb"); + + if (file == nullptr) + { + printf("Failed to open file.\n"); + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + return -2; + } + + fwrite(buffer, length, 1, file); + fclose(file); + + if (R_FAILED(fsdevCommitDevice(SAVE_DEV))) + { + printf("Committing failed.\n"); + return -3; + } + + fsdevUnmountDevice(SAVE_DEV); + fsFsClose(&fs); + + return 0; +} diff --git a/source/main.cpp b/source/main.cpp index 6d909ad1..86e051a1 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -213,7 +213,7 @@ int main(int argc, char **argv) if (l_debugger->getRunningApplicationPID() != 0) { Gui::g_splashDisplayed = true; - Gui::g_nextGui = GUI_CHEATS; + Gui::g_nextGui = GUI_CHEATS; } else Gui::g_nextGui = GUI_MAIN; diff --git a/source/main.cpp1 b/source/main.cpp1 new file mode 100644 index 00000000..6fff0329 --- /dev/null +++ b/source/main.cpp1 @@ -0,0 +1,357 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "guis/gui.hpp" +#include "guis/gui_main.hpp" +#include "guis/gui_editor.hpp" +#include "guis/gui_tx_warning.hpp" +#include "guis/gui_cheats.hpp" +#include "guis/gui_about.hpp" +#include "guis/gui_guide.hpp" + +#include "helpers/title.hpp" + +#include "theme.h" +#include "helpers/util.h" +#include "helpers/config.hpp" + +#define LONG_PRESS_DELAY 2 +#define LONG_PRESS_ACTIVATION_DELAY 300 + +char* g_edizonPath; + +static int debugOutputFile; + +static bool updateThreadRunning = false; +static Mutex mutexCurrGui; +static Gui* currGui = nullptr; +static s64 inputTicker = 0; + +static u32 kheld = 0, kheldOld = 0; +static u32 kdown = 0; + +void initTitles() { + std::vector saveInfoList; + + _getSaveList(saveInfoList); + + s32 userCount = 0; + s32 foundUserCount = 0; + + accountGetUserCount(&userCount); + + AccountUid userIDs[userCount]; + accountListAllUsers(userIDs, userCount, &foundUserCount); + + for (auto saveInfo : saveInfoList) { + bool accountPresent = false; + + for (s32 i = 0; i < foundUserCount; i++) + if (userIDs[i] == saveInfo.uid) + accountPresent = true; + + if (!accountPresent) continue; + + if (Title::g_titles.find(saveInfo.application_id) == Title::g_titles.end()) + Title::g_titles.insert({(u64)saveInfo.application_id, new Title(saveInfo)}); + + Title::g_titles[saveInfo.application_id]->addUserID(saveInfo.uid); + + if (Account::g_accounts.find(saveInfo.uid) == Account::g_accounts.end()) { + Account *account = new Account(saveInfo.uid); + + if (!account->isInitialized()) { + delete account; + continue; + } + Account::g_accounts.insert(std::make_pair(static_cast(saveInfo.uid), account)); + } + // break; //hack + } +} + +void update() { + while (updateThreadRunning) { + auto begin = std::chrono::steady_clock::now(); + + mutexLock(&mutexCurrGui); + if (currGui != nullptr) + currGui->update(); + mutexUnlock(&mutexCurrGui); + + if (kheld & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN)) inputTicker++; + else inputTicker = 0; + + svcSleepThread(1.0E6 - std::chrono::duration(std::chrono::steady_clock::now() - begin).count()); + } +} + +void createFolders() { + printf(EDIZON_DIR "/saves\n"); + mkdir("/switch", 0777); + mkdir(EDIZON_DIR "", 0777); + mkdir(EDIZON_DIR "/saves", 0777); + mkdir(EDIZON_DIR "/batch_saves", 0777); + mkdir(EDIZON_DIR "/restore", 0777); + mkdir(EDIZON_DIR "/editor", 0777); + mkdir(EDIZON_DIR "/editor/scripts", 0777); + mkdir(EDIZON_DIR "/editor/scripts/lib", 0777); + mkdir(EDIZON_DIR "/editor/scripts/lib/python3.5", 0777); +} + +void requestDraw() { + if (currGui != nullptr) + currGui->draw(); +} + +void serviceInitialize() { + setsysInitialize(); + socketInitializeDefault(); + nsInitialize(); + accountInitialize(AccountServiceType_Administrator); + plInitialize(PlServiceType_User); + psmInitialize(); + pminfoInitialize(); + pmdmntInitialize(); + romfsInit(); + hidsysInitialize(); + pcvInitialize(); + clkrstInitialize(); + ledInit(); + + curl_global_init(CURL_GLOBAL_ALL); + + u64 pid = 0; + Title::g_activeTitle = 0; + + pmdmntGetApplicationProcessId(&pid); + pminfoGetProgramId(&Title::g_activeTitle, pid); + + accountGetLastOpenedUser(&Account::g_activeUser); +} + +void serviceExit() { + setsysExit(); + socketExit(); + nsExit(); + accountExit(); + plExit(); + psmExit(); + pminfoExit(); + pmdmntExit(); + romfsExit(); + hidsysExit(); + pcvExit(); + clkrstExit(); + + curl_global_cleanup(); + + close(debugOutputFile); + +} + +void redirectStdio() { + nxlinkStdio(); + + debugOutputFile = open(EDIZON_DIR "/EdiZon.log", O_APPEND | O_WRONLY); + + if (debugOutputFile >= 0) { + fflush(stdout); + dup2(debugOutputFile, STDOUT_FILENO); + fflush(stderr); + dup2(debugOutputFile, STDERR_FILENO); + } +} + +int main(int argc, char** argv) { + void *haddr; + + serviceInitialize(); + + redirectStdio(); + + framebufferCreate(&Gui::g_fb_obj, nwindowGetDefault(), 1280, 720, PIXEL_FORMAT_RGBA_8888, 2); + framebufferMakeLinear(&Gui::g_fb_obj); + + ColorSetId colorSetId; + setsysGetColorSetId(&colorSetId); + setTheme(colorSetId); + + initTitles(); + + printf("%s\n", EDIZON_DIR); + + createFolders(); + + Config::readConfig(); + + Gui::g_nextGui = GUI_CHEATS; + + if (isServiceRunning("tx") && !isServiceRunning("rnx") && !Config::getConfig()->hideSX) + Gui::g_nextGui = GUI_TX_WARNING; + + g_edizonPath = new char[strlen(argv[0]) + 1]; + strcpy(g_edizonPath, argv[0] + 5); + + mutexInit(&mutexCurrGui); + + updateThreadRunning = true; + std::thread updateThread(update); + + + while (appletMainLoop()) { + hidScanInput(); + kheld = hidKeysHeld(CONTROLLER_P1_AUTO); + kdown = hidKeysDown(CONTROLLER_P1_AUTO); + + if (Gui::g_nextGui != GUI_INVALID) { + mutexLock(&mutexCurrGui); + if (currGui != nullptr) { + delete currGui; + currGui = nullptr; + } + + do { + gui_t nextGuiStart = Gui::g_nextGui; + switch (Gui::g_nextGui) { + case GUI_MAIN: + currGui = new GuiMain(); + break; + case GUI_EDITOR: + currGui = new GuiEditor(); + break; + case GUI_TX_WARNING: + currGui = new GuiTXWarning(); + break; + case GUI_CHEATS: + currGui = new GuiCheats(); + break; + case GUI_GUIDE: + currGui = new GuiGuide(); + break; + case GUI_ABOUT: + currGui = new GuiAbout(); + break; + + case GUI_INVALID: [[fallthrough]] + default: break; + } + if (nextGuiStart == Gui::g_nextGui) + Gui::g_nextGui = GUI_INVALID; + } while(Gui::g_nextGui != GUI_INVALID); + + mutexUnlock(&mutexCurrGui); + } + + if (currGui != nullptr) { + currGui->draw(); + + if (Gui::g_splashDisplayed) { + if (inputTicker > LONG_PRESS_ACTIVATION_DELAY && (inputTicker % LONG_PRESS_DELAY) == 0) { + if (Gui::g_currMessageBox != nullptr) + Gui::g_currMessageBox->onInput(kheld); + else if (Gui::g_currListSelector != nullptr) + Gui::g_currListSelector->onInput(kheld); + else + currGui->onInput(kheld); + } else if (kdown || hidKeysUp(CONTROLLER_P1_AUTO)) { + if (Gui::g_currMessageBox != nullptr) + Gui::g_currMessageBox->onInput(kdown); + else if (Gui::g_currListSelector != nullptr) + Gui::g_currListSelector->onInput(kdown); + else + currGui->onInput(kdown); + } + } + } + + if (kheld != kheldOld) { + inputTicker = 0; + } + + static touchPosition touchPosStart, touchPosCurr, touchPosOld; + static u8 touchCount, touchCountOld; + static bool touchHappend = false; + + touchCount = hidTouchCount(); + + if (touchCount > 0) + hidTouchRead(&touchPosCurr, 0); + + if(touchCount > 0 && touchCountOld == 0) + hidTouchRead(&touchPosStart, 0); + + if (abs(static_cast(touchPosStart.px - touchPosCurr.px)) < 10 && abs(static_cast(touchPosStart.py - touchPosCurr.py)) < 10) { + if (touchCount == 0 && touchCountOld > 0) { + touchHappend = true; + + if (Gui::g_currMessageBox != nullptr) + Gui::g_currMessageBox->onTouch(touchPosCurr); + else if (Gui::g_currListSelector != nullptr) + Gui::g_currListSelector->onTouch(touchPosCurr); + else + currGui->onTouch(touchPosCurr); + } + } else if (touchCount > 0) { + if (Gui::g_currMessageBox != nullptr) + Gui::g_currMessageBox->onGesture(touchPosStart, touchPosCurr, false); + else if (Gui::g_currListSelector != nullptr) + Gui::g_currListSelector->onGesture(touchPosStart, touchPosCurr, false); + else + currGui->onGesture(touchPosStart, touchPosCurr, false); + } + + if (touchCount == 0 && touchCountOld > 0 && !touchHappend) { + if (Gui::g_currMessageBox != nullptr) + Gui::g_currMessageBox->onGesture(touchPosStart, touchPosCurr, true); + else if (Gui::g_currListSelector != nullptr) + Gui::g_currListSelector->onGesture(touchPosStart, touchPosCurr, true); + else + currGui->onGesture(touchPosStart, touchPosCurr, true); + } + + touchCountOld = touchCount; + touchPosOld = touchPosCurr; + touchHappend = false; + + kheldOld = kheld; + + if (Gui::g_requestExit) { + if (Gui::g_currMessageBox == nullptr) + break; + } + } + + updateThreadRunning = false; + + updateThread.join(); + + delete[] g_edizonPath; + + for (auto it = Title::g_titles.begin(); it != Title::g_titles.end(); it++) + delete it->second; + + for (auto it = Account::g_accounts.begin(); it != Account::g_accounts.end(); it++) + delete it->second; + + Title::g_titles.clear(); + Account::g_accounts.clear(); + + if (currGui != nullptr) + delete currGui; + + framebufferClose(&Gui::g_fb_obj); + + serviceExit(); + + return 0; +} From 091f52ea5adf448065c52541e4592d859101a51b Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 20 Jul 2020 12:02:36 +0800 Subject: [PATCH 05/95] Move splash screen to before scanning saves to avoid black screen --- source/guis/gui_main.cpp | 2 +- source/main.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/source/guis/gui_main.cpp b/source/guis/gui_main.cpp index 79a300a5..e21b66a0 100644 --- a/source/guis/gui_main.cpp +++ b/source/guis/gui_main.cpp @@ -69,7 +69,7 @@ void GuiMain::draw() { Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x5D, 0x4F, 0x4E, 0xFF)); Gui::drawImage(Gui::g_framebuffer_width / 2 - 128, Gui::g_framebuffer_height / 2 - 128, 256, 256, edizon_logo_bin, IMAGE_MODE_BGR24); - if (splashCnt++ >= 70) + // if (splashCnt++ >= 70) Gui::g_splashDisplayed = true; Gui::endDraw(); diff --git a/source/main.cpp b/source/main.cpp index 86e051a1..94a4f635 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -201,6 +201,15 @@ int main(int argc, char **argv) setsysGetColorSetId(&colorSetId); setTheme(colorSetId); +#if SPLASH_ENABLED + if (!Gui::g_splashDisplayed) + { + static Gui *currGui = nullptr; + currGui = new GuiMain(); + currGui->draw(); + } +#endif + initTitles(); printf("%s\n", EDIZON_DIR); @@ -213,7 +222,7 @@ int main(int argc, char **argv) if (l_debugger->getRunningApplicationPID() != 0) { Gui::g_splashDisplayed = true; - Gui::g_nextGui = GUI_CHEATS; + Gui::g_nextGui = GUI_CHEATS; } else Gui::g_nextGui = GUI_MAIN; From 4de1727ace2fb93c509e114fc746c1724add892c Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 00:26:55 +0800 Subject: [PATCH 06/95] with splash change and added abort and plus key to start pointer search and attempt to bookmark file name change --- include/guis/gui_cheats.hpp | 4 ++ source/guis/gui_cheats.cpp | 126 +++++++++++++++++++++++++++++++----- source/main.cpp | 17 ++--- 3 files changed, 122 insertions(+), 25 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index f44d65f8..36c867b1 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -78,6 +78,8 @@ class GuiCheats : public Gui u64 m_max_range = 0x300; u64 m_low_main_heap_addr = 0x100000000; u64 m_high_main_heap_addr = 0x10000000000; + u64 m_pointer_found = 0; + bool m_abort = false; std::map m_frozenAddresses; @@ -124,6 +126,8 @@ class GuiCheats : public Gui char label[18]; searchType_t type; pointer_chain_t pointer; + bool heap = true; + u32 offset = 0; }; pointer_chain_t m_hitcount; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 0558b69d..9c524334 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -105,7 +105,7 @@ GuiCheats::GuiCheats() : Gui() m_frozenAddresses.insert({frozenAddresses[i].address, frozenAddresses[i].value.value}); } - MemoryInfo meminfo = {0}; + MemoryInfo meminfo = {0}; u64 lastAddr = 0; do @@ -123,7 +123,7 @@ GuiCheats::GuiCheats() : Gui() for (u64 addrOffset = meminfo.addr; addrOffset < meminfo.addr + meminfo.size; addrOffset += 0x20000000) { - switch (meminfo.type) + switch (meminfo.type) { case MemType_CodeStatic: case MemType_CodeMutable: @@ -182,23 +182,84 @@ GuiCheats::GuiCheats() : Gui() m_memoryDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); - // start mod bookmark - + // start mod bookmark BM2 + // std::stringstream filebuildIDStr; + // { + // std::stringstream buildIDStr; + // for (u8 i = 0; i < 8; i++) + // buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + // buildIDStr.str("attrdumpbookmark"); + // filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".dat"; + // } if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDumpBookmark->getDumpInfo().heapBaseAddress != m_heapBaseAddr) + // is a different run need to refresh the list { + // rename(filebuildIDStr.str().c_str(), EDIZON_DIR "/tempbookmark.dat"); + // MemoryDump *tempdump; + // tempdump = new MemoryDump(EDIZON_DIR "/tempbookmark.dat", DumpType::ADDR, false); m_memoryDumpBookmark->clear(); m_AttributeDumpBookmark->clear(); delete m_memoryDumpBookmark; delete m_AttributeDumpBookmark; m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, true); m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, true); + // m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); + + // if (tempdump->size() > 0) // create new bookmark list from past + // { + + // u64 offset = 0; + // u64 bufferSize = MAX_BUFFER_SIZE % sizeof(bookmark_t) * sizeof(bookmark_t); // need to be multiple of + // u8 *buffer = new u8[bufferSize]; + + // while (offset < tempdump->size()) + // { + // if (tempdump->size() - offset < bufferSize) + // bufferSize = tempdump->size() - offset; + // tempdump->getData(offset, buffer, bufferSize); + // bookmark_t bookmark; + // u64 address; + // for (u64 i = 0; i < bufferSize; i += sizeof(bookmark_t)) + // { + // memcpy(&bookmark, buffer + i, sizeof(bookmark_t)); + // if (bookmark.heap) + // { + // address = bookmark.offset + m_heapBaseAddr; + // } + // else + // { + // address = bookmark.offset + m_mainBaseAddr; + // } + // // check memory before adding + // MemoryInfo meminfo; + // meminfo = m_debugger->queryMemory(address); + // if (meminfo.perm == Perm_Rw) + // { + // m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + // m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + // } + // } + + // offset += bufferSize; + // } + + // delete buffer; + // m_AttributeDumpBookmark->flushBuffer(); + // m_memoryDumpBookmark->flushBuffer(); + // } + + // delete tempdump; + // remove(EDIZON_DIR "/tempbookmark.dat"); + // } + // else + // m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); m_AttributeDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); - // m_memoryDumpBookmark->setSearchParams(searchType, searchMode, searchRegion, searchValue1, searchValue2); } else m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); // end mod + std::stringstream ss; // check this @@ -609,7 +670,7 @@ void GuiCheats::drawSearchPointerMenu() if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 4) Gui::drawRectangled(622 + strWidth, 405, 3, 35, currTheme.highlightColor); - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0EF Start Search \uE0E1 Back \uE0E0 Edit", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0EF Start Search \uE0E1 Abort \uE0E0 Edit", ALIGNED_RIGHT); // if (m_selectedEntry == 3) // Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 155, 345, 310, 90, currTheme.highlightColor); @@ -853,6 +914,8 @@ void GuiCheats::onInput(u32 kdown) else if (m_searchMenuLocation == SEARCH_POINTER) { m_searchMenuLocation = SEARCH_NONE; + m_abort = true; + printf("abort pressed .. \n"); } else if (m_searchMenuLocation == SEARCH_editRAM) { @@ -885,21 +948,25 @@ void GuiCheats::onInput(u32 kdown) if (m_debugger->getRunningApplicationPID() == 0) return; - + // BM2 if (m_searchMenuLocation == SEARCH_POINTER) { + if (kdown & KEY_PLUS) + { + m_abort = false; + (new Snackbar("Starting pointer search"))->show(); + startpointersearch(m_EditorBaseAddr); + } if (kdown & KEY_UP) { if (m_selectedEntry > 0) m_selectedEntry--; } - if (kdown & KEY_DOWN) { if (m_selectedEntry < 4) m_selectedEntry++; } - if (kdown & KEY_R) { if (m_selectedEntry == 0 && m_max_depth < MAX_POINTER_DEPTH) @@ -919,7 +986,6 @@ void GuiCheats::onInput(u32 kdown) m_forwarddump = !m_forwarddump; }; } - if (kdown & KEY_L) { if (m_selectedEntry == 0 && m_max_depth > 2) @@ -1066,6 +1132,18 @@ void GuiCheats::onInput(u32 kdown) bookmark_t bookmark; bookmark.type = m_searchType; Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + + if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + { + bookmark.offset = address - m_memoryDump->getDumpInfo().heapBaseAddress; + bookmark.heap = true; + } + else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + { + bookmark.offset = address - m_memoryDump->getDumpInfo().mainBaseAddress; + bookmark.heap = false; + } + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); m_AttributeDumpBookmark->flushBuffer(); @@ -1089,6 +1167,7 @@ void GuiCheats::onInput(u32 kdown) printf("start pointer search ....................\n"); m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); printf("Address %lx \n\n\n", m_EditorBaseAddr); + m_abort = false; m_Time1 = time(NULL); // m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); m_searchValue[0]._u64 = m_EditorBaseAddr - 0x800; @@ -1341,6 +1420,7 @@ void GuiCheats::onInput(u32 kdown) { if (m_memoryDump1 != nullptr) { // in bookmark mode + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_searchMenuLocation = SEARCH_POINTER; // (new Snackbar("Searching pointer "))->show(); } @@ -1956,7 +2036,7 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory MemoryDump *newdataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); - MemoryDump *newstringDump = new MemoryDump(EDIZON_DIR "/stringdump.dat", DumpType::DATA, true); // to del when not needed + MemoryDump *newstringDump = new MemoryDump(EDIZON_DIR "/stringdump.csv", DumpType::DATA, true); // to del when not needed helperinfo_t helperinfo; helperinfo.count = 0; @@ -2115,9 +2195,14 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s newdataDump->addData((u8 *)&realValue, sizeof(u64)); helperinfo.count++; // printf("%lx,%lx\n",address,realValue); - char st[25]; // replace the printf - snprintf(st, 25, "'%lx,'%lx\n", address, realValue); // - newstringDump->addData((u8 *)&st, sizeof(st)); // + std::stringstream ss; // replace the printf + ss.str(""); + ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; + char st[27]; + // st[28] = 13; + snprintf(st, 27, "%s\n", ss.str().c_str()); // + newstringDump->addData((u8 *)&st, sizeof(st)); // } break; } @@ -3081,7 +3166,9 @@ void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDu m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); // pointed targets is in this file m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, true); // create file but maybe later just open it pointer_chain_t pointerchain; - printf("check point 1\n"); + printf("Start pointer search %lx\n", targetaddress); + m_Time1 = time(NULL); + m_pointer_found = 0; pointerchain.depth = 0; try { @@ -3098,6 +3185,8 @@ void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDu m_pointeroffsetDump->flushBuffer(); delete m_pointeroffsetDump; + printf("End pointer search \n"); + printf("Time taken =%d Found %d pointer chain\n", time(NULL) - m_Time1, m_pointer_found); } void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain) //MemoryDump **displayDump, MemoryDump **dataDump, @@ -3120,6 +3209,7 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc printf("+%lx z=%d ", pointerchain.offset[z], z); printf("\n\n"); // printf("\nsize=%d\n", sizeof(pointer_chain_t)); + m_pointer_found++; return; // consider don't return to find more }; @@ -3151,6 +3241,8 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc // return; // just to check for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) { + if (m_abort) + return; u64 pointedaddress = *reinterpret_cast(&buffer[i]); if (targetaddress >= pointedaddress) { @@ -3198,7 +3290,7 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc // pointerchain.offset[pointerchain.depth] = minimum; pointerchain.depth++; - // printf("**Found %d sources \n", sources.size()); + printf("**Found %d sources for address %lx at depth %d\n", sources.size(), targetaddress, pointerchain.depth); for (sourceinfo_t sourceinfo : sources) { // targetaddress = 0x1000; @@ -3227,7 +3319,7 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc pointersearch(newtargetaddress, pointerchain); } } - + return; // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); diff --git a/source/main.cpp b/source/main.cpp index 94a4f635..a76f37ac 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -201,6 +201,15 @@ int main(int argc, char **argv) setsysGetColorSetId(&colorSetId); setTheme(colorSetId); + Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; + if (l_debugger->getRunningApplicationPID() != 0) + { + Gui::g_splashDisplayed = true; + Gui::g_nextGui = GUI_CHEATS; + } + else + Gui::g_nextGui = GUI_MAIN; + #if SPLASH_ENABLED if (!Gui::g_splashDisplayed) { @@ -218,14 +227,6 @@ int main(int argc, char **argv) Config::readConfig(); - Debugger *l_debugger = new Debugger(); //Debugger *m_debugger; - if (l_debugger->getRunningApplicationPID() != 0) - { - Gui::g_splashDisplayed = true; - Gui::g_nextGui = GUI_CHEATS; - } - else - Gui::g_nextGui = GUI_MAIN; if (isServiceRunning("tx") && !isServiceRunning("rnx") && !Config::getConfig()->hideSX) Gui::g_nextGui = GUI_TX_WARNING; From 8aecba423ac3d39aac1b2f8d8e9ffcc01bab466e Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 07:45:10 +0800 Subject: [PATCH 07/95] partial offset save implementation done --- source/guis/gui_cheats.cpp | 64 ++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 9c524334..e086cc99 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -105,7 +105,7 @@ GuiCheats::GuiCheats() : Gui() m_frozenAddresses.insert({frozenAddresses[i].address, frozenAddresses[i].value.value}); } - MemoryInfo meminfo = {0}; + MemoryInfo meminfo = {0}; u64 lastAddr = 0; do @@ -123,7 +123,7 @@ GuiCheats::GuiCheats() : Gui() for (u64 addrOffset = meminfo.addr; addrOffset < meminfo.addr + meminfo.size; addrOffset += 0x20000000) { - switch (meminfo.type) + switch (meminfo.type) { case MemType_CodeStatic: case MemType_CodeMutable: @@ -156,7 +156,6 @@ GuiCheats::GuiCheats() : Gui() m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::UNDEFINED, false); // start mod make list of memory found toggle between current find and bookmark m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, false); - m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, false); // end mod if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDump->getDumpInfo().heapBaseAddress != m_heapBaseAddr) @@ -183,26 +182,59 @@ GuiCheats::GuiCheats() : Gui() m_memoryDump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); // start mod bookmark BM2 - // std::stringstream filebuildIDStr; - // { - // std::stringstream buildIDStr; - // for (u8 i = 0; i < 8; i++) - // buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; - // buildIDStr.str("attrdumpbookmark"); - // filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".dat"; - // } + std::stringstream filebuildIDStr; + { + std::stringstream buildIDStr; + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + // buildIDStr.str("attdumpbookmark"); + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".dat"; + } + + m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); if (m_debugger->getRunningApplicationPID() == 0 || m_memoryDumpBookmark->getDumpInfo().heapBaseAddress != m_heapBaseAddr) // is a different run need to refresh the list { + // delete m_AttributeDumpBookmark; // rename(filebuildIDStr.str().c_str(), EDIZON_DIR "/tempbookmark.dat"); - // MemoryDump *tempdump; - // tempdump = new MemoryDump(EDIZON_DIR "/tempbookmark.dat", DumpType::ADDR, false); + MemoryDump *tempdump; + tempdump = new MemoryDump(EDIZON_DIR "/tempbookmark.dat", DumpType::ADDR, true); m_memoryDumpBookmark->clear(); - m_AttributeDumpBookmark->clear(); delete m_memoryDumpBookmark; - delete m_AttributeDumpBookmark; m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, true); - m_AttributeDumpBookmark = new MemoryDump(EDIZON_DIR "/attdumpbookmark.dat", DumpType::ADDR, true); + + if (m_AttributeDumpBookmark->size() > 0) + { + bookmark_t bookmark; + u64 address; + for (u64 i = 0; i < m_AttributeDumpBookmark->size(); i += sizeof(bookmark_t)) + { + m_AttributeDumpBookmark->getData(i, (u8 *)&bookmark, sizeof(bookmark_t)); + if (bookmark.heap) + { + address = bookmark.offset + m_heapBaseAddr; + } + else + { + address = bookmark.offset + m_mainBaseAddr; + } + // check memory before adding + MemoryInfo meminfo; + meminfo = m_debugger->queryMemory(address); + if (meminfo.perm == Perm_Rw) + { + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + tempdump->addData((u8 *)&bookmark, sizeof(bookmark_t)); + } + } + } + tempdump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + tempdump->flushBuffer(); + delete tempdump; + + m_AttributeDumpBookmark->clear(); + delete m_AttributeDumpBookmark; + m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); // m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); // if (tempdump->size() > 0) // create new bookmark list from past From ed52cb6d4fedb948121060ebec643f2283c9c298 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 08:14:12 +0800 Subject: [PATCH 08/95] bookmark OK --- source/guis/gui_cheats.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index e086cc99..2214630f 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -234,7 +234,19 @@ GuiCheats::GuiCheats() : Gui() m_AttributeDumpBookmark->clear(); delete m_AttributeDumpBookmark; - m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); + + remove(filebuildIDStr.str().c_str()); + while (access(filebuildIDStr.str().c_str(), F_OK) == 0) + { + printf("waiting for delete\n"); + } + rename(EDIZON_DIR "/tempbookmark.dat", filebuildIDStr.str().c_str()); + while (access(filebuildIDStr.str().c_str(), F_OK) != 0) + { + printf("waiting for rename\n"); + } + + m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); // m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); // if (tempdump->size() > 0) // create new bookmark list from past From 550fc7f18eed52e7c93b5093972b63d3ef5a9ca3 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 09:33:39 +0800 Subject: [PATCH 09/95] Bookmark edit label OK --- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 147 ++++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 64 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 36c867b1..0fcb6334 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -128,6 +128,7 @@ class GuiCheats : public Gui pointer_chain_t pointer; bool heap = true; u32 offset = 0; + bool deleted =false; }; pointer_chain_t m_hitcount; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 2214630f..eb525dc3 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1170,32 +1170,42 @@ void GuiCheats::onInput(u32 kdown) // add bookmark if (kdown & KEY_PLUS && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { - u64 address = 0; - m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); - - bookmark_t bookmark; - bookmark.type = m_searchType; - Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); - - if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) - { - bookmark.offset = address - m_memoryDump->getDumpInfo().heapBaseAddress; - bookmark.heap = true; + if (m_memoryDump1 != nullptr) + { //Bookmark case + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", bookmark.label, SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); } - else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + else { - bookmark.offset = address - m_memoryDump->getDumpInfo().mainBaseAddress; - bookmark.heap = false; - } + u64 address = 0; + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); - m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); - m_AttributeDumpBookmark->flushBuffer(); + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); - m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); - m_memoryDumpBookmark->flushBuffer(); + if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + { + bookmark.offset = address - m_memoryDump->getDumpInfo().heapBaseAddress; + bookmark.heap = true; + } + else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + { + bookmark.offset = address - m_memoryDump->getDumpInfo().mainBaseAddress; + bookmark.heap = false; + } - (new Snackbar("Address added to bookmark!"))->show(); // prompt for label - printf("%s\n", "PLUS key pressed"); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + + (new Snackbar("Address added to bookmark!"))->show(); // prompt for label + printf("%s\n", "PLUS key pressed"); + } } // add bookmark end // show memory editor @@ -1346,55 +1356,64 @@ void GuiCheats::onInput(u32 kdown) { //make sure not using bookmark m_searchType if (m_memoryDump1 != nullptr) - { - m_memoryDump = m_memoryDump1; - m_memoryDump1 = nullptr; + { //Bookmark case + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + bookmark.deleted = true; + m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // m_memoryDumpBookmark->flushBuffer(); + // m_memoryDump = m_memoryDump1; + // m_memoryDump1 = nullptr; } - m_addresslist_offset = 0; - // end mod - if (m_memoryDump->size() == 0) + else { - std::vector options; - if (m_frozenAddresses.size() == 0) - return; - - std::stringstream ss; - for (auto [addr, value] : m_frozenAddresses) + m_addresslist_offset = 0; + // end mod + if (m_memoryDump->size() == 0) { - ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr - m_addressSpaceBaseAddr) << " ] "; - ss << "( " << std::dec << value << " )"; - options.push_back(ss.str()); - ss.str(""); + std::vector options; + + if (m_frozenAddresses.size() == 0) + return; + + std::stringstream ss; + for (auto [addr, value] : m_frozenAddresses) + { + ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr - m_addressSpaceBaseAddr) << " ] "; + ss << "( " << std::dec << value << " )"; + options.push_back(ss.str()); + ss.str(""); + } + + (new ListSelector("Frozen Addresses", "\uE0E0 Unfreeze \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { + if (k & KEY_A) + { + auto itr = m_frozenAddresses.begin(); + std::advance(itr, selectedItem); + + dmntchtDisableFrozenAddress(itr->first); + m_frozenAddresses.erase(itr->first); + } + }) + ->show(); } + else + { + m_memoryDump->clear(); + remove(EDIZON_DIR "/memdump1.dat"); + remove(EDIZON_DIR "/memdump1a.dat"); + remove(EDIZON_DIR "/memdump2.dat"); + remove(EDIZON_DIR "/memdump3.dat"); + + // m_searchType = SEARCH_TYPE_NONE; + // m_searchMode = SEARCH_MODE_NONE; + // m_searchRegion = SEARCH_REGION_NONE; + // m_searchValue[0]._u64 = 0; + // m_searchValue[1]._u64 = 0; - (new ListSelector("Frozen Addresses", "\uE0E0 Unfreeze \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { - if (k & KEY_A) - { - auto itr = m_frozenAddresses.begin(); - std::advance(itr, selectedItem); - - dmntchtDisableFrozenAddress(itr->first); - m_frozenAddresses.erase(itr->first); - } - }) - ->show(); - } - else - { - m_memoryDump->clear(); - remove(EDIZON_DIR "/memdump1.dat"); - remove(EDIZON_DIR "/memdump1a.dat"); - remove(EDIZON_DIR "/memdump2.dat"); - remove(EDIZON_DIR "/memdump3.dat"); - - // m_searchType = SEARCH_TYPE_NONE; - // m_searchMode = SEARCH_MODE_NONE; - // m_searchRegion = SEARCH_REGION_NONE; - // m_searchValue[0]._u64 = 0; - // m_searchValue[1]._u64 = 0; - - m_menuLocation = CHEATS; + m_menuLocation = CHEATS; + } } } // start mod KEY_PLUS From c35845d8a793999fbf30796ca9791b3acbbd2a85 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 10:09:10 +0800 Subject: [PATCH 10/95] bookmark delete done --- source/guis/gui_cheats.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index eb525dc3..24074f31 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -218,6 +218,7 @@ GuiCheats::GuiCheats() : Gui() { address = bookmark.offset + m_mainBaseAddr; } + if (bookmark.deleted) continue; // don't add deleted bookmark // check memory before adding MemoryInfo meminfo; meminfo = m_debugger->queryMemory(address); @@ -624,7 +625,7 @@ void GuiCheats::draw() ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; Gui::drawRectangle(Gui::g_framebuffer_width - 555, 300 + line * 40, 545, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 545, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, bookmark.label, ALIGNED_LEFT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 545, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, bookmark.deleted ? "To be deleted" : bookmark.label, ALIGNED_LEFT); Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 340, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); } } @@ -1359,7 +1360,7 @@ void GuiCheats::onInput(u32 kdown) { //Bookmark case bookmark_t bookmark; m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); - bookmark.deleted = true; + bookmark.deleted = !bookmark.deleted; m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); // m_memoryDumpBookmark->flushBuffer(); // m_memoryDump = m_memoryDump1; From 5c1c9938c78ccff06b169caf32b95d5b99d32946 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 10:52:50 +0800 Subject: [PATCH 11/95] bug fix on higher order byte not clear for less than 64 bit type --- Makefile | 2 +- source/guis/gui_cheats.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 322a6906..ad808596 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 2 +VERSION_MICRO := 3 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 24074f31..579a5923 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -218,7 +218,8 @@ GuiCheats::GuiCheats() : Gui() { address = bookmark.offset + m_mainBaseAddr; } - if (bookmark.deleted) continue; // don't add deleted bookmark + if (bookmark.deleted) + continue; // don't add deleted bookmark // check memory before adding MemoryInfo meminfo; meminfo = m_debugger->queryMemory(address); @@ -1099,6 +1100,7 @@ void GuiCheats::onInput(u32 kdown) if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS) { printf("start checking pointer\n"); + (new Snackbar("Adding address from cheat not supported yet"))->show(); // pointercheck(); disable for now; } @@ -1175,8 +1177,8 @@ void GuiCheats::onInput(u32 kdown) { //Bookmark case bookmark_t bookmark; m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); - Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", bookmark.label, SwkbdType_QWERTY, bookmark.label, 18); - m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + if (Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", bookmark.label, SwkbdType_QWERTY, bookmark.label, 18)) + m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); } else { @@ -1773,7 +1775,7 @@ void GuiCheats::onInput(u32 kdown) } if (std::string(str) == "") return; - + m_searchValue[m_searchValueIndex]._u64 = 0; //hack to fix bug elsewhere if (m_searchValueFormat == FORMAT_HEX) { m_searchValue[m_searchValueIndex]._u64 = static_cast(std::stoul(str, nullptr, 16)); From b99e0dfc7d850e45c38691d33dd9d9ae020dffef Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 21 Jul 2020 18:12:36 +0800 Subject: [PATCH 12/95] Add bookmark from code done --- include/guis/gui_cheats.hpp | 4 ++ source/guis/gui_cheats.cpp | 139 ++++++++++++++++++++++++++++++++++-- 2 files changed, 139 insertions(+), 4 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 0fcb6334..aa7cfe5f 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -107,6 +107,10 @@ class GuiCheats : public Gui u64 offset; }; +#define IS_PTRCODE_START 0x580F0000 +#define IS_OFFSET 0x580F1000 +#define IS_FINAL 0x780F0000 + #define MAX_NUM_SOURCE_POINTER 200 // bound check for debugging; #define MAX_POINTER_DEPTH 6 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 579a5923..28df5821 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1099,9 +1099,132 @@ void GuiCheats::onInput(u32 kdown) if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS) { - printf("start checking pointer\n"); - - (new Snackbar("Adding address from cheat not supported yet"))->show(); + // printf("start adding cheat to bookmark\n"); + // m_cheatCnt + DmntCheatDefinition cheat = m_cheats[m_selectedEntry].definition; + bookmark_t bookmark; + memcpy(&bookmark.label, &cheat.readable_name, sizeof(bookmark.label)); + bookmark.pointer.depth = 0; + bool success = false; + u32 offset[MAX_POINTER_DEPTH + 1]; + u64 depth = 0; + u64 address; + bool no7 = true; + + for (u8 i = 0; i < cheat.num_opcodes; i++) + { + u8 opcode = (cheat.opcodes[i] >> 28) & 0xF; + u8 Register = (cheat.opcodes[i] >> 16) & 0xF; + u8 FSA = (cheat.opcodes[i] >> 12) & 0xF; + u8 T = (cheat.opcodes[i] >> 24) & 0xF; + + printf("code %lx opcode %d register %d FSA %d %lx \n", cheat.opcodes[i], opcode, Register, FSA, cheat.opcodes[i + 1]); + + if (depth > MAX_POINTER_DEPTH) + { + (new Snackbar("this code is bigger than space catered on the bookmark !!"))->show(); + printf("!!!!!!!!!!!!!!!!!!!!!!!this code is bigger than space catered on the bookmark !! \n"); + break; + } + + if (depth == 0) + { + if (opcode == 5 && FSA == 0) + { + i++; + offset[depth] = cheat.opcodes[i]; + depth++; + } + continue; + } + if (opcode == 5 && FSA == 1) + { + i++; + offset[depth] = cheat.opcodes[i]; + depth++; + continue; + } + if (opcode == 7 && FSA == 0) + { + i++; + offset[depth] = cheat.opcodes[i]; + // success = true; + no7 = false; + continue; + // break; + } + if (opcode == 6) + { + if (no7) + { + offset[depth] = 0; + } + switch (T) + { + case 1: + bookmark.type = SEARCH_TYPE_UNSIGNED_8BIT; + break; + case 2: + bookmark.type = SEARCH_TYPE_UNSIGNED_16BIT; + break; + case 4: + bookmark.type = SEARCH_TYPE_UNSIGNED_32BIT; + break; + case 8: + bookmark.type = SEARCH_TYPE_UNSIGNED_64BIT; + break; + default: + bookmark.type = SEARCH_TYPE_UNSIGNED_32BIT; + break; + } + success = true; + break; + } + } + + if (success) + { + // compute address + printf("success ! \n"); + bookmark.pointer.depth = depth; + u64 nextaddress = m_mainBaseAddr; + printf("main[%lx]", nextaddress); + u8 i = 0; + for (int z = depth; z >= 0; z--) + { + // bookmark_t bm; + bookmark.pointer.offset[z] = offset[i]; + printf("+%lx z=%d ", bookmark.pointer.offset[z], z); + nextaddress += bookmark.pointer.offset[z]; + printf("[%lx]", nextaddress); + // m_memoryDumpBookmark->addData((u8 *)&nextaddress, sizeof(u64)); + // m_AttributeDumpBookmark->addData((u8 *)&bm, sizeof(bookmark_t)); + MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); + if (meminfo.perm == Perm_Rw) + { + address = nextaddress; + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + } + else + { + printf("*access denied*\n"); + success = false; + break; + } + printf("(%lx)", nextaddress); + i++; + } + printf("\n"); + + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + (new Snackbar("Adding address from cheat to bookmark"))->show(); + } + else + { + (new Snackbar("Not able to extract address from cheat"))->show(); + } + // pointercheck(); disable for now; } // end mod @@ -3212,7 +3335,14 @@ void GuiCheats::pointercheck() printf("+%lx z=%d ", pointer_chain.offset[z], z); nextaddress += pointer_chain.offset[z]; printf("[%lx]", nextaddress); - m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); + if (meminfo.perm == Perm_Rw) + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + else + { + printf("*access denied*"); + break; + } printf("(%lx)", nextaddress); } printf("\n\n"); @@ -3236,6 +3366,7 @@ void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDu m_Time1 = time(NULL); m_pointer_found = 0; pointerchain.depth = 0; + m_abort = false; try { pointersearch(targetaddress, pointerchain); //&m_memoryDump, &m_dataDump, From c8bb465eeed08e7bef952de78b26ff197870a5d5 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 22 Jul 2020 08:52:29 +0800 Subject: [PATCH 13/95] Update README.md --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a14a443..a1edcff2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,17 @@ -# EdiZon +# EdiZon SE


Latest Release Discord Server Build Status

+This fork is based on the solid foundation of EdiZon. The changes made are on the game memory hack aspect. + +I have added bookmark functionality, completed the range search feature and enhanced the speed to enable search for small value which generates lots of hits. +Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. + +Work in progress : Pointer search so more location can preserve over different game run and stage change in game. + +PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. A Homebrew save file dumper, injector and on-console editor for Horizon, the OS of the Nintendo Switch. Please note if you are using Atmosphere 0.10.0+, you **must** use the snapshot version of EdiZon. Older versions of EdiZon do **not** work on the latest Atmosphere. From 66607e6df0ecbad547fac4fc642e3e82492667f2 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 22 Jul 2020 08:56:01 +0800 Subject: [PATCH 14/95] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a1edcff2..c618e2e4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ # EdiZon SE -


- Latest Release - Discord Server - Build Status -

+ This fork is based on the solid foundation of EdiZon. The changes made are on the game memory hack aspect. I have added bookmark functionality, completed the range search feature and enhanced the speed to enable search for small value which generates lots of hits. @@ -13,6 +9,13 @@ Work in progress : Pointer search so more location can preserve over different g PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. + +


+ Latest Release + Discord Server + Build Status +

+ A Homebrew save file dumper, injector and on-console editor for Horizon, the OS of the Nintendo Switch. Please note if you are using Atmosphere 0.10.0+, you **must** use the snapshot version of EdiZon. Older versions of EdiZon do **not** work on the latest Atmosphere. From 1169b367889d6e0128465a49841abc223f1c945a Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 22 Jul 2020 08:56:30 +0800 Subject: [PATCH 15/95] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c618e2e4..b0eae224 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ Work in progress : Pointer search so more location can preserve over different g PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. + +


Latest Release Discord Server From 5b5777b53ba6f849c633853dee9342c7e97392ce Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 22 Jul 2020 11:39:32 +0800 Subject: [PATCH 16/95] Minor bug fixes --- Makefile | 2 +- include/guis/gui_cheats.hpp | 2 +- source/guis/gui_cheats.cpp | 16 ++++++++++------ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index ad808596..72ef774d 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 3 +VERSION_MICRO := 3a NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index aa7cfe5f..d3af1574 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -46,7 +46,7 @@ class GuiCheats : public Gui { CHEATS, CANDIDATES - } m_menuLocation = CHEATS; + } m_menuLocation = CANDIDATES; enum { SEARCH_NONE, diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 28df5821..d4ced3ed 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1000,8 +1000,9 @@ void GuiCheats::onInput(u32 kdown) if (kdown & KEY_PLUS) { m_abort = false; - (new Snackbar("Starting pointer search"))->show(); - startpointersearch(m_EditorBaseAddr); + // (new Snackbar("Starting pointer search"))->show(); + printf("starting pointer search from plus %lx \n", m_EditorBaseAddr); + // startpointersearch(m_EditorBaseAddr); } if (kdown & KEY_UP) { @@ -1097,7 +1098,7 @@ void GuiCheats::onInput(u32 kdown) m_searchValue[1]._u64 = 0x8000000000; } - if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS) + if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS && (m_cheatCnt > 0)) { // printf("start adding cheat to bookmark\n"); // m_cheatCnt @@ -1215,7 +1216,9 @@ void GuiCheats::onInput(u32 kdown) i++; } printf("\n"); - + } + if (success) + { m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); (new Snackbar("Adding address from cheat to bookmark"))->show(); @@ -1225,7 +1228,7 @@ void GuiCheats::onInput(u32 kdown) (new Snackbar("Not able to extract address from cheat"))->show(); } - // pointercheck(); disable for now; + // pointercheck(); //disable for now; } // end mod @@ -1611,6 +1614,7 @@ void GuiCheats::onInput(u32 kdown) { // in bookmark mode m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_searchMenuLocation = SEARCH_POINTER; + // pointercheck(); // (new Snackbar("Searching pointer "))->show(); } else if (m_searchMode == SEARCH_MODE_NONE) @@ -3325,7 +3329,7 @@ void GuiCheats::pointercheck() m_pointeroffsetDump->getData(offset, buffer, bufferSize); for (u64 i = 0; i < bufferSize; i += sizeof(pointer_chain_t)) { - pointer_chain_t pointer_chain = *reinterpret_cast(&buffer[i]); + pointer_chain = *reinterpret_cast(&buffer[i]); u64 nextaddress = m_mainBaseAddr; printf("main[%lx]", nextaddress); // m_debugger->readMemory(&nextaddress, sizeof(u64), ( m_mainBaseAddr+ pointer_chain.offset[pointer_chain.depth])); From d1797527d9241e1e7eef6f034201274dae5ab15e Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 22 Jul 2020 21:03:07 +0800 Subject: [PATCH 17/95] rebase 1st half --- source/guis/gui_cheats.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index d4ced3ed..3e75c783 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1210,7 +1210,7 @@ void GuiCheats::onInput(u32 kdown) { printf("*access denied*\n"); success = false; - break; + // break; } printf("(%lx)", nextaddress); i++; @@ -1225,7 +1225,22 @@ void GuiCheats::onInput(u32 kdown) } else { - (new Snackbar("Not able to extract address from cheat"))->show(); + if (bookmark.pointer.depth > 2) // depth of 2 means only one pointer hit high chance of wrong positive + { + (new MessageBox("Extracted pointer chain is broken on current memory state\n \n If the game is in correct state\n \n would you like to try to rebase the chain?", MessageBox::YES_NO)) + ->setSelectionAction([&](u8 selection) { + if (selection) + { + // to insert rebase code here + (new Snackbar("Rebasing ..."))->show(); + } + else + Gui::g_currMessageBox->hide(); + }) + ->show(); + } + else + (new Snackbar("Not able to extract address from cheat"))->show(); } // pointercheck(); //disable for now; From ee5e8316db6d346f94562275d53a3d2eaeed3fbf Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 23 Jul 2020 12:31:14 +0800 Subject: [PATCH 18/95] ready for rebasing pointer chain --- .vscode/settings.json | 5 +- include/guis/gui_cheats.hpp | 15 ++- source/guis/gui_cheats.cpp | 179 +++++++++++++++++++++++++++++++----- 3 files changed, 169 insertions(+), 30 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 82ff87b2..7497c8cb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -81,5 +81,8 @@ "numbers": "cpp", "span": "cpp" }, - "C_Cpp.default.includePath": ["include"] + "C_Cpp.default.includePath": [ + "include" + ], + "C_Cpp.errorSquiggles": "Disabled" } \ No newline at end of file diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index d3af1574..6d46fcd8 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -12,6 +12,7 @@ #include "helpers/memory_dump.hpp" #include "helpers/dmntcht.h" + enum { FORMAT_DEC, @@ -107,7 +108,7 @@ class GuiCheats : public Gui u64 offset; }; -#define IS_PTRCODE_START 0x580F0000 +#define IS_PTRCODE_START 0x580F0000 #define IS_OFFSET 0x580F1000 #define IS_FINAL 0x780F0000 @@ -117,7 +118,6 @@ class GuiCheats : public Gui #define MAX_POINTER_TARGET 3 bool m_forwardonly = false; bool m_forwarddump = false; // reduce from 138 to 26 - struct pointer_chain_t { u64 depth; @@ -132,20 +132,25 @@ class GuiCheats : public Gui pointer_chain_t pointer; bool heap = true; u32 offset = 0; - bool deleted =false; + bool deleted = false; }; + bookmark_t bookmark; pointer_chain_t m_hitcount; + void rebasepointer(); //struct bookmark_t bookmark); + // bool check_chain(bookmark_t *bookmark, u64 *address); // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); // void pointersearch(u64 targetaddress, MemoryDump **displayDump, MemoryDump **dataDump, pointer_chain_t pointerchain); void pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain); void pointercheck(); void startpointersearch(u64 targetaddress); //, MemoryDump **displayDump); - void searchpointer(u64 address, u64 depth, u64 range, pointer_chain_t pointerchain); + void searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain); + u64 m_heapSize = 0; u64 m_mainSize = 0; - + u64 m_heapEnd = 0; + u64 m_mainend = 0; u8 m_buildID[0x20]; DmntCheatEntry *m_cheats; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 3e75c783..c07782dc 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -10,7 +10,7 @@ #include "helpers/util.h" #include "edizon_logo_bin.h" - +// #define checkheap #define MAX_BUFFER_SIZE 0x1000000 // increase size for faster speed static const std::vector dataTypes = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr"}; @@ -68,15 +68,15 @@ GuiCheats::GuiCheats() : Gui() m_heapSize = metadata.heap_extents.size; m_mainSize = metadata.main_nso_extents.size; - if (m_mainBaseAddr < m_heapBaseAddr) + if (m_mainBaseAddr < m_heapBaseAddr) // not used but have to move lower for it to be correct { m_low_main_heap_addr = m_mainBaseAddr; - m_high_main_heap_addr = m_heapBaseAddr + m_heapSize; + m_high_main_heap_addr = m_heapEnd; } else { m_low_main_heap_addr = m_heapBaseAddr; - m_high_main_heap_addr = m_mainBaseAddr + m_mainSize; + m_high_main_heap_addr = m_mainend; } memcpy(m_buildID, metadata.main_nso_build_id, 0x20); @@ -105,17 +105,44 @@ GuiCheats::GuiCheats() : Gui() m_frozenAddresses.insert({frozenAddresses[i].address, frozenAddresses[i].value.value}); } +#ifdef checkheap + printf("m_heapBaseAddr = %lx m_heapSize = %lx m_mainBaseAddr + m_mainSize = %lx\n", m_heapBaseAddr, m_heapSize, m_mainBaseAddr + m_mainSize); +#endif MemoryInfo meminfo = {0}; u64 lastAddr = 0; + m_heapBaseAddr = 0; + m_heapSize = 0; + m_heapEnd = 0; + m_mainend = 0; do { lastAddr = meminfo.addr; meminfo = m_debugger->queryMemory(meminfo.addr + meminfo.size); + if (meminfo.type == MemType_Heap) + { + if (m_heapBaseAddr == 0) + { + m_heapBaseAddr = meminfo.addr; + } + m_heapSize += meminfo.size; // not going to use this but calculate this anyway this don't match for some game + m_heapEnd = meminfo.addr + meminfo.size; // turns out that m_heapEnd may not be same as m_heapBaseAddr + m_heapSize + } + + if (meminfo.type == MemType_CodeMutable) + { + m_mainend = meminfo.addr + meminfo.size; // same for m_mainend not the same as m_mainBaseAddr + m_mainSize; + } + m_memoryInfo.push_back(meminfo); } while (lastAddr < meminfo.addr + meminfo.size); +#ifdef checkheap + printf("m_heapBaseAddr = %lx m_heapSize = %lx m_heapEnd = %lx m_mainend =%lx\n", m_heapBaseAddr, m_heapSize, m_heapEnd, m_mainend); + // for some game heap info was very far off +#endif + for (MemoryInfo meminfo : m_memoryInfo) { if (m_mainBaseAddr == 0x00 && (meminfo.type == MemType_CodeStatic)) @@ -480,11 +507,11 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 900, 75, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "HEAP : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr; - ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr + m_heapSize; + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapEnd; Gui::drawTextAligned(font14, 900, 105, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "MAIN : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr; - ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr + m_mainSize; + ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainend; Gui::drawTextAligned(font14, 900, 135, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); Gui::drawRectangle(256, 50, 394, 137, COLOR_WHITE); @@ -1103,7 +1130,7 @@ void GuiCheats::onInput(u32 kdown) // printf("start adding cheat to bookmark\n"); // m_cheatCnt DmntCheatDefinition cheat = m_cheats[m_selectedEntry].definition; - bookmark_t bookmark; + //bookmark_t bookmark; memcpy(&bookmark.label, &cheat.readable_name, sizeof(bookmark.label)); bookmark.pointer.depth = 0; bool success = false; @@ -1119,7 +1146,7 @@ void GuiCheats::onInput(u32 kdown) u8 FSA = (cheat.opcodes[i] >> 12) & 0xF; u8 T = (cheat.opcodes[i] >> 24) & 0xF; - printf("code %lx opcode %d register %d FSA %d %lx \n", cheat.opcodes[i], opcode, Register, FSA, cheat.opcodes[i + 1]); + printf("code %x opcode %d register %d FSA %d %x \n", cheat.opcodes[i], opcode, Register, FSA, cheat.opcodes[i + 1]); if (depth > MAX_POINTER_DEPTH) { @@ -1232,10 +1259,10 @@ void GuiCheats::onInput(u32 kdown) if (selection) { // to insert rebase code here - (new Snackbar("Rebasing ..."))->show(); + // (new Snackbar("Rebasing ..."))->show(); + rebasepointer(); //bookmark); } - else - Gui::g_currMessageBox->hide(); + Gui::g_currMessageBox->hide(); }) ->show(); } @@ -1372,7 +1399,7 @@ void GuiCheats::onInput(u32 kdown) m_searchValue[1]._u64 = m_EditorBaseAddr; startpointersearch(m_EditorBaseAddr); printf("done pointer search \n"); - printf("Time taken =%d\n", time(NULL) - m_Time1); + printf("Time taken =%ld\n", time(NULL) - m_Time1); // m_EditorBaseAddr = static_cast(std::stoul(input, nullptr, 16)); // m_searchMenuLocation = SEARCH_editRAM; @@ -2395,7 +2422,7 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s } break; case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize - if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainBaseAddr + m_mainSize))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapBaseAddr + m_heapSize)))) + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) { if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) break; @@ -2484,7 +2511,7 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t } if (helpercount != (*displayDump)->size() / sizeof(u64)) { - printf("Integrity problem with helper file helpercount = %d memdumpsize = %d \n", helpercount, (*displayDump)->size() / sizeof(u64)); + printf("Integrity problem with helper file helpercount = %d memdumpsize = %ld \n", helpercount, (*displayDump)->size() / sizeof(u64)); (new Snackbar("Helper integrity check failed !"))->show(); return; } @@ -2620,7 +2647,7 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t } break; case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize - if ((value._s64 >= m_mainBaseAddr && value._s64 <= (m_mainBaseAddr + m_mainSize)) || (value._s64 >= m_heapBaseAddr && value._s64 <= (m_heapBaseAddr + m_heapSize))) + if ((value._s64 >= m_mainBaseAddr && value._s64 <= (m_mainend)) || (value._s64 >= m_heapBaseAddr && value._s64 <= (m_heapEnd))) { newDump->addData((u8 *)&address, sizeof(u64)); newdataDump->addData((u8 *)&value, sizeof(u64)); @@ -2659,7 +2686,7 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t break; } } - printf("%d of %d done \n", offset, (*displayDump)->size()); // maybe consider message box this info + printf("%ld of %ld done \n", offset, (*displayDump)->size()); // maybe consider message box this info offset += bufferSize; } @@ -2846,8 +2873,8 @@ void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t sea ledOn = !ledOn; printf("%s%lx\n", "meminfo.size ", meminfo.size); printf("%s%lx\n", "meminfo.addr ", meminfo.addr); - printf("%s%lx\n", "meminfo.type ", meminfo.type); - printf("%s%lx\n", "meminfo.perm ", meminfo.perm); + printf("%s%x\n", "meminfo.type ", meminfo.type); + printf("%s%x\n", "meminfo.perm ", meminfo.perm); u64 offset = 0; u64 bufferSize = MAX_BUFFER_SIZE; // hack increase from 40K to 1M u8 *buffer = new u8[bufferSize]; @@ -3086,7 +3113,7 @@ void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchValue_t sea } if (helpercount != (*displayDump)->size() / sizeof(u64)) { - printf("Integrity problem with helper file helpercount = %d memdumpsize = %d \n", helpercount, (*displayDump)->size() / sizeof(u64)); + printf("Integrity problem with helper file helpercount = %d memdumpsize = %ld \n", helpercount, (*displayDump)->size() / sizeof(u64)); (new Snackbar("Helper integrity check failed !"))->show(); return; } @@ -3402,15 +3429,119 @@ void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDu m_pointeroffsetDump->flushBuffer(); delete m_pointeroffsetDump; printf("End pointer search \n"); - printf("Time taken =%d Found %d pointer chain\n", time(NULL) - m_Time1, m_pointer_found); + printf("Time taken =%ld Found %ld pointer chain\n", time(NULL) - m_Time1, m_pointer_found); +} + +void GuiCheats::rebasepointer() //struct bookmark_t bookmark) //Go through memory and add to bookmark potential target with different first offset +{ + for (MemoryInfo meminfo : m_memoryInfo) + { + if (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable) + continue; + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // consider to increase from 10k to 1M (not a big problem) + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + try + { + m_debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + } + catch (...) + { + printf(" have error with readmemory \n"); + }; + + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += sizeof(u64)) + { + u64 Address = meminfo.addr + offset + i; + memset(&realValue, 0, 8); + memcpy(&realValue, buffer + i, sizeof(u64)); + + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + { + bookmark.pointer.offset[bookmark.pointer.depth] = Address - m_mainBaseAddr; + bool success = true; + u64 nextaddress = m_mainBaseAddr; + u64 address; + printf("main[%lx]", nextaddress); + + for (int z = bookmark.pointer.depth; z >= 0; z--) + { + // bookmark_t bm; + + printf("+%lx z=%d ", bookmark.pointer.offset[z], z); + nextaddress += bookmark.pointer.offset[z]; + printf("[%lx]", nextaddress); + MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); + if (meminfo.perm == Perm_Rw) + { + address = nextaddress; + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + } + else + { + printf("*access denied*\n"); + success = false; + break; + } + printf("(%lx)", nextaddress); + } + printf("\n"); + + if (success) + { + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + // (new Snackbar("Adding address from cheat to bookmark"))->show(); + } + } + } + offset += bufferSize; + } + delete[] buffer; + } } +// bool GuiCheats::check_chain(bookmark_t *bookmark, u64 *address) +// { +// // return false; +// bool success = true; +// u64 nextaddress = m_mainBaseAddr; +// printf("main[%lx]", nextaddress); +// for (int z = (*bookmark).pointer.depth; z >= 0; z--) +// { +// printf("+%lx z=%d ", (*bookmark).pointer.offset[z], z); +// nextaddress += (*bookmark).pointer.offset[z]; +// printf("[%lx]", nextaddress); +// MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); +// if (meminfo.perm == Perm_Rw) +// { +// *address = nextaddress; +// m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); +// } +// else +// { +// printf("*access denied*"); +// success = false; +// break; +// } +// printf("(%lx)", nextaddress); +// } +// printf("\n"); +// return success; +// } + void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain) //MemoryDump **displayDump, MemoryDump **dataDump, { // printf("target address = %lx depth = %d \n", targetaddress, pointerchain.depth); // printf("check point 1a\n"); - if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainBaseAddr + m_mainSize))) + if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) { printf("\ntarget reached!=========================\n"); printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); @@ -3506,7 +3637,7 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc // pointerchain.offset[pointerchain.depth] = minimum; pointerchain.depth++; - printf("**Found %d sources for address %lx at depth %d\n", sources.size(), targetaddress, pointerchain.depth); + printf("**Found %ld sources for address %lx at depth %ld\n", sources.size(), targetaddress, pointerchain.depth); for (sourceinfo_t sourceinfo : sources) { // targetaddress = 0x1000; @@ -3520,7 +3651,7 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc // printf("fileoffset = %lx thefileoffset =%lx new target address is %lx old target was %lx\n", sourceinfo.foffset, thefileoffset, newtargetaddress, targetaddress); if (m_forwardonly) { - if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainBaseAddr + m_mainSize)))) + if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainend)))) { pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; @@ -3649,7 +3780,7 @@ void GuiCheats::searchpointer(u64 address, u64 depth, u64 range, struct pointer_ pointerchain.depth++; m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); - printf("found at depth %d\n", pointerchain.depth); + printf("found at depth %ld\n", pointerchain.depth); return; } if (depth == 0) From 1b67c10cda4c88c8dfafdede5e50384613d7b555 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 23 Jul 2020 18:41:07 +0800 Subject: [PATCH 19/95] rebase of cheat code done, now to write code to file --- include/guis/gui_cheats.hpp | 5 +- source/guis/gui_cheats.cpp | 121 ++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 14 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 6d46fcd8..59cc631f 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -137,7 +137,7 @@ class GuiCheats : public Gui bookmark_t bookmark; pointer_chain_t m_hitcount; - void rebasepointer(); //struct bookmark_t bookmark); + void rebasepointer(searchValue_t value); //struct bookmark_t bookmark); // bool check_chain(bookmark_t *bookmark, u64 *address); // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); @@ -146,7 +146,8 @@ class GuiCheats : public Gui void pointercheck(); void startpointersearch(u64 targetaddress); //, MemoryDump **displayDump); void searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain); - + bool valuematch(searchValue_t value, u64 nextaddress); + bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); u64 m_heapSize = 0; u64 m_mainSize = 0; u64 m_heapEnd = 0; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index c07782dc..bb64bde6 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -11,8 +11,19 @@ #include "edizon_logo_bin.h" // #define checkheap +// #define printpointerchain #define MAX_BUFFER_SIZE 0x1000000 // increase size for faster speed - +#define STARTTIMER \ + time_t unixTime1 = time(NULL); +#define ENDTIMER \ + printf(" Time used is %d \n", time(NULL) - unixTime1); +#define R_UNLESS(expr, res) \ + ({ \ + if (!(expr)) \ + { \ + return static_cast<::ams::Result>(res); \ + } \ + }) static const std::vector dataTypes = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr"}; static const std::vector dataTypeSizes = {1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8}; static const std::vector dataTypeMaxValues = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; @@ -68,7 +79,7 @@ GuiCheats::GuiCheats() : Gui() m_heapSize = metadata.heap_extents.size; m_mainSize = metadata.main_nso_extents.size; - if (m_mainBaseAddr < m_heapBaseAddr) // not used but have to move lower for it to be correct + if (m_mainBaseAddr < m_heapBaseAddr) // not used but have to move lower for it to be correct { m_low_main_heap_addr = m_mainBaseAddr; m_high_main_heap_addr = m_heapEnd; @@ -134,7 +145,7 @@ GuiCheats::GuiCheats() : Gui() { m_mainend = meminfo.addr + meminfo.size; // same for m_mainend not the same as m_mainBaseAddr + m_mainSize; } - + m_memoryInfo.push_back(meminfo); } while (lastAddr < meminfo.addr + meminfo.size); @@ -1258,9 +1269,12 @@ void GuiCheats::onInput(u32 kdown) ->setSelectionAction([&](u8 selection) { if (selection) { - // to insert rebase code here - // (new Snackbar("Rebasing ..."))->show(); - rebasepointer(); //bookmark); + searchValue_t value; + while (!getinput("Enter the value at this memory", "You must know what type is the value and set it correctly in the search memory type setting", "", &value)) + { + } + printf("value = %ld\n",value); + rebasepointer(value); //bookmark); } Gui::g_currMessageBox->hide(); }) @@ -2647,7 +2661,7 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t } break; case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize - if ((value._s64 >= m_mainBaseAddr && value._s64 <= (m_mainend)) || (value._s64 >= m_heapBaseAddr && value._s64 <= (m_heapEnd))) + if ((value._u64 >= m_mainBaseAddr && value._u64 <= (m_mainend)) || (value._u64 >= m_heapBaseAddr && value._u64 <= (m_heapEnd))) { newDump->addData((u8 *)&address, sizeof(u64)); newdataDump->addData((u8 *)&value, sizeof(u64)); @@ -3432,8 +3446,9 @@ void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDu printf("Time taken =%ld Found %ld pointer chain\n", time(NULL) - m_Time1, m_pointer_found); } -void GuiCheats::rebasepointer() //struct bookmark_t bookmark) //Go through memory and add to bookmark potential target with different first offset +void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) //Go through memory and add to bookmark potential target with different first offset { + STARTTIMER for (MemoryInfo meminfo : m_memoryInfo) { if (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable) @@ -3462,21 +3477,25 @@ void GuiCheats::rebasepointer() //struct bookmark_t bookmark) //Go through memor memset(&realValue, 0, 8); memcpy(&realValue, buffer + i, sizeof(u64)); - if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd))) { bookmark.pointer.offset[bookmark.pointer.depth] = Address - m_mainBaseAddr; bool success = true; u64 nextaddress = m_mainBaseAddr; u64 address; +#ifdef printpointerchain printf("main[%lx]", nextaddress); - +#endif for (int z = bookmark.pointer.depth; z >= 0; z--) { // bookmark_t bm; - +#ifdef printpointerchain printf("+%lx z=%d ", bookmark.pointer.offset[z], z); +#endif nextaddress += bookmark.pointer.offset[z]; +#ifdef printpointerchain printf("[%lx]", nextaddress); +#endif MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); if (meminfo.perm == Perm_Rw) { @@ -3485,18 +3504,28 @@ void GuiCheats::rebasepointer() //struct bookmark_t bookmark) //Go through memor } else { +#ifdef printpointerchain printf("*access denied*\n"); +#endif success = false; break; } +#ifdef printpointerchain printf("(%lx)", nextaddress); +#endif } +#ifdef printpointerchain printf("\n"); +#endif - if (success) + if (success && valuematch(value, address)) { + bookmark.type = m_searchType; m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); +#ifdef printpointerchain + printf("Success BM added \n"); +#endif // (new Snackbar("Adding address from cheat to bookmark"))->show(); } } @@ -3505,6 +3534,9 @@ void GuiCheats::rebasepointer() //struct bookmark_t bookmark) //Go through memor } delete[] buffer; } + ENDTIMER + m_memoryDumpBookmark->flushBuffer(); + m_AttributeDumpBookmark->flushBuffer(); } // bool GuiCheats::check_chain(bookmark_t *bookmark, u64 *address) @@ -3920,3 +3952,68 @@ static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) return !(cheatsFolderEmpty || realCheatDoesExist); } + + bool GuiCheats::getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue) +{ + char str[0x21]; + Gui::requestKeyboardInput(headerText, subHeaderText, initialText, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); + if (std::string(str) == "") + return false; + (*searchValue)._u64 = 0; + if (m_searchValueFormat == FORMAT_HEX) + { + (*searchValue)._u64 = static_cast(std::stoul(str, nullptr, 16)); + } + else + { + switch (m_searchType) + { + case SEARCH_TYPE_UNSIGNED_8BIT: + (*searchValue)._u8 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_16BIT: + (*searchValue)._u16 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_32BIT: + (*searchValue)._u32 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_UNSIGNED_64BIT: + (*searchValue)._u64 = static_cast(std::stoul(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_8BIT: + (*searchValue)._s8 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_16BIT: + (*searchValue)._s16 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_32BIT: + (*searchValue)._s32 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_SIGNED_64BIT: + (*searchValue)._s64 = static_cast(std::stol(str, nullptr, 0)); + break; + case SEARCH_TYPE_FLOAT_32BIT: + (*searchValue)._f32 = static_cast(std::stof(str)); + break; + case SEARCH_TYPE_FLOAT_64BIT: + (*searchValue)._f64 = static_cast(std::stod(str)); + break; + case SEARCH_TYPE_POINTER: + (*searchValue)._u64 = static_cast(std::stol(str)); + break; + case SEARCH_TYPE_NONE: + break; + } + } + return true; +} +bool GuiCheats::valuematch(searchValue_t value, u64 nextaddress) +{ + searchValue_t realvalue; + realvalue._u64 = 0; + m_debugger->readMemory(&realvalue, dataTypeSizes[m_searchType], nextaddress); + if (realvalue._u64 == value._u64) + return true; + else + return false; +} \ No newline at end of file From 342d3fcaf54d5e5433c7093f096870dc8a265075 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 23 Jul 2020 19:09:39 +0800 Subject: [PATCH 20/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0eae224..ff3f195d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This fork is based on the solid foundation of EdiZon. The changes made are on the game memory hack aspect. I have added bookmark functionality, completed the range search feature and enhanced the speed to enable search for small value which generates lots of hits. -Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. +Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. Able to rebase first offset of cheat code for game version change that only affects the first offset. Work in progress : Pointer search so more location can preserve over different game run and stage change in game. From ecb97663ac5bf6ae1cc509787c18509eaed272bf Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 24 Jul 2020 13:42:40 +0800 Subject: [PATCH 21/95] Write code back to file --- Makefile | 2 +- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 103 ++++++++++++++++++++++++++++++++++-- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 72ef774d..4b710243 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 3a +VERSION_MICRO := 5 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 59cc631f..3e209137 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -148,6 +148,7 @@ class GuiCheats : public Gui void searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain); bool valuematch(searchValue_t value, u64 nextaddress); bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); + bool addcodetofile(u64 index); u64 m_heapSize = 0; u64 m_mainSize = 0; u64 m_heapEnd = 0; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index bb64bde6..0e7222a6 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1145,7 +1145,7 @@ void GuiCheats::onInput(u32 kdown) memcpy(&bookmark.label, &cheat.readable_name, sizeof(bookmark.label)); bookmark.pointer.depth = 0; bool success = false; - u32 offset[MAX_POINTER_DEPTH + 1]; + u64 offset[MAX_POINTER_DEPTH + 1] = {0}; u64 depth = 0; u64 address; bool no7 = true; @@ -1272,8 +1272,8 @@ void GuiCheats::onInput(u32 kdown) searchValue_t value; while (!getinput("Enter the value at this memory", "You must know what type is the value and set it correctly in the search memory type setting", "", &value)) { - } - printf("value = %ld\n",value); + } + printf("value = %ld\n", value); rebasepointer(value); //bookmark); } Gui::g_currMessageBox->hide(); @@ -1670,6 +1670,25 @@ void GuiCheats::onInput(u32 kdown) { // in bookmark mode m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_searchMenuLocation = SEARCH_POINTER; + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // printf("m_selectedEntry + m_addresslist_offset %ld\n", m_selectedEntry + m_addresslist_offset); + // u64 index = m_selectedEntry + m_addresslist_offset; + if (bookmark.pointer.depth > 1) + { + addcodetofile(m_selectedEntry + m_addresslist_offset); + // (new MessageBox("Add current pointer chain to cheat file?", MessageBox::YES_NO)) + // ->setSelectionAction([&](u8 selection) { + // if (selection) + // { + // addcodetofile(index); // index also does not preserve; need to figure out why this won't work + // m_searchMenuLocation = SEARCH_NONE; + // } + // Gui::g_currMessageBox->hide(); + // }) + // ->show(); + } + // pointercheck(); // (new Snackbar("Searching pointer "))->show(); } @@ -3953,7 +3972,7 @@ static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) return !(cheatsFolderEmpty || realCheatDoesExist); } - bool GuiCheats::getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue) +bool GuiCheats::getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue) { char str[0x21]; Gui::requestKeyboardInput(headerText, subHeaderText, initialText, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, str, 0x20); @@ -4016,4 +4035,78 @@ bool GuiCheats::valuematch(searchValue_t value, u64 nextaddress) return true; else return false; -} \ No newline at end of file +} +bool GuiCheats::addcodetofile(u64 index) +{ + std::stringstream buildIDStr; + std::stringstream filebuildIDStr; + { + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + // buildIDStr.str("attdumpbookmark"); + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; + } + + std::stringstream realCheatPath; + { + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << "/cheats/"; + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << buildIDStr.str() << ".txt"; + } + + bookmark_t bookmark; + u64 address; + m_AttributeDumpBookmark->getData(index * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + m_memoryDump->getData(index * sizeof(u64), &address, sizeof(u64)); + searchValue_t realvalue; + realvalue._u64 = 0; + m_debugger->readMemory(&realvalue, dataTypeSizes[bookmark.type], address); + + FILE *pfile; + pfile = fopen(filebuildIDStr.str().c_str(), "a"); + std::stringstream ss; + if (pfile != NULL) + { + // printf("going to write to file\n"); + ss.str(""); + ss << "[" << bookmark.label << "]" + << "\n"; + ss << "580F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[bookmark.pointer.depth] << "\n"; + for (int z = bookmark.pointer.depth - 1; z > 0; z--) + { + ss << "580F1000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[z] << "\n"; + } + ss << "780F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[0] << "\n"; + ss << "6" << dataTypeSizes[bookmark.type] + 0 << "0F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(16) << realvalue._u64 << "\n"; + printf("index = %ld depth = %ld offset = %ld offset = %ld offset = %ld offset = %ld\n", index, bookmark.pointer.depth, bookmark.pointer.offset[3], bookmark.pointer.offset[2], bookmark.pointer.offset[1], bookmark.pointer.offset[0]); + printf("address = %lx value = %lx \n", address, realvalue._u64); + printf("dataTypeSizes[bookmark.type] %d\n", dataTypeSizes[bookmark.type]); + + // std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; + // snprintf(st, 27, "%s\n", ss.str().c_str()); char st[27]; + // fputs(filebuildIDStr.str().c_str(), pfile); + // fputs("fopen example", pfile); + //std::endl is basicly: + //std::cout << "\n" << std::flush; "\r\n" + // char st[1000]; + // snprintf(st, 1000, "%s\n", ss.str().c_str()); + fputs(ss.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on Edizon dir \n"); + + pfile = fopen(realCheatPath.str().c_str(), "a"); + if (pfile != NULL) + { + fputs(ss.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on contents dir \n"); + + return true; +} From 03de0839d41e4e3ec51953d85300f6849668578d Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 24 Jul 2020 20:59:53 +0800 Subject: [PATCH 22/95] Cheat code writeback done --- source/guis/gui_cheats.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 0e7222a6..887cc8a9 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1677,6 +1677,9 @@ void GuiCheats::onInput(u32 kdown) if (bookmark.pointer.depth > 1) { addcodetofile(m_selectedEntry + m_addresslist_offset); + m_searchMenuLocation = SEARCH_NONE; + // dmntchtForceOpenCheatProcess(); + (new Snackbar("Coded added to cheat file, reload to take effect"))->show(); // (new MessageBox("Add current pointer chain to cheat file?", MessageBox::YES_NO)) // ->setSelectionAction([&](u8 selection) { // if (selection) From ad0fad127c759f6a907f8821db77868e0b7a7400 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 25 Jul 2020 17:13:38 +0800 Subject: [PATCH 23/95] refactored pointersearch 2 function the same as pointersearch ready for further development --- include/guis/gui_cheats.hpp | 26 ++++++- source/guis/gui_cheats.cpp | 146 +++++++++++++++++++++++++++++++++++- 2 files changed, 168 insertions(+), 4 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 3e209137..ff400829 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -116,6 +116,27 @@ class GuiCheats : public Gui #define MAX_POINTER_DEPTH 6 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 #define MAX_POINTER_TARGET 3 + struct PointerSearch_state + { + // u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget + u64 index[MAX_POINTER_DEPTH + 1] = {0}; // when there is a hit retrieve the offsets with indexs and sources[index].offset + u64 num_offsets[MAX_POINTER_DEPTH + 1] = {0}; // for analysis + u64 num_sources[MAX_POINTER_DEPTH + 1] = {0}; // this is how we will go down the column + sourceinfo_t sources[MAX_POINTER_DEPTH + 1][MAX_NUM_SOURCE_POINTER]; //the data matrix to get nexttarget from foffset and m_memoryDump1 + }; + PointerSearch_state *m_PointerSearch = nullptr; + void startpointersearch2(u64 targetaddress); + void pointersearch2(u64 targetaddress, u64 depth); + void resumepointersearch2(); + bool m_pointersearch_done = false; +#define PS_depth depth +#define PS_index m_PointerSearch->index[PS_depth] +// #define PS_indexP m_PointerSearch->index[PS_depth-1] +#define PS_num_offsets m_PointerSearch->num_offsets[PS_depth] +#define PS_num_sources m_PointerSearch->num_sources[PS_depth] +// #define PS_num_sourcesP m_PointerSearch->num_sources[PS_depth-1] +#define PS_sources m_PointerSearch->sources[PS_depth] + bool m_forwardonly = false; bool m_forwarddump = false; // reduce from 138 to 26 struct pointer_chain_t @@ -134,8 +155,9 @@ class GuiCheats : public Gui u32 offset = 0; bool deleted = false; }; - bookmark_t bookmark; - pointer_chain_t m_hitcount; + bookmark_t m_bookmark; //global for use in pointer search , target address to be updated dynamically by display routine TBD + bookmark_t bookmark; //maybe not used + pointer_chain_t m_hitcount; // maybe not used void rebasepointer(searchValue_t value); //struct bookmark_t bookmark); // bool check_chain(bookmark_t *bookmark, u64 *address); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 887cc8a9..bbea5656 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1401,17 +1401,18 @@ void GuiCheats::onInput(u32 kdown) m_searchMenuLocation = SEARCH_editRAM; m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; } - if ((kdown & KEY_LSTICK) && (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR)) + if ((kdown & KEY_LSTICK) && (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) && (m_memoryDump1 != nullptr)) { printf("start pointer search ....................\n"); m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); printf("Address %lx \n\n\n", m_EditorBaseAddr); m_abort = false; m_Time1 = time(NULL); // m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); m_searchValue[0]._u64 = m_EditorBaseAddr - 0x800; m_searchValue[1]._u64 = m_EditorBaseAddr; - startpointersearch(m_EditorBaseAddr); + startpointersearch2(m_EditorBaseAddr); printf("done pointer search \n"); printf("Time taken =%ld\n", time(NULL) - m_Time1); @@ -3737,7 +3738,148 @@ void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerc // return; } // change address to new one +void GuiCheats::startpointersearch2(u64 targetaddress) // using global m_bookmark which has the label field already set correctly +{ + m_PointerSearch = new PointerSearch_state; + m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); // pointed targets is in this file + printf("Start pointer search %lx\n", targetaddress); + m_Time1 = time(NULL); + m_pointer_found = 0; + m_abort = false; + m_pointersearch_done = false; + // PS_depth = 0; // need this if m_PointerSearch isn't created here + // m_PointerSearch->index = {0}; // + try + { + pointersearch2(targetaddress, 0); //&m_memoryDump, &m_dataDump, + } + catch (...) + { + printf("Caught an exception\n"); + } + printf("End pointer search \n"); + printf("Time taken =%ld Found %ld pointer chain\n", time(NULL) - m_Time1, m_pointer_found); + + if (m_pointersearch_done) + { + delete m_PointerSearch; + } +} +void GuiCheats::resumepointersearch2() +{ + pointersearch2(0, 0); // 0 means continue + if (m_pointersearch_done) + { + delete m_PointerSearch; + } +} + +void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **displayDump, MemoryDump **dataDump, +{ + // printf("targetaddress %lx PS_depth %ld PS_index %ld PS_num_sources %ld\n",targetaddress, PS_depth, PS_index, PS_num_sources); + if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) + { + + printf("\ntarget reached!=========================\n"); + printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); + m_bookmark.pointer.offset[PS_depth] = targetaddress - m_mainBaseAddr; + m_bookmark.pointer.depth = PS_depth; + for (int z = PS_depth - 1; z >= 0; z--) + { + m_bookmark.pointer.offset[z] = m_PointerSearch->sources[z][m_PointerSearch->index[z]].offset; + } + + m_AttributeDumpBookmark->addData((u8 *)&m_bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); + // m_pointeroffsetDump->flushBuffer(); // is this useful? + printf("main"); + for (int z = m_bookmark.pointer.depth; z >= 0; z--) + printf("+%lx z=%d ", m_bookmark.pointer.offset[z], z); + printf("\n\n"); + m_pointer_found++; + return; // consider don't return to find more + }; + if (PS_depth == m_max_depth) + { + // printf("max pointer depth reached\n\n"); + return; + } + u64 offset = 0; + // u64 thefileoffset; + u64 bufferSize = MAX_BUFFER_SIZE; + u8 *buffer = new u8[bufferSize]; + u64 distance; + u64 minimum = m_max_range; // a large number to start + // std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers + sourceinfo_t sourceinfo; + // printf("PS_num_sources %d ", PS_num_sources); + PS_num_sources = 0; + while (offset < m_dataDump->size()) + { + if (m_dataDump->size() - offset < bufferSize) + bufferSize = m_dataDump->size() - offset; + m_dataDump->getData(offset, buffer, bufferSize); // BM4 + + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + if (m_abort) + return; + u64 pointedaddress = *reinterpret_cast(&buffer[i]); + if (targetaddress >= pointedaddress) + { + distance = targetaddress - pointedaddress; + if (distance < minimum) + { + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + PS_sources[PS_num_sources] = sourceinfo; + PS_num_sources++; + // sources.push_back(sourceinfo); + // thefileoffset = offset + i; //for debug only + } + else if (distance == minimum) + { + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + PS_sources[PS_num_sources] = sourceinfo; + PS_num_sources++; + // sources.push_back(sourceinfo); + // thefileoffset = offset + i; //for deubg only + } + } + if (PS_num_sources > m_max_source) + break; + } + if (PS_num_sources > m_max_source) + break; + offset += bufferSize; + } + + delete[] buffer; // release memory use for the search of sources + // printf("**Found %ld sources for address %lx at depth %ld\n", PS_num_sources, targetaddress, PS_depth); + // PS_depth++; + PS_index = 0; + while (PS_index < PS_num_sources) + { + u64 newtargetaddress; + m_memoryDump1->getData(PS_sources[PS_index].foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte + if (m_forwardonly) + { + if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainend)))) + { + pointersearch2(newtargetaddress, PS_depth + 1); + } + } + else + { + pointersearch2(newtargetaddress, PS_depth + 1); + } + PS_index++; + } + return; +} // printf("not found \n"); // return; From fe9316f466e554f086331799a6bba8a4d2efa9ab Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 25 Jul 2020 21:24:38 +0800 Subject: [PATCH 24/95] fix bookmark add from pointer search bug --- source/guis/gui_cheats.cpp | 52 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index bbea5656..7203bc62 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1039,8 +1039,14 @@ void GuiCheats::onInput(u32 kdown) { m_abort = false; // (new Snackbar("Starting pointer search"))->show(); + m_searchMenuLocation = SEARCH_NONE; printf("starting pointer search from plus %lx \n", m_EditorBaseAddr); - // startpointersearch(m_EditorBaseAddr); + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + m_abort = false; + m_Time1 = time(NULL); + startpointersearch2(m_EditorBaseAddr); // need help here; don't know what always crash when startpointersearch2 is called from here + printf("done pointer search \n"); + printf("Time taken =%ld\n", time(NULL) - m_Time1); } if (kdown & KEY_UP) { @@ -1671,28 +1677,30 @@ void GuiCheats::onInput(u32 kdown) { // in bookmark mode m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_searchMenuLocation = SEARCH_POINTER; - bookmark_t bookmark; - m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); - // printf("m_selectedEntry + m_addresslist_offset %ld\n", m_selectedEntry + m_addresslist_offset); - // u64 index = m_selectedEntry + m_addresslist_offset; - if (bookmark.pointer.depth > 1) + if (false) { - addcodetofile(m_selectedEntry + m_addresslist_offset); - m_searchMenuLocation = SEARCH_NONE; - // dmntchtForceOpenCheatProcess(); - (new Snackbar("Coded added to cheat file, reload to take effect"))->show(); - // (new MessageBox("Add current pointer chain to cheat file?", MessageBox::YES_NO)) - // ->setSelectionAction([&](u8 selection) { - // if (selection) - // { - // addcodetofile(index); // index also does not preserve; need to figure out why this won't work - // m_searchMenuLocation = SEARCH_NONE; - // } - // Gui::g_currMessageBox->hide(); - // }) - // ->show(); + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // printf("m_selectedEntry + m_addresslist_offset %ld\n", m_selectedEntry + m_addresslist_offset); + // u64 index = m_selectedEntry + m_addresslist_offset; + if (bookmark.pointer.depth > 1) + { + addcodetofile(m_selectedEntry + m_addresslist_offset); + m_searchMenuLocation = SEARCH_NONE; + // dmntchtForceOpenCheatProcess(); + (new Snackbar("Coded added to cheat file, reload to take effect"))->show(); + // (new MessageBox("Add current pointer chain to cheat file?", MessageBox::YES_NO)) + // ->setSelectionAction([&](u8 selection) { + // if (selection) + // { + // addcodetofile(index); // index also does not preserve; need to figure out why this won't work + // m_searchMenuLocation = SEARCH_NONE; + // } + // Gui::g_currMessageBox->hide(); + // }) + // ->show(); + } } - // pointercheck(); // (new Snackbar("Searching pointer "))->show(); } @@ -3791,6 +3799,8 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp m_AttributeDumpBookmark->addData((u8 *)&m_bookmark, sizeof(bookmark_t)); m_AttributeDumpBookmark->flushBuffer(); + m_memoryDumpBookmark->addData((u8 *)&m_mainBaseAddr, sizeof(u64)); //need to update + m_memoryDumpBookmark->flushBuffer(); // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); // m_pointeroffsetDump->flushBuffer(); // is this useful? printf("main"); From 0b4e8390fd23dc5e2d1c1627b5f7b14a2bb213a8 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 25 Jul 2020 21:43:14 +0800 Subject: [PATCH 25/95] Tool bug? Strange that this change solved the crash --- source/guis/gui_cheats.cpp | 534 ++++++++++++++++++------------------- 1 file changed, 267 insertions(+), 267 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 7203bc62..ea92f5c2 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -3448,34 +3448,34 @@ void GuiCheats::pointercheck() } } -void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDump, MemoryDump **dataDump, pointer_chain_t pointerchain) -{ - m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); // pointed targets is in this file - m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, true); // create file but maybe later just open it - pointer_chain_t pointerchain; - printf("Start pointer search %lx\n", targetaddress); - m_Time1 = time(NULL); - m_pointer_found = 0; - pointerchain.depth = 0; - m_abort = false; - try - { - pointersearch(targetaddress, pointerchain); //&m_memoryDump, &m_dataDump, - } - catch (...) - { - printf("Caught an exception\n"); - } - // add some rubbish just for testing - // char st[250]; // replace the printf - // snprintf(st, 250, "Just for testing ====="); // - // m_pointeroffsetDump->addData((u8 *)&st, sizeof(st)); // - - m_pointeroffsetDump->flushBuffer(); - delete m_pointeroffsetDump; - printf("End pointer search \n"); - printf("Time taken =%ld Found %ld pointer chain\n", time(NULL) - m_Time1, m_pointer_found); -} +// void GuiCheats::startpointersearch(u64 targetaddress) //, MemoryDump **displayDump, MemoryDump **dataDump, pointer_chain_t pointerchain) +// { +// m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); // pointed targets is in this file +// m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/ptrdump1.dat", DumpType::POINTER, true); // create file but maybe later just open it +// pointer_chain_t pointerchain; +// printf("Start pointer search %lx\n", targetaddress); +// m_Time1 = time(NULL); +// m_pointer_found = 0; +// pointerchain.depth = 0; +// m_abort = false; +// try +// { +// pointersearch(targetaddress, pointerchain); //&m_memoryDump, &m_dataDump, +// } +// catch (...) +// { +// printf("Caught an exception\n"); +// } +// // add some rubbish just for testing +// // char st[250]; // replace the printf +// // snprintf(st, 250, "Just for testing ====="); // +// // m_pointeroffsetDump->addData((u8 *)&st, sizeof(st)); // +// +// m_pointeroffsetDump->flushBuffer(); +// delete m_pointeroffsetDump; +// printf("End pointer search \n"); +// printf("Time taken =%ld Found %ld pointer chain\n", time(NULL) - m_Time1, m_pointer_found); +// } void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) //Go through memory and add to bookmark potential target with different first offset { @@ -3599,153 +3599,153 @@ void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) // return success; // } -void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain) //MemoryDump **displayDump, MemoryDump **dataDump, -{ - // printf("target address = %lx depth = %d \n", targetaddress, pointerchain.depth); - - // printf("check point 1a\n"); - if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) - { - printf("\ntarget reached!=========================\n"); - printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); - // pointerchain.depth++; - // pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; - // // save pointerchain - pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; - m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); - m_pointeroffsetDump->flushBuffer(); // is this useful? - printf("main"); - for (int z = pointerchain.depth; z >= 0; z--) - printf("+%lx z=%d ", pointerchain.offset[z], z); - printf("\n\n"); - // printf("\nsize=%d\n", sizeof(pointer_chain_t)); - m_pointer_found++; - return; // consider don't return to find more - }; - - if (pointerchain.depth == m_max_depth) - { - // printf("max pointer depth reached\n\n"); - return; - } - - // printf("\n starting pointer search for address = %lx at depth %d ", targetaddress, pointerchain.depth); - u64 offset = 0; - u64 thefileoffset = 0; - u64 bufferSize = MAX_BUFFER_SIZE; - u8 *buffer = new u8[bufferSize]; - u64 distance; - u64 minimum = m_max_range; // a large number to start - std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers - sourceinfo_t sourceinfo; - // std::vector distances; - - while (offset < m_dataDump->size()) - { - if (m_dataDump->size() - offset < bufferSize) - bufferSize = m_dataDump->size() - offset; - // printf("checkpoint 2\n"); - m_dataDump->getData(offset, buffer, bufferSize); // BM4 - bool writeback = false; - // printf("checkpoint 3\n"); - // return; // just to check - for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) - { - if (m_abort) - return; - u64 pointedaddress = *reinterpret_cast(&buffer[i]); - if (targetaddress >= pointedaddress) - { - distance = targetaddress - pointedaddress; - if (distance < minimum) - { - // minimum = distance; - // sources.clear(); - sourceinfo.foffset = offset + i; - sourceinfo.offset = distance; - sources.push_back(sourceinfo); - thefileoffset = offset + i; - // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop - // writeback = true; // - } - else if (distance == minimum) - { - sourceinfo.foffset = offset + i; - sourceinfo.offset = distance; - sources.push_back(sourceinfo); - // sources.push_back(offset + i); - thefileoffset = offset + i; - // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop - // writeback = true; // - // pointerchain.fileoffset[pointerchain.depth] = offset + i; - // pointerchain.offset[pointerchain.depth] = distance; - } - } - if (sources.size() > m_max_source) - break; - } - if (sources.size() > m_max_source) - break; - // if (writeback) - // { - // m_dataDump->putData(offset, buffer, bufferSize); - // m_dataDump->flushBuffer(); - // } - offset += bufferSize; - } - delete[] buffer; // release memory use for the search of sources - - // Now we have fileoffsets stored in sources to repeat this process - // printf("memory scan completed offset is %lx at depth %lx\n\n", minimum, pointerchain.depth); - // pointerchain.offset[pointerchain.depth] = minimum; - pointerchain.depth++; - - printf("**Found %ld sources for address %lx at depth %ld\n", sources.size(), targetaddress, pointerchain.depth); - for (sourceinfo_t sourceinfo : sources) - { - // targetaddress = 0x1000; - // printf("size of memorydump is %lx ", m_memoryDump1->size()); // I swapped the bookmark - //m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); - u64 newtargetaddress; - m_memoryDump1->getData(sourceinfo.foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte - - // u64 checkaddress; // debug use - // m_dataDump->getData(foffset, &checkaddress, sizeof(u64)); //double check it for debug purpose - // printf("fileoffset = %lx thefileoffset =%lx new target address is %lx old target was %lx\n", sourceinfo.foffset, thefileoffset, newtargetaddress, targetaddress); - if (m_forwardonly) - { - if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainend)))) - { - pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; - pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; - pointersearch(newtargetaddress, pointerchain); - } - } - else - { - /* code */ - pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; - pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; - pointersearch(newtargetaddress, pointerchain); - } - } - - return; - - // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); - - // printf("depth is %d new address is %lx offset is %lx code offset is %lx \n", pointerchain.depth, address, pointerchain.fileoffset[pointerchain.depth], pointerchain.offset[pointerchain.depth]); - // if (address < m_mainBaseAddr + m_mainSize) - // { - // printf("target reached!"); - // printf("final offset is %lx \n", address - m_mainBaseAddr); - // pointerchain.depth++; - // pointerchain.offset[pointerchain.depth] = address - m_mainBaseAddr; - // // save pointerchain - // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); - // return; -} -// change address to new one +// void GuiCheats::pointersearch(u64 targetaddress, struct pointer_chain_t pointerchain) //MemoryDump **displayDump, MemoryDump **dataDump, +// { +// // printf("target address = %lx depth = %d \n", targetaddress, pointerchain.depth); +// +// // printf("check point 1a\n"); +// if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) +// { +// printf("\ntarget reached!=========================\n"); +// printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); +// // pointerchain.depth++; +// // pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; +// // // save pointerchain +// pointerchain.offset[pointerchain.depth] = targetaddress - m_mainBaseAddr; +// m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); +// m_pointeroffsetDump->flushBuffer(); // is this useful? +// printf("main"); +// for (int z = pointerchain.depth; z >= 0; z--) +// printf("+%lx z=%d ", pointerchain.offset[z], z); +// printf("\n\n"); +// // printf("\nsize=%d\n", sizeof(pointer_chain_t)); +// m_pointer_found++; +// return; // consider don't return to find more +// }; +// +// if (pointerchain.depth == m_max_depth) +// { +// // printf("max pointer depth reached\n\n"); +// return; +// } +// +// // printf("\n starting pointer search for address = %lx at depth %d ", targetaddress, pointerchain.depth); +// u64 offset = 0; +// u64 thefileoffset = 0; +// u64 bufferSize = MAX_BUFFER_SIZE; +// u8 *buffer = new u8[bufferSize]; +// u64 distance; +// u64 minimum = m_max_range; // a large number to start +// std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers +// sourceinfo_t sourceinfo; +// // std::vector distances; +// +// while (offset < m_dataDump->size()) +// { +// if (m_dataDump->size() - offset < bufferSize) +// bufferSize = m_dataDump->size() - offset; +// // printf("checkpoint 2\n"); +// m_dataDump->getData(offset, buffer, bufferSize); // BM4 +// bool writeback = false; +// // printf("checkpoint 3\n"); +// // return; // just to check +// for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) +// { +// if (m_abort) +// return; +// u64 pointedaddress = *reinterpret_cast(&buffer[i]); +// if (targetaddress >= pointedaddress) +// { +// distance = targetaddress - pointedaddress; +// if (distance < minimum) +// { +// // minimum = distance; +// // sources.clear(); +// sourceinfo.foffset = offset + i; +// sourceinfo.offset = distance; +// sources.push_back(sourceinfo); +// thefileoffset = offset + i; +// // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop +// // writeback = true; // +// } +// else if (distance == minimum) +// { +// sourceinfo.foffset = offset + i; +// sourceinfo.offset = distance; +// sources.push_back(sourceinfo); +// // sources.push_back(offset + i); +// thefileoffset = offset + i; +// // *reinterpret_cast(&buffer[i]) = 0; // to prevent endless loop +// // writeback = true; // +// // pointerchain.fileoffset[pointerchain.depth] = offset + i; +// // pointerchain.offset[pointerchain.depth] = distance; +// } +// } +// if (sources.size() > m_max_source) +// break; +// } +// if (sources.size() > m_max_source) +// break; +// // if (writeback) +// // { +// // m_dataDump->putData(offset, buffer, bufferSize); +// // m_dataDump->flushBuffer(); +// // } +// offset += bufferSize; +// } +// delete[] buffer; // release memory use for the search of sources +// +// // Now we have fileoffsets stored in sources to repeat this process +// // printf("memory scan completed offset is %lx at depth %lx\n\n", minimum, pointerchain.depth); +// // pointerchain.offset[pointerchain.depth] = minimum; +// pointerchain.depth++; +// +// printf("**Found %ld sources for address %lx at depth %ld\n", sources.size(), targetaddress, pointerchain.depth); +// for (sourceinfo_t sourceinfo : sources) +// { +// // targetaddress = 0x1000; +// // printf("size of memorydump is %lx ", m_memoryDump1->size()); // I swapped the bookmark +// //m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); +// u64 newtargetaddress; +// m_memoryDump1->getData(sourceinfo.foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte +// +// // u64 checkaddress; // debug use +// // m_dataDump->getData(foffset, &checkaddress, sizeof(u64)); //double check it for debug purpose +// // printf("fileoffset = %lx thefileoffset =%lx new target address is %lx old target was %lx\n", sourceinfo.foffset, thefileoffset, newtargetaddress, targetaddress); +// if (m_forwardonly) +// { +// if ((targetaddress > newtargetaddress) || ((m_mainBaseAddr <= newtargetaddress) && (newtargetaddress <= (m_mainend)))) +// { +// pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; +// pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; +// pointersearch(newtargetaddress, pointerchain); +// } +// } +// else +// { +// /* code */ +// pointerchain.fileoffset[pointerchain.depth - 1] = sourceinfo.foffset; +// pointerchain.offset[pointerchain.depth - 1] = sourceinfo.offset; +// pointersearch(newtargetaddress, pointerchain); +// } +// } +// +// return; +// +// // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); +// +// // printf("depth is %d new address is %lx offset is %lx code offset is %lx \n", pointerchain.depth, address, pointerchain.fileoffset[pointerchain.depth], pointerchain.offset[pointerchain.depth]); +// // if (address < m_mainBaseAddr + m_mainSize) +// // { +// // printf("target reached!"); +// // printf("final offset is %lx \n", address - m_mainBaseAddr); +// // pointerchain.depth++; +// // pointerchain.offset[pointerchain.depth] = address - m_mainBaseAddr; +// // // save pointerchain +// // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); +// // return; +// } +// // change address to new one void GuiCheats::startpointersearch2(u64 targetaddress) // using global m_bookmark which has the label field already set correctly { m_PointerSearch = new PointerSearch_state; @@ -3966,98 +3966,98 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp // for (u8 i = 0; i < 20; i++) // printf("%d= %d ", i, m_hitcount.offset[i]); -void GuiCheats::searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain) //assumed range don't extend beyond a segment, need to make seperate call to cover multi segment -{ - // using global to reduce overhead - // use separate function if need to get rid of range in the passed variable // u64 m_max_depth; used in first call - // u64 m_target; - // u64 m_numoffset; - // u64 m_max_range; - // u64 m_low_main_heap_addr; The lowerst of main or heap start - // u64 m_high_main_heap_addr; The highest - // printf("in function current depth is %d @@@@@@@@@@@@@@@@@@@@@\n", depth); - // return; - m_hitcount.offset[pointerchain.depth]++; - - if (address <= m_target && m_target <= address + range) - { - printf("found ========================="); - pointerchain.offset[pointerchain.depth] = m_target - address; - pointerchain.depth++; - m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); - // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); - printf("found at depth %ld\n", pointerchain.depth); - return; - } - if (depth == 0) - { - // printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); - return; - // printf("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); - } - pointerchain.depth++; // for all call - depth--; // for all call - // u8 *buffer = new u8[range]; - u32 num = m_numoffset; - u32 nextrange; - u64 nextaddress; - // u32 endaddress = address + range; - // printf("I am at 1"); - u64 bufferSize = MAX_BUFFER_SIZE; - if (range < bufferSize) - bufferSize = range; - u8 *buffer = new u8[bufferSize]; - // printf("I am at 2"); - for (MemoryInfo meminfo : m_targetmemInfos) // a shorten list that has only the real targets - { - if (address < meminfo.addr) - { - // printf("I am at 4"); - return; // address not accessible} - } - if (address > meminfo.addr + meminfo.size) - { - // printf("I am at 5, address =%lx meminfo.addr = %1x, meminfo.size =%1x \n", address, meminfo.addr, meminfo.size); - continue; // next segment - } - u64 offset = 0; - u64 segmentend = meminfo.addr + meminfo.size; - // printf("I am at 3\n"); - while (address + offset < segmentend) - { - if (segmentend - (address + offset) < bufferSize) - bufferSize = segmentend - (address + offset); - - // printf("reading address %lx bufferSize %lx meminfo.addr is %lx meminfo.size is %lx ", (address + offset), bufferSize, meminfo.addr, meminfo.size); - // printf("Time since last update %d \n", time(NULL) - m_Time1); // printf("Top level meminfo.addr %lx\n time= %d\n", meminfo.addr, time(NULL) - m_Time1); - // return; - m_debugger->readMemory(buffer, bufferSize, (address + offset)); - for (u64 i = 0; i < bufferSize; i += sizeof(u64)) //for (u64 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) - { - nextaddress = *reinterpret_cast(&buffer[i]); - // printf("nextaddress = %lx \n", nextaddress); - if ((nextaddress >= m_low_main_heap_addr) && (nextaddress <= m_high_main_heap_addr)) - { - // printf("found ptr === %lx ======================================= pointerchain.depth is %d ==============offset+i is %d \n",nextaddress, pointerchain.depth, offset + i); - pointerchain.offset[pointerchain.depth] = offset + i; // per call - searchpointer(nextaddress, depth, m_max_range, pointerchain); - num--; - if (num == 0) - { - // printf("not found returning &&&&&&&&&&&&&&&&&&&&\n\n"); - return; - } - } - range -= sizeof(u64); - if (range == 0) - return; - } - - offset += bufferSize; - } - } - delete[] buffer; -} +// void GuiCheats::searchpointer(u64 address, u64 depth, u64 range, struct pointer_chain_t pointerchain) //assumed range don't extend beyond a segment, need to make seperate call to cover multi segment +// { +// // using global to reduce overhead +// // use separate function if need to get rid of range in the passed variable // u64 m_max_depth; used in first call +// // u64 m_target; +// // u64 m_numoffset; +// // u64 m_max_range; +// // u64 m_low_main_heap_addr; The lowerst of main or heap start +// // u64 m_high_main_heap_addr; The highest +// // printf("in function current depth is %d @@@@@@@@@@@@@@@@@@@@@\n", depth); +// // return; +// m_hitcount.offset[pointerchain.depth]++; +// +// if (address <= m_target && m_target <= address + range) +// { +// printf("found ========================="); +// pointerchain.offset[pointerchain.depth] = m_target - address; +// pointerchain.depth++; +// m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); //((u8 *)&address, sizeof(u64)); +// // *m_pointeroffsetDump->getData(offset * sizeof(pointer_chain_t) , void *buffer, size_t bufferSize); +// printf("found at depth %ld\n", pointerchain.depth); +// return; +// } +// if (depth == 0) +// { +// // printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); +// return; +// // printf("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); +// } +// pointerchain.depth++; // for all call +// depth--; // for all call +// // u8 *buffer = new u8[range]; +// u32 num = m_numoffset; +// u32 nextrange; +// u64 nextaddress; +// // u32 endaddress = address + range; +// // printf("I am at 1"); +// u64 bufferSize = MAX_BUFFER_SIZE; +// if (range < bufferSize) +// bufferSize = range; +// u8 *buffer = new u8[bufferSize]; +// // printf("I am at 2"); +// for (MemoryInfo meminfo : m_targetmemInfos) // a shorten list that has only the real targets +// { +// if (address < meminfo.addr) +// { +// // printf("I am at 4"); +// return; // address not accessible} +// } +// if (address > meminfo.addr + meminfo.size) +// { +// // printf("I am at 5, address =%lx meminfo.addr = %1x, meminfo.size =%1x \n", address, meminfo.addr, meminfo.size); +// continue; // next segment +// } +// u64 offset = 0; +// u64 segmentend = meminfo.addr + meminfo.size; +// // printf("I am at 3\n"); +// while (address + offset < segmentend) +// { +// if (segmentend - (address + offset) < bufferSize) +// bufferSize = segmentend - (address + offset); +// +// // printf("reading address %lx bufferSize %lx meminfo.addr is %lx meminfo.size is %lx ", (address + offset), bufferSize, meminfo.addr, meminfo.size); +// // printf("Time since last update %d \n", time(NULL) - m_Time1); // printf("Top level meminfo.addr %lx\n time= %d\n", meminfo.addr, time(NULL) - m_Time1); +// // return; +// m_debugger->readMemory(buffer, bufferSize, (address + offset)); +// for (u64 i = 0; i < bufferSize; i += sizeof(u64)) //for (u64 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) +// { +// nextaddress = *reinterpret_cast(&buffer[i]); +// // printf("nextaddress = %lx \n", nextaddress); +// if ((nextaddress >= m_low_main_heap_addr) && (nextaddress <= m_high_main_heap_addr)) +// { +// // printf("found ptr === %lx ======================================= pointerchain.depth is %d ==============offset+i is %d \n",nextaddress, pointerchain.depth, offset + i); +// pointerchain.offset[pointerchain.depth] = offset + i; // per call +// searchpointer(nextaddress, depth, m_max_range, pointerchain); +// num--; +// if (num == 0) +// { +// // printf("not found returning &&&&&&&&&&&&&&&&&&&&\n\n"); +// return; +// } +// } +// range -= sizeof(u64); +// if (range == 0) +// return; +// } +// +// offset += bufferSize; +// } +// } +// delete[] buffer; +// } /** * Primary: From 84d63cb3b7a2ad4d7154f4cce65d95690de789bb Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 26 Jul 2020 02:37:44 +0800 Subject: [PATCH 26/95] use ZL as shift key --- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 91 ++++++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index ff400829..3bcca21f 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -81,6 +81,7 @@ class GuiCheats : public Gui u64 m_high_main_heap_addr = 0x10000000000; u64 m_pointer_found = 0; bool m_abort = false; + bool m_showpointermenu = false; std::map m_frozenAddresses; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index ea92f5c2..36caaa66 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -16,7 +16,7 @@ #define STARTTIMER \ time_t unixTime1 = time(NULL); #define ENDTIMER \ - printf(" Time used is %d \n", time(NULL) - unixTime1); + printf(" Time used is %ld \n", time(NULL) - unixTime1); #define R_UNLESS(expr, res) \ ({ \ if (!(expr)) \ @@ -844,7 +844,7 @@ void GuiCheats::drawSearchRAMMenu() u32 strWidth = 0; std::stringstream ss; - if (m_searchMenuLocation == SEARCH_NONE) + if ((m_searchMenuLocation == SEARCH_NONE) || (m_searchMenuLocation == SEARCH_POINTER) || (m_searchMenuLocation == SEARCH_editRAM)) return; Gui::drawRectangled(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, Gui::makeColor(0x00, 0x00, 0x00, 0xA0)); @@ -980,6 +980,8 @@ void GuiCheats::drawSearchRAMMenu() break; case SEARCH_NONE: + case SEARCH_editRAM: + case SEARCH_POINTER: break; } } @@ -995,10 +997,11 @@ void GuiCheats::onInput(u32 kdown) Gui::g_requestExit = true; return; } - else if (m_searchMenuLocation == SEARCH_POINTER) + else if ((m_searchMenuLocation == SEARCH_POINTER) || (m_showpointermenu)) { m_searchMenuLocation = SEARCH_NONE; m_abort = true; + m_showpointermenu = false; printf("abort pressed .. \n"); } else if (m_searchMenuLocation == SEARCH_editRAM) @@ -1039,14 +1042,17 @@ void GuiCheats::onInput(u32 kdown) { m_abort = false; // (new Snackbar("Starting pointer search"))->show(); - m_searchMenuLocation = SEARCH_NONE; + // m_searchMenuLocation = SEARCH_NONE; printf("starting pointer search from plus %lx \n", m_EditorBaseAddr); m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_abort = false; m_Time1 = time(NULL); startpointersearch2(m_EditorBaseAddr); // need help here; don't know what always crash when startpointersearch2 is called from here + char st[100]; + snprintf(st, 100, "Done pointer search found %ld pointer in %d seconds", m_pointer_found, time(NULL) - m_Time1); printf("done pointer search \n"); printf("Time taken =%ld\n", time(NULL) - m_Time1); + (new Snackbar(st))->show(); } if (kdown & KEY_UP) { @@ -1279,7 +1285,7 @@ void GuiCheats::onInput(u32 kdown) while (!getinput("Enter the value at this memory", "You must know what type is the value and set it correctly in the search memory type setting", "", &value)) { } - printf("value = %ld\n", value); + printf("value = %ld\n", value._u64); rebasepointer(value); //bookmark); } Gui::g_currMessageBox->hide(); @@ -1651,7 +1657,10 @@ void GuiCheats::onInput(u32 kdown) if (m_menuLocation == CANDIDATES) m_selectedEntry = 0; } - if (kdown & KEY_ZR) + + u32 kheld = hidKeysHeld(CONTROLLER_P1_AUTO); + + if ((kdown & KEY_ZR) && !(kheld & KEY_ZL)) { m_addresslist_offset += 8; if (m_addresslist_offset >= (m_memoryDump->size() / sizeof(u64))) @@ -1661,7 +1670,7 @@ void GuiCheats::onInput(u32 kdown) // printf("%s\n", "ZR key pressed"); } - if (kdown & KEY_ZL) + if ((kdown & KEY_ZR) && (kheld & KEY_ZL)) { if (m_addresslist_offset >= 8) m_addresslist_offset -= 8; @@ -1669,7 +1678,8 @@ void GuiCheats::onInput(u32 kdown) } // End Mod - if (kdown & KEY_Y) + // hidScanInput(); + if ((kdown & KEY_Y) && (kheld & KEY_ZL)) { if (m_searchMenuLocation == SEARCH_NONE) { @@ -1677,7 +1687,21 @@ void GuiCheats::onInput(u32 kdown) { // in bookmark mode m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_searchMenuLocation = SEARCH_POINTER; - if (false) + // m_showpointermenu = true; + } + } + } + + if ((kdown & KEY_Y) && !(kheld & KEY_ZL)) + { + if (m_searchMenuLocation == SEARCH_NONE) + { + if (m_memoryDump1 != nullptr) + { // in bookmark mode + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + // m_searchMenuLocation = SEARCH_POINTER; + // m_showpointermenu = true; + if (m_menuLocation == CANDIDATES) { bookmark_t bookmark; m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); @@ -1732,12 +1756,12 @@ void GuiCheats::onInput(u32 kdown) printf("%s\n", tidStr.c_str()); printf("%s\n", buildIDStr.c_str()); //make sure not using bookmark - if (m_memoryDump1 != nullptr) - { - m_memoryDump = m_memoryDump1; - m_memoryDump1 = nullptr; - } - m_addresslist_offset = 0; + // if (m_memoryDump1 != nullptr) + // { + // m_memoryDump = m_memoryDump1; + // m_memoryDump1 = nullptr; + // } + // m_addresslist_offset = 0; // end mod } } @@ -1765,6 +1789,7 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntry = 0; break; case SEARCH_NONE: + case SEARCH_POINTER: break; case SEARCH_editRAM: // need UP if (m_selectedEntry > 4) @@ -1795,6 +1820,7 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntry = 1; break; case SEARCH_NONE: + case SEARCH_POINTER: break; case SEARCH_editRAM: // need DOWN if (m_selectedEntry < 35) @@ -1823,6 +1849,7 @@ void GuiCheats::onInput(u32 kdown) m_searchValueIndex--; break; case SEARCH_NONE: + case SEARCH_POINTER: break; case SEARCH_editRAM: // need LEFT if (m_selectedEntry % 5 > 1) @@ -1846,6 +1873,7 @@ void GuiCheats::onInput(u32 kdown) m_searchValueIndex++; break; case SEARCH_NONE: + case SEARCH_POINTER: break; case SEARCH_editRAM: // need RIGHT if (m_selectedEntry % 5 < 4) @@ -2475,14 +2503,13 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s newdataDump->addData((u8 *)&realValue, sizeof(u64)); helperinfo.count++; // printf("%lx,%lx\n",address,realValue); - std::stringstream ss; // replace the printf - ss.str(""); - ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; - ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; - char st[27]; - // st[28] = 13; - snprintf(st, 27, "%s\n", ss.str().c_str()); // - newstringDump->addData((u8 *)&st, sizeof(st)); // + // std::stringstream ss; // replace the printf + // ss.str(""); + // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; + // char st[27]; + // snprintf(st, 27, "%s\n", ss.str().c_str()); // + // newstringDump->addData((u8 *)&st, sizeof(st)); // } break; } @@ -2603,7 +2630,7 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); } searchValue_t value = {0}; - searchValue_t testing = {0}; // temp + // searchValue_t testing = {0}; // temp u64 address = 0; address = *reinterpret_cast(&buffer[i]); //(*displayDump)->getData(i * sizeof(u64), &address, sizeof(u64)); @@ -2802,8 +2829,8 @@ void GuiCheats::searchMemoryValuesPrimary(Debugger *debugger, searchType_t searc { bool ledOn = false; - searchValue_t zeroValue; - zeroValue._u64 = 0; + // searchValue_t zeroValue; + // zeroValue._u64 = 0; // printf("%s\n", "searchMemoryValuesPrimary"); // printf("%s\n", titleNameStr.c_str()); // printf("%s\n", tidStr.c_str()); @@ -3699,7 +3726,7 @@ void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) // // printf("memory scan completed offset is %lx at depth %lx\n\n", minimum, pointerchain.depth); // // pointerchain.offset[pointerchain.depth] = minimum; // pointerchain.depth++; -// +// // printf("**Found %ld sources for address %lx at depth %ld\n", sources.size(), targetaddress, pointerchain.depth); // for (sourceinfo_t sourceinfo : sources) // { @@ -3708,7 +3735,7 @@ void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) // //m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); // u64 newtargetaddress; // m_memoryDump1->getData(sourceinfo.foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte -// +// // // u64 checkaddress; // debug use // // m_dataDump->getData(foffset, &checkaddress, sizeof(u64)); //double check it for debug purpose // // printf("fileoffset = %lx thefileoffset =%lx new target address is %lx old target was %lx\n", sourceinfo.foffset, thefileoffset, newtargetaddress, targetaddress); @@ -3729,11 +3756,11 @@ void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) // pointersearch(newtargetaddress, pointerchain); // } // } -// +// // return; -// +// // // (*displayDump)->getData(pointerchain.fileoffset[pointerchain.depth] * sizeof(u64), &address, sizeof(u64)); -// +// // // printf("depth is %d new address is %lx offset is %lx code offset is %lx \n", pointerchain.depth, address, pointerchain.fileoffset[pointerchain.depth], pointerchain.offset[pointerchain.depth]); // // if (address < m_mainBaseAddr + m_mainSize) // // { @@ -3784,7 +3811,7 @@ void GuiCheats::resumepointersearch2() void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **displayDump, MemoryDump **dataDump, { - // printf("targetaddress %lx PS_depth %ld PS_index %ld PS_num_sources %ld\n",targetaddress, PS_depth, PS_index, PS_num_sources); + // printf("targetaddress %lx PS_depth %ld PS_index %ld PS_num_sources %ld\n", targetaddress, PS_depth, PS_index, PS_num_sources); if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) { From 3e8016da443f9d82748ade1a8e3d546272ca1484 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 26 Jul 2020 21:58:12 +0800 Subject: [PATCH 27/95] Dynamic bookmark and pointer chain resolution display --- Makefile | 2 +- source/guis/gui_cheats.cpp | 87 +++++++++++++++++++++++++++++++++++--- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 4b710243..e563a3e8 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 5 +VERSION_MICRO := 6 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 36caaa66..080e6f21 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -532,11 +532,50 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 290, 130, COLOR_BLACK, pidStr.c_str(), ALIGNED_LEFT); Gui::drawTextAligned(font14, 290, 150, COLOR_BLACK, buildIDStr.c_str(), ALIGNED_LEFT); - if ((Account::g_activeUser.uid[0] != 0) && (Account::g_activeUser.uid[1] != 0)) + // if ((Account::g_activeUser.uid[0] != 0) && (Account::g_activeUser.uid[1] != 0)) + // { + // ss.str(""); + // ss << Account::g_accounts[Account::g_activeUser]->getUserName() << " [ " << std::hex << (Account::g_activeUser.uid[1]) << " " << (Account::g_activeUser.uid[0]) << " ]"; + // Gui::drawTextAligned(font20, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + // } + //draw pointer chain if availabe on bookmark + // status bar + if (m_memoryDump1 != nullptr && m_menuLocation == CANDIDATES) { - ss.str(""); - ss << Account::g_accounts[Account::g_activeUser]->getUserName() << " [ " << std::hex << (Account::g_activeUser.uid[1]) << " " << (Account::g_activeUser.uid[0]) << " ]"; - Gui::drawTextAligned(font20, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + if (bookmark.pointer.depth > 0) + { + ss.str(""); + int i = 0; + ss << "z=" << bookmark.pointer.depth << " main"; //[0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << m_mainBaseAddr << "]"; + u64 nextaddress = m_mainBaseAddr; + for (int z = bookmark.pointer.depth; z >= 0; z--) + { + ss << "+" << std::uppercase << std::hex << bookmark.pointer.offset[z]; + // ss << " z= " << z << " "; + // printf("+%lx z=%d ", pointer_chain.offset[z], z); + nextaddress += bookmark.pointer.offset[z]; + // ss << "[0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << nextaddress << "]"; + // printf("[%lx]", nextaddress); + MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); + if (meminfo.perm == Perm_Rw) + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + else + { + ss << "(*access denied*)"; + // printf("*access denied*"); + break; + } + ss << "(" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << nextaddress << ")"; + i++; + if ((i == 4) || (i == 8)) + ss << "\n"; + // printf("(%lx)", nextaddress); + } + ss << " " << dataTypes[bookmark.type]; + Gui::drawTextAligned(font14, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } } if (m_cheatCnt > 0) @@ -637,7 +676,7 @@ void GuiCheats::draw() Gui::drawRectangle(Gui::g_framebuffer_width - 550, 300 + line * 40, 496, 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 530, 305 + line * 40, (m_selectedEntry == line && m_menuLocation == CANDIDATES) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); } - else // Book mark screen + else // Bookmark screen for (u8 line = 0; line < 8; line++) { if ((line + m_addresslist_offset) >= (m_memoryDump->size() / sizeof(u64))) @@ -651,14 +690,47 @@ void GuiCheats::draw() u64 address = 0; m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); m_AttributeDumpBookmark->getData((line + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + if (bookmark.pointer.depth > 0) // check if pointer chain point to valid address update address if necessary + { + bool updateaddress = true; + u64 nextaddress = m_mainBaseAddr; + for (int z = bookmark.pointer.depth; z >= 0; z--) + { + nextaddress += bookmark.pointer.offset[z]; + MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); + if (meminfo.perm == Perm_Rw) + if (z == 0) + { + if (address == nextaddress) + updateaddress = false; + else + { + address = nextaddress; + } + } + else + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + else + { + updateaddress = false; + break; + } + } + if (updateaddress) + { + m_memoryDump->putData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); + m_memoryDump->flushBuffer(); + } + } // bookmark display - ss << "[0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << "]"; //<< std::left << std::setfill(' ') << std::setw(18) << bookmark.label << ss << " ( " << _getAddressDisplayString(address, m_debugger, (searchType_t)bookmark.type) << " )"; if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) ss << " \uE130"; + if (bookmark.pointer.depth > 1) // have pointer + ss << " *"; } else ss << "And " << std::dec << ((m_memoryDump->size() / sizeof(u64)) - 8) << " others..."; @@ -1044,7 +1116,7 @@ void GuiCheats::onInput(u32 kdown) // (new Snackbar("Starting pointer search"))->show(); // m_searchMenuLocation = SEARCH_NONE; printf("starting pointer search from plus %lx \n", m_EditorBaseAddr); - m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + // m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_abort = false; m_Time1 = time(NULL); startpointersearch2(m_EditorBaseAddr); // need help here; don't know what always crash when startpointersearch2 is called from here @@ -1686,6 +1758,7 @@ void GuiCheats::onInput(u32 kdown) if (m_memoryDump1 != nullptr) { // in bookmark mode m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_searchMenuLocation = SEARCH_POINTER; // m_showpointermenu = true; } From 7dfe321b29394abec33358a0b19c1cc8dd9f8bba Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 26 Jul 2020 22:41:01 +0800 Subject: [PATCH 28/95] Update README.md --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ff3f195d..f409b060 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,20 @@ This fork is based on the solid foundation of EdiZon. The changes made are on the game memory hack aspect. I have added bookmark functionality, completed the range search feature and enhanced the speed to enable search for small value which generates lots of hits. -Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. Able to rebase first offset of cheat code for game version change that only affects the first offset. +Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. Able to rebase first offset of cheat code for game version change that only affects the first offset. Pointer search result is added back into bookmark. Bookmark with pointer chain attached will dynamically adjust the address on the bookmark list. Work in progress : Pointer search so more location can preserve over different game run and stage change in game. -PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. +PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. New key combo ZL+Y to get into pointer search setup. + +Here are the steps to do pointer search. +1. Clear previous search result if any. +2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). +3. Select the bookmark with address you want to find the pointer chain that targets it. +4. Press Lstick down will start the search with default configuration. +5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. +6. Result is added to the bookmark. Test it and if a good pointer chain is found add it to the cheat code file. + From 889b0c38b4e5f505e574a76668f2c71ed7e44a88 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 26 Jul 2020 22:45:46 +0800 Subject: [PATCH 29/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f409b060..c6f91d75 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This fork is based on the solid foundation of EdiZon. The changes made are on th I have added bookmark functionality, completed the range search feature and enhanced the speed to enable search for small value which generates lots of hits. Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. Able to rebase first offset of cheat code for game version change that only affects the first offset. Pointer search result is added back into bookmark. Bookmark with pointer chain attached will dynamically adjust the address on the bookmark list. -Work in progress : Pointer search so more location can preserve over different game run and stage change in game. +Work in progress : Faster pointer search, pause/resume of search, examination of intermidiate result, change search parameters mid search. PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. New key combo ZL+Y to get into pointer search setup. From 0a9f3e82d6ad7c9450b05d4ca6a11988b278d9c7 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 27 Jul 2020 13:30:05 +0800 Subject: [PATCH 30/95] static code type support for transfer between bookmark and cheat code --- Makefile | 2 +- include/guis/gui_cheats.hpp | 9 ++- source/guis/gui_cheats.cpp | 156 ++++++++++++++++++++++++++++++++---- 3 files changed, 148 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index e563a3e8..42eb12a9 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 6 +VERSION_MICRO := 7 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 3bcca21f..f11260a3 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -142,10 +142,10 @@ class GuiCheats : public Gui bool m_forwarddump = false; // reduce from 138 to 26 struct pointer_chain_t { - u64 depth; - u64 offset[MAX_POINTER_DEPTH + 1]; // offset to address pointed by pointer + u64 depth = 0; + u64 offset[MAX_POINTER_DEPTH + 1] = {0}; // offset to address pointed by pointer // below is for debugging can consider removing; - u64 fileoffset[MAX_POINTER_DEPTH + 1]; // offset to the file that has the address where the pointer was stored in this instance for debugging + u64 fileoffset[MAX_POINTER_DEPTH + 1] = {0}; // offset to the file that has the address where the pointer was stored in this instance for debugging }; struct bookmark_t { @@ -157,7 +157,7 @@ class GuiCheats : public Gui bool deleted = false; }; bookmark_t m_bookmark; //global for use in pointer search , target address to be updated dynamically by display routine TBD - bookmark_t bookmark; //maybe not used + bookmark_t bookmark; //used in add book mark pointer_chain_t m_hitcount; // maybe not used void rebasepointer(searchValue_t value); //struct bookmark_t bookmark); @@ -172,6 +172,7 @@ class GuiCheats : public Gui bool valuematch(searchValue_t value, u64 nextaddress); bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); bool addcodetofile(u64 index); + bool addstaticcodetofile(u64 index); u64 m_heapSize = 0; u64 m_mainSize = 0; u64 m_heapEnd = 0; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 080e6f21..c0bf7574 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -540,6 +540,7 @@ void GuiCheats::draw() // } //draw pointer chain if availabe on bookmark // status bar + // if (false) if (m_memoryDump1 != nullptr && m_menuLocation == CANDIDATES) { bookmark_t bookmark; @@ -576,6 +577,21 @@ void GuiCheats::draw() ss << " " << dataTypes[bookmark.type]; Gui::drawTextAligned(font14, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); } + else + { + ss.str(""); + if (bookmark.heap == true) + { + ss << "Heap + "; + } + else + { + ss << "Main + "; + } + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.offset; + ss << " " << dataTypes[bookmark.type]; + Gui::drawTextAligned(font14, 768, 205, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } } if (m_cheatCnt > 0) @@ -690,6 +706,7 @@ void GuiCheats::draw() u64 address = 0; m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); m_AttributeDumpBookmark->getData((line + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // if (false) if (bookmark.pointer.depth > 0) // check if pointer chain point to valid address update address if necessary { bool updateaddress = true; @@ -1119,7 +1136,7 @@ void GuiCheats::onInput(u32 kdown) // m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_abort = false; m_Time1 = time(NULL); - startpointersearch2(m_EditorBaseAddr); // need help here; don't know what always crash when startpointersearch2 is called from here + startpointersearch2(m_EditorBaseAddr); char st[100]; snprintf(st, 100, "Done pointer search found %ld pointer in %d seconds", m_pointer_found, time(NULL) - m_Time1); printf("done pointer search \n"); @@ -1228,6 +1245,7 @@ void GuiCheats::onInput(u32 kdown) //bookmark_t bookmark; memcpy(&bookmark.label, &cheat.readable_name, sizeof(bookmark.label)); bookmark.pointer.depth = 0; + bookmark.deleted = false; bool success = false; u64 offset[MAX_POINTER_DEPTH + 1] = {0}; u64 depth = 0; @@ -1240,6 +1258,7 @@ void GuiCheats::onInput(u32 kdown) u8 Register = (cheat.opcodes[i] >> 16) & 0xF; u8 FSA = (cheat.opcodes[i] >> 12) & 0xF; u8 T = (cheat.opcodes[i] >> 24) & 0xF; + u8 M = (cheat.opcodes[i] >> 20) & 0xF; printf("code %x opcode %d register %d FSA %d %x \n", cheat.opcodes[i], opcode, Register, FSA, cheat.opcodes[i + 1]); @@ -1250,6 +1269,49 @@ void GuiCheats::onInput(u32 kdown) break; } + if (opcode == 0) + { //static case + i++; + bookmark.offset = cheat.opcodes[i]; + switch (T) + { + case 1: + bookmark.type = SEARCH_TYPE_UNSIGNED_8BIT; + i++; + break; + case 2: + bookmark.type = SEARCH_TYPE_UNSIGNED_16BIT; + i++; + break; + case 4: + bookmark.type = SEARCH_TYPE_UNSIGNED_32BIT; + i++; + break; + case 8: + bookmark.type = SEARCH_TYPE_UNSIGNED_64BIT; + i += 2; + break; + default: + printf("cheat code processing error, wrong width value\n"); + bookmark.type = SEARCH_TYPE_UNSIGNED_32BIT; + i++; + break; + }; + if (M == 1) + { + bookmark.heap = true; + address = m_heapBaseAddr + bookmark.offset; + } + else + { + bookmark.heap = false; + address = m_mainBaseAddr + bookmark.offset; + } + + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + continue; + } if (depth == 0) { if (opcode == 5 && FSA == 0) @@ -1297,6 +1359,7 @@ void GuiCheats::onInput(u32 kdown) bookmark.type = SEARCH_TYPE_UNSIGNED_64BIT; break; default: + printf("cheat code processing error, wrong width value\n"); bookmark.type = SEARCH_TYPE_UNSIGNED_32BIT; break; } @@ -1783,20 +1846,13 @@ void GuiCheats::onInput(u32 kdown) if (bookmark.pointer.depth > 1) { addcodetofile(m_selectedEntry + m_addresslist_offset); - m_searchMenuLocation = SEARCH_NONE; - // dmntchtForceOpenCheatProcess(); - (new Snackbar("Coded added to cheat file, reload to take effect"))->show(); - // (new MessageBox("Add current pointer chain to cheat file?", MessageBox::YES_NO)) - // ->setSelectionAction([&](u8 selection) { - // if (selection) - // { - // addcodetofile(index); // index also does not preserve; need to figure out why this won't work - // m_searchMenuLocation = SEARCH_NONE; - // } - // Gui::g_currMessageBox->hide(); - // }) - // ->show(); } + else + { + addstaticcodetofile(m_selectedEntry + m_addresslist_offset); + } + m_searchMenuLocation = SEARCH_NONE; + (new Snackbar("Coded added to cheat file, reload to take effect"))->show(); } // pointercheck(); // (new Snackbar("Searching pointer "))->show(); @@ -1962,6 +2018,17 @@ void GuiCheats::onInput(u32 kdown) u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; bookmark_t bookmark; + if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + { + bookmark.offset = address - m_memoryDump->getDumpInfo().heapBaseAddress; + bookmark.heap = true; + } + else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + { + bookmark.offset = address - m_memoryDump->getDumpInfo().mainBaseAddress; + bookmark.heap = false; + } + bookmark.type = m_searchType; Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); @@ -4365,3 +4432,64 @@ bool GuiCheats::addcodetofile(u64 index) return true; } + +bool GuiCheats::addstaticcodetofile(u64 index) +{ + std::stringstream buildIDStr; + std::stringstream filebuildIDStr; + { + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + // buildIDStr.str("attdumpbookmark"); + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; + } + + std::stringstream realCheatPath; + { + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << "/cheats/"; + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << buildIDStr.str() << ".txt"; + } + + bookmark_t bookmark; + u64 address; + m_AttributeDumpBookmark->getData(index * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + m_memoryDump->getData(index * sizeof(u64), &address, sizeof(u64)); + searchValue_t realvalue; + realvalue._u64 = 0; + m_debugger->readMemory(&realvalue, dataTypeSizes[bookmark.type], address); + + FILE *pfile; + pfile = fopen(filebuildIDStr.str().c_str(), "a"); + std::stringstream ss; + if (pfile != NULL) + { + // printf("going to write to file\n"); + ss.str(""); + ss << "[" << bookmark.label << "]" + << "\n"; + ss << "0" << dataTypeSizes[bookmark.type] + 0 << (bookmark.heap ? 1 : 0) << "00000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.offset << " " + << std::uppercase << std::hex << std::setfill('0') << ((dataTypeSizes[bookmark.type] == 8) ? std::setw(16) : std::setw(8)) + << ((dataTypeSizes[bookmark.type] == 8) ? realvalue._u64 : realvalue._u32) << "\n"; + printf("index = %ld depth = %ld offset = %ld offset = %ld offset = %ld offset = %ld\n", index, bookmark.pointer.depth, bookmark.pointer.offset[3], bookmark.pointer.offset[2], bookmark.pointer.offset[1], bookmark.pointer.offset[0]); + printf("address = %lx value = %lx \n", address, realvalue._u64); + printf("dataTypeSizes[bookmark.type] %d\n", dataTypeSizes[bookmark.type]); + fputs(ss.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on Edizon dir \n"); + + pfile = fopen(realCheatPath.str().c_str(), "a"); + if (pfile != NULL) + { + fputs(ss.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on contents dir \n"); + + return true; +} From 1ec36a0b8b5697d0d5e95f37736ae7d704aedd07 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 27 Jul 2020 14:57:11 +0800 Subject: [PATCH 31/95] No more compiler warnings --- source/guis/gui_cheats.cpp | 63 ++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index c0bf7574..d1ac305f 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -866,8 +866,8 @@ void GuiCheats::drawSearchPointerMenu() void GuiCheats::drawEditRAMMenu() { - static u32 cursorBlinkCnt = 0; - u32 strWidth = 0; + // static u32 cursorBlinkCnt = 0; + // u32 strWidth = 0; std::stringstream ss; if (m_searchMenuLocation != SEARCH_editRAM) // need @@ -1077,6 +1077,7 @@ void GuiCheats::drawSearchRAMMenu() void GuiCheats::onInput(u32 kdown) { + u32 kheld = hidKeysHeld(CONTROLLER_P1_AUTO); if (kdown & KEY_B) { @@ -1138,7 +1139,7 @@ void GuiCheats::onInput(u32 kdown) m_Time1 = time(NULL); startpointersearch2(m_EditorBaseAddr); char st[100]; - snprintf(st, 100, "Done pointer search found %ld pointer in %d seconds", m_pointer_found, time(NULL) - m_Time1); + snprintf(st, 100, "Done pointer search found %ld pointer in %ld seconds", m_pointer_found, time(NULL) - m_Time1); printf("done pointer search \n"); printf("Time taken =%ld\n", time(NULL) - m_Time1); (new Snackbar(st))->show(); @@ -1793,8 +1794,6 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntry = 0; } - u32 kheld = hidKeysHeld(CONTROLLER_P1_AUTO); - if ((kdown & KEY_ZR) && !(kheld & KEY_ZL)) { m_addresslist_offset += 8; @@ -1907,8 +1906,10 @@ void GuiCheats::onInput(u32 kdown) switch (m_searchMenuLocation) { case SEARCH_TYPE: - [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry % 2 == 1) - m_selectedEntry--; + // [[fallthrough]] + case SEARCH_MODE: + if (m_selectedEntry % 2 == 1) + m_selectedEntry--; break; case SEARCH_REGION: if (m_selectedEntry > 0) @@ -1937,8 +1938,10 @@ void GuiCheats::onInput(u32 kdown) switch (m_searchMenuLocation) { case SEARCH_TYPE: - [[fallthrough]] case SEARCH_MODE : if ((m_selectedEntry + 1) < 12 && m_selectedEntry % 2 == 0) - m_selectedEntry++; + // [[fallthrough]] + case SEARCH_MODE: + if ((m_selectedEntry + 1) < 12 && m_selectedEntry % 2 == 0) + m_selectedEntry++; break; case SEARCH_REGION: if (m_selectedEntry < 3) @@ -1968,8 +1971,10 @@ void GuiCheats::onInput(u32 kdown) switch (m_searchMenuLocation) { case SEARCH_TYPE: - [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry >= 2) - m_selectedEntry -= 2; + // [[fallthrough]] + case SEARCH_MODE: + if (m_selectedEntry >= 2) + m_selectedEntry -= 2; break; case SEARCH_REGION: break; @@ -1992,8 +1997,10 @@ void GuiCheats::onInput(u32 kdown) switch (m_searchMenuLocation) { case SEARCH_TYPE: - [[fallthrough]] case SEARCH_MODE : if (m_selectedEntry <= 9) - m_selectedEntry += 2; + // [[fallthrough]] + case SEARCH_MODE: + if (m_selectedEntry <= 9) + m_selectedEntry += 2; break; case SEARCH_REGION: break; @@ -2652,6 +2659,13 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s // newstringDump->addData((u8 *)&st, sizeof(st)); // } break; + case SEARCH_MODE_NONE: + case SEARCH_MODE_SAME: + case SEARCH_MODE_DIFF: + case SEARCH_MODE_INC: + case SEARCH_MODE_DEC: + printf("search mode non !"); + break; } } @@ -3201,6 +3215,23 @@ void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t sea } } break; + case SEARCH_MODE_POINTER: + if (((newValue._u64 >= m_mainBaseAddr) && (newValue._u64 <= (m_mainend))) || ((newValue._u64 >= m_heapBaseAddr) && (newValue._u64 <= (m_heapEnd)))) + { + addrDump->addData((u8 *)&addr, sizeof(u64)); + newMemDump->addData((u8 *)&newValue, sizeof(u64)); + helperinfo.count++; + } + printf("error 321\n"); + break; + case SEARCH_MODE_RANGE: + case SEARCH_MODE_NONE: + case SEARCH_MODE_NEQ: + case SEARCH_MODE_EQ: + case SEARCH_MODE_GT: + case SEARCH_MODE_LT: + printf("error 123\n"); + break; } addr += dataTypeSizes[searchType]; } @@ -3505,6 +3536,12 @@ void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchValue_t sea } break; case SEARCH_MODE_NONE: + case SEARCH_MODE_POINTER: + case SEARCH_MODE_RANGE: + case SEARCH_MODE_NEQ: + case SEARCH_MODE_EQ: + case SEARCH_MODE_GT: + case SEARCH_MODE_LT: break; } } From 26951a67b47f6e8cab8697959b23c7fed6ed47af Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 28 Jul 2020 07:31:36 +0800 Subject: [PATCH 32/95] pause resume and status for pointer search done --- Makefile | 2 +- include/guis/gui_cheats.hpp | 13 +- source/guis/gui_cheats.cpp | 248 ++++++++++++++++++++++-------------- source/main.cpp | 4 +- 4 files changed, 169 insertions(+), 98 deletions(-) diff --git a/Makefile b/Makefile index 42eb12a9..eaf0629d 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 7 +VERSION_MICRO := 8 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index f11260a3..b552348d 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -119,7 +119,7 @@ class GuiCheats : public Gui #define MAX_POINTER_TARGET 3 struct PointerSearch_state { - // u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget + u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget u64 index[MAX_POINTER_DEPTH + 1] = {0}; // when there is a hit retrieve the offsets with indexs and sources[index].offset u64 num_offsets[MAX_POINTER_DEPTH + 1] = {0}; // for analysis u64 num_sources[MAX_POINTER_DEPTH + 1] = {0}; // this is how we will go down the column @@ -129,7 +129,9 @@ class GuiCheats : public Gui void startpointersearch2(u64 targetaddress); void pointersearch2(u64 targetaddress, u64 depth); void resumepointersearch2(); - bool m_pointersearch_done = false; + bool m_pointersearch_canresume = false; + bool m_PS_resume = false; + bool m_PS_pause = false; #define PS_depth depth #define PS_index m_PointerSearch->index[PS_depth] // #define PS_indexP m_PointerSearch->index[PS_depth-1] @@ -137,6 +139,13 @@ class GuiCheats : public Gui #define PS_num_sources m_PointerSearch->num_sources[PS_depth] // #define PS_num_sourcesP m_PointerSearch->num_sources[PS_depth-1] #define PS_sources m_PointerSearch->sources[PS_depth] +#define PS_lastdepth m_PointerSearch->depth +#define REPLACEFILE(file1,file2) remove(file2);\ + while (access(file2, F_OK) == 0)\ + { printf("waiting for delete %s\n",file2); } \ + rename(file1,file2);\ + while (access(file2, F_OK) != 0)\ + { printf("waiting for rename %s\n",file1); } bool m_forwardonly = false; bool m_forwarddump = false; // reduce from 138 to 26 diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index d1ac305f..39146ef7 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -275,16 +275,17 @@ GuiCheats::GuiCheats() : Gui() m_AttributeDumpBookmark->clear(); delete m_AttributeDumpBookmark; - remove(filebuildIDStr.str().c_str()); - while (access(filebuildIDStr.str().c_str(), F_OK) == 0) - { - printf("waiting for delete\n"); - } - rename(EDIZON_DIR "/tempbookmark.dat", filebuildIDStr.str().c_str()); - while (access(filebuildIDStr.str().c_str(), F_OK) != 0) - { - printf("waiting for rename\n"); - } + // remove(filebuildIDStr.str().c_str()); + // while (access(filebuildIDStr.str().c_str(), F_OK) == 0) + // { + // printf("waiting for delete\n"); + // } + // rename(EDIZON_DIR "/tempbookmark.dat", filebuildIDStr.str().c_str()); + // while (access(filebuildIDStr.str().c_str(), F_OK) != 0) + // { + // printf("waiting for rename\n"); + // } + REPLACEFILE(filebuildIDStr.str().c_str(), EDIZON_DIR "/tempbookmark.dat"); m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); // m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); @@ -1077,7 +1078,7 @@ void GuiCheats::drawSearchRAMMenu() void GuiCheats::onInput(u32 kdown) { - u32 kheld = hidKeysHeld(CONTROLLER_P1_AUTO); + u32 kheld = hidKeysHeld(CONTROLLER_PLAYER_1) | hidKeysHeld(CONTROLLER_HANDHELD); if (kdown & KEY_B) { @@ -1128,7 +1129,7 @@ void GuiCheats::onInput(u32 kdown) // BM2 if (m_searchMenuLocation == SEARCH_POINTER) { - if (kdown & KEY_PLUS) + if ((kdown & KEY_PLUS) && !(kheld & KEY_ZL)) { m_abort = false; // (new Snackbar("Starting pointer search"))->show(); @@ -1137,13 +1138,23 @@ void GuiCheats::onInput(u32 kdown) // m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_abort = false; m_Time1 = time(NULL); - startpointersearch2(m_EditorBaseAddr); + if (m_pointersearch_canresume) + resumepointersearch2(); + else + startpointersearch2(m_EditorBaseAddr); char st[100]; snprintf(st, 100, "Done pointer search found %ld pointer in %ld seconds", m_pointer_found, time(NULL) - m_Time1); printf("done pointer search \n"); printf("Time taken =%ld\n", time(NULL) - m_Time1); (new Snackbar(st))->show(); } + if ((kdown & KEY_PLUS) && (kheld & KEY_ZL)) + { + m_pointersearch_canresume = false; + delete m_PointerSearch; + printf("set resume to false\n"); + } + if (kdown & KEY_UP) { if (m_selectedEntry > 0) @@ -1560,7 +1571,10 @@ void GuiCheats::onInput(u32 kdown) // m_pointeroffsetDump = new MemoryDump(EDIZON_DIR "/pointerdump1.dat", DumpType::POINTER, true); m_searchValue[0]._u64 = m_EditorBaseAddr - 0x800; m_searchValue[1]._u64 = m_EditorBaseAddr; - startpointersearch2(m_EditorBaseAddr); + if (m_pointersearch_canresume) + resumepointersearch2(); + else + startpointersearch2(m_EditorBaseAddr); printf("done pointer search \n"); printf("Time taken =%ld\n", time(NULL) - m_Time1); @@ -1826,7 +1840,11 @@ void GuiCheats::onInput(u32 kdown) } } } - + // if ((kdown & KEY_X) && (kheld & KEY_ZL)) + // { + // printf("resume \n"); + // resumepointersearch2(); + // } if ((kdown & KEY_Y) && !(kheld & KEY_ZL)) { if (m_searchMenuLocation == SEARCH_NONE) @@ -3958,7 +3976,8 @@ void GuiCheats::startpointersearch2(u64 targetaddress) // using global m_bookmar m_Time1 = time(NULL); m_pointer_found = 0; m_abort = false; - m_pointersearch_done = false; + m_PS_resume = false; + m_PS_pause = false; // PS_depth = 0; // need this if m_PointerSearch isn't created here // m_PointerSearch->index = {0}; // try @@ -3972,111 +3991,152 @@ void GuiCheats::startpointersearch2(u64 targetaddress) // using global m_bookmar printf("End pointer search \n"); printf("Time taken =%ld Found %ld pointer chain\n", time(NULL) - m_Time1, m_pointer_found); - if (m_pointersearch_done) + if (!m_PS_pause) { delete m_PointerSearch; } + else + m_pointersearch_canresume = true; + delete m_dataDump; } void GuiCheats::resumepointersearch2() { - pointersearch2(0, 0); // 0 means continue - if (m_pointersearch_done) + if (m_pointersearch_canresume) { - delete m_PointerSearch; + m_PS_resume = true; + m_PS_pause = false; + m_dataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, false); + pointersearch2(0, 0); + delete m_dataDump; + if (!m_PS_pause) + { + delete m_PointerSearch; + } } } void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **displayDump, MemoryDump **dataDump, { - // printf("targetaddress %lx PS_depth %ld PS_index %ld PS_num_sources %ld\n", targetaddress, PS_depth, PS_index, PS_num_sources); - if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) + if (!m_PS_resume) { - - printf("\ntarget reached!=========================\n"); - printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); - m_bookmark.pointer.offset[PS_depth] = targetaddress - m_mainBaseAddr; - m_bookmark.pointer.depth = PS_depth; - for (int z = PS_depth - 1; z >= 0; z--) + // printf("targetaddress %lx PS_depth %ld PS_index %ld PS_num_sources %ld\n", targetaddress, PS_depth, PS_index, PS_num_sources); + if ((m_mainBaseAddr <= targetaddress) && (targetaddress <= (m_mainend))) { - m_bookmark.pointer.offset[z] = m_PointerSearch->sources[z][m_PointerSearch->index[z]].offset; - } - m_AttributeDumpBookmark->addData((u8 *)&m_bookmark, sizeof(bookmark_t)); - m_AttributeDumpBookmark->flushBuffer(); - m_memoryDumpBookmark->addData((u8 *)&m_mainBaseAddr, sizeof(u64)); //need to update - m_memoryDumpBookmark->flushBuffer(); - // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); - // m_pointeroffsetDump->flushBuffer(); // is this useful? - printf("main"); - for (int z = m_bookmark.pointer.depth; z >= 0; z--) - printf("+%lx z=%d ", m_bookmark.pointer.offset[z], z); - printf("\n\n"); - m_pointer_found++; - return; // consider don't return to find more - }; - if (PS_depth == m_max_depth) - { - // printf("max pointer depth reached\n\n"); - return; - } - u64 offset = 0; - // u64 thefileoffset; - u64 bufferSize = MAX_BUFFER_SIZE; - u8 *buffer = new u8[bufferSize]; - u64 distance; - u64 minimum = m_max_range; // a large number to start - // std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers - sourceinfo_t sourceinfo; - // printf("PS_num_sources %d ", PS_num_sources); - PS_num_sources = 0; - while (offset < m_dataDump->size()) - { - if (m_dataDump->size() - offset < bufferSize) - bufferSize = m_dataDump->size() - offset; - m_dataDump->getData(offset, buffer, bufferSize); // BM4 + printf("\ntarget reached!=========================\n"); + printf("final offset is %lx \n", targetaddress - m_mainBaseAddr); + m_bookmark.pointer.offset[PS_depth] = targetaddress - m_mainBaseAddr; + m_bookmark.pointer.depth = PS_depth; + for (int z = PS_depth - 1; z >= 0; z--) + { + m_bookmark.pointer.offset[z] = m_PointerSearch->sources[z][m_PointerSearch->index[z]].offset; + } - for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + m_AttributeDumpBookmark->addData((u8 *)&m_bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + m_memoryDumpBookmark->addData((u8 *)&m_mainBaseAddr, sizeof(u64)); //need to update + m_memoryDumpBookmark->flushBuffer(); + // m_pointeroffsetDump->addData((u8 *)&pointerchain, sizeof(pointer_chain_t)); + // m_pointeroffsetDump->flushBuffer(); // is this useful? + printf("main"); + for (int z = m_bookmark.pointer.depth; z >= 0; z--) + printf("+%lx z=%d ", m_bookmark.pointer.offset[z], z); + printf("\n\n"); + m_pointer_found++; + return; // consider don't return to find more + }; + if (PS_depth == m_max_depth) { - if (m_abort) - return; - u64 pointedaddress = *reinterpret_cast(&buffer[i]); - if (targetaddress >= pointedaddress) + // printf("max pointer depth reached\n\n"); + return; + } + u64 offset = 0; + // u64 thefileoffset; + u64 bufferSize = MAX_BUFFER_SIZE; + u8 *buffer = new u8[bufferSize]; + u64 distance; + u64 minimum = m_max_range; // a large number to start + // std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers + sourceinfo_t sourceinfo; + // printf("PS_num_sources %d ", PS_num_sources); + PS_num_sources = 0; + while (offset < m_dataDump->size()) + { + if (m_dataDump->size() - offset < bufferSize) + bufferSize = m_dataDump->size() - offset; + m_dataDump->getData(offset, buffer, bufferSize); // BM4 + + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) { - distance = targetaddress - pointedaddress; - if (distance < minimum) - { - sourceinfo.foffset = offset + i; - sourceinfo.offset = distance; - PS_sources[PS_num_sources] = sourceinfo; - PS_num_sources++; - // sources.push_back(sourceinfo); - // thefileoffset = offset + i; //for debug only - } - else if (distance == minimum) + if (m_abort) + return; + u64 pointedaddress = *reinterpret_cast(&buffer[i]); + if (targetaddress >= pointedaddress) { - sourceinfo.foffset = offset + i; - sourceinfo.offset = distance; - PS_sources[PS_num_sources] = sourceinfo; - PS_num_sources++; - // sources.push_back(sourceinfo); - // thefileoffset = offset + i; //for deubg only + distance = targetaddress - pointedaddress; + if (distance < minimum) + { + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + PS_sources[PS_num_sources] = sourceinfo; + PS_num_sources++; + // sources.push_back(sourceinfo); + // thefileoffset = offset + i; //for debug only + } + else if (distance == minimum) + { + sourceinfo.foffset = offset + i; + sourceinfo.offset = distance; + PS_sources[PS_num_sources] = sourceinfo; + PS_num_sources++; + // sources.push_back(sourceinfo); + // thefileoffset = offset + i; //for deubg only + } } + if (PS_num_sources > m_max_source) + break; } if (PS_num_sources > m_max_source) break; + offset += bufferSize; } - if (PS_num_sources > m_max_source) - break; - offset += bufferSize; - } - delete[] buffer; // release memory use for the search of sources - // printf("**Found %ld sources for address %lx at depth %ld\n", PS_num_sources, targetaddress, PS_depth); + delete[] buffer; // release memory use for the search of sources + // printf("**Found %ld sources for address %lx at depth %ld\n", PS_num_sources, targetaddress, PS_depth); + PS_index = 0; + } + else if (PS_depth == PS_lastdepth) + { + m_PS_resume = false; + } - // PS_depth++; - PS_index = 0; while (PS_index < PS_num_sources) { + hidScanInput(); + u32 kheld = hidKeysHeld(CONTROLLER_PLAYER_1) | hidKeysHeld(CONTROLLER_HANDHELD); + // u32 kdown = hidKeysDown(CONTROLLER_PLAYER_1) | hidKeysDown(CONTROLLER_HANDHELD); + if ((kheld & KEY_B) && (kheld & KEY_ZL)) + { + m_PS_pause = true; + PS_lastdepth = PS_depth; + } + if (m_PS_pause) + return; + + // status update + std::stringstream SS; + SS.str(""); + SS << "F=" << std::setw(2) << m_pointer_found; + for (u64 i = 0; i < m_max_depth; i++) + SS << " Z=" << i << ":" << std::setfill('0') << std::setw(2) << m_PointerSearch->index[i] + << "/" << std::setfill('0') << std::setw(2) << m_PointerSearch->num_sources[i] << " "; + // SS << "\n"; + // printf(SS.str().c_str()); + Gui::beginDraw(); + Gui::drawRectangle(70, 465, 1150, 40, currTheme.backgroundColor); + Gui::drawText(font20, 70, 465, currTheme.textColor, SS.str().c_str()); + Gui::endDraw(); + u64 newtargetaddress; m_memoryDump1->getData(PS_sources[PS_index].foffset, &newtargetaddress, sizeof(u64)); // fileoffset is in byte if (m_forwardonly) @@ -4090,6 +4150,8 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp { pointersearch2(newtargetaddress, PS_depth + 1); } + if (m_PS_pause) + return; PS_index++; } return; diff --git a/source/main.cpp b/source/main.cpp index a76f37ac..8a426b05 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -242,8 +242,8 @@ int main(int argc, char **argv) while (appletMainLoop()) { hidScanInput(); - kheld = hidKeysHeld(CONTROLLER_P1_AUTO); - kdown = hidKeysDown(CONTROLLER_P1_AUTO); + kheld = hidKeysHeld(CONTROLLER_PLAYER_1)|hidKeysHeld(CONTROLLER_HANDHELD); + kdown = hidKeysDown(CONTROLLER_PLAYER_1)|hidKeysDown(CONTROLLER_HANDHELD); if (Gui::g_nextGui != GUI_INVALID) { From 1df417da94d419888037d304b6f87904a1355568 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 28 Jul 2020 18:07:02 +0800 Subject: [PATCH 33/95] check for wait for file delete complete --- source/guis/gui_cheats.cpp | 45 ++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 39146ef7..11b1aa83 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -285,7 +285,7 @@ GuiCheats::GuiCheats() : Gui() // { // printf("waiting for rename\n"); // } - REPLACEFILE(filebuildIDStr.str().c_str(), EDIZON_DIR "/tempbookmark.dat"); + REPLACEFILE(EDIZON_DIR "/tempbookmark.dat", filebuildIDStr.str().c_str()); m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); // m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, true); @@ -2252,27 +2252,33 @@ void GuiCheats::onInput(u32 kdown) printf("%s%lx\n", "Dump Size = ", m_memoryDump->size()); GuiCheats::searchMemoryValuesSecondary(m_debugger, m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); delete m_memoryDump; - remove(EDIZON_DIR "/memdump1.dat"); - rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); - printf("%s\n", "renaming"); + // remove(EDIZON_DIR "/memdump1.dat"); + // rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + // printf("%s\n", "renaming"); + REPLACEFILE(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat") m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); } else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { GuiCheats::searchMemoryValuesTertiary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); delete m_memoryDump; - remove(EDIZON_DIR "/memdump1.dat"); - remove(EDIZON_DIR "/memdump1a.dat"); - rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); - rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + // remove(EDIZON_DIR "/memdump1.dat"); + // remove(EDIZON_DIR "/memdump1a.dat"); + // rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + // rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + REPLACEFILE(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + REPLACEFILE(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); - remove(EDIZON_DIR "/datadump2.dat"); - rename(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); - // rename B to A - remove(EDIZON_DIR "/datadumpA.dat"); - rename(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat"); - remove(EDIZON_DIR "/datadumpB.dat"); - rename(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + // remove(EDIZON_DIR "/datadump2.dat"); + // rename(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); + REPLACEFILE(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); + // // rename B to A + // remove(EDIZON_DIR "/datadumpA.dat"); + // rename(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat"); + REPLACEFILE(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat") + // remove(EDIZON_DIR "/datadumpB.dat"); + // rename(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + REPLACEFILE(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); } } else @@ -2288,8 +2294,9 @@ void GuiCheats::onInput(u32 kdown) GuiCheats::searchMemoryAddressesSecondary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, &m_memoryDump); if (m_nothingchanged == false) { - remove(EDIZON_DIR "/memdump1a.dat"); // remove old helper - rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); // rename new helper to current helper + // remove(EDIZON_DIR "/memdump1a.dat"); // remove old helper + // rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); // rename new helper to current helper + REPLACEFILE(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); } } } @@ -4367,8 +4374,8 @@ static void _moveLonelyCheats(u8 *buildID, u64 titleID) realCheatPath << buildIDStr.str() << ".txt"; - rename(lonelyCheatPath.str().c_str(), realCheatPath.str().c_str()); - + // rename(lonelyCheatPath.str().c_str(), realCheatPath.str().c_str()); + REPLACEFILE(lonelyCheatPath.str().c_str(), realCheatPath.str().c_str()); (new MessageBox("A new cheat has been added for this title. \n Please restart the game to start using it.", MessageBox::OKAY))->show(); } } From 683fa5f1584bb22b441ea7c549d60ab1eaf5f8b4 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:14:26 +0800 Subject: [PATCH 34/95] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index c6f91d75..08f806ce 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,7 @@ Here are the steps to do pointer search. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. 6. Result is added to the bookmark. Test it and if a good pointer chain is found add it to the cheat code file. - - - +Original functinality of Edizon on game save is available when launched without a game running.


Latest Release From 76e790aacb3f5121e341a57396713966567cfbd7 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:16:25 +0800 Subject: [PATCH 35/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 08f806ce..a886da5b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ PS: In app help on button currently don't show hint what right stick down and le Here are the steps to do pointer search. 1. Clear previous search result if any. -2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). +2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). The result of this search is used for pointer subsequent pointer search. Very important to get it right to find the pointer chains. 3. Select the bookmark with address you want to find the pointer chain that targets it. 4. Press Lstick down will start the search with default configuration. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. From cb0552ce3f13a00b30ba80f14cd602168c59e1b2 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:16:59 +0800 Subject: [PATCH 36/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a886da5b..5dac5f39 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ PS: In app help on button currently don't show hint what right stick down and le Here are the steps to do pointer search. 1. Clear previous search result if any. -2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). The result of this search is used for pointer subsequent pointer search. Very important to get it right to find the pointer chains. +2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). The result of this search is used for subsequent pointer search. Very important to get it right to find the pointer chains. 3. Select the bookmark with address you want to find the pointer chain that targets it. 4. Press Lstick down will start the search with default configuration. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. From 8e0f9e983e7d0d09c15b15711fc462a6c8e3f650 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:32:01 +0800 Subject: [PATCH 37/95] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5dac5f39..db914c0a 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,9 @@ Here are the steps to do pointer search. 4. Press Lstick down will start the search with default configuration. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. 6. Result is added to the bookmark. Test it and if a good pointer chain is found add it to the cheat code file. +7. Pointer search can be paused by holddown ZL+B. Normal functionality of the app is all available while pointer search is pause. +8. Start pointer search again to resume (step 4 or 5). Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". +9. Results are appended to the bookmark list. Test them to see the validity of the chain when the game state change, especially after relaunching the game. When satisfied that a good bookmark entry is found Y while highlighting the bookmark to add it to the code list. Original functinality of Edizon on game save is available when launched without a game running. From 053507c6344b429b1f976f875fddc3d6f202edaa Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:35:03 +0800 Subject: [PATCH 38/95] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index db914c0a..62f1d536 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ Here are the steps to do pointer search. 3. Select the bookmark with address you want to find the pointer chain that targets it. 4. Press Lstick down will start the search with default configuration. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. -6. Result is added to the bookmark. Test it and if a good pointer chain is found add it to the cheat code file. +6. Results are appended to the bookmark list. Test them to see the validity of the chain when the game state change, especially after relaunching the game. When satisfied that a good bookmark entry is found press Y while highlighting the bookmark to add it to the cheat code file. 7. Pointer search can be paused by holddown ZL+B. Normal functionality of the app is all available while pointer search is pause. 8. Start pointer search again to resume (step 4 or 5). Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". -9. Results are appended to the bookmark list. Test them to see the validity of the chain when the game state change, especially after relaunching the game. When satisfied that a good bookmark entry is found Y while highlighting the bookmark to add it to the code list. + Original functinality of Edizon on game save is available when launched without a game running. From 7fbedeba18df1c984e4e2a545c1adc78ef085f63 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:41:45 +0800 Subject: [PATCH 39/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62f1d536..d62e6aae 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Here are the steps to do pointer search. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. 6. Results are appended to the bookmark list. Test them to see the validity of the chain when the game state change, especially after relaunching the game. When satisfied that a good bookmark entry is found press Y while highlighting the bookmark to add it to the cheat code file. 7. Pointer search can be paused by holddown ZL+B. Normal functionality of the app is all available while pointer search is pause. -8. Start pointer search again to resume (step 4 or 5). Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". +8. Start pointer search again to resume (step 4 or 5), in resume case the currently search parameters are used for future iteration of the loop intermediate target lists are preserved. Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". Original functinality of Edizon on game save is available when launched without a game running. From 192963a2b8cc95c2e7ae4b19cdd9443447758017 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:45:14 +0800 Subject: [PATCH 40/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d62e6aae..7102f1dc 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Here are the steps to do pointer search. 5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. 6. Results are appended to the bookmark list. Test them to see the validity of the chain when the game state change, especially after relaunching the game. When satisfied that a good bookmark entry is found press Y while highlighting the bookmark to add it to the cheat code file. 7. Pointer search can be paused by holddown ZL+B. Normal functionality of the app is all available while pointer search is pause. -8. Start pointer search again to resume (step 4 or 5), in resume case the currently search parameters are used for future iteration of the loop intermediate target lists are preserved. Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". +8. Start pointer search again to resume (step 4 or 5), in resume case the currently search parameters are used for future iteration of the loop, intermediate targets that are queued up for processing is preserved. Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". Original functinality of Edizon on game save is available when launched without a game running. From a0529e93f05fb93f9e00889567cdb09376108ecf Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:55:32 +0800 Subject: [PATCH 41/95] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7102f1dc..80abf6c5 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Work in progress : Faster pointer search, pause/resume of search, examination of PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. New key combo ZL+Y to get into pointer search setup. -Here are the steps to do pointer search. +Here are the steps to do pointer chain search. 1. Clear previous search result if any. 2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). The result of this search is used for subsequent pointer search. Very important to get it right to find the pointer chains. 3. Select the bookmark with address you want to find the pointer chain that targets it. @@ -19,6 +19,9 @@ Here are the steps to do pointer search. 7. Pointer search can be paused by holddown ZL+B. Normal functionality of the app is all available while pointer search is pause. 8. Start pointer search again to resume (step 4 or 5), in resume case the currently search parameters are used for future iteration of the loop, intermediate targets that are queued up for processing is preserved. Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". +Interpreting the pointer chain search status display. +F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of of intermediate targets at this depth) + Original functinality of Edizon on game save is available when launched without a game running. From 0cb2d02bcb546bbf9efb6e1276a9f7bba8b88fe7 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:56:08 +0800 Subject: [PATCH 42/95] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 80abf6c5..7ddb33b7 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Here are the steps to do pointer chain search. 8. Start pointer search again to resume (step 4 or 5), in resume case the currently search parameters are used for future iteration of the loop, intermediate targets that are queued up for processing is preserved. Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". Interpreting the pointer chain search status display. + F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of of intermediate targets at this depth) From 7db6970343f7cf865060b492a8e4b94d1a837d84 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:56:38 +0800 Subject: [PATCH 43/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ddb33b7..cc47aa87 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Here are the steps to do pointer chain search. Interpreting the pointer chain search status display. -F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of of intermediate targets at this depth) + F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of of intermediate targets at this depth) Original functinality of Edizon on game save is available when launched without a game running. From b4098b3d143da3fae34b1a8a48d0d467cdb62d3f Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:58:15 +0800 Subject: [PATCH 44/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cc47aa87..90cae6f6 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Here are the steps to do pointer chain search. Interpreting the pointer chain search status display. - F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of of intermediate targets at this depth) + F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of intermediate targets at this depth) Original functinality of Edizon on game save is available when launched without a game running. From 53168c91250e2f881e25b403cceb5d40917f1d40 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 29 Jul 2020 10:00:33 +0800 Subject: [PATCH 45/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90cae6f6..010b53a0 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Here are the steps to do pointer chain search. Interpreting the pointer chain search status display. - F=(pointer chain found) Z=(depth from target) (index to intermediate target being processed currently at this depth)/(total number of intermediate targets at this depth) + F=(pointer chain found) Z=(depth from target):(index to intermediate target being processed currently at this depth)/(total number of intermediate targets at this depth) Original functinality of Edizon on game save is available when launched without a game running. From a6028d17c598aa038be8ee2126167fd7b370b833 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 30 Jul 2020 23:54:02 +0800 Subject: [PATCH 46/95] Sort sources by distance and limite Max num of offsets, preserve search state not working yet --- Makefile | 2 +- include/guis/gui_cheats.hpp | 38 ++++++-- source/guis/gui_cheats.cpp | 179 +++++++++++++++++++++++++++++------- 3 files changed, 175 insertions(+), 44 deletions(-) diff --git a/Makefile b/Makefile index eaf0629d..758b3b9f 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 5 -VERSION_MICRO := 8 +VERSION_MICRO := 9 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index b552348d..19e4b06f 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -72,6 +72,20 @@ class GuiCheats : public Gui MemoryDump *m_AttributeDumpBookmark; MemoryDump *m_pointeroffsetDump; MemoryDump *m_dataDump; + struct PSsetup_t + { + u64 m_numoffset = 3; + u64 m_max_source = 200; + u64 m_max_depth = 2; + u64 m_max_range = 0x300; + u64 m_EditorBaseAddr = 0; + u64 m_mainBaseAddr; + u64 m_mainend; + bool m_pointersearch_canresume = false; + bool m_PS_resume = false; + bool m_PS_pause = false; + // PointerSearch_state *m_PointerSearch = nullptr; + }; u64 m_target = 0; u64 m_numoffset = 3; u64 m_max_source = 200; @@ -114,9 +128,9 @@ class GuiCheats : public Gui #define IS_FINAL 0x780F0000 #define MAX_NUM_SOURCE_POINTER 200 // bound check for debugging; -#define MAX_POINTER_DEPTH 6 // up to 4 seems OK with forward only search took 94s. 215s for big dump +#define MAX_POINTER_DEPTH 12 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 -#define MAX_POINTER_TARGET 3 +#define MAX_NUM_POINTER_OFFSET 30 struct PointerSearch_state { u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget @@ -140,12 +154,17 @@ class GuiCheats : public Gui // #define PS_num_sourcesP m_PointerSearch->num_sources[PS_depth-1] #define PS_sources m_PointerSearch->sources[PS_depth] #define PS_lastdepth m_PointerSearch->depth -#define REPLACEFILE(file1,file2) remove(file2);\ - while (access(file2, F_OK) == 0)\ - { printf("waiting for delete %s\n",file2); } \ - rename(file1,file2);\ - while (access(file2, F_OK) != 0)\ - { printf("waiting for rename %s\n",file1); } +#define REPLACEFILE(file1, file2) \ + remove(file2); \ + while (access(file2, F_OK) == 0) \ + { \ + printf("waiting for delete %s\n", file2); \ + } \ + rename(file1, file2); \ + while (access(file2, F_OK) != 0) \ + { \ + printf("waiting for rename %s\n", file1); \ + } bool m_forwardonly = false; bool m_forwarddump = false; // reduce from 138 to 26 @@ -182,6 +201,9 @@ class GuiCheats : public Gui bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); bool addcodetofile(u64 index); bool addstaticcodetofile(u64 index); + void PSsaveSTATE(); + void PSresumeSTATE(); + u64 m_heapSize = 0; u64 m_mainSize = 0; u64 m_heapEnd = 0; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 11b1aa83..fe89849e 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -801,48 +801,58 @@ void GuiCheats::drawSearchPointerMenu() // ss << _getValueDisplayString(m_searchValue[0], m_searchType); // else if (m_searchValueFormat == FORMAT_HEX) - Gui::drawText(font20, 310, 165, currTheme.textColor, "Max Depth"); + Gui::drawText(font20, 310, 160, currTheme.textColor, "Max Depth"); ss.str(""); ss << std::uppercase << std::dec << m_max_depth; Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); - Gui::drawTextAligned(font20, 620, 165, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font20, 620, 160, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 0) - Gui::drawRectangled(622 + strWidth, 165, 3, 35, currTheme.highlightColor); + Gui::drawRectangled(622 + strWidth, 160, 3, 35, currTheme.highlightColor); - Gui::drawText(font20, 310, 225, currTheme.textColor, "Max Range"); + Gui::drawText(font20, 310, 200, currTheme.textColor, "Max Range"); ss.str(""); ss << "0x" << std::uppercase << std::hex << m_max_range; Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); - Gui::drawTextAligned(font20, 620, 225, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font20, 620, 200, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 1) - Gui::drawRectangled(622 + strWidth, 225, 3, 35, currTheme.highlightColor); + Gui::drawRectangled(622 + strWidth, 200, 3, 35, currTheme.highlightColor); - Gui::drawText(font20, 310, 285, currTheme.textColor, "Max Source"); + Gui::drawText(font20, 310, 240, currTheme.textColor, "Max Source"); ss.str(""); ss << std::uppercase << std::dec << m_max_source; Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); - Gui::drawTextAligned(font20, 620, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font20, 620, 240, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 2) - Gui::drawRectangled(622 + strWidth, 285, 3, 35, currTheme.highlightColor); + Gui::drawRectangled(622 + strWidth, 240, 3, 35, currTheme.highlightColor); - Gui::drawText(font20, 310, 345, currTheme.textColor, "Target Address"); + Gui::drawText(font20, 310, 280, currTheme.textColor, "Target Address"); ss.str(""); ss << "0x" << std::uppercase << std::hex << m_EditorBaseAddr; + if (m_pointersearch_canresume) + ss << " Resumable"; Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); - Gui::drawTextAligned(font20, 620, 345, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font20, 620, 280, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 3) - Gui::drawRectangled(622 + strWidth, 345, 3, 35, currTheme.highlightColor); + Gui::drawRectangled(622 + strWidth, 280, 3, 35, currTheme.highlightColor); - Gui::drawText(font20, 310, 405, currTheme.textColor, "Dump Forward only"); + Gui::drawText(font20, 310, 320, currTheme.textColor, "Dump Forward only"); ss.str(""); if (m_forwarddump) ss << "YES"; else ss << "NO"; Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); - Gui::drawTextAligned(font20, 620, 405, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font20, 620, 320, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 4) - Gui::drawRectangled(622 + strWidth, 405, 3, 35, currTheme.highlightColor); + Gui::drawRectangled(622 + strWidth, 320, 3, 35, currTheme.highlightColor); + + Gui::drawText(font20, 310, 360, currTheme.textColor, "Max num of Offsets"); + ss.str(""); + ss << "0x" << std::uppercase << std::hex << m_numoffset; + Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); + Gui::drawTextAligned(font20, 620, 360, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 5) + Gui::drawRectangled(622 + strWidth, 360, 3, 35, currTheme.highlightColor); Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0EF Start Search \uE0E1 Abort \uE0E0 Edit", ALIGNED_RIGHT); @@ -1085,6 +1095,7 @@ void GuiCheats::onInput(u32 kdown) if (m_searchMenuLocation == SEARCH_NONE) { // Gui::g_nextGui = GUI_MAIN; + PSsaveSTATE(); Gui::g_requestExit = true; return; } @@ -1162,7 +1173,7 @@ void GuiCheats::onInput(u32 kdown) } if (kdown & KEY_DOWN) { - if (m_selectedEntry < 4) + if (m_selectedEntry < 5) m_selectedEntry++; } if (kdown & KEY_R) @@ -1182,6 +1193,10 @@ void GuiCheats::onInput(u32 kdown) else if (m_selectedEntry == 4) { m_forwarddump = !m_forwarddump; + } + else if (m_selectedEntry == 5 && m_numoffset < MAX_NUM_POINTER_OFFSET) + { + m_numoffset++; }; } if (kdown & KEY_L) @@ -1194,9 +1209,13 @@ void GuiCheats::onInput(u32 kdown) { m_max_range -= 0x100; } - else if (m_selectedEntry == 2 && m_max_source > 20) + else if (m_selectedEntry == 2 && m_max_source > 10) { m_max_source -= 10; + } + else if (m_selectedEntry == 5 && m_numoffset > 1) + { + m_numoffset--; }; } } @@ -1836,6 +1855,7 @@ void GuiCheats::onInput(u32 kdown) m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_searchMenuLocation = SEARCH_POINTER; + PSresumeSTATE(); // m_showpointermenu = true; } } @@ -4063,8 +4083,8 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp u8 *buffer = new u8[bufferSize]; u64 distance; u64 minimum = m_max_range; // a large number to start - // std::vector sources; // potential sources that points at target with a offset, we will search for the nearest address being pointed by pointer/pointers sourceinfo_t sourceinfo; + std::vector> sources = {{}}; // printf("PS_num_sources %d ", PS_num_sources); PS_num_sources = 0; while (offset < m_dataDump->size()) @@ -4081,31 +4101,61 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp if (targetaddress >= pointedaddress) { distance = targetaddress - pointedaddress; - if (distance < minimum) - { - sourceinfo.foffset = offset + i; - sourceinfo.offset = distance; - PS_sources[PS_num_sources] = sourceinfo; - PS_num_sources++; - // sources.push_back(sourceinfo); - // thefileoffset = offset + i; //for debug only - } - else if (distance == minimum) + if (distance <= minimum) { sourceinfo.foffset = offset + i; sourceinfo.offset = distance; - PS_sources[PS_num_sources] = sourceinfo; - PS_num_sources++; - // sources.push_back(sourceinfo); - // thefileoffset = offset + i; //for deubg only + // PS_sources[PS_num_sources] = sourceinfo; + // PS_num_sources++; + for (u32 j = 0; j < sources.size(); j++) + { + + if (sources[j].size() == 0 || sources[j][0].offset == distance) + { + sources[j].push_back(sourceinfo); + break; + } + else if (sources[j][0].offset > distance) + { + sources.insert(sources.begin() + j, {sourceinfo}); + break; + } + else if (j == sources.size() - 1) + { + sources.push_back({sourceinfo}); + } + } } + // else if (distance == minimum) + // { + // sourceinfo.foffset = offset + i; + // sourceinfo.offset = distance; + // PS_sources[PS_num_sources] = sourceinfo; + // PS_num_sources++; + // } } + // if (PS_num_sources > m_max_source) + // break; + } + // if (PS_num_sources > m_max_source) + // break; + offset += bufferSize; + } + + PS_num_sources = 0; + for (u32 j = 0; j < sources.size(); j++) + { + if (j > m_numoffset) + break; + for (u32 k = 0; k < sources[j].size(); k++) + { + PS_sources[PS_num_sources] = sources[j][k]; + PS_num_sources++; if (PS_num_sources > m_max_source) break; } if (PS_num_sources > m_max_source) break; - offset += bufferSize; } delete[] buffer; // release memory use for the search of sources @@ -4135,13 +4185,17 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp SS.str(""); SS << "F=" << std::setw(2) << m_pointer_found; for (u64 i = 0; i < m_max_depth; i++) + { SS << " Z=" << i << ":" << std::setfill('0') << std::setw(2) << m_PointerSearch->index[i] << "/" << std::setfill('0') << std::setw(2) << m_PointerSearch->num_sources[i] << " "; + if (i == 5 || i == 11) + SS << "\n"; + } // SS << "\n"; // printf(SS.str().c_str()); Gui::beginDraw(); - Gui::drawRectangle(70, 465, 1150, 40, currTheme.backgroundColor); - Gui::drawText(font20, 70, 465, currTheme.textColor, SS.str().c_str()); + Gui::drawRectangle(70, 420, 1150, 65, currTheme.backgroundColor); + Gui::drawTextAligned(font20, 70, 420, currTheme.textColor, SS.str().c_str(), ALIGNED_LEFT); Gui::endDraw(); u64 newtargetaddress; @@ -4539,6 +4593,61 @@ bool GuiCheats::addcodetofile(u64 index) return true; } +void GuiCheats::PSsaveSTATE() +{ + PSsetup_t save; + save.m_numoffset = m_numoffset; + save.m_max_source = m_max_source; + save.m_max_depth = m_max_depth; + save.m_max_range = m_max_range; + save.m_EditorBaseAddr = m_EditorBaseAddr; + save.m_mainBaseAddr = m_mainBaseAddr; + save.m_mainend = m_mainend; + save.m_pointersearch_canresume = m_pointersearch_canresume; + save.m_PS_resume = m_PS_resume; + save.m_PS_pause = m_PS_pause; + MemoryDump *PSdump; + PSdump = new MemoryDump(EDIZON_DIR "/PSstatedump.dat", DumpType::UNDEFINED, true); + PSdump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + PSdump->addData((u8 *)&save, sizeof(PSsetup_t)); + if (m_PointerSearch != nullptr) + PSdump->addData((u8 *)m_PointerSearch, sizeof(PointerSearch_state)); + PSdump->flushBuffer(); + delete PSdump; + printf("done saving PSstate\n"); + // PointerSearch_state *m_PointerSearch = nullptr; + //if (PSdump->size() > 0) +} + +void GuiCheats::PSresumeSTATE() +{ + PSsetup_t save; + MemoryDump *PSdump; + PSdump = new MemoryDump(EDIZON_DIR "/PSstatedump.dat", DumpType::UNDEFINED, false); + if (PSdump->size() > 0 && PSdump->getDumpInfo().heapBaseAddress == m_heapBaseAddr) + { + PSdump->getData(0, &save, sizeof(PSsetup_t)); + if (PSdump->size() == sizeof(PSsetup_t) + sizeof(PointerSearch_state)) + { + if (m_PointerSearch = nullptr) + m_PointerSearch = new PointerSearch_state; + PSdump->getData(sizeof(PSsetup_t), m_PointerSearch, sizeof(PointerSearch_state)); + } + delete PSdump; + m_numoffset = save.m_numoffset; + m_max_source = save.m_max_source; + m_max_depth = save.m_max_depth; + m_max_range = save.m_max_range; + m_mainBaseAddr = save.m_mainBaseAddr; + m_mainend = save.m_mainend; + m_pointersearch_canresume = save.m_pointersearch_canresume; + m_PS_resume = save.m_PS_resume; + m_PS_pause = save.m_PS_pause; + if (m_pointersearch_canresume) + m_EditorBaseAddr = save.m_EditorBaseAddr; + } +} + bool GuiCheats::addstaticcodetofile(u64 index) { std::stringstream buildIDStr; From 1b31c554da3a5a77185c27883aad4d7f1ace79cf Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 31 Jul 2020 19:46:04 +0800 Subject: [PATCH 47/95] PC dump done --- Makefile | 4 +- include/guis/gui_cheats.hpp | 7 ++ source/guis/gui_cheats.cpp | 160 +++++++++++++++++++++++++++++++++++- 3 files changed, 168 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 758b3b9f..be6ab357 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,8 @@ include $(DEVKITPRO)/libnx/switch_rules # - /default_icon.jpg #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 -VERSION_MINOR := 5 -VERSION_MICRO := 9 +VERSION_MINOR := 6 +VERSION_MICRO := 0 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 19e4b06f..afa2300d 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -188,6 +188,8 @@ class GuiCheats : public Gui bookmark_t bookmark; //used in add book mark pointer_chain_t m_hitcount; // maybe not used + std::stringstream m_PCDump_filename; + void PCdump(); void rebasepointer(searchValue_t value); //struct bookmark_t bookmark); // bool check_chain(bookmark_t *bookmark, u64 *address); // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); @@ -222,6 +224,11 @@ class GuiCheats : public Gui searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos); + void searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t searchValue1, + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); + void searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, MemoryDump **displayDump); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index fe89849e..42f6ca27 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -227,6 +227,7 @@ GuiCheats::GuiCheats() : Gui() buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; // buildIDStr.str("attdumpbookmark"); filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".dat"; + m_PCDump_filename << EDIZON_DIR "/" << buildIDStr.str() << ".dmp1"; } m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); @@ -1140,6 +1141,15 @@ void GuiCheats::onInput(u32 kdown) // BM2 if (m_searchMenuLocation == SEARCH_POINTER) { + if (kdown & KEY_Y) + { + printf("starting PC dump\n"); + m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; + m_searchRegion = SEARCH_REGION_HEAP_AND_MAIN; + GuiCheats::searchMemoryAddressesPrimary2(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + // PCdump(); + } + if ((kdown & KEY_PLUS) && !(kheld & KEY_ZL)) { m_abort = false; @@ -4629,7 +4639,7 @@ void GuiCheats::PSresumeSTATE() PSdump->getData(0, &save, sizeof(PSsetup_t)); if (PSdump->size() == sizeof(PSsetup_t) + sizeof(PointerSearch_state)) { - if (m_PointerSearch = nullptr) + if (m_PointerSearch == nullptr) m_PointerSearch = new PointerSearch_state; PSdump->getData(sizeof(PSsetup_t), m_PointerSearch, sizeof(PointerSearch_state)); } @@ -4708,3 +4718,151 @@ bool GuiCheats::addstaticcodetofile(u64 index) return true; } +void GuiCheats::PCdump() +{ + bool ledOn = true; + u8 j = 1; + while (access(m_PCDump_filename.str().c_str(), F_OK) == 0) + { + m_PCDump_filename.seekp(-1, std::ios_base::end); + m_PCDump_filename << (0 + j++); + printf("%s\n", m_PCDump_filename.str().c_str()); + } + MemoryDump *PCDump; + PCDump = new MemoryDump(m_PCDump_filename.str().c_str(), DumpType::DATA, true); + PCDump->addData((u8 *)&m_EditorBaseAddr, sizeof(u64)); // first entry is the target address + PCDump->addData((u8 *)&m_mainBaseAddr, sizeof(u64)); + PCDump->addData((u8 *)&m_mainend, sizeof(u64)); + for (MemoryInfo meminfo : m_memoryInfo) + { + if (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable) + continue; + setLedState(ledOn); + ledOn = !ledOn; + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // consider to increase from 10k to 1M (not a big problem) + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + m_debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += sizeof(u64)) + { + u64 address = meminfo.addr + offset + i; + memset(&realValue, 0, 8); + memcpy(&realValue, buffer + i, sizeof(u64)); + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + { + PCDump->addData((u8 *)&address, sizeof(u64)); + PCDump->addData((u8 *)&realValue, sizeof(u64)); + } + } + } + offset += bufferSize; + } + PCDump->flushBuffer(); + delete PCDump; + setLedState(false); +} + +void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) +{ + u8 j = 1; + while (access(m_PCDump_filename.str().c_str(), F_OK) == 0) + { + m_PCDump_filename.seekp(-1, std::ios_base::end); + m_PCDump_filename << (0 + j++); + printf("%s\n", m_PCDump_filename.str().c_str()); + } + MemoryDump *PCDump; + PCDump = new MemoryDump(m_PCDump_filename.str().c_str(), DumpType::DATA, true); + PCDump->addData((u8 *)&m_EditorBaseAddr, sizeof(u64)); // first entry is the target address + PCDump->addData((u8 *)&m_mainBaseAddr, sizeof(u64)); + PCDump->addData((u8 *)&m_mainend, sizeof(u64)); + + bool ledOn = false; + + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time primary search", unixTime1); + // printf("main %lx main end %lx heap %lx heap end %lx \n",m_mainBaseAddr, m_mainBaseAddr+m_mainSize, m_heapBaseAddr, m_heapBaseAddr+m_heapSize); + for (MemoryInfo meminfo : memInfos) + { + + // printf("%s%p", "meminfo.addr, ", meminfo.addr); + // printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); + // printf("%s%p", ", meminfo.size, ", meminfo.size); + // printf("%s%lx", ", meminfo.type, ", meminfo.type); + // printf("%s%lx", ", meminfo.attr, ", meminfo.attr); + // printf("%s%lx", ", meminfo.perm, ", meminfo.perm); + // printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); + // printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); + + if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) + continue; + else if (searchRegion == SEARCH_REGION_MAIN && + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && + (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + continue; + else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + continue; + + setLedState(ledOn); + ledOn = !ledOn; + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // consider to increase from 10k to 1M (not a big problem) + u8 *buffer = new u8[bufferSize]; + while (offset < meminfo.size) + { + + if (meminfo.size - offset < bufferSize) + bufferSize = meminfo.size - offset; + + debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); + + searchValue_t realValue = {0}; + for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + { + u64 address = meminfo.addr + offset + i; + memset(&realValue, 0, 8); + memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + { + if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) + break; + // (*displayDump)->addData((u8 *)&address, sizeof(u64)); + // newdataDump->addData((u8 *)&realValue, sizeof(u64)); + // helperinfo.count++; + PCDump->addData((u8 *)&address, sizeof(u64)); + PCDump->addData((u8 *)&realValue, sizeof(u64)); + // printf("%lx,%lx\n",address,realValue); + // std::stringstream ss; // replace the printf + // ss.str(""); + // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; + // char st[27]; + // snprintf(st, 27, "%s\n", ss.str().c_str()); // + // newstringDump->addData((u8 *)&st, sizeof(st)); // + } + } + + offset += bufferSize; + } + + delete[] buffer; + } + + setLedState(false); + + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + PCDump->flushBuffer(); + delete PCDump; +} +// \ No newline at end of file From 54cc9d96aee336dda121e88b2915d8f23ee0b4f7 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 3 Aug 2020 12:55:09 +0800 Subject: [PATCH 48/95] export to pointersearcher SE --- include/guis/gui_cheats.hpp | 5 +++++ source/guis/gui_cheats.cpp | 44 ++++++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index afa2300d..2f42b4ba 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -190,6 +190,11 @@ class GuiCheats : public Gui std::stringstream m_PCDump_filename; void PCdump(); + enum MemoryType + { + MAIN, + HEAP + }; void rebasepointer(searchValue_t value); //struct bookmark_t bookmark); // bool check_chain(bookmark_t *bookmark, u64 *address); // void startpointersearch(u64 address, u64 depth, u64 range, u64 num, MemoryDump **displayDump); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 42f6ca27..fcee49ad 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -2697,7 +2697,8 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s } break; case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize - if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + // if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) { if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) break; @@ -4776,11 +4777,22 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t m_PCDump_filename << (0 + j++); printf("%s\n", m_PCDump_filename.str().c_str()); } + if (j == 1) + j++; + std::stringstream m_PCAttr_filename; + m_PCAttr_filename << m_PCDump_filename.str().c_str(); + m_PCAttr_filename.seekp(-4, std::ios_base::end); + m_PCAttr_filename << "att" << (j - 1); + MemoryDump *PCDump; PCDump = new MemoryDump(m_PCDump_filename.str().c_str(), DumpType::DATA, true); - PCDump->addData((u8 *)&m_EditorBaseAddr, sizeof(u64)); // first entry is the target address + MemoryDump *PCAttr; + PCAttr = new MemoryDump(m_PCAttr_filename.str().c_str(), DumpType::DATA, true); PCDump->addData((u8 *)&m_mainBaseAddr, sizeof(u64)); PCDump->addData((u8 *)&m_mainend, sizeof(u64)); + PCDump->addData((u8 *)&m_heapBaseAddr, sizeof(u64)); + PCDump->addData((u8 *)&m_heapEnd, sizeof(u64)); + PCDump->addData((u8 *)&m_EditorBaseAddr, sizeof(u64)); // first entry is the target address bool ledOn = false; @@ -4812,7 +4824,9 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t setLedState(ledOn); ledOn = !ledOn; - + printf("meminfo.addr,%lx,meminfo.size,%lx,meminfo.type,%d,", meminfo.addr, meminfo.size, meminfo.type); + PCAttr->addData((u8 *)&meminfo, sizeof(MemoryInfo)); + u64 counting_pointers = 0; u64 offset = 0; u64 bufferSize = MAX_BUFFER_SIZE; // consider to increase from 10k to 1M (not a big problem) u8 *buffer = new u8[bufferSize]; @@ -4831,15 +4845,32 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t memset(&realValue, 0, 8); memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); - if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + // if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) { if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) break; // (*displayDump)->addData((u8 *)&address, sizeof(u64)); // newdataDump->addData((u8 *)&realValue, sizeof(u64)); // helperinfo.count++; + + // realValue._u64 = realValue._u64 - m_heapBaseAddr; + // MemoryType fromtype; + // if (meminfo.type == MemType_Heap) + // { + // address = address - m_heapBaseAddr; + // fromtype = HEAP; + // } + // else + // { + // address = address - m_mainBaseAddr; + // fromtype = MAIN; + // } + // PCDump->addData((u8 *)&fromtype, sizeof(fromtype)); + PCDump->addData((u8 *)&address, sizeof(u64)); PCDump->addData((u8 *)&realValue, sizeof(u64)); + counting_pointers++; // printf("%lx,%lx\n",address,realValue); // std::stringstream ss; // replace the printf // ss.str(""); @@ -4853,7 +4884,8 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t offset += bufferSize; } - + printf("count,%lx\n", counting_pointers); + PCAttr->addData((u8 *)&counting_pointers, sizeof(counting_pointers)); delete[] buffer; } @@ -4864,5 +4896,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); PCDump->flushBuffer(); delete PCDump; + PCAttr->flushBuffer(); + delete PCAttr; } // \ No newline at end of file From ce4ce31ecc7001f21eb06172f8df20e32c6d0979 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 4 Aug 2020 23:49:03 +0800 Subject: [PATCH 49/95] Import Bookmark done --- Makefile | 2 +- include/guis/gui_cheats.hpp | 14 +-- source/guis/gui_cheats.cpp | 181 +++++++++++++++++++++++++++++++++++- 3 files changed, 185 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index be6ab357..ee51362e 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 0 +VERSION_MICRO := 1 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 2f42b4ba..f7552dc5 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -173,11 +173,11 @@ class GuiCheats : public Gui u64 depth = 0; u64 offset[MAX_POINTER_DEPTH + 1] = {0}; // offset to address pointed by pointer // below is for debugging can consider removing; - u64 fileoffset[MAX_POINTER_DEPTH + 1] = {0}; // offset to the file that has the address where the pointer was stored in this instance for debugging + // u64 fileoffset[MAX_POINTER_DEPTH + 1] = {0}; // offset to the file that has the address where the pointer was stored in this instance for debugging }; struct bookmark_t { - char label[18]; + char label[18] = {0}; searchType_t type; pointer_chain_t pointer; bool heap = true; @@ -210,7 +210,9 @@ class GuiCheats : public Gui bool addstaticcodetofile(u64 index); void PSsaveSTATE(); void PSresumeSTATE(); - + void updatebookmark(bool clearunresolved, bool importbookmark); + bool unresolved(pointer_chain_t pointer); + bool unresolved2(pointer_chain_t *pointer); u64 m_heapSize = 0; u64 m_mainSize = 0; u64 m_heapEnd = 0; @@ -230,9 +232,9 @@ class GuiCheats : public Gui MemoryDump **displayDump, std::vector memInfos); void searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t searchValue1, - searchValue_t searchValue2, searchType_t searchType, - searchMode_t searchMode, searchRegion_t searchRegion, - MemoryDump **displayDump, std::vector memInfos); + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, searchRegion_t searchRegion, + MemoryDump **displayDump, std::vector memInfos); void searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index fcee49ad..56c7086e 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -267,6 +267,11 @@ GuiCheats::GuiCheats() : Gui() m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); tempdump->addData((u8 *)&bookmark, sizeof(bookmark_t)); } + else + { + m_memoryDumpBookmark->addData((u8 *)&m_heapBaseAddr, sizeof(u64)); + tempdump->addData((u8 *)&bookmark, sizeof(bookmark_t)); + } } } tempdump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); @@ -1541,7 +1546,21 @@ void GuiCheats::onInput(u32 kdown) } } // add bookmark - if (kdown & KEY_PLUS && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + if ((kdown & KEY_PLUS) && (kheld & KEY_ZL)) + { + if (m_memoryDump1 != nullptr) + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + + updatebookmark(true, true); + + m_memoryDump1 = m_memoryDump; + m_memoryDump = m_memoryDumpBookmark; + } + } + + if (kdown & KEY_PLUS && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR && !(kheld & KEY_ZL)) { if (m_memoryDump1 != nullptr) { //Bookmark case @@ -1729,7 +1748,21 @@ void GuiCheats::onInput(u32 kdown) } } - if (kdown & KEY_MINUS) + if ((kdown & KEY_MINUS) && (kheld & KEY_ZL)) + { + if (m_memoryDump1 != nullptr) + { + m_memoryDump = m_memoryDump1; + m_memoryDump1 = nullptr; + + updatebookmark(true, false); + + m_memoryDump1 = m_memoryDump; + m_memoryDump = m_memoryDumpBookmark; + } + } + + if ((kdown & KEY_MINUS) && !(kheld & KEY_ZL)) { //make sure not using bookmark m_searchType if (m_memoryDump1 != nullptr) @@ -4771,17 +4804,22 @@ void GuiCheats::PCdump() void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) { u8 j = 1; + int k = -1; while (access(m_PCDump_filename.str().c_str(), F_OK) == 0) { - m_PCDump_filename.seekp(-1, std::ios_base::end); + m_PCDump_filename.seekp(k, std::ios_base::end); m_PCDump_filename << (0 + j++); printf("%s\n", m_PCDump_filename.str().c_str()); + if (j > 10) + k = -2; + if (j > 100) + k = -3; } if (j == 1) j++; std::stringstream m_PCAttr_filename; m_PCAttr_filename << m_PCDump_filename.str().c_str(); - m_PCAttr_filename.seekp(-4, std::ios_base::end); + m_PCAttr_filename.seekp(k - 3, std::ios_base::end); m_PCAttr_filename << "att" << (j - 1); MemoryDump *PCDump; @@ -4899,4 +4937,137 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t PCAttr->flushBuffer(); delete PCAttr; } -// \ No newline at end of file +// +void GuiCheats::updatebookmark(bool clearunresolved, bool importbookmark) +{ + std::stringstream filebuildIDStr; + std::stringstream buildIDStr; + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".dat"; + + MemoryDump *tempdump; + tempdump = new MemoryDump(EDIZON_DIR "/tempbookmark.dat", DumpType::ADDR, true); + m_memoryDumpBookmark->clear(); + delete m_memoryDumpBookmark; + m_memoryDumpBookmark = new MemoryDump(EDIZON_DIR "/memdumpbookmark.dat", DumpType::ADDR, true); + if (m_AttributeDumpBookmark->size() > 0) + { + bookmark_t bookmark; + u64 address; + for (u64 i = 0; i < m_AttributeDumpBookmark->size(); i += sizeof(bookmark_t)) + { + m_AttributeDumpBookmark->getData(i, (u8 *)&bookmark, sizeof(bookmark_t)); + if (bookmark.deleted) + continue; // don't add deleted bookmark + if (clearunresolved) + { + if (unresolved(bookmark.pointer)) + continue; + } + if (bookmark.heap) + { + address = bookmark.offset + m_heapBaseAddr; + } + else + { + address = bookmark.offset + m_mainBaseAddr; + } + MemoryInfo meminfo; + meminfo = m_debugger->queryMemory(address); + if (meminfo.perm != Perm_Rw) + continue; + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + tempdump->addData((u8 *)&bookmark, sizeof(bookmark_t)); + } + if (importbookmark) + { + bookmark_t bookmark; + bookmark.type = m_searchType; + if (Gui::requestKeyboardInput("Import Bookmark", "Enter Label for bookmark to be imported from file.", bookmark.label, SwkbdType_QWERTY, bookmark.label, 18)) + { + std::stringstream filebuildIDStr; + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".bmk"; + MemoryDump *bmkdump; + bmkdump = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); + if (bmkdump->size() > 0) + { + printf(" file exist %s \n", filebuildIDStr.str().c_str()); + u64 bufferSize = bmkdump->size(); + printf(" file size is %ld with %ld pointer chains\n", bufferSize, bufferSize / sizeof(pointer_chain_t)); + u8 *buffer = new u8[bufferSize]; + bmkdump->getData(0, buffer, bufferSize); + u32 goodcount = 0; + for (u64 i = 0; i < bufferSize; i += sizeof(pointer_chain_t)) + { + memcpy(&(bookmark.pointer), buffer + i, sizeof(pointer_chain_t)); + if (unresolved(bookmark.pointer)) + continue; + goodcount++; + m_memoryDumpBookmark->addData((u8 *)&m_heapBaseAddr, sizeof(u64)); + tempdump->addData((u8 *)&bookmark, sizeof(bookmark_t)); + } + printf("found %d good ones\n", goodcount); + } + else + { + printf("bookmark file %s missing \n", filebuildIDStr.str().c_str()); + (new Snackbar("Bookmark file to import from is missing"))->show(); + } + }; + } + tempdump->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + tempdump->flushBuffer(); + delete tempdump; + m_AttributeDumpBookmark->clear(); + delete m_AttributeDumpBookmark; + REPLACEFILE(EDIZON_DIR "/tempbookmark.dat", filebuildIDStr.str().c_str()); + m_AttributeDumpBookmark = new MemoryDump(filebuildIDStr.str().c_str(), DumpType::ADDR, false); + m_memoryDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + m_AttributeDumpBookmark->setBaseAddresses(m_addressSpaceBaseAddr, m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize); + } +}; +bool GuiCheats::unresolved2(pointer_chain_t *pointer) +{ + printf("source= %lx", pointer->depth); + for (int z = pointer->depth; z >= 0; z--) + printf("+ %lx ", pointer->offset[z]); + printf("\n"); + return true; +} + +bool GuiCheats::unresolved(pointer_chain_t pointer) +{ + printf("z=%lx ", pointer.depth); + if (pointer.depth != 0) + { + printf("[main"); + u64 nextaddress = m_mainBaseAddr; + for (int z = pointer.depth; z >= 0; z--) + { + printf("+%lx]", pointer.offset[z]); + nextaddress += pointer.offset[z]; + MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); + if (meminfo.perm == Perm_Rw) + if (z == 0) + { + printf("(%lx)\n", nextaddress); // nextaddress = the target + return false; + } + else + { + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + printf("[(%lx)", nextaddress); + } + else + { + printf(" * access denied *\n"); + return true; + } + } + printf("\n"); + return false; + } + else + return false; +} \ No newline at end of file From 2da3e337da248e3ddbc94e63f1c44cd17c2cbc8f Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 5 Aug 2020 09:31:42 +0800 Subject: [PATCH 50/95] Update README.md --- README.md | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 010b53a0..91e9aa0e 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,22 @@ # EdiZon SE -This fork is based on the solid foundation of EdiZon. The changes made are on the game memory hack aspect. +This fork is based on the foundation of EdiZon 3.1 nightly. The changes made are on the game memory hack aspect. + +Here are the added features: +1. Range search. +2. Compare with previous value search. +3. Bookmark memory location found. +4. Speed enhancement to make small integer value in first search practicle. +5. Bookmark adjust to changing main and heap start address on subsequent launch of the game. Bookmark with pointer chain attached updates memory address dynamically when the chain is able to resolve into a valid memory address. +6. Extract memory address from dmnt cheat code and add it to bookmark for exploration of the memory location. +7. Rebase feature to extract potential pointer chain form dmnt cheat code made for previous version of the game. +8. In app pointer chain search for address on bookmark. +9. Export dump to PC app (forked from pointersearcher 0.4) for more powerful pointer chain search. +10. Import PC app search result for validation and testing. +11. Create dmnt cheat code from pointer chain found. + +PS: In app help on button combo currently don't show enough hints. Please refer to wiki for instructions on how to use the app. -I have added bookmark functionality, completed the range search feature and enhanced the speed to enable search for small value which generates lots of hits. -Bookmark automatically adjust relative to main and heap so static location relative to main and heap will continue to work for different game run. You can also extract the memory location pointed by cheat code to bookmark to explore/edit the ram around there. Able to rebase first offset of cheat code for game version change that only affects the first offset. Pointer search result is added back into bookmark. Bookmark with pointer chain attached will dynamically adjust the address on the bookmark list. - -Work in progress : Faster pointer search, pause/resume of search, examination of intermidiate result, change search parameters mid search. - -PS: In app help on button currently don't show hint what right stick down and left stick down do. Right stick down relates to memory edit and Left stick down relates to pointer search. Just try it to figure it out. New key combo ZL+Y to get into pointer search setup. - -Here are the steps to do pointer chain search. -1. Clear previous search result if any. -2. Perform a search of type pointer when the game is in the state you want. (Press Lstick down will quickly setup the search). The result of this search is used for subsequent pointer search. Very important to get it right to find the pointer chains. -3. Select the bookmark with address you want to find the pointer chain that targets it. -4. Press Lstick down will start the search with default configuration. -5. Or press LZ+Y to go setting page for the search parameters. Move the cursor to the position you want to modify and press L or R to increment or decrement the value. Some value cannot be modified at the moment. Press + to start the search. -6. Results are appended to the bookmark list. Test them to see the validity of the chain when the game state change, especially after relaunching the game. When satisfied that a good bookmark entry is found press Y while highlighting the bookmark to add it to the cheat code file. -7. Pointer search can be paused by holddown ZL+B. Normal functionality of the app is all available while pointer search is pause. -8. Start pointer search again to resume (step 4 or 5), in resume case the currently search parameters are used for future iteration of the loop, intermediate targets that are queued up for processing is preserved. Very important to ensure memory search results is valid before continuing the pointer chain search, repeat step 2 if necessary. To abort the search and start from scratch press ZL+"+". - -Interpreting the pointer chain search status display. - - F=(pointer chain found) Z=(depth from target):(index to intermediate target being processed currently at this depth)/(total number of intermediate targets at this depth) Original functinality of Edizon on game save is available when launched without a game running. From cc445f10cfc0f9c2e1d66bf944fea730bc583741 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 5 Aug 2020 11:12:12 +0800 Subject: [PATCH 51/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91e9aa0e..30a933d8 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Here are the added features: 10. Import PC app search result for validation and testing. 11. Create dmnt cheat code from pointer chain found. -PS: In app help on button combo currently don't show enough hints. Please refer to wiki for instructions on how to use the app. +PS: In app help on button combo currently don't show enough hints. Please refer to https://github.com/tomvita/EdiZon-SE/wiki for instructions on how to use the app. From ca0f7c85a708d8718c4d33cee26099d36b660292 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 6 Aug 2020 13:52:29 +0800 Subject: [PATCH 52/95] ACNH use #define HAVESAVE false --- Makefile | 2 +- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index ee51362e..df6703c9 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 1 +VERSION_MICRO := 1a NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index f7552dc5..c880f7b2 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -131,6 +131,7 @@ class GuiCheats : public Gui #define MAX_POINTER_DEPTH 12 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 #define MAX_NUM_POINTER_OFFSET 30 +#define HAVESAVE false struct PointerSearch_state { u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 56c7086e..427f58b8 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -355,7 +355,7 @@ GuiCheats::GuiCheats() : Gui() // check this printf("%s\n", "before part"); - if (m_debugger->getRunningApplicationTID() != 0) + if ((m_debugger->getRunningApplicationTID() != 0) && HAVESAVE) { if (Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName().length() < 24) ss << Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleName(); @@ -502,7 +502,7 @@ void GuiCheats::draw() Gui::drawRectangle(256, 50, Gui::g_framebuffer_width - 256, 206, currTheme.separatorColor); // Don't draw icon - if (m_debugger->getRunningApplicationTID() != 0) + if ((m_debugger->getRunningApplicationTID() != 0) && HAVESAVE) Gui::drawImage(0, 0, 256, 256, Title::g_titles[m_debugger->getRunningApplicationTID()]->getTitleIcon(), IMAGE_MODE_RGB24); else Gui::drawRectangle(0, 0, 256, 256, Gui::makeColor(0x00, 0x00, 0xFF, 0xFF)); @@ -4822,6 +4822,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t m_PCAttr_filename.seekp(k - 3, std::ios_base::end); m_PCAttr_filename << "att" << (j - 1); + //MemoryDump *newstringDump = new MemoryDump(EDIZON_DIR "/stringdump.csv", DumpType::DATA, true); MemoryDump *PCDump; PCDump = new MemoryDump(m_PCDump_filename.str().c_str(), DumpType::DATA, true); MemoryDump *PCAttr; @@ -4909,7 +4910,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t PCDump->addData((u8 *)&address, sizeof(u64)); PCDump->addData((u8 *)&realValue, sizeof(u64)); counting_pointers++; - // printf("%lx,%lx\n",address,realValue); + // printf("0x%lx,0x%lx\n",address,realValue); // std::stringstream ss; // replace the printf // ss.str(""); // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; @@ -4936,6 +4937,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t delete PCDump; PCAttr->flushBuffer(); delete PCAttr; + delete newstringDump; } // void GuiCheats::updatebookmark(bool clearunresolved, bool importbookmark) From 974ae376d6720c6b52f5e5323cb4144d49ad36e6 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 6 Aug 2020 20:14:40 +0800 Subject: [PATCH 53/95] Minor UI bug fix --- Makefile | 2 +- include/guis/gui_cheats.hpp | 2 +- source/guis/gui_cheats.cpp | 11 ++++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index df6703c9..77a7dde2 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 1a +VERSION_MICRO := 2 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index c880f7b2..1a2a93dd 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -131,7 +131,7 @@ class GuiCheats : public Gui #define MAX_POINTER_DEPTH 12 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 #define MAX_NUM_POINTER_OFFSET 30 -#define HAVESAVE false +#define HAVESAVE true struct PointerSearch_state { u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 427f58b8..b9e8fb5f 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -467,7 +467,12 @@ void GuiCheats::draw() } if (m_menuLocation == CHEATS) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + { + if (m_memoryDump1 == nullptr) + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + else + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + } else if (m_memoryDump1 == nullptr) { if (m_memoryDump->size() == 0) @@ -1283,7 +1288,7 @@ void GuiCheats::onInput(u32 kdown) m_searchValue[1]._u64 = 0x8000000000; } - if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS && (m_cheatCnt > 0)) + if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS && (m_cheatCnt > 0) && (m_memoryDump1 != nullptr)) { // printf("start adding cheat to bookmark\n"); // m_cheatCnt @@ -4937,7 +4942,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t delete PCDump; PCAttr->flushBuffer(); delete PCAttr; - delete newstringDump; + // delete newstringDump; } // void GuiCheats::updatebookmark(bool clearunresolved, bool importbookmark) From 0b763c371729def8562833c8140c6f6d8ececef7 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 7 Aug 2020 15:50:28 +0800 Subject: [PATCH 54/95] Stability improvement on known value search --- Makefile | 2 +- include/guis/gui_cheats.hpp | 4 + source/guis/gui_cheats.cpp | 339 ++++++++++++++++++++++++++++++++++-- 3 files changed, 325 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 77a7dde2..413c32e5 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 2 +VERSION_MICRO := 3 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 1a2a93dd..79e7783d 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -241,6 +241,10 @@ class GuiCheats : public Gui searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, MemoryDump **displayDump); + void searchMemoryAddressesSecondary2(Debugger *debugger, searchValue_t searchValue1, + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, MemoryDump **displayDump); + void searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index b9e8fb5f..19a4c126 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -2328,25 +2328,39 @@ void GuiCheats::onInput(u32 kdown) } else if (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { - GuiCheats::searchMemoryValuesTertiary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); - delete m_memoryDump; - // remove(EDIZON_DIR "/memdump1.dat"); - // remove(EDIZON_DIR "/memdump1a.dat"); - // rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); - // rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); - REPLACEFILE(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); - REPLACEFILE(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); - m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); - // remove(EDIZON_DIR "/datadump2.dat"); - // rename(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); - REPLACEFILE(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); - // // rename B to A - // remove(EDIZON_DIR "/datadumpA.dat"); - // rename(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat"); - REPLACEFILE(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat") - // remove(EDIZON_DIR "/datadumpB.dat"); - // rename(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); - REPLACEFILE(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + if (m_searchMode == SEARCH_MODE_DIFFA || m_searchMode == SEARCH_MODE_SAMEA) + { + GuiCheats::searchMemoryValuesTertiary(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + delete m_memoryDump; + // remove(EDIZON_DIR "/memdump1.dat"); + // remove(EDIZON_DIR "/memdump1a.dat"); + // rename(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + // rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + REPLACEFILE(EDIZON_DIR "/memdump3.dat", EDIZON_DIR "/memdump1.dat"); + REPLACEFILE(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + m_memoryDump = new MemoryDump(EDIZON_DIR "/memdump1.dat", DumpType::ADDR, false); + // remove(EDIZON_DIR "/datadump2.dat"); + // rename(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); + REPLACEFILE(EDIZON_DIR "/datadump4.dat", EDIZON_DIR "/datadump2.dat"); + // // rename B to A + // remove(EDIZON_DIR "/datadumpA.dat"); + // rename(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat"); + REPLACEFILE(EDIZON_DIR "/datadumpAa.dat", EDIZON_DIR "/datadumpA.dat") + // remove(EDIZON_DIR "/datadumpB.dat"); + // rename(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + REPLACEFILE(EDIZON_DIR "/datadumpBa.dat", EDIZON_DIR "/datadumpB.dat"); + } + else + { + m_nothingchanged = false; + GuiCheats::searchMemoryAddressesSecondary2(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, &m_memoryDump); + if (m_nothingchanged == false) + { + // remove(EDIZON_DIR "/memdump1a.dat"); // remove old helper + // rename(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); // rename new helper to current helper + REPLACEFILE(EDIZON_DIR "/memdump3a.dat", EDIZON_DIR "/memdump1a.dat"); + } + } } } else @@ -3071,6 +3085,293 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); } +void GuiCheats::searchMemoryAddressesSecondary2(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, searchMode_t searchMode, MemoryDump **displayDump) +{ + MemoryDump *newDump = new MemoryDump(EDIZON_DIR "/memdump2.dat", DumpType::ADDR, true); + bool ledOn = false; + //begin + time_t unixTime1 = time(NULL); + printf("%s%lx\n", "Start Time Secondary search", unixTime1); + + u64 offset = 0; + u64 bufferSize = MAX_BUFFER_SIZE; // this is for file access going for 1M + u8 *buffer = new u8[bufferSize]; + u8 *predatabuffer = new u8[bufferSize]; + searchValue_t prevalue = {0}; + // helper init + MemoryDump *helperDump = new MemoryDump(EDIZON_DIR "/memdump1a.dat", DumpType::HELPER, false); // has address, size, count for fetching buffer from memory + MemoryDump *newhelperDump = new MemoryDump(EDIZON_DIR "/memdump3a.dat", DumpType::HELPER, true); // has address, size, count for fetching buffer from memory + REPLACEFILE(EDIZON_DIR "/datadump2.dat", EDIZON_DIR "/predatadump2.dat"); + MemoryDump *predataDump = new MemoryDump(EDIZON_DIR "/predatadump2.dat", DumpType::DATA, false); + MemoryDump *newdataDump = new MemoryDump(EDIZON_DIR "/datadump2.dat", DumpType::DATA, true); + // MemoryDump *debugdump1 = new MemoryDump(EDIZON_DIR "/debugdump1.dat", DumpType::HELPER, true); + if (helperDump->size() == 0) + { + (new Snackbar("Helper file not found !"))->show(); + return; + } + else + { + // helper integrity check + printf("start helper integrity check address secondary \n"); + u32 helpercount = 0; + helperinfo_t helperinfo; + for (u64 i = 0; i < helperDump->size(); i += sizeof(helperinfo)) + { + helperDump->getData(i, &helperinfo, sizeof(helperinfo)); + helpercount += helperinfo.count; + } + if (helpercount != (*displayDump)->size() / sizeof(u64)) + { + printf("Integrity problem with helper file helpercount = %d memdumpsize = %ld \n", helpercount, (*displayDump)->size() / sizeof(u64)); + (new Snackbar("Helper integrity check failed !"))->show(); + return; + } + printf("end helper integrity check address secondary \n"); + // end helper integrity check + + std::stringstream Message; + Message << "Traversing title memory.\n \nThis may take a while... secondary search\nTime " << (unixTime1 - time(NULL)) << " total " << (*displayDump)->size(); + (new MessageBox(Message.str(), MessageBox::NONE))->show(); + requestDraw(); + } + + u8 *ram_buffer = new u8[bufferSize]; + u64 helper_offset = 0; + helperinfo_t helperinfo; + helperinfo_t newhelperinfo; + newhelperinfo.count = 0; + + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); // helper_offset+=sizeof(helperinfo) + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + // helper init end + while (offset < (*displayDump)->size()) + { + if ((*displayDump)->size() - offset < bufferSize) + bufferSize = (*displayDump)->size() - offset; + (*displayDump)->getData(offset, buffer, bufferSize); // BM4 + predataDump->getData(offset, predatabuffer, bufferSize); + + for (u64 i = 0; i < bufferSize; i += sizeof(u64)) // for (size_t i = 0; i < (bufferSize / sizeof(u64)); i++) + { + if (helperinfo.count == 0) + { + if (newhelperinfo.count != 0) + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + // printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + // printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + // printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + helper_offset += sizeof(helperinfo); + helperDump->getData(helper_offset, &helperinfo, sizeof(helperinfo)); + debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); + } + searchValue_t value = {0}; + // searchValue_t testing = {0}; // temp + u64 address = 0; + + address = *reinterpret_cast(&buffer[i]); //(*displayDump)->getData(i * sizeof(u64), &address, sizeof(u64)); + prevalue._u64 = *reinterpret_cast(&predatabuffer[i]); + + memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); // extrat from buffer instead of making call + helperinfo.count--; // each fetch dec + // testing = value; // temp + // debugger->readMemory(&value, dataTypeSizes[searchType], address); + // if (testing._u64 != value._u64) + // { + // printf("%s%lx\n", "helperinfo.address ", helperinfo.address); + // printf("%s%lx\n", "helperinfo.size ", helperinfo.size); + // printf("%s%lx\n", "helperinfo.count ", helperinfo.count); + // printf("%s%lx\n", "address ", address); + // printf("%s%lx\n", "testing._u64 ", testing._u64); + // printf("%s%lx\n", "value ", value); + // printf("%s%lx\n", " address - helperinfo.address ", address - helperinfo.address); + // printf("%s%lx\n", " * (ram_buffer + address - helperinfo.address) ", *(ram_buffer + address - helperinfo.address)); + // printf("%s%lx\n", " * (&ram_buffer[ address - helperinfo.address]) ", *(&ram_buffer[address - helperinfo.address])); + // printf("%s%lx\n", " (ram_buffer + address - helperinfo.address) ", (ram_buffer + address - helperinfo.address)); + // printf("%s%lx\n", " (&ram_buffer[ address - helperinfo.address]) ", (&ram_buffer[address - helperinfo.address])); + // printf("%s%lx\n", " helperinfo.size - address + helperinfo.address ", helperinfo.size - address + helperinfo.address); + // // debugdump1->addData((u8 *)&ram_buffer, helperinfo.size); + // // debugger->readMemory(ram_buffer, 0x50, address); + // // debugdump2->addData((u8 *)&ram_buffer, 0x50); + // // + // // delete debugdump2; + // } + + if (i % 50000 == 0) + { + setLedState(ledOn); + ledOn = !ledOn; + } + + switch (searchMode) + { + case SEARCH_MODE_EQ: + if (value._s64 == searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_NEQ: + if (value._s64 != searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_GT: + if (value._s64 > searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFFA: //need to rewrite + if (value._s64 != prevalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_LT: + if (value._s64 < searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_SAMEA: // need to rewrite + if (value._s64 == prevalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_RANGE: + if (value._s64 >= searchValue1._s64 && value._s64 <= searchValue2._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); // add here + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize + if ((value._u64 >= m_mainBaseAddr && value._u64 <= (m_mainend)) || (value._u64 >= m_heapBaseAddr && value._u64 <= (m_heapEnd))) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_SAME: + if (value._s64 == prevalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DIFF: + if (value._s64 != prevalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_INC: + if (value._s64 > prevalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_DEC: + if (value._s64 < prevalue._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&value, sizeof(u64)); + newhelperinfo.count++; + } + break; + case SEARCH_MODE_NONE: + break; + } + } + printf("%ld of %ld done \n", offset, (*displayDump)->size()); // maybe consider message box this info + offset += bufferSize; + } + + if (newhelperinfo.count != 0) // take care of the last one + { + newhelperinfo.address = helperinfo.address; + newhelperinfo.size = helperinfo.size; + newhelperDump->addData((u8 *)&newhelperinfo, sizeof(newhelperinfo)); + // printf("%s%lx\n", "newhelperinfo.address ", newhelperinfo.address); + // printf("%s%lx\n", "newhelperinfo.size ", newhelperinfo.size); + // printf("%s%lx\n", "newhelperinfo.count ", newhelperinfo.count); + newhelperinfo.count = 0; + } + //end + newDump->flushBuffer(); + newhelperDump->flushBuffer(); + newdataDump->flushBuffer(); + + if (newDump->size() > 0) + { + // delete m_memoryDump; + // remove(EDIZON_DIR "/memdump1.dat"); + // rename(EDIZON_DIR "/memdump2.dat", EDIZON_DIR "/memdump2.dat"); + (*displayDump)->clear(); + (*displayDump)->setSearchParams(searchType, searchMode, (*displayDump)->getDumpInfo().searchRegion, searchValue1, searchValue2); + (*displayDump)->setDumpType(DumpType::ADDR); + + // begin copy + offset = 0; + bufferSize = MAX_BUFFER_SIZE; //0x1000000; // match what was created before + printf("%s%lx\n", "bufferSize ", bufferSize); // printf + while (offset < newDump->size()) + { + if (newDump->size() - offset < bufferSize) + bufferSize = newDump->size() - offset; + newDump->getData(offset, buffer, bufferSize); + (*displayDump)->addData(buffer, bufferSize); + offset += bufferSize; + } + // end copy + + (*displayDump)->flushBuffer(); + } + else + { + (new Snackbar("None of values changed to the entered one!"))->show(); + m_nothingchanged = true; + } + + setLedState(false); + delete newDump; + delete newhelperDump; + delete helperDump; + // delete debugdump1; + delete newdataDump; + delete[] buffer; + delete[] predatabuffer; + delete[] ram_buffer; + + remove(EDIZON_DIR "/memdump2.dat"); + time_t unixTime2 = time(NULL); + printf("%s%lx\n", "Stop Time secondary search ", unixTime2); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); +} + /////////////////////////////////////////////// // read void GuiCheats::searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos) From 7f97f39656cb612153dc75e0bdcccf757338cf88 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 10 Aug 2020 09:13:28 +0800 Subject: [PATCH 55/95] reloadcheats & dumpcodetofile --- include/guis/gui_cheats.hpp | 2 + source/guis/gui_cheats.cpp | 157 +++++++++++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 79e7783d..bdbd4894 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -208,6 +208,8 @@ class GuiCheats : public Gui bool valuematch(searchValue_t value, u64 nextaddress); bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); bool addcodetofile(u64 index); + bool dumpcodetofile(); + void reloadcheats(); bool addstaticcodetofile(u64 index); void PSsaveSTATE(); void PSresumeSTATE(); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 19a4c126..2953627a 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -93,6 +93,7 @@ GuiCheats::GuiCheats() : Gui() memcpy(m_buildID, metadata.main_nso_build_id, 0x20); _moveLonelyCheats(m_buildID, m_debugger->getRunningApplicationTID()); + dumpcodetofile(); dmntchtGetCheatCount(&m_cheatCnt); @@ -4760,6 +4761,7 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp static void _moveLonelyCheats(u8 *buildID, u64 titleID) { std::stringstream lonelyCheatPath; + // std::stringstream EdizonCheatPath; std::stringstream realCheatPath; std::stringstream buildIDStr; @@ -4768,6 +4770,7 @@ static void _moveLonelyCheats(u8 *buildID, u64 titleID) buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; lonelyCheatPath << EDIZON_DIR "/cheats/" << buildIDStr.str() << ".txt"; + // EdizonCheatPath << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; if (access(lonelyCheatPath.str().c_str(), F_OK) == 0) { @@ -4778,10 +4781,19 @@ static void _moveLonelyCheats(u8 *buildID, u64 titleID) realCheatPath << buildIDStr.str() << ".txt"; - // rename(lonelyCheatPath.str().c_str(), realCheatPath.str().c_str()); REPLACEFILE(lonelyCheatPath.str().c_str(), realCheatPath.str().c_str()); (new MessageBox("A new cheat has been added for this title. \n Please restart the game to start using it.", MessageBox::OKAY))->show(); } + // else + // { + // realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << titleID; + // realCheatPath << "/cheats/"; + // realCheatPath << buildIDStr.str() << ".txt"; + // } + // if (access(realCheatPath.str().c_str(), F_OK) == 0) + // { + // REPLACEFILE(realCheatPath.str().c_str(), EdizonCheatPath.str().c_str()); + // } } static bool _wrongCheatsPresent(u8 *buildID, u64 titleID) @@ -4943,6 +4955,149 @@ bool GuiCheats::addcodetofile(u64 index) return true; } +void GuiCheats::reloadcheats() +{ + if (m_cheats != nullptr) + delete m_cheats; + dmntchtGetCheatCount(&m_cheatCnt); + if (m_cheatCnt > 0) + { + m_cheats = new DmntCheatEntry[m_cheatCnt]; + dmntchtGetCheats(m_cheats, m_cheatCnt, 0, &m_cheatCnt); + } +} +bool GuiCheats::dumpcodetofile() +{ + std::stringstream buildIDStr; + std::stringstream filebuildIDStr; + { + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; + } + std::stringstream realCheatPath; + { + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << "/cheats/"; + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << buildIDStr.str() << ".txt"; + } + FILE *pfile; + pfile = fopen(filebuildIDStr.str().c_str(), "w"); + std::stringstream SS; + std::stringstream ss; + if (pfile != NULL) + { + GuiCheats::reloadcheats(); + SS.str(""); + for (u32 i = 0; i < m_cheatCnt; i++) + { + SS << "[" << m_cheats[i].definition.readable_name << "]\n"; + ss.str(""); + for (u32 j = 0; j < m_cheats[i].definition.num_opcodes; j++) + { + u16 opcode = (m_cheats[i].definition.opcodes[j] >> 28) & 0xF; + u8 T = (m_cheats[i].definition.opcodes[j] >> 24) & 0xF; + if ((opcode == 9) && (((m_cheats[i].definition.opcodes[j] >> 8) & 0xF) == 0)) + { + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j] << "\n"; + continue; + } + if (opcode == 0xC) + { + opcode = (m_cheats[i].definition.opcodes[j] >> 24) & 0xFF; + T = (m_cheats[i].definition.opcodes[j] >> 20) & 0xF; + u8 X = (m_cheats[i].definition.opcodes[j] >> 8) & 0xF; + if (opcode == 0xC0) + { + opcode = opcode * 16 + X; + } + } + switch (opcode) + { + case 0: + case 1: + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; + // 3+1 + case 9: + case 0xC04: + // 2+1 + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; + case 3: + // 1+1 + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; + if (T == 8 || (T == 1 && opcode == 3)) + { + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j] << " "; + } + break; + case 4: + case 6: + // 3 + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; + case 5: + case 7: + case 0xC00: + case 0xC02: + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; + // 2 + case 2: + case 8: + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC01: + case 0xC03: + case 0xC05: + default: + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j] << " "; + // 1 + break; + } + if (j >= (m_cheats[i].definition.num_opcodes)) // better to be ugly than to corrupt + { + printf("error encountered in addcodetofile \n "); + ss.str(""); + for (u32 k = 0; k < m_cheats[i].definition.num_opcodes; k++) + { + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[k++] << " "; + } + ss << "\n"; + break; + } + ss << "\n"; + } + SS << ss.str().c_str() << "\n"; + } + // DmntCheatDefinition cheat = m_cheats[m_selectedEntry].definition; + // memcpy(&bookmark.label, &cheat.readable_name, sizeof(bookmark.label)); + // << "\n"; + // ss << "580F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[bookmark.pointer.depth] << "\n"; + // for (int z = bookmark.pointer.depth - 1; z > 0; z--) + // { + // ss << "580F1000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[z] << "\n"; + // } + // ss << "780F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[0] << "\n"; + // ss << "6" << dataTypeSizes[bookmark.type] + 0 << "0F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(16) << realvalue._u64 << "\n"; + + fputs(SS.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on Edizon dir \n"); + + // pfile = fopen(realCheatPath.str().c_str(), "w"); + // if (pfile != NULL) + // { + // fputs(ss.str().c_str(), pfile); + // fclose(pfile); + // } + // else + // printf("failed writing to cheat file on contents dir \n"); + return true; +} + void GuiCheats::PSsaveSTATE() { PSsetup_t save; From f57ce4f8e0aa78264393ad626316b204dc9350e9 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 10 Aug 2020 19:49:30 +0800 Subject: [PATCH 56/95] reloadcheatsfromfile written, not tested, decided to continue with modding dmnt:cht --- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 160 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index bdbd4894..a7b1f6a5 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -210,6 +210,7 @@ class GuiCheats : public Gui bool addcodetofile(u64 index); bool dumpcodetofile(); void reloadcheats(); + bool reloadcheatsfromfile(u8 *buildID, u64 titleID); bool addstaticcodetofile(u64 index); void PSsaveSTATE(); void PSresumeSTATE(); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 2953627a..a5de19a8 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -93,6 +93,7 @@ GuiCheats::GuiCheats() : Gui() memcpy(m_buildID, metadata.main_nso_build_id, 0x20); _moveLonelyCheats(m_buildID, m_debugger->getRunningApplicationTID()); + // reloadcheatsfromfile(m_buildID, m_debugger->getRunningApplicationTID()); dumpcodetofile(); dmntchtGetCheatCount(&m_cheatCnt); @@ -4955,6 +4956,165 @@ bool GuiCheats::addcodetofile(u64 index) return true; } +bool GuiCheats::reloadcheatsfromfile(u8 *buildID, u64 titleID) +{ + std::stringstream realCheatPath; + std::stringstream buildIDStr; + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << titleID; + realCheatPath << "/cheats/"; + realCheatPath << buildIDStr.str() << ".txt"; + if (access(realCheatPath.str().c_str(), F_OK) == 0) + { + reloadcheats(); // reloaded from dmnt + if (m_cheatCnt > 0) // clear the cheats + { + for (u32 i = 0; i < m_cheatCnt; i++) + { + dmntchtRemoveCheat(m_cheats[i].cheat_id); + } + } + // read cheat file into buffer + FILE *pfile; + pfile = fopen(realCheatPath.str().c_str(), "r+b"); + fseek(pfile, 0, SEEK_END); + u64 bufferSize = ftell(pfile); + u8 *s = new u8[bufferSize + 1]; + /* Read cheats into buffer. */ + fseek(pfile, 0, SEEK_SET); + fread(s, sizeof(bufferSize), 1, pfile); + s[bufferSize] = '\x00'; + /* Parse cheat buffer. */ + // return this->ParseCheats(cht_txt, std::strlen(cht_txt)); + //bool CheatProcessManager::ParseCheats(const char *s, size_t len) + { + DmntCheatEntry cheat; + /* Parse the input string. */ + size_t i = 0; + cheat.definition.num_opcodes = 0; + // CheatEntry *cur_entry = nullptr; + while (i < bufferSize) + { + if (std::isspace(static_cast(s[i]))) + { + /* Just ignore whitespace. */ + i++; + } + else if (s[i] == '[') + { + if (cheat.definition.num_opcodes > 0) + { + if (dmntchtAddCheat(&(cheat.definition), false, &(cheat.cheat_id))) + { + cheat.definition.num_opcodes = 0; + } + else + { + printf("error adding cheat code\n"); + return false; + } + } + /* Parse a readable cheat name. */ + // cur_entry = this->GetFreeCheatEntry(); + // if (cur_entry == nullptr) + // { + // return false; + // } + /* Extract name bounds. */ + size_t j = i + 1; + while (s[j] != ']') + { + j++; + if (j >= bufferSize) + { + return false; + } + } + /* s[i+1:j] is cheat name. */ + const size_t cheat_name_len = std::min(j - i - 1, sizeof(cheat.definition.readable_name)); + std::memcpy(cheat.definition.readable_name, &s[i + 1], cheat_name_len); + cheat.definition.readable_name[cheat_name_len] = 0; + /* Skip onwards. */ + i = j + 1; + } + else if (s[i] == '{') + { + /* We're parsing a master cheat. */ + // cur_entry = &this->cheat_entries[0]; + /* There can only be one master cheat. */ + // if (cur_entry->definition.num_opcodes > 0) + // { + // return false; + // } + /* Extract name bounds */ + size_t j = i + 1; + while (s[j] != '}') + { + j++; + if (j >= bufferSize) + { + return false; + } + } + /* s[i+1:j] is cheat name. */ + const size_t cheat_name_len = std::min(j - i - 1, sizeof(cheat.definition.readable_name)); + memcpy(cheat.definition.readable_name, &s[i + 1], cheat_name_len); + cheat.definition.readable_name[cheat_name_len] = 0; + /* Skip onwards. */ + i = j + 1; + } + else if (std::isxdigit(static_cast(s[i]))) + { + /* Make sure that we have a cheat open. */ + // if (cur_entry == nullptr) + // { + // return false; + // } + /* Bounds check the opcode count. */ + // if (cur_entry->definition.num_opcodes >= util::size(cur_entry->definition.opcodes)) + // { + // return false; + // } + /* We're parsing an instruction, so validate it's 8 hex digits. */ + for (size_t j = 1; j < 8; j++) + { + /* Validate 8 hex chars. */ + if (i + j >= bufferSize || !std::isxdigit(static_cast(s[i + j]))) + { + return false; + } + } + /* Parse the new opcode. */ + char hex_str[9] = {0}; + std::memcpy(hex_str, &s[i], 8); + cheat.definition.opcodes[cheat.definition.num_opcodes++] = std::strtoul(hex_str, NULL, 16); + /* Skip onwards. */ + i += 8; + } + else + { + /* Unexpected character encountered. */ + return false; + } + } + if (cheat.definition.num_opcodes > 0) + { + if (dmntchtAddCheat(&(cheat.definition), false, &(cheat.cheat_id))) + { + cheat.definition.num_opcodes = 0; + } + else + { + printf("error adding cheat code\n"); + return false; + } + } + } + // + reloadcheats(); + } +} void GuiCheats::reloadcheats() { if (m_cheats != nullptr) From 6bbabdb13790691ae96c639ddbda348e9d25a36f Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 10 Aug 2020 20:35:47 +0800 Subject: [PATCH 57/95] noicon config --- Makefile | 2 +- include/guis/gui_cheats.hpp | 10 ++++++---- source/guis/gui_cheats.cpp | 14 ++++++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 413c32e5..bbfabd8f 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 3 +VERSION_MICRO := 4 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index a7b1f6a5..b1ac0c02 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -131,7 +131,9 @@ class GuiCheats : public Gui #define MAX_POINTER_DEPTH 12 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 #define MAX_NUM_POINTER_OFFSET 30 -#define HAVESAVE true +#define HAVESAVE m_havesave + bool m_havesave = true; + void iconloadcheck(); struct PointerSearch_state { u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget @@ -209,7 +211,7 @@ class GuiCheats : public Gui bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); bool addcodetofile(u64 index); bool dumpcodetofile(); - void reloadcheats(); + void reloadcheats(); bool reloadcheatsfromfile(u8 *buildID, u64 titleID); bool addstaticcodetofile(u64 index); void PSsaveSTATE(); @@ -245,8 +247,8 @@ class GuiCheats : public Gui searchMode_t searchMode, MemoryDump **displayDump); void searchMemoryAddressesSecondary2(Debugger *debugger, searchValue_t searchValue1, - searchValue_t searchValue2, searchType_t searchType, - searchMode_t searchMode, MemoryDump **displayDump); + searchValue_t searchValue2, searchType_t searchType, + searchMode_t searchMode, MemoryDump **displayDump); void searchMemoryValuesPrimary(Debugger *debugger, searchType_t searchType, searchMode_t searchMode, searchRegion_t searchRegion, MemoryDump **displayDump, std::vector memInfos); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index a5de19a8..7c194b5a 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -94,7 +94,8 @@ GuiCheats::GuiCheats() : Gui() _moveLonelyCheats(m_buildID, m_debugger->getRunningApplicationTID()); // reloadcheatsfromfile(m_buildID, m_debugger->getRunningApplicationTID()); - dumpcodetofile(); + dumpcodetofile(); + iconloadcheck(); dmntchtGetCheatCount(&m_cheatCnt); @@ -5126,6 +5127,15 @@ void GuiCheats::reloadcheats() dmntchtGetCheats(m_cheats, m_cheatCnt, 0, &m_cheatCnt); } } +void GuiCheats::iconloadcheck() +{ + std::stringstream filenoiconStr; + filenoiconStr << EDIZON_DIR "/noicon.txt"; + if (access(filenoiconStr.str().c_str(), F_OK) == 0) + { + m_havesave = false; + } +} bool GuiCheats::dumpcodetofile() { std::stringstream buildIDStr; @@ -5170,7 +5180,7 @@ bool GuiCheats::dumpcodetofile() T = (m_cheats[i].definition.opcodes[j] >> 20) & 0xF; u8 X = (m_cheats[i].definition.opcodes[j] >> 8) & 0xF; if (opcode == 0xC0) - { + { opcode = opcode * 16 + X; } } From e0a34589ba8569706bea4e2147f54b7147759ce4 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 11 Aug 2020 00:55:26 +0800 Subject: [PATCH 58/95] Change --- source/guis/gui_cheats.cpp | 89 +++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 7c194b5a..442d2c1e 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1049,7 +1049,24 @@ void GuiCheats::drawSearchRAMMenu() if (m_searchValueFormat == FORMAT_DEC) ss << _getValueDisplayString(m_searchValue[0], m_searchType); else if (m_searchValueFormat == FORMAT_HEX) - ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u64; + { + switch (dataTypeSizes[m_searchType]) + { + case 1: + ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u8; + break; + case 2: + ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u16; + break; + default: + case 4: + ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u32; + break; + case 8: + ss << "0x" << std::uppercase << std::hex << m_searchValue[0]._u64; + break; + } + } Gui::getTextDimensions(font20, ss.str().c_str(), &strWidth, nullptr); Gui::drawTextAligned(font20, 310, 285, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -1843,7 +1860,37 @@ void GuiCheats::onInput(u32 kdown) // Gui::g_nextGui = GUI_MAIN; // return; // } - if (kdown & KEY_R) + if ((kdown & KEY_R) && (kheld & KEY_ZL)) + { + if (m_menuLocation == CANDIDATES && m_memoryDump1 != nullptr) + { + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + if (m_bookmark.type < SEARCH_TYPE_FLOAT_64BIT) + { + u8 i = static_cast(m_bookmark.type) + 1; + m_bookmark.type = static_cast(i); + } + m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + }; + }; + + if ((kdown & KEY_L) && (kheld & KEY_ZL)) + { + if (m_menuLocation == CANDIDATES && m_memoryDump1 != nullptr) + { + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + if (m_bookmark.type > SEARCH_TYPE_UNSIGNED_8BIT) + { + u8 i = static_cast(m_bookmark.type) - 1; + m_bookmark.type = static_cast(i); + } + m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + }; + }; + + if ((kdown & KEY_R) && !(kheld & KEY_ZL)) { if (m_searchValueFormat == FORMAT_HEX) m_searchValueFormat = FORMAT_DEC; @@ -1853,7 +1900,7 @@ void GuiCheats::onInput(u32 kdown) printf("%s\n", "HEX"); printf("%s\n", "R key pressed"); } - if (kdown & KEY_L) //toggle bookmark view bookmark : (m_memoryDump1 != nullptr) + if ((kdown & KEY_L) && !(kheld & KEY_ZL)) //toggle bookmark view bookmark : (m_memoryDump1 != nullptr) { if (m_memoryDump1 == nullptr) { @@ -2490,7 +2537,24 @@ static std::string _getAddressDisplayString(u64 address, Debugger *debugger, sea searchValue._u64 = debugger->peekMemory(address); // start mod for address content display if (m_searchValueFormat == FORMAT_HEX) - ss << "0x" << std::uppercase << std::hex << searchValue._u64; + { + switch (dataTypeSizes[searchType]) + { + case 1: + ss << "0x" << std::uppercase << std::hex << searchValue._u8; + break; + case 2: + ss << "0x" << std::uppercase << std::hex << searchValue._u16; + break; + default: + case 4: + ss << "0x" << std::uppercase << std::hex << searchValue._u32; + break; + case 8: + ss << "0x" << std::uppercase << std::hex << searchValue._u64; + break; + } + } else { @@ -2544,7 +2608,22 @@ static std::string _getValueDisplayString(searchValue_t searchValue, searchType_ if (m_searchValueFormat == FORMAT_HEX) { - ss << "0x" << std::uppercase << std::hex << searchValue._u64; + switch (dataTypeSizes[searchType]) + { + case 1: + ss << "0x" << std::uppercase << std::hex << searchValue._u8; + break; + case 2: + ss << "0x" << std::uppercase << std::hex << searchValue._u16; + break; + default: + case 4: + ss << "0x" << std::uppercase << std::hex << searchValue._u32; + break; + case 8: + ss << "0x" << std::uppercase << std::hex << searchValue._u64; + break; + } } else { From 26932ce24e2dc0f04047e5456545dda29232194c Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 11 Aug 2020 22:45:18 +0800 Subject: [PATCH 59/95] dumpcodetofile bug fix --- source/guis/gui_cheats.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 442d2c1e..a7601f59 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -5263,6 +5263,14 @@ bool GuiCheats::dumpcodetofile() opcode = opcode * 16 + X; } } + if (opcode == 10) + { + u8 O = (m_cheats[i].definition.opcodes[j] >> 8) & 0xF; + if (O == 2 || O == 4 || O == 5) + T = 8; + else + T = 4; + } switch (opcode) { case 0: @@ -5274,10 +5282,12 @@ bool GuiCheats::dumpcodetofile() // 2+1 ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; case 3: + case 10: // 1+1 - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j++] << " "; - if (T == 8 || (T == 1 && opcode == 3)) + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j] << " "; + if (T == 8 || (T == 0 && opcode == 3)) { + j++; ss << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << m_cheats[i].definition.opcodes[j] << " "; } break; From ce67d2a60ee3e364bad36794ef3e557d7258b705 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 12 Aug 2020 13:21:35 +0800 Subject: [PATCH 60/95] Bookmark added from memory editor inherit pointer chain that was used as starting address --- include/guis/gui_cheats.hpp | 4 ++-- source/guis/gui_cheats.cpp | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index b1ac0c02..f6305703 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -77,7 +77,7 @@ class GuiCheats : public Gui u64 m_numoffset = 3; u64 m_max_source = 200; u64 m_max_depth = 2; - u64 m_max_range = 0x300; + u64 m_max_range = 0x800; u64 m_EditorBaseAddr = 0; u64 m_mainBaseAddr; u64 m_mainend; @@ -90,7 +90,7 @@ class GuiCheats : public Gui u64 m_numoffset = 3; u64 m_max_source = 200; u64 m_max_depth = 2; - u64 m_max_range = 0x300; + u64 m_max_range = 0x800; u64 m_low_main_heap_addr = 0x100000000; u64 m_high_main_heap_addr = 0x10000000000; u64 m_pointer_found = 0; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index a7601f59..ac6c6746 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1630,6 +1630,7 @@ void GuiCheats::onInput(u32 kdown) if (kdown & KEY_RSTICK && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_searchMenuLocation = SEARCH_editRAM; m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; } @@ -2175,11 +2176,22 @@ void GuiCheats::onInput(u32 kdown) bookmark.type = m_searchType; Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + if (m_bookmark.pointer.depth > 0) + { + s64 offset = address - m_EditorBaseAddr + m_bookmark.pointer.offset[0]; + if (offset >= 0 && offset < (s64)m_max_range) + { + memcpy(&(bookmark.pointer), &(m_bookmark.pointer), (m_bookmark.pointer.depth + 2) * 8); + bookmark.pointer.offset[0] = (u64)offset; + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + } + } m_AttributeDumpBookmark->flushBuffer(); + m_memoryDumpBookmark->flushBuffer(); (new Snackbar("Address added to bookmark!"))->show(); - m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); - m_memoryDumpBookmark->flushBuffer(); printf("%s\n", "PLUS key pressed"); } if (kdown & KEY_ZR) @@ -5194,6 +5206,7 @@ bool GuiCheats::reloadcheatsfromfile(u8 *buildID, u64 titleID) // reloadcheats(); } + return true; } void GuiCheats::reloadcheats() { From ba9cdf2aa6e248ec7efacbcae1b35e5bb401fea8 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 12 Aug 2020 15:30:20 +0800 Subject: [PATCH 61/95] include code static with MAIN search --- source/guis/gui_cheats.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index ac6c6746..f7eecfc0 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -2702,22 +2702,14 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s time_t unixTime1 = time(NULL); printf("%s%lx\n", "Start Time primary search", unixTime1); // printf("main %lx main end %lx heap %lx heap end %lx \n",m_mainBaseAddr, m_mainBaseAddr+m_mainSize, m_heapBaseAddr, m_heapBaseAddr+m_heapSize); + printf("value1=%lx value2=%lx typesize=%d\n", searchValue1._u64, searchValue2._u64, dataTypeSizes[searchType]); for (MemoryInfo meminfo : memInfos) { - // printf("%s%p", "meminfo.addr, ", meminfo.addr); - // printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); - // printf("%s%p", ", meminfo.size, ", meminfo.size); - // printf("%s%lx", ", meminfo.type, ", meminfo.type); - // printf("%s%lx", ", meminfo.attr, ", meminfo.attr); - // printf("%s%lx", ", meminfo.perm, ", meminfo.perm); - // printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); - // printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); - if (searchRegion == SEARCH_REGION_HEAP && meminfo.type != MemType_Heap) continue; else if (searchRegion == SEARCH_REGION_MAIN && - (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) + (meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable && meminfo.type != MemType_CodeStatic)) continue; else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) @@ -2725,6 +2717,14 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) continue; + // printf("%s%p", "meminfo.addr, ", meminfo.addr); + // printf("%s%p", ", meminfo.end, ", meminfo.addr + meminfo.size); + // printf("%s%p", ", meminfo.size, ", meminfo.size); + // printf("%s%lx", ", meminfo.type, ", meminfo.type); + // printf("%s%lx", ", meminfo.attr, ", meminfo.attr); + // printf("%s%lx", ", meminfo.perm, ", meminfo.perm); + // printf("%s%lx", ", meminfo.device_refcount, ", meminfo.device_refcount); + // printf("%s%lx\n", ", meminfo.ipc_refcount, ", meminfo.ipc_refcount); setLedState(ledOn); ledOn = !ledOn; From c41604f18e35fd5b5d5ac600ad03b2477c937185 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 13 Aug 2020 00:59:51 +0800 Subject: [PATCH 62/95] bug fix --- Makefile | 2 +- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 20 +++++++++++--------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index bbfabd8f..e116a0dc 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 4 +VERSION_MICRO := 5 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index f6305703..389bab3c 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -109,6 +109,7 @@ class GuiCheats : public Gui u64 m_heapBaseAddr = 0x00; u64 m_mainBaseAddr = 0x00; u64 m_EditorBaseAddr = 0x00; + u64 m_BookmarkAddr = 0; u8 m_addressmod = 0; time_t m_Time1; struct helperinfo_t diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f7eecfc0..c5b1737a 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1603,14 +1603,14 @@ void GuiCheats::onInput(u32 kdown) bookmark.type = m_searchType; Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); - if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + if (address >= m_heapBaseAddr && address < m_heapEnd) { - bookmark.offset = address - m_memoryDump->getDumpInfo().heapBaseAddress; + bookmark.offset = address - m_heapBaseAddr; bookmark.heap = true; } - else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + else if (address >= m_mainBaseAddr && address < m_mainend) { - bookmark.offset = address - m_memoryDump->getDumpInfo().mainBaseAddress; + bookmark.offset = address - m_mainBaseAddr; bookmark.heap = false; } @@ -1630,6 +1630,7 @@ void GuiCheats::onInput(u32 kdown) if (kdown & KEY_RSTICK && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_BookmarkAddr = m_EditorBaseAddr; m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_searchMenuLocation = SEARCH_editRAM; m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; @@ -2162,14 +2163,14 @@ void GuiCheats::onInput(u32 kdown) u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; bookmark_t bookmark; - if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) + if (address >= m_heapBaseAddr && address < m_heapEnd) { - bookmark.offset = address - m_memoryDump->getDumpInfo().heapBaseAddress; + bookmark.offset = address - m_heapBaseAddr; bookmark.heap = true; } - else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) + else if (address >= m_mainBaseAddr && address < m_mainend) { - bookmark.offset = address - m_memoryDump->getDumpInfo().mainBaseAddress; + bookmark.offset = address - m_mainBaseAddr; bookmark.heap = false; } @@ -2179,7 +2180,8 @@ void GuiCheats::onInput(u32 kdown) m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); if (m_bookmark.pointer.depth > 0) { - s64 offset = address - m_EditorBaseAddr + m_bookmark.pointer.offset[0]; + s64 offset = address - m_BookmarkAddr + m_bookmark.pointer.offset[0]; + // printf("address = %lx m_EditorBaseAddr = %lx m_bookmark.pointer.offset[0] = %lx m_addressmod = %lx\n", address, m_EditorBaseAddr, m_bookmark.pointer.offset[0],m_addressmod); if (offset >= 0 && offset < (s64)m_max_range) { memcpy(&(bookmark.pointer), &(m_bookmark.pointer), (m_bookmark.pointer.depth + 2) * 8); From a173590b1f5e89611aa03e9b4332958f40b1122b Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 15 Aug 2020 10:53:15 +0800 Subject: [PATCH 63/95] show version and some bug fix --- Makefile | 2 +- source/guis/gui_cheats.cpp | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index e116a0dc..6f97c5e1 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 5 +VERSION_MICRO := 6 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index c5b1737a..f47b7402 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -527,18 +527,21 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 122, currTheme.textColor, "Stack", ALIGNED_LEFT); Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); + ss.str(""); + ss << "EdiZon SE : 3.6.6"; + Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr + m_addressSpaceSize; - Gui::drawTextAligned(font14, 900, 75, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font14, 900, 92, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "HEAP : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapBaseAddr; ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_heapEnd; - Gui::drawTextAligned(font14, 900, 105, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font14, 900, 122, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "MAIN : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainBaseAddr; ss << " - 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_mainend; - Gui::drawTextAligned(font14, 900, 135, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); + Gui::drawTextAligned(font14, 900, 152, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); Gui::drawRectangle(256, 50, 394, 137, COLOR_WHITE); @@ -689,10 +692,10 @@ void GuiCheats::draw() u64 address = 0; m_memoryDump->getData((line + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); // candidate display - if (address >= m_memoryDump->getDumpInfo().heapBaseAddress && address < (m_memoryDump->getDumpInfo().heapBaseAddress + m_memoryDump->getDumpInfo().heapSize)) - ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().heapBaseAddress) << " ]"; - else if (address >= m_memoryDump->getDumpInfo().mainBaseAddress && address < (m_memoryDump->getDumpInfo().mainBaseAddress + m_memoryDump->getDumpInfo().mainSize)) - ss << "[ MAIN + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().mainBaseAddress) << " ]"; + if (address >= m_heapBaseAddr && address < m_heapEnd) + ss << "[ HEAP + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_heapBaseAddr) << " ]"; + else if (address >= m_mainBaseAddr && address < m_mainend) + ss << "[ MAIN + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_mainBaseAddr) << " ]"; else ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address - m_memoryDump->getDumpInfo().addrSpaceBaseAddress) << " ]"; From 577c721292412312366730b58e5c362b06302f77 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 15 Aug 2020 19:07:41 +0800 Subject: [PATCH 64/95] ZL + B ForceCloseCheatProcess --- include/helpers/dmntcht.h | 8 +++++++- source/guis/gui_cheats.cpp | 9 ++++++++- source/helpers/dmntcht.c | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/helpers/dmntcht.h b/include/helpers/dmntcht.h index 186782ce..555276dc 100644 --- a/include/helpers/dmntcht.h +++ b/include/helpers/dmntcht.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Atmosphère-NX + * Copyright (c) 2018-2020 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -67,12 +67,15 @@ Result dmntchtHasCheatProcess(bool *out); Result dmntchtGetCheatProcessEvent(Event *event); Result dmntchtGetCheatProcessMetadata(DmntCheatProcessMetadata *out_metadata); Result dmntchtForceOpenCheatProcess(void); +Result dmntchtForceCloseCheatProcess(void); Result dmntchtGetCheatProcessMappingCount(u64 *out_count); Result dmntchtGetCheatProcessMappings(MemoryInfo *buffer, u64 max_count, u64 offset, u64 *out_count); Result dmntchtReadCheatProcessMemory(u64 address, void *buffer, size_t size); Result dmntchtWriteCheatProcessMemory(u64 address, const void *buffer, size_t size); Result dmntchtQueryCheatProcessMemory(MemoryInfo *mem_info, u64 address); +Result dmntchtPauseCheatProcess(void); +Result dmntchtResumeCheatProcess(void); Result dmntchtGetCheatCount(u64 *out_count); Result dmntchtGetCheats(DmntCheatEntry *buffer, u64 max_count, u64 offset, u64 *out_count); @@ -80,6 +83,9 @@ Result dmntchtGetCheatById(DmntCheatEntry *out_cheat, u32 cheat_id); Result dmntchtToggleCheat(u32 cheat_id); Result dmntchtAddCheat(DmntCheatDefinition *cheat, bool enabled, u32 *out_cheat_id); Result dmntchtRemoveCheat(u32 cheat_id); +Result dmntchtReadStaticRegister(u64 *out, u8 which); +Result dmntchtWriteStaticRegister(u8 which, u64 value); +Result dmntchtResetStaticRegisters(); Result dmntchtGetFrozenAddressCount(u64 *out_count); Result dmntchtGetFrozenAddresses(DmntFrozenAddressEntry *buffer, u64 max_count, u64 offset, u64 *out_count); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f47b7402..f5520cfd 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -66,6 +66,7 @@ GuiCheats::GuiCheats() : Gui() dmntchtInitialize(); dmntchtForceOpenCheatProcess(); + // dmntchtPauseCheatProcess(); DmntCheatProcessMetadata metadata; dmntchtGetCheatProcessMetadata(&metadata); @@ -395,6 +396,7 @@ GuiCheats::GuiCheats() : Gui() GuiCheats::~GuiCheats() { + // dmntchtResumeCheatProcess(); if (m_debugger != nullptr) { delete m_debugger; @@ -528,7 +530,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.6.6"; + ss << "EdiZon SE : 3.6.6"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size @@ -1129,6 +1131,11 @@ void GuiCheats::onInput(u32 kdown) if (m_searchMenuLocation == SEARCH_NONE) { // Gui::g_nextGui = GUI_MAIN; + if (kheld & KEY_ZL) + { + printf("dmnt force close cheat process test\n"); + dmntchtForceCloseCheatProcess(); + }; PSsaveSTATE(); Gui::g_requestExit = true; return; diff --git a/source/helpers/dmntcht.c b/source/helpers/dmntcht.c index 3bdd4f05..f1c80465 100644 --- a/source/helpers/dmntcht.c +++ b/source/helpers/dmntcht.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 Atmosphère-NX + * Copyright (c) 2018-2020 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -60,8 +60,24 @@ Result dmntchtGetCheatProcessMetadata(DmntCheatProcessMetadata *out_metadata) { return serviceDispatchOut(&g_dmntchtSrv, 65002, *out_metadata); } +static Result _dmntchtCmdVoid(Service* srv, u32 cmd_id) { + return serviceDispatch(srv, cmd_id); +} + Result dmntchtForceOpenCheatProcess(void) { - return serviceDispatch(&g_dmntchtSrv, 65003); + return _dmntchtCmdVoid(&g_dmntchtSrv, 65003); +} + +Result dmntchtForceCloseCheatProcess(void) { + return _dmntchtCmdVoid(&g_dmntchtSrv, 65009); +} + +Result dmntchtPauseCheatProcess(void) { + return _dmntchtCmdVoid(&g_dmntchtSrv, 65004); +} + +Result dmntchtResumeCheatProcess(void) { + return _dmntchtCmdVoid(&g_dmntchtSrv, 65005); } static Result _dmntchtGetCount(u64 *out_count, u32 cmd_id) { @@ -144,6 +160,23 @@ Result dmntchtRemoveCheat(u32 cheat_id) { return _dmntchtCmdInU32NoOut(cheat_id, 65205); } +Result dmntchtReadStaticRegister(u64 *out, u8 which) { + return serviceDispatchInOut(&g_dmntchtSrv, 65206, which, *out); +} + +Result dmntchtWriteStaticRegister(u8 which, u64 value) { + const struct { + u64 which; + u64 value; + } in = { which, value }; + + return serviceDispatchIn(&g_dmntchtSrv, 65207, in); +} + +Result dmntchtResetStaticRegisters() { + return _dmntchtCmdVoid(&g_dmntchtSrv, 65208); +} + Result dmntchtGetFrozenAddressCount(u64 *out_count) { return _dmntchtGetCount(out_count, 65300); } From e68410f1b065ed49ddf5a0f63fef66df5da24f9c Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 15 Aug 2020 19:59:13 +0800 Subject: [PATCH 65/95] ZL+B toggle dmnt --- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 389bab3c..5a2ea526 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -135,6 +135,7 @@ class GuiCheats : public Gui #define HAVESAVE m_havesave bool m_havesave = true; void iconloadcheck(); + void autoattachcheck(); struct PointerSearch_state { u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f5520cfd..6fd783a2 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -65,7 +65,8 @@ GuiCheats::GuiCheats() : Gui() return; dmntchtInitialize(); - dmntchtForceOpenCheatProcess(); + // dmntchtForceOpenCheatProcess(); + autoattachcheck(); // dmntchtPauseCheatProcess(); DmntCheatProcessMetadata metadata; @@ -640,6 +641,8 @@ void GuiCheats::draw() } } } + else if (m_mainBaseAddr == 0) + Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Dmnt detached from game process, press ZL+B to reattach,\n \n relaunch EdiZon SE to access this game", ALIGNED_CENTER); else if (m_cheatsPresent && m_memoryDump->size() == 0) Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Cheats for this game present but title version or region doesn't match!", ALIGNED_CENTER); @@ -1133,8 +1136,11 @@ void GuiCheats::onInput(u32 kdown) // Gui::g_nextGui = GUI_MAIN; if (kheld & KEY_ZL) { - printf("dmnt force close cheat process test\n"); - dmntchtForceCloseCheatProcess(); + if (m_mainBaseAddr == 0) + dmntchtForceOpenCheatProcess(); + else + dmntchtForceCloseCheatProcess(); + printf("dmnt toggled \n"); }; PSsaveSTATE(); Gui::g_requestExit = true; @@ -5240,6 +5246,15 @@ void GuiCheats::iconloadcheck() m_havesave = false; } } +void GuiCheats::autoattachcheck() +{ + std::stringstream filenoiconStr; + filenoiconStr << EDIZON_DIR "/autoattach.txt"; + if (access(filenoiconStr.str().c_str(), F_OK) == 0) + { + dmntchtForceOpenCheatProcess(); + } +} bool GuiCheats::dumpcodetofile() { std::stringstream buildIDStr; From db9d7217b824205428b8cf8d2f8c3da788712a05 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 16 Aug 2020 10:52:56 +0800 Subject: [PATCH 66/95] fix a splash screen display bug --- icon.jpg | Bin 12541 -> 12514 bytes icon2.jpg | Bin 0 -> 12541 bytes source/main.cpp | 7 +------ 3 files changed, 1 insertion(+), 6 deletions(-) create mode 100644 icon2.jpg diff --git a/icon.jpg b/icon.jpg index 725c0b84f884ef0a57b32c4cecdd8d545a734ffd..9eddb6051eb11a2c128eb4f09beb29f6cd0569ee 100644 GIT binary patch delta 10528 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 delta 10625 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 diff --git a/icon2.jpg b/icon2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..725c0b84f884ef0a57b32c4cecdd8d545a734ffd GIT binary patch literal 12541 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 sEW@u@4|ndY5JcB%E74r1q2?XbpQYW literal 0 HcmV?d00001 diff --git a/source/main.cpp b/source/main.cpp index 8a426b05..40e66b87 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -207,17 +207,12 @@ int main(int argc, char **argv) Gui::g_splashDisplayed = true; Gui::g_nextGui = GUI_CHEATS; } - else - Gui::g_nextGui = GUI_MAIN; - -#if SPLASH_ENABLED + if (!Gui::g_splashDisplayed) { - static Gui *currGui = nullptr; currGui = new GuiMain(); currGui->draw(); } -#endif initTitles(); From a0b58e0c57a3f56a09f78cbec9ff4a94418a473f Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 16 Aug 2020 11:03:53 +0800 Subject: [PATCH 67/95] fix a splash screen display bug --- source/main.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 8a426b05..40e66b87 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -207,17 +207,12 @@ int main(int argc, char **argv) Gui::g_splashDisplayed = true; Gui::g_nextGui = GUI_CHEATS; } - else - Gui::g_nextGui = GUI_MAIN; - -#if SPLASH_ENABLED + if (!Gui::g_splashDisplayed) { - static Gui *currGui = nullptr; currGui = new GuiMain(); currGui->draw(); } -#endif initTitles(); From 7a314054d4b0df6777c89d401b943bad0937493c Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 16 Aug 2020 21:07:05 +0800 Subject: [PATCH 68/95] UI improvements --- Makefile | 2 +- source/guis/gui_cheats.cpp | 44 ++++++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 6f97c5e1..78662f6d 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 6 +VERSION_MICRO := 7 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 6fd783a2..b8ca7be9 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -386,10 +386,10 @@ GuiCheats::GuiCheats() : Gui() buildIDStr = ss.str(); - if (m_cheatCnt == 0) - m_menuLocation = CANDIDATES; if (m_memoryDump->size() == 0) m_menuLocation = CHEATS; + if (m_cheatCnt == 0) + m_menuLocation = CANDIDATES; appletSetMediaPlaybackState(true); } @@ -475,9 +475,9 @@ void GuiCheats::draw() if (m_menuLocation == CHEATS) { if (m_memoryDump1 == nullptr) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); else - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); } else if (m_memoryDump1 == nullptr) { @@ -494,7 +494,8 @@ void GuiCheats::draw() { if (m_memoryDump->size() > 0) { - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM add \uE0F0 Reset search \uE0E3 Search again \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE0E6+\uE0E1 Detach debugger \uE0E4 BM toggle \uE0E5 Hex Mode \uE0EF BM add \uE0F0 Reset search \uE0E3 Search again \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E7 Page Up \uE0E7 Page Down \uE105 Memory Editor", ALIGNED_RIGHT); } else Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Reset search \uE0E1 Quit", ALIGNED_RIGHT); @@ -504,7 +505,9 @@ void GuiCheats::draw() { if (m_memoryDumpBookmark->size() > 0) { - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0EF BM label \uE0E3 Add Cheat \uE0F0 Delete BM \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E5 Hex Mode \uE0EF BM label \uE0E3 Add Cheat \uE0F0 Delete BM \uE0E2 Freeze value \uE0E7 Page Down \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E4 \uE0E6+\uE0E5 Change Type \uE0E6+\uE0F0 Refresh Bookmark \uE0E6+\uE0EF Import Bookmark \uE0E6+\uE0E3 Pointer Search \uE0E6+\uE0E7 Page Up \uE105 Memory Editor", ALIGNED_RIGHT); + // } else Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E4 BM toggle \uE0E1 Quit", ALIGNED_RIGHT); @@ -531,7 +534,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.6.6"; + ss << "EdiZon SE : 3.6.7"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size @@ -642,7 +645,7 @@ void GuiCheats::draw() } } else if (m_mainBaseAddr == 0) - Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Dmnt detached from game process, press ZL+B to reattach,\n \n relaunch EdiZon SE to access this game", ALIGNED_CENTER); + Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Dmnt detached from game process, press ZL+B to attach,\n \n relaunch EdiZon SE to access this game", ALIGNED_CENTER); else if (m_cheatsPresent && m_memoryDump->size() == 0) Gui::drawTextAligned(font24, Gui::g_framebuffer_width / 2, Gui::g_framebuffer_height / 2 + 50, currTheme.textColor, "Cheats for this game present but title version or region doesn't match!", ALIGNED_CENTER); @@ -876,7 +879,7 @@ void GuiCheats::drawSearchPointerMenu() if (cursorBlinkCnt++ % 60 > 10 && m_selectedEntry == 5) Gui::drawRectangled(622 + strWidth, 360, 3, 35, currTheme.highlightColor); - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0EF Start Search \uE0E1 Abort \uE0E0 Edit", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, Gui::g_framebuffer_height - 100, currTheme.textColor, "\uE0E6+\uE0E3 Make Dump for pointersearcher SE \uE0EF Start Search \uE0E1 Abort \uE0E4 \uE0E5 Edit Value", ALIGNED_RIGHT); // if (m_selectedEntry == 3) // Gui::drawRectangled(Gui::g_framebuffer_width / 2 - 155, 345, 310, 90, currTheme.highlightColor); @@ -1192,7 +1195,12 @@ void GuiCheats::onInput(u32 kdown) printf("starting PC dump\n"); m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; m_searchRegion = SEARCH_REGION_HEAP_AND_MAIN; + Gui::beginDraw(); + Gui::drawRectangle(70, 420, 1150, 65, currTheme.backgroundColor); + Gui::drawTextAligned(font20, 70, 420, currTheme.textColor, "Making Dump for pointersearcher SE", ALIGNED_LEFT); + Gui::endDraw(); GuiCheats::searchMemoryAddressesPrimary2(m_debugger, m_searchValue[0], m_searchValue[1], m_searchType, m_searchMode, m_searchRegion, &m_memoryDump, m_memoryInfo); + (new Snackbar("Dump for pointersearcher SE completed"))->show(); // PCdump(); } @@ -1324,7 +1332,7 @@ void GuiCheats::onInput(u32 kdown) m_searchValue[1]._u64 = 0x8000000000; } - if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS && (m_cheatCnt > 0) && (m_memoryDump1 != nullptr)) + if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS && (m_cheatCnt > 0) && (m_memoryDump1 != nullptr) && !(kheld & KEY_ZL)) { // printf("start adding cheat to bookmark\n"); // m_cheatCnt @@ -5264,14 +5272,14 @@ bool GuiCheats::dumpcodetofile() buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; } - std::stringstream realCheatPath; - { - realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); - mkdir(realCheatPath.str().c_str(), 0777); - realCheatPath << "/cheats/"; - mkdir(realCheatPath.str().c_str(), 0777); - realCheatPath << buildIDStr.str() << ".txt"; - } + // std::stringstream realCheatPath; + // { + // realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + // mkdir(realCheatPath.str().c_str(), 0777); + // realCheatPath << "/cheats/"; + // mkdir(realCheatPath.str().c_str(), 0777); + // realCheatPath << buildIDStr.str() << ".txt"; + // } FILE *pfile; pfile = fopen(filebuildIDStr.str().c_str(), "w"); std::stringstream SS; From 0534cc0753f0b83f1ccb9c7ebd9f5ed863fa08b7 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 18 Aug 2020 12:09:18 +0800 Subject: [PATCH 69/95] UI bug fixs and improvements --- include/guis/gui_cheats.hpp | 7 +++ source/guis/gui_cheats.cpp | 118 +++++++++++++++++++++++++++++------- 2 files changed, 103 insertions(+), 22 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 5a2ea526..9d1bf0d7 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -38,8 +38,15 @@ class GuiCheats : public Gui color_t m_memory[1024] = {0}; u8 m_selectedEntry = 0; + u8 m_selectedEntrySave = 0; + u8 m_selectedEntrySaveCL = 0; + u8 m_selectedEntrySaveBM = 0; + u8 m_selectedEntrySaveSR = 0; + u8 m_searchValueIndex = 0; u32 m_addresslist_offset = 0; + u32 m_addresslist_offsetSaveBM = 0; + u32 m_addresslist_offsetSaveSR = 0; searchValue_t m_searchValue[2]; diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index b8ca7be9..89b87e09 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1158,6 +1158,7 @@ void GuiCheats::onInput(u32 kdown) } else if (m_searchMenuLocation == SEARCH_editRAM) { + m_selectedEntry = m_selectedEntrySave; m_searchMenuLocation = SEARCH_NONE; } else if (m_searchMenuLocation == SEARCH_TYPE) @@ -1405,7 +1406,7 @@ void GuiCheats::onInput(u32 kdown) m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); - continue; + break; } if (depth == 0) { @@ -1501,7 +1502,7 @@ void GuiCheats::onInput(u32 kdown) { m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); - (new Snackbar("Adding address from cheat to bookmark"))->show(); + (new Snackbar("Adding pointer chain from cheat to bookmark"))->show(); } else { @@ -1523,7 +1524,7 @@ void GuiCheats::onInput(u32 kdown) ->show(); } else - (new Snackbar("Not able to extract address from cheat"))->show(); + (new Snackbar("Not able to extract pointer chain from cheat"))->show(); } // pointercheck(); //disable for now; @@ -1536,15 +1537,27 @@ void GuiCheats::onInput(u32 kdown) if (m_cheatCnt > 0) { m_menuLocation = CHEATS; - m_selectedEntry = 0; - cheatListOffset = 0; + if (m_memoryDump1 == nullptr) + m_selectedEntrySaveSR = m_selectedEntry; + else + m_selectedEntrySaveBM = m_selectedEntry; + + m_selectedEntry = m_selectedEntrySaveCL; + // cheatListOffset = 0; } if (kdown & KEY_RIGHT) { + m_selectedEntrySaveCL = m_selectedEntry; m_menuLocation = CANDIDATES; - m_selectedEntry = 0; - cheatListOffset = 0; + if (m_memoryDump1 == nullptr) + m_selectedEntry = m_selectedEntrySaveSR; + else + m_selectedEntry = m_selectedEntrySaveBM; + + + // m_selectedEntry = 0; + // cheatListOffset = 0; } } @@ -1606,6 +1619,17 @@ void GuiCheats::onInput(u32 kdown) m_memoryDump1 = m_memoryDump; m_memoryDump = m_memoryDumpBookmark; + + if (m_memoryDump->size() > 0) + { + if (m_memoryDump->size() / sizeof(u64) - 1 < m_selectedEntry) + m_selectedEntry = m_memoryDump->size() / sizeof(u64) - 1; + } + else + { + m_menuLocation = CHEATS; + m_selectedEntry = 0; + }; } } @@ -1657,6 +1681,7 @@ void GuiCheats::onInput(u32 kdown) m_BookmarkAddr = m_EditorBaseAddr; m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); m_searchMenuLocation = SEARCH_editRAM; + m_selectedEntrySave = m_selectedEntry; m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; } if ((kdown & KEY_LSTICK) && (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) && (m_memoryDump1 != nullptr)) @@ -1810,6 +1835,22 @@ void GuiCheats::onInput(u32 kdown) m_memoryDump1 = m_memoryDump; m_memoryDump = m_memoryDumpBookmark; + + if (m_memoryDump->size() > 0) + { + if (m_memoryDump->size() / sizeof(u64) - 1 < m_selectedEntry) + m_selectedEntry = m_memoryDump->size() / sizeof(u64) - 1; + } + else + { + // m_selectedEntrySave = 0; + m_selectedEntrySaveBM = 0; + if (m_menuLocation != CHEATS) + { + m_menuLocation = CHEATS; + m_selectedEntry = m_selectedEntrySaveCL; + } + }; } } @@ -1930,25 +1971,57 @@ void GuiCheats::onInput(u32 kdown) { if (m_memoryDump1 == nullptr) { - m_memoryDump1 = m_memoryDump; - m_memoryDump = m_memoryDumpBookmark; - m_addresslist_offset = 0; - //consider to remove later - if (m_searchType == SEARCH_TYPE_NONE) - m_searchType = SEARCH_TYPE_UNSIGNED_32BIT; // to make sure not blank - // end - // (new Snackbar("Switch to bookmark List!"))->show(); - printf("%s\n", "Bookmark"); + // WIP + // switch to bookmark + // if (m_memoryDumpBookmark->size() == 0) + // { + // updatebookmark(true, false); + // } + if (m_memoryDumpBookmark->size() == 0) + m_menuLocation = CHEATS; + + { + m_memoryDump1 = m_memoryDump; + m_memoryDump = m_memoryDumpBookmark; + + if (m_menuLocation == CANDIDATES) + { + m_selectedEntrySaveSR = m_selectedEntry; + m_addresslist_offsetSaveSR = m_addresslist_offset; + m_selectedEntry = m_selectedEntrySaveBM; + m_addresslist_offset = m_addresslist_offsetSaveBM; + } + + if (m_memoryDump->size() == 0 && m_cheatCnt > 0) + { + m_menuLocation = CHEATS; + }; + //consider to remove later + if (m_searchType == SEARCH_TYPE_NONE) + m_searchType = SEARCH_TYPE_UNSIGNED_32BIT; // to make sure not blank + // end + // (new Snackbar("Switch to bookmark List!"))->show(); + printf("%s\n", "Bookmark"); + } } else { m_memoryDump = m_memoryDump1; m_memoryDump1 = nullptr; + + if (m_menuLocation == CANDIDATES) + { + m_selectedEntrySaveBM = m_selectedEntry; + m_addresslist_offsetSaveBM = m_addresslist_offset; + m_selectedEntry = m_selectedEntrySaveSR; + m_addresslist_offset = m_addresslist_offsetSaveSR; + } + // (new Snackbar("Switch to Normal List!"))->show(); } printf("%s\n", "L key pressed"); - if (m_menuLocation == CANDIDATES) - m_selectedEntry = 0; + // if (m_menuLocation == CANDIDATES) + // m_selectedEntry = 0; } if ((kdown & KEY_ZR) && !(kheld & KEY_ZL)) @@ -1998,7 +2071,7 @@ void GuiCheats::onInput(u32 kdown) m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); // m_searchMenuLocation = SEARCH_POINTER; // m_showpointermenu = true; - if (m_menuLocation == CANDIDATES) + if (m_menuLocation == CANDIDATES && m_memoryDumpBookmark->size() != 0) { bookmark_t bookmark; m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); @@ -2021,6 +2094,7 @@ void GuiCheats::onInput(u32 kdown) else if (m_searchMode == SEARCH_MODE_NONE) { m_searchMenuLocation = SEARCH_MODE; + m_selectedEntry = 0; // m_selectedEntry = m_searchType == SEARCH_TYPE_NONE ? 0 : m_searchType; } else @@ -2036,10 +2110,10 @@ void GuiCheats::onInput(u32 kdown) m_searchMode = SEARCH_MODE_DIFFA; m_selectedEntry = 1; } - else - m_selectedEntry = 0; + // else + // m_selectedEntry = 0; - cheatListOffset = 0; + // cheatListOffset = 0; } printf("%s\n", "Y key pressed"); printf("%s\n", titleNameStr.c_str()); From 187f03bf41ba9450f832c715a1b16b7c555760b5 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 18 Aug 2020 18:21:36 +0800 Subject: [PATCH 70/95] cheat code delete --- Makefile | 2 +- include/guis/gui_cheats.hpp | 2 + source/guis/gui_cheats.cpp | 303 +++++++++++++++++++++++++----------- 3 files changed, 216 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index 78662f6d..1057952c 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 7 +VERSION_MICRO := 8 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 9d1bf0d7..2659685a 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -219,6 +219,7 @@ class GuiCheats : public Gui bool valuematch(searchValue_t value, u64 nextaddress); bool getinput(std::string headerText, std::string subHeaderText, std::string initialText, searchValue_t *searchValue); bool addcodetofile(u64 index); + bool editcodefile(); bool dumpcodetofile(); void reloadcheats(); bool reloadcheatsfromfile(u8 *buildID, u64 titleID); @@ -236,6 +237,7 @@ class GuiCheats : public Gui DmntCheatEntry *m_cheats; u64 m_cheatCnt; + bool *m_cheatDelete; void drawSearchRAMMenu(); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 89b87e09..d9b396f6 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -96,7 +96,7 @@ GuiCheats::GuiCheats() : Gui() _moveLonelyCheats(m_buildID, m_debugger->getRunningApplicationTID()); // reloadcheatsfromfile(m_buildID, m_debugger->getRunningApplicationTID()); - dumpcodetofile(); + // dumpcodetofile(); iconloadcheck(); dmntchtGetCheatCount(&m_cheatCnt); @@ -104,6 +104,9 @@ GuiCheats::GuiCheats() : Gui() if (m_cheatCnt > 0) { m_cheats = new DmntCheatEntry[m_cheatCnt]; + m_cheatDelete = new bool[m_cheatCnt]; + for (u64 i = 0; i < m_cheatCnt; i++) + m_cheatDelete[i] = false; dmntchtGetCheats(m_cheats, m_cheatCnt, 0, &m_cheatCnt); } else if (_wrongCheatsPresent(m_buildID, m_debugger->getRunningApplicationTID())) @@ -475,9 +478,15 @@ void GuiCheats::draw() if (m_menuLocation == CHEATS) { if (m_memoryDump1 == nullptr) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + { + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE104 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); + } else - Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + { + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE104 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); + } } else if (m_memoryDump1 == nullptr) { @@ -534,7 +543,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.6.7"; + ss << "EdiZon SE : 3.6.8"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size @@ -628,9 +637,9 @@ void GuiCheats::draw() { if (line >= m_cheatCnt) break; - + // WIP ss.str(""); - ss << "\uE070 " << m_cheats[line].definition.readable_name; + ss << "\uE070 " << (m_cheatDelete[line] ? " Press \uE104 to delete" : (m_cheats[line].definition.readable_name)); Gui::drawRectangle(52, 300 + (line - cheatListOffset) * 40, 646, 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); Gui::drawTextAligned(font14, 70, 305 + (line - cheatListOffset) * 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -1314,16 +1323,30 @@ void GuiCheats::onInput(u32 kdown) } } // start mod - if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS) + if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) { - // m_searchMenuLocation = SEARCH_editRAM; - // printf("L Stick pressed, start pointer search *************\n"); - // startpointersearch(m_heapBaseAddr + 80, 10, 0x800, 3); - // printf("done pointer search ********************************\n"); - // printf("making a dump for pointers"); - // GuiCheats::searchMemoryAddressesPrimary(m_debugger, m_searchValue[0], m_searchValue[1], SEARCH_TYPE_UNSIGNED_64BIT, SEARCH_MODE_RANGE, SEARCH_REGION_HEAP_AND_MAIN, &m_memoryDump, m_memoryInfo); + // Edit cheats + // WIP + for (u64 i = 0; i < m_cheatCnt; i++) + if (m_cheatDelete[i]) + { + m_cheatDelete[i] = false; + dmntchtRemoveCheat(m_cheats[i].cheat_id); + } + reloadcheats(); // m_menuLocation = CANDIDATES; + // m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; + // m_searchMode = SEARCH_MODE_POINTER; + // m_searchRegion = SEARCH_REGION_HEAP_AND_MAIN; + // m_searchMenuLocation = SEARCH_VALUE; + // m_selectedEntry = 1; + // m_searchValue[0]._u64 = 0x1000000000; + // m_searchValue[1]._u64 = 0x8000000000; + } + if ((kdown & KEY_X) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) + { + m_menuLocation = CANDIDATES; m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; m_searchMode = SEARCH_MODE_POINTER; m_searchRegion = SEARCH_REGION_HEAP_AND_MAIN; @@ -1332,6 +1355,11 @@ void GuiCheats::onInput(u32 kdown) m_searchValue[0]._u64 = 0x1000000000; m_searchValue[1]._u64 = 0x8000000000; } + if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS && (kheld & KEY_ZL)) + { + dumpcodetofile(); + (new Snackbar("Writing change to file"))->show(); + } if ((kdown & KEY_PLUS) && m_menuLocation == CHEATS && (m_cheatCnt > 0) && (m_memoryDump1 != nullptr) && !(kheld & KEY_ZL)) { @@ -1538,9 +1566,15 @@ void GuiCheats::onInput(u32 kdown) { m_menuLocation = CHEATS; if (m_memoryDump1 == nullptr) + { m_selectedEntrySaveSR = m_selectedEntry; + m_addresslist_offsetSaveSR = m_addresslist_offset; + } else + { m_selectedEntrySaveBM = m_selectedEntry; + m_addresslist_offsetSaveBM = m_addresslist_offset; + } m_selectedEntry = m_selectedEntrySaveCL; // cheatListOffset = 0; @@ -1551,10 +1585,15 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntrySaveCL = m_selectedEntry; m_menuLocation = CANDIDATES; if (m_memoryDump1 == nullptr) + { m_selectedEntry = m_selectedEntrySaveSR; + m_addresslist_offset = m_addresslist_offsetSaveSR; + } else + { m_selectedEntry = m_selectedEntrySaveBM; - + m_addresslist_offset = m_addresslist_offsetSaveBM; + } // m_selectedEntry = 0; // cheatListOffset = 0; @@ -1857,66 +1896,76 @@ void GuiCheats::onInput(u32 kdown) if ((kdown & KEY_MINUS) && !(kheld & KEY_ZL)) { //make sure not using bookmark m_searchType - if (m_memoryDump1 != nullptr) - { //Bookmark case - bookmark_t bookmark; - m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); - bookmark.deleted = !bookmark.deleted; - m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); - // m_memoryDumpBookmark->flushBuffer(); - // m_memoryDump = m_memoryDump1; - // m_memoryDump1 = nullptr; - } - else + if (m_menuLocation == CANDIDATES) { - - m_addresslist_offset = 0; - // end mod - if (m_memoryDump->size() == 0) + if (m_memoryDump1 != nullptr) + { //Bookmark case + bookmark_t bookmark; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + bookmark.deleted = !bookmark.deleted; + m_AttributeDumpBookmark->putData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); + // m_memoryDumpBookmark->flushBuffer(); + // m_memoryDump = m_memoryDump1; + // m_memoryDump1 = nullptr; + } + else { - std::vector options; - - if (m_frozenAddresses.size() == 0) - return; - std::stringstream ss; - for (auto [addr, value] : m_frozenAddresses) + // m_addresslist_offset = 0; + m_selectedEntrySaveSR = 0; + m_addresslist_offsetSaveSR = 0; + // end mod + if (m_memoryDump->size() == 0) { - ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr - m_addressSpaceBaseAddr) << " ] "; - ss << "( " << std::dec << value << " )"; - options.push_back(ss.str()); - ss.str(""); - } + std::vector options; - (new ListSelector("Frozen Addresses", "\uE0E0 Unfreeze \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { - if (k & KEY_A) - { - auto itr = m_frozenAddresses.begin(); - std::advance(itr, selectedItem); + if (m_frozenAddresses.size() == 0) + return; - dmntchtDisableFrozenAddress(itr->first); - m_frozenAddresses.erase(itr->first); - } - }) - ->show(); - } - else - { - m_memoryDump->clear(); - remove(EDIZON_DIR "/memdump1.dat"); - remove(EDIZON_DIR "/memdump1a.dat"); - remove(EDIZON_DIR "/memdump2.dat"); - remove(EDIZON_DIR "/memdump3.dat"); - - // m_searchType = SEARCH_TYPE_NONE; - // m_searchMode = SEARCH_MODE_NONE; - // m_searchRegion = SEARCH_REGION_NONE; - // m_searchValue[0]._u64 = 0; - // m_searchValue[1]._u64 = 0; + std::stringstream ss; + for (auto [addr, value] : m_frozenAddresses) + { + ss << "[ BASE + 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr - m_addressSpaceBaseAddr) << " ] "; + ss << "( " << std::dec << value << " )"; + options.push_back(ss.str()); + ss.str(""); + } - m_menuLocation = CHEATS; + (new ListSelector("Frozen Addresses", "\uE0E0 Unfreeze \uE0E1 Back", options))->setInputAction([&](u32 k, u16 selectedItem) { + if (k & KEY_A) + { + auto itr = m_frozenAddresses.begin(); + std::advance(itr, selectedItem); + + dmntchtDisableFrozenAddress(itr->first); + m_frozenAddresses.erase(itr->first); + } + }) + ->show(); + } + else + { + m_memoryDump->clear(); + remove(EDIZON_DIR "/memdump1.dat"); + remove(EDIZON_DIR "/memdump1a.dat"); + remove(EDIZON_DIR "/memdump2.dat"); + remove(EDIZON_DIR "/memdump3.dat"); + + // m_searchType = SEARCH_TYPE_NONE; + // m_searchMode = SEARCH_MODE_NONE; + // m_searchRegion = SEARCH_REGION_NONE; + // m_searchValue[0]._u64 = 0; + // m_searchValue[1]._u64 = 0; + + m_menuLocation = CHEATS; + } } } + else + { // WIP working on cheat menu + // m_cheatCnt + m_cheatDelete[m_selectedEntry] = !m_cheatDelete[m_selectedEntry]; + } } // start mod KEY_PLUS // if (kdown & KEY_PLUS) { @@ -1977,8 +2026,9 @@ void GuiCheats::onInput(u32 kdown) // { // updatebookmark(true, false); // } - if (m_memoryDumpBookmark->size() == 0) - m_menuLocation = CHEATS; + + // if (m_memoryDumpBookmark->size() == 0) + // m_menuLocation = CHEATS; { m_memoryDump1 = m_memoryDump; @@ -1989,13 +2039,13 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntrySaveSR = m_selectedEntry; m_addresslist_offsetSaveSR = m_addresslist_offset; m_selectedEntry = m_selectedEntrySaveBM; - m_addresslist_offset = m_addresslist_offsetSaveBM; } + m_addresslist_offset = m_addresslist_offsetSaveBM; - if (m_memoryDump->size() == 0 && m_cheatCnt > 0) - { - m_menuLocation = CHEATS; - }; + // if (m_memoryDump->size() == 0 && m_cheatCnt > 0) + // { + // m_menuLocation = CHEATS; + // }; //consider to remove later if (m_searchType == SEARCH_TYPE_NONE) m_searchType = SEARCH_TYPE_UNSIGNED_32BIT; // to make sure not blank @@ -2014,11 +2064,17 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntrySaveBM = m_selectedEntry; m_addresslist_offsetSaveBM = m_addresslist_offset; m_selectedEntry = m_selectedEntrySaveSR; - m_addresslist_offset = m_addresslist_offsetSaveSR; } + m_addresslist_offset = m_addresslist_offsetSaveSR; // (new Snackbar("Switch to Normal List!"))->show(); } + + if (m_memoryDumpBookmark->size() == 0 && m_menuLocation == CANDIDATES && m_cheatCnt > 0) + { + m_selectedEntry = m_selectedEntrySaveCL; + m_menuLocation = CHEATS; + } printf("%s\n", "L key pressed"); // if (m_menuLocation == CANDIDATES) // m_selectedEntry = 0; @@ -5147,6 +5203,68 @@ bool GuiCheats::addcodetofile(u64 index) return true; } +bool GuiCheats::editcodefile() // not used work in progress +{ + std::stringstream buildIDStr; + std::stringstream filebuildIDStr; + { + for (u8 i = 0; i < 8; i++) + buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; + filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; + } + + std::stringstream realCheatPath; + { + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + realCheatPath << "/cheats/"; + realCheatPath << buildIDStr.str() << ".txt"; + } + + FILE *pfile; + pfile = fopen(realCheatPath.str().c_str(), "r+b"); + fseek(pfile, 0, SEEK_END); + u64 bufferSize = ftell(pfile); + u8 *s = new u8[bufferSize + 1]; + /* Read cheats into buffer. */ + fseek(pfile, 0, SEEK_SET); + fread(s, sizeof(bufferSize), 1, pfile); + s[bufferSize] = '\x00'; + { + size_t i = 0; + while (i < bufferSize) + { + if (std::isspace(static_cast(s[i]))) + { + /* Just ignore whitespace. */ + i++; + } + else if (s[i] == '[') + { + size_t j = i + 1; + while (s[j] != ']') + { + j++; + if (j >= bufferSize) + { + return false; + } + } + } + } + } + // WIP + pfile = fopen(filebuildIDStr.str().c_str(), "w+b"); + std::stringstream ss; + if (pfile != NULL) + { + ss.str(""); + fputs(ss.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on Edizon dir \n"); + return true; +} bool GuiCheats::reloadcheatsfromfile(u8 *buildID, u64 titleID) { @@ -5312,10 +5430,15 @@ void GuiCheats::reloadcheats() { if (m_cheats != nullptr) delete m_cheats; + if (m_cheatDelete != nullptr) + delete m_cheatDelete; dmntchtGetCheatCount(&m_cheatCnt); if (m_cheatCnt > 0) { m_cheats = new DmntCheatEntry[m_cheatCnt]; + m_cheatDelete = new bool[m_cheatCnt]; + for (u64 i = 0; i < m_cheatCnt; i++) + m_cheatDelete[i] = false; dmntchtGetCheats(m_cheats, m_cheatCnt, 0, &m_cheatCnt); } } @@ -5346,21 +5469,21 @@ bool GuiCheats::dumpcodetofile() buildIDStr << std::nouppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)m_buildID[i]; filebuildIDStr << EDIZON_DIR "/" << buildIDStr.str() << ".txt"; } - // std::stringstream realCheatPath; - // { - // realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); - // mkdir(realCheatPath.str().c_str(), 0777); - // realCheatPath << "/cheats/"; - // mkdir(realCheatPath.str().c_str(), 0777); - // realCheatPath << buildIDStr.str() << ".txt"; - // } + std::stringstream realCheatPath; + { + realCheatPath << "/atmosphere/contents/" << std::uppercase << std::hex << std::setfill('0') << std::setw(sizeof(u64) * 2) << m_debugger->getRunningApplicationTID(); + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << "/cheats/"; + mkdir(realCheatPath.str().c_str(), 0777); + realCheatPath << buildIDStr.str() << ".txt"; + } FILE *pfile; pfile = fopen(filebuildIDStr.str().c_str(), "w"); std::stringstream SS; std::stringstream ss; if (pfile != NULL) { - GuiCheats::reloadcheats(); + // GuiCheats::reloadcheats(); SS.str(""); for (u32 i = 0; i < m_cheatCnt; i++) { @@ -5468,14 +5591,14 @@ bool GuiCheats::dumpcodetofile() else printf("failed writing to cheat file on Edizon dir \n"); - // pfile = fopen(realCheatPath.str().c_str(), "w"); - // if (pfile != NULL) - // { - // fputs(ss.str().c_str(), pfile); - // fclose(pfile); - // } - // else - // printf("failed writing to cheat file on contents dir \n"); + pfile = fopen(realCheatPath.str().c_str(), "w"); + if (pfile != NULL) + { + fputs(SS.str().c_str(), pfile); + fclose(pfile); + } + else + printf("failed writing to cheat file on contents dir \n"); return true; } From d1d8e709547d99864ebba0df45add27c85eafd20 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:03:25 +0800 Subject: [PATCH 71/95] UI fix --- source/guis/gui_cheats.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index d9b396f6..2865a422 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -480,12 +480,12 @@ void GuiCheats::draw() if (m_memoryDump1 == nullptr) { Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE104 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); } else { Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE104 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); } } else if (m_memoryDump1 == nullptr) @@ -1142,6 +1142,7 @@ void GuiCheats::onInput(u32 kdown) u32 kheld = hidKeysHeld(CONTROLLER_PLAYER_1) | hidKeysHeld(CONTROLLER_HANDHELD); if (kdown & KEY_B) { + m_selectedEntry = 0; if (m_searchMenuLocation == SEARCH_NONE) { @@ -1344,7 +1345,7 @@ void GuiCheats::onInput(u32 kdown) // m_searchValue[0]._u64 = 0x1000000000; // m_searchValue[1]._u64 = 0x8000000000; } - if ((kdown & KEY_X) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) + if ((kdown & KEY_X) && (kheld & KEY_ZL)) { m_menuLocation = CANDIDATES; m_searchType = SEARCH_TYPE_UNSIGNED_64BIT; @@ -1604,7 +1605,7 @@ void GuiCheats::onInput(u32 kdown) { /* Candidates menu */ if (m_memoryDump->size() > 0) { - if (kdown & KEY_X && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + if (kdown & KEY_X && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR && !(kheld & KEY_ZL)) { u64 address = 0; m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &address, sizeof(u64)); From ab229259eea21e61823c7847e95f4a5e77b43a3f Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 18 Aug 2020 20:14:11 +0800 Subject: [PATCH 72/95] UI fix --- source/guis/gui_cheats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 2865a422..19962c96 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -504,7 +504,7 @@ void GuiCheats::draw() if (m_memoryDump->size() > 0) { Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE0E6+\uE0E1 Detach debugger \uE0E4 BM toggle \uE0E5 Hex Mode \uE0EF BM add \uE0F0 Reset search \uE0E3 Search again \uE0E2 Freeze value \uE0E0 Edit value \uE0E1 Quit", ALIGNED_RIGHT); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E7 Page Up \uE0E7 Page Down \uE105 Memory Editor", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search \uE0E6+\uE0E7 Page Up \uE0E7 Page Down \uE105 Memory Editor", ALIGNED_RIGHT); } else Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 50, currTheme.textColor, "\uE0F0 Reset search \uE0E1 Quit", ALIGNED_RIGHT); From 70c8db6827c7b473f1a14227d0dfcd9d6be0d9ed Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 21 Aug 2020 11:39:56 +0800 Subject: [PATCH 73/95] show conditional button --- include/guis/gui_cheats.hpp | 5 + source/guis/gui_cheats.cpp | 282 +++++++++++++++++++++++++++++++++++- 2 files changed, 281 insertions(+), 6 deletions(-) diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 2659685a..d680f700 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -63,6 +63,7 @@ class GuiCheats : public Gui SEARCH_REGION, SEARCH_VALUE, SEARCH_editRAM, + SEARCH_editRAM2, SEARCH_POINTER } m_searchMenuLocation = SEARCH_NONE; @@ -242,6 +243,10 @@ class GuiCheats : public Gui void drawSearchRAMMenu(); void drawEditRAMMenu(); + std::string buttonStr(u32 buttoncode); + void drawEditRAMMenu2(); + bool m_editCheat = false; + void editor_input(u32 kdown,u32 kheld); void drawSearchPointerMenu(); void searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 19962c96..c546aac6 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -26,6 +26,36 @@ }) static const std::vector dataTypes = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr"}; static const std::vector dataTypeSizes = {1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8}; +static const std::vector buttonNames = {"\uE0A0 ", "\uE0A1 ", "\uE0A2 ", "\uE0A3 ", "\uE0C4 ", "\uE0C5 ", "\uE0A4 ", "\uE0A5 ", "\uE0A6 ", "\uE0A7 ", "\uE0B3 ", "\uE0B4 ", "\uE0B1 ", "\uE0AF ", "\uE0B2 ", "\uE0B0 "}; +// static const std::vector buttonNames = {"\uE0A0", "\uE0A1", "\uE0A2", "\uE0A3", "\uE0C4", "\uE0C5", "\uE0A4", "\uE0A5", "\uE0A6", "\uE0A7", "\uE0B3", "\uE0B4", "\uE0B1", "\uE0AF", "\uE0B2", "\uE0B0"}; +// static const std::vector buttonNames = {"\uE0E0", "\uE0E1", "\uE0E2", "\uE0E3", "\uE104", "\uE105", "\uE0E4", "\uE0E5", "\uE0E6", "\uE0E7", "\uE0EF", "\uE0F0", "\uE0ED", "\uE0EB", "\uE0EE", "\uE0EC"}; +static const std::vector buttonCodes = {0x80000001, + 0x80000002, + 0x80000004, + 0x80000008, + 0x80000010, + 0x80000020, + 0x80000040, + 0x80000080, + 0x80000100, + 0x80000200, + 0x80000400, + 0x80000800, + 0x80001000, + 0x80002000, + 0x80004000, + 0x80008000}; + +// 0x80010000, +// 0x80020000, +// 0x80040000, +// 0x80080000, +// 0x80100000, +// 0x80200000, +// 0x80400000, +// 0x80800000, +// 0x81000000, +// 0x82000000}; static const std::vector dataTypeMaxValues = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; static const std::vector dataTypeMinValues = {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()}; @@ -479,12 +509,12 @@ void GuiCheats::draw() { if (m_memoryDump1 == nullptr) { - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE104 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE105 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); } else { - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE104 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0EF BM add \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE0EF BM add \uE105 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); } } @@ -639,7 +669,7 @@ void GuiCheats::draw() break; // WIP ss.str(""); - ss << "\uE070 " << (m_cheatDelete[line] ? " Press \uE104 to delete" : (m_cheats[line].definition.readable_name)); + ss << "\uE070 " << buttonStr(m_cheats[line].definition.opcodes[0]) << (m_cheatDelete[line] ? " Press \uE104 to delete" : (m_cheats[line].definition.readable_name)); Gui::drawRectangle(52, 300 + (line - cheatListOffset) * 40, 646, 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); Gui::drawTextAligned(font14, 70, 305 + (line - cheatListOffset) * 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -801,6 +831,7 @@ void GuiCheats::draw() drawSearchRAMMenu(); drawEditRAMMenu(); + drawEditRAMMenu2(); drawSearchPointerMenu(); Gui::endDraw(); } @@ -971,6 +1002,218 @@ void GuiCheats::drawEditRAMMenu() } } } +// WIP edit ram +std::string GuiCheats::buttonStr(u32 buttoncode) +{ + for (u32 i = 0; i < buttonCodes.size(); i++) + { + if (buttoncode == buttonCodes[i]) + return buttonNames[i].c_str(); + } + return ""; +} +void GuiCheats::drawEditRAMMenu2() +{ + std::stringstream ss; + if (m_searchMenuLocation != SEARCH_editRAM2) + return; + Gui::drawRectangle(0, 0, Gui::g_framebuffer_width, Gui::g_framebuffer_height, currTheme.backgroundColor); + Gui::drawRectangle(100, 135, Gui::g_framebuffer_width - 200, 1, currTheme.textColor); + Gui::drawText(font24, 120, 70, currTheme.textColor, "\uE132 Edit Memory 2"); + Gui::drawTextAligned(font20, 100, 160, currTheme.textColor, "\uE149 \uE0A4", ALIGNED_LEFT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 100, 160, currTheme.textColor, "\uE0A5 \uE14A", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, 260, 160, m_searchMenuLocation == SEARCH_TYPE ? currTheme.selectedColor : currTheme.textColor, "U8", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 510, 160, m_searchMenuLocation == SEARCH_MODE ? currTheme.selectedColor : currTheme.textColor, "U16", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 760, 160, m_searchMenuLocation == SEARCH_REGION ? currTheme.selectedColor : currTheme.textColor, "u32", ALIGNED_CENTER); + Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "u64", ALIGNED_CENTER); + u64 addr = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20; + u32 out; + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + ss.str(""); + ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << " ] " << dataTypes[m_searchType]; + Gui::drawText(font24, 520, 70, currTheme.textColor, ss.str().c_str()); + ss.str(""); + dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + Gui::drawText(font24, 830, 70, currTheme.textColor, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); //ss.str().c_str() + for (u8 i = 0; i < 40; i++) + { + if (m_selectedEntry == i) + Gui::drawRectangled(88 + (i % 5) * 225, 235 + (i / 5) * 50, 225, 50, m_searchMode == static_cast(i) ? currTheme.selectedColor : currTheme.highlightColor); + if ((i % 5) != 0) + { + Gui::drawRectangled(93 + (i % 5) * 225, 240 + (i / 5) * 50, 215, 40, currTheme.separatorColor); + ss.str(""); + dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; + Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + addr += 4; + } + else + { + ss.str(""); + ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (addr) << " ]"; + Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); + } + } + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 70, currTheme.textColor, "\uE0E4 \uE0E5 Change Mode \uE0E3 Goto address \uE0EF BM add \uE0E7 PageDown \uE0E0 Edit value \uE0E1 Back", ALIGNED_RIGHT); + Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E4 \uE0E6+\uE0E5 Change Type \uE0E6+\uE0E0 Follow \uE0E6+\uE0E7 PageUp \uE0E6+\uE0E1 Quit", ALIGNED_RIGHT); +} +void GuiCheats::editor_input(u32 kdown, u32 kheld) +{ + if (kdown & KEY_B && kheld & KEY_ZL) + { + m_selectedEntry = m_selectedEntrySave; + m_searchMenuLocation = SEARCH_NONE; + } + else if (kdown & KEY_UP) + { + if (m_selectedEntry > 4) + m_selectedEntry -= 5; + else + { + m_EditorBaseAddr -= 0x10; + } + } + else if (kdown & KEY_DOWN) + { + if (m_selectedEntry < 35) + m_selectedEntry += 5; + else + { + m_EditorBaseAddr += 0x10; + } + } + else if (kdown & KEY_LEFT) + { + if (m_selectedEntry % 5 > 1) + m_selectedEntry--; + } + else if (kdown & KEY_RIGHT) + { + if (m_selectedEntry % 5 < 4) + m_selectedEntry++; + } + else if (kdown & KEY_PLUS) // Add bookmark + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + bookmark_t bookmark; + if (address >= m_heapBaseAddr && address < m_heapEnd) + { + bookmark.offset = address - m_heapBaseAddr; + bookmark.heap = true; + } + else if (address >= m_mainBaseAddr && address < m_mainend) + { + bookmark.offset = address - m_mainBaseAddr; + bookmark.heap = false; + } + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + if (m_bookmark.pointer.depth > 0) + { + s64 offset = address - m_BookmarkAddr + m_bookmark.pointer.offset[0]; + if (offset >= 0 && offset < (s64)m_max_range) + { + memcpy(&(bookmark.pointer), &(m_bookmark.pointer), (m_bookmark.pointer.depth + 2) * 8); + bookmark.pointer.offset[0] = (u64)offset; + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + } + } + m_AttributeDumpBookmark->flushBuffer(); + m_memoryDumpBookmark->flushBuffer(); + (new Snackbar("Address added to bookmark!"))->show(); + printf("%s\n", "PLUS key pressed"); + } + else if (kdown & KEY_ZR && kheld & KEY_ZL) // Page Up + { + m_EditorBaseAddr -= 0x80; + } + else if (kdown & KEY_ZR) // Page down + { + m_EditorBaseAddr += 0x80; + } + else if (kdown & KEY_R && kheld & KEY_ZL) // change type + { + if (m_searchType < SEARCH_TYPE_FLOAT_64BIT) + { + u8 i = static_cast(m_searchType) + 1; + m_searchType = static_cast(i); + } + } + else if (kdown & KEY_L && kheld & KEY_ZL) // Chang type + { + if (m_searchType > SEARCH_TYPE_UNSIGNED_8BIT) + { + u8 i = static_cast(m_searchType) - 1; + m_searchType = static_cast(i); + } + } + else if (kdown & KEY_R) + { + } + else if (kdown & KEY_L) + { + } + else if (kdown & KEY_X) // Hex mode toggle + { + if (m_searchValueFormat == FORMAT_DEC) + m_searchValueFormat = FORMAT_HEX; + else + m_searchValueFormat = FORMAT_DEC; + } + else if (kdown & KEY_Y) // Goto + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + std::stringstream ss; + ss << "0x" << std::uppercase << std::hex << address; + char input[16]; + if (Gui::requestKeyboardInput("Enter Address", "Enter Address to add to bookmark .", ss.str(), SwkbdType_QWERTY, input, 18)) + { + address = static_cast(std::stoul(input, nullptr, 16)); + bookmark_t bookmark; + bookmark.type = m_searchType; + Gui::requestKeyboardInput("Enter Label", "Enter Label to add to bookmark .", "", SwkbdType_QWERTY, bookmark.label, 18); + m_AttributeDumpBookmark->addData((u8 *)&bookmark, sizeof(bookmark_t)); + m_AttributeDumpBookmark->flushBuffer(); + (new Snackbar("Address added to bookmark!"))->show(); + m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); + m_memoryDumpBookmark->flushBuffer(); + } + } + else if (kdown & KEY_A) + { + u64 address = m_EditorBaseAddr - (m_EditorBaseAddr % 16) - 0x20 + (m_selectedEntry - 1 - (m_selectedEntry / 5)) * 4 + m_addressmod; + char input[16]; + char initialString[21]; + strcpy(initialString, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); + if (Gui::requestKeyboardInput("Enter value", "Enter a value that should get written at this .", initialString, m_searchValueFormat == FORMAT_DEC ? SwkbdType_NumPad : SwkbdType_QWERTY, input, 18)) + { + if (m_searchValueFormat == FORMAT_HEX) + { + auto value = static_cast(std::stoul(input, nullptr, 16)); + m_debugger->writeMemory(&value, dataTypeSizes[m_searchType], address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_32BIT) + { + auto value = static_cast(std::atof(input)); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType == SEARCH_TYPE_FLOAT_64BIT) + { + auto value = std::atof(input); + m_debugger->writeMemory(&value, sizeof(value), address); + } + else if (m_searchType != SEARCH_TYPE_NONE) + { + auto value = std::atol(input); + m_debugger->writeMemory((void *)&value, dataTypeSizes[m_searchType], address); + } + } + } +} void GuiCheats::drawSearchRAMMenu() { @@ -1132,6 +1375,7 @@ void GuiCheats::drawSearchRAMMenu() break; case SEARCH_NONE: case SEARCH_editRAM: + case SEARCH_editRAM2: case SEARCH_POINTER: break; } @@ -1140,6 +1384,11 @@ void GuiCheats::drawSearchRAMMenu() void GuiCheats::onInput(u32 kdown) { u32 kheld = hidKeysHeld(CONTROLLER_PLAYER_1) | hidKeysHeld(CONTROLLER_HANDHELD); + if (m_searchMenuLocation == SEARCH_editRAM2) + { + editor_input(kdown, kheld); + return; + }; if (kdown & KEY_B) { m_selectedEntry = 0; @@ -1324,10 +1573,17 @@ void GuiCheats::onInput(u32 kdown) } } // start mod + if ((kdown & KEY_RSTICK) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) + { + m_editCheat = true; + + } if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) { // Edit cheats // WIP + // if (m_cheats[m_selectedEntry].definition.opcodes[0]) + for (u64 i = 0; i < m_cheatCnt; i++) if (m_cheatDelete[i]) { @@ -1715,7 +1971,7 @@ void GuiCheats::onInput(u32 kdown) // add bookmark end // show memory editor // BM1 - if (kdown & KEY_RSTICK && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + if (kdown & KEY_RSTICK && !(kheld & KEY_ZL) && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) { m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); m_BookmarkAddr = m_EditorBaseAddr; @@ -1724,6 +1980,16 @@ void GuiCheats::onInput(u32 kdown) m_selectedEntrySave = m_selectedEntry; m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; } + if (kdown & KEY_RSTICK && (kheld & KEY_ZL) && m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) + { + m_memoryDump->getData((m_selectedEntry + m_addresslist_offset) * sizeof(u64), &m_EditorBaseAddr, sizeof(u64)); + m_BookmarkAddr = m_EditorBaseAddr; + m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &m_bookmark, sizeof(bookmark_t)); + m_searchMenuLocation = SEARCH_editRAM2; + m_selectedEntrySave = m_selectedEntry; + m_selectedEntry = (m_EditorBaseAddr % 16) / 4 + 11; + } + if ((kdown & KEY_LSTICK) && (m_memoryDump->getDumpInfo().dumpType == DumpType::ADDR) && (m_memoryDump1 != nullptr)) { printf("start pointer search ....................\n"); @@ -2214,6 +2480,7 @@ void GuiCheats::onInput(u32 kdown) case SEARCH_NONE: case SEARCH_POINTER: break; + case SEARCH_editRAM2: case SEARCH_editRAM: // need UP if (m_selectedEntry > 4) m_selectedEntry -= 5; @@ -2247,6 +2514,7 @@ void GuiCheats::onInput(u32 kdown) case SEARCH_NONE: case SEARCH_POINTER: break; + case SEARCH_editRAM2: case SEARCH_editRAM: // need DOWN if (m_selectedEntry < 35) m_selectedEntry += 5; @@ -2278,6 +2546,7 @@ void GuiCheats::onInput(u32 kdown) case SEARCH_NONE: case SEARCH_POINTER: break; + case SEARCH_editRAM2: case SEARCH_editRAM: // need LEFT if (m_selectedEntry % 5 > 1) m_selectedEntry--; @@ -2304,6 +2573,7 @@ void GuiCheats::onInput(u32 kdown) case SEARCH_NONE: case SEARCH_POINTER: break; + case SEARCH_editRAM2: case SEARCH_editRAM: // need RIGHT if (m_selectedEntry % 5 < 4) m_selectedEntry++; @@ -2426,7 +2696,7 @@ void GuiCheats::onInput(u32 kdown) if (m_searchValueFormat == FORMAT_HEX) { auto value = static_cast(std::stoul(input, nullptr, 16)); - m_debugger->writeMemory(&value, sizeof(value), address); + m_debugger->writeMemory(&value, dataTypeSizes[m_searchType], address); } else if (m_searchType == SEARCH_TYPE_FLOAT_32BIT) { @@ -4399,7 +4669,7 @@ void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) printf("\n"); #endif - if (success && valuematch(value, address)) + if (success && (bookmark.pointer.depth > 4 || valuematch(value, address))) { bookmark.type = m_searchType; m_memoryDumpBookmark->addData((u8 *)&address, sizeof(u64)); From ec08aec927632da8f4747687127e95616cbef6d2 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 21 Aug 2020 14:24:25 +0800 Subject: [PATCH 74/95] simple conditional button add/ remove/ edit --- source/guis/gui_cheats.cpp | 92 +++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index c546aac6..d6c795e9 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -26,7 +26,7 @@ }) static const std::vector dataTypes = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "f32", "f64", "ptr"}; static const std::vector dataTypeSizes = {1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 8}; -static const std::vector buttonNames = {"\uE0A0 ", "\uE0A1 ", "\uE0A2 ", "\uE0A3 ", "\uE0C4 ", "\uE0C5 ", "\uE0A4 ", "\uE0A5 ", "\uE0A6 ", "\uE0A7 ", "\uE0B3 ", "\uE0B4 ", "\uE0B1 ", "\uE0AF ", "\uE0B2 ", "\uE0B0 "}; +static const std::vector buttonNames = {"\uE0A0 ", "\uE0A1 ", "\uE0A2 ", "\uE0A3 ", "\uE0C4 ", "\uE0C5 ", "\uE0A4 ", "\uE0A5 ", "\uE0A6 ", "\uE0A7 ", "\uE0B3 ", "\uE0B4 ", "\uE0B1 ", "\uE0AF ", "\uE0B2 ", "\uE0B0 ", "\uE091 ", "\uE092 ", "\uE090 ", "\uE093 ", "\uE145 ", "\uE143 ", "\uE146 ", "\uE144 "}; // static const std::vector buttonNames = {"\uE0A0", "\uE0A1", "\uE0A2", "\uE0A3", "\uE0C4", "\uE0C5", "\uE0A4", "\uE0A5", "\uE0A6", "\uE0A7", "\uE0B3", "\uE0B4", "\uE0B1", "\uE0AF", "\uE0B2", "\uE0B0"}; // static const std::vector buttonNames = {"\uE0E0", "\uE0E1", "\uE0E2", "\uE0E3", "\uE104", "\uE105", "\uE0E4", "\uE0E5", "\uE0E6", "\uE0E7", "\uE0EF", "\uE0F0", "\uE0ED", "\uE0EB", "\uE0EE", "\uE0EC"}; static const std::vector buttonCodes = {0x80000001, @@ -44,16 +44,15 @@ static const std::vector buttonCodes = {0x80000001, 0x80001000, 0x80002000, 0x80004000, - 0x80008000}; - -// 0x80010000, -// 0x80020000, -// 0x80040000, -// 0x80080000, -// 0x80100000, -// 0x80200000, -// 0x80400000, -// 0x80800000, + 0x80008000, + 0x80010000, + 0x80020000, + 0x80040000, + 0x80080000, + 0x80100000, + 0x80200000, + 0x80400000, + 0x80800000}; // 0x81000000, // 0x82000000}; static const std::vector dataTypeMaxValues = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; @@ -510,12 +509,12 @@ void GuiCheats::draw() if (m_memoryDump1 == nullptr) { Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE105 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE105 Remove condition key \uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); } else { Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 65, currTheme.textColor, "\uE0EF BM add \uE105 Modify \uE0F2 Delete \uE0E6+\uE104 Write to File \uE0E6+\uE0E1 Detach \uE0E4 BM toggle \uE0E3 Search RAM \uE0E0 Cheat on/off \uE0E1 Quit", ALIGNED_RIGHT); - Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); + Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 35, currTheme.textColor, "\uE0E6+\uE105 Remove condition key \uE0E6+\uE0E2 Preparation for pointer Search", ALIGNED_RIGHT); } } else if (m_memoryDump1 == nullptr) @@ -669,7 +668,7 @@ void GuiCheats::draw() break; // WIP ss.str(""); - ss << "\uE070 " << buttonStr(m_cheats[line].definition.opcodes[0]) << (m_cheatDelete[line] ? " Press \uE104 to delete" : (m_cheats[line].definition.readable_name)); + ss << "\uE070 " << buttonStr(m_cheats[line].definition.opcodes[0]) << ((m_editCheat && line == m_selectedEntry) ? "Press button for conditional execute" : (m_cheatDelete[line] ? " Press \uE104 to delete" : (m_cheats[line].definition.readable_name))); Gui::drawRectangle(52, 300 + (line - cheatListOffset) * 40, 646, 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? currTheme.highlightColor : line % 2 == 0 ? currTheme.backgroundColor : currTheme.separatorColor); Gui::drawTextAligned(font14, 70, 305 + (line - cheatListOffset) * 40, (m_selectedEntry == line && m_menuLocation == CHEATS) ? COLOR_BLACK : currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -1389,6 +1388,45 @@ void GuiCheats::onInput(u32 kdown) editor_input(kdown, kheld); return; }; + if (m_editCheat) + { + // printf("kdown = %x, kheld = %x\n", kdown, kheld); + u32 keycode = 0x80000000 | kdown; + if (buttonStr(keycode) != "") + { + // edit cheat + if ((m_cheats[m_selectedEntry].definition.opcodes[0] & 0xF0000000) == 0x80000000) + { + m_cheats[m_selectedEntry].definition.opcodes[0] = keycode; + } + else + { + if (m_cheats[m_selectedEntry].definition.num_opcodes < 0x100 + 2) + { + m_cheats[m_selectedEntry].definition.opcodes[m_cheats[m_selectedEntry].definition.num_opcodes + 1] = 0x20000000; + + for (u32 i = m_cheats[m_selectedEntry].definition.num_opcodes; i > 0; i--) + { + m_cheats[m_selectedEntry].definition.opcodes[i] = m_cheats[m_selectedEntry].definition.opcodes[i - 1]; + } + m_cheats[m_selectedEntry].definition.num_opcodes += 2; + m_cheats[m_selectedEntry].definition.opcodes[0] = keycode; + } + } + // insert cheat + for (u32 i = m_selectedEntry; i < m_cheatCnt; i++) + { + dmntchtRemoveCheat(m_cheats[i].cheat_id); + } + for (u32 i = m_selectedEntry; i < m_cheatCnt; i++) + { + u32 outid; + dmntchtAddCheat(&(m_cheats[i].definition), m_cheats[i].enabled, &outid); + } + }; + m_editCheat = false; + return; + } if (kdown & KEY_B) { m_selectedEntry = 0; @@ -1576,7 +1614,31 @@ void GuiCheats::onInput(u32 kdown) if ((kdown & KEY_RSTICK) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) { m_editCheat = true; - + while ((hidKeysHeld(CONTROLLER_PLAYER_1) | hidKeysHeld(CONTROLLER_HANDHELD)) != 0) + { + hidScanInput(); + } + } + if ((kdown & KEY_RSTICK) && m_menuLocation == CHEATS && (kheld & KEY_ZL)) + { // remove condition key + if ((m_cheats[m_selectedEntry].definition.opcodes[0] & 0xF0000000) == 0x80000000 && (m_cheats[m_selectedEntry].definition.opcodes[m_cheats[m_selectedEntry].definition.num_opcodes - 1] & 0xF0000000) == 0x20000000) + { + for (u32 i = 0; i < m_cheats[m_selectedEntry].definition.num_opcodes - 1; i++) + { + m_cheats[m_selectedEntry].definition.opcodes[i] = m_cheats[m_selectedEntry].definition.opcodes[i + 1]; + } + m_cheats[m_selectedEntry].definition.num_opcodes -= 2; + } + // insert cheat + for (u32 i = m_selectedEntry; i < m_cheatCnt; i++) + { + dmntchtRemoveCheat(m_cheats[i].cheat_id); + } + for (u32 i = m_selectedEntry; i < m_cheatCnt; i++) + { + u32 outid; + dmntchtAddCheat(&(m_cheats[i].definition), m_cheats[i].enabled, &outid); + } } if ((kdown & KEY_LSTICK) && m_menuLocation == CHEATS && !(kheld & KEY_ZL)) { From 405b3b49c8ca2fef3c65ca850d239766bbcb7b5a Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 21 Aug 2020 14:25:13 +0800 Subject: [PATCH 75/95] update version no. --- Makefile | 2 +- source/guis/gui_cheats.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1057952c..a51688b6 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 8 +VERSION_MICRO := 9 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index d6c795e9..45b5ab77 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -572,7 +572,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.6.8"; + ss << "EdiZon SE : 3.6.9"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size From b1e6256377893ab93b57602eb8a08a565af23fb6 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 21 Aug 2020 14:47:06 +0800 Subject: [PATCH 76/95] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30a933d8..ae97104f 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,10 @@ Here are the added features: 9. Export dump to PC app (forked from pointersearcher 0.4) for more powerful pointer chain search. 10. Import PC app search result for validation and testing. 11. Create dmnt cheat code from pointer chain found. +12. Ability to detach dmnt from game process. +13. Adding/Removing conditional button to cheat code. -PS: In app help on button combo currently don't show enough hints. Please refer to https://github.com/tomvita/EdiZon-SE/wiki for instructions on how to use the app. +PS: Please refer to https://github.com/tomvita/EdiZon-SE/wiki for instructions on how to use the app. From 6cfa20c3a2c817495a06fa4f9e19eeaf0faea35d Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 27 Aug 2020 08:38:53 +0800 Subject: [PATCH 77/95] Check total opcodes when toggling cheat --- Makefile | 2 +- source/guis/gui_cheats.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a51688b6..a9a5841c 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 6 -VERSION_MICRO := 9 +VERSION_MICRO := 10 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 45b5ab77..bf9445fd 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -572,7 +572,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.6.9"; + ss << "EdiZon SE : 3.6.10"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size @@ -2179,6 +2179,19 @@ void GuiCheats::onInput(u32 kdown) if (m_cheatCnt == 0) return; + // count total opcode + u32 opcodecount = m_cheats[m_selectedEntry].definition.num_opcodes; + for (u32 i = 0; i < m_cheatCnt; i++) + { + if (m_cheats[i].enabled) + opcodecount += m_cheats[i].definition.num_opcodes; + } + if (opcodecount > 0x400) + { + (new Snackbar("Total opcode count would exceed 1024!"))->show(); + return; + } + dmntchtToggleCheat(m_cheats[m_selectedEntry].cheat_id); u64 cheatCnt = 0; @@ -6135,6 +6148,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t time_t unixTime1 = time(NULL); printf("%s%lx\n", "Start Time primary search", unixTime1); + dmntchtPauseCheatProcess(); // printf("main %lx main end %lx heap %lx heap end %lx \n",m_mainBaseAddr, m_mainBaseAddr+m_mainSize, m_heapBaseAddr, m_heapBaseAddr+m_heapSize); for (MemoryInfo meminfo : memInfos) { @@ -6176,7 +6190,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); searchValue_t realValue = {0}; - for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + for (u32 i = 0; i < bufferSize; i += 4) { u64 address = meminfo.addr + offset + i; memset(&realValue, 0, 8); @@ -6235,6 +6249,7 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t delete PCDump; PCAttr->flushBuffer(); delete PCAttr; + dmntchtResumeCheatProcess(); // delete newstringDump; } // From 4e5e4074a77990b143aa5919af2e8f754f48832c Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 30 Aug 2020 10:38:23 +0800 Subject: [PATCH 78/95] enable 32 bit pointer mode --- Makefile | 4 +-- include/guis/gui_cheats.hpp | 1 + source/guis/gui_cheats.cpp | 57 +++++++++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index a9a5841c..0150549b 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,8 @@ include $(DEVKITPRO)/libnx/switch_rules # - /default_icon.jpg #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 -VERSION_MINOR := 6 -VERSION_MICRO := 10 +VERSION_MINOR := 7 +VERSION_MICRO := 0 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index d680f700..a31ffd9d 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -246,6 +246,7 @@ class GuiCheats : public Gui std::string buttonStr(u32 buttoncode); void drawEditRAMMenu2(); bool m_editCheat = false; + bool m_32bitmode = false; void editor_input(u32 kdown,u32 kheld); void drawSearchPointerMenu(); void searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index bf9445fd..f893fa47 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -162,6 +162,7 @@ GuiCheats::GuiCheats() : Gui() m_heapSize = 0; m_heapEnd = 0; m_mainend = 0; + u32 mod = 0; do { @@ -178,11 +179,18 @@ GuiCheats::GuiCheats() : Gui() m_heapEnd = meminfo.addr + meminfo.size; // turns out that m_heapEnd may not be same as m_heapBaseAddr + m_heapSize } - if (meminfo.type == MemType_CodeMutable) + if (meminfo.type == MemType_CodeMutable && mod == 2) { m_mainend = meminfo.addr + meminfo.size; // same for m_mainend not the same as m_mainBaseAddr + m_mainSize; } + if (meminfo.type == MemType_CodeStatic && meminfo.perm == Perm_Rx) + { + if (mod == 1) + m_mainBaseAddr = meminfo.addr; + mod++; + } + m_memoryInfo.push_back(meminfo); } while (lastAddr < meminfo.addr + meminfo.size); @@ -191,10 +199,15 @@ GuiCheats::GuiCheats() : Gui() // for some game heap info was very far off #endif + if (m_mainend < 0xFFFFFFFF && m_heapEnd < 0xFFFFFFFF) + m_32bitmode = true; + else + m_32bitmode = false; + for (MemoryInfo meminfo : m_memoryInfo) { - if (m_mainBaseAddr == 0x00 && (meminfo.type == MemType_CodeStatic)) - m_mainBaseAddr = meminfo.addr; + // if (m_mainBaseAddr == 0x00 && (meminfo.type == MemType_CodeStatic)) // wasn't executed since it isn't 0x00 but this code is getting wrong address + // m_mainBaseAddr = meminfo.addr; for (u64 addrOffset = meminfo.addr; addrOffset < meminfo.addr + meminfo.size; addrOffset += 0x20000000) { @@ -572,7 +585,9 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.6.10"; + ss << "EdiZon SE : 3.7.0"; + if (m_32bitmode) + ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); ss.str(""); ss << "BASE : 0x" << std::uppercase << std::setfill('0') << std::setw(10) << std::hex << m_addressSpaceBaseAddr; //metadata.address_space_extents.size @@ -623,7 +638,7 @@ void GuiCheats::draw() // printf("[%lx]", nextaddress); MemoryInfo meminfo = m_debugger->queryMemory(nextaddress); if (meminfo.perm == Perm_Rw) - m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + m_debugger->readMemory(&nextaddress, ((m_32bitmode) ? sizeof(u32) : sizeof(u64)), nextaddress); else { ss << "(*access denied*)"; @@ -790,7 +805,7 @@ void GuiCheats::draw() } } else - m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + m_debugger->readMemory(&nextaddress, ((m_32bitmode) ? sizeof(u32) : sizeof(u64)), nextaddress); else { updateaddress = false; @@ -1832,7 +1847,10 @@ void GuiCheats::onInput(u32 kdown) if (meminfo.perm == Perm_Rw) { address = nextaddress; - m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + if (m_32bitmode) + m_debugger->readMemory(&nextaddress, sizeof(u32), nextaddress); + else + m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); } else { @@ -3242,11 +3260,20 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); searchValue_t realValue = {0}; - for (u32 i = 0; i < bufferSize; i += dataTypeSizes[searchType]) + u32 inc_i; + if (searchMode == SEARCH_MODE_POINTER) + inc_i = 4; + else + inc_i = dataTypeSizes[searchType]; + + for (u32 i = 0; i < bufferSize; i += inc_i) { u64 address = meminfo.addr + offset + i; memset(&realValue, 0, 8); - memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + if (searchMode == SEARCH_MODE_POINTER && m_32bitmode) + memcpy(&realValue, buffer + i, 4); + else + memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); switch (searchMode) { @@ -4701,7 +4728,10 @@ void GuiCheats::rebasepointer(searchValue_t value) //struct bookmark_t bookmark) { u64 Address = meminfo.addr + offset + i; memset(&realValue, 0, 8); - memcpy(&realValue, buffer + i, sizeof(u64)); + if (m_32bitmode) + memcpy(&realValue, buffer + i, sizeof(u32)); + else + memcpy(&realValue, buffer + i, sizeof(u64)); if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd))) { @@ -6194,7 +6224,10 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t { u64 address = meminfo.addr + offset + i; memset(&realValue, 0, 8); - memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + if (m_32bitmode) + memcpy(&realValue, buffer + i, 4); //dataTypeSizes[searchType]); + else + memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); // if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) @@ -6371,7 +6404,7 @@ bool GuiCheats::unresolved(pointer_chain_t pointer) } else { - m_debugger->readMemory(&nextaddress, sizeof(u64), nextaddress); + m_debugger->readMemory(&nextaddress, ((m_32bitmode) ? sizeof(u32) : sizeof(u64)), nextaddress); printf("[(%lx)", nextaddress); } else From c59a688e3594b8b6907a491aa9c9c08eb6c24986 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 1 Sep 2020 11:37:33 +0800 Subject: [PATCH 79/95] support 32bit pointer for add cheat code to file --- Makefile | 2 +- source/guis/gui_cheats.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 0150549b..7647ff0d 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 0 +VERSION_MICRO := 1 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f893fa47..3f682747 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -585,7 +585,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.0"; + ss << "EdiZon SE : 3.7.1"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -5542,10 +5542,10 @@ bool GuiCheats::addcodetofile(u64 index) ss.str(""); ss << "[" << bookmark.label << "]" << "\n"; - ss << "580F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[bookmark.pointer.depth] << "\n"; + ss << ((m_32bitmode)? "540F0000 ":"580F0000 ") << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[bookmark.pointer.depth] << "\n"; for (int z = bookmark.pointer.depth - 1; z > 0; z--) { - ss << "580F1000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[z] << "\n"; + ss <<((m_32bitmode)? "540F1000 ":"580F1000 ") << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[z] << "\n"; } ss << "780F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[0] << "\n"; ss << "6" << dataTypeSizes[bookmark.type] + 0 << "0F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(16) << realvalue._u64 << "\n"; From 3282efde83306916fbe4c48cea668d092eb98e07 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 1 Sep 2020 17:05:44 +0800 Subject: [PATCH 80/95] Icon for ACNH --- Makefile | 2 +- include/guis/gui_cheats.hpp | 7 +++++-- source/guis/gui_cheats.cpp | 15 ++++++++++++--- source/helpers/save.cpp | 4 +++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 7647ff0d..6ee5306c 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 1 +VERSION_MICRO := 2 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index a31ffd9d..14a26b3c 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -140,7 +140,7 @@ class GuiCheats : public Gui #define MAX_POINTER_DEPTH 12 // up to 4 seems OK with forward only search took 94s. 215s for big dump #define MAX_POINTER_RANGE 0x2000 #define MAX_NUM_POINTER_OFFSET 30 -#define HAVESAVE m_havesave +#define HAVESAVE (Title::g_titles[m_debugger->getRunningApplicationTID()] != nullptr) //m_havesave bool m_havesave = true; void iconloadcheck(); void autoattachcheck(); @@ -235,6 +235,9 @@ class GuiCheats : public Gui u64 m_heapEnd = 0; u64 m_mainend = 0; u8 m_buildID[0x20]; + // NsApplicationControlData appControlData; + // std::string m_titleName; + // std::string m_versionString; DmntCheatEntry *m_cheats; u64 m_cheatCnt; @@ -247,7 +250,7 @@ class GuiCheats : public Gui void drawEditRAMMenu2(); bool m_editCheat = false; bool m_32bitmode = false; - void editor_input(u32 kdown,u32 kheld); + void editor_input(u32 kdown, u32 kheld); void drawSearchPointerMenu(); void searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t searchValue1, searchValue_t searchValue2, searchType_t searchType, diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 3f682747..f57dcabf 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -235,6 +235,15 @@ GuiCheats::GuiCheats() : Gui() } } } + //BM Begin title id and icon init + + // size_t appControlDataSize = 0; + // NacpLanguageEntry *languageEntry = nullptr; + // std::memset(&appControlData, 0x00, sizeof(NsApplicationControlData)); + // nsGetApplicationControlData(NsApplicationControlSource_Storage, m_debugger->getRunningApplicationTID(), &appControlData, sizeof(NsApplicationControlData), &appControlDataSize); + // nacpGetLanguageEntry(&appControlData.nacp, &languageEntry); + // m_titleName = std::string(languageEntry->name); + // m_versionString = std::string(appControlData.nacp.display_version); //BM Begin pointer search init @@ -585,7 +594,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.1"; + ss << "EdiZon SE : 3.7.2"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -5542,10 +5551,10 @@ bool GuiCheats::addcodetofile(u64 index) ss.str(""); ss << "[" << bookmark.label << "]" << "\n"; - ss << ((m_32bitmode)? "540F0000 ":"580F0000 ") << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[bookmark.pointer.depth] << "\n"; + ss << ((m_32bitmode) ? "540F0000 " : "580F0000 ") << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[bookmark.pointer.depth] << "\n"; for (int z = bookmark.pointer.depth - 1; z > 0; z--) { - ss <<((m_32bitmode)? "540F1000 ":"580F1000 ") << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[z] << "\n"; + ss << ((m_32bitmode) ? "540F1000 " : "580F1000 ") << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[z] << "\n"; } ss << "780F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << bookmark.pointer.offset[0] << "\n"; ss << "6" << dataTypeSizes[bookmark.type] + 0 << "0F0000 " << std::uppercase << std::hex << std::setfill('0') << std::setw(16) << realvalue._u64 << "\n"; diff --git a/source/helpers/save.cpp b/source/helpers/save.cpp index 5edc6eb3..0e25e800 100644 --- a/source/helpers/save.cpp +++ b/source/helpers/save.cpp @@ -176,9 +176,11 @@ Result _getSaveList(std::vector &saveInfoList) for (; R_SUCCEEDED(rc) && total_entries > 0; rc = fsSaveDataInfoReaderRead(&iterator, &info, 1, &total_entries)) { - if ((info.save_data_type == FsSaveDataType_Account) && (info.application_id == l_debugger->getRunningApplicationTID())) // hacked to get only the running title + if ((info.save_data_type == FsSaveDataType_Account) && (l_debugger->getRunningApplicationTID() != 0)) // hacked to get only the running title { + info.application_id = l_debugger->getRunningApplicationTID(); saveInfoList.push_back(info); + break; } else if ((info.save_data_type == FsSaveDataType_Account) && (l_debugger->getRunningApplicationTID() == 0)) // hacked to get only the running title { From ff25455062394a88f82edcf81cc046d108d7b35f Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 2 Sep 2020 14:57:55 +0800 Subject: [PATCH 81/95] show save for last title used only --- .vscode/c_cpp_properties.json | 2 +- Makefile | 2 +- include/guis/gui_guide.hpp | 2 +- include/helpers/config.hpp | 1 + romfs/guide/1/1/config.json | 13 +++---------- romfs/guide/1/1/text.txt | 26 +++++++++++++++++++------- source/guis/gui_about.cpp | 26 +++++++++++++------------- source/guis/gui_cheats.cpp | 6 ++++-- source/guis/gui_main.cpp | 2 +- source/helpers/save.cpp | 11 ++++++++++- source/main.cpp | 2 +- 11 files changed, 55 insertions(+), 38 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 6898775e..640e03bc 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,7 @@ "DEBUG", "SWITCH", "__SWITCH__", - "VERSION_STRING=\"3.1.0\"" + "VERSION_STRING=\"3.7.3\"" ], "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", diff --git a/Makefile b/Makefile index 6ee5306c..21d1de1e 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 2 +VERSION_MICRO := 3 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_guide.hpp b/include/guis/gui_guide.hpp index 62c76999..a7e2849c 100644 --- a/include/guis/gui_guide.hpp +++ b/include/guis/gui_guide.hpp @@ -6,7 +6,7 @@ #include #include -#define GUIDE_PAGE_CNT 10 +#define GUIDE_PAGE_CNT 1 class GuiGuide : public Gui { public: diff --git a/include/helpers/config.hpp b/include/helpers/config.hpp index 26a5e8b5..f3d93fa7 100644 --- a/include/helpers/config.hpp +++ b/include/helpers/config.hpp @@ -12,6 +12,7 @@ namespace Config { char magic[8]; bool hideSX; char latestCommit[40]; + u64 lasttitle = 0; } config_data_t; void readConfig(); diff --git a/romfs/guide/1/1/config.json b/romfs/guide/1/1/config.json index 68aa04bd..c52ce309 100644 --- a/romfs/guide/1/1/config.json +++ b/romfs/guide/1/1/config.json @@ -1,20 +1,13 @@ { "images" : [ - { - "title" : "", - "path" : "banner.bin", - "x" : 0, - "y" : 50, - "w" : 1280, - "h" : 348 - } + ], "text" : [ { - "title" : "Introduction", + "title" : "Introduction to EdiZon SE", "path" : "text.txt", "x" : 50, - "y" : 410 + "y" : 100 } ] } \ No newline at end of file diff --git a/romfs/guide/1/1/text.txt b/romfs/guide/1/1/text.txt index ccbb52e8..956e20d4 100644 --- a/romfs/guide/1/1/text.txt +++ b/romfs/guide/1/1/text.txt @@ -1,7 +1,19 @@ -EdiZon is a all-in-one Homebrew for save file management, save file editing, -memory manipulation and cheat management. This quick start guide will guide you -through all of the features EdiZon has to offer. - -If you have any questions about a topic that isn't covered in this guide (like for example -how to create your own save file editors or cheats) please visit EdiZon's GitHub -Readme and Wiki or join our Discord server. \ No newline at end of file +This fork is based on the foundation of EdiZon 3.1 nightly. The changes made are on the game memory hack aspect. + +Here are the added features: + Range search. + Compare with previous value search. + Bookmark memory location found. + Speed enhancement to make small integer value in first search practicle. + Bookmark adjust to changing main and heap start address on subsequent launch of the game. + Bookmark with pointer chain attached updates memory address dynamically when the chain is able to resolve into a valid memory address. + Extract memory address from dmnt cheat code and add it to bookmark for exploration of the memory location. + Rebase feature to extract potential pointer chain form dmnt cheat code made for previous version of the game. + In app pointer chain search for address on bookmark. + Export dump to PC app (forked from pointersearcher 0.4) for more powerful pointer chain search. + Import PC app search result for validation and testing. + Create dmnt cheat code from pointer chain found. + Ability to detach dmnt from game process. + Adding/Removing conditional button to cheat code. + +Please refer to https://github.com/tomvita/EdiZon-SE/wiki for instructions on how to use the app. \ No newline at end of file diff --git a/source/guis/gui_about.cpp b/source/guis/gui_about.cpp index 7bb21a0c..d1d0469a 100644 --- a/source/guis/gui_about.cpp +++ b/source/guis/gui_about.cpp @@ -50,28 +50,28 @@ void GuiAbout::draw() { else Gui::drawTextAligned(font20, Gui::g_framebuffer_width - 50, Gui::g_framebuffer_height - 51, currTheme.textColor, "\uE0E1 Back \uE0E0 OK", ALIGNED_RIGHT); - Gui::drawTextAligned(fontHuge, 100, 180, Gui::makeColor(0xFB, 0xA6, 0x15, 0xFF), "EdiZon v" VERSION_STRING, ALIGNED_LEFT); - Gui::drawTextAligned(font20, 130, 190, currTheme.separatorColor, "by WerWolv", ALIGNED_LEFT); + Gui::drawTextAligned(fontHuge, 100, 180, Gui::makeColor(0xFB, 0xA6, 0x15, 0xFF), "EdiZon SE v" VERSION_STRING, ALIGNED_LEFT); + Gui::drawTextAligned(font20, 130, 190, currTheme.separatorColor, "by Tomvita", ALIGNED_LEFT); - Gui::drawTextAligned(font14, 120, 250, currTheme.textColor, "Special thank to anybody who got involved into this project.", ALIGNED_LEFT); - Gui::drawTextAligned(font14, 120, 270, currTheme.textColor, "Especially to all the config/cheat developers that brought this project to life!", ALIGNED_LEFT); + Gui::drawTextAligned(font14, 120, 250, currTheme.textColor, "Special thank to WerWolv who made the original EdiZon and the help and advise he gave.", ALIGNED_LEFT); + // Gui::drawTextAligned(font14, 120, 270, currTheme.textColor, "Especially to all the config/cheat developers that brought this project to life!", ALIGNED_LEFT); - Gui::drawTextAligned(font14, 900, 250, Gui::makeColor(0x51, 0x97, 0xF0, 0xFF), "Twitter: https://twitter.com/WerWolv", ALIGNED_LEFT); - Gui::drawTextAligned(font14, 900, 275, Gui::makeColor(0x1A, 0x5E, 0xA7, 0xFF), "PayPal: https://werwolv.net/donate", ALIGNED_LEFT); + // Gui::drawTextAligned(font14, 900, 250, Gui::makeColor(0x51, 0x97, 0xF0, 0xFF), "Twitter: https://twitter.com/WerWolv", ALIGNED_LEFT); + // Gui::drawTextAligned(font14, 900, 275, Gui::makeColor(0x1A, 0x5E, 0xA7, 0xFF), "PayPal: https://werwolv.net/donate", ALIGNED_LEFT); Gui::drawRectangled(50, 350, Gui::g_framebuffer_width - 100, 250, currTheme.textColor); Gui::drawRectangled(51, 351, Gui::g_framebuffer_width - 102, updateAvailable ? 190 : 248, currTheme.backgroundColor); Gui::drawShadow(52, 352, Gui::g_framebuffer_width - 104, 248); - if (updateAvailable) - Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 555, currTheme.backgroundColor, "A update for EdiZon, save editor or cheat is available!", ALIGNED_CENTER); +// if (updateAvailable) +// Gui::drawTextAligned(font20, Gui::g_framebuffer_width / 2, 555, currTheme.backgroundColor, "A update for EdiZon SE is available!", ALIGNED_CENTER); - Gui::drawTextAligned(font20, 60, 360, currTheme.selectedColor, "EdiZon Update", ALIGNED_LEFT); +// Gui::drawTextAligned(font20, 60, 360, currTheme.selectedColor, "EdiZon SE Update", ALIGNED_LEFT); - Gui::drawTextAligned(font14, 80, 400, currTheme.textColor, std::string("Latest EdiZon version: " + (remoteVersion == "" ? "..." : remoteVersion)).c_str(), ALIGNED_LEFT); - Gui::drawTextAligned(font14, 80, 425, currTheme.textColor, std::string("Latest database commit: [ " + (remoteCommitSha == "" ? "..." : remoteCommitSha) + " ] ").c_str(), ALIGNED_LEFT); - Gui::drawTextAligned(font14, 90, 450, currTheme.separatorColor, (remoteCommitMessage == "" ? "..." : remoteCommitMessage.c_str()), ALIGNED_LEFT); +// Gui::drawTextAligned(font14, 80, 400, currTheme.textColor, std::string("Latest EdiZon SE version: " + (remoteVersion == "" ? "..." : remoteVersion)).c_str(), ALIGNED_LEFT); +// Gui::drawTextAligned(font14, 80, 425, currTheme.textColor, std::string("Latest database commit: [ " + (remoteCommitSha == "" ? "..." : remoteCommitSha) + " ] ").c_str(), ALIGNED_LEFT); +// Gui::drawTextAligned(font14, 90, 450, currTheme.separatorColor, (remoteCommitMessage == "" ? "..." : remoteCommitMessage.c_str()), ALIGNED_LEFT); Gui::endDraw(); } @@ -164,5 +164,5 @@ static void getVersionInfoAsync(void* args) { curl_easy_cleanup(curl); - updateAvailable = (strcmp(remoteCommitSha.c_str(), Config::getConfig()->latestCommit) != 0 && strcmp(remoteCommitSha.c_str(), "???") != 0); + // updateAvailable = (strcmp(remoteCommitSha.c_str(), Config::getConfig()->latestCommit) != 0 && strcmp(remoteCommitSha.c_str(), "???") != 0); } diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f57dcabf..4e268e52 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -8,7 +8,7 @@ #include #include "helpers/util.h" - +#include "helpers/config.hpp" #include "edizon_logo_bin.h" // #define checkheap // #define printpointerchain @@ -127,6 +127,8 @@ GuiCheats::GuiCheats() : Gui() // reloadcheatsfromfile(m_buildID, m_debugger->getRunningApplicationTID()); // dumpcodetofile(); iconloadcheck(); + Config::getConfig()->lasttitle = m_debugger->getRunningApplicationTID(); + Config::writeConfig(); dmntchtGetCheatCount(&m_cheatCnt); @@ -594,7 +596,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.2"; + ss << "EdiZon SE : 3.7.3"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); diff --git a/source/guis/gui_main.cpp b/source/guis/gui_main.cpp index e21b66a0..f1d59100 100644 --- a/source/guis/gui_main.cpp +++ b/source/guis/gui_main.cpp @@ -133,7 +133,7 @@ void GuiMain::draw() { Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 8, 3, currTheme.separatorColor, timeBuffer, ALIGNED_RIGHT); Gui::drawTextAligned(font14, Gui::g_framebuffer_width - 80, 3, currTheme.separatorColor, batteryBuffer, ALIGNED_RIGHT); - Gui::drawTextAligned(font14, 8, 3, currTheme.separatorColor, "EdiZon v" VERSION_STRING, ALIGNED_LEFT); + Gui::drawTextAligned(font14, 8, 3, currTheme.separatorColor, "EdiZon SE v" VERSION_STRING, ALIGNED_LEFT); Gui::drawRectangled(Gui::g_framebuffer_width - 72, 5, 7, 18, currTheme.separatorColor); Gui::drawRectangled(Gui::g_framebuffer_width - 75, 8, 13, 18, currTheme.separatorColor); diff --git a/source/helpers/save.cpp b/source/helpers/save.cpp index 0e25e800..6ef461d3 100644 --- a/source/helpers/save.cpp +++ b/source/helpers/save.cpp @@ -7,6 +7,7 @@ #include "helpers/account.hpp" #include "helpers/title.hpp" #include "helpers/debugger.hpp" +#include "helpers/config.hpp" using json = nlohmann::json; s32 deleteDirRecursively(const char *path, bool isSave) @@ -182,10 +183,18 @@ Result _getSaveList(std::vector &saveInfoList) saveInfoList.push_back(info); break; } + else if ((info.save_data_type == FsSaveDataType_Account) && (Config::getConfig()->lasttitle) != 0 ) + { + if (info.application_id == Config::getConfig()->lasttitle) + { + saveInfoList.push_back(info); + break; + } + } else if ((info.save_data_type == FsSaveDataType_Account) && (l_debugger->getRunningApplicationTID() == 0)) // hacked to get only the running title { saveInfoList.push_back(info); - } + } } fsSaveDataInfoReaderClose(&iterator); diff --git a/source/main.cpp b/source/main.cpp index 40e66b87..8c869b7a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -214,13 +214,13 @@ int main(int argc, char **argv) currGui->draw(); } + Config::readConfig(); initTitles(); printf("%s\n", EDIZON_DIR); createFolders(); - Config::readConfig(); if (isServiceRunning("tx") && !isServiceRunning("rnx") && !Config::getConfig()->hideSX) From dc01c40e51fed98c24d0c666f6dee5a892d65e1e Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 2 Sep 2020 15:28:53 +0800 Subject: [PATCH 82/95] bug fix --- source/guis/gui_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/guis/gui_main.cpp b/source/guis/gui_main.cpp index f1d59100..005fe4e7 100644 --- a/source/guis/gui_main.cpp +++ b/source/guis/gui_main.cpp @@ -226,6 +226,8 @@ void GuiMain::onInput(u32 kdown) { if ((m_selected.titleIndex % 2) == 0) { if (static_cast(m_selected.titleIndex + 1) < ((!m_editableOnly) ? Title::g_titles.size() : EditorConfigParser::g_editableTitles.size())) m_selected.titleIndex++; + else + m_selected.extraOption = 0; } else { if (m_selected.titleIndex < (std::ceil(xOffset / 256.0F) * 2 + 4)) m_selected.extraOption = 0; From 3a21c4d01644a6ba8c7f5fd8587f6918363e9d21 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 10 Sep 2020 10:42:04 +0800 Subject: [PATCH 83/95] PC dump with compression --- .vscode/c_cpp_properties.json | 2 +- Makefile | 2 +- include/guis/gui_cheats.hpp | 1 + include/helpers/memory_dump.hpp | 2 + include/lz.h | 5 ++ source/guis/gui_cheats.cpp | 48 ++++++++++++++- source/guis/lz.cpp | 101 ++++++++++++++++++++++++++++++++ source/helpers/memory_dump.cpp | 28 ++++++++- 8 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 include/lz.h create mode 100644 source/guis/lz.cpp diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 640e03bc..0f98cf59 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,7 @@ "DEBUG", "SWITCH", "__SWITCH__", - "VERSION_STRING=\"3.7.3\"" + "VERSION_STRING=\"3.7.4\"" ], "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", diff --git a/Makefile b/Makefile index 21d1de1e..bbe5275f 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 3 +VERSION_MICRO := 4 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 14a26b3c..92b4a657 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -144,6 +144,7 @@ class GuiCheats : public Gui bool m_havesave = true; void iconloadcheck(); void autoattachcheck(); + void testlz(); struct PointerSearch_state { u64 depth = 0; // depth and index[depth] is where the search is at, pointersearch2 will increment depth and call itself with nexttarget diff --git a/include/helpers/memory_dump.hpp b/include/helpers/memory_dump.hpp index c201fb6a..3318a676 100644 --- a/include/helpers/memory_dump.hpp +++ b/include/helpers/memory_dump.hpp @@ -5,6 +5,7 @@ #include #include extern bool print_details; +// extern bool m_compress = false; class MemoryDump { public: @@ -26,6 +27,7 @@ class MemoryDump void setDumpType(enum DumpType dumpType); void flushBuffer(); + bool m_compress = false; private: FILE *m_dumpFile; diff --git a/include/lz.h b/include/lz.h new file mode 100644 index 00000000..49893cf7 --- /dev/null +++ b/include/lz.h @@ -0,0 +1,5 @@ +// #include + +// bool m_compress = false; +int LZ_Compress(const unsigned char *in, unsigned char *out, unsigned int insize); +int LZ_Uncompress(const unsigned char *in, unsigned char *out, unsigned int insize); diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 4e268e52..d7a9fe06 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -10,6 +10,7 @@ #include "helpers/util.h" #include "helpers/config.hpp" #include "edizon_logo_bin.h" +#include "lz.h" // #define checkheap // #define printpointerchain #define MAX_BUFFER_SIZE 0x1000000 // increase size for faster speed @@ -596,7 +597,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.3"; + ss << "EdiZon SE : 3.7.4"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -5846,6 +5847,46 @@ void GuiCheats::autoattachcheck() { dmntchtForceOpenCheatProcess(); } + // testlz(); +} +void GuiCheats::testlz() +{ + time_t unixTime1 = time(NULL); + std::stringstream filenoiconStr; + filenoiconStr << EDIZON_DIR "/ff756020d95b3ec5.dmp2"; + MemoryDump *PCDump,*PCDump2; + u64 bufferSize = 0x1000000; + u8 *buffer = new u8[bufferSize]; + u8 *outbuffer = new u8[bufferSize + 0x50000]; + PCDump = new MemoryDump(filenoiconStr.str().c_str(), DumpType::DATA, false); + filenoiconStr << "a"; + PCDump2 = new MemoryDump(filenoiconStr.str().c_str(), DumpType::DATA, true); + u64 S = PCDump->size(); + u64 total = 0; + for (u64 index = 0; index < S;) + { + if ((S - index) < bufferSize) + bufferSize = S - index; + PCDump->getData(index, buffer, bufferSize); + printf("Start LZ \n"); + u64 count = LZ_Compress(buffer, outbuffer, bufferSize); + PCDump2->addData((u8*)&count, sizeof(count)); + PCDump2->addData(outbuffer, count); + + float r = (float)count / (float)bufferSize; + printf("Index = %lx , End LZ bufferSize = %lx , outsize = %x , ration = %f\n",index, bufferSize, count, r); + index += bufferSize; + total +=count; + } + delete buffer; + delete outbuffer; + time_t unixTime2 = time(NULL); + printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + float r = (float) total / (float) S; + printf("Size = %lx , outsize = %x , ration = %f\n", S, total, r); + delete PCDump; + PCDump2->flushBuffer(); + delete PCDump2; } bool GuiCheats::dumpcodetofile() { @@ -6184,7 +6225,8 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t PCDump->addData((u8 *)&m_heapBaseAddr, sizeof(u64)); PCDump->addData((u8 *)&m_heapEnd, sizeof(u64)); PCDump->addData((u8 *)&m_EditorBaseAddr, sizeof(u64)); // first entry is the target address - + PCDump->flushBuffer(); + PCDump->m_compress = true; bool ledOn = false; time_t unixTime1 = time(NULL); @@ -6289,6 +6331,8 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t time_t unixTime2 = time(NULL); printf("%s%lx\n", "Stop Time ", unixTime2); printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); + if (PCDump->m_compress) + printf("mcompress = true\n"); PCDump->flushBuffer(); delete PCDump; PCAttr->flushBuffer(); diff --git a/source/guis/lz.cpp b/source/guis/lz.cpp new file mode 100644 index 00000000..bfe498b8 --- /dev/null +++ b/source/guis/lz.cpp @@ -0,0 +1,101 @@ +// #include +// #include "pch.h" +#include +//#include +typedef uint64_t u64; +/************************************************************************* +* LZ_Compress() - Compress a block of data using an LZ8 coder. +* in - Input (uncompressed) buffer. +* out - Output (compressed) buffer. This buffer must be 1/8 larger +* than the input buffer to cater for the worst case. +* insize - Number of input bytes. +* The function returns the size of the compressed data. +*************************************************************************/ +int LZ_Compress(const unsigned char *in, unsigned char *out, unsigned int insize) { + unsigned int inpos, outpos; + struct marker_t { + unsigned char back : 4; + unsigned char front : 4; + } marker = {0}; +#define MAXRANGE 16 + if (insize < 1) { + return 0; + } + inpos = 0; + outpos = 0; + do { + marker.front = 8; + for (int front = 0; front <= 8; front++) { + for (unsigned int back = 1; back <= MAXRANGE; back++) { + if (inpos < back * 8) { + break; + } + if ((*(u64 *)(&in[inpos - back * 8]) & (0xFFFFFFFFFFFFFFFF << 8 * front)) == (*(u64 *)(&in[inpos]) & (0xFFFFFFFFFFFFFFFF << 8 * front))) { + marker.front = front; + marker.back = back - 1; + front = 8; + break; + } + } + } + out[outpos] = *(unsigned char *)(&marker); + outpos += sizeof(marker_t); + *(unsigned long long *)(&out[outpos]) = *(unsigned long long *)(&in[inpos]); + outpos += marker.front; + inpos += 8; + } while (inpos < MAXRANGE*8); + do { + marker.front = 8; + for (int front = 0; front <= 8; front++) { + for (unsigned int back = 1; back <= MAXRANGE; back++) { + //if (inpos < back * 8) { + // break; + //} + if ((*(u64*)(&in[inpos - back * 8]) & (0xFFFFFFFFFFFFFFFF << 8 * front)) == (*(u64*)(&in[inpos]) & (0xFFFFFFFFFFFFFFFF << 8 * front))) { + marker.front = front; + marker.back = back - 1; + front = 8; + break; + } + } + } + out[outpos] = *(unsigned char*)(&marker); + outpos += sizeof(marker_t); + *(unsigned long long*)(&out[outpos]) = *(unsigned long long*)(&in[inpos]); + outpos += marker.front; + inpos += 8; + } while (inpos < insize); + return outpos; +} +/************************************************************************* +* LZ_Uncompress() - Uncompress a block of data using an LZ8 decoder. +* in - Input (compressed) buffer. +* out - Output (uncompressed) buffer. This buffer must be large +* enough to hold the uncompressed data. +* insize - Number of input bytes. +**************************************************************************/ +int LZ_Uncompress(const unsigned char *in, unsigned char *out, unsigned int insize) { + unsigned int inpos, outpos; + struct marker_t { + unsigned char back : 4; + unsigned char front : 4; + } marker = {0}; + if (insize < 1) { + return 0; + } + //marker = *(marker_t *)(&in[0]); + inpos = 0; + outpos = 0; + do { + marker = *(marker_t *)(&in[inpos]); + inpos++; + if (marker.front == 8) { + *(u64 *)(&out[outpos]) = *(u64 *)(&in[inpos]); + } else { + *(u64 *)(&out[outpos]) = (*(u64 *)(&in[inpos]) & ~(0xFFFFFFFFFFFFFFFF << (8 * marker.front))) | (*(u64 *)(&out[outpos - (marker.back + 1) * 8]) & (0xFFFFFFFFFFFFFFFF << (8 * marker.front))); + } + inpos += marker.front; + outpos += 8; + } while (inpos < insize); + return outpos; +} diff --git a/source/helpers/memory_dump.cpp b/source/helpers/memory_dump.cpp index b5fe8336..063295b6 100644 --- a/source/helpers/memory_dump.cpp +++ b/source/helpers/memory_dump.cpp @@ -1,5 +1,6 @@ #include "helpers/memory_dump.hpp" #include +#include "lz.h" // // #include "guis/gui_cheats.hpp" @@ -23,7 +24,6 @@ bool print_details = false; MemoryDump::MemoryDump(std::string filePath, DumpType dumpType, bool discardFile) : m_filePath(filePath) { m_dataHeader = {0}; - m_dataHeader.magic = 0x4E5A4445; m_dataHeader.endOfHeader = '@'; m_dataHeader.dumpType = (char)dumpType; @@ -130,7 +130,18 @@ void MemoryDump::addData(u8 *buffer, size_t dataSize) MemoryDump::flushBuffer(); fseek(m_dumpFile, 0, SEEK_END); // read shouldn't this come after flushbuffer?? - fwrite(buffer, sizeof(u8), dataSize, m_dumpFile); + if (m_compress) + { + // u8 *cbuffer = new u8[BUFFER_SIZE * 9 / 8 + 4]; + // *(u32 *)&cbuffer[0] = LZ_Compress(buffer, &cbuffer[4], dataSize); + // fwrite(cbuffer, sizeof(u8), *(u32 *)&cbuffer[0], m_dumpFile); + u8 *cbuffer = new u8[m_data.size() * 9 / 8]; + int csize = LZ_Compress(&m_data[0], cbuffer, m_data.size()); + fwrite(cbuffer, sizeof(u8), csize, m_dumpFile); + delete cbuffer; + } + else + fwrite(buffer, sizeof(u8), dataSize, m_dumpFile); m_dataHeader.dataSize += dataSize; MemoryDump::writeHeader(); // Maybe implement this section directly to avoid extra flashbuffer, seek, writeheader } @@ -225,7 +236,16 @@ void MemoryDump::flushBuffer() if (m_data.size() > 0 && isFileOpen()) { fseek(m_dumpFile, 0, SEEK_END); - fwrite(&m_data[0], sizeof(u8), m_data.size(), m_dumpFile); + if (m_compress) + { + u8 *cbuffer = new u8[m_data.size() * 9 / 8 ]; + int csize = LZ_Compress(&m_data[0], cbuffer, m_data.size()); + fwrite(cbuffer, sizeof(u8), csize , m_dumpFile); + delete cbuffer; + printf("mcompress\n"); + } + else + fwrite(&m_data[0], sizeof(u8), m_data.size(), m_dumpFile); m_dataHeader.dataSize += m_data.size(); @@ -239,6 +259,8 @@ void MemoryDump::writeHeader() { if (isFileOpen()) { + if (m_compress) + m_dataHeader.magic = 0x4E5A4665; fseek(m_dumpFile, 0, SEEK_SET); fwrite(&m_dataHeader, sizeof(m_dataHeader), 1, m_dumpFile); fflush(m_dumpFile); From 7bc9412e19baafd360c0aec071ab515d9fd7498e Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 18 Sep 2020 12:28:32 +0800 Subject: [PATCH 84/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae97104f..58cd5b5a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Here are the added features: PS: Please refer to https://github.com/tomvita/EdiZon-SE/wiki for instructions on how to use the app. - +To establish common base for support please start from a clean boot with the latest atmosphere and only Sigpatches needed to run the game and latest releases from https://github.com/tomvita. Please state the url you downloaded from. No extra software unless it is related to the topic underdiscussoin. Original functinality of Edizon on game save is available when launched without a game running. From d64fc282aa53313588c2484658a927da46b0b940 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 19 Sep 2020 10:41:21 +0800 Subject: [PATCH 85/95] fixed title info for mario 3d --- Makefile | 2 +- source/guis/gui_cheats.cpp | 6 +++--- source/helpers/title.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index bbe5275f..9dafdf58 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 4 +VERSION_MICRO := 4a NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index d7a9fe06..f98aeef2 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -597,7 +597,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.4"; + ss << "EdiZon SE : 3.7.4a"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -5874,7 +5874,7 @@ void GuiCheats::testlz() PCDump2->addData(outbuffer, count); float r = (float)count / (float)bufferSize; - printf("Index = %lx , End LZ bufferSize = %lx , outsize = %x , ration = %f\n",index, bufferSize, count, r); + printf("Index = %lx , End LZ bufferSize = %lx , outsize = %lx , ration = %f\n",index, bufferSize, count, r); index += bufferSize; total +=count; } @@ -5883,7 +5883,7 @@ void GuiCheats::testlz() time_t unixTime2 = time(NULL); printf("%s%ld\n", "Stop Time ", unixTime2 - unixTime1); float r = (float) total / (float) S; - printf("Size = %lx , outsize = %x , ration = %f\n", S, total, r); + printf("Size = %lx , outsize = %lx , ration = %f\n", S, total, r); delete PCDump; PCDump2->flushBuffer(); delete PCDump2; diff --git a/source/helpers/title.cpp b/source/helpers/title.cpp index ffbc3332..6c9a21c4 100644 --- a/source/helpers/title.cpp +++ b/source/helpers/title.cpp @@ -18,7 +18,7 @@ Title::Title(FsSaveDataInfo& saveInfo) { } memset(buf.get(), 0, sizeof(NsApplicationControlData)); - rc = nsGetApplicationControlData(NsApplicationControlSource_Storage, saveInfo.application_id, buf.get(), sizeof(NsApplicationControlData), &outsize); + rc = nsGetApplicationControlData(NsApplicationControlSource_Storage, saveInfo.application_id & 0xFFFFFFFFFFFFFFF0, buf.get(), sizeof(NsApplicationControlData), &outsize); if (R_FAILED(rc)) { m_errorCode = 2; return; From 6fb2147c695f226d937f9ecdc38179c35257669b Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 25 Sep 2020 12:31:31 +0800 Subject: [PATCH 86/95] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 58cd5b5a..917fd32a 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ To establish common base for support please start from a clean boot with the lat Original functinality of Edizon on game save is available when launched without a game running. -


- Latest Release +


+ Latest Release Discord Server Build Status

From ead8118e7d1c7977dff4e1bc4159f529b24c17d1 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Fri, 25 Sep 2020 12:42:34 +0800 Subject: [PATCH 87/95] Update README.md --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 917fd32a..6a786623 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,11 @@ Original functinality of Edizon on game save is available when launched without


Latest Release - Discord Server - Build Status + +

- -A Homebrew save file dumper, injector and on-console editor for Horizon, the OS of the Nintendo Switch. -Please note if you are using Atmosphere 0.10.0+, you **must** use the snapshot version of EdiZon. Older versions of EdiZon do **not** work on the latest Atmosphere. + +The following is the original readme the first two part is mostly unmodified except now you only see the save game functionality if you enter when no game is running and only the last game is display if there was a last game. To see all the games enter into "cheat" when no game is running and the next time EdiZon SE is launched all the game save will appear. # Overview EdiZon consists of 3 different main functionalities. From c0eb70006db077d09b3c41cb735da59cd8b8eed6 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 26 Sep 2020 15:43:28 +0800 Subject: [PATCH 88/95] envIsSyscallHinted --- .vscode/c_cpp_properties.json | 2 +- Makefile | 2 +- include/guis/gui_cheats.hpp | 2 +- include/helpers/debugger.hpp | 7 ++-- source/guis/gui_cheats.cpp | 77 ++++++++++++++++++++++++++++------- source/helpers/debugger.cpp | 66 ++++++++++++++++++++++++++---- 6 files changed, 129 insertions(+), 27 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 0f98cf59..4ec84bbe 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,7 @@ "DEBUG", "SWITCH", "__SWITCH__", - "VERSION_STRING=\"3.7.4\"" + "VERSION_STRING=\"3.7.5\"" ], "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", diff --git a/Makefile b/Makefile index 9dafdf58..6a97fd61 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 4a +VERSION_MICRO := 5 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/include/guis/gui_cheats.hpp b/include/guis/gui_cheats.hpp index 92b4a657..40877ed1 100644 --- a/include/guis/gui_cheats.hpp +++ b/include/guis/gui_cheats.hpp @@ -143,7 +143,7 @@ class GuiCheats : public Gui #define HAVESAVE (Title::g_titles[m_debugger->getRunningApplicationTID()] != nullptr) //m_havesave bool m_havesave = true; void iconloadcheck(); - void autoattachcheck(); + bool autoattachcheck(); void testlz(); struct PointerSearch_state { diff --git a/include/helpers/debugger.hpp b/include/helpers/debugger.hpp index 9c5afd22..08a7978c 100644 --- a/include/helpers/debugger.hpp +++ b/include/helpers/debugger.hpp @@ -8,10 +8,12 @@ class Debugger { ~Debugger(); Result attachToProcess(); - + void detatch(); u64 getRunningApplicationTID(); u64 getRunningApplicationPID(); - + bool m_dmnt = true; + Result m_rc = 0; + Handle m_debugHandle = 0; // no action to be taken to attach u64 peekMemory(u64 address); Result pokeMemory(size_t varSize, u64 address, u64 value); MemoryInfo queryMemory(u64 address); @@ -19,6 +21,5 @@ class Debugger { Result writeMemory(void *buffer, size_t bufferSize, u64 address); private: - Handle m_debugHandle; u64 m_tid = 0, m_pid = 0; }; \ No newline at end of file diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f98aeef2..54c6a208 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -75,7 +75,15 @@ GuiCheats::GuiCheats() : Gui() // Check if dmnt:cht is running and we're not on sxos m_sysmodulePresent = isServiceRunning("dmnt:cht") && !(isServiceRunning("tx") && !isServiceRunning("rnx")); + // dmntchtForceOpenCheatProcess(); + // dmntchtPauseCheatProcess(); m_debugger = new Debugger(); + dmntchtInitialize(); + if (!autoattachcheck()) + m_debugger->attachToProcess(); + if (!m_debugger->m_dmnt) { m_sysmodulePresent = true; } + // printf(" envIsSyscallHinted(0x60) = %d \n",envIsSyscallHinted(0x60)); + // printf("init debugger success m_rc = %x m_debugHandle = %x m_dmnt = %x\n",(u32) m_debugger->m_rc, m_debugger->m_debugHandle, m_debugger->m_dmnt); m_cheats = nullptr; m_memoryDump = nullptr; // start mod bookmark; @@ -94,13 +102,32 @@ GuiCheats::GuiCheats() : Gui() if (!m_sysmodulePresent) return; - dmntchtInitialize(); - // dmntchtForceOpenCheatProcess(); - autoattachcheck(); - // dmntchtPauseCheatProcess(); DmntCheatProcessMetadata metadata; - dmntchtGetCheatProcessMetadata(&metadata); + if (m_debugger->m_dmnt) + dmntchtGetCheatProcessMetadata(&metadata); + else + { + LoaderModuleInfo proc_modules[2] = {}; + s32 num_modules=2; + ldrDmntInitialize(); + Result rc = ldrDmntGetProcessModuleInfo(m_debugger->getRunningApplicationPID(), proc_modules, std::size(proc_modules), &num_modules); + ldrDmntExit(); + const LoaderModuleInfo *proc_module = nullptr; + if (num_modules == 2) + { + proc_module = &proc_modules[1]; + } + else if (num_modules == 1) + { + proc_module = &proc_modules[0]; + } + if (rc != 0) + printf("num_modules = %x, proc_module->base_address = %lx , pid = %ld, rc = %x\n ", num_modules, proc_module->base_address, m_debugger->getRunningApplicationPID(), rc); + metadata.main_nso_extents.base = proc_module->base_address; + metadata.main_nso_extents.size = proc_module->size; + std::memcpy(metadata.main_nso_build_id, proc_module->build_id, sizeof((metadata.main_nso_build_id))); + }; m_addressSpaceBaseAddr = metadata.address_space_extents.base; m_addressSpaceSize = metadata.address_space_extents.size; @@ -197,6 +224,15 @@ GuiCheats::GuiCheats() : Gui() m_memoryInfo.push_back(meminfo); } while (lastAddr < meminfo.addr + meminfo.size); +if (!(m_debugger->m_dmnt)){ + + m_addressSpaceBaseAddr = metadata.main_nso_extents.base; + m_addressSpaceSize = metadata.main_nso_extents.size; + m_EditorBaseAddr = m_heapBaseAddr; + m_heapSize = m_heapEnd-m_heapBaseAddr; + m_mainSize = m_mainend-m_mainBaseAddr; +} + #ifdef checkheap printf("m_heapBaseAddr = %lx m_heapSize = %lx m_heapEnd = %lx m_mainend =%lx\n", m_heapBaseAddr, m_heapSize, m_heapEnd, m_mainend); // for some game heap info was very far off @@ -597,7 +633,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.4a"; + ss << "EdiZon SE : 3.7.5"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -1003,7 +1039,8 @@ void GuiCheats::drawEditRAMMenu() Gui::drawText(font24, 520, 70, currTheme.textColor, ss.str().c_str()); // Next to display the value in the selected type now is u32 in hex ss.str(""); - dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + // dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + m_debugger->readMemory(&out, sizeof(u32), address); // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; Gui::drawText(font24, 820, 70, currTheme.textColor, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); //ss.str().c_str() @@ -1015,7 +1052,8 @@ void GuiCheats::drawEditRAMMenu() { Gui::drawRectangled(93 + (i % 5) * 225, 240 + (i / 5) * 50, 215, 40, currTheme.separatorColor); ss.str(""); - dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + // dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + m_debugger->readMemory(&out, sizeof(u32), addr); ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); addr += 4; @@ -1059,7 +1097,8 @@ void GuiCheats::drawEditRAMMenu2() ss << "[ " << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << (address) << " ] " << dataTypes[m_searchType]; Gui::drawText(font24, 520, 70, currTheme.textColor, ss.str().c_str()); ss.str(""); - dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + //dmntchtReadCheatProcessMemory(address, &out, sizeof(u32)); + m_debugger->readMemory(&out, sizeof(u32), address); Gui::drawText(font24, 830, 70, currTheme.textColor, _getAddressDisplayString(address, m_debugger, m_searchType).c_str()); //ss.str().c_str() for (u8 i = 0; i < 40; i++) { @@ -1069,7 +1108,8 @@ void GuiCheats::drawEditRAMMenu2() { Gui::drawRectangled(93 + (i % 5) * 225, 240 + (i / 5) * 50, 215, 40, currTheme.separatorColor); ss.str(""); - dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + // dmntchtReadCheatProcessMemory(addr, &out, sizeof(u32)); + m_debugger->readMemory(&out, sizeof(u32), addr); ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << out << ""; Gui::drawTextAligned(font20, 200 + (i % 5) * 225, 245 + (i / 5) * 50, currTheme.textColor, ss.str().c_str(), ALIGNED_CENTER); addr += 4; @@ -1461,15 +1501,20 @@ void GuiCheats::onInput(u32 kdown) if (m_searchMenuLocation == SEARCH_NONE) { // Gui::g_nextGui = GUI_MAIN; + PSsaveSTATE(); if (kheld & KEY_ZL) { - if (m_mainBaseAddr == 0) + if (!m_debugger -> m_dmnt) + { + m_debugger->detatch(); dmntchtForceOpenCheatProcess(); + printf("force open called\n"); + } else dmntchtForceCloseCheatProcess(); printf("dmnt toggled \n"); + return; }; - PSsaveSTATE(); Gui::g_requestExit = true; return; } @@ -3246,7 +3291,7 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s else if (searchRegion == SEARCH_REGION_HEAP_AND_MAIN && (meminfo.type != MemType_Heap && meminfo.type != MemType_CodeWritable && meminfo.type != MemType_CodeMutable)) continue; - else if (searchRegion == SEARCH_REGION_RAM && (meminfo.perm & Perm_Rw) != Perm_Rw) + else if ( (meminfo.perm & Perm_Rw) != Perm_Rw) //searchRegion == SEARCH_REGION_RAM && continue; // printf("%s%p", "meminfo.addr, ", meminfo.addr); @@ -5839,14 +5884,18 @@ void GuiCheats::iconloadcheck() m_havesave = false; } } -void GuiCheats::autoattachcheck() +bool GuiCheats::autoattachcheck() { std::stringstream filenoiconStr; filenoiconStr << EDIZON_DIR "/autoattach.txt"; if (access(filenoiconStr.str().c_str(), F_OK) == 0) { + if (m_debugger->m_dmnt) dmntchtForceOpenCheatProcess(); + return true; } + else + return false; // testlz(); } void GuiCheats::testlz() diff --git a/source/helpers/debugger.cpp b/source/helpers/debugger.cpp index b5b016d9..bd05e465 100644 --- a/source/helpers/debugger.cpp +++ b/source/helpers/debugger.cpp @@ -14,14 +14,37 @@ Debugger::Debugger() { } Debugger::~Debugger() { + if (!m_dmnt) + { + svcContinueDebugEvent(m_debugHandle, 4 | 2 | 1, 0, 0); + svcCloseHandle(m_debugHandle); + } pminfoExit(); pmdmntExit(); } Result Debugger::attachToProcess() { - return dmntchtForceOpenCheatProcess(); + if (m_debugHandle == 0 && (envIsSyscallHinted(0x60) == 1)) + { + m_rc = svcDebugActiveProcess(&m_debugHandle, m_pid); + if ((int)m_rc == 0) + { + m_dmnt = false; + return m_rc; + } + } + return 0; + // return dmntchtForceOpenCheatProcess(); +} +void Debugger::detatch() +{ + if (!m_dmnt) + { + svcContinueDebugEvent(m_debugHandle, 4 | 2 | 1, 0, 0); + svcCloseHandle(m_debugHandle); + m_dmnt = true; + } } - u64 Debugger::getRunningApplicationTID() { return m_tid; } @@ -32,27 +55,56 @@ u64 Debugger::getRunningApplicationPID() { u64 Debugger::peekMemory(u64 address) { u64 out; - dmntchtReadCheatProcessMemory(address, &out, sizeof(u64)); + if (m_dmnt) + dmntchtReadCheatProcessMemory(address, &out, sizeof(u64)); + else + { + svcReadDebugProcessMemory(&out, m_debugHandle, address, sizeof(u64)); + } + return out; } Result Debugger::pokeMemory(size_t varSize, u64 address, u64 value) { + + + if (m_dmnt) return dmntchtWriteCheatProcessMemory(address, &value, varSize); + else + { + return svcWriteDebugProcessMemory(m_debugHandle, &value, address, varSize); + } + } Result Debugger::readMemory(void *buffer, size_t bufferSize, u64 address) { - return dmntchtReadCheatProcessMemory(address, buffer, bufferSize); + if (m_dmnt) + return dmntchtReadCheatProcessMemory(address, buffer, bufferSize); + else + { + return svcReadDebugProcessMemory(buffer, m_debugHandle, address, bufferSize); + } } Result Debugger::writeMemory(void *buffer, size_t bufferSize, u64 address) { - return dmntchtWriteCheatProcessMemory(address, buffer, bufferSize); + if (m_dmnt) + return dmntchtWriteCheatProcessMemory(address, buffer, bufferSize); + else + { + return svcWriteDebugProcessMemory(m_debugHandle, buffer, address, bufferSize); + } } MemoryInfo Debugger::queryMemory(u64 address) { MemoryInfo memInfo = { 0 }; - - dmntchtQueryCheatProcessMemory(&memInfo, address); + if (m_dmnt) + dmntchtQueryCheatProcessMemory(&memInfo, address); + else + { + u32 pageinfo; // ignored + svcQueryDebugProcessMemory(&memInfo, &pageinfo, m_debugHandle, address); + } return memInfo; } \ No newline at end of file From 178abe8f65d59ae6b90bfaa69ad8c7560ed5e48d Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sat, 26 Sep 2020 15:44:04 +0800 Subject: [PATCH 89/95] allow function without dmnt --- source/helpers/debugger.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/helpers/debugger.cpp b/source/helpers/debugger.cpp index bd05e465..773a04f0 100644 --- a/source/helpers/debugger.cpp +++ b/source/helpers/debugger.cpp @@ -30,10 +30,10 @@ Result Debugger::attachToProcess() { if ((int)m_rc == 0) { m_dmnt = false; - return m_rc; } + return m_rc; } - return 0; + return 1; // return dmntchtForceOpenCheatProcess(); } void Debugger::detatch() From a7a07661f741aaca145ab580ec38d2a00ae8c03a Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 27 Sep 2020 20:22:52 +0800 Subject: [PATCH 90/95] mask out zero and pointers from DIFF search --- source/guis/gui_cheats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 54c6a208..ed195f72 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -4231,7 +4231,7 @@ void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t sea } break; case SEARCH_MODE_DIFF: - if (newValue._u64 != oldValue._u64) + if ((newValue._u64 != oldValue._u64) && (newValue._u64 <= m_heapBaseAddr || newValue._u64 >= (m_heapEnd)) && (newValue._u64 != 0)) { addrDump->addData((u8 *)&addr, sizeof(u64)); newMemDump->addData((u8 *)&newValue, sizeof(u64)); @@ -4587,7 +4587,7 @@ void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchValue_t sea } break; case SEARCH_MODE_DIFF: - if (value._s64 != oldvalue._s64) + if ((value._s64 != oldvalue._s64) && (value._u64 <= m_heapBaseAddr || value._u64 >= (m_heapEnd)) && (value._u64 != 0)) { newDump->addData((u8 *)&address, sizeof(u64)); newvalueDump->addData((u8 *)&value, sizeof(u64)); From a892cd7dd5c16d39a35d7f67645dd7c30dc606eb Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Sun, 27 Sep 2020 20:33:05 +0800 Subject: [PATCH 91/95] Not masking out zero for DIFF --- .vscode/c_cpp_properties.json | 2 +- Makefile | 2 +- source/guis/gui_cheats.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 4ec84bbe..c7ea57ae 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,7 @@ "DEBUG", "SWITCH", "__SWITCH__", - "VERSION_STRING=\"3.7.5\"" + "VERSION_STRING=\"3.7.6\"" ], "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", diff --git a/Makefile b/Makefile index 6a97fd61..4618a44e 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 5 +VERSION_MICRO := 6 NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index ed195f72..4dfa2674 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -633,7 +633,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.5"; + ss << "EdiZon SE : 3.7.6"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -4231,7 +4231,7 @@ void GuiCheats::searchMemoryValuesSecondary(Debugger *debugger, searchType_t sea } break; case SEARCH_MODE_DIFF: - if ((newValue._u64 != oldValue._u64) && (newValue._u64 <= m_heapBaseAddr || newValue._u64 >= (m_heapEnd)) && (newValue._u64 != 0)) + if ((newValue._u64 != oldValue._u64) && (newValue._u64 <= m_heapBaseAddr || newValue._u64 >= (m_heapEnd)) ) { addrDump->addData((u8 *)&addr, sizeof(u64)); newMemDump->addData((u8 *)&newValue, sizeof(u64)); @@ -4587,7 +4587,7 @@ void GuiCheats::searchMemoryValuesTertiary(Debugger *debugger, searchValue_t sea } break; case SEARCH_MODE_DIFF: - if ((value._s64 != oldvalue._s64) && (value._u64 <= m_heapBaseAddr || value._u64 >= (m_heapEnd)) && (value._u64 != 0)) + if ((value._s64 != oldvalue._s64) && (value._u64 <= m_heapBaseAddr || value._u64 >= (m_heapEnd))) { newDump->addData((u8 *)&address, sizeof(u64)); newvalueDump->addData((u8 *)&value, sizeof(u64)); From baf0ad905d59482fb35c166246c44dd941939aad Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Mon, 28 Sep 2020 11:04:13 +0800 Subject: [PATCH 92/95] xor hack --- source/guis/gui_cheats.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 4dfa2674..7ac7f891 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -1305,7 +1305,7 @@ void GuiCheats::drawSearchRAMMenu() Gui::drawTextAligned(font20, 1010, 160, m_searchMenuLocation == SEARCH_VALUE ? currTheme.selectedColor : currTheme.textColor, "VALUE", ALIGNED_CENTER); static const char *const typeNames[] = {"u8", "s8", "u16", "s16", "u32", "s32", "u64", "s64", "flt", "dbl", "void*"}; - static const char *const modeNames[] = {"==", "!=", ">", "StateB", "<", "StateA", "A..B", "SAME", "DIFF", "+ +", "- -", "PTR"}; + static const char *const modeNames[] = {"==", "!=", "=X", "StateB", "<", "StateA", "A..B", "SAME", "DIFF", "+ +", "- -", "PTR"}; static const char *const regionNames[] = {"HEAP", "MAIN", "HEAP + MAIN", "RAM"}; switch (m_searchMenuLocation) @@ -3317,6 +3317,7 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s debugger->readMemory(buffer, bufferSize, meminfo.addr + offset); searchValue_t realValue = {0}; + searchValue_t realValuep = {0}; u32 inc_i; if (searchMode == SEARCH_MODE_POINTER) inc_i = 4; @@ -3331,6 +3332,7 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s memcpy(&realValue, buffer + i, 4); else memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); + memcpy(&realValuep, buffer + i + dataTypeSizes[searchType], dataTypeSizes[searchType]); switch (searchMode) { @@ -3349,6 +3351,13 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s } break; case SEARCH_MODE_GT: + realValue._s64 = realValue._s64 ^ realValuep._s64; + if (realValue._s64 == searchValue1._s64) + { + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + helperinfo.count++; + } + break; if (searchType & (SEARCH_TYPE_SIGNED_8BIT | SEARCH_TYPE_SIGNED_16BIT | SEARCH_TYPE_SIGNED_32BIT | SEARCH_TYPE_SIGNED_64BIT | SEARCH_TYPE_FLOAT_32BIT | SEARCH_TYPE_FLOAT_64BIT)) { if (realValue._s64 > searchValue1._s64) @@ -3572,12 +3581,14 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t debugger->readMemory(ram_buffer, helperinfo.size, helperinfo.address); } searchValue_t value = {0}; + searchValue_t valuep = {0}; // searchValue_t testing = {0}; // temp u64 address = 0; address = *reinterpret_cast(&buffer[i]); //(*displayDump)->getData(i * sizeof(u64), &address, sizeof(u64)); memcpy(&value, ram_buffer + address - helperinfo.address, dataTypeSizes[searchType]); // extrat from buffer instead of making call + memcpy(&valuep, ram_buffer + address - helperinfo.address + dataTypeSizes[searchType], dataTypeSizes[searchType]); helperinfo.count--; // each fetch dec // testing = value; // temp // debugger->readMemory(&value, dataTypeSizes[searchType], address); @@ -3625,6 +3636,13 @@ void GuiCheats::searchMemoryAddressesSecondary(Debugger *debugger, searchValue_t } break; case SEARCH_MODE_GT: + value._s64 = value._s64 ^ valuep._s64; + if (value._s64 == searchValue1._s64) + { + newDump->addData((u8 *)&address, sizeof(u64)); + newhelperinfo.count++; + } + break; if (value._s64 > searchValue1._s64) { newDump->addData((u8 *)&address, sizeof(u64)); From 5f27122fcf7315857f872b0e30306b064b0a18c8 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Tue, 29 Sep 2020 01:09:14 +0800 Subject: [PATCH 93/95] search don't stop --- .vscode/c_cpp_properties.json | 2 +- Makefile | 2 +- source/guis/gui_cheats.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index c7ea57ae..c5ef9abe 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,7 @@ "DEBUG", "SWITCH", "__SWITCH__", - "VERSION_STRING=\"3.7.6\"" + "VERSION_STRING=\"3.7.6x\"" ], "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", diff --git a/Makefile b/Makefile index 4618a44e..40a6a899 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 6 +VERSION_MICRO := 6x NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index 7ac7f891..f46127fd 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -633,7 +633,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.6"; + ss << "EdiZon SE : 3.7.6x"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -5121,7 +5121,7 @@ void GuiCheats::pointersearch2(u64 targetaddress, u64 depth) //MemoryDump **disp printf("+%lx z=%d ", m_bookmark.pointer.offset[z], z); printf("\n\n"); m_pointer_found++; - return; // consider don't return to find more + // return; // consider don't return to find more }; if (PS_depth == m_max_depth) { From 6ec9dd4bb110d1a99426cbde6f98c5ccac184121 Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Wed, 30 Sep 2020 14:38:42 +0800 Subject: [PATCH 94/95] bookmark bug --- source/guis/gui_cheats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index f46127fd..b0eae885 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -873,7 +873,7 @@ void GuiCheats::draw() if (m_frozenAddresses.find(address) != m_frozenAddresses.end()) ss << " \uE130"; - if (bookmark.pointer.depth > 1) // have pointer + if (bookmark.pointer.depth > 0) // have pointer ss << " *"; } else @@ -2550,7 +2550,7 @@ void GuiCheats::onInput(u32 kdown) m_AttributeDumpBookmark->getData((m_selectedEntry + m_addresslist_offset) * sizeof(bookmark_t), &bookmark, sizeof(bookmark_t)); // printf("m_selectedEntry + m_addresslist_offset %ld\n", m_selectedEntry + m_addresslist_offset); // u64 index = m_selectedEntry + m_addresslist_offset; - if (bookmark.pointer.depth > 1) + if (bookmark.pointer.depth > 0) { addcodetofile(m_selectedEntry + m_addresslist_offset); } From 53aa6f233b9b636e2ad5e0bdc62c202f879f1b6b Mon Sep 17 00:00:00 2001 From: tomvita <68505331+tomvita@users.noreply.github.com> Date: Thu, 1 Oct 2020 10:09:38 +0800 Subject: [PATCH 95/95] fix pcdump bug --- .vscode/c_cpp_properties.json | 2 +- Makefile | 2 +- source/guis/gui_cheats.cpp | 109 +++++++++++++++++----------------- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index c5ef9abe..fc48e1b8 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -14,7 +14,7 @@ "DEBUG", "SWITCH", "__SWITCH__", - "VERSION_STRING=\"3.7.6x\"" + "VERSION_STRING=\"3.7.7x\"" ], "compilerPath": "F:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", "cStandard": "c11", diff --git a/Makefile b/Makefile index 40a6a899..1c25d9c0 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 3 VERSION_MINOR := 7 -VERSION_MICRO := 6x +VERSION_MICRO := 7x NIGHTLY := APP_TITLE := EdiZon SE diff --git a/source/guis/gui_cheats.cpp b/source/guis/gui_cheats.cpp index b0eae885..a9827a8f 100644 --- a/source/guis/gui_cheats.cpp +++ b/source/guis/gui_cheats.cpp @@ -633,7 +633,7 @@ void GuiCheats::draw() Gui::drawTextAligned(font14, 700, 142, currTheme.textColor, "Others", ALIGNED_LEFT); ss.str(""); - ss << "EdiZon SE : 3.7.6x"; + ss << "EdiZon SE : 3.7.7x"; if (m_32bitmode) ss << " 32 bit pointer mode"; Gui::drawTextAligned(font14, 900, 62, currTheme.textColor, ss.str().c_str(), ALIGNED_LEFT); @@ -3438,23 +3438,24 @@ void GuiCheats::searchMemoryAddressesPrimary(Debugger *debugger, searchValue_t s } break; case SEARCH_MODE_POINTER: //m_heapBaseAddr, m_mainBaseAddr, m_heapSize, m_mainSize - // if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) - if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) - { - if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) - break; - (*displayDump)->addData((u8 *)&address, sizeof(u64)); - newdataDump->addData((u8 *)&realValue, sizeof(u64)); - helperinfo.count++; - // printf("%lx,%lx\n",address,realValue); - // std::stringstream ss; // replace the printf - // ss.str(""); - // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; - // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; - // char st[27]; - // snprintf(st, 27, "%s\n", ss.str().c_str()); // - // newstringDump->addData((u8 *)&st, sizeof(st)); // - } + if ((realValue._u64 != 0)) + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + // if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) + { + if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) + break; + (*displayDump)->addData((u8 *)&address, sizeof(u64)); + newdataDump->addData((u8 *)&realValue, sizeof(u64)); + helperinfo.count++; + // printf("%lx,%lx\n",address,realValue); + // std::stringstream ss; // replace the printf + // ss.str(""); + // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; + // char st[27]; + // snprintf(st, 27, "%s\n", ss.str().c_str()); // + // newstringDump->addData((u8 *)&st, sizeof(st)); // + } break; case SEARCH_MODE_NONE: case SEARCH_MODE_SAME: @@ -6348,42 +6349,42 @@ void GuiCheats::searchMemoryAddressesPrimary2(Debugger *debugger, searchValue_t memcpy(&realValue, buffer + i, 4); //dataTypeSizes[searchType]); else memcpy(&realValue, buffer + i, dataTypeSizes[searchType]); - - // if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) - if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) - { - if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) - break; - // (*displayDump)->addData((u8 *)&address, sizeof(u64)); - // newdataDump->addData((u8 *)&realValue, sizeof(u64)); - // helperinfo.count++; - - // realValue._u64 = realValue._u64 - m_heapBaseAddr; - // MemoryType fromtype; - // if (meminfo.type == MemType_Heap) - // { - // address = address - m_heapBaseAddr; - // fromtype = HEAP; - // } - // else - // { - // address = address - m_mainBaseAddr; - // fromtype = MAIN; - // } - // PCDump->addData((u8 *)&fromtype, sizeof(fromtype)); - - PCDump->addData((u8 *)&address, sizeof(u64)); - PCDump->addData((u8 *)&realValue, sizeof(u64)); - counting_pointers++; - // printf("0x%lx,0x%lx\n",address,realValue); - // std::stringstream ss; // replace the printf - // ss.str(""); - // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; - // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; - // char st[27]; - // snprintf(st, 27, "%s\n", ss.str().c_str()); // - // newstringDump->addData((u8 *)&st, sizeof(st)); // - } + if (realValue._u64 != 0) + if (((realValue._u64 >= m_mainBaseAddr) && (realValue._u64 <= (m_mainend))) || ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= (m_heapEnd)))) + // if ((realValue._u64 >= m_heapBaseAddr) && (realValue._u64 <= m_heapEnd)) + { + if ((m_forwarddump) && (address > realValue._u64) && (meminfo.type == MemType_Heap)) + break; + // (*displayDump)->addData((u8 *)&address, sizeof(u64)); + // newdataDump->addData((u8 *)&realValue, sizeof(u64)); + // helperinfo.count++; + + // realValue._u64 = realValue._u64 - m_heapBaseAddr; + // MemoryType fromtype; + // if (meminfo.type == MemType_Heap) + // { + // address = address - m_heapBaseAddr; + // fromtype = HEAP; + // } + // else + // { + // address = address - m_mainBaseAddr; + // fromtype = MAIN; + // } + // PCDump->addData((u8 *)&fromtype, sizeof(fromtype)); + + PCDump->addData((u8 *)&address, sizeof(u64)); + PCDump->addData((u8 *)&realValue, sizeof(u64)); + counting_pointers++; + // printf("0x%lx,0x%lx\n",address,realValue); + // std::stringstream ss; // replace the printf + // ss.str(""); + // ss << "0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << address; + // ss << ",0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(10) << realValue._u64; + // char st[27]; + // snprintf(st, 27, "%s\n", ss.str().c_str()); // + // newstringDump->addData((u8 *)&st, sizeof(st)); // + } } offset += bufferSize;