forked from Mirror/GodMode9
Scripting: add keysel command
This commit is contained in:
parent
8628e18d35
commit
0caf2a6cbb
@ -56,3 +56,24 @@ bool CheckButton(u32 button) {
|
|||||||
for(; (t_pressed < 0x13000) && ((HID_STATE & button) == button); t_pressed++);
|
for(; (t_pressed < 0x13000) && ((HID_STATE & button) == button); t_pressed++);
|
||||||
return (t_pressed >= 0x13000);
|
return (t_pressed >= 0x13000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ButtonToString(u32 button, char* str) {
|
||||||
|
const char* strings[] = { BUTTON_STRINGS };
|
||||||
|
|
||||||
|
*str = '\0';
|
||||||
|
if (button) {
|
||||||
|
u32 b = 0;
|
||||||
|
for (b = 0; !((button>>b)&0x1); b++);
|
||||||
|
if (b < countof(strings)) strcpy(str, strings[b]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 StringToButton(char* str) {
|
||||||
|
const char* strings[] = { BUTTON_STRINGS };
|
||||||
|
|
||||||
|
u32 b = 0;
|
||||||
|
for (b = 0; b < countof(strings); b++)
|
||||||
|
if (strcmp(str, strings[b]) == 0) break;
|
||||||
|
|
||||||
|
return (b == countof(strings)) ? 0 : 1<<b;
|
||||||
|
}
|
||||||
|
@ -33,6 +33,12 @@
|
|||||||
#define SD_EJECT (1 << 17)
|
#define SD_EJECT (1 << 17)
|
||||||
#define TIMEOUT_HID (1 << 31)
|
#define TIMEOUT_HID (1 << 31)
|
||||||
|
|
||||||
|
// strings for button conversion
|
||||||
|
#define BUTTON_STRINGS "A", "B", "SELECT", "START", "RIGHT", "LEFT", "UP", "DOWN", "R", "L", "X", "Y"
|
||||||
|
|
||||||
|
|
||||||
u32 InputWait(u32 timeout_sec);
|
u32 InputWait(u32 timeout_sec);
|
||||||
bool CheckButton(u32 button);
|
bool CheckButton(u32 button);
|
||||||
|
|
||||||
|
void ButtonToString(u32 button, char* str);
|
||||||
|
u32 StringToButton(char* str);
|
||||||
|
@ -599,6 +599,41 @@ u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...) {
|
|||||||
return (sel >= n) ? 0 : sel + 1;
|
return (sel >= n) ? 0 : sel + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...) {
|
||||||
|
char str[STRBUF_SIZE] = { 0 };
|
||||||
|
char* ptr = str;
|
||||||
|
va_list va;
|
||||||
|
va_start(va, format);
|
||||||
|
ptr += vsnprintf(ptr, STRBUF_SIZE, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
ptr += snprintf(ptr, STRBUF_SIZE - (ptr-str), "\n ");
|
||||||
|
for (u32 i = 0; i < n; i++) {
|
||||||
|
char buttonstr[16];
|
||||||
|
ButtonToString(keys[i], buttonstr);
|
||||||
|
ptr += snprintf(ptr, STRBUF_SIZE - (ptr-str), "\n<%s> %s", buttonstr, options[i]);
|
||||||
|
}
|
||||||
|
ptr += snprintf(ptr, STRBUF_SIZE - (ptr-str), "\n \n<%s> %s", "B", "cancel");
|
||||||
|
|
||||||
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
DrawStringCenter(MAIN_SCREEN, COLOR_STD_FONT, COLOR_STD_BG, "%s", str);
|
||||||
|
|
||||||
|
u32 sel = 0;
|
||||||
|
while (!sel) {
|
||||||
|
u32 pad_state = InputWait(0);
|
||||||
|
if (pad_state & BUTTON_B) break;
|
||||||
|
for (u32 i = 0; i < n; i++) {
|
||||||
|
if (keys[i] & pad_state) {
|
||||||
|
sel = i+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShowInputPrompt(char* inputstr, u32 max_size, u32 resize, const char* alphabet, const char *format, va_list va) {
|
bool ShowInputPrompt(char* inputstr, u32 max_size, u32 resize, const char* alphabet, const char *format, va_list va) {
|
||||||
const u32 alphabet_size = strnlen(alphabet, 256);
|
const u32 alphabet_size = strnlen(alphabet, 256);
|
||||||
const u32 input_shown = 22;
|
const u32 input_shown = 22;
|
||||||
|
@ -73,6 +73,7 @@ void ShowString(const char *format, ...);
|
|||||||
void ShowIconString(u8* icon, int w, int h, const char *format, ...);
|
void ShowIconString(u8* icon, int w, int h, const char *format, ...);
|
||||||
bool ShowPrompt(bool ask, const char *format, ...);
|
bool ShowPrompt(bool ask, const char *format, ...);
|
||||||
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
u32 ShowSelectPrompt(u32 n, const char** options, const char *format, ...);
|
||||||
|
u32 ShowHotkeyPrompt(u32 n, const char** options, const u32* keys, const char *format, ...);
|
||||||
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...);
|
||||||
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);
|
u64 ShowHexPrompt(u64 start_val, u32 n_digits, const char *format, ...);
|
||||||
u64 ShowNumberPrompt(u64 start_val, const char *format, ...);
|
u64 ShowNumberPrompt(u64 start_val, const char *format, ...);
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
#define _FLG(c) ((c >= 'a') ? (1 << (c - 'a')) : 0)
|
#define _FLG(c) ((c >= 'a') ? (1 << (c - 'a')) : 0)
|
||||||
|
|
||||||
#define IS_CTRLFLOW_CMD(id) ((id == CMD_ID_IF) || (id == CMD_ID_ELIF) || (id == CMD_ID_ELSE) || (id == CMD_ID_END) || \
|
#define IS_CTRLFLOW_CMD(id) ((id == CMD_ID_IF) || (id == CMD_ID_ELIF) || (id == CMD_ID_ELSE) || (id == CMD_ID_END) || \
|
||||||
(id == CMD_ID_GOTO) || (id == CMD_ID_LABELSEL) || \
|
(id == CMD_ID_GOTO) || (id == CMD_ID_LABELSEL) || (id == CMD_ID_KEYSEL) || \
|
||||||
(id == CMD_ID_FOR) || (id == CMD_ID_NEXT))
|
(id == CMD_ID_FOR) || (id == CMD_ID_NEXT))
|
||||||
|
|
||||||
// command ids (also entry into the cmd_list array below)
|
// command ids (also entry into the cmd_list array below)
|
||||||
@ -75,6 +75,7 @@ typedef enum {
|
|||||||
CMD_ID_NEXT,
|
CMD_ID_NEXT,
|
||||||
CMD_ID_GOTO,
|
CMD_ID_GOTO,
|
||||||
CMD_ID_LABELSEL,
|
CMD_ID_LABELSEL,
|
||||||
|
CMD_ID_KEYSEL,
|
||||||
CMD_ID_ECHO,
|
CMD_ID_ECHO,
|
||||||
CMD_ID_QR,
|
CMD_ID_QR,
|
||||||
CMD_ID_ASK,
|
CMD_ID_ASK,
|
||||||
@ -143,6 +144,7 @@ Gm9ScriptCmd cmd_list[] = {
|
|||||||
{ CMD_ID_NEXT , _CMD_NEXT , 0, 0 },
|
{ CMD_ID_NEXT , _CMD_NEXT , 0, 0 },
|
||||||
{ CMD_ID_GOTO , "goto" , 1, 0 },
|
{ CMD_ID_GOTO , "goto" , 1, 0 },
|
||||||
{ CMD_ID_LABELSEL, "labelsel", 2, 0 },
|
{ CMD_ID_LABELSEL, "labelsel", 2, 0 },
|
||||||
|
{ CMD_ID_KEYSEL , "keysel" , 2, 0 },
|
||||||
{ CMD_ID_ECHO , "echo" , 1, 0 },
|
{ CMD_ID_ECHO , "echo" , 1, 0 },
|
||||||
{ CMD_ID_QR , "qr" , 2, 0 },
|
{ CMD_ID_QR , "qr" , 2, 0 },
|
||||||
{ CMD_ID_ASK , "ask" , 1, 0 },
|
{ CMD_ID_ASK , "ask" , 1, 0 },
|
||||||
@ -916,16 +918,16 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "label not found");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "label not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (id == CMD_ID_LABELSEL) {
|
else if ((id == CMD_ID_LABELSEL) || (id == CMD_ID_KEYSEL)) {
|
||||||
const char* options[_CHOICE_MAX_N] = { NULL };
|
const char* options[_CHOICE_MAX_N] = { NULL };
|
||||||
char* options_jmp[_CHOICE_MAX_N] = { NULL };
|
char* options_jmp[_CHOICE_MAX_N] = { NULL };
|
||||||
char options_str[_CHOICE_MAX_N][_CHOICE_STR_LEN+1];
|
char options_str[_CHOICE_MAX_N][_CHOICE_STR_LEN+1];
|
||||||
|
u32 options_keys[_CHOICE_MAX_N] = { 0 };
|
||||||
|
|
||||||
char* ast = strchr(argv[1], '*');
|
char* ast = strchr(argv[1], '*');
|
||||||
char* ptr = NULL;
|
char* ptr = NULL;
|
||||||
u32 n_opt = 0;
|
u32 n_opt = 0;
|
||||||
while ((ptr = find_label(argv[1], ptr))) {
|
while ((ptr = find_label(argv[1], ptr))) {
|
||||||
options[n_opt] = options_str[n_opt];
|
|
||||||
options_jmp[n_opt] = ptr;
|
options_jmp[n_opt] = ptr;
|
||||||
|
|
||||||
while (*(ptr++) != '@');
|
while (*(ptr++) != '@');
|
||||||
@ -937,10 +939,21 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
else if (ptr[i] == '_') choice[i] = ' ';
|
else if (ptr[i] == '_') choice[i] = ' ';
|
||||||
else choice[i] = ptr[i];
|
else choice[i] = ptr[i];
|
||||||
}
|
}
|
||||||
|
if (id == CMD_ID_KEYSEL) {
|
||||||
|
char* keystr = choice;
|
||||||
|
for (; *choice != ' ' && *choice != '\0'; choice++);
|
||||||
|
if (*choice != '\0') *(choice++) = '\0';
|
||||||
|
options_keys[n_opt] = StringToButton(keystr);
|
||||||
|
if (!options_keys[n_opt]) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
options[n_opt] = choice;
|
||||||
if (++n_opt >= _CHOICE_MAX_N) break;
|
if (++n_opt >= _CHOICE_MAX_N) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 result = ShowSelectPrompt(n_opt, options, "%s", argv[0]);
|
u32 result = (id == CMD_ID_LABELSEL) ? ShowSelectPrompt(n_opt, options, "%s", argv[0]) :
|
||||||
|
ShowHotkeyPrompt(n_opt, options, options_keys, "%s", argv[0]);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
ret = false;
|
ret = false;
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "user abort");
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "user abort");
|
||||||
|
@ -1,308 +0,0 @@
|
|||||||
# GodMode9 "Hello Script"
|
|
||||||
# Tutorial script - read / run this to learn how it works
|
|
||||||
# last changed: 20170906
|
|
||||||
# author: d0k3
|
|
||||||
|
|
||||||
# COMMENTS / SCRIPTING BASICS / 'echo' COMMAND
|
|
||||||
# Anything after '#' will be ignored by the scripting engine
|
|
||||||
# Commands and arguments are separated by whitespaces, any redundant whitespaces will be ignored
|
|
||||||
# Use '"' if an argument has to include whitespaces
|
|
||||||
# The echo command outputs info on screen
|
|
||||||
echo "'Hello Script'\nby d0k3\n \nThis is a sample script to\nshowcase the GM9 script engine." # comments work anywhere
|
|
||||||
# Unknown commands lead to script abort (remove the '#' below to test)
|
|
||||||
# iamunknown test test
|
|
||||||
|
|
||||||
# 'qr' COMMAND
|
|
||||||
# The 'qr' command does the same as the echo command, but also displays a QR code on the top screen
|
|
||||||
qr "Scan for cool stuff!" https://github.com/d0k3/GodMode9
|
|
||||||
|
|
||||||
# 'ask' COMMAND
|
|
||||||
# The 'ask' command is similar to the 'echo' command, but will allow the user to abort
|
|
||||||
# Note that normally any failed command (like a negative user response on 'ask') will result in script abort
|
|
||||||
ask "Continue running this script?"
|
|
||||||
|
|
||||||
# (-o/-s) SWITCHES
|
|
||||||
# You may use the -o / --optional and -s / --silent switches on any command
|
|
||||||
# -o / --optional continues on failures
|
|
||||||
# -s / --silent tries to suppress all error messages
|
|
||||||
# This would have completely ignored the user response on the previous command:
|
|
||||||
ask -o -s "Really continue running this script?\n(I will completely ignore your answer)"
|
|
||||||
|
|
||||||
# ENVIRONMENTAL VARS
|
|
||||||
# GM9VER is the GodMode9 version number
|
|
||||||
# REGION is the region of your device's SysNAND (USA, EUR, JPN, KOR, CHN, TWN or UNK for unknown)
|
|
||||||
# SERIAL is the serial number of your device
|
|
||||||
# GM9OUT is the standard output path
|
|
||||||
# CURRDIR is the directory the script is running from
|
|
||||||
# HAX is the hax the system is currently running from ("ntrboot", "sighax", "a9lh" or empty)
|
|
||||||
# ONTYPE is the console type ("O3DS" or "N3DS")
|
|
||||||
# RDTYPE is the unit type ("devkit" or "retail")
|
|
||||||
# SYSID0 is the id0 belonging to your SysNAND
|
|
||||||
# EMUID0 is the id0 belonging to your EmuNAND (if available)
|
|
||||||
# TIMESTAMP is the current time in hhmmss format
|
|
||||||
# DATESTAMP is the current date in YYMMDD format
|
|
||||||
# Use $[VAR] to get the *content* of a variable VAR
|
|
||||||
echo "Your GodMode9 version is $[GM9VER]\nYour region is $[REGION]\nYour serial number is $[SERIAL]\nYour std output path is $[GM9OUT]\nCurrent dir is $[CURRDIR]\nCurrent hax is $[HAX]\nYour system is a $[RDTYPE] $[ONTYPE]\nCurrent datestamp is: $[DATESTAMP]\nCurrent timestamp is: $[TIMESTAMP]\n \nYour sys / emu ID0 is:\n$[SYSID0]\n$[EMUID0]"
|
|
||||||
qr "You can also have this as a QR code :)" "Your GodMode9 version is $[GM9VER]\nYour region is $[REGION]\nYour serial number is $[SERIAL]\nYour std output path is $[GM9OUT]\nCurrent dir is $[CURRDIR]\nCurrent hax is $[HAX]\nYour system is a $[RDTYPE] $[ONTYPE]\nCurrent datestamp is: $[DATESTAMP]\nCurrent timestamp is: $[TIMESTAMP]\n \nYour sys / emu ID0 is:\n$[SYSID0]\n$[EMUID0]"
|
|
||||||
|
|
||||||
# ERRORMSG and SUCCESSMSG / 'set' COMMAND
|
|
||||||
# These two are special environment vars, allowing you to control the message on script failure or success
|
|
||||||
set ERRORMSG "HelloScript testing script failed"
|
|
||||||
set SUCCESSMSG "HelloScript testing script success"
|
|
||||||
# you can also reset these to return to default script messages
|
|
||||||
# set ERRORMSG ""
|
|
||||||
# set SUCCESSMSG ""
|
|
||||||
|
|
||||||
# 'chk' COMMAND
|
|
||||||
# Using the check command, you can check if two arguments match (not case sensitive)
|
|
||||||
# -u / -unequal check if not matching instead
|
|
||||||
# These checks will (most likely) pass
|
|
||||||
chk "hello" "HeLlo"
|
|
||||||
chk "0:/gm9/out" $[GM9OUT]
|
|
||||||
chk $[SYSID0] $[SYSID0]
|
|
||||||
# unsure about these
|
|
||||||
chk -o $[HAX] "sighax"
|
|
||||||
chk -o -u $[HAX] ""
|
|
||||||
|
|
||||||
# PREVIEW_MODE, PREVIEW_COLOR_ACTIVE, PREVIEW_COLOR_COMMENT and PREVIEW_COLOR_CODE
|
|
||||||
# PREVIEW_MODE controls how the preview on the top screen is displayed, set it it to off, quick or full
|
|
||||||
# PREVIEW_COLOR_ACTIVE, PREVIEW_COLOR_COMMENT and PREVIEW_COLOR_CODE set the colors of the preview (RGB, hex)
|
|
||||||
set PREVIEW_MODE quick
|
|
||||||
# we don't want these ugly colors
|
|
||||||
# set PREVIEW_COLOR_ACTIVE 00FF00
|
|
||||||
# set PREVIEW_COLOR_COMMENT 0000FF
|
|
||||||
# set PREVIEW_COLOR_CODE FF0000
|
|
||||||
|
|
||||||
# CREATING VARS
|
|
||||||
# You can also create new variables using 'set'
|
|
||||||
# Notice how you can use variables when setting variables
|
|
||||||
set TESTPATH 0:/testdir/$[SERIAL]_tick.db
|
|
||||||
echo "Your testpath is:\n$[TESTPATH]"
|
|
||||||
|
|
||||||
# 'input' COMMAND
|
|
||||||
# The 'input' command will allow the user to input a string and store that string in a variable
|
|
||||||
# Preset the variable to have an initial value
|
|
||||||
set USERINPUT "Hello World"
|
|
||||||
input "Enter something please?" USERINPUT
|
|
||||||
echo "You entered:\n$[USERINPUT]"
|
|
||||||
|
|
||||||
# 'strsplit' COMMAND
|
|
||||||
# The 'strsplit' command extracts a substring from a string
|
|
||||||
# -b / --before extracts the substring *before* the split char
|
|
||||||
# -f / --first matches the first, not last occurence of the split char
|
|
||||||
strsplit TESTSPLIT1 "one/two/three" "/"
|
|
||||||
strsplit -b TESTSPLIT2 "one/two/three" "/"
|
|
||||||
strsplit -f TESTSPLIT3 "one/two/three" "/"
|
|
||||||
strsplit -b -f TESTSPLIT4 "one/two/three" "/"
|
|
||||||
echo "one/two/three\n$[TESTSPLIT1]\n$[TESTSPLIT2]\n$[TESTSPLIT3]\n$[TESTSPLIT4]"
|
|
||||||
|
|
||||||
# strrep COMMAND
|
|
||||||
# The 'strrep' command replaces one char with another inside a string
|
|
||||||
# notice how we use TESTREP both as input and output
|
|
||||||
set TESTREP "Hello_World"
|
|
||||||
strrep TESTREP $[TESTREP] "_ "
|
|
||||||
echo $[TESTREP]
|
|
||||||
|
|
||||||
# 'filesel' COMMAND
|
|
||||||
# The 'filesel' command allows the user to choose a file inside a directory
|
|
||||||
# The path is stored inside a variable, and the selection can be limited via wildcards
|
|
||||||
# -d / --include_dirs allows to browse folders and select files inside
|
|
||||||
filesel "Please select a file" 0:/*.* SELFILE
|
|
||||||
|
|
||||||
# 'dirsel' COMMAND
|
|
||||||
# The 'dirsel' command works identically to the 'filesel' command, but allows selecting a dir
|
|
||||||
# Note that a final slash ('/') is not expected here and there can be no wildcard pattern.
|
|
||||||
dirsel "Now, select a dir" 0: SELDIR
|
|
||||||
echo "You selected $[SELFILE]\nand $[SELDIR]\nWe'll do nothing with either :)."
|
|
||||||
|
|
||||||
# 'allow' COMMAND
|
|
||||||
# typically used at the beginning of a script, prompts to allow writes to the location given in the argument
|
|
||||||
# doing this from the beginning is preferable, so that no actions are taken unless all required write permissions are unlocked
|
|
||||||
# (note #1: without 'allow', write permissions are still in place and the user will be asked on demand)
|
|
||||||
# (note #2: this simple testing script requires no additional permissions, thus the command is hidden behind a '#')
|
|
||||||
# -a / --all allows writes to the specified location and all included files and directories
|
|
||||||
# allow -a M:/
|
|
||||||
|
|
||||||
# 'rm' COMMAND
|
|
||||||
# The 'rm' command is used to remove files and directories (recursively)
|
|
||||||
# Here, we remove the dir if it is still here from an earlier run of this script
|
|
||||||
# If it is not here, we ignore any errors and keep silent about it
|
|
||||||
rm -o -s 0:/testdir
|
|
||||||
|
|
||||||
# 'mkdir' COMMAND
|
|
||||||
# Use this to create a directory at the specified location
|
|
||||||
mkdir 0:/testdir
|
|
||||||
|
|
||||||
# 'imgmount' COMMAND
|
|
||||||
# The 'imgmount' command is used to mount an image.
|
|
||||||
# An image can be (among other things) FAT, NAND, NCCH, NCSD, FIRM, ticket.db...
|
|
||||||
imgmount S:/ctrnand_full.bin
|
|
||||||
|
|
||||||
# 'cp' COMMAND
|
|
||||||
# Use 'cp' to copy a file or directory (recursively)
|
|
||||||
# -h / --hash also adds a .sha file containing the files SHA256
|
|
||||||
# -w / --overwite forces overwrite on existing files
|
|
||||||
# -k / --skip forces skip on existing files
|
|
||||||
# -n / --no_cancel prevents user cancels (useful on critical operations)
|
|
||||||
cp -h -w -n 7:/dbs/ticket.db $[TESTPATH]
|
|
||||||
|
|
||||||
# 'imgumount' COMMAND
|
|
||||||
# This unmounts the current mounted image.
|
|
||||||
imgumount
|
|
||||||
|
|
||||||
# 'findnot' COMMAND
|
|
||||||
# Use 'findnot' in conjunction with '?' to find an unused filename
|
|
||||||
findnot $[TESTPATH]_???.rn RENPATH
|
|
||||||
|
|
||||||
# 'mv' COMMAND
|
|
||||||
# The 'mv command renames or moves a file or directory
|
|
||||||
# -w / --overwite forces overwrite on existing files
|
|
||||||
# -k / --skip forces skip on existing files
|
|
||||||
# -n / --no_cancel prevents user cancels (useful on critical operations)
|
|
||||||
mv -w -k $[TESTPATH] $[RENPATH]
|
|
||||||
|
|
||||||
# 'find' COMMAND
|
|
||||||
# The 'find' command has two main uses, (1) checking if files / dirs exist and (2) finding files / dirs
|
|
||||||
# Here we use it to check for RENPATH, thus we use NULL as second argument (we're not interested in the output)
|
|
||||||
find $[RENPATH] NULL
|
|
||||||
# Wildcards ('*' / '?') are allowed when searching for a file / directory name
|
|
||||||
# If wildcards are used, 'find' will return the last alphanumerical match
|
|
||||||
# -f / --first return the first alphanumerical match instead
|
|
||||||
find S:/nand.* NANDIMAGE
|
|
||||||
|
|
||||||
# 'sha' COMMAND
|
|
||||||
# Use this to check a files' SHA256
|
|
||||||
sha $[RENPATH] $[TESTPATH].sha
|
|
||||||
# Instead of an .sha file you can also use the SHA256 in hex as second argument
|
|
||||||
# sha S:/sector0x96.bin 82F2730D2C2DA3F30165F987FDCCAC5CBAB24B4E5F65C981CD7BE6F438E6D9D3
|
|
||||||
# This also allows partial SHA checks (for @x:y handling see 'inject' below)
|
|
||||||
# sha S:/firm0.bin@100:100 078CC0CFD850A27093DDA2630C3603CA0C96969BD1F26DA48AC7B1BAE5DD5219
|
|
||||||
|
|
||||||
# 'shaget' COMMAND
|
|
||||||
# Use this to calculate (and store) a files' SHA256
|
|
||||||
# If the second argument is a filename, the SHA256 will be stored there
|
|
||||||
# shaget 0:/boot.firm 0:/boot.firm.sha
|
|
||||||
# If it's a variable, it will be stored there temporarily instead
|
|
||||||
shaget S:/nand_hdr.bin NANDHDRSHA
|
|
||||||
sha S:/nand_hdr.bin $[NANDHDRSHA]
|
|
||||||
# Partial SHA calculation is also possible (for @x:y handling see 'inject' below)
|
|
||||||
# shaget 0:/boot.firm@100:100 0:/boot.firm.partial.sha
|
|
||||||
|
|
||||||
# 'inject' COMMAND
|
|
||||||
# This command is used to inject part of one file into another
|
|
||||||
# The syntax is: inject origin@x:y destination@z
|
|
||||||
# x: origin offset (in hex)
|
|
||||||
# y: origin size, starting at x (in hex)
|
|
||||||
# z: destination offset (in hex)
|
|
||||||
# If destination does not exist or z is not given, a new destination file will be created(!)
|
|
||||||
# If x is not given, the full origin file size, starting from offset 0, is used to inject
|
|
||||||
# If y is not given, everything starting from offset x is used to inject
|
|
||||||
# -n / --no_cancel prevents user cancels (useful on critical operations)
|
|
||||||
inject S:/nand_hdr.bin@100:4 $[RENPATH]@200 # offsets and sizes are in hex
|
|
||||||
# As we just deliberately corrupted our test file, the subsequent SHA check will fail
|
|
||||||
set ERRORMSG "SHA check failed (this was expected)"
|
|
||||||
sha -o $[RENPATH] $[TESTPATH].sha
|
|
||||||
set ERRORMSG ""
|
|
||||||
|
|
||||||
# 'fdummy' COMMAND
|
|
||||||
# This command creates a dummy file of the specified size (size in hex)
|
|
||||||
# Contents of the dummy file are undefined and existing files won't be overwritten
|
|
||||||
set DUMMY 0:/testdir/dummy.bin
|
|
||||||
fdummy $[DUMMY] 400
|
|
||||||
|
|
||||||
# 'fill' COMMAND
|
|
||||||
# This command fills (a portition of) a file with the specified byte value
|
|
||||||
# The syntax is: fill destination@x:y fillbyte
|
|
||||||
# x: destination offset (in hex)
|
|
||||||
# y: destination size, starting at x (in hex)
|
|
||||||
# If x is not given, the full file size, starting from offset 0, is overwritten
|
|
||||||
# If y is not given, everything starting from offset x is overwritten
|
|
||||||
# -n / --no_cancel prevents user cancels (useful on critical operations)
|
|
||||||
fill $[DUMMY]@100:100 FF
|
|
||||||
fill $[DUMMY]@300 80
|
|
||||||
|
|
||||||
# 'fset' COMMAND
|
|
||||||
# This command sets a portition of a file with the specified data in hex
|
|
||||||
# The syntax is: fset destination@x hexdata
|
|
||||||
# x: destination offset (in hex)
|
|
||||||
# y: bytes to write (in hex) (must be lower than hexdata size)
|
|
||||||
# If x is not given, data is inserted at the beginning of the file
|
|
||||||
# If y is not given, all of hexdata is written to the file
|
|
||||||
# -e / --flip_endian flips the order of the bytes
|
|
||||||
fset $[DUMMY]@100 48454c4c4f # 'HELLO'
|
|
||||||
|
|
||||||
# 'fget' COMMAND
|
|
||||||
# This command reads data from a file and stores it in a var
|
|
||||||
# The syntax is: fset origin@x:y var
|
|
||||||
# x: origin offset (in hex)
|
|
||||||
# y: origin size, starting at x (in hex)
|
|
||||||
# Both x and y have to be set(!)
|
|
||||||
# -e / --flip_endian flips the order of the bytes
|
|
||||||
fget -e $[DUMMY]@100:5 OLLEH
|
|
||||||
echo "This is 'HELLO', in hex and reverse:\n$[OLLEH]"
|
|
||||||
|
|
||||||
# 'fixcmac' COMMAND
|
|
||||||
# Use this to fix the CMACs for a file or a whole folder (recursively)
|
|
||||||
# This will count as success if a file does not contain a CMAC
|
|
||||||
# More info on CMACs: http://3dbrew.org/wiki/Savegames#AES_CMAC_header
|
|
||||||
# fixcmac 1:/data
|
|
||||||
|
|
||||||
# 'verify' COMMAND
|
|
||||||
# Certain file formats (NAND, NCCH, NCSD, CIA, FIRM, ...) can also be verified. Use 'verify' to do so.
|
|
||||||
# verify -o s:/firm0.bin # As drive letters are case sensitive, this would fail
|
|
||||||
verify S:/firm1.bin
|
|
||||||
|
|
||||||
# 'decrypt' COMMAND
|
|
||||||
# Certain file formats (NCCH, NCSD, CIA, FIRM, BOSS, ...) can be decrypted. Use 'decrypt' to do so.
|
|
||||||
# Take note that all crypto operations are done INPLACE and will overwrite the file(!)
|
|
||||||
# decrypt 0:/x.ncch
|
|
||||||
|
|
||||||
# 'encrypt' COMMAND
|
|
||||||
# Certain file formats (NCCH, NCSD, CIA, BOSS, ...) can be encrypted. Use 'encrypt' to do so.
|
|
||||||
# Take note that all crypto operations are done INPLACE and will overwrite the file(!)
|
|
||||||
# encrypt 0:/x.ncch
|
|
||||||
|
|
||||||
# 'buildcia' COMMAND
|
|
||||||
# You can build CIA files from certain file formats (TMD, NCCH, NCSD ...). Use 'buildcia' to do so.
|
|
||||||
# CIA files will always be built to the standard output directory (0:/gm9/out)
|
|
||||||
# -l / --legit force CIA to be legit (only works for legit system installed titles)
|
|
||||||
# buildcia 0:/x.ncch
|
|
||||||
|
|
||||||
# 'sdump' COMMAND
|
|
||||||
# This command dumps a supported file to the standard output directory (0:/gm9/out)
|
|
||||||
# Supported files: encTitleKeys.bin, decTitleKeys.bin, seeddb.bin
|
|
||||||
# -w / --overwrite overwrite existing files without asking
|
|
||||||
# sdump encTitleKeys.bin
|
|
||||||
# sdump decTitleKeys.bin
|
|
||||||
# sdump seeddb.bin
|
|
||||||
|
|
||||||
# 'applyips' COMMAND
|
|
||||||
# This will apply the given IPS-formatted delta patch (argument 1) to the specified file (argument 2)
|
|
||||||
# to produce the patched file (argument 3). 2 and 3 may be the same to perform an in-place patch.
|
|
||||||
# applyips 0:/example/patch.ips 0:/data/original.bin 0:/game/modded.bin
|
|
||||||
|
|
||||||
# 'applybps' COMMAND
|
|
||||||
# This will apply the given BPS-formatted delta patch (argument 1) to the specified file (argument 2)
|
|
||||||
# to produce the patched file (argument 3).
|
|
||||||
# applybps 0:/example/patch.bps 0:/data/original.bin 0:/game/modded.bin
|
|
||||||
|
|
||||||
# 'applybpm' COMMAND
|
|
||||||
# This will apply the given BPM-formatted delta patch (argument 1) to the specified directory (argument 2)
|
|
||||||
# to produce a directory containing patched files (argument 3).
|
|
||||||
# applybpm 0:/example/patch.bpm 0:/data/originalfolder 0:/game/moddedfolder
|
|
||||||
|
|
||||||
# 'boot' COMMAND
|
|
||||||
# Use this command to chainload a compatible FIRM
|
|
||||||
# boot 0:/boot.firm
|
|
||||||
# disabled cause it would leave the script
|
|
||||||
|
|
||||||
# 'switchsd' COMMAND
|
|
||||||
# Use this to allow the user to switch the SD card
|
|
||||||
# switchsd "Please switch SD card."
|
|
||||||
|
|
||||||
# 'reboot' / 'poweroff' COMMAND
|
|
||||||
# These are used to reboot or power off the 3DS console
|
|
||||||
set ERRORMSG "Test script finished,\n(without reboot)\n \nIgnore the error message."
|
|
||||||
ask "Reboot now?"
|
|
||||||
reboot
|
|
||||||
poweroff # this line can never be reached
|
|
@ -1,19 +0,0 @@
|
|||||||
# line 1: bad # of args
|
|
||||||
echo -o "#"
|
|
||||||
|
|
||||||
# This works.
|
|
||||||
echo "check #"
|
|
||||||
|
|
||||||
# The % symbol disappears.
|
|
||||||
echo "%"
|
|
||||||
echo "check %"
|
|
||||||
|
|
||||||
# error message fail
|
|
||||||
echo "-"
|
|
||||||
|
|
||||||
# This works.
|
|
||||||
echo "check -"
|
|
||||||
|
|
||||||
# Probably not bug. Syntax abuse but adding it here anyway.
|
|
||||||
bkpt
|
|
||||||
echo """
|
|
@ -1,4 +0,0 @@
|
|||||||
sdump -w encTitleKeys.bin
|
|
||||||
sdump -w decTitleKeys.bin
|
|
||||||
sdump -w seeddb.bin
|
|
||||||
sdump -o -w shalalala.bin
|
|
@ -69,6 +69,38 @@ labelsel -o -s "Choose preview mode" choice_*
|
|||||||
goto outside
|
goto outside
|
||||||
|
|
||||||
|
|
||||||
|
# keysel sample code
|
||||||
|
@spaghetti_keysel_example
|
||||||
|
|
||||||
|
@kchoice_X_Preview_off
|
||||||
|
set PREVIEW_MODE off
|
||||||
|
goto kchooser
|
||||||
|
|
||||||
|
@kchoice_Y_Preview_quick
|
||||||
|
set PREVIEW_MODE quick
|
||||||
|
goto kchooser
|
||||||
|
|
||||||
|
@kchoice_R_Preview_full
|
||||||
|
set PREVIEW_MODE full
|
||||||
|
goto kchooser
|
||||||
|
|
||||||
|
@kchoice_L_Preview_png
|
||||||
|
set PREVIEW_MODE V:/GodMode9_splash.png
|
||||||
|
goto kchooser
|
||||||
|
|
||||||
|
@kchoice_SELECT_Preview_custom
|
||||||
|
set PREVIEW_MODE "Your text can be here"
|
||||||
|
input -o "Enter anything:" PREVIEW_MODE
|
||||||
|
goto kchooser
|
||||||
|
|
||||||
|
@kchoice_START_Leave_script
|
||||||
|
goto outside
|
||||||
|
|
||||||
|
@kchooser
|
||||||
|
keysel -o -s "Choose preview mode via key" kchoice_*
|
||||||
|
goto outside
|
||||||
|
|
||||||
|
|
||||||
# for-next sample code
|
# for-next sample code
|
||||||
@spaghetti_fornext_sample
|
@spaghetti_fornext_sample
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user