diff --git a/arm9/source/godmode.c b/arm9/source/godmode.c index 56a8860..148e796 100644 --- a/arm9/source/godmode.c +++ b/arm9/source/godmode.c @@ -61,7 +61,7 @@ u32 SplashInit(const char* modestr) { if (splash) { bitmap = PNG_Decompress(splash, splash_size, &splash_width, &splash_height); - DrawBitmap(TOP_SCREEN, -1, -1, splash_width, splash_height, bitmap); + if (bitmap) DrawBitmap(TOP_SCREEN, -1, -1, splash_width, splash_height, bitmap); } else DrawStringF(TOP_SCREEN, 10, 10, COLOR_STD_FONT, COLOR_TRANSPARENT, "(" VRAM0_SPLASH_PNG " not found)"); if (modestr) DrawStringF(TOP_SCREEN, SCREEN_WIDTH_TOP - 10 - GetDrawStringWidth(modestr), diff --git a/arm9/source/system/png.c b/arm9/source/system/png.c index 8b4f847..a8ee83c 100644 --- a/arm9/source/system/png.c +++ b/arm9/source/system/png.c @@ -4,8 +4,7 @@ #include "lodepng.h" #include "png.h" -#include "ui.h" - +#ifndef MONITOR_HEAP static inline void _rgb_swap(u8 *img, size_t sz) { // maybe process in batches of 3 pixels / 12 bytes at a time? @@ -49,3 +48,22 @@ u8 *PNG_Compress(u8 *fb, u32 w, u32 h, size_t *png_sz) return img; } +#else +u8 *PNG_Decompress(const u8 *png, size_t png_len, u32 *w, u32 *h) +{ + (void) png; + (void) w; + (void) h; + (void) png_len; + return NULL; +} + +u8 *PNG_Compress(u8 *fb, u32 w, u32 h, size_t *png_sz) +{ + (void) fb; + (void) png_sz; + (void) w; + (void) h; + return NULL; +} +#endif diff --git a/data/HelloScript.gm9 b/data/HelloScript.gm9 new file mode 100644 index 0000000..172c4b3 --- /dev/null +++ b/data/HelloScript.gm9 @@ -0,0 +1,308 @@ +# 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 diff --git a/data/echotest.gm9 b/data/echotest.gm9 new file mode 100644 index 0000000..4b15ff7 --- /dev/null +++ b/data/echotest.gm9 @@ -0,0 +1,19 @@ +# 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 """ \ No newline at end of file diff --git a/data/sdumptest.gm9 b/data/sdumptest.gm9 new file mode 100644 index 0000000..3e4dbbd --- /dev/null +++ b/data/sdumptest.gm9 @@ -0,0 +1,4 @@ +sdump -w encTitleKeys.bin +sdump -w decTitleKeys.bin +sdump -w seeddb.bin +sdump -o -w shalalala.bin