Files
TegraExplorer/source/tegraexplorer/mainmenu.c
niklascfw 61671f2ec1
Some checks failed
TegraExplorer builder / build (push) Has been cancelled
Initial commit
2025-11-23 00:09:05 +01:00

252 lines
7.9 KiB
C

#include "mainmenu.h"
#include "../gfx/gfx.h"
#include "../gfx/gfxutils.h"
#include "../gfx/menu.h"
#include "tools.h"
#include "../hid/hid.h"
#include "../fs/menus/explorer.h"
#include <utils/btn.h>
#include <storage/nx_sd.h>
#include "tconf.h"
#include "../keys/keys.h"
#include "../storage/mountmanager.h"
#include "../storage/gptmenu.h"
#include "../storage/emummc.h"
#include <utils/util.h>
#include "../fs/fsutils.h"
#include <soc/fuse.h>
#include "../utils/utils.h"
#include "../config.h"
#include "../fs/readers/folderReader.h"
#include <string.h>
#include <mem/heap.h>
#include "../fs/menus/filemenu.h"
#define INCLUDE_BUILTIN_SCRIPTS 1
//#define SCRIPT_ONLY 1
#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
MainExit = 0,
#else
MainExit = 0,
#endif
MainPowerOff,
MainRebootRCM,
MainRebootNormal,
MainRebootHekate,
MainRebootAMS,
MainScripts,
};
MenuEntry_t mainMenuEntries[] = {
#ifndef SCRIPT_ONLY
[MainExit] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "-- Exit --"},
#else
[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"},
[MainRebootNormal] = {.optionUnion = COLORTORGB(COLOR_VIOLET), .name = "Reboot normally"},
[MainRebootHekate] = {.optionUnion = COLORTORGB(COLOR_VIOLET), .name = "Reboot to bootloader/update.bin"},
[MainRebootAMS] = {.optionUnion = COLORTORGB(COLOR_VIOLET), .name = "Reboot to atmosphere/reboot_payload.bin"},
[MainScripts] = {.optionUnion = COLORTORGB(COLOR_WHITE) | SKIPBIT, .name = "\n-- Scripts --"}
};
extern bool sd_mounted;
extern int launch_payload(char *path);
void RebootToAMS(){
launch_payload("sd:/atmosphere/reboot_payload.bin");
}
void RebootToHekate(){
launch_payload("sd:/bootloader/update.bin");
}
menuPaths mainMenuPaths[] = {
#ifndef SCRIPT_ONLY
[MainRebootAMS] = RebootToAMS,
[MainRebootHekate] = RebootToHekate,
#endif
[MainRebootRCM] = reboot_rcm,
[MainPowerOff] = power_off,
[MainRebootNormal] = reboot_normal,
};
void EnterMainMenu(){
int res = 0;
while (1){
if (sd_get_card_removed())
sd_unmount();
#ifndef SCRIPT_ONLY
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;
#endif
// -- Scripts --
#ifndef INCLUDE_BUILTIN_SCRIPTS
mainMenuEntries[MainScripts].hide = (!sd_mounted || !FileExists("sd:/tegraexplorer/scripts"));
#else
mainMenuEntries[MainScripts].hide = ((!sd_mounted || !FileExists("sd:/tegraexplorer/scripts")) && !EMBEDDED_SCRIPTS_LEN);
#endif
Vector_t ent = newVec(sizeof(MenuEntry_t), ARRAY_SIZE(mainMenuEntries));
ent.count = ARRAY_SIZE(mainMenuEntries);
memcpy(ent.data, mainMenuEntries, sizeof(MenuEntry_t) * ARRAY_SIZE(mainMenuEntries));
Vector_t scriptFiles = {0};
u8 hasScripts = 0;
#ifdef INCLUDE_BUILTIN_SCRIPTS
for (int i = 0; i < EMBEDDED_SCRIPTS_LEN; i++){
MenuEntry_t m = {.name = embedded_scripts_g[i].name, .optionUnion = COLORTORGB(COLOR_BLUE), .icon = 128};
vecAdd(&ent, m);
}
#endif
if (sd_mounted && FileExists("sd:/tegraexplorer/scripts")){
scriptFiles = ReadFolder("sd:/tegraexplorer/scripts", &res);
if (!res){
if (!scriptFiles.count){
FREE(scriptFiles.data);
mainMenuEntries[MainScripts].hide = 1;
}
else {
hasScripts = 1;
vecForEach(FSEntry_t*, scriptFile, (&scriptFiles)){
if (!scriptFile->isDir && StrEndsWith(scriptFile->name, ".te")){
MenuEntry_t a = MakeMenuOutFSEntry(*scriptFile);
vecAdd(&ent, a);
}
}
if (ent.count == ARRAY_SIZE(mainMenuEntries)){
clearFileVector(&scriptFiles);
hasScripts = 0;
mainMenuEntries[MainScripts].hide = 1;
}
}
}
}
gfx_clearscreen();
gfx_putc('\n');
res = newMenu(&ent, res, 79, 30, (ent.count == ARRAY_SIZE(mainMenuEntries)) ? ALWAYSREDRAW : ALWAYSREDRAW | ENABLEPAGECOUNT, ent.count - ARRAY_SIZE(mainMenuEntries));
if (res < MainScripts && mainMenuPaths[res] != NULL)
mainMenuPaths[res]();
#ifndef INCLUDE_BUILTIN_SCRIPTS
else if (hasScripts){
#else
else {
if (res - ARRAY_SIZE(mainMenuEntries) < EMBEDDED_SCRIPTS_LEN){
char *script = embedded_scripts_g[res - ARRAY_SIZE(mainMenuEntries)].script;
RunScriptString(script, strlen(script));
}
else {
#endif
vecDefArray(MenuEntry_t*, entArray, ent);
MenuEntry_t entry = entArray[res];
FSEntry_t fsEntry = {.name = entry.name, .sizeUnion = entry.sizeUnion};
RunScript("sd:/tegraexplorer/scripts", fsEntry);
#ifdef INCLUDE_BUILTIN_SCRIPTS
}
#endif
}
if (hasScripts){
clearFileVector(&scriptFiles);
}
free(ent.data);
}
}