From f4032dd4dc194d27daa683b28a1d936e36cf2705 Mon Sep 17 00:00:00 2001 From: Pk11 Date: Tue, 9 Mar 2021 00:23:19 -0600 Subject: [PATCH 1/8] WIP: Add hex editor --- arm9/Makefile | 2 +- arm9/source/file_browse.cpp | 6 ++ arm9/source/file_browse.h | 1 + arm9/source/hexEditor.cpp | 177 ++++++++++++++++++++++++++++++++++++ arm9/source/hexEditor.h | 6 ++ 5 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 arm9/source/hexEditor.cpp create mode 100644 arm9/source/hexEditor.h diff --git a/arm9/Makefile b/arm9/Makefile index 59bcf9c..f08d8c2 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -15,7 +15,7 @@ else GIT_VER := $(shell git describe --abbrev=0 --tags)-$(shell git rev-parse --short HEAD) endif -# Ensure version.hpp exists +# Ensure version.h exists ifeq (,$(wildcard include/version.h)) $(shell mkdir -p include) $(shell touch include/version.h) diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index 052fa6a..eb4c209 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -38,6 +38,7 @@ #include "driveMenu.h" #include "driveOperations.h" #include "dumpOperations.h" +#include "hexEditor.h" #include "nitrofs.h" #include "inifile.h" #include "nds_loader_arm9.h" @@ -231,6 +232,8 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { assignedOp[++maxCursors] = FileOperation::mountImg; printf(" Mount as FAT image\n"); } + assignedOp[++maxCursors] = FileOperation::hexEdit; + printf(" Open in hex editor\n"); } assignedOp[++maxCursors] = FileOperation::showInfo; printf(entry->isDirectory ? " Show directory info\n" : " Show file info\n"); @@ -375,6 +378,9 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { currentDrive = 6; } break; + } case FileOperation::hexEdit: { + hexEditor(entry->name.c_str()); + break; } case FileOperation::none: { break; } diff --git a/arm9/source/file_browse.h b/arm9/source/file_browse.h index 0255590..64bdc20 100644 --- a/arm9/source/file_browse.h +++ b/arm9/source/file_browse.h @@ -43,6 +43,7 @@ enum class FileOperation { showInfo, copySdOut, copyFatOut, + hexEdit, }; bool extension(const std::string &filename, const std::vector &extensions); diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp new file mode 100644 index 0000000..7a32fc9 --- /dev/null +++ b/arm9/source/hexEditor.cpp @@ -0,0 +1,177 @@ +#include "hexEditor.h" + +#include "tonccpy.h" + +#include +#include + + +u32 jumpToOffset(u32 offset) { + consoleClear(); + + u8 cursorPosition = 0; + u16 pressed = 0, held = 0; + while(1) { + printf("\x1B[9;6H\x1B[47m-------------------"); + printf("\x1B[10;8H\x1B[47mJump to Offset"); + printf("\x1B[12;11H\x1B[33m%08lx", offset); + printf("\x1B[12;%dH\x1B[43m%lx", 17 - cursorPosition, (offset >> ((cursorPosition + 1) * 4)) & 0xF); + printf("\x1B[13;6H\x1B[47m-------------------"); + + do { + swiWaitForVBlank(); + scanKeys(); + pressed = keysDown(); + held = keysDownRepeat(); + } while(!held); + + if(held & KEY_UP) { + offset += 0x10 << (cursorPosition * 4); + } else if(held & KEY_DOWN) { + offset -= 0x10 << (cursorPosition * 4); + } else if(held & KEY_LEFT) { + if(cursorPosition < 6) + cursorPosition++; + } else if(held & KEY_RIGHT) { + if(cursorPosition > 0) + cursorPosition--; + } else if(pressed & (KEY_A | KEY_B)) { + return offset; + } + } +} + +void hexEditor(const char *path) { + FILE *file = fopen(path, "rb+"); + + if(!file) + return; + + consoleClear(); + + fseek(file, 0, SEEK_END); + u32 fileSize = ftell(file); + fseek(file, 0, SEEK_SET); + + u8 cursorPosition = 0, mode = 0; + u16 pressed = 0, held = 0; + u32 offset = 0; + + char data[8 * 23]; + fseek(file, offset, SEEK_SET); + fread(data, 1, sizeof(data), file); + + while(1) { + printf("\x1B[0;11H\x1B[42mHex Editor"); + printf("\x1B[0;0H\x1B[37m%04lx", offset >> 0x10); + + if(mode < 2 && held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) { + fseek(file, offset, SEEK_SET); + fread(data, 1, sizeof(data), file); + } + + for(int i = 0; i < 23; i++) { + printf("\x1B[%d;0H\x1B[37m%04lx", i + 1, (offset + i * 8) & 0xFFFF); + for(int j = 0; j < 4; j++) + printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 5 + (j * 2), (mode > 0 && i * 8 + j == cursorPosition) ? (mode > 1 ? 41 : 31) : 33, data[i * 8 + j]); + for(int j = 0; j < 4; j++) + printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 14 + (j * 2), (mode > 0 && i * 8 + 4 + j == cursorPosition) ? (mode > 1 ? 41 : 31) : 33, data[i * 8 + 4 + j]); + char line[9] = {0}; + for(int j = 0; j < 8; j++) { + char c = data[i * 8 + j]; + if(c < ' ' || c > 127) + line[j] = ' '; + else + line[j] = c; + } + printf("\x1B[%d;%dH\x1B[47m%.8s", i + 1, 23, line); + } + + // Change color of selected char + if(mode > 0) + printf("\x1B[%d;%dH\x1B[%dm%c", 1 + cursorPosition / 8, 23 + cursorPosition % 8, mode > 1 ? 41 : 31, data[cursorPosition]); + + do { + swiWaitForVBlank(); + scanKeys(); + pressed = keysDown(); + held = keysDownRepeat(); + } while(!held); + + if(mode == 0) { + if (held & KEY_UP) { + if(offset > 8) + offset -= 8; + else + offset = 0; + } else if (held & KEY_DOWN) { + if(offset < fileSize - 8 * 23) + offset += 8; + else + offset = fileSize - 8 * 23; + } else if (held & KEY_LEFT) { + if(offset > 8 * 23) + offset -= 8 * 23; + else + offset = 0; + } else if (held & KEY_RIGHT) { + if(offset < fileSize - 8 * 23) + offset += 8 * 23; + else + offset = fileSize - 8 * 23; + } else if (pressed & KEY_A) { + mode = 1; + } else if (pressed & KEY_B) { + return; + } else if(pressed & KEY_Y) { + offset = jumpToOffset(offset); + consoleClear(); + } + } else if(mode == 1) { + if (held & KEY_UP) { + if(cursorPosition >= 8) + cursorPosition -= 8; + else if(offset > 8) + offset -= 8; + else + offset = 0; + } else if (held & KEY_DOWN) { + if(cursorPosition < 8 * 22) + cursorPosition += 8; + else if(offset < fileSize - 8 * 23) + offset += 8; + else + offset = fileSize - 8 * 23; + } else if (held & KEY_LEFT) { + if(cursorPosition > 0) + cursorPosition--; + } else if (held & KEY_RIGHT) { + if(cursorPosition < 8 * 23 - 1) + cursorPosition++; + } else if (pressed & KEY_A) { + mode = 2; + } else if (pressed & KEY_B) { + mode = 0; + } else if(pressed & KEY_Y) { + offset = jumpToOffset(offset); + consoleClear(); + } + } else if(mode == 2) { + if (held & KEY_UP) { + data[cursorPosition]++; + } else if (held & KEY_DOWN) { + data[cursorPosition]--; + } else if (held & KEY_LEFT) { + data[cursorPosition] += 0x10; + } else if (held & KEY_RIGHT) { + data[cursorPosition] -= 0x10; + } else if (pressed & (KEY_A | KEY_B)) { + mode = 1; + fseek(file, offset + cursorPosition, SEEK_SET); + fwrite(data + cursorPosition, 1, 1, file); + } + } + } + + fclose(file); +} diff --git a/arm9/source/hexEditor.h b/arm9/source/hexEditor.h new file mode 100644 index 0000000..078c408 --- /dev/null +++ b/arm9/source/hexEditor.h @@ -0,0 +1,6 @@ +#ifndef HEX_EDITOR_H +#define HEX_EDITOR_H + +void hexEditor(const char *path); + +#endif From d8090ed60f40ee5f4fe705a5e06805fb00b3bd32 Mon Sep 17 00:00:00 2001 From: Pk11 Date: Wed, 10 Mar 2021 00:28:35 -0600 Subject: [PATCH 2/8] Add limit to jumping and swap left/right when editing byte value --- arm9/source/hexEditor.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index 7a32fc9..95f4810 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -6,7 +6,7 @@ #include -u32 jumpToOffset(u32 offset) { +u32 jumpToOffset(u32 offset, u32 limit) { consoleClear(); u8 cursorPosition = 0; @@ -26,9 +26,11 @@ u32 jumpToOffset(u32 offset) { } while(!held); if(held & KEY_UP) { - offset += 0x10 << (cursorPosition * 4); + if(offset + (0x10 << (cursorPosition * 4)) < limit - 8 * 23) + offset += 0x10 << (cursorPosition * 4); } else if(held & KEY_DOWN) { - offset -= 0x10 << (cursorPosition * 4); + if(offset - (0x10 << (cursorPosition * 4)) > 0) + offset -= 0x10 << (cursorPosition * 4); } else if(held & KEY_LEFT) { if(cursorPosition < 6) cursorPosition++; @@ -65,7 +67,7 @@ void hexEditor(const char *path) { printf("\x1B[0;11H\x1B[42mHex Editor"); printf("\x1B[0;0H\x1B[37m%04lx", offset >> 0x10); - if(mode < 2 && held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) { + if(mode < 2) { fseek(file, offset, SEEK_SET); fread(data, 1, sizeof(data), file); } @@ -88,8 +90,12 @@ void hexEditor(const char *path) { } // Change color of selected char - if(mode > 0) - printf("\x1B[%d;%dH\x1B[%dm%c", 1 + cursorPosition / 8, 23 + cursorPosition % 8, mode > 1 ? 41 : 31, data[cursorPosition]); + if(mode > 0) { + char c = data[cursorPosition]; + if(c < ' ' || c > 127) + c = ' '; + printf("\x1B[%d;%dH\x1B[%dm%c", 1 + cursorPosition / 8, 23 + cursorPosition % 8, mode > 1 ? 41 : 31, c); + } do { swiWaitForVBlank(); @@ -124,7 +130,7 @@ void hexEditor(const char *path) { } else if (pressed & KEY_B) { return; } else if(pressed & KEY_Y) { - offset = jumpToOffset(offset); + offset = jumpToOffset(offset, fileSize); consoleClear(); } } else if(mode == 1) { @@ -153,7 +159,7 @@ void hexEditor(const char *path) { } else if (pressed & KEY_B) { mode = 0; } else if(pressed & KEY_Y) { - offset = jumpToOffset(offset); + offset = jumpToOffset(offset, fileSize); consoleClear(); } } else if(mode == 2) { @@ -162,9 +168,9 @@ void hexEditor(const char *path) { } else if (held & KEY_DOWN) { data[cursorPosition]--; } else if (held & KEY_LEFT) { - data[cursorPosition] += 0x10; - } else if (held & KEY_RIGHT) { data[cursorPosition] -= 0x10; + } else if (held & KEY_RIGHT) { + data[cursorPosition] += 0x10; } else if (pressed & (KEY_A | KEY_B)) { mode = 1; fseek(file, offset + cursorPosition, SEEK_SET); From 8d607e70a2b51175f88205068aa021601d30178d Mon Sep 17 00:00:00 2001 From: Pk11 Date: Thu, 11 Mar 2021 17:47:05 -0600 Subject: [PATCH 3/8] Improve colors, fix non-mod 8 sized files, probably more --- arm9/source/hexEditor.cpp | 134 +++++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 46 deletions(-) diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index 95f4810..284c008 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -1,12 +1,18 @@ #include "hexEditor.h" +#include "date.h" #include "tonccpy.h" +#include #include #include +extern PrintConsole bottomConsole, bottomConsoleBG, topConsole; -u32 jumpToOffset(u32 offset, u32 limit) { +u32 jumpToOffset(u32 offset) { + consoleSelect(&bottomConsoleBG); + consoleClear(); + consoleSelect(&bottomConsole); consoleClear(); u8 cursorPosition = 0; @@ -14,23 +20,24 @@ u32 jumpToOffset(u32 offset, u32 limit) { while(1) { printf("\x1B[9;6H\x1B[47m-------------------"); printf("\x1B[10;8H\x1B[47mJump to Offset"); - printf("\x1B[12;11H\x1B[33m%08lx", offset); - printf("\x1B[12;%dH\x1B[43m%lx", 17 - cursorPosition, (offset >> ((cursorPosition + 1) * 4)) & 0xF); + printf("\x1B[12;11H\x1B[37m%08lx", offset); + printf("\x1B[12;%dH\x1B[41m%lx", 17 - cursorPosition, (offset >> ((cursorPosition + 1) * 4)) & 0xF); printf("\x1B[13;6H\x1B[47m-------------------"); + consoleSelect(&topConsole); do { swiWaitForVBlank(); scanKeys(); pressed = keysDown(); held = keysDownRepeat(); + printf("\x1B[30m\x1B[0;26H %s", RetTime().c_str()); // Print time } while(!held); + consoleSelect(&bottomConsole); if(held & KEY_UP) { - if(offset + (0x10 << (cursorPosition * 4)) < limit - 8 * 23) - offset += 0x10 << (cursorPosition * 4); + offset = (offset & ~(0xF0 << cursorPosition * 4)) | ((offset + (0x10 << (cursorPosition * 4))) & (0xF0 << cursorPosition * 4)); } else if(held & KEY_DOWN) { - if(offset - (0x10 << (cursorPosition * 4)) > 0) - offset -= 0x10 << (cursorPosition * 4); + offset = (offset & ~(0xF0 << cursorPosition * 4)) | ((offset - (0x10 << (cursorPosition * 4))) & (0xF0 << cursorPosition * 4)); } else if(held & KEY_LEFT) { if(cursorPosition < 6) cursorPosition++; @@ -44,6 +51,12 @@ u32 jumpToOffset(u32 offset, u32 limit) { } void hexEditor(const char *path) { + // Custom palettes + BG_PALETTE_SUB[0x1F] = 0x9CF7; + BG_PALETTE_SUB[0x2F] = 0xB710; + BG_PALETTE_SUB[0x3F] = 0xAE8D; + BG_PALETTE_SUB[0x7F] = 0xEA2D; + FILE *file = fopen(path, "rb+"); if(!file) @@ -55,29 +68,44 @@ void hexEditor(const char *path) { u32 fileSize = ftell(file); fseek(file, 0, SEEK_SET); + u8 maxLines = std::min(23lu, fileSize / 8); + u32 maxSize = ((fileSize - 8 * maxLines) & ~7) + (fileSize & 7 ? 8 : 0); + u8 cursorPosition = 0, mode = 0; u16 pressed = 0, held = 0; u32 offset = 0; - char data[8 * 23]; + char data[8 * maxLines]; fseek(file, offset, SEEK_SET); fread(data, 1, sizeof(data), file); while(1) { - printf("\x1B[0;11H\x1B[42mHex Editor"); - printf("\x1B[0;0H\x1B[37m%04lx", offset >> 0x10); + consoleSelect(&bottomConsoleBG); + printf ("\x1B[0;0H\x1B[46m"); // Blue + for (int i = 0; i < 4; i++) + printf ("\2"); + printf ("\x1B[42m"); // Green + for (int i = 0; i < 32 - 4; i++) + printf ("\2"); + + consoleSelect(&bottomConsole); + + printf("\x1B[0;11H\x1B[30mHex Editor"); + + printf("\x1B[0;0H\x1B[30m%04lx", offset >> 0x10); if(mode < 2) { fseek(file, offset, SEEK_SET); - fread(data, 1, sizeof(data), file); + toncset(data, 0, sizeof(data)); + fread(data, 1, std::min((u32)sizeof(data), fileSize - offset), file); } - for(int i = 0; i < 23; i++) { + for(int i = 0; i < maxLines; i++) { printf("\x1B[%d;0H\x1B[37m%04lx", i + 1, (offset + i * 8) & 0xFFFF); for(int j = 0; j < 4; j++) - printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 5 + (j * 2), (mode > 0 && i * 8 + j == cursorPosition) ? (mode > 1 ? 41 : 31) : 33, data[i * 8 + j]); + printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 5 + (j * 2), (mode > 0 && i * 8 + j == cursorPosition) ? (mode > 1 ? 30 : 31) : (offset + i * 8 + j >= fileSize ? 38 : 32 + (j % 2)), data[i * 8 + j]); for(int j = 0; j < 4; j++) - printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 14 + (j * 2), (mode > 0 && i * 8 + 4 + j == cursorPosition) ? (mode > 1 ? 41 : 31) : 33, data[i * 8 + 4 + j]); + printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 14 + (j * 2), (mode > 0 && i * 8 + 4 + j == cursorPosition) ? (mode > 1 ? 30 : 31) : (offset + i * 8 + 4 + j >= fileSize ? 38 : 32 + (j % 2)), data[i * 8 + 4 + j]); char line[9] = {0}; for(int j = 0; j < 8; j++) { char c = data[i * 8 + j]; @@ -86,51 +114,50 @@ void hexEditor(const char *path) { else line[j] = c; } - printf("\x1B[%d;%dH\x1B[47m%.8s", i + 1, 23, line); + printf("\x1B[%d;23H\x1B[47m%.8s", i + 1, line); + if(mode > 0 && cursorPosition / 8 == i) { + printf("\x1B[%d;%dH\x1B[%dm%c", i + 1, 23 + cursorPosition % 8, mode > 1 ? 30 : 31, line[cursorPosition % 8]); + } } - // Change color of selected char - if(mode > 0) { - char c = data[cursorPosition]; - if(c < ' ' || c > 127) - c = ' '; - printf("\x1B[%d;%dH\x1B[%dm%c", 1 + cursorPosition / 8, 23 + cursorPosition % 8, mode > 1 ? 41 : 31, c); - } + consoleSelect(&topConsole); do { swiWaitForVBlank(); scanKeys(); pressed = keysDown(); held = keysDownRepeat(); + printf("\x1B[30m\x1B[0;26H %s", RetTime().c_str()); // Print time } while(!held); + consoleSelect(&bottomConsole); if(mode == 0) { - if (held & KEY_UP) { + if(keysHeld() & KEY_R && held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) { + if (held & KEY_UP) { + offset = std::max((s64)offset - 0x1000, 0ll); + } else if (held & KEY_DOWN) { + offset = std::min(offset + 0x1000, maxSize); + } else if (held & KEY_LEFT) { + offset = std::max((s64)offset - 0x10000, 0ll); + } else if (held & KEY_RIGHT) { + offset = std::min(offset + 0x10000, maxSize); + } + } else if (held & KEY_UP) { if(offset > 8) offset -= 8; - else - offset = 0; } else if (held & KEY_DOWN) { - if(offset < fileSize - 8 * 23) + if(offset < fileSize - 8 * maxLines) offset += 8; - else - offset = fileSize - 8 * 23; } else if (held & KEY_LEFT) { - if(offset > 8 * 23) - offset -= 8 * 23; - else - offset = 0; + offset = std::max((s64)offset - 8 * maxLines, 0ll); } else if (held & KEY_RIGHT) { - if(offset < fileSize - 8 * 23) - offset += 8 * 23; - else - offset = fileSize - 8 * 23; + offset = std::min(offset + 8 * maxLines, maxSize); } else if (pressed & KEY_A) { mode = 1; } else if (pressed & KEY_B) { - return; + break; } else if(pressed & KEY_Y) { - offset = jumpToOffset(offset, fileSize); + offset = std::min(jumpToOffset(offset), maxSize); consoleClear(); } } else if(mode == 1) { @@ -139,27 +166,28 @@ void hexEditor(const char *path) { cursorPosition -= 8; else if(offset > 8) offset -= 8; - else - offset = 0; } else if (held & KEY_DOWN) { if(cursorPosition < 8 * 22) cursorPosition += 8; - else if(offset < fileSize - 8 * 23) + else if(offset < fileSize - 8 * maxLines) offset += 8; - else - offset = fileSize - 8 * 23; + cursorPosition = std::min(cursorPosition, (u8)(fileSize - offset - 1)); } else if (held & KEY_LEFT) { if(cursorPosition > 0) cursorPosition--; } else if (held & KEY_RIGHT) { - if(cursorPosition < 8 * 23 - 1) - cursorPosition++; + if(cursorPosition < 8 * maxLines - 1) + cursorPosition = std::min((u8)(cursorPosition + 1), (u8)(fileSize - offset - 1)); } else if (pressed & KEY_A) { mode = 2; + consoleSelect(&bottomConsoleBG); + printf("\x1B[%d;%dH\x1B[%dm\2\2", 1 + cursorPosition / 8, 5 + (cursorPosition % 8 * 2) + (cursorPosition % 8 / 4), 31); + printf("\x1B[%d;%dH\x1B[%dm\2", 1 + cursorPosition / 8, 23 + cursorPosition % 8, 31); + consoleSelect(&bottomConsole); } else if (pressed & KEY_B) { mode = 0; } else if(pressed & KEY_Y) { - offset = jumpToOffset(offset, fileSize); + offset = std::min(jumpToOffset(offset), maxSize); consoleClear(); } } else if(mode == 2) { @@ -175,9 +203,23 @@ void hexEditor(const char *path) { mode = 1; fseek(file, offset + cursorPosition, SEEK_SET); fwrite(data + cursorPosition, 1, 1, file); + + consoleSelect(&bottomConsoleBG); + printf("\x1B[%d;%dH\x1B[%dm\2\2", 1 + cursorPosition / 8, 5 + (cursorPosition % 8 * 2) + (cursorPosition % 8 / 4), 30); + printf("\x1B[%d;%dH\x1B[%dm\2", 1 + cursorPosition / 8, 23 + cursorPosition % 8, 30); + consoleSelect(&bottomConsole); } } } fclose(file); + + // Restore color palette + BG_PALETTE_SUB[0x1F] = 0x000F; + BG_PALETTE_SUB[0x2F] = 0x01E0; + BG_PALETTE_SUB[0x3F] = 0x3339; + BG_PALETTE_SUB[0x7F] = 0x656A; + + consoleSelect(&bottomConsoleBG); + consoleClear(); } From 2d59362d9c611a45df1f7b0f2c6ea8ef48a305fe Mon Sep 17 00:00:00 2001 From: Pk11 Date: Fri, 12 Mar 2021 07:59:01 -0600 Subject: [PATCH 4/8] Read only for NAND/NitroFS/FAT IMG drives --- arm9/Makefile | 4 ++-- arm9/source/file_browse.cpp | 2 +- arm9/source/hexEditor.cpp | 20 ++++++++++++-------- arm9/source/hexEditor.h | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/arm9/Makefile b/arm9/Makefile index f08d8c2..fe7f79e 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -8,11 +8,11 @@ endif include $(DEVKITARM)/ds_rules -# If on a tagged commit, use the tag instead of the commit +# If on a tagged commit, use just tag ifneq ($(shell echo $(shell git tag -l --points-at HEAD) | head -c 1),) GIT_VER := $(shell git tag -l --points-at HEAD) else -GIT_VER := $(shell git describe --abbrev=0 --tags)-$(shell git rev-parse --short HEAD) +GIT_VER := $(shell git describe --abbrev=0 --tags)-$(shell git rev-parse --short=7 HEAD) endif # Ensure version.h exists diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index eb4c209..36a0f42 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -379,7 +379,7 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { } break; } case FileOperation::hexEdit: { - hexEditor(entry->name.c_str()); + hexEditor(entry->name.c_str(), currentDrive); break; } case FileOperation::none: { break; diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index 284c008..57eba56 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -50,17 +50,19 @@ u32 jumpToOffset(u32 offset) { } } -void hexEditor(const char *path) { +void hexEditor(const char *path, int drive) { // Custom palettes BG_PALETTE_SUB[0x1F] = 0x9CF7; BG_PALETTE_SUB[0x2F] = 0xB710; BG_PALETTE_SUB[0x3F] = 0xAE8D; BG_PALETTE_SUB[0x7F] = 0xEA2D; - FILE *file = fopen(path, "rb+"); + FILE *file = fopen(path, drive < 4 ? "rb+" : "rb"); - if(!file) + if(!file) { + nocashMessage("test"); return; + } consoleClear(); @@ -179,11 +181,13 @@ void hexEditor(const char *path) { if(cursorPosition < 8 * maxLines - 1) cursorPosition = std::min((u8)(cursorPosition + 1), (u8)(fileSize - offset - 1)); } else if (pressed & KEY_A) { - mode = 2; - consoleSelect(&bottomConsoleBG); - printf("\x1B[%d;%dH\x1B[%dm\2\2", 1 + cursorPosition / 8, 5 + (cursorPosition % 8 * 2) + (cursorPosition % 8 / 4), 31); - printf("\x1B[%d;%dH\x1B[%dm\2", 1 + cursorPosition / 8, 23 + cursorPosition % 8, 31); - consoleSelect(&bottomConsole); + if(drive < 4) { + mode = 2; + consoleSelect(&bottomConsoleBG); + printf("\x1B[%d;%dH\x1B[%dm\2\2", 1 + cursorPosition / 8, 5 + (cursorPosition % 8 * 2) + (cursorPosition % 8 / 4), 31); + printf("\x1B[%d;%dH\x1B[%dm\2", 1 + cursorPosition / 8, 23 + cursorPosition % 8, 31); + consoleSelect(&bottomConsole); + } } else if (pressed & KEY_B) { mode = 0; } else if(pressed & KEY_Y) { diff --git a/arm9/source/hexEditor.h b/arm9/source/hexEditor.h index 078c408..887a17b 100644 --- a/arm9/source/hexEditor.h +++ b/arm9/source/hexEditor.h @@ -1,6 +1,6 @@ #ifndef HEX_EDITOR_H #define HEX_EDITOR_H -void hexEditor(const char *path); +void hexEditor(const char *path, int drive); #endif From e40ebe4b878f877fed739148b491e4115e4c664f Mon Sep 17 00:00:00 2001 From: Pk11 Date: Fri, 12 Mar 2021 08:10:56 -0600 Subject: [PATCH 5/8] Remove debug message --- arm9/source/hexEditor.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index 57eba56..01a5cfa 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -59,10 +59,8 @@ void hexEditor(const char *path, int drive) { FILE *file = fopen(path, drive < 4 ? "rb+" : "rb"); - if(!file) { - nocashMessage("test"); + if(!file) return; - } consoleClear(); From 5e10ed280919f17d697518da3ab918264ca98faa Mon Sep 17 00:00:00 2001 From: Pk11 Date: Sat, 13 Mar 2021 21:44:10 -0600 Subject: [PATCH 6/8] Use capital A-F for hex I didn't realize you could do %X instead of %x for that --- arm9/source/hexEditor.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index 01a5cfa..8b9c28a 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -20,8 +20,8 @@ u32 jumpToOffset(u32 offset) { while(1) { printf("\x1B[9;6H\x1B[47m-------------------"); printf("\x1B[10;8H\x1B[47mJump to Offset"); - printf("\x1B[12;11H\x1B[37m%08lx", offset); - printf("\x1B[12;%dH\x1B[41m%lx", 17 - cursorPosition, (offset >> ((cursorPosition + 1) * 4)) & 0xF); + printf("\x1B[12;11H\x1B[37m%08lX", offset); + printf("\x1B[12;%dH\x1B[41m%lX", 17 - cursorPosition, (offset >> ((cursorPosition + 1) * 4)) & 0xF); printf("\x1B[13;6H\x1B[47m-------------------"); consoleSelect(&topConsole); @@ -92,7 +92,7 @@ void hexEditor(const char *path, int drive) { printf("\x1B[0;11H\x1B[30mHex Editor"); - printf("\x1B[0;0H\x1B[30m%04lx", offset >> 0x10); + printf("\x1B[0;0H\x1B[30m%04lX", offset >> 0x10); if(mode < 2) { fseek(file, offset, SEEK_SET); @@ -101,11 +101,11 @@ void hexEditor(const char *path, int drive) { } for(int i = 0; i < maxLines; i++) { - printf("\x1B[%d;0H\x1B[37m%04lx", i + 1, (offset + i * 8) & 0xFFFF); + printf("\x1B[%d;0H\x1B[37m%04lX", i + 1, (offset + i * 8) & 0xFFFF); for(int j = 0; j < 4; j++) - printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 5 + (j * 2), (mode > 0 && i * 8 + j == cursorPosition) ? (mode > 1 ? 30 : 31) : (offset + i * 8 + j >= fileSize ? 38 : 32 + (j % 2)), data[i * 8 + j]); + printf("\x1B[%d;%dH\x1B[%dm%02X", i + 1, 5 + (j * 2), (mode > 0 && i * 8 + j == cursorPosition) ? (mode > 1 ? 30 : 31) : (offset + i * 8 + j >= fileSize ? 38 : 32 + (j % 2)), data[i * 8 + j]); for(int j = 0; j < 4; j++) - printf("\x1B[%d;%dH\x1B[%dm%02x", i + 1, 14 + (j * 2), (mode > 0 && i * 8 + 4 + j == cursorPosition) ? (mode > 1 ? 30 : 31) : (offset + i * 8 + 4 + j >= fileSize ? 38 : 32 + (j % 2)), data[i * 8 + 4 + j]); + printf("\x1B[%d;%dH\x1B[%dm%02X", i + 1, 14 + (j * 2), (mode > 0 && i * 8 + 4 + j == cursorPosition) ? (mode > 1 ? 30 : 31) : (offset + i * 8 + 4 + j >= fileSize ? 38 : 32 + (j % 2)), data[i * 8 + 4 + j]); char line[9] = {0}; for(int j = 0; j < 8; j++) { char c = data[i * 8 + j]; From 0041a0fa680791de230fdb678622bb7177b0679f Mon Sep 17 00:00:00 2001 From: Pk11 Date: Sat, 13 Mar 2021 23:45:49 -0600 Subject: [PATCH 7/8] Fix TWLBot releases not having the commit messages --- .github/workflows/building.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/building.yml b/.github/workflows/building.yml index 631189b..b58aa57 100644 --- a/.github/workflows/building.yml +++ b/.github/workflows/building.yml @@ -53,7 +53,7 @@ jobs: echo ::set-output name=author_name::$(git log -1 "$GITHUB_SHA" --pretty="%aN") echo ::set-output name=committer_name::$(git log -1 "$GITHUB_SHA" --pretty="%cN") echo ::set-output name=commit_subject::$(git log -1 "$GITHUB_SHA" --pretty="%s") - echo ::set-output name=commit_message::$(git log -1 "$GITHUB_SHA" --pretty="%b") + echo ::set-output name=commit_message::$(git log -1 "$GITHUB_SHA" --pretty="%B") - name: Publish build to GH Actions uses: actions/upload-artifact@v2 with: From 219a0a43250aad4e99272bf9f7aad12c9df3d514 Mon Sep 17 00:00:00 2001 From: Pk11 Date: Fri, 23 Apr 2021 01:35:35 -0500 Subject: [PATCH 8/8] Fix tiny files and add searching Also make the formatting of 'if's and 'for's consistent --- arm9/source/file_browse.h | 1 + arm9/source/hexEditor.cpp | 229 +++++++++++++++++++++++++++++++++----- 2 files changed, 203 insertions(+), 27 deletions(-) diff --git a/arm9/source/file_browse.h b/arm9/source/file_browse.h index 64bdc20..70bd321 100644 --- a/arm9/source/file_browse.h +++ b/arm9/source/file_browse.h @@ -47,6 +47,7 @@ enum class FileOperation { }; bool extension(const std::string &filename, const std::vector &extensions); +void OnKeyPressed(int key); std::string browseForFile (void); void getDirectoryContents (std::vector& dirContents); diff --git a/arm9/source/hexEditor.cpp b/arm9/source/hexEditor.cpp index 8b9c28a..2a1c823 100644 --- a/arm9/source/hexEditor.cpp +++ b/arm9/source/hexEditor.cpp @@ -2,6 +2,7 @@ #include "date.h" #include "tonccpy.h" +#include "file_browse.h" #include #include @@ -9,6 +10,8 @@ extern PrintConsole bottomConsole, bottomConsoleBG, topConsole; +extern void reinitConsoles(void); + u32 jumpToOffset(u32 offset) { consoleSelect(&bottomConsoleBG); consoleClear(); @@ -50,6 +53,172 @@ u32 jumpToOffset(u32 offset) { } } +u32 search(u32 offset, FILE *file) { + consoleSelect(&bottomConsoleBG); + consoleClear(); + consoleSelect(&bottomConsole); + consoleClear(); + + u8 cursorPosition = 0; + u16 pressed = 0, held = 0; + while(1) { + printf("\x1B[9;4H\x1B[47m-----------------------"); + printf("\x1B[10;5H%c Search for String %c", cursorPosition == 0 ? '>' : ' ', cursorPosition == 0 ? '<' : ' '); + printf("\x1B[11;5H%c Search for Data %c", cursorPosition == 1 ? '>' : ' ', cursorPosition == 1 ? '<' : ' '); + printf("\x1B[12;4H-----------------------"); + + consoleSelect(&topConsole); + do { + swiWaitForVBlank(); + scanKeys(); + pressed = keysDown(); + held = keysDownRepeat(); + printf("\x1B[30m\x1B[0;26H %s", RetTime().c_str()); // Print time + } while(!held); + consoleSelect(&bottomConsole); + + if(held & (KEY_UP | KEY_DOWN)) { + cursorPosition ^= 1; + } else if(pressed & KEY_A) { + break; + } else if(pressed & KEY_B) { + return offset; + } + } + + char str[64] = {0}; + size_t strLen = 1; + + if(cursorPosition == 0) { + consoleDemoInit(); + Keyboard *kbd = keyboardDemoInit(); + kbd->OnKeyPressed = OnKeyPressed; + + // keyboardShow(); + printf("Search for:\n"); + fgets(str, sizeof(str), stdin); + keyboardHide(); + consoleClear(); + + reinitConsoles(); + consoleSelect(&bottomConsole); + + BG_PALETTE_SUB[0x1F] = 0x9CF7; + BG_PALETTE_SUB[0x2F] = 0xB710; + BG_PALETTE_SUB[0x3F] = 0xAE8D; + BG_PALETTE_SUB[0x7F] = 0xEA2D; + + strLen = strlen(str) - 1; + if(strLen == 0) + return offset; + + str[strLen] = 0; // Remove ending \n that fgets has + } else { + consoleClear(); + + cursorPosition = 0; + while(1) { + printf("\x1B[9;6H\x1B[47m------------------"); + printf("\x1B[10;9HEnter value:"); + u8 pos = 15 - strLen; + for(size_t i = 0; i < strLen * 2; i++) { + printf("\x1B[12;%dH\x1B[%dm%X", pos + i, (i == cursorPosition ? 31 : ((i / 2 % 2) ? 33 : 32)), str[i / 2] >> (!(i % 2) * 4) & 0xF); + } + printf("\x1B[13;6H\x1B[47m------------------"); + + consoleSelect(&topConsole); + do { + swiWaitForVBlank(); + scanKeys(); + pressed = keysDown(); + held = keysDownRepeat(); + printf("\x1B[30m\x1B[0;26H %s", RetTime().c_str()); // Print time + } while(!held); + consoleSelect(&bottomConsole); + + if(held & KEY_UP) { + char val = str[cursorPosition / 2]; + u8 shift = !(cursorPosition % 2) * 4; + str[cursorPosition / 2] = (val & (0xF0 >> shift)) | ((val + (1 << shift)) & (0xF << shift)); + } else if(held & KEY_DOWN) { + char val = str[cursorPosition / 2]; + u8 shift = !(cursorPosition % 2) * 4; + str[cursorPosition / 2] = (val & (0xF0 >> shift)) | ((val - (1 << shift)) & (0xF << shift)); + } else if(held & KEY_LEFT) { + if(cursorPosition > 0) + cursorPosition--; + } else if(held & KEY_RIGHT) { + if(cursorPosition < strLen * 2 - 1) { + cursorPosition++; + } else if(strLen < 8) { + strLen++; + cursorPosition++; + } + } else if(pressed & KEY_A) { + break; + } else if(pressed & KEY_B) { + return offset; + } else if(pressed & KEY_X) { + if(strLen > 1) { + str[strLen - 1] = 0; + strLen--; + if(cursorPosition > strLen * 2 - 1) + cursorPosition -= 2; + consoleClear(); + } + } + } + } + + consoleClear(); + printf("\x1B[9;6H\x1B[47m---------------------"); + printf("\x1B[10;12HSearching"); + printf("\x1B[14;8HPress B to cancel"); + printf("\x1B[15;6H---------------------"); + + size_t len = 32 << 10, pos = offset; + fseek(file, 0, SEEK_END); + size_t fileLen = ftell(file); + char *buf = new char[len]; + do { + scanKeys(); + if(keysDown() & KEY_B) { + delete[] buf; + return offset; + } + + printf("\x1B[12;6H%10d/%d", pos, fileLen); + + if(fseek(file, pos, SEEK_SET) != 0) + break; + len = fread(buf, 1, len, file); + + for(size_t i = 0; i < len - strLen && len >= strLen; i++) { + if(memcmp(buf + i, str, strLen) == 0) { + delete[] buf; + return (pos + i) & ~7; + } + } + + pos += len; + } while(len == 32 << 10); + delete[] buf; + + consoleClear(); + printf("\x1B[9;5H\x1B[47m---------------------"); + printf("\x1B[10;6HReached end of file"); + printf("\x1B[11;8Hwith no results"); + printf("\x1B[12;5H---------------------"); + + do { + swiWaitForVBlank(); + scanKeys(); + printf("\x1B[30m\x1B[0;26H %s", RetTime().c_str()); // Print time + } while(!keysDown()); + + return offset; +} + void hexEditor(const char *path, int drive) { // Custom palettes BG_PALETTE_SUB[0x1F] = 0x9CF7; @@ -68,7 +237,7 @@ void hexEditor(const char *path, int drive) { u32 fileSize = ftell(file); fseek(file, 0, SEEK_SET); - u8 maxLines = std::min(23lu, fileSize / 8); + u8 maxLines = std::min(23lu, fileSize / 8 + (fileSize % 8 != 0)); u32 maxSize = ((fileSize - 8 * maxLines) & ~7) + (fileSize & 7 ? 8 : 0); u8 cursorPosition = 0, mode = 0; @@ -82,10 +251,10 @@ void hexEditor(const char *path, int drive) { while(1) { consoleSelect(&bottomConsoleBG); printf ("\x1B[0;0H\x1B[46m"); // Blue - for (int i = 0; i < 4; i++) + for(int i = 0; i < 4; i++) printf ("\2"); printf ("\x1B[42m"); // Green - for (int i = 0; i < 32 - 4; i++) + for(int i = 0; i < 32 - 4; i++) printf ("\2"); consoleSelect(&bottomConsole); @@ -133,52 +302,55 @@ void hexEditor(const char *path, int drive) { if(mode == 0) { if(keysHeld() & KEY_R && held & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) { - if (held & KEY_UP) { + if(held & KEY_UP) { offset = std::max((s64)offset - 0x1000, 0ll); - } else if (held & KEY_DOWN) { + } else if(held & KEY_DOWN) { offset = std::min(offset + 0x1000, maxSize); - } else if (held & KEY_LEFT) { + } else if(held & KEY_LEFT) { offset = std::max((s64)offset - 0x10000, 0ll); - } else if (held & KEY_RIGHT) { + } else if(held & KEY_RIGHT) { offset = std::min(offset + 0x10000, maxSize); } - } else if (held & KEY_UP) { - if(offset > 8) + } else if(held & KEY_UP) { + if(offset >= 8) offset -= 8; - } else if (held & KEY_DOWN) { - if(offset < fileSize - 8 * maxLines) + } else if(held & KEY_DOWN) { + if(offset < fileSize - 8 * maxLines && fileSize > 8 * maxLines) offset += 8; - } else if (held & KEY_LEFT) { + } else if(held & KEY_LEFT) { offset = std::max((s64)offset - 8 * maxLines, 0ll); - } else if (held & KEY_RIGHT) { + } else if(held & KEY_RIGHT) { offset = std::min(offset + 8 * maxLines, maxSize); - } else if (pressed & KEY_A) { + } else if(pressed & KEY_A) { mode = 1; - } else if (pressed & KEY_B) { + } else if(pressed & KEY_B) { break; + } else if(pressed & KEY_X) { + offset = std::min(search(offset, file), maxSize); + consoleClear(); } else if(pressed & KEY_Y) { offset = std::min(jumpToOffset(offset), maxSize); consoleClear(); } } else if(mode == 1) { - if (held & KEY_UP) { + if(held & KEY_UP) { if(cursorPosition >= 8) cursorPosition -= 8; else if(offset > 8) offset -= 8; - } else if (held & KEY_DOWN) { + } else if(held & KEY_DOWN) { if(cursorPosition < 8 * 22) cursorPosition += 8; - else if(offset < fileSize - 8 * maxLines) + else if(offset < fileSize - 8 * maxLines && fileSize > 8 * maxLines) offset += 8; cursorPosition = std::min(cursorPosition, (u8)(fileSize - offset - 1)); - } else if (held & KEY_LEFT) { + } else if(held & KEY_LEFT) { if(cursorPosition > 0) cursorPosition--; - } else if (held & KEY_RIGHT) { + } else if(held & KEY_RIGHT) { if(cursorPosition < 8 * maxLines - 1) cursorPosition = std::min((u8)(cursorPosition + 1), (u8)(fileSize - offset - 1)); - } else if (pressed & KEY_A) { + } else if(pressed & KEY_A) { if(drive < 4) { mode = 2; consoleSelect(&bottomConsoleBG); @@ -186,22 +358,25 @@ void hexEditor(const char *path, int drive) { printf("\x1B[%d;%dH\x1B[%dm\2", 1 + cursorPosition / 8, 23 + cursorPosition % 8, 31); consoleSelect(&bottomConsole); } - } else if (pressed & KEY_B) { + } else if(pressed & KEY_B) { mode = 0; + } else if(pressed & KEY_X) { + offset = std::min(search(offset, file), maxSize); + consoleClear(); } else if(pressed & KEY_Y) { offset = std::min(jumpToOffset(offset), maxSize); consoleClear(); } } else if(mode == 2) { - if (held & KEY_UP) { + if(held & KEY_UP) { data[cursorPosition]++; - } else if (held & KEY_DOWN) { + } else if(held & KEY_DOWN) { data[cursorPosition]--; - } else if (held & KEY_LEFT) { + } else if(held & KEY_LEFT) { data[cursorPosition] -= 0x10; - } else if (held & KEY_RIGHT) { + } else if(held & KEY_RIGHT) { data[cursorPosition] += 0x10; - } else if (pressed & (KEY_A | KEY_B)) { + } else if(pressed & (KEY_A | KEY_B)) { mode = 1; fseek(file, offset + cursorPosition, SEEK_SET); fwrite(data + cursorPosition, 1, 1, file);