From 22e884ce39f375301242edef64542ad01f4a7d7f Mon Sep 17 00:00:00 2001 From: Harley Amundsen Date: Sat, 21 Jan 2017 07:28:59 -0500 Subject: [PATCH] v1.2.0 - Changed config format to include... mediatype. No major features added besides this --- Makefile | 8 +-- include/common.h | 1 - include/conf.h | 7 +++ include/fs.h | 6 +- include/tests.h | 1 + romfs/config | 1 + source/backup.c | 1 + source/conf.c | 29 +++++++++ source/fs.c | 149 ++++++++++++++++++++++++++++++++++++++++++++-- source/kb.c | 4 ++ source/launcher.c | 29 +++++++-- source/main.c | 44 ++++++++++---- source/tests.c | 59 +++++++++++++++++- source/town.c | 123 ++++++++++++++++++++++---------------- 14 files changed, 379 insertions(+), 83 deletions(-) create mode 100644 include/conf.h create mode 100644 romfs/config create mode 100644 source/conf.c diff --git a/Makefile b/Makefile index d530c38..e5d5f5e 100644 --- a/Makefile +++ b/Makefile @@ -47,16 +47,16 @@ ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft # -ffunction-sections \ # $(ARCH) -CFLAGS := -g -Wall -Wextra -O2 -mword-relocations \ - -fomit-frame-pointer -ffunction-sections \ +CFLAGS := -ggdb -Wall -Wextra -O2 -mword-relocations \ + -ffunction-sections \ $(ARCH) CFLAGS += $(INCLUDE) -DARM11 -D_3DS CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +ASFLAGS := -ggdb $(ARCH) +LDFLAGS = -specs=3dsx.specs -ggdb $(ARCH) -Wl,-Map,$(notdir $*.map) LIBS := -lsfil -lsftd -lfreetype -lpng -lz -lsf2d -lcitro3d -lctru -lm diff --git a/include/common.h b/include/common.h index ec097f1..1b10a79 100644 --- a/include/common.h +++ b/include/common.h @@ -7,7 +7,6 @@ #define EU_GAMEID 0x0004000000086400 #define JP_GAMEID 0x0004000000086200 #define SECOND_IN_NS (1000*1000*1000) -#define SIZE_GARDEN 522752 #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) extern bool is3dsx; diff --git a/include/conf.h b/include/conf.h new file mode 100644 index 0000000..5e35bea --- /dev/null +++ b/include/conf.h @@ -0,0 +1,7 @@ +typedef struct{ + char* townname; + unsigned char mediatype_val; +} conftok_t; + +int conf_parse(const char* data, conftok_t* token); +int conf_gen(char** data, conftok_t* token); //data must be a pointer! diff --git a/include/fs.h b/include/fs.h index d76f0c8..e85149c 100644 --- a/include/fs.h +++ b/include/fs.h @@ -21,14 +21,18 @@ extern FS_Archive game_arch; extern FS_Archive sdmc_arch; Result fs_init(); -Result open_archives(); +Result open_sdmc_archive(); +Result open_game_archive(); Result close_archives(); void fs_fini(); +int load_config(char** current_town); + dir_t get_dirs(char* path); file_t get_files(FS_Archive arch, char* path); void get_mediatype(); +void change_mediatype(); int get_titleid(); #endif diff --git a/include/tests.h b/include/tests.h index 5054701..b7ada8f 100644 --- a/include/tests.h +++ b/include/tests.h @@ -3,6 +3,7 @@ void run_tests(); +void conf_parse_test(); void text_test(); void simple_gfx_test(); void gfx_test(); diff --git a/romfs/config b/romfs/config new file mode 100644 index 0000000..a58932d --- /dev/null +++ b/romfs/config @@ -0,0 +1 @@ +Main \ No newline at end of file diff --git a/source/backup.c b/source/backup.c index e04276c..58575fa 100644 --- a/source/backup.c +++ b/source/backup.c @@ -176,6 +176,7 @@ void backup_to_prev_folder(char* dirname){ ret = FSUSER_DeleteFile(sdmc_arch, fsMakePath(PATH_ASCII, filepath)); if(ret){ gfx_error(ret, __FILENAME__, __LINE__); + gfx_waitmessage("dirname: %s", dirname); return; } free(filepath); diff --git a/source/conf.c b/source/conf.c new file mode 100644 index 0000000..7c64bc0 --- /dev/null +++ b/source/conf.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#include "common.h" +#include "gfx.h" +#include "conf.h" + +//tokens must be array or pre-allocated pointer +int conf_parse(const char* data, conftok_t* token){ + int len; + + len = data[0]; + token->townname = calloc(len+1, 1); //1 = '\0' + sprintf(token->townname, "%.*s", len, &data[1]); + token->mediatype_val = data[1+len]; + + return 0; +} + +//data must not be a pointer to an array +int conf_gen(char** data, conftok_t* token){ + //str format: (length of townname (1 bytes))townname(mediatype_val (1 byte)) + *data = calloc(1+strlen(token->townname+1+1), 1); + sprintf(*data, "%c%s%c", strlen(token->townname), token->townname, token->mediatype_val); + + return 0; +} diff --git a/source/fs.c b/source/fs.c index c20e84f..fed4635 100644 --- a/source/fs.c +++ b/source/fs.c @@ -1,11 +1,14 @@ +#include #include #include +#include #include <3ds.h> #include "common.h" #include "gfx.h" #include "menu.h" +#include "conf.h" #include "fs.h" FS_MediaType mediatype; @@ -29,17 +32,22 @@ Result fs_init(){ return ret; } -Result open_archives(){ +Result open_sdmc_archive(){ Result ret; - u32* path; - FS_Path null_binpath, game_binpath; //open sdmc card - null_binpath = (FS_Path){PATH_EMPTY, 1, (u8*)""}; - ret = FSUSER_OpenArchive(&sdmc_arch, ARCHIVE_SDMC, null_binpath); + ret = FSUSER_OpenArchive(&sdmc_arch, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")); if(ret) return ret; + return ret; +} + +Result open_game_archive(){ + Result ret; + u32* path; + FS_Path game_binpath; + if(is3dsx){ ret = FSUSER_OpenArchive(&game_arch, ARCHIVE_SAVEDATA, fsMakePath(PATH_EMPTY, "")); if(ret) @@ -70,6 +78,97 @@ void fs_fini(){ fsExit(); } +int load_config(char** current_town){ + //loads config file and sets *current_town + Result ret; + Handle handle; + FILE* f; + u64 size; + int tempsize; + u32 read; //bytes read + u32 written; //bytes written + char* buf; + conftok_t token; + const char* configpath = "/TownManager/config"; + + //if config file was just created now + if((ret = FSUSER_CreateFile(sdmc_arch, fsMakePath(PATH_ASCII, configpath), 0, 0)) == 0){ + //open template config file + if(!(f = fopen("romfs:/config", "r"))){ + gfx_waitmessage("Could not open template config file."); + return -1; + } + fseek(f, 0L, SEEK_END); + tempsize = ftell(f); + rewind(f); + if((buf = malloc(tempsize)) == NULL){ + gfx_waitmessage("malloc failed! %s:%d", __FILENAME__, __LINE__); + return -1; + } + fread(buf, tempsize, 1, f); + fclose(f); + + //open the newly created config file + if((ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, configpath), FS_OPEN_READ | FS_OPEN_WRITE, 0))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + conf_parse(buf, &token); + get_mediatype(); + token.mediatype_val = mediatype; + free(buf); + buf = calloc(2+strlen(token.townname)+1+1, 1); + conf_gen(&buf, &token); + size = strlen(buf); + if((ret = FSFILE_Write(handle, &written, 0, buf, size, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if(size != written){ + gfx_waitmessage("size != written! %s:%d", __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_SetSize(handle, size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_Close(handle))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + *current_town = "Main"; + return 0; + } + //if config file exists + else{ + if((ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, configpath), FS_OPEN_READ, 0))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_GetSize(handle, &size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if((buf = malloc(size)) == NULL){ + gfx_waitmessage("malloc failed! %s:%d", __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_Read(handle, &read, 0, buf, size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_Close(handle))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + conf_parse(buf, &token); + mediatype = token.mediatype_val; + *current_town = token.townname; + } + + return 0; +} + dir_t get_dirs(char* path){ Result ret; Handle handle; @@ -93,6 +192,7 @@ dir_t get_dirs(char* path){ dirs.dirs[dirs.numdirs-1] = u16str2str(get_ent.name); } while(read > 0); + FSDIR_Close(handle); return dirs; } @@ -121,6 +221,7 @@ file_t get_files(FS_Archive arch, char* path){ files.files[files.numfiles-1] = u16str2str(get_ent.name); } while(read > 0); + FSDIR_Close(handle); return files; } @@ -145,6 +246,44 @@ void get_mediatype(){ } } +void change_mediatype(){ + Result ret; + Handle handle; + u32 read; + u32 written; + u32 size; + char* buf; + conftok_t token; + + get_mediatype(); + if((ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/config"), FS_OPEN_READ | FS_OPEN_WRITE, 0))){ + gfx_error(ret, __FILENAME__, __LINE__); + return; + } + if((ret = FSFILE_GetSize(handle, (u64*)&size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return; + } + buf = malloc(size); + if((ret = FSFILE_Read(handle, &read, 0, buf, size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return; + } + conf_parse(buf, &token); + token.mediatype_val = mediatype; + conf_gen(&buf, &token); + if((ret = FSFILE_Write(handle, &written, 0, buf, size, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME))){ + gfx_error(ret, __FILENAME__, __LINE__); + return; + } + if((ret = FSFILE_Close(handle))){ + gfx_error(ret, __FILENAME__, __LINE__); + return; + } + + gfx_waitmessage("Changed media source."); +} + int get_titleid(){ Result ret; u32 num_sdtitles; diff --git a/source/kb.c b/source/kb.c index 0b7f5b1..9413e61 100644 --- a/source/kb.c +++ b/source/kb.c @@ -1,4 +1,5 @@ #include +#include #include <3ds.h> @@ -12,6 +13,9 @@ char* get_string(char* hint){ swkbdSetHintText(&key_state, hint); swkbdInputText(&key_state, input, 64); + if(strcmp(input, "") == 0){ + return NULL; + } return input; } diff --git a/source/launcher.c b/source/launcher.c index 7f2d1e4..63158b0 100644 --- a/source/launcher.c +++ b/source/launcher.c @@ -8,6 +8,7 @@ #include "fs.h" #include "gfx.h" #include "backup.h" +#include "conf.h" #include "launcher.h" static Handle nssHandle = 0; @@ -29,8 +30,10 @@ int prepare_to_launch(char* dirname){ char* townpath; char* filepath; char* buf; - u32 written; u64 size; + u32 read; + u32 written; + conftok_t token; file_t sdmc_files, game_files; int i; int error; @@ -86,16 +89,32 @@ int prepare_to_launch(char* dirname){ if(is3dsx) fs_init(); free(townpath); - //Write dirname as the sole contents of the /TownManager/tm.conf file - if((ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/tm.conf"), FS_OPEN_WRITE, 0))){ + if((ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/config"), FS_OPEN_READ | FS_OPEN_WRITE, 0))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_GetSize(handle, &size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return -1; + } + if((buf = malloc(size)) == NULL){ + gfx_waitmessage("%s:%d malloc failed!", __FILENAME__, __LINE__); + return -1; + } + if((ret = FSFILE_Read(handle, &read, 0, buf, size))){ gfx_error(ret, __FILENAME__, __LINE__); return -1; } - if((ret = FSFILE_Write(handle, &written, 0, dirname, strlen(dirname)+1, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME))){ + conf_parse(buf, &token); + token.townname = dirname; + free(buf); + buf = calloc(2+strlen(token.townname)+1+1, 1); //1 = '\0' + conf_gen(&buf, &token); + if((ret = FSFILE_SetSize(handle, strlen(buf)))){ gfx_error(ret, __FILENAME__, __LINE__); return -1; } - if((ret = FSFILE_SetSize(handle, (u64)(strlen(dirname)+1)))){ + if((ret = FSFILE_Write(handle, &written, 0, buf, strlen(buf), FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME))){ gfx_error(ret, __FILENAME__, __LINE__); return -1; } diff --git a/source/main.c b/source/main.c index 437458a..6868b26 100644 --- a/source/main.c +++ b/source/main.c @@ -1,4 +1,5 @@ #include +#include #include #include <3ds.h> @@ -13,10 +14,11 @@ #include "launcher.h" int debug = 0; +const char* tmver = "1.2.0"; int main(){ Result ret; - char* current_town; + char* current_town = NULL; if(debug == 1){ run_tests(); return 0; @@ -27,30 +29,45 @@ int main(){ int menuindex = 0; int menucount; - char headerstr[] = "TownManager"; + char* headerstr; + headerstr = calloc(strlen("TownManager - v")+10+1, 1); //give 10 chars for ver string + sprintf(headerstr, "TownManager - v%s", tmver); char** menu_entries = NULL; gfx_init(); if(is3dsx){ - ret = fs_init(); - if(ret){ + if((ret = fs_init())){ gfx_error(ret, __FILENAME__, __LINE__); goto main_cleanup; } } - get_mediatype(); - if(get_titleid() == -1) + //open sdmc archive + if((ret = open_sdmc_archive())){ + gfx_error(ret, __FILENAME__, __LINE__); + goto main_cleanup; + } + //create sdmc:/TownManager if it does not already exist + FSUSER_CreateDirectory(sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager"), 0); + //load configuration file + if(load_config(¤t_town) < 0){ + gfx_waitmessage("load_config failed"); goto main_cleanup; + } + //get titleid (titleid varies depending on region) + if(get_titleid() == -1){ + gfx_waitmessage("get_titleid failed"); + goto main_cleanup; + } + //initialize launcher launcher_init(); - ret = open_archives(); - if(ret){ + //open game archive + if((ret = open_game_archive())){ gfx_error(ret, __FILENAME__, __LINE__); goto main_cleanup; } - load_tm_config(¤t_town); - if(strcmp(current_town, "") != 0){ + if(current_town != NULL){ backup_to_prev_folder(current_town); } @@ -59,12 +76,15 @@ int main(){ display_menu(menu_entries, menucount, &menuindex, headerstr); - if(menuindex != menucount-1 && menuindex != -1){ + if(menuindex < menucount-2 && menuindex != -1){ town_opts(menu_entries[menuindex]); } - else if(menucount != 1 && menuindex != -1){ + else if(menuindex == menucount-2){ create_town(); } + else if(menuindex == menucount-1){ + change_mediatype(); + } } main_cleanup: close_archives(); diff --git a/source/tests.c b/source/tests.c index ac92b6b..a04c835 100644 --- a/source/tests.c +++ b/source/tests.c @@ -1,4 +1,5 @@ #include +#include #include <3ds.h> #include @@ -10,18 +11,70 @@ #include "kb.h" #include "launcher.h" #include "backup.h" +#include "fs.h" +#include "conf.h" #include "tests.h" void run_tests(){ + conf_parse_test(); //text_test(); //simple_gfx_test(); //gfx_test(); - menu_test(); - kb_test(); - launcher_test(); + //menu_test(); + //kb_test(); + //launcher_test(); } +void conf_parse_test(){ + Handle handle; + u32 written; + Result ret; + char* orig_str1; + char* reconst_str1; + conftok_t token = {NULL, 0}; + + + gfx_init(); + open_sdmc_archive(); + + const char* townname = "Tokyo"; + const int mediatype_val = 1; + //str format: (length of townname (2 bytes))townname(mediatype_val (1 byte)) + orig_str1 = calloc(2+strlen(townname)+1+1, 1); //refer to above, last 1 = '\0' + sprintf(orig_str1, "%02d%s%c", strlen(townname), townname, mediatype_val); + conf_parse(orig_str1, &token); + gfx_waitmessage("townname:"); + gfx_waitmessage((char*)token.townname); + gfx_waitmessage("mediatype:"); + gfx_waitmessage("%d", token.mediatype_val); + //goto conf_parse_test_cleanup; //temporary + conf_gen(&reconst_str1, &token); + + gfx_waitmessage("Reconstructed str:%s", reconst_str1); + + FSUSER_CreateDirectory(sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager"), 0); + if((ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/test.txt"), FS_OPEN_WRITE | FS_OPEN_CREATE, 0))){ + gfx_error(ret, __FILENAME__, __LINE__); + goto conf_parse_test_cleanup; + } + if((ret = FSFILE_Write(handle, &written, 0, reconst_str1, strlen(reconst_str1), FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME))){ + gfx_error(ret, __FILENAME__, __LINE__); + goto conf_parse_test_cleanup; + } + if((ret = FSFILE_SetSize(handle, strlen(reconst_str1)))){ + gfx_error(ret, __FILENAME__, __LINE__); + } + if(written != strlen(reconst_str1)){ + gfx_waitmessage("Error! size of reconst_str1 is %u and written in %u", strlen(reconst_str1), written); + } +conf_parse_test_cleanup: + if((ret = FSFILE_Close(handle))){ + gfx_error(ret, __FILENAME__, __LINE__); + } + + gfx_fini(); +} void text_test(){ gfxInitDefault(); diff --git a/source/town.c b/source/town.c index 9c253b1..bba3965 100644 --- a/source/town.c +++ b/source/town.c @@ -11,6 +11,7 @@ #include "backup.h" #include "kb.h" #include "launcher.h" +#include "conf.h" #include "town.h" void populate_menu_entries(char*** menu_entries, int* menucount){ @@ -20,23 +21,28 @@ void populate_menu_entries(char*** menu_entries, int* menucount){ dirs = get_dirs("/TownManager/Saves/"); - *menucount = dirs.numdirs+1; - *menu_entries = malloc((dirs.numdirs+1)*sizeof(char*)); + *menucount = dirs.numdirs+2; //"New" and "Change media source" + *menu_entries = malloc((dirs.numdirs+2)*sizeof(char*)); for(i = 0; i < dirs.numdirs; i++){ (*menu_entries)[i] = dirs.dirs[i]; } - (*menu_entries)[dirs.numdirs] = "New"; + (*menu_entries)[dirs.numdirs] = "-New town-"; + (*menu_entries)[dirs.numdirs+1] = "-Change media source-"; } void create_town(){ Result ret; Handle handle; + u32 read; u32 written; + u32 size; char* townname; char* savesdir = "/TownManager/Saves/"; char* towndir; char* filepath; + char* buf; file_t files; + conftok_t token; int i; townname = get_string("Enter a town name"); @@ -52,18 +58,28 @@ void create_town(){ gfx_error(ret, __FILENAME__, __LINE__); return; } - //Write townname as the sole contents of the /TownManager/tm.conf file - ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/tm.conf"), FS_OPEN_WRITE, 0); + //Change town in config file + ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/config"), FS_OPEN_WRITE, 0); if(ret){ gfx_error(ret, __FILENAME__, __LINE__); return; } - ret = FSFILE_Write(handle, &written, 0, townname, strlen(townname)+1, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME); + + size = 2+strlen(townname)+1+1; + buf = calloc(size, 1); //see conf.c for info on what this means + if((ret = FSFILE_Read(handle, &read, 0, buf, size))){ + gfx_error(ret, __FILENAME__, __LINE__); + return; + } + conf_parse(buf, &token); + token.townname = townname; + conf_gen(&buf, &token); + ret = FSFILE_Write(handle, &written, 0, buf, strlen(buf)+1, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME); if(ret){ gfx_error(ret, __FILENAME__, __LINE__); return; } - ret = FSFILE_SetSize(handle, (u64)(strlen(townname)+1)); + ret = FSFILE_SetSize(handle, (u64)(strlen(buf)+1)); if(ret){ gfx_error(ret, __FILENAME__, __LINE__); return; @@ -105,7 +121,7 @@ void init_save_folder(){ char* filepath; u64 size; int i; - + gfx_waitmessage("No save folders detected! Importing current saves as 'Main'."); ret = FSUSER_CreateDirectory(sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/Saves/Main"), 0); if(ret){ @@ -140,7 +156,7 @@ void load_tm_config(char** current){ int i; int eol = 0; char* buf2; - + FSUSER_CreateDirectory(sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager"), 0); ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/tm.conf"), FS_OPEN_READ | FS_OPEN_CREATE, 0); if(ret){ @@ -166,7 +182,7 @@ void load_tm_config(char** current){ gfx_waitmessage("Bytes read does not match size! (load_tm_config())"); return; } - + for(i = 0; i < (int)read; i++){ if(buf[i] == '\n'){ break; @@ -183,7 +199,6 @@ void load_tm_config(char** current){ void town_opts(char* dirname){ int menuindex = 0; int menucount = 4; - char* current_town; int ret; char headerstr[] = "Town options"; @@ -194,9 +209,7 @@ void town_opts(char* dirname){ "Rename town", "Delete town" }; - - load_tm_config(¤t_town); - + while(aptMainLoop()){ display_menu(menu_entries, menucount, &menuindex, headerstr); @@ -207,27 +220,27 @@ void town_opts(char* dirname){ case 0: //code to load game files and inject them into game ret = prepare_to_launch(dirname); - if(ret == -1){ - gfx_waitmessage("Game failed to launch :("); + if(ret == -1){ + gfx_waitmessage("Game failed to launch :("); + break; + } + if(is3dsx){ + gfx_displaymessage("Launching game... (this may take ~10 seconds)"); + } + launch_game(); + svcSleepThread(2*SECOND_IN_NS); //so that the last message gets displayed and stays there as the game launches break; - } - if(is3dsx){ - gfx_displaymessage("Launching game... (this may take ~10 seconds)"); - } - launch_game(); - svcSleepThread(2*SECOND_IN_NS); //so that the last message gets displayed and stays there as the game launches - break; - case 1: - clone_town(dirname); - return; - case 2: - rename_town(dirname); - return; - case 3: - delete_town(dirname); - return; + case 1: + clone_town(dirname); + return; + case 2: + rename_town(dirname); + return; + case 3: + delete_town(dirname); + return; + } } - } } void clone_town(char* dirname){ @@ -242,7 +255,7 @@ void clone_town(char* dirname){ int i; newtown = get_string("Enter a name for the cloned town"); - if(strcmp(newtown, "") == 0){ + if(newtown == NULL){ gfx_waitmessage("Nothing entered. Town not cloned"); return; } @@ -269,11 +282,14 @@ void clone_town(char* dirname){ void rename_town(char* dirname){ Result ret; char* savespath = "/TownManager/Saves/"; - char* newname; + char* newname = NULL; char oldpath[strlen(savespath)+strlen(dirname)+1]; char newpath[strlen(savespath)+64+1]; newname = get_string("Enter the new name of the town"); + if(newname == NULL){ + return; + } memset(oldpath, '\0', sizeof(oldpath)); sprintf(oldpath, "%s%s", savespath, dirname); memset(newpath, '\0', sizeof(newpath)); @@ -291,13 +307,15 @@ void delete_town(char* dirname){ Handle handle; int error = 0; u32 read; + u32 written; u64 size; char* savespath = "/TownManager/Saves/"; char* dirpath; - char* lasttown; + char* buf; + conftok_t token; - //check if town in tm.conf is the same as the selected town - ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/tm.conf"), FS_OPEN_READ, 0); + //check if town in config is the same as the selected town + ret = FSUSER_OpenFile(&handle, sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/config"), FS_OPEN_READ, 0); if(ret){ gfx_error(ret, __FILENAME__, __LINE__); error = 1; @@ -309,36 +327,37 @@ void delete_town(char* dirname){ error = 1; goto delete_town_cleanup; } - lasttown = calloc(size+1, 1); - ret = FSFILE_Read(handle, &read, 0, lasttown, (u32)size); + buf = calloc(size+1, 1); + ret = FSFILE_Read(handle, &read, 0, buf, (u32)size); if(ret){ gfx_error(ret, __FILENAME__, __LINE__); error = 1; goto delete_town_cleanup; } - FSFILE_Close(handle); - //if same, delete tm.conf + conf_parse(buf, &token); + + //if Main, don't delete if(strcmp(dirname, "Main") == 0){ gfx_waitmessage("'Main' cannot be deleted as it is the default save file."); error = 1; goto delete_town_cleanup; } - if(strcmp(dirname, lasttown) == 0){ - gfx_displaymessage("Deleting tm.conf..."); - ret = FSUSER_DeleteFile(sdmc_arch, fsMakePath(PATH_ASCII, "/TownManager/tm.conf")); - if(ret){ - gfx_error(ret, __FILENAME__, __LINE__); - error = 1; - } + if(strcmp(dirname, token.townname) == 0){ + //changes default town back to Main + token.townname = "Main"; + size = 2+strlen(token.townname)+1+1; + conf_gen(&buf, &token); + FSFILE_Write(handle, &written, 0, buf, size, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME); + FSFILE_SetSize(handle, (u64)size); } - free(lasttown); + free(buf); + FSFILE_Close(handle); //Delete town folder dirpath = calloc(strlen(savespath)+strlen(dirname)+1, 1); sprintf(dirpath, "%s%s", savespath, dirname); gfx_displaymessage("Deleting town..."); - ret = FSUSER_DeleteDirectoryRecursively(sdmc_arch, fsMakePath(PATH_ASCII, dirpath)); - if(ret){ + if((ret = FSUSER_DeleteDirectoryRecursively(sdmc_arch, fsMakePath(PATH_ASCII, dirpath)))){ gfx_waitmessage("dirpath: %s", dirpath); gfx_error(ret, __FILENAME__, __LINE__); error = 1;