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] 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; }