252 lines
7.9 KiB
C
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);
|
|
}
|
|
}
|
|
|