mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-09 18:31:43 +00:00
strike
This commit is contained in:
parent
e881a04f86
commit
0db3bd8812
10 changed files with 171 additions and 40 deletions
|
|
@ -119,7 +119,7 @@ override_disallowed_functions = {
|
|||
"src/pc/djui/djui_console.h": [ " djui_console_create", "djui_console_message_create", "djui_console_message_dequeue" ],
|
||||
"src/pc/djui/djui_chat_message.h": [ "create_from" ],
|
||||
"src/game/interaction.h": [ "process_interaction", "_handle_" ],
|
||||
"src/game/save_file.h": [ "save_file_get_dir" ],
|
||||
"src/game/save_file.h": [ "save_file_get_dir", "save_file_get_first_available_index" ],
|
||||
"src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ],
|
||||
"src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ],
|
||||
"src/pc/network/network_player.h": [ "_init", "_connected[^_]", "_shutdown", "_disconnected", "_update", "construct_player_popup", "network_player_name_valid" ],
|
||||
|
|
|
|||
|
|
@ -6797,7 +6797,7 @@ METAL = CAP --- @type PlayerPart
|
|||
--- | `METAL`
|
||||
|
||||
--- @type integer
|
||||
NUM_SAVE_FILES = 32
|
||||
NUM_SAVE_FILES = 64
|
||||
|
||||
SAVE_FILE_A = 0 --- @type SaveFileIndex
|
||||
SAVE_FILE_B = 1 --- @type SaveFileIndex
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ extern "C" {
|
|||
extern s32 osEepromProbe(OSMesgQueue *);
|
||||
extern s32 osEepromRead(OSMesgQueue *, u8, u8 *);
|
||||
extern s32 osEepromWrite(OSMesgQueue *, u8, u8 *);
|
||||
extern s32 osEepromLongReadLegacy(OSMesgQueue *, u8 , u8 *, int);
|
||||
extern s32 osEepromLongRead(OSMesgQueue *, u8, u8, u8 *, int);
|
||||
extern s32 osEepromLongWrite(OSMesgQueue *, u8, u8, u8 *, int);
|
||||
|
||||
|
|
|
|||
|
|
@ -219,6 +219,10 @@ SAVE_TITLE = "SAVE"
|
|||
ERASE_TITLE = "ERASE"
|
||||
CONFIRM = "Are you sure you want to erase this save slot?"
|
||||
ERASE = "Erase"
|
||||
CREATE_SAVE = "Create Save"
|
||||
CREATE = "Create"
|
||||
CREATE_TITLE = "CREATE"
|
||||
CREATE_NAME = "Set Save File @'s Name:"
|
||||
EDIT = "Edit"
|
||||
EDIT_TITLE = "EDIT"
|
||||
EDIT_NAME = "Edit Save File @'s Name:"
|
||||
|
|
|
|||
|
|
@ -98,11 +98,6 @@ s8 get_level_course_num(s16 levelNum) {
|
|||
return gLevelToCourseNumTable[levelNum];
|
||||
}
|
||||
|
||||
void save_file_get_dir(int fileIndex, char* outPath, size_t size) {
|
||||
snprintf(outPath, size, "%s%s%d.bin", SAVE_DIRECTORY, SAVE_FILENAME, fileIndex);
|
||||
printf("Returning filepath: %s\n", outPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Byteswap all multibyte fields in a SaveBlockSignature.
|
||||
*/
|
||||
|
|
@ -274,6 +269,20 @@ static void save_file_bswap(struct SaveBuffer *buf) {
|
|||
}
|
||||
}
|
||||
|
||||
void save_file_get_dir(int fileIndex, char* outPath, size_t size) {
|
||||
snprintf(outPath, size, "%s%s%d.bin", SAVE_DIRECTORY, SAVE_FILENAME, fileIndex);
|
||||
}
|
||||
|
||||
s32 save_file_get_first_available_index() {
|
||||
if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY))) return 0;
|
||||
for (int i = 0; i < NUM_SAVE_FILES; i++) {
|
||||
char filePath[256];
|
||||
save_file_get_dir(i, filePath, 256);
|
||||
if (!fs_sys_file_exists(fs_get_write_path(filePath))) return i;
|
||||
}
|
||||
return NUM_SAVE_FILES;
|
||||
}
|
||||
|
||||
void save_file_do_save(s32 fileIndex, s8 forceSave) {
|
||||
if (INVALID_FILE_INDEX(fileIndex)) { return; }
|
||||
if (gNetworkType != NT_SERVER) {
|
||||
|
|
@ -306,8 +315,11 @@ void save_file_erase(s32 fileIndex) {
|
|||
bzero(&gSaveBuffer.files[fileIndex][0], sizeof(gSaveBuffer.files[fileIndex][0]));
|
||||
bzero(&gSaveBuffer.files[fileIndex][1], sizeof(gSaveBuffer.files[fileIndex][1]));
|
||||
|
||||
gSaveFileModified = TRUE;
|
||||
save_file_do_save(fileIndex, TRUE);
|
||||
if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY))) return;
|
||||
char filepath[256];
|
||||
save_file_get_dir(fileIndex, filepath, 256);
|
||||
if (!fs_sys_file_exists(fs_get_write_path(filepath))) return;
|
||||
remove(fs_get_write_path(filepath));
|
||||
}
|
||||
|
||||
void save_file_reload(u8 loadAll) {
|
||||
|
|
@ -349,6 +361,17 @@ void save_file_load_all(UNUSED u8 reload) {
|
|||
|
||||
gSaveFileModified = FALSE;
|
||||
|
||||
if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY))) {
|
||||
// Attempt to get and convert old save data into new
|
||||
struct LegacySaveBuffer saveBuffer = { 0 };
|
||||
s32 status = osEepromLongReadLegacy(&gSIEventMesgQueue, 0, (void*)&saveBuffer, sizeof(saveBuffer));
|
||||
// 0 is success
|
||||
if (status == 0) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
write_eeprom_data(i, saveBuffer.files[i], sizeof(saveBuffer.files[i]), 0);
|
||||
}
|
||||
}
|
||||
|
||||
bzero(&gSaveBuffer, sizeof(gSaveBuffer));
|
||||
|
||||
for (int file = 0; file < NUM_SAVE_FILES; file++) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "course_table.h"
|
||||
|
||||
#define NUM_SAVE_FILES 32
|
||||
#define NUM_SAVE_FILES 64
|
||||
// size of savebuffer
|
||||
#define EEPROM_SIZE 128
|
||||
|
||||
|
|
@ -60,6 +60,35 @@ struct SaveBuffer
|
|||
struct SaveFile files[NUM_SAVE_FILES][2];
|
||||
};
|
||||
|
||||
// Legacy save info for loading old save files
|
||||
struct LegacyMainMenuSaveData
|
||||
{
|
||||
// Each save file has a 2 bit "age" for each course. The higher this value,
|
||||
// the older the high score is. This is used for tie-breaking when displaying
|
||||
// on the high score screen.
|
||||
u32 coinScoreAges[4];
|
||||
u16 soundMode;
|
||||
|
||||
#ifdef VERSION_EU
|
||||
u16 language;
|
||||
#define SUBTRAHEND 8
|
||||
#else
|
||||
#define SUBTRAHEND 6
|
||||
#endif
|
||||
|
||||
// Pad to match the EEPROM size of 0x200 (10 bytes on JP/US, 8 bytes on EU)
|
||||
u8 filler[512 / 2 - SUBTRAHEND - 4 * (4 + sizeof(struct SaveFile))];
|
||||
|
||||
struct SaveBlockSignature signature;
|
||||
};
|
||||
|
||||
struct LegacySaveBuffer {
|
||||
// Each of the four save files has two copies. If one is bad, the other is used as a backup.
|
||||
struct SaveFile files[4][2];
|
||||
// The main menu data has two copies. If one is bad, the other is used as a backup.
|
||||
struct LegacyMainMenuSaveData menuData[2];
|
||||
};
|
||||
|
||||
extern u8 gLastCompletedCourseNum;
|
||||
extern u8 gLastCompletedStarNum;
|
||||
extern s8 sUnusedGotGlobalCoinHiScore;
|
||||
|
|
@ -122,6 +151,8 @@ s8 get_level_course_num(s16 levelNum);
|
|||
|
||||
void save_file_get_dir(int fileIndex, char* outPath, size_t size);
|
||||
|
||||
s32 save_file_get_first_available_index();
|
||||
|
||||
/* |description|
|
||||
Saves the current state of the game into a specified save file. Includes data verification and backup management.
|
||||
Useful for maintaining game progress during play or when saving manually
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ enum RefreshRateMode {
|
|||
RRM_MAX
|
||||
};
|
||||
|
||||
extern char configSaveNames[32][MAX_SAVE_NAME_STRING];
|
||||
extern char configSaveNames[64][MAX_SAVE_NAME_STRING];
|
||||
|
||||
// display settings
|
||||
extern ConfigWindow configWindow;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,22 @@
|
|||
#include "game/save_file.h"
|
||||
#include "pc/configfile.h"
|
||||
|
||||
static struct DjuiFlowLayout* sSaveLayout = NULL;
|
||||
static struct DjuiPaginated* sSavePaginated = NULL;
|
||||
static struct DjuiInputbox* sSaveNameInputBox = NULL;
|
||||
static struct DjuiBase* sSaveButtonCaller = NULL;
|
||||
static struct DjuiButton* sSaveButtons[NUM_SAVE_FILES] = { NULL };
|
||||
static s32 sButtonTag = 0;
|
||||
static bool sEditing = true;
|
||||
|
||||
static void djui_panel_host_save_update_button(struct DjuiButton* button, int slot);
|
||||
static void djui_panel_host_save_add_saves(struct DjuiBase* base);
|
||||
|
||||
static void djui_panel_host_reload_saves() {
|
||||
djui_base_destroy_children(&sSaveLayout->base);
|
||||
djui_panel_host_save_add_saves(&sSaveLayout->base);
|
||||
djui_paginated_calculate_height(sSavePaginated);
|
||||
}
|
||||
|
||||
static void djui_panel_host_save_save_name_change(UNUSED struct DjuiBase* caller) {
|
||||
snprintf(configSaveNames[sButtonTag], MAX_SAVE_NAME_STRING, "%s", sSaveNameInputBox->buffer);
|
||||
|
|
@ -21,7 +31,23 @@ static void djui_panel_host_save_save_name_change(UNUSED struct DjuiBase* caller
|
|||
}
|
||||
}
|
||||
|
||||
static void djui_panel_create_create(struct DjuiBase* caller) {
|
||||
if (sEditing) { return; }
|
||||
if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY)))
|
||||
fs_sys_mkdir(fs_get_write_path(SAVE_DIRECTORY));
|
||||
char filePath[256];
|
||||
save_file_get_dir(sButtonTag, filePath, 256);
|
||||
if (fs_sys_file_exists(fs_get_write_path(filePath))) return;
|
||||
u8 content[EEPROM_SIZE] = { 0 };
|
||||
FILE *fp = fopen(fs_get_write_path(filePath), "wb");
|
||||
if (fp == NULL) { return; }
|
||||
fwrite(content, 1, EEPROM_SIZE, fp);
|
||||
djui_panel_host_reload_saves();
|
||||
djui_panel_menu_back(caller);
|
||||
}
|
||||
|
||||
static bool djui_panel_edit_back(UNUSED struct DjuiBase* caller) {
|
||||
if (!sEditing) { return false; }
|
||||
if (configSaveNames[sButtonTag][0] == '\0') {
|
||||
snprintf(configSaveNames[sButtonTag], MAX_SAVE_NAME_STRING, "SM64");
|
||||
}
|
||||
|
|
@ -30,15 +56,15 @@ static bool djui_panel_edit_back(UNUSED struct DjuiBase* caller) {
|
|||
}
|
||||
|
||||
static void djui_panel_edit_create(struct DjuiBase* caller) {
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(HOST_SAVE, EDIT_TITLE), false);
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(sEditing ? DLANG(HOST_SAVE, EDIT_TITLE) : DLANG(HOST_SAVE, CREATE_TITLE), false);
|
||||
struct DjuiBase* body = djui_three_panel_get_body(panel);
|
||||
{
|
||||
struct DjuiRect* rect1 = djui_rect_container_create(body, 32);
|
||||
{
|
||||
char buffer[64] = { 0 };
|
||||
char slotBuffer[4];
|
||||
snprintf(slotBuffer, sizeof(slotBuffer), "%d", sButtonTag);
|
||||
djui_language_replace(DLANG(HOST_SAVE, EDIT_NAME), buffer, 64, '@', slotBuffer);
|
||||
snprintf(slotBuffer, sizeof(slotBuffer), "%d", sButtonTag + 1);
|
||||
djui_language_replace(sEditing ? DLANG(HOST_SAVE, EDIT_NAME) : DLANG(HOST_SAVE, CREATE_NAME), buffer, 64, '@', slotBuffer);
|
||||
struct DjuiText* text = djui_text_create(&rect1->base, buffer);
|
||||
djui_base_set_size_type(&text->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE);
|
||||
djui_base_set_color(&text->base, 220, 220, 220, 255);
|
||||
|
|
@ -56,6 +82,7 @@ static void djui_panel_edit_create(struct DjuiBase* caller) {
|
|||
djui_interactable_hook_value_change(&sSaveNameInputBox->base, djui_panel_host_save_save_name_change);
|
||||
}
|
||||
|
||||
if (!sEditing) djui_button_create(body, DLANG(HOST_SAVE, CREATE), DJUI_BUTTON_STYLE_NORMAL, djui_panel_create_create);
|
||||
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back);
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +90,19 @@ static void djui_panel_edit_create(struct DjuiBase* caller) {
|
|||
djui_panel_add(caller, panel, NULL);
|
||||
}
|
||||
|
||||
static void djui_panel_save_create(struct DjuiBase* caller) {
|
||||
sEditing = false;
|
||||
sButtonTag = save_file_get_first_available_index();
|
||||
if (sButtonTag >= NUM_SAVE_FILES) return;
|
||||
djui_panel_edit_create(caller);
|
||||
}
|
||||
|
||||
static void djui_panel_host_save_edit(struct DjuiBase* caller) {
|
||||
sEditing = true;
|
||||
sButtonTag = caller->tag;
|
||||
djui_panel_edit_create(caller);
|
||||
}
|
||||
|
||||
static void djui_panel_host_save_update_button(struct DjuiButton* button, int slot) {
|
||||
char starString[64] = { 0 };
|
||||
if (configSaveNames[slot][0] == '\0') {
|
||||
|
|
@ -82,6 +122,7 @@ static void djui_panel_host_save_erase_yes(struct DjuiBase* caller) {
|
|||
save_file_erase(sButtonTag);
|
||||
play_character_sound(gMarioState, CHAR_SOUND_WAAAOOOW);
|
||||
djui_panel_host_save_update_button(sSaveButtons[sButtonTag], sButtonTag);
|
||||
djui_panel_host_reload_saves();
|
||||
djui_panel_menu_back(caller);
|
||||
}
|
||||
|
||||
|
|
@ -93,9 +134,33 @@ static void djui_panel_host_save_erase(struct DjuiBase* caller) {
|
|||
djui_panel_host_save_erase_yes);
|
||||
}
|
||||
|
||||
static void djui_panel_host_save_edit(struct DjuiBase* caller) {
|
||||
sButtonTag = caller->tag;
|
||||
djui_panel_edit_create(caller);
|
||||
void djui_panel_host_save_add_saves(struct DjuiBase* base) {
|
||||
if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY))) return;
|
||||
for (int i = 0; i < NUM_SAVE_FILES; i++) {
|
||||
char filepath[256];
|
||||
save_file_get_dir(i, filepath, 256);
|
||||
if (!fs_sys_file_exists(fs_get_write_path(filepath))) continue;
|
||||
struct DjuiRect* rect1 = djui_rect_container_create(base, 32);
|
||||
{
|
||||
struct DjuiButton* button1 = djui_button_create(&rect1->base, "", DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_save_button_click);
|
||||
djui_panel_host_save_update_button(button1, i);
|
||||
djui_base_set_size(&button1->base, 0.6f, 32);
|
||||
button1->base.tag = i;
|
||||
sSaveButtons[i] = button1;
|
||||
|
||||
struct DjuiButton* button2 = djui_button_create(&rect1->base, DLANG(HOST_SAVE, ERASE), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_save_erase);
|
||||
button2->base.tag = i;
|
||||
djui_base_set_size(&button2->base, 0.19f, 32);
|
||||
djui_base_set_alignment(&button2->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
|
||||
djui_base_set_location(&button2->base, configDjuiThemeCenter ? 127 : button1->rect->base.width.value + 98, 0);
|
||||
djui_base_set_enabled(&button2->base, gDjuiInMainMenu || gCurrSaveFileNum - 1 != i);
|
||||
|
||||
struct DjuiButton* button3 = djui_button_create(&rect1->base, DLANG(HOST_SAVE, EDIT), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_save_edit);
|
||||
button3->base.tag = i;
|
||||
djui_base_set_size(&button3->base, 0.19f, 32);
|
||||
djui_base_set_alignment(&button3->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_TOP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void djui_panel_host_save_create(struct DjuiBase* caller) {
|
||||
|
|
@ -104,29 +169,14 @@ void djui_panel_host_save_create(struct DjuiBase* caller) {
|
|||
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(HOST_SAVE, SAVE_TITLE), false);
|
||||
struct DjuiBase* body = djui_three_panel_get_body(panel);
|
||||
{
|
||||
for (int i = 0; i < NUM_SAVE_FILES; i++) {
|
||||
struct DjuiRect* rect1 = djui_rect_container_create(body, 32);
|
||||
{
|
||||
struct DjuiButton* button1 = djui_button_create(&rect1->base, "", DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_save_button_click);
|
||||
djui_panel_host_save_update_button(button1, i);
|
||||
djui_base_set_size(&button1->base, 0.6f, 32);
|
||||
button1->base.tag = i;
|
||||
sSaveButtons[i] = button1;
|
||||
|
||||
struct DjuiButton* button2 = djui_button_create(&rect1->base, DLANG(HOST_SAVE, ERASE), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_save_erase);
|
||||
button2->base.tag = i;
|
||||
djui_base_set_size(&button2->base, 0.19f, 32);
|
||||
djui_base_set_alignment(&button2->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_TOP);
|
||||
djui_base_set_location(&button2->base, configDjuiThemeCenter ? 127 : button1->rect->base.width.value + 98, 0);
|
||||
djui_base_set_enabled(&button2->base, gDjuiInMainMenu || gCurrSaveFileNum - 1 != i);
|
||||
|
||||
struct DjuiButton* button3 = djui_button_create(&rect1->base, DLANG(HOST_SAVE, EDIT), DJUI_BUTTON_STYLE_NORMAL, djui_panel_host_save_edit);
|
||||
button3->base.tag = i;
|
||||
djui_base_set_size(&button3->base, 0.19f, 32);
|
||||
djui_base_set_alignment(&button3->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_TOP);
|
||||
}
|
||||
}
|
||||
struct DjuiPaginated* paginated = djui_paginated_create(body, 8);
|
||||
paginated->showMaxCount = true;
|
||||
sSaveLayout = paginated->layout;
|
||||
djui_panel_host_save_add_saves(&paginated->layout->base);
|
||||
djui_paginated_calculate_height(paginated);
|
||||
sSavePaginated = paginated;
|
||||
|
||||
djui_button_create(body, DLANG(HOST_SAVE, CREATE_SAVE), DJUI_BUTTON_STYLE_NORMAL, djui_panel_save_create);
|
||||
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_NORMAL, djui_panel_menu_back);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2997,7 +2997,7 @@ char gSmluaConstants[] = ""
|
|||
"EMBLEM=7\n"
|
||||
"PLAYER_PART_MAX=8\n"
|
||||
"METAL=CAP\n"
|
||||
"NUM_SAVE_FILES=32\n"
|
||||
"NUM_SAVE_FILES=64\n"
|
||||
"SAVE_FILE_A=0\n"
|
||||
"SAVE_FILE_B=1\n"
|
||||
"SAVE_FILE_C=2\n"
|
||||
|
|
|
|||
|
|
@ -125,6 +125,28 @@ s32 osEepromProbe(UNUSED OSMesgQueue *mq) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
s32 osEepromLongReadLegacy(UNUSED OSMesgQueue *mq, u8 address, u8 *buffer, int nbytes) {
|
||||
if (gOverrideEeprom != NULL) {
|
||||
memcpy(buffer, gOverrideEeprom + address * 8, nbytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 content[512];
|
||||
s32 ret = -1;
|
||||
|
||||
fs_file_t *fp = fs_open(SAVE_FILENAME_OLD);
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (fs_read(fp, content, 512) == 512) {
|
||||
memcpy(buffer, content + address * 8, nbytes);
|
||||
ret = 0;
|
||||
}
|
||||
fs_close(fp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 osEepromLongRead(UNUSED OSMesgQueue *mq, u8 fileIndex, u8 address, u8 *buffer, int nbytes) {
|
||||
if (gOverrideEeprom != NULL) {
|
||||
memcpy(buffer, gOverrideEeprom + address * 8, nbytes);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue