Compare commits

..

7 Commits

Author SHA1 Message Date
suchmememanyskill
ba0ded0f8b start of tsV2 2020-11-06 21:19:29 +01:00
aspargas2
024ef7cd6e fix github workflows CI (#28)
* switch github CI to docker

* empty commit to trigger CI
2020-10-29 02:21:34 +01:00
huhenU
4b445d6c9c Add check for unmounted SD card in emmc (#26)
* Add check for unmounted SD card

* Implement it the better way and remove message Meme doesn't like

* Remove comma and remove dump option if no sd is inserted

Hopefully the last commit to this PR. Hopefully.
2020-08-11 17:12:20 +02:00
suchmememanyskill
0991c73c60 (hopefully) fix workflow file 2020-08-03 13:19:50 +02:00
suchmememanyskill
3527b6ac4d Merge branch 'dev' 2020-08-03 13:10:42 +02:00
suchmememanyskill
0146f0ddb0 Bump version 2020-08-03 13:10:02 +02:00
SuchMemeManySkill
b42b52eb43 Include a (bad) method to dump with .cnmt.nca 2020-07-14 17:38:56 +02:00
36 changed files with 1456 additions and 1291 deletions

View File

@@ -8,27 +8,14 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: devkitpro/devkita64_devkitarm
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1
- name: Install devkitpro
run: |
wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb
sudo dpkg -i devkitpro-pacman.deb
sudo dkp-pacman -S switch-dev --noconfirm
sudo dkp-pacman -S devkitARM --noconfirm
- name: Build TegraExplorer - name: Build TegraExplorer
run: | run: make -j$(nproc)
echo # SETTING PATH #
export DEVKITPRO=/opt/devkitpro
export DEVKITARM=${DEVKITPRO}/devkitARM
export DEVKITPPC=${DEVKITPRO}/devkitPPC
export PATH=${DEVKITPRO}/tools/bin:$PATH
echo # MAKE #
make -j$(nproc)
- uses: actions/upload-artifact@master - uses: actions/upload-artifact@master
with: with:

View File

@@ -11,7 +11,7 @@ include $(DEVKITARM)/base_rules
IPL_LOAD_ADDR := 0x40003000 IPL_LOAD_ADDR := 0x40003000
LPVERSION_MAJOR := 3 LPVERSION_MAJOR := 3
LPVERSION_MINOR := 0 LPVERSION_MINOR := 0
LPVERSION_BUGFX := 3 LPVERSION_BUGFX := 4
################################################################################ ################################################################################

View File

@@ -540,6 +540,11 @@ void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade){
memset(gfx_ctxt.fb + y * gfx_ctxt.stride + y0, shade, (y1 - y0 + 1) * 4); memset(gfx_ctxt.fb + y * gfx_ctxt.stride + y0, shade, (y1 - y0 + 1) * 4);
} }
} }
void gfx_setPixel(int x, int y, u32 color) {
*(gfx_ctxt.fb + (YLEFT - x) * gfx_ctxt.stride + y) = color;
}
/* /*
void gfx_boxGrey_old(int x0, int y0, int x1, int y1, u8 shade){ void gfx_boxGrey_old(int x0, int y0, int x1, int y1, u8 shade){
for (int y = y0; y <= y1; y++){ for (int y = y0; y <= y1; y++){

View File

@@ -53,6 +53,7 @@ void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 po
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y); void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
void gfx_box(int x0, int y0, int x1, int y1, u32 color); void gfx_box(int x0, int y0, int x1, int y1, u32 color);
void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade); void gfx_boxGrey(int x0, int y0, int x1, int y1, u8 shade);
void gfx_setPixel(int x, int y, u32 color);
/* /*
#define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x) #define GFX_SETPOSCORRECTED(x, y) gfx_con_setpos(y - YLEFT, x)

View File

@@ -116,3 +116,5 @@ extern gpt_entry_rule gpt_fs_rules[];
extern menu_entry mmcmenu_start[]; extern menu_entry mmcmenu_start[];
extern menu_entry mmcmenu_filemenu[]; extern menu_entry mmcmenu_filemenu[];
extern menu_entry fwDump_typeMenu[];

View File

@@ -93,3 +93,10 @@ menu_entry mmcmenu_filemenu[] = {
{"\nBack", COLOR_WHITE, {ISMENU}}, {"\nBack", COLOR_WHITE, {ISMENU}},
{"Dump to SD", COLOR_YELLOW, {ISMENU}} {"Dump to SD", COLOR_YELLOW, {ISMENU}}
}; };
menu_entry fwDump_typeMenu[] = {
{"Back\n", COLOR_WHITE, {ISMENU}},
{"Firmware format type:", COLOR_WHITE, {ISMENU | ISSKIP}},
{"Daybreak (prod.keys required!)", COLOR_BLUE, {ISMENU}},
{"ChoiNX", COLOR_VIOLET, {ISMENU}}
};

View File

@@ -59,3 +59,5 @@ typedef struct {
#define isFS 0x80 #define isFS 0x80
#define isBOOT 0x2 #define isBOOT 0x2
typedef void (*func_void_ptr)();

View File

@@ -219,9 +219,6 @@ int dump_biskeys(){
//nx_emmc_gpt_parse(&sys_gpt, &storage); //nx_emmc_gpt_parse(&sys_gpt, &storage);
se_aes_key_set(8, bis_key[2] + 0x00, 0x10);
se_aes_key_set(9, bis_key[2] + 0x10, 0x10);
pkg1inf.ver = pkg1_id->kb; pkg1inf.ver = pkg1_id->kb;
strcpy(pkg1inf.id, pkg1_id->id); strcpy(pkg1inf.id, pkg1_id->id);
return 0; return 0;

View File

@@ -28,6 +28,7 @@ extern sdmmc_storage_t storage;
extern emmc_part_t *system_part; extern emmc_part_t *system_part;
extern char *clipboard; extern char *clipboard;
extern u8 clipboardhelper; extern u8 clipboardhelper;
extern bool sd_mounted;
void addEntry(emmc_part_t *part, u8 property_GPT, int spot){ void addEntry(emmc_part_t *part, u8 property_GPT, int spot){
@@ -73,6 +74,12 @@ int fillMmcMenu(short mmcType){
mu_createObjects(count, &mmcMenuEntries); mu_createObjects(count, &mmcMenuEntries);
if (!sd_mounted)
sd_mount();
SETBIT(mmcmenu_filemenu[3].property, ISHIDE, !sd_mounted);
SETBIT(mmcmenu_start[1].property, ISHIDE, !sd_mounted);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
mu_copySingle(mmcmenu_start[i].name, mmcmenu_start[i].storage, mmcmenu_start[i].property, &mmcMenuEntries[i]); mu_copySingle(mmcmenu_start[i].name, mmcmenu_start[i].storage, mmcmenu_start[i].property, &mmcMenuEntries[i]);

View File

@@ -204,7 +204,7 @@ int filemenu(menu_entry file){
while (hidRead()->buttons); while (hidRead()->buttons);
*/ */
runScript(fsutil_getnextloc(currentpath, file.name)); startScript(fsutil_getnextloc(currentpath, file.name));
fsreader_readfolder(currentpath); fsreader_readfolder(currentpath);
break; break;
case FILE_HEXVIEW: case FILE_HEXVIEW:

View File

@@ -0,0 +1,62 @@
#include "keys.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../sec/se.h"
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../../config/ini.h"
#include "../common/common.h"
#include <string.h>
char *getKey(const char *search, link_t *inilist){
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){
if (ini_sec->type == INI_CHOICE){
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if (!strcmp(search, kv->key))
return kv->val;
}
}
}
return NULL;
}
u8 getHexSingle(const char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
}
u8 *getHex(const char *in){
u32 len = strlen(in), count = 0;
u8 *out = calloc(len / 2, sizeof(u8));
for (u32 i = 0; i < len; i += 2){
out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1]));
}
return out;
}
u8 *GetKey(const char *keypath, const char *keyName){
LIST_INIT(inilist);
char *key;
u8 *hex = NULL;
if (!ini_parse(&inilist, keypath, false)){
gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 1);
goto out_free;
}
if ((key = getKey(keyName, &inilist)) == NULL){
gfx_errDisplay("GetKey", ERR_INI_PARSE_FAIL, 2);
goto out_free;
}
hex = getHex(key);
out_free:;
list_empty(&inilist);
return hex;
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include "../../utils/types.h"
u8 *GetKey(const char *keypath, const char *keyName);

View File

@@ -0,0 +1,46 @@
#include "nca.h"
#include "keys.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../sec/se.h"
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../../config/ini.h"
#include "../common/common.h"
#include <string.h>
int SetHeaderKey(){
u8 *header_key = GetKey("sd:/switch/prod.keys", "header_key");
if (header_key == NULL)
return -1;
se_aes_key_set(4, header_key + 0x00, 0x10);
se_aes_key_set(5, header_key + 0x10, 0x10);
return 0;
}
int GetNcaType(char *ncaPath){
FIL fp;
u32 read_bytes = 0;
if (f_open(&fp, ncaPath, FA_READ | FA_OPEN_EXISTING))
return -1;
u8 *dec_header = (u8*)malloc(0x600);
if (f_lseek(&fp, 0x200) || f_read(&fp, dec_header, 32, &read_bytes) || read_bytes != 32){
f_close(&fp);
free(dec_header);
return -1;
}
se_aes_xts_crypt(5,4,0,1,dec_header + 0x200, dec_header, 32, 1);
u8 ContentType = dec_header[0x205];
f_close(&fp);
free(dec_header);
return ContentType;
}

View File

@@ -0,0 +1,4 @@
#pragma once
int GetNcaType(char *ncaPath);
int SetHeaderKey();

View File

@@ -1,4 +1,5 @@
#include "savesign.h" #include "savesign.h"
#include "keys.h"
#include "../../utils/types.h" #include "../../utils/types.h"
#include "../../libs/fatfs/ff.h" #include "../../libs/fatfs/ff.h"
#include "../../sec/se.h" #include "../../sec/se.h"
@@ -62,62 +63,15 @@ out_free:;
return success; return success;
} }
char *getKey(const char *search, link_t *inilist){
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, inilist, link){
if (ini_sec->type == INI_CHOICE){
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if (!strcmp(search, kv->key))
return kv->val;
}
}
}
return NULL;
}
u8 getHexSingle(const char c) {
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
}
u8 *getHex(const char *in){
u32 len = strlen(in), count = 0;
u8 *out = calloc(len / 2, sizeof(u8));
for (u32 i = 0; i < len; i += 2){
out[count++] = (u8)(getHexSingle(in[i]) << 4) | (getHexSingle(in[i + 1]));
}
return out;
}
bool save_sign(const char *keypath, const char *savepath){ bool save_sign(const char *keypath, const char *savepath){
LIST_INIT(inilist); u8 *key = GetKey(keypath, "save_mac_key");
char *key;
u8 *hex;
bool success = false;
if (!ini_parse(&inilist, keypath, false)){ if (key == NULL){
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 1); return false;
goto out_free;
} }
if ((key = getKey("save_mac_key", &inilist)) == NULL){ if (!save_commit(savepath, key))
gfx_errDisplay("save_sign", ERR_INI_PARSE_FAIL, 2); return false;
goto out_free;
} return true;
hex = getHex(key);
if (!save_commit(savepath, hex))
goto out_free;
success = true;
out_free:;
list_empty(&inilist);
return success;
} }

View File

@@ -23,7 +23,7 @@ void gfx_clearscreen(){
gfx_boxGrey(0, 703, 1279, 719, 0xFF); gfx_boxGrey(0, 703, 1279, 719, 0xFF);
gfx_boxGrey(0, 0, 1279, 15, 0xFF); gfx_boxGrey(0, 0, 1279, 15, 0xFF);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
gfx_printf("Tegraexplorer v2.0.3 | Battery: %3d%%\n", battery >> 8); gfx_printf("Tegraexplorer v2.0.4 | Battery: %3d%%\n", battery >> 8);
RESETCOLOR; RESETCOLOR;
} }

View File

@@ -60,7 +60,10 @@ void MainMenu_Tools(){
displaygpio(); displaygpio();
break; break;
case TOOLS_DUMPFIRMWARE: case TOOLS_DUMPFIRMWARE:
dumpfirmware(SYSMMC); res = menu_make(fwDump_typeMenu, 4, "-- Fw Type --");
if (res >= 2)
dumpfirmware(SYSMMC, (res == 2));
break; break;
} }
} }

View File

@@ -0,0 +1,281 @@
#include "args.h"
#include "parser.h"
#include "scriptCtx.h"
#include "lexer.h"
#include "functions.h"
#include "list.h"
#include <string.h>
#include "../../mem/heap.h"
#include "../utils/utils.h"
// do not include first openToken!
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken) {
int i = 0;
int layer = 0;
for (; i < len; i++) {
if (tokens[i].token == openToken)
layer++;
else if (tokens[i].token == closeToken) {
if (layer == 0)
return i;
layer--;
}
}
return -1;
}
dictValue_t getVarFromToken(scriptCtx_t* ctx, lexarToken_t* tokens, int* index, u32 maxLen) {
dictValue_t val = { 0 };
val.free = 0;
int i = *index;
u8 not = 0;
if (tokens[i].token == Not) {
not = 1;
i++;
}
if (tokens[i].token == Not)
return ErrDictValue(ERRDOUBLENOT);
if (tokens[i].token == Variable) {
char* funcName = tokens[i].text;
if (tokens[i + 1].token == LBracket) {
i += 2;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LBracket, RBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
ctx->args_loc.tokens = &tokens[i];
ctx->args_loc.stored = argCount;
val = executeFunction(ctx, funcName);
i += argCount;
}
else if (tokens[i + 1].token == LSBracket) {
dictValue_t* var = varVectorFind(&ctx->vars, tokens[i].text);
i += 2;
if (var == NULL)
return ErrDictValue(ERRNOVAR);
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 2, LSBracket, RSBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
dictValue_t index = solveEquation(ctx, &tokens[i], argCount);
i += argCount;
if (index.varType != IntType)
return ErrDictValue(ERRINVALIDTYPE);
if (var->arrayLen <= index.integer || index.integer < 0)
return ErrDictValue(ERRSYNTAX);
switch (var->varType) {
case StringArrayType:
val = StrDictValue(var->stringArray[index.integer]);
break;
case IntArrayType:
val = IntDictValue(var->integerArray[index.integer]);
break;
case ByteArrayType:
val = IntDictValue(var->byteArray[index.integer]);
break;
default:
return ErrDictValue(ERRINVALIDTYPE);
}
}
else {
dictValue_t* var = varVectorFind(&ctx->vars, tokens[i].text);
if (var != NULL) {
if (var->type == IntType) {
val = IntDictValue(var->integer);
}
else if (var->type == StringType){
val = StrDictValue(util_cpyStr(var->string));
val.free = 1;
}
else {
val = *var;
val.free = 0;
}
}
else
return ErrDictValue(ERRNOVAR);
}
}
else if (tokens[i].token == LSBracket) {
i++;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LSBracket, RSBracket);
if (argCount <= 0)
return ErrDictValue(-5);
varVector_t arrayVars = extractVars(ctx, &tokens[i], argCount);
int type = arrayVars.vars[0].value.varType;
if (!(type == StringType || type == IntType))
return ErrDictValue(ERRINVALIDTYPE);
val.type = (type + 2) | FREEINDICT;
val.arrayLen = arrayVars.stored;
val.integerArray = calloc(val.arrayLen, (type == IntType) ? sizeof(int) : sizeof(char*));
val.free = (type == StringType) ? 1 : 0;
for (int i = 0; i < arrayVars.stored; i++) {
if (arrayVars.vars[i].value.varType != type)
return ErrDictValue(ERRINVALIDTYPE); // Free-ing issue!!
if (type == StringType) {
val.stringArray[i] = util_cpyStr(arrayVars.vars[i].value.string);
}
else {
val.integerArray[i] = arrayVars.vars[i].value.integer;
}
}
i += argCount;
varVectorFree(&arrayVars);
}
else if (tokens[i].token == LBracket) {
i += 1;
int argCount = distanceBetweenTokens(&tokens[i], maxLen - 1, LBracket, RBracket);
if (argCount < 0)
return ErrDictValue(ERRSYNTAX);
val = solveEquation(ctx, &tokens[i], argCount);
i += argCount;
}
else if (tokens[i].token == IntLit) {
val = IntDictValue(tokens[i].val);
}
else if (tokens[i].token == StrLit) {
val = StrDictValue(tokens[i].text); // Do we need to copy the string here? if we set var.free = 0, it shouldn't matter
val.free = 0;
}
else {
// ERR
return ErrDictValue(ERRNOVAR);
}
if (not) {
if (val.type == IntType)
val.integer = !val.integer;
else
return ErrDictValue(ERRINVALIDTYPE);
}
*index = i;
return val;
}
int matchTypes(dictValue_t d1, dictValue_t d2, int type) {
return (d1.varType == d2.varType && d1.varType == type);
}
#define ELIFT(token) else if (localOpToken == token)
dictValue_t solveEquation(scriptCtx_t *ctx, lexarToken_t* tokens, u32 len) {
dictValue_t res = { 0 };
u16 lastToken = 0;
for (int i = 0; i < len; i++) {
if (tokens[i].token == Variable || tokens[i].token == StrLit || tokens[i].token == IntLit || tokens[i].token == Not || tokens[i].token == LBracket || tokens[i].token == LSBracket){
dictValue_t val = getVarFromToken(ctx, tokens, &i, len - i);
if (val.type == ErrType)
return val;
if (lastToken) {
u16 localOpToken = lastToken; // do we need local op token?
lastToken = 0;
if (matchTypes(res, val, IntType)) {
if (localOpToken == Plus)
res.integer += val.integer;
ELIFT(Minus)
res.integer -= val.integer;
ELIFT(Multiply)
res.integer *= val.integer;
ELIFT(Division)
res.integer /= val.integer;
ELIFT(Mod)
res.integer %= val.integer;
ELIFT(Smaller)
res.integer = res.integer < val.integer;
ELIFT(SmallerEqual)
res.integer = res.integer <= val.integer;
ELIFT(Bigger)
res.integer = res.integer > val.integer;
ELIFT(BiggerEqual)
res.integer = res.integer >= val.integer;
ELIFT(EqualEqual)
res.integer = res.integer == val.integer;
ELIFT(NotEqual)
res.integer = res.integer != val.integer;
ELIFT(LogicAND) {
res.integer = res.integer && val.integer;
if (!res.integer)
break;
}
ELIFT(LogicOR) {
res.integer = res.integer || val.integer;
if (res.integer)
break;
}
ELIFT(AND)
res.integer = res.integer & val.integer;
ELIFT(OR)
res.integer = res.integer | val.integer;
else
return ErrDictValue(ERRBADOPERATOR);
}
else if (matchTypes(res, val, StringType)) {
if (localOpToken == Plus) {
char* buff = calloc(strlen(res.string) + strlen(val.string) + 1, 1);
strcpy(buff, res.string);
strcat(buff, val.string);
if (res.free)
free(res.string);
if (val.free)
free(val.string);
res.string = buff;
}
ELIFT(EqualEqual) {
res.type = IntType;
int compRes = !strcmp(res.string, val.string);
if (res.free)
free(res.string);
if (val.free)
free(val.string);
res.integer = compRes;
res.free = 0;
}
ELIFT(Minus) {
if (!strcmp(res.string + strlen(res.string) - strlen(val.string), val.string)) {
*(res.string + strlen(res.string) - strlen(val.string)) = 0;
}
free(val.string);
}
else
return ErrDictValue(ERRBADOPERATOR);
}
else
return ErrDictValue(ERRBADOPERATOR);
}
else {
res = val;
}
}
else if (tokens[i].token >= Plus && tokens[i].token <= OR) {
lastToken = tokens[i].token;
}
}
return res;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "types.h"
char* createStrOutTextHolder(textHolder_t t);
dictValue_t solveEquation(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);
int distanceBetweenTokens(lexarToken_t* tokens, u32 len, int openToken, int closeToken);

View File

@@ -1,664 +1,177 @@
#include <string.h>
#include <stdlib.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../hid/hid.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "variables.h"
#include "../utils/utils.h"
#include "functions.h" #include "functions.h"
#include "../fs/fsutils.h" #include "list.h"
#include "../../utils/sprintf.h" #include "args.h"
#include "../fs/fsactions.h" #include "parser.h"
#include "../emmc/emmcoperations.h" #include "lexer.h"
#include "../emmc/emmcmenu.h" #include "types.h"
#include "scriptCtx.h"
#include "../../gfx/gfx.h"
#include "../../mem/heap.h"
#include <string.h>
#include "../../hid/hid.h"
extern FIL scriptin; dictValue_t funcPrint(scriptCtx_t* ctx, varVector_t* args) {
extern char **argv; for (int i = 0; i < args->stored; i++) {
extern u32 argc; switch (args->vars[i].value.varType) {
extern int forceExit; case IntType:
extern short currentlyMounted; gfx_printf("%d", args->vars[i].value.integer);
break;
int parseIntInput(char *in, int *out){ case StringType:
if (in[0] == '@'){ gfx_printf("%s", args->vars[i].value.string);
if (str_int_find(in, out)) break;
return -1;
}
else
*out = atoi(in);
return 0;
}
/*
int parseJmpInput(char *in, u64 *out){
if (in[0] == '?'){
if (str_jmp_find(in, out))
return -1;
else
return 0;
}
else
return -1;
}
*/
int parseStringInput(char *in, char **out){
if (in[0] == '$'){
if (str_str_find(in, out))
return -1;
else
return 0;
}
else{
*out = in;
return 0;
} }
} }
#pragma GCC push_options return NullDictValue();
#pragma GCC optimize ("Os")
u32 currentcolor = COLOR_WHITE;
int part_printf(){
SWAPCOLOR(currentcolor);
for (int i = 0; i < argc; i++){
if (argv[i][0] == '@'){
int toprintint;
if (parseIntInput(argv[i], &toprintint))
return INFUNC_FAIL;
gfx_printf("%d", toprintint);
}
else {
char *toprintstring;
if (parseStringInput(argv[i], &toprintstring))
return INFUNC_FAIL;
gfx_printf(toprintstring);
}
} }
dictValue_t funcPrintln(scriptCtx_t* ctx, varVector_t* args) {
funcPrint(ctx, args);
gfx_printf("\n"); gfx_printf("\n");
return 0; return NullDictValue();
} }
int part_print_int(){ dictValue_t funcIf(scriptCtx_t* ctx, varVector_t* args) {
int toprint; if (args->vars[0].value.varType == IntType) {
if (parseIntInput(argv[0], &toprint)) setCurIndentInstruction(ctx, (args->vars[0].value.integer == 0), -1);
return INFUNC_FAIL; return NullDictValue();
SWAPCOLOR(currentcolor);
gfx_printf("%s: %d\n", argv[0], toprint);
return 0;
} }
int part_Wait(){ return ErrDictValue(ERRINVALIDTYPE);
int arg;
u32 begintime;
SWAPCOLOR(currentcolor);
if (parseIntInput(argv[0], &arg))
return INFUNC_FAIL;
begintime = get_tmr_s();
while (begintime + arg > get_tmr_s()){
gfx_printf("\r<Wait %d seconds> ", (begintime + arg) - get_tmr_s());
} }
gfx_printf("\r \r"); dictValue_t scriptElse(scriptCtx_t* ctx, varVector_t* args) {
return 0; indentInstructor_t curInstruction = getCurIndentInstruction(ctx);
setCurIndentInstruction(ctx, !curInstruction.skip, -1);
return NullDictValue();
} }
int part_Check(){ dictValue_t scriptWhile(scriptCtx_t* ctx, varVector_t* args) {
int left, right; if (args->vars[0].value.varType == IntType) {
if (parseIntInput(argv[0], &left)) setCurIndentInstruction(ctx, (args->vars[0].value.integer == 0), ctx->lastTokenPos);
return INFUNC_FAIL; return NullDictValue();
if (parseIntInput(argv[2], &right))
return INFUNC_FAIL;
if (!strcmp(argv[1], "=="))
return (left == right);
else if (!strcmp(argv[1], "!="))
return (left != right);
else if (!strcmp(argv[1], ">="))
return (left >= right);
else if (!strcmp(argv[1], "<="))
return (left <= right);
else if (!strcmp(argv[1], ">"))
return (left > right);
else if (!strcmp(argv[1], "<"))
return (left < right);
else
return INFUNC_FAIL;
} }
int part_if(){ return ErrDictValue(ERRINVALIDTYPE);
int condition;
if (parseIntInput(argv[0], &condition))
return INFUNC_FAIL;
getfollowingchar('{');
if (!condition)
skipbrackets();
return 0;
/*
if (condition)
return 0;
else {
skipbrackets();
return 0;
}
*/
} }
int part_if_args(){ dictValue_t scriptLen(scriptCtx_t* ctx, varVector_t* args) {
int condition; if (args->vars[0].value.varType >= IntArrayType && args->vars[0].value.varType <= ByteArrayType)
if ((condition = part_Check()) < 0) return IntDictValue(args->vars[0].value.arrayLen);
return INFUNC_FAIL; else if (args->vars[0].value.varType == StringType) {
if (args->vars[0].value.string != NULL)
getfollowingchar('{'); return IntDictValue(strlen(args->vars[0].value.string));
if (!condition)
skipbrackets();
return 0;
} }
int part_Math(){ return ErrDictValue(ERRINVALIDTYPE);
int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &right))
return INFUNC_FAIL;
switch (argv[1][0]){
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
}
return INFUNC_FAIL;
} }
int part_SetInt(){ dictValue_t scriptMakeByteArray(scriptCtx_t* ctx, varVector_t* args) {
int out; if (args->vars[0].value.varType == IntArrayType) {
parseIntInput(argv[0], &out); u8* buff = calloc(args->vars[0].value.arrayLen, 1);
return out; for (int i = 0; i < args->vars[0].value.arrayLen; i++) {
buff[i] = (u8)(args->vars[0].value.integerArray[i] & 0xFF);
} }
int part_SetString(){ return DictValueCreate(ByteArrayType | FREEINDICT, args->vars[0].value.arrayLen, buff);
char *arg0;
if (parseStringInput(argv[0], &arg0))
return INFUNC_FAIL;
if (argv[1][0] != '$')
return INFUNC_FAIL;
str_str_add(argv[1], arg0);
return 0;
} }
int part_SetStringIndex(){ return ErrDictValue(ERRINVALIDTYPE);
int index;
char *out;
if (parseIntInput(argv[0], &index))
return INFUNC_FAIL;
if (argv[1][0] != '$')
return INFUNC_FAIL;
if (str_str_index(index, &out))
return INFUNC_FAIL;
str_str_add(argv[1], out);
return 0;
} }
int part_goto(){ dictValue_t scriptWait(scriptCtx_t*ctx, varVector_t* args){
int target = 0; Inputs* input = hidWait();
if (parseIntInput(argv[0], &target))
return INFUNC_FAIL;
str_int_add("@RETURN", (int)f_tell(&scriptin)); return IntDictValue(input->buttons);
f_lseek(&scriptin, target);
return 0;
} }
int part_invert(){ dictValue_t scriptSetPixel(scriptCtx_t *ctx, varVector_t* args){
int arg; int pixelArgs[5] = {0};
if (parseIntInput(argv[0], &arg))
return INFUNC_FAIL; for (int i = 0; i < args->stored; i++){
return (arg) ? 0 : 1; if (args->vars[i].value.varType != IntType)
return ErrDictValue(ERRINVALIDTYPE);
pixelArgs[i] = args->vars[i].value.integer;
} }
int part_fs_exists(){ u32 color = 0xFF000000 | ((pixelArgs[2] & 0xFF) << 16) | ((pixelArgs[3] & 0xFF) << 8) | ((pixelArgs[4] & 0xFF));
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
return fsutil_checkfile(path); gfx_setPixel(pixelArgs[0], pixelArgs[1], color);
return NullDictValue();
} }
int part_ConnectMMC(){ const static str_fnc_struct functions[] = {
char *arg; {"print", funcPrint, {0x40}},
parseStringInput(argv[0], &arg); {"println", funcPrintln, {0x40}},
{"if", funcIf, {1}},
if (!strcmp(arg, "SYSMMC")) {"while", scriptWhile, {1}},
connect_mmc(SYSMMC); {"else", scriptElse, {0}},
else if (!strcmp(arg, "EMUMMC")) {"len", scriptLen, {1}},
connect_mmc(EMUMMC); {"byte", scriptMakeByteArray, {1}},
else {"wait", scriptWait, {0}},
return INFUNC_FAIL; {"setPixel", scriptSetPixel, {5}},
{NULL, NULL, {0}},
return 0;
}
int part_MountMMC(){
char *arg;
parseStringInput(argv[0], &arg);
return mount_mmc(arg, 2);
}
int part_Pause(){
Inputs *input = hidWaitMask(KEY_A | KEY_B | KEY_X | KEY_Y | KEY_POW | KEY_VOLP | KEY_VOLM | KEY_LUP | KEY_LDOWN | KEY_LLEFT | KEY_LRIGHT);
str_int_add("@BTN_POWER", input->pow);
str_int_add("@BTN_VOL+", input->volp);
str_int_add("@BTN_VOL-", input->volm);
str_int_add("@BTN_A", input->a);
str_int_add("@BTN_B", input->b);
str_int_add("@BTN_X", input->x);
str_int_add("@BTN_Y", input->y);
str_int_add("@BTN_UP", input->Lup);
str_int_add("@BTN_DOWN", input->Ldown);
str_int_add("@BTN_LEFT", input->Lleft);
str_int_add("@BTN_RIGHT", input->Lright);
str_int_add("@JOYCONN", hidConnected());
return input->buttons;
}
int part_addstrings(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
combined = calloc(strlen(left) + strlen(middle) + 1, sizeof(char));
sprintf(combined, "%s%s", left, middle);
str_str_add(argv[2], combined);
free(combined);
return 0;
}
int part_setColor(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
if (!strcmp(arg, "RED"))
currentcolor = COLOR_RED;
else if (!strcmp(arg, "ORANGE"))
currentcolor = COLOR_ORANGE;
else if (!strcmp(arg, "YELLOW"))
currentcolor = COLOR_YELLOW;
else if (!strcmp(arg, "GREEN"))
currentcolor = COLOR_GREEN;
else if (!strcmp(arg, "BLUE"))
currentcolor = COLOR_BLUE;
else if (!strcmp(arg, "VIOLET"))
currentcolor = COLOR_VIOLET;
else if (!strcmp(arg, "WHITE"))
currentcolor = COLOR_WHITE;
else
return INFUNC_FAIL;
return 0;
}
int part_Exit(){
forceExit = true;
return 0;
}
int part_fs_Move(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
int res;
res = f_rename(left, right);
if (res)
res = f_rename(left, right);
return res;
}
int part_fs_Delete(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
int res;
res = f_unlink(arg);
if (res)
res = f_unlink(arg);
return res;
}
int part_fs_DeleteRecursive(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
return fsact_del_recursive(arg);
}
int part_fs_Copy(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return fsact_copy(left, right, COPY_MODE_PRINT);
}
int part_fs_CopyRecursive(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return fsact_copy_recursive(left, right);
}
int part_fs_MakeDir(){
char *arg;
if (parseStringInput(argv[0], &arg))
return INFUNC_FAIL;
int res;
res = f_mkdir(arg);
if (res)
res = f_mkdir(arg);
return res;
}
DIR dir;
FILINFO fno;
int isdirvalid = false;
int part_fs_OpenDir(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (f_opendir(&dir, path))
return INFUNC_FAIL;
isdirvalid = true;
str_int_add("@ISDIRVALID", isdirvalid);
return 0;
}
int part_fs_CloseDir(){
if (!isdirvalid)
return 0;
f_closedir(&dir);
isdirvalid = false;
str_int_add("@ISDIRVALID", isdirvalid);
return 0;
}
int part_fs_ReadDir(){
if (!isdirvalid)
return INFUNC_FAIL;
if (!f_readdir(&dir, &fno) && fno.fname[0]){
str_str_add("$FILENAME", fno.fname);
str_int_add("@ISDIR", (fno.fattrib & AM_DIR) ? 1 : 0);
}
else {
part_fs_CloseDir();
}
return 0;
}
int part_setPrintPos(){
int left, right;
if (parseIntInput(argv[0], &left))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &right))
return INFUNC_FAIL;
if (left > 78)
return INFUNC_FAIL;
if (right > 42)
return INFUNC_FAIL;
gfx_con_setpos(left * 16, right * 16);
return 0;
}
int part_stringcompare(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
return (strcmp(left, right)) ? 0 : 1;
}
int part_fs_combinePath(){
char *combined, *left, *middle;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &middle))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
combined = fsutil_getnextloc(left, middle);
str_str_add(argv[2], combined);
free(combined);
return 0;
}
int part_mmc_dumpPart(){
char *left, *right;
if (parseStringInput(argv[0], &left))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &right))
return INFUNC_FAIL;
if (!strcmp(left, "BOOT")){
return emmcDumpBoot(right);
}
else {
return emmcDumpSpecific(left, right);
}
}
int part_mmc_restorePart(){
char *path;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (currentlyMounted < 0)
return INFUNC_FAIL;
return mmcFlashFile(path, currentlyMounted, false);
}
int part_fs_extractBisFile(){
char *path, *outfolder;
if (parseStringInput(argv[0], &path))
return INFUNC_FAIL;
if (parseStringInput(argv[1], &outfolder))
return INFUNC_FAIL;
return extract_bis_file(path, outfolder);
}
int part_clearscreen(){
gfx_clearscreen();
return 0;
}
int part_getPos(){
return (int)f_tell(&scriptin);
}
int part_subString(){
char *str, *sub;
int start, size;
if (parseStringInput(argv[0], &str))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &start))
return INFUNC_FAIL;
if (parseIntInput(argv[2], &size))
return INFUNC_FAIL;
if (argv[3][0] != '$')
return INFUNC_FAIL;
if (start >= strlen(str))
return INFUNC_FAIL;
sub = utils_copyStringSize(str + start, size);
str_str_add(argv[3], sub);
free(sub);
return 0;
}
int part_inputString(){
char *start, *out;
int len;
if (parseStringInput(argv[0], &start))
return INFUNC_FAIL;
if (parseIntInput(argv[1], &len))
return INFUNC_FAIL;
if (argv[2][0] != '$')
return INFUNC_FAIL;
if (len > 39)
return INFUNC_FAIL;
out = utils_InputText(start, len);
if (out == NULL)
return 1;
str_str_add(argv[2], out);
free(out);
return 0;
}
int part_strLen(){
char *in;
if (parseStringInput(argv[0], &in))
return INFUNC_FAIL;
return strlen(in);
}
str_fnc_struct functions[] = {
{"printf", part_printf, 255},
{"printInt", part_print_int, 1},
{"setPrintPos", part_setPrintPos, 2},
{"clearscreen", part_clearscreen, 0},
{"if", part_if, 1},
{"if", part_if_args, 3}, // function overloading
{"math", part_Math, 3},
{"check", part_Check, 3},
{"setInt", part_SetInt, 1},
{"goto", part_goto, 1},
{"setString", part_SetString, 2},
{"setStringIndex", part_SetStringIndex, 2},
{"setColor", part_setColor, 1},
{"combineStrings", part_addstrings, 3},
{"compareStrings", part_stringcompare, 2},
{"subString", part_subString, 4},
{"inputString", part_inputString, 3},
{"stringLength", part_strLen, 1},
{"invert", part_invert, 1},
{"fs_exists", part_fs_exists, 1},
{"fs_move", part_fs_Move, 2},
{"fs_mkdir", part_fs_MakeDir, 1},
{"fs_del", part_fs_Delete, 1},
{"fs_delRecursive", part_fs_DeleteRecursive, 1},
{"fs_copy", part_fs_Copy, 2},
{"fs_copyRecursive", part_fs_CopyRecursive, 2},
{"fs_openDir", part_fs_OpenDir, 1},
{"fs_closeDir", part_fs_CloseDir, 0},
{"fs_readDir", part_fs_ReadDir, 0},
{"fs_combinePath", part_fs_combinePath, 3},
{"fs_extractBisFile", part_fs_extractBisFile, 2},
{"mmc_connect", part_ConnectMMC, 1},
{"mmc_mount", part_MountMMC, 1},
{"mmc_dumpPart", part_mmc_dumpPart, 2},
{"mmc_restorePart", part_mmc_restorePart, 1},
{"getPosition", part_getPos, 0},
{"pause", part_Pause, 0},
{"wait", part_Wait, 1},
{"exit", part_Exit, 0},
{NULL, NULL, 0}
}; };
#pragma GCC pop_options varVector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len) {
varVector_t args = varVectorInit(4);
int lastLoc = 0;
for (int i = 0; i < len; i++) {
if (tokens[i].token == LSBracket) {
int distance = distanceBetweenTokens(&tokens[i + 1], len - i - 1, LSBracket, RSBracket);
i += distance + 1;
}
if (tokens[i].token == Seperator) {
dictValue_t res = solveEquation(ctx, &tokens[lastLoc], i - lastLoc);
lastLoc = i + 1;
varVectorAdd(&args, DictCreate(NULL, res));
}
if (i + 1 >= len) {
dictValue_t res = solveEquation(ctx, &tokens[lastLoc], i + 1 - lastLoc);
varVectorAdd(&args, DictCreate(NULL, res));
}
}
return args;
}
dictValue_t executeFunction(scriptCtx_t* ctx, char* func_name) {
int argCount = 0;
varVector_t args = { 0 };
if (ctx->args_loc.stored > 0) {
args = extractVars(ctx, ctx->args_loc.tokens, ctx->args_loc.stored);
for (int i = 0; i < args.stored; i++) {
if (args.vars[i].value.varType == ErrType)
return args.vars[i].value;
}
argCount = args.stored;
}
int run_function(char *func_name, int *out){
for (u32 i = 0; functions[i].key != NULL; i++) { for (u32 i = 0; functions[i].key != NULL; i++) {
if (!strcmp(functions[i].key, func_name)) { if (!strcmp(functions[i].key, func_name)) {
if (argc != functions[i].arg_count && functions[i].arg_count != 255) if (argCount != functions[i].argCount && !functions[i].varArgs)
continue; continue;
*out = functions[i].value(); dictValue_t val = functions[i].value(ctx, &args);
return (*out == INFUNC_FAIL) ? -1 : 0; // free args
varVectorFree(&args);
return val;
} }
} }
return -2;
dictValue_t* var = varVectorFind(&ctx->vars, func_name);
if (var != NULL) {
if (var->type == JumpType) {
setCurIndentInstruction(ctx, 0, ctx->curPos);
ctx->curPos = var->integer - 1;
ctx->lastToken.token = Invalid;
return NullDictValue();
}
}
return ErrDictValue(ERRNOFUNC);
} }

View File

@@ -1,13 +1,10 @@
#pragma once #pragma once
#include "../../utils/types.h" #include "types.h"
typedef void (*func_void_ptr)(); #define BIT(n) (1U << n)
typedef int (*func_int_ptr)();
typedef struct { #define VARARGS(x) {x, 1, 0}
char *key; #define OPERATORARGS(x) {x, 0, 1}
func_int_ptr value;
u8 arg_count;
} str_fnc_struct;
int run_function(char *func_name, int *out); dictValue_t executeFunction(scriptCtx_t* ctx, char* func_name);
varVector_t extractVars(scriptCtx_t* ctx, lexarToken_t* tokens, u32 len);

View File

@@ -0,0 +1,195 @@
#include "lexer.h"
#include "parser.h"
#include "args.h"
#include "../utils/utils.h"
#include "../../mem/heap.h"
#include <string.h>
static inline int isValidWord(char c) {
char r = c | 0x20;
return (r >= 'a' && r <= 'z');
}
static inline int isValidVar(char c) {
char r = c | 0x20;
return ((r >= 'a' && r <= 'z') || (r >= '0' && r <= '9'));
}
static inline int isValidNum(char c) {
return (c >= '0' && c <= '9');
}
static inline int isValidHexNum(char c) {
char r = c | 0x20;
return (isValidNum(r) || (r >= 'a' && r <= 'f'));
}
#define makeLexarToken(token, var) (lexarToken_t) {token, {var}}
#define makeLexarIntToken(intVar) (lexarToken_t) {IntLit, .val = intVar}
typedef struct {
u8 tokenC;
u16 tokenN;
} lexarTranslation_t;
lexarTranslation_t lexarTranslations[] = {
{'(', LBracket},
{')', RBracket},
{'{', LCBracket},
{'}', RCBracket},
{',', Seperator},
{'+', Plus},
{'-', Minus},
{'*', Multiply},
{'/', Division},
{'%', Mod},
{'<', Smaller},
{'>', Bigger},
{'=', Equal},
{'!', Not},
{'[', LSBracket},
{']', RSBracket},
{'\0', 0},
};
char lexarDebugGetTokenC(u16 tokenN) {
for (int i = 0; lexarTranslations[i].tokenC; i++) {
if (lexarTranslations[i].tokenN == tokenN) {
return lexarTranslations[i].tokenC;
}
}
return '?';
}
lexarVector_t lexarVectorInit(int startSize) {
lexarVector_t l = { 0 };
l.tokens = calloc(startSize, sizeof(lexarVector_t));
l.len = startSize;
l.stored = 0;
return l;
}
void lexarVectorAdd(lexarVector_t* vec, lexarToken_t token) {
if (vec->stored >= vec->len) {
vec->len *= 2;
//vec->tokens = realloc(vec->tokens, vec->len * sizeof(lexarToken_t));
void *temp = calloc(vec->len, sizeof(lexarToken_t));
memcpy(temp, vec->tokens, vec->len / 2 * sizeof(lexarToken_t));
free(vec->tokens);
vec->tokens = temp;
}
vec->tokens[vec->stored++] = token;
}
void lexarVectorClear(lexarVector_t* vec) {
for (int i = 0; i < vec->stored; i++) {
if (vec->tokens[i].token == Variable || vec->tokens[i].token == StrLit)
if (vec->tokens[i].text != NULL)
free(vec->tokens[i].text);
}
free(vec->tokens);
}
#define ELIFC(c) else if (*in == c)
lexarVector_t lexarGo(const char* in) {
lexarVector_t vec = lexarVectorInit(16);
while (*in) {
if (isValidWord(*in)) {
char* startWord = in;
in++;
while (isValidVar(*in))
in++;
lexarVectorAdd(&vec, makeLexarToken(Variable, utils_copyStringSize(startWord, in - startWord)));
continue;
}
else if (isValidNum(*in) || (*in == '-' && isValidNum(in[1]))) {
int parse = 0;
u8 negative = (*in == '-');
if (negative)
in++;
if (*in == '0' && (in[1] | 0x20) == 'x') {
in += 2;
while (isValidHexNum(*in)) {
parse = parse * 16 + (*in & 0x0F) + (*in >= 'A' ? 9 : 0);
in++;
}
}
else while (isValidNum(*in)) {
parse = parse * 10 + *in++ - '0';
}
if (negative)
parse *= -1;
lexarVectorAdd(&vec, makeLexarIntToken(parse));
continue;
}
ELIFC('"') {
char* startStr = ++in;
while (*in != '"')
in++;
lexarVectorAdd(&vec, makeLexarToken(StrLit, utils_copyStringSize(startStr, in - startStr)));
in++;
continue;
}
ELIFC('#') {
while (*in != '\n')
in++;
in++;
continue;
}
ELIFC('&') {
if (in[1] == '&') {
lexarVectorAdd(&vec, makeLexarToken(LogicAND, 0));
in++;
}
else {
lexarVectorAdd(&vec, makeLexarToken(AND, 0));
}
in++;
continue;
}
ELIFC('|') {
if (in[1] == '|') {
lexarVectorAdd(&vec, makeLexarToken(LogicOR, 0));
in++;
}
else {
lexarVectorAdd(&vec, makeLexarToken(OR, 0));
}
in++;
continue;
}
int val = 0;
for (int i = 0; lexarTranslations[i].tokenC; i++) {
if (lexarTranslations[i].tokenC == *in) {
val = lexarTranslations[i].tokenN;
break;
}
}
in++;
if (*in == '=' && val >= Smaller && val <= Not) {
val++;
in++;
}
if (val != Invalid)
lexarVectorAdd(&vec, makeLexarToken(val, 0));
}
return vec;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "types.h"
lexarVector_t lexarGo(const char* in);
char lexarDebugGetTokenC(u16 tokenN);
void lexarVectorClear(lexarVector_t* vec);

View File

@@ -0,0 +1,88 @@
#include "list.h"
#include <string.h>
#include "types.h"
#include "../../mem/heap.h"
void freeDictValue(dictValue_t dv) {
if (dv.string == NULL)
return;
switch (dv.varType) {
case StringType:
case IntArrayType:
case ByteArrayType: // As it's a union with the biggest object being a pointer, this should be the same
free(dv.string);
break;
case StringArrayType:
for (unsigned int i = 0; i < dv.arrayLen; i++)
free(dv.stringArray[i]);
free(dv.stringArray);
}
}
void freeDict(dict_t* dict) {
freeDictValue(dict->value);
free(dict->key);
free(dict);
}
varVector_t varVectorInit(int startSize) {
varVector_t vec = { 0 };
vec.vars = calloc(startSize, sizeof(dict_t));
vec.len = startSize;
vec.stored = 0;
return vec;
}
dictValue_t* varVectorFind(varVector_t* vec, const char* key) {
for (int i = 0; i < vec->stored; i++) {
if (!strcmp(vec->vars[i].key, key))
return &vec->vars[i].value;
}
return NULL;
}
void varVectorAdd(varVector_t* vec, dict_t add) {
dictValue_t* var = NULL;
if (add.key != NULL)
var = varVectorFind(vec, add.key);
if (var != NULL) {
freeDictValue(*var);
*var = add.value;
free(add.key);
return;
}
if (vec->stored >= vec->len) {
vec->len *= 2;
dict_t* old = vec->vars;
//vec->vars = realloc(old, vec->len * sizeof(dict_t));
void *temp = calloc(vec->len, sizeof(dict_t));
memcpy(temp, vec->vars, vec->len / 2 * sizeof(dict_t));
free(vec->vars);
vec->vars = temp;
if (vec->vars == NULL) {
free(old);
}
}
vec->vars[vec->stored] = add;
vec->stored++;
}
void varVectorFree(varVector_t* vec) {
for (int i = 0; i < vec->stored; i++) {
dict_t *var = &vec->vars[i];
if (var->key != NULL) {
free(var->key);
var->key = NULL;
}
if (var->value.free)
freeDictValue(var->value);
}
free(vec->vars);
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include "types.h"
#define dictValSetInt(dictVal, i) dictVal.integer = i; dictVal.type = IntType;
#define dictValSetStr(dictVal, str) dictVal.string = strdup(str); dictVal.type = StringType;
#define dictValSetJump(dictVal, i) dictVal.integer = i; dictVal.type = JumpType;
#define dictValInt(i) (dictValue_t) {IntType, 0, i}
#define DictCreate(key, value) (dict_t) {key, value}
#define DictValueCreate(type, arrayLen, val) (dictValue_t) {type, arrayLen, val}
void freeDictValue(dictValue_t dv);
void freeDict(dict_t* dict);
varVector_t varVectorInit(int startSize);
void varVectorAdd(varVector_t* vec, dict_t add);
dictValue_t* varVectorFind(varVector_t* vec, const char* key);
static inline void freeDictValueOnVar(dictValue_t dv) {
if (dv.free)
freeDictValue(dv);
}
void varVectorFree(varVector_t* vec);

View File

@@ -1,307 +1,263 @@
#include "args.h"
#include "parser.h"
#include "types.h"
#include "list.h"
#include "functions.h"
#include "scriptCtx.h"
#include "lexer.h"
#include <string.h> #include <string.h>
#include "../../mem/heap.h" #include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../utils/btn.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "functions.h"
#include "variables.h"
#include "../fs/fsreader.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include "../../storage/nx_sd.h"
#include "../../gfx/gfx.h"
#include "../../hid/hid.h" #include "../../hid/hid.h"
#include "../gfx/gfxutils.h"
int countchars(const char* in, char target) { //#define DPRINTF(str, ...) printf(str, __VA_ARGS__)
u32 len = strlen(in); #define DPRINTF
u32 count = 0;
for (u32 i = 0; i < len; i++) { #define findNextCharsCtx(ctx, targets) findNextChars(&(ctx->curPos), targets)
if (in[i] == '"'){
while (in[++i] != '"'){ int checkIfVar(u16 token) {
if (i >= len) return (token == StrLit || token == IntLit || token == Variable || token == RSBracket);
return -1;
}
}
if (in[i] == target)
count++;
} }
return count; void printToken(lexarToken_t* token) {
switch (token->token) {
case 1:
gfx_printf("%s ", token->text);
break;
case 6:
//printf("%d: '%s'\n", vec.tokens[i].token, vec.tokens[i].text);
gfx_printf("\"%s\" ", token->text);
break;
case 7:
//printf("%d: %d\n", vec.tokens[i].token, vec.tokens[i].val);
gfx_printf("%d ", token->val);
break;
default:
//printf("%d: %c\n", vec.tokens[i].token, lexarDebugGetTokenC(vec.tokens[i].token));
gfx_printf("%c ", lexarDebugGetTokenC(token->token));
break;
}
} }
char **argv = NULL; scriptResult_t runFunction(scriptCtx_t* ctx) {
u32 argc; dictValue_t res = solveEquation(ctx, &ctx->script->tokens[ctx->startEq], ctx->curPos - ctx->startEq);
u32 splitargs(const char* in) {
// arg like '5, "6", @arg7'
u32 i = 0, count = 1, len = strlen(in), curcount = 0, begin, end;
count += countchars(in, ','); if (res.varType == ErrType)
return scriptResultCreate(res.integer, &ctx->script->tokens[ctx->startEq]);
if (!count) ctx->startEq = ctx->curPos;
return 0; if (ctx->varToken.token != Invalid) { // we should not assign null's
ctx->varToken.token = Invalid;
if (ctx->varIndexSet) {
ctx->varIndexSet = 0;
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (!(arrayVal == NULL || arrayVal->arrayLen <= ctx->varIndex)) {
if (arrayVal->varType == IntArrayType && res.varType == IntType) {
arrayVal->integerArray[ctx->varIndex] = res.integer;
}
else if (arrayVal->varType == StringArrayType && res.varType == StringType) {
free(arrayVal->stringArray[ctx->varIndex]);
arrayVal->stringArray[ctx->varIndex] = res.string;
}
else if (arrayVal->varType == ByteArrayType && res.varType == IntType) {
arrayVal->byteArray[ctx->varIndex] = (u8)(res.integer & 0xFF);
}
else {
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->startEq]);
}
}
else {
return scriptResultCreate(ERRNOVAR, &ctx->script->tokens[ctx->startEq]);
}
}
else {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), res));
}
}
else {
freeDictValueOnVar(res);
}
argv = calloc(count + 1, sizeof(char*)); return scriptResultCreate(0, 0);
}
while (i < len && curcount < count) { // TODO
if (in[i] == ' ' || in[i] == ','){ // Make sure mem gets free'd properly
// Fix bug that custom functions cannot be run from end of script
// add arrays
#define RUNFUNCWITHPANIC(ctx) scriptResult_t res = runFunction(ctx); if (res.resCode != 0) return res
scriptResult_t mainLoop(scriptCtx_t* ctx) {
for (ctx->curPos = 0; ctx->curPos < ctx->script->stored; ctx->curPos++) {
u32 i = ctx->curPos;
lexarToken_t curToken = ctx->script->tokens[i];
//printToken(&curToken);
if (checkIfVar(ctx->lastToken.token) && curToken.token == Variable) {
RUNFUNCWITHPANIC(ctx);
}
else if (curToken.token == Equal) {
// Set last var to lastToken, if lastToken is var
if (ctx->lastToken.token == RSBracket) {
int layer = 0;
i = ctx->lastTokenPos - 1;
for (; i > 0; i--) {
if (ctx->script->tokens[i].token == RSBracket)
layer++;
else if (ctx->script->tokens[i].token == LSBracket) {
if (layer == 0)
break;
layer--;
}
}
i--;
if (ctx->script->tokens[i].token == Variable) {
dictValue_t index = solveEquation(ctx, &ctx->script->tokens[i + 2], ctx->lastTokenPos - i - 2);
ctx->lastTokenPos = i;
ctx->lastToken = ctx->script->tokens[i];
if (index.varType == IntType) {
ctx->varIndex = index.integer;
ctx->varIndexSet = 1;
if (ctx->varIndexSet) {
dictValue_t* arrayVal = varVectorFind(&ctx->vars, ctx->varToken.text);
if (arrayVal == NULL) {
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->varIndex < 0 || ctx->varIndex >= arrayVal->arrayLen || arrayVal->varType < IntArrayType)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
}
else
return scriptResultCreate(ERRINVALIDTYPE, &ctx->script->tokens[ctx->curPos]);
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
}
if (ctx->lastToken.token == Variable) {
ctx->startEq = ctx->curPos + 1;
ctx->varToken = ctx->lastToken;
}
else
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
//printf("Setting token %s to next assignment", ctx->lastToken.text);
// !! check prev for ] for arrays
}
else if (curToken.token == LBracket) {
i++; i++;
int distance = distanceBetweenTokens(&ctx->script->tokens[i], ctx->script->stored - i, LBracket, RBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
i += distance;
ctx->curPos = i;
if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
}
continue;
}
else if (curToken.token == LCBracket) {
if (ctx->lastToken.token == Equal && ctx->varToken.token == Variable) {
varVectorAdd(&ctx->vars, DictCreate(util_cpyStr(ctx->varToken.text), DictValueCreate(JumpType, 0, ctx->curPos)));
ctx->varToken.token = Invalid;
setCurIndentInstruction(ctx, 1, -1);
}
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
}
ctx->startEq = ctx->curPos + 1;
indentInstructor_t ins = getCurIndentInstruction(ctx);
if (ins.active) {
if (ins.skip) {
int distance = distanceBetweenTokens(&ctx->script->tokens[i + 1], ctx->script->stored - i - 1, LCBracket, RCBracket);
if (distance < 0)
return scriptResultCreate(ERRSYNTAX, &ctx->script->tokens[ctx->curPos]);
ctx->curPos += distance + 1;
ctx->startEq = ctx->curPos + 1;
}
else {
ctx->indentLevel++;
}
}
else
return scriptResultCreate(ERRINACTIVEINDENT, &ctx->script->tokens[ctx->curPos]);
}
else if (curToken.token == RCBracket) {
if (checkIfVar(ctx->lastToken.token)) {
RUNFUNCWITHPANIC(ctx);
if (i != ctx->curPos)
continue; continue;
} }
begin = i; ctx->indentLevel--;
while (strrchr(" ,)", in[i]) == NULL){ indentInstructor_t ins = getCurIndentInstruction(ctx);
if (in[i] == '"'){ if (ins.active && ins.jump) {
begin = i + 1; ctx->curPos = ins.jumpLoc - 1;
while (in[++i] != '"'){
if (in[i] == '\0')
return 0;
}
} }
if (in[i] == '\0') ctx->startEq = ctx->curPos + 1;
return 0; }
else if (ctx->curPos + 1 >= ctx->script->stored && checkIfVar(ctx->lastToken.token)) {
i++; solveEquation(ctx, &ctx->script->tokens[ctx->startEq], i + 1 - ctx->startEq);
} }
end = i; ctx->lastToken = ctx->script->tokens[ctx->curPos];
ctx->lastTokenPos = ctx->curPos;
if (in[i - 1] == '"'){
end--;
} }
argv[curcount++] = utils_copyStringSize(in + begin, (u32)(end - begin)); return scriptResultCreate(0, 0);
}
return curcount;
} }
FIL scriptin; const char* functionFails[] = {
UINT endByte = 0; "An invalid operation was performed",
int forceExit = false; "Double Nots are not allowed",
char currentchar = 0; "A syntax error was found",
"The recieved type was incorrect",
"The variable could not be found",
"The specified function could not be found",
"An inactive indent was found"
};
char getnextchar(){ void startScript(char* path) {
f_read(&scriptin, &currentchar, sizeof(char), &endByte); char* file = sd_file_read(path, NULL);
if (sizeof(char) != endByte) if (file == NULL)
forceExit = true;
//gfx_printf("|%c|", currentchar);
return currentchar;
}
void getfollowingchar(char end){
while (currentchar != end && !f_eof(&scriptin)){
if (currentchar == '"'){
while (getnextchar() != '"' && !f_eof(&scriptin));
}
getnextchar();
}
}
void getnextvalidchar(){
while ((!((currentchar >= '?' && currentchar <= 'Z') || (currentchar >= 'a' && currentchar <= 'z') || currentchar == '#') && !f_eof(&scriptin)) /*|| currentchar == ';' */)
getnextchar();
}
char *makestr(u32 size, char ignore){
char *str;
u32 count = 0;
str = calloc(size + 1, sizeof(char));
for (u32 i = 0; i < size; i++){
getnextchar();
if (ignore != 0 && ignore == currentchar)
continue;
str[count++] = currentchar;
}
return str;
}
char *readtilchar(char end, char ignore){
FSIZE_t offset, size;
offset = f_tell(&scriptin);
getfollowingchar(end);
size = f_tell(&scriptin) - offset;
if (size <= 0)
return NULL;
f_lseek(&scriptin, offset - 1);
return makestr((u32)size, ignore);
}
char *funcbuff = NULL;
void functionparser(){
char *unsplitargs;
/*
if (funcbuff != NULL)
free(funcbuff);
*/
funcbuff = readtilchar('(', ' ');
getfollowingchar('(');
getnextchar();
unsplitargs = readtilchar(')', 0);
if (unsplitargs != NULL){
argc = splitargs(unsplitargs);
getnextchar();
}
else {
argc = 0;
}
getnextchar();
free(unsplitargs);
}
char *gettargetvar(){
char *variable = NULL;
variable = readtilchar('=', ' ');
getfollowingchar('=');
getnextchar();
return variable;
}
void mainparser(){
char *variable = NULL;
int res, out = 0;
getnextvalidchar();
if (f_eof(&scriptin))
return; return;
if (currentchar == '#'){
getfollowingchar('\n');
return;
}
if (currentchar == '@'){
variable = gettargetvar();
getnextvalidchar();
}
functionparser();
res = run_function(funcbuff, &out);
if (res < 0){
printerrors = true;
//gfx_printf("%s|%s|%d", funcbuff, argv[0], argc);
//btn_wait();
int lineNumber = 1;
u64 end = f_tell(&scriptin);
f_lseek(&scriptin, 0);
while (f_tell(&scriptin) < end && !f_eof(&scriptin)){
if (getnextchar() == '\n')
lineNumber++;
}
gfx_errDisplay((res == -1) ? funcbuff : "run_function", (res == -1) ? ERR_IN_FUNC : ERR_SCRIPT_LOOKUP_FAIL, lineNumber);
forceExit = true;
//gfx_printf("Func: %s\nArg1: %s\n", funcbuff, argv[0]);
}
else {
str_int_add("@RESULT", out);
if (variable != NULL)
str_int_add(variable, out);
}
//gfx_printf("\nGoing to next func %c\n", currentchar);
if (funcbuff != NULL){
free(funcbuff);
funcbuff = NULL;
}
if (argv != NULL) {
for (int i = 0; argv[i] != NULL; i++)
free(argv[i]);
free(argv);
argv = NULL;
}
if (variable != NULL){
free(variable);
}
}
void skipbrackets(){
u32 bracketcounter = 0;
getfollowingchar('{');
getnextchar();
while ((currentchar != '}' || bracketcounter != 0) && !f_eof(&scriptin)){
if (currentchar == '{')
bracketcounter++;
else if (currentchar == '}')
bracketcounter--;
getnextchar();
}
}
extern u32 currentcolor;
extern char *currentpath;
void runScript(char *path){
int res;
char *path_local = NULL;
forceExit = false;
currentchar = 0;
currentcolor = COLOR_WHITE;
gfx_clearscreen(); gfx_clearscreen();
utils_copystring(path, &path_local);
res = f_open(&scriptin, path, FA_READ | FA_OPEN_EXISTING); scriptCtx_t ctx = createScriptCtx();
if (res != FR_OK){ lexarVector_t vec = lexarGo(file);
gfx_errDisplay("ParseScript", res, 1); free(file);
return; ctx.script = &vec;
scriptResult_t res = mainLoop(&ctx);
gfx_printf("end of script\n");
if (res.resCode) {
gfx_printf("[ERROR] %d\n%s\nNear:", res.resCode, functionFails[res.resCode - 1]);
printToken(res.nearToken);
} }
printerrors = false; gfx_printf("\n\n");
//mainLoop2(&ctx, &vec);
//add builtin vars lexarVectorClear(&vec);
str_int_add("@EMUMMC", emu_cfg.enabled); destroyScriptCtx(&ctx);
str_int_add("@RESULT", 0); hidWait();
str_int_add("@JOYCONN", hidConnected());
str_str_add("$CURRENTPATH", currentpath);
//str_int_printall();
while (!f_eof(&scriptin) && !forceExit){
mainparser();
}
printerrors = true;
//str_int_printall();
f_close(&scriptin);
str_int_clear();
//str_jmp_clear();
str_str_clear();
free(path_local);
//btn_wait();
} }

View File

@@ -1,7 +1,9 @@
#pragma once #pragma once
#define INFUNC_FAIL (int)0xC0000000 #include "types.h"
//#define DictValue(type, val, len) (dictValue_t) {type, len, val}
void runScript(char *path); #define scriptResultCreate(resCode, funcName) (scriptResult_t) {resCode, funcName}
void skipbrackets();
void getfollowingchar(char end); void startScript(char* path);
char* readFile(char* path);

View File

@@ -0,0 +1,37 @@
#include "scriptCtx.h"
#include "list.h"
#include "malloc.h"
#include "types.h"
scriptCtx_t createScriptCtx() {
scriptCtx_t ctx;
ctx.indentInstructors = calloc(sizeof(indentInstructor_t), 64);
ctx.indentLevel = 0;
ctx.vars = varVectorInit(16);
ctx.script = NULL;
ctx.lastToken.token = 0;
ctx.varToken.token = 0;
ctx.startEq = 0;
ctx.varIndexStruct = 0;
return ctx;
}
void destroyScriptCtx(scriptCtx_t* ctx) {
// TODO
varVectorFree(&ctx->vars);
free(ctx->indentInstructors);
}
u8 setIndentInstruction(scriptCtx_t* ctx, u8 level, u8 skip, int jumpLoc) {
if (level >= 64)
return 1;
ctx->indentInstructors[level].skip = skip;
ctx->indentInstructors[level].active = 1;
ctx->indentInstructors[level].jump = (jumpLoc >= 0) ? 1 : 0;
ctx->indentInstructors[level].jumpLoc = jumpLoc;
return 0;
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include "types.h"
#define TEXTHOLDEREMPTY() (textHolder_t) {0}
#define TEXTHOLDER(start, len) (textHolder_t) {start, len, 1}
u8 setIndentInstruction(scriptCtx_t* ctx, u8 level, u8 skip, int jumpLoc);
void destroyScriptCtx(scriptCtx_t* ctx);
scriptCtx_t createScriptCtx();
static inline indentInstructor_t getCurIndentInstruction(scriptCtx_t* ctx);
static inline u8 setCurIndentInstruction(scriptCtx_t* ctx, u8 skip, int jumpLoc);
static inline u8 setCurIndentInstruction(scriptCtx_t* ctx, u8 skip, int jumpLoc) {
return setIndentInstruction(ctx, ctx->indentLevel, skip, jumpLoc);
}
static inline indentInstructor_t getCurIndentInstruction(scriptCtx_t* ctx) {
return ctx->indentInstructors[ctx->indentLevel];
}

View File

@@ -0,0 +1,174 @@
#pragma once
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef struct {
u16 token;
union {
char* text;
int val;
};
} lexarToken_t;
typedef struct {
lexarToken_t* tokens;
u32 len;
u32 stored;
} lexarVector_t;
enum Tokens {
Invalid = 0,
Variable = 1,
LBracket,
RBracket,
RCBracket,
LCBracket,
StrLit,
IntLit,
Seperator,
Plus,
Minus,
Multiply,
Division,
Mod,
Smaller,
SmallerEqual,
Bigger,
BiggerEqual,
Equal,
EqualEqual,
Not,
NotEqual,
LogicAND,
LogicOR,
LSBracket,
RSBracket,
AND,
OR
};
enum Errors {
ERRBADOPERATOR = 1,
ERRDOUBLENOT,
ERRSYNTAX,
ERRINVALIDTYPE,
ERRNOVAR,
ERRNOFUNC,
ERRINACTIVEINDENT
};
typedef struct { // this is to keep track of how many {} we passed. Keep an internal var with the "indentation level", +1 for {, -1 for }. have an array with the following def on what to do (on func: enter, set indentation & jump back, on while, jump to while, use while as if, on if simply set true or false)
union {
struct {
u8 active : 1;
u8 skip : 1;
u8 jump : 1;
};
u8 container;
};
int jumpLoc;
} indentInstructor_t;
typedef struct {
char* start;
u32 len;
union {
struct {
u8 set : 1;
};
u8 options;
};
} textHolder_t;
typedef struct {
int resCode;
lexarToken_t* nearToken;
} scriptResult_t;
#define JumpDictValue(jump) (dictValue_t) {{JumpType}, 0, .integer = jump}
#define StrDictValue(str) (dictValue_t) {{StringType}, 0, .string = str}
#define ErrDictValue(err) (dictValue_t) {{ErrType}, 0, .integer = err}
#define NullDictValue() (dictValue_t) {{NullType}, 0, .integer = 0}
#define IntArrDictValue(arr, len) (dictValue_t) {{IntArrayType}, len, .integerArray = arr}
#define StringArrDictValue(arr, len) (dictValue_t) {{StringArrayType}, len, .stringArray = arr}
#define IntDictValue(i) (dictValue_t) {{IntType}, 0, .integer = i}
enum {
IntType = 0,
StringType,
IntArrayType,
StringArrayType,
ByteArrayType,
JumpType,
DictType,
NullType,
ErrType,
};
typedef struct {
union {
u8 type;
struct {
u8 varType : 7;
u8 free : 1;
};
};
unsigned int arrayLen;
union {
int integer;
char* string;
unsigned char* byteArray;
int* integerArray;
char** stringArray;
};
} dictValue_t;
typedef struct {
char* key;
dictValue_t value;
} dict_t;
typedef struct {
dict_t* vars;
u32 len;
u32 stored;
} varVector_t;
typedef struct {
indentInstructor_t* indentInstructors;
u8 indentLevel; // -> max 63
varVector_t vars;
lexarVector_t* script;
lexarToken_t lastToken;
lexarToken_t varToken;
u32 startEq;
u32 curPos;
u32 lastTokenPos;
lexarVector_t args_loc;
union {
u32 varIndexStruct;
struct {
u32 varIndex : 31;
u32 varIndexSet : 1;
};
};
} scriptCtx_t;
typedef dictValue_t(*func_int_ptr)(scriptCtx_t* ctx, varVector_t* args);
typedef struct {
char* key;
func_int_ptr value;
union {
u8 args;
struct {
u8 argCount : 6;
u8 varArgs : 1;
u8 operatorParse : 1;
};
};
} str_fnc_struct;
#define FREEINDICT 0x80

View File

@@ -1,250 +0,0 @@
#include <string.h>
#include "../../mem/heap.h"
#include "../gfx/gfxutils.h"
#include "../emmc/emmc.h"
#include "../../utils/types.h"
#include "../../libs/fatfs/ff.h"
#include "../../utils/sprintf.h"
#include "../../utils/btn.h"
#include "../../gfx/gfx.h"
#include "../../utils/util.h"
#include "../../storage/emummc.h"
#include "parser.h"
#include "../common/common.h"
#include "../fs/fsactions.h"
#include "variables.h"
#include "../utils/utils.h"
static dict_str_int *str_int_table = NULL;
static dict_str_str *str_str_table = NULL;
//static dict_str_loc *str_jmp_table = NULL;
int str_int_add(char *key, int value){
char *key_local;
dict_str_int *keyvaluepair;
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_int));
keyvaluepair->key = key_local;
keyvaluepair->value = value;
keyvaluepair->next = NULL;
if (str_int_table == NULL){
str_int_table = keyvaluepair;
}
else {
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
temp->value = value;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_int_find(char *key, int *out){
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
if (!strcmp(temp->key, key)){
*out = temp->value;
return 0;
}
temp = temp->next;
}
return -1;
}
void str_int_clear(){
dict_str_int *cur, *next;
cur = str_int_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur);
cur = next;
}
str_int_table = NULL;
}
void str_int_printall(){
dict_str_int *temp;
temp = str_int_table;
while (temp != NULL){
gfx_printf("%s -> %d\n", temp->key, temp->value);
temp = temp->next;
}
}
/*
int str_jmp_add(char *key, u64 value){
char *key_local;
dict_str_loc *keyvaluepair;
//gfx_printf("Adding |%s|\n", key_local);
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_loc));
keyvaluepair->key = key_local;
keyvaluepair->value = value;
keyvaluepair->next = NULL;
if (str_jmp_table == NULL){
str_jmp_table = keyvaluepair;
}
else {
dict_str_loc *temp;
temp = str_jmp_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
temp->value = value;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_jmp_find(char *key, u64 *out){
dict_str_loc *temp;
temp = str_jmp_table;
//gfx_printf("Searching |%s|\n", key);
while (temp != NULL){
if (!strcmp(temp->key, key)){
//gfx_printf("Key found!\n", temp->value);
*out = temp->value;
return 0;
}
temp = temp->next;
}
//gfx_printf("no key!\n");
return -1;
}
void str_jmp_clear(){
dict_str_loc *cur, *next;
cur = str_jmp_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur);
cur = next;
}
str_jmp_table = NULL;
}
*/
int str_str_add(char *key, char *value){
char *key_local, *value_local;
dict_str_str *keyvaluepair;
//gfx_printf("Adding |%s|\n", key_local);
utils_copystring(value, &value_local);
utils_copystring(key, &key_local);
keyvaluepair = calloc(1, sizeof(dict_str_str));
keyvaluepair->key = key_local;
keyvaluepair->value = value_local;
keyvaluepair->next = NULL;
if (str_str_table == NULL){
str_str_table = keyvaluepair;
}
else {
dict_str_str *temp;
temp = str_str_table;
while (temp != NULL){
if (!strcmp(temp->key, key_local)){
free(keyvaluepair);
free(key_local);
free(temp->value);
temp->value = value_local;
return 0;
}
if (temp->next == NULL){
temp->next = keyvaluepair;
return 0;
}
temp = temp->next;
}
}
return 0;
}
int str_str_find(char *key, char **out){
dict_str_str *temp;
temp = str_str_table;
while (temp != NULL){
if (!strcmp(temp->key, key)){
*out = temp->value;
return 0;
}
temp = temp->next;
}
return -1;
}
int str_str_index(int index, char **out){
dict_str_str *temp;
temp = str_str_table;
for (int i = 0; i < index; i++){
if (temp == NULL)
return -1;
temp = temp->next;
}
if (temp == NULL)
return -1;
*out = temp->value;
return 0;
}
void str_str_clear(){
dict_str_str *cur, *next;
cur = str_str_table;
while (cur != NULL){
next = cur->next;
free(cur->key);
free(cur->value);
free(cur);
cur = next;
}
str_str_table = NULL;
}

View File

@@ -1,34 +0,0 @@
#pragma once
#include "../../utils/types.h"
typedef struct _dict_str_int {
char *key;
int value;
struct _dict_str_int *next;
} dict_str_int;
typedef struct _dict_str_str {
char *key;
char *value;
struct _dict_str_str *next;
} dict_str_str;
typedef struct _dict_str_loc {
char *key;
u64 value;
struct _dict_str_loc *next;
} dict_str_loc;
int str_int_add(char *key, int value);
int str_int_find(char *key, int *out);
void str_int_clear();
void str_int_printall();
/*
int str_jmp_add(char *key, u64 value);
int str_jmp_find(char *key, u64 *out);
void str_jmp_clear();
*/
int str_str_add(char *key, char *value);
int str_str_find(char *key, char **out);
int str_str_index(int index, char **out);
void str_str_clear();

View File

@@ -17,6 +17,7 @@
#include "../fs/fsutils.h" #include "../fs/fsutils.h"
#include "../../mem/heap.h" #include "../../mem/heap.h"
#include "../utils/utils.h" #include "../utils/utils.h"
#include "../fs/nca.h"
extern bool sd_mount(); extern bool sd_mount();
extern void sd_unmount(); extern void sd_unmount();
@@ -93,7 +94,9 @@ void displaygpio(){
} }
} }
int dumpfirmware(int mmc){
// bad code ahead aaaa
int dumpfirmware(int mmc, bool daybreak){
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
bool fail = false; bool fail = false;
@@ -107,6 +110,22 @@ int dumpfirmware(int mmc){
connect_mmc(mmc); connect_mmc(mmc);
mount_mmc("SYSTEM", 2); mount_mmc("SYSTEM", 2);
if (daybreak){
if (!fsutil_checkfile("sd:/switch/prod.keys")){
SWAPCOLOR(COLOR_RED);
gfx_printf("prod.keys not found.\nPress any button to exit");
hidWait();
return true;
}
if (SetHeaderKey()){
SWAPCOLOR(COLOR_RED);
gfx_printf("Failed to find header key.\nPress any button to exit");
hidWait();
return true;
}
}
gfx_printf("PKG1 version: %d\n", pkg1.ver); gfx_printf("PKG1 version: %d\n", pkg1.ver);
gfx_printf("Creating folders...\n"); gfx_printf("Creating folders...\n");
@@ -115,7 +134,24 @@ int dumpfirmware(int mmc){
sdbase = calloc(32 + strlen(pkg1.id), sizeof(char)); sdbase = calloc(32 + strlen(pkg1.id), sizeof(char));
sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id); sprintf(sdbase, "sd:/tegraexplorer/Firmware/%d (%s)", pkg1.ver, pkg1.id);
gfx_printf("Out: %s\n", sdbase);
if (fsutil_checkfile(sdbase)){
SWAPCOLOR(COLOR_RED);
gfx_printf("Destination folder already exists.\nPress X to delete this folder, any other button to cancel\nPath: %s", sdbase);
Inputs *input = hidWait();
if (!input->x){
free(sdbase);
return true;
}
else {
SWAPCOLOR(COLOR_WHITE);
gfx_printf("\nDeleting folder..\n");
fsact_del_recursive(sdbase);
}
}
gfx_printf("\rOut: %s\n", sdbase);
f_mkdir(sdbase); f_mkdir(sdbase);
if ((ret = f_opendir(&dir, sysbase))) if ((ret = f_opendir(&dir, sysbase)))
@@ -127,16 +163,39 @@ int dumpfirmware(int mmc){
printerrors = 0; printerrors = 0;
while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){ while(!f_readdir(&dir, &fno) && fno.fname[0] && !fail){
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath);
utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp); utils_copystring(fsutil_getnextloc(sysbase, fno.fname), &syspathtemp);
if (fno.fattrib & AM_DIR){ if (fno.fattrib & AM_DIR){
utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath); utils_copystring(fsutil_getnextloc(syspathtemp, "00"), &syspath);
free(syspathtemp);
} }
else else
syspath = syspathtemp; syspath = syspathtemp;
if (daybreak){
u8 ContentType = GetNcaType(syspath);
if (ContentType < 0){
fail = true;
continue;
}
char *temp;
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &temp);
if (ContentType == 0x01){
sdpath = calloc(strlen(temp) + 6, 1);
strcpy(sdpath, temp);
memcpy(sdpath + strlen(temp) - 4, ".cnmt.nca", 10);
free(temp);
}
else {
sdpath = temp;
}
}
else
utils_copystring(fsutil_getnextloc(sdbase, fno.fname), &sdpath);
ret = fsact_copy(syspath, sdpath, 0); ret = fsact_copy(syspath, sdpath, 0);
gfx_printf("%d %s\r", ++amount, fno.fname); gfx_printf("%d %s\r", ++amount, fno.fname);
@@ -145,6 +204,8 @@ int dumpfirmware(int mmc){
fail = true; fail = true;
free(sdpath); free(sdpath);
free(syspathtemp);
if (syspath != syspathtemp)
free(syspath); free(syspath);
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../../utils/types.h"
void displayinfo(); void displayinfo();
void displaygpio(); void displaygpio();
int format(int mode); int format(int mode);
int dumpfirmware(int mmc); int dumpfirmware(int mmc, bool daybreak);

View File

@@ -203,3 +203,9 @@ char *utils_copyStringSize(const char *in, int size){
memcpy(out, in, size); memcpy(out, in, size);
return out; return out;
} }
char* util_cpyStr(const char* in){
char *out = malloc(strlen(in) + 1);
strcpy(out, in);
return out;
}

View File

@@ -25,3 +25,4 @@ void utils_copystring(const char *in, char **out);
char *utils_InputText(char *start, int maxLen); char *utils_InputText(char *start, int maxLen);
void utils_takeScreenshot(); void utils_takeScreenshot();
char *utils_copyStringSize(const char *in, int size); char *utils_copyStringSize(const char *in, int size);
char* util_cpyStr(const char* in);