diff --git a/src/game/save_file.c b/src/game/save_file.c index a8db910b..934b122e 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -391,7 +391,6 @@ BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex) { void save_file_load_all(void) { s32 file; - s32 validSlots; gMainMenuDataModified = FALSE; gSaveFileModified = FALSE; @@ -405,6 +404,7 @@ void save_file_load_all(void) { gSaveFileModified = TRUE; gMainMenuDataModified = TRUE; #else + s32 validSlots; read_eeprom_data(&gSaveBuffer, sizeof(gSaveBuffer)); if (save_file_need_bswap(&gSaveBuffer)) diff --git a/src/game/text_save.inc.h b/src/game/text_save.inc.h index 29b6851b..1325f0a5 100644 --- a/src/game/text_save.inc.h +++ b/src/game/text_save.inc.h @@ -5,43 +5,38 @@ #include "pc/ini.h" #include "pc/platform.h" -#define FILENAME_FORMAT "%s/save_file_%d.sav" +#define FILENAME_FORMAT "%s\\sm64_save_file_%d.sav" #define NUM_COURSES 15 #define NUM_BONUS_COURSES 10 #define NUM_FLAGS 21 #define NUM_CAP_ON 4 -/* Flag keys */ const char *sav_flags[NUM_FLAGS] = { "file_exists", "wing_cap", "metal_cap", "vanish_cap", "key_1", "key_2", "basement_door", "upstairs_door", "ddd_moved_back", "moat_drained", "pps_door", "wf_door", "ccm_door", "jrb_door", "bitdw_door", - "bitfs_door", "", "", "", "", "50star_door" + "bitfs_door", "", "", "", "", "50star_door" // 4 Cap flags are processed in their own section }; -/* Main course keys */ const char *sav_courses[NUM_COURSES] = { "bob", "wf", "jrb", "ccm", "bbh", "hmc", "lll", "ssl", "ddd", "sl", "wdw", "ttm", "thi", "ttc", "rr" }; -/* Bonus courses keys (including Castle Course) */ const char *sav_bonus_courses[NUM_BONUS_COURSES] = { - "hub", "bitdw", "bitfs", "bits", "pss", "cotmc", - "totwc", "vcutm", "wmotr", "sa", + "bitdw", "bitfs", "bits", "pss", "cotmc", + "totwc", "vcutm", "wmotr", "sa", "hub" // hub is Castle Grounds }; -/* Mario's cap type keys */ const char *cap_on_types[NUM_CAP_ON] = { "ground", "klepto", "ukiki", "mrblizzard" }; -/* Sound modes */ const char *sound_modes[3] = { "stereo", "mono", "headset" }; -/* Get current timestamp */ +/* Get current timestamp string */ static void get_timestamp(char* buffer) { time_t timer; struct tm* tm_info; @@ -77,104 +72,107 @@ static u32 int_to_bin(u32 n) { } /** - * Write SaveFile and MainMenuSaveData structs to a text-based savefile. + * Write SaveFile and MainMenuSaveData structs to a text-based savefile */ static s32 write_text_save(s32 fileIndex) { FILE* file; struct SaveFile *savedata; struct MainMenuSaveData *menudata; char filename[SYS_MAX_PATH] = { 0 }; - char value[SYS_MAX_PATH] = { 0 }; + char *value; u32 i, bit, flags, coins, stars, starFlags; - /* Define savefile's name */ if (snprintf(filename, sizeof(filename), FILENAME_FORMAT, sys_save_path(), fileIndex) < 0) return -1; file = fopen(filename, "wt"); - if (file == NULL) + if (file == NULL) { + printf("Savefile '%s' not found!\n", filename); return -1; - else - printf("Updating savefile in '%s'\n", filename); + } else + printf("Saving updated progress to '%s'\n", filename); - /* Write header */ fprintf(file, "# Super Mario 64 save file\n"); fprintf(file, "# Comment starts with #\n"); fprintf(file, "# True = 1, False = 0\n"); - /* Write current timestamp */ get_timestamp(value); fprintf(file, "# %s\n", value); - /* Write MainMenuSaveData info */ menudata = &gSaveBuffer.menuData[0]; fprintf(file, "\n[menu]\n"); fprintf(file, "coin_score_age = %d\n", menudata->coinScoreAges[fileIndex]); - /* Sound mode */ if (menudata->soundMode == 0) { - fprintf(file, "sound_mode = %s\n", sound_modes[0]); // stereo + fprintf(file, "sound_mode = %s\n", sound_modes[0]); // stereo } else if (menudata->soundMode == 3) { - fprintf(file, "sound_mode = %s\n", sound_modes[1]); // mono + fprintf(file, "sound_mode = %s\n", sound_modes[1]); // mono } else if (menudata->soundMode == 1) { - fprintf(file, "sound_mode = %s\n", sound_modes[2]); // headset + fprintf(file, "sound_mode = %s\n", sound_modes[2]); // headset } else { printf("Undefined sound mode!"); return -1; } - /* Write all flags */ fprintf(file, "\n[flags]\n"); for (i = 1; i < NUM_FLAGS; i++) { if (strcmp(sav_flags[i], "")) { flags = save_file_get_flags(); - flags = (flags & (1 << i)); /* Get a specific bit */ - flags = (flags) ? 1 : 0; /* Determine if bit is set or not */ + flags = (flags & (1 << i)); // Get 'star' flag bit + flags = (flags) ? 1 : 0; fprintf(file, "%s = %d\n", sav_flags[i], flags); } } - /* Write coin count and star flags from each course (except Castle Grounds) */ fprintf(file, "\n[courses]\n"); for (i = 0; i < NUM_COURSES; i++) { stars = save_file_get_star_flags(fileIndex, i); coins = save_file_get_course_coin_score(fileIndex, i); - starFlags = int_to_bin(stars); /* 63 -> 111111 */ + starFlags = int_to_bin(stars); // 63 -> 111111 fprintf(file, "%s = \"%d, %07d\"\n", sav_courses[i], coins, starFlags); } - /* Write star flags from each bonus cource (including Castle Grounds) */ fprintf(file, "\n[bonus]\n"); for (i = 0; i < NUM_BONUS_COURSES; i++) { - if (i == 0) { - stars = save_file_get_star_flags(fileIndex, -1); - } else { - stars = save_file_get_star_flags(fileIndex, i+14); - } - starFlags = int_to_bin(stars); + char *format; - fprintf(file, "%s = %d\n", sav_bonus_courses[i], starFlags); + if (i == NUM_BONUS_COURSES-1) { + // Process Castle Grounds + stars = save_file_get_star_flags(fileIndex, -1); + format = "%05d"; + } else if (i == 3) { + // Process Princess's Secret Slide + stars = save_file_get_star_flags(fileIndex, 18); + format = "%02d"; + } else { + // Process bonus courses + stars = save_file_get_star_flags(fileIndex, i+15); + format = "%d"; + } + + starFlags = int_to_bin(stars); + if (sprintf(value, format, starFlags) < 0) + return -1; + fprintf(file, "%s = %s\n", sav_bonus_courses[i], value); } - /* Write who steal Mario's cap */ fprintf(file, "\n[cap]\n"); for (i = 0; i < NUM_CAP_ON; i++) { - flags = save_file_get_flags(); // Read all flags - bit = (1 << (i+16)); // Determine current flag - flags = (flags & bit); // Get `cap` flag - flags = (flags) ? 1 : 0; // Determine if bit is set or not + flags = save_file_get_flags(); + bit = (1 << (i+16)); // Determine current flag + flags = (flags & bit); // Get 'cap' flag bit + flags = (flags) ? 1 : 0; if (flags) { fprintf(file, "type = %s\n", cap_on_types[i]); break; } } - /* Write in what course and area Mario losted its cap, and cap's position */ savedata = &gSaveBuffer.files[fileIndex][0]; switch(savedata->capLevel) { case COURSE_SSL: @@ -187,12 +185,13 @@ static s32 write_text_save(s32 fileIndex) { fprintf(file, "level = %s\n", "ttm"); break; default: - fprintf(file, "level = %s\n", "none"); break; } - fprintf(file, "area = %d\n", savedata->capArea); + if (savedata->capLevel) { + fprintf(file, "area = %d\n", savedata->capArea); + } - /* Update a backup */ + // Backup is nessecary for saving recent progress after gameover bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1], sizeof(gSaveBuffer.files[fileIndex][1])); @@ -201,22 +200,19 @@ static s32 write_text_save(s32 fileIndex) { } /** - * Read gSaveBuffer data from a text-based savefile. + * Read gSaveBuffer data from a text-based savefile */ static s32 read_text_save(s32 fileIndex) { char filename[SYS_MAX_PATH] = { 0 }; - char temp[SYS_MAX_PATH] = { 0 }; const char *value; ini_t *savedata; u32 i, flag, coins, stars, starFlags; u32 capArea; - /* Define savefile's name */ if (snprintf(filename, sizeof(filename), FILENAME_FORMAT, sys_save_path(), fileIndex) < 0) return -1; - /* Try to open the file */ savedata = ini_load(filename); if (savedata == NULL) { return -1; @@ -224,7 +220,6 @@ static s32 read_text_save(s32 fileIndex) { printf("Loading savefile from '%s'\n", filename); } - /* Read coin score age for selected file and sound mode */ ini_sget(savedata, "menu", "coin_score_age", "%d", &gSaveBuffer.menuData[0].coinScoreAges[fileIndex]); @@ -245,32 +240,28 @@ static s32 read_text_save(s32 fileIndex) { return -1; } - /* Parse main flags */ for (i = 1; i < NUM_FLAGS; i++) { value = ini_get(savedata, "flags", sav_flags[i]); - if (value) { - flag = strtol(value, &temp, 10); + flag = value[0] - '0'; // Flag should be 0 or 1 if (flag) { - flag = 1 << i; /* Look #define in header.. */ + flag = 1 << i; // Flags defined in 'save_file' header gSaveBuffer.files[fileIndex][0].flags |= flag; } } } - /* Parse coin and star values for each main course */ for (i = 0; i < NUM_COURSES; i++) { value = ini_get(savedata, "courses", sav_courses[i]); if (value) { sscanf(value, "%d, %d", &coins, &stars); - starFlags = bin_to_int(stars); /* 111111 -> 63 */ + starFlags = bin_to_int(stars); // 111111 -> 63 save_file_set_star_flags(fileIndex, i, starFlags); gSaveBuffer.files[fileIndex][0].courseCoinScores[i] = coins; } } - /* Parse star values for each bonus course */ for (i = 0; i < NUM_BONUS_COURSES; i++) { value = ini_get(savedata, "bonus", sav_bonus_courses[i]); if (value) { @@ -278,19 +269,18 @@ static s32 read_text_save(s32 fileIndex) { starFlags = bin_to_int(stars); if (strlen(value) == 5) { - /* Process Castle Grounds */ + // Process Castle Grounds save_file_set_star_flags(fileIndex, -1, starFlags); } else if (strlen(value) == 2) { - /* Process Princess's Secret Slide */ - save_file_set_star_flags(fileIndex, COURSE_PSS, starFlags); + // Process Princess's Secret Slide + save_file_set_star_flags(fileIndex, 18, starFlags); } else { - /* Process another shitty bonus course */ + // Process bonus courses save_file_set_star_flags(fileIndex, i+15, starFlags); } } } - /* Find, who steal Mario's cap ... */ for (i = 0; i < NUM_CAP_ON; i++) { value = ini_get(savedata, "cap", "type"); if (value) { @@ -302,20 +292,16 @@ static s32 read_text_save(s32 fileIndex) { } } - /* ... it's level ... */ value = ini_get(savedata, "cap", "level"); if (value) { if (strcmp(value, "ssl") == 0) { - gSaveBuffer.files[fileIndex][0].capLevel = 8; // ssl + gSaveBuffer.files[fileIndex][0].capLevel = COURSE_SSL; // ssl } else if (strcmp(value, "sl") == 0) { - gSaveBuffer.files[fileIndex][0].capLevel = 10; // sl + gSaveBuffer.files[fileIndex][0].capLevel = COURSE_SL; // sl } else if (strcmp(value, "ttm") == 0) { - gSaveBuffer.files[fileIndex][0].capLevel = 12; // ttm - } - else if (strcmp(value, "none") == 0) { - gSaveBuffer.files[fileIndex][0].capLevel = 0; + gSaveBuffer.files[fileIndex][0].capLevel = COURSE_TTM; // ttm } else { printf("Invalid 'cap:level' flag!\n"); @@ -323,7 +309,6 @@ static s32 read_text_save(s32 fileIndex) { } } - /* ... and it's area */ value = ini_get(savedata, "cap", "area"); if (value) { sscanf(value, "%d", &capArea); @@ -336,14 +321,13 @@ static s32 read_text_save(s32 fileIndex) { } } - /* Good, file exists for gSaveBuffer */ + // Good, file exists for gSaveBuffer gSaveBuffer.files[fileIndex][0].flags |= SAVE_FLAG_FILE_EXISTS; - /* Make a backup */ + // Backup is nessecary for saving recent progress after gameover bcopy(&gSaveBuffer.files[fileIndex][0], &gSaveBuffer.files[fileIndex][1], sizeof(gSaveBuffer.files[fileIndex][1])); - /* Cleaning up after ourselves */ ini_free(savedata); return 0; }