Add support for dropping various save formats into the game window (#404)

This commit is contained in:
Garrett Cox
2024-05-23 21:31:50 -05:00
committed by GitHub
parent e5076a1127
commit 904c3641d9
8 changed files with 902 additions and 3 deletions
+60
View File
@@ -54,6 +54,7 @@ CrowdControl* CrowdControl::Instance;
#include "2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h"
#include "2s2h/DeveloperTools/DebugConsole.h"
#include "2s2h/DeveloperTools/DeveloperTools.h"
#include "2s2h/SaveManager/SaveManager.h"
// Resource Types/Factories
#include "resource/type/Array.h"
@@ -402,6 +403,52 @@ extern "C" void OTRExtScanner() {
}
}
std::string SanitizePath(std::string stringValue) {
// Add backslashes.
for (auto i = stringValue.begin();;) {
auto const pos =
std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; });
if (pos == stringValue.end()) {
break;
}
i = std::next(stringValue.insert(pos, '\\'), 2);
}
// Removes others.
stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(),
[](char const c) { return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }),
stringValue.end());
return stringValue;
}
void Ben_ProcessDroppedFiles(std::string filePath) {
SPDLOG_INFO("Processing dropped file: {}", filePath);
bool handled = false;
if (!handled) {
handled = SaveManager_HandleFileDropped(filePath);
}
if (!handled) {
handled = BinarySaveConverter_HandleFileDropped(filePath);
}
// if (!handled) {
// handled = Randomizer_HandleFileDropped(filePath);
// }
// if (!handled) {
// handled = Presets_HandleFileDropped(filePath);
// }
if (!handled) {
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Unsupported file dropped, ignoring");
}
}
extern "C" void InitOTR() {
#if not defined(__SWITCH__) && not defined(__WIIU__)
if (!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("mm.zip", appShortName))) {
@@ -444,6 +491,9 @@ extern "C" void InitOTR() {
// OTRMessage_Init();
OTRAudio_Init();
// OTRExtScanner();
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFileDropped>(Ben_ProcessDroppedFiles);
time_t now = time(NULL);
tm* tm_now = localtime(&now);
if (tm_now->tm_mon == 11 && tm_now->tm_mday >= 24 && tm_now->tm_mday <= 25) {
@@ -614,6 +664,16 @@ extern "C" void Graph_StartFrame() {
}
}
#endif
if (CVarGetInteger(CVAR_NEW_FILE_DROPPED, 0)) {
std::string filePath = SanitizePath(CVarGetString(CVAR_DROPPED_FILE, ""));
if (!filePath.empty()) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnFileDropped>(filePath);
}
CVarClear(CVAR_NEW_FILE_DROPPED);
CVarClear(CVAR_DROPPED_FILE);
}
OTRGlobals::Instance->context->GetWindow()->StartFrame();
}
@@ -2,6 +2,7 @@
#define GAME_INTERACTOR_H
#ifdef __cplusplus
#include <string>
extern "C" {
#endif
#include "z64actor.h"
@@ -241,6 +242,8 @@ class GameInteractor {
}
};
DEFINE_HOOK(OnFileDropped, (std::string path));
DEFINE_HOOK(OnGameStateMainFinish, ());
DEFINE_HOOK(OnGameStateDrawFinish, ());
DEFINE_HOOK(OnGameStateUpdate, ());
File diff suppressed because it is too large Load Diff
+80
View File
@@ -8,6 +8,11 @@
#include "macros.h"
#include "BenJsonConversions.hpp"
extern "C" {
#include "src/overlays/gamestates/ovl_file_choose/z_file_select.h"
extern FileSelectState* gFileSelectState;
}
// This entire thing is temporary until we have a more robust save system that
// supports backwards compatability, migrations, threaded saving, save sections, etc.
typedef enum FlashSlotFile {
@@ -99,6 +104,79 @@ int SaveManager_ReadSaveFile(std::filesystem::path fileName, nlohmann::json& j)
return 0;
}
int SaveManager_GetOpenFileSlot() {
std::string fileName = "save_0.sav";
if (!std::filesystem::exists(savesFolderPath / fileName)) {
return 0;
}
fileName = "save_2.sav";
if (!std::filesystem::exists(savesFolderPath / fileName)) {
return 2;
}
return -1;
}
bool SaveManager_HandleFileDropped(std::string filePath) {
try {
std::ifstream fileStream(filePath);
if (!fileStream.is_open()) {
return false;
}
// Check if first byte is "{"
if (fileStream.peek() != '{') {
return false;
}
nlohmann::json j;
try {
fileStream >> j;
} catch (nlohmann::json::parse_error& e) {
SPDLOG_ERROR("Failed to parse JSON: {}", e.what());
return false;
}
if (!j.contains("type") || j["type"] != "2S2H_SAVE") {
SPDLOG_ERROR("Invalid save file type");
return false;
}
int saveSlot = SaveManager_GetOpenFileSlot();
if (saveSlot == -1) {
SPDLOG_ERROR("No save slot available");
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "No save slot available");
return true;
}
std::string fileName = "save_" + std::to_string(saveSlot) + ".sav";
SaveManager_WriteSaveFile(fileName, j);
if (gFileSelectState != NULL) {
func_801457CC(&gFileSelectState->state, &gFileSelectState->sramCtx);
if (gFileSelectState->menuMode == FS_MENU_MODE_CONFIG && gFileSelectState->configMode == CM_MAIN_MENU) {
gFileSelectState->configMode = CM_FADE_IN_START;
}
}
return true;
} catch (std::exception& e) {
SPDLOG_ERROR("Failed to load file: {}", e.what());
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load file");
return false;
} catch (...) {
SPDLOG_ERROR("Failed to load file");
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load file");
return false;
}
}
extern "C" void SaveManager_SysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u32 pageCount) {
FlashSlotFile flashSlotFile = FLASH_SLOT_FILE_UNAVAILABLE;
bool isBackup = false;
@@ -132,6 +210,7 @@ extern "C" void SaveManager_SysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u
j["save"] = save;
j["version"] = CURRENT_SAVE_VERSION;
j["type"] = "2S2H_SAVE";
SaveManager_WriteSaveFile(fileName, j);
} else {
@@ -156,6 +235,7 @@ extern "C" void SaveManager_SysFlashrom_WriteData(u8* saveBuffer, u32 pageNum, u
nlohmann::json j = saveContext;
j["version"] = CURRENT_SAVE_VERSION;
j["type"] = "2S2H_SAVE";
SaveManager_WriteSaveFile(fileName, j);
} else {
+6 -1
View File
@@ -4,7 +4,12 @@
#include <libultraship/libultraship.h>
#ifndef __cplusplus
#ifdef __cplusplus
bool SaveManager_HandleFileDropped(std::string filePath);
bool BinarySaveConverter_HandleFileDropped(std::string filePath);
int SaveManager_GetOpenFileSlot();
void SaveManager_WriteSaveFile(std::filesystem::path fileName, nlohmann::json j);
#else
void SaveManager_SysFlashrom_WriteData(u8* addr, u32 pageNum, u32 pageCount);
s32 SaveManager_SysFlashrom_ReadData(void* addr, u32 pageNum, u32 pageCount);
#endif
+2 -1
View File
@@ -4,7 +4,8 @@
#include "libc/stdarg.h"
#include <string.h>
#ifndef __GNUC__
// 2S2H This file might just outright get removed soon. Ifdeffing for now
#if 0
//void bcopy(void* __src, void* __dest, int __n);
//int bcmp(void* __s1, void* __s2, int __n);
//void bzero(void* begin, int length);
@@ -21,6 +21,8 @@ f32 D_808144F14 = 8.0f;
f32 D_808144F18 = 100.0f;
s32 D_808144F1C = 0;
FileSelectState* gFileSelectState = NULL;
static Gfx sScreenFillSetupDL[] = {
gsDPPipeSync(),
gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN |
@@ -2533,11 +2535,13 @@ void FileSelect_InitContext(GameState* thisx) {
void FileSelect_Destroy(GameState* this) {
ShrinkWindow_Destroy();
gFileSelectState = NULL;
}
void FileSelect_Init(GameState* thisx) {
s32 pad;
FileSelectState* this = (FileSelectState*)thisx;
gFileSelectState = this;
size_t size;
GameState_SetFramerateDivisor(&this->state, 1);