From 61671f2ec11c8ddbd1173b914bb9de65bf32e6c5 Mon Sep 17 00:00:00 2001 From: niklascfw Date: Sun, 23 Nov 2025 00:09:05 +0100 Subject: [PATCH] Initial commit --- Makefile | 7 +- scripts/HelloWorld.te | 2 + scripts/Problembehandlung/ResetCalibration.te | 7 + scripts/Problembehandlung/SDCardCheck.te | 6 + scripts/Problembehandlung/USBReconnect.te | 5 + source/tegraexplorer/mainmenu.c | 185 ++++++++---------- tools/bin2c/bin2c | Bin 0 -> 16416 bytes tools/lz/lz77 | Bin 0 -> 16752 bytes 8 files changed, 107 insertions(+), 105 deletions(-) create mode 100644 scripts/HelloWorld.te create mode 100644 scripts/Problembehandlung/ResetCalibration.te create mode 100644 scripts/Problembehandlung/SDCardCheck.te create mode 100644 scripts/Problembehandlung/USBReconnect.te create mode 100755 tools/bin2c/bin2c create mode 100755 tools/lz/lz77 diff --git a/Makefile b/Makefile index e72adf2..e4da449 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,7 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC) ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall -Wno-missing-braces $(CUSTOMDEFINES) LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) +SCRIPT_SRCS := $(shell find scripts -name '*.te') ################################################################################ @@ -109,13 +110,13 @@ $(BUILDDIR)/$(TARGET)/script/builtin.o: $(BUILDDIR)/$(TARGET)/script/builtin.c @mkdir -p "$(@D)" $(CC) $(CFLAGS) $(BDKINC) -c $< -o $@ -$(BUILDDIR)/$(TARGET)/script/builtin.c: scripts/*.te +$(BUILDDIR)/$(TARGET)/script/builtin.c: $(SCRIPT_SRCS) @mkdir -p "$(@D)" @mkdir -p "$(BUILDDIR)/$(TARGET)/scripts" ifeq ($(OS),Windows_NT) - @py ts-minifier.py --such-meme -d "$(BUILDDIR)/$(TARGET)/scripts" $(wildcard scripts/*.te) + @py ts-minifier.py --such-meme -d "$(BUILDDIR)/$(TARGET)/scripts" $(SCRIPT_SRCS) @py te2c.py "$(BUILDDIR)/$(TARGET)/script/builtin" "$(BUILDDIR)/$(TARGET)/scripts" else - @python3 ts-minifier.py --such-meme -d "$(BUILDDIR)/$(TARGET)/scripts" $(wildcard scripts/*.te) + @python3 ts-minifier.py --such-meme -d "$(BUILDDIR)/$(TARGET)/scripts" $(SCRIPT_SRCS) @python3 te2c.py "$(BUILDDIR)/$(TARGET)/script/builtin" "$(BUILDDIR)/$(TARGET)/scripts" endif diff --git a/scripts/HelloWorld.te b/scripts/HelloWorld.te new file mode 100644 index 0000000..4f0bec7 --- /dev/null +++ b/scripts/HelloWorld.te @@ -0,0 +1,2 @@ +println("Hello world from TegraScript!") +pause() diff --git a/scripts/Problembehandlung/ResetCalibration.te b/scripts/Problembehandlung/ResetCalibration.te new file mode 100644 index 0000000..bfe8189 --- /dev/null +++ b/scripts/Problembehandlung/ResetCalibration.te @@ -0,0 +1,7 @@ +println("Joy-Con Kalibrierungshinweis") +println("Dieser Hinweis beschreibt die manuelle Neukalibrierung der Joy-Cons.") +println("") +println("1. Gehe im Hauptmenü auf \"Rekalibrieren\" oder halte L3+R3 gedrückt.") +println("2. Bewege beide Sticks in alle Richtungen und lasse sie in Mittelstellung los.") +println("3. Drücke beliebige Taste, um zurückzukehren.") +pause() diff --git a/scripts/Problembehandlung/SDCardCheck.te b/scripts/Problembehandlung/SDCardCheck.te new file mode 100644 index 0000000..aef2548 --- /dev/null +++ b/scripts/Problembehandlung/SDCardCheck.te @@ -0,0 +1,6 @@ +println("SD-Karten Schnelltest") +println("1. Entferne die SD-Karte sicher vom Switch.") +println("2. Setze die SD-Karte erneut ein und warte einige Sekunden.") +println("3. Wähle im Hauptmenü \"Mount SD\" oder starte TegraExplorer neu.") +println("Drücke den Power- oder B-Button, um fortzufahren.") +pause() diff --git a/scripts/Problembehandlung/USBReconnect.te b/scripts/Problembehandlung/USBReconnect.te new file mode 100644 index 0000000..e163680 --- /dev/null +++ b/scripts/Problembehandlung/USBReconnect.te @@ -0,0 +1,5 @@ +println("USB-Reconnect Assistent") +println("1. Ziehe das USB-Kabel kurz ab und stecke es wieder ein.") +println("2. Drücke bei Bedarf den Power-Button, um den Bildschirm zu aktivieren.") +println("3. Wenn TegraExplorer wieder reagiert, wähle mit B diese Hilfe ab.") +pause() diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index 0b4be86..eb1c6e9 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -27,22 +27,92 @@ #ifdef INCLUDE_BUILTIN_SCRIPTS #include "../../build/TegraExplorer/script/builtin.h" + +#define MAX_BUILTIN_MENU_ENTRIES (EMBEDDED_SCRIPTS_LEN * 2) + +typedef struct { + char name[64]; + int scriptIndices[EMBEDDED_SCRIPTS_LEN]; + int scriptCount; +} EmbeddedScriptFolder_t; + +static void GetScriptDisplayName(const char *fullName, char *out, size_t outSize) { + if (!out || outSize == 0) { + return; + } + + const char *start = strrchr(fullName, '/'); + start = (start) ? start + 1 : fullName; + + size_t len = 0; + while (start[len] && len < outSize - 1) { + len++; + } + + if (len >= 3 && start[len - 3] == '.' && start[len - 2] == 't' && start[len - 1] == 'e') { + len -= 3; + } + + if (len >= outSize) { + len = outSize - 1; + } + + memcpy(out, start, len); + out[len] = '\0'; +} + +static void RunEmbeddedScriptIndex(int index) { + if (index < 0 || index >= EMBEDDED_SCRIPTS_LEN) { + return; + } + + RunScriptString((char*)embedded_scripts_g[index].script, (u32)strlen(embedded_scripts_g[index].script)); +} + +static void ShowEmbeddedFolder(const EmbeddedScriptFolder_t *folder) { + if (!folder || folder->scriptCount <= 0) { + return; + } + + Vector_t ent = newVec(sizeof(MenuEntry_t), folder->scriptCount + 1); + MenuEntry_t backEntry = {.optionUnion = COLORTORGB(COLOR_WHITE), .name = "<- Zurück"}; + vecAdd(&ent, backEntry); + + char displayNames[EMBEDDED_SCRIPTS_LEN][64] = {{0}}; + for (int i = 0; i < folder->scriptCount; i++) { + int scriptIndex = folder->scriptIndices[i]; + if (scriptIndex < 0 || scriptIndex >= EMBEDDED_SCRIPTS_LEN) { + continue; + } + + GetScriptDisplayName(embedded_scripts_g[scriptIndex].name, displayNames[i], sizeof(displayNames[i])); + MenuEntry_t entry = {.optionUnion = COLORTORGB(COLOR_BLUE), .name = displayNames[i], .icon = 128}; + vecAdd(&ent, entry); + } + + int selected = (ent.count > 1) ? 1 : 0; + while (1) { + gfx_clearscreen(); + gfx_printf("%s\n\n", folder->name); + int res = newMenu(&ent, selected, 79, 28, ALWAYSREDRAW | ENABLEPAGECOUNT, ent.count - 1); + if (res <= 0) { + break; + } + + selected = res; + int scriptIndex = folder->scriptIndices[res - 1]; + RunEmbeddedScriptIndex(scriptIndex); + } + + free(ent.data); +} #endif extern hekate_config h_cfg; enum { #ifndef SCRIPT_ONLY - MainExplore = 0, - MainBrowseSd, - MainMountSd, - MainBrowseEmmc, - MainBrowseEmummc, - MainTools, - MainPartitionSd, - MainViewKeys, - MainViewCredits, - MainExit, + MainExit = 0, #else MainExit = 0, #endif @@ -56,18 +126,9 @@ enum { MenuEntry_t mainMenuEntries[] = { #ifndef SCRIPT_ONLY - [MainExplore] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "-- Explore --"}, - [MainBrowseSd] = {.optionUnion = COLORTORGB(COLOR_GREEN), .name = "Browse SD"}, - [MainMountSd] = {.optionUnion = COLORTORGB(COLOR_YELLOW)}, // To mount/unmount the SD - [MainBrowseEmmc] = {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "Browse EMMC"}, - [MainBrowseEmummc] = {.optionUnion = COLORTORGB(COLOR_BLUE), .name = "Browse EMUMMC"}, - [MainTools] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "\n-- Tools --"}, - [MainPartitionSd] = {.optionUnion = COLORTORGB(COLOR_ORANGE), .name = "Partition the sd"}, - [MainViewKeys] = {.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "View dumped keys"}, - [MainViewCredits] = {.optionUnion = COLORTORGB(COLOR_YELLOW), .name = "Credits"}, - [MainExit] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "\n-- Exit --"}, + [MainExit] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "-- Exit --"}, #else - [MainExit] = {.optionUnion = COLORTORGB(COLOR_WHITE), .name = "\n-- Exit --"}, + [MainExit] = {.optionUnion = COLORTORGB(COLOR_WHITE), .name = "-- Exit --"}, #endif [MainPowerOff] = {.optionUnion = COLORTORGB(COLOR_VIOLET), .name = "Power off"}, [MainRebootRCM] = {.optionUnion = COLORTORGB(COLOR_VIOLET), .name = "Reboot to RCM"}, @@ -77,62 +138,7 @@ MenuEntry_t mainMenuEntries[] = { [MainScripts] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "\n-- Scripts --"} }; -void HandleSD(){ - gfx_clearscreen(); - TConf.curExplorerLoc = LOC_SD; - if (!sd_mount() || sd_get_card_removed()){ - gfx_printf("Sd is not mounted!"); - hidWait(); - } - else - FileExplorer("sd:/"); -} - -void HandleEMMC(){ - GptMenu(MMC_CONN_EMMC); -} - -void HandleEMUMMC(){ - GptMenu(MMC_CONN_EMUMMC); -} - -void ViewKeys(){ - gfx_clearscreen(); - for (int i = 0; i < 3; i++){ - gfx_printf("\nBis key 0%d: ", i); - PrintKey(dumpedKeys.bis_key[i], AES_128_KEY_SIZE * 2); - } - - gfx_printf("\nMaster key 0: "); - PrintKey(dumpedKeys.master_key, AES_128_KEY_SIZE); - gfx_printf("\nHeader key: "); - PrintKey(dumpedKeys.header_key, AES_128_KEY_SIZE * 2); - gfx_printf("\nSave mac key: "); - PrintKey(dumpedKeys.save_mac_key, AES_128_KEY_SIZE); - - u8 fuseCount = 0; - for (u32 i = 0; i < 32; i++){ - if ((fuse_read_odm(7) >> i) & 1) - fuseCount++; - } - - gfx_printf("\n\nPkg1 ID: '%s'\nFuse count: %d", TConf.pkg1ID, fuseCount); - - hidWait(); -} - -void ViewCredits(){ - gfx_clearscreen(); - gfx_printf("\nTegraexplorer v%d.%d.%d\nBy SuchMemeManySkill\n\nBased on Lockpick_RCM & Hekate, from shchmue & CTCaer\n\n\n", LP_VER_MJ, LP_VER_MN, LP_VER_BF); - - if (hidRead()->r) - gfx_printf("%k\"I'm not even sure if it works\" - meme", COLOR_ORANGE); - - hidWait(); -} - extern bool sd_mounted; -extern bool is_sd_inited; extern int launch_payload(char *path); void RebootToAMS(){ @@ -143,26 +149,11 @@ void RebootToHekate(){ launch_payload("sd:/bootloader/update.bin"); } -void MountOrUnmountSD(){ - gfx_clearscreen(); - if (sd_mounted) - sd_unmount(); - else if (!sd_mount()) - hidWait(); -} - menuPaths mainMenuPaths[] = { #ifndef SCRIPT_ONLY - [MainBrowseSd] = HandleSD, - [MainMountSd] = MountOrUnmountSD, - [MainBrowseEmmc] = HandleEMMC, - [MainBrowseEmummc] = HandleEMUMMC, - [MainPartitionSd] = FormatSD, - [MainViewKeys] = ViewKeys, - [MainViewCredits] = ViewCredits, - #endif [MainRebootAMS] = RebootToAMS, [MainRebootHekate] = RebootToHekate, + #endif [MainRebootRCM] = reboot_rcm, [MainPowerOff] = power_off, [MainRebootNormal] = reboot_normal, @@ -175,16 +166,6 @@ void EnterMainMenu(){ sd_unmount(); #ifndef SCRIPT_ONLY - // -- Explore -- - mainMenuEntries[MainBrowseSd].hide = !sd_mounted; - mainMenuEntries[MainMountSd].name = (sd_mounted) ? "Unmount SD" : "Mount SD"; - mainMenuEntries[MainBrowseEmummc].hide = (!emu_cfg.enabled || !sd_mounted); - - // -- Tools -- - mainMenuEntries[MainPartitionSd].hide = (!is_sd_inited || sd_get_card_removed()); - mainMenuEntries[MainViewKeys].hide = !TConf.keysDumped; - - // -- Exit -- mainMenuEntries[MainRebootAMS].hide = (!sd_mounted || !FileExists("sd:/atmosphere/reboot_payload.bin")); mainMenuEntries[MainRebootHekate].hide = (!sd_mounted || !FileExists("sd:/bootloader/update.bin")); mainMenuEntries[MainRebootRCM].hide = h_cfg.t210b01; diff --git a/tools/bin2c/bin2c b/tools/bin2c/bin2c new file mode 100755 index 0000000000000000000000000000000000000000..9d930eb67dd246c388e169136920dc32497e49d6 GIT binary patch literal 16416 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 literal 0 HcmV?d00001 diff --git a/tools/lz/lz77 b/tools/lz/lz77 new file mode 100755 index 0000000000000000000000000000000000000000..e3481a1e48465493d5c5e98a60c98c629ca2abaa GIT binary patch literal 16752 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 JbSbz{@!wZ*KfC|{ literal 0 HcmV?d00001