* copy n64 pal 10 doing this so i can check diffs i make * transfer german->jp icon item * overlays, message data, icon item jpn, audio, code todo: title_static, gameplay keep * add kanji and fix title cards * title static * spell folder correctly * boss title cards, do action, icon item, item name, map name * headers for jpn stuff * gameplay_keep * Scenes, audio, jp text extraction, rom support, overlay fixes, sheik & darunia todo: test & disable darunia fix cvar for ntsc * msgptr init fix * icon item offsets * comment out title cards until zapd can fix itself (we extract these in a different file anyway) * compile and font implemented to get past title screen * file select * message, kaleido and everything else but rando * uintptr_t * rando and custom messages working! * ntsc-j 1.0 support * n64 logo? * copy ntsc 10 to 11 * ntsc 11 extraction * change title version names * copy ntsc 11 to 12 * ntsc 12 extraction * clean up some todos * re checkout submodules post merge * fix US filename * support cross-version filenames * add new versions to non-mq list * use correct message table init * Fix ntsc nes message table overriding pal nes message table * actual fix, allows extraction * fix file name using wrong font of file being hovered over * Fix barinade crash * re-add pal * better jabu fix and revert LUS * fix gerudo title cards * better better owl select * more owl fixes * build * fix some name decode issues * Switch Language Mid Text * Fix PAL displaying for JP filenames * Fix AskToEquip Crash * Disable Credits Timing Fix on NTSC * Fix JP Text positioning * basic language switching (BIG todo: file select, title screen) * Title Screen Hopefully working * add ntsc to linux appimage stuff, TODO: add .v64/.n64 support * Update OTRExporter * Fix pause to decide offset * Fix bomb item name crash * fix fire arrows and PoH * builds * update asset changes and fix menu language changing * fix name decode * Fix crashes and add rando/boss rush select stuff * Revive debug feature by setting language cvar too * Fix ocarina text speed softlock, and update jp text speed changes * Merge remote-tracking branch 'upstream/develop' into NTSC * Fix options menu and let pal use japanese fully * Resolve some suggestions * match up gTextSpeed changes to english (still broken!) * Fix text speed crash * Set default filename language on save init funcs * bump otrexporter * Display same correct info for n64 ntsc-j and ntsc-u * quicktext more closely aligned with decomp * linux appimage v64/n64 checksums * bump zapd * Credits Fix Tooltip Adjusted * update supported hashes json * update shasums to include JP n64
220 lines
7.2 KiB
C++
220 lines
7.2 KiB
C++
#pragma once
|
|
|
|
#include <libultraship/libultra/gbi.h>
|
|
#include "z64save.h"
|
|
|
|
#define SECTION_PARENT_NONE -1
|
|
typedef struct {
|
|
u8 valid;
|
|
u16 deaths;
|
|
u8 playerName[8];
|
|
u16 healthCapacity;
|
|
u32 questItems;
|
|
s8 defense;
|
|
u16 health;
|
|
u32 requiresMasterQuest;
|
|
u32 requiresOriginal;
|
|
u8 seedHash[5];
|
|
u8 randoSave;
|
|
char buildVersion[50];
|
|
s16 buildVersionMajor;
|
|
s16 buildVersionMinor;
|
|
s16 buildVersionPatch;
|
|
|
|
u8 inventoryItems[24];
|
|
u16 equipment;
|
|
u32 upgrades;
|
|
u8 isMagicAcquired;
|
|
u8 isDoubleMagicAcquired;
|
|
s16 rupees;
|
|
s16 gsTokens;
|
|
u8 isDoubleDefenseAcquired;
|
|
s32 filenameLanguage;
|
|
s32 gregFound;
|
|
s32 hasWallet;
|
|
} SaveFileMetaInfo;
|
|
|
|
typedef enum {
|
|
/* 0 */ NAME_LANGUAGE_PAL,
|
|
/* 1 */ NAME_LANGUAGE_NTSC_JPN,
|
|
/* 2 */ NAME_LANGUAGE_NTSC_ENG,
|
|
} FilenameLanguage;
|
|
|
|
#ifdef __cplusplus
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <functional>
|
|
#include <vector>
|
|
#include <filesystem>
|
|
|
|
#define BS_THREAD_POOL_ENABLE_PRIORITY
|
|
#define BS_THREAD_POOL_ENABLE_PAUSE
|
|
#include <BS_thread_pool.hpp>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
class SaveManager {
|
|
public:
|
|
static SaveManager* Instance;
|
|
|
|
static void WriteSaveFile(const std::filesystem::path& savePath, uintptr_t addr, void* dramAddr, size_t size);
|
|
static void ReadSaveFile(std::filesystem::path savePath, uintptr_t addr, void* dramAddr, size_t size);
|
|
|
|
using InitFunc = void (*)(bool isDebug);
|
|
using LoadFunc = void (*)();
|
|
using SaveFunc = void (*)(SaveContext* saveContext, int sectionID, bool fullSave);
|
|
using PostFunc = void (*)(int version);
|
|
|
|
typedef struct {
|
|
std::string name;
|
|
int version;
|
|
SaveManager::SaveFunc func;
|
|
bool saveWithBase;
|
|
int parentSection;
|
|
} SaveFuncInfo;
|
|
|
|
SaveManager();
|
|
|
|
void Init();
|
|
void InitFile(bool isDebug);
|
|
void SaveFile(int fileNum);
|
|
void SaveSection(int fileNum, int sectionID, bool threaded);
|
|
int GetSaveSectionID(std::string& name);
|
|
void SaveGlobal();
|
|
void LoadFile(int fileNum);
|
|
bool SaveFile_Exist(int fileNum);
|
|
void ThreadPoolWait();
|
|
|
|
// Adds a function that is called when we are intializing a save, including when we are loading a save.
|
|
void AddInitFunction(InitFunc func);
|
|
|
|
// Adds a function to handling loading a section
|
|
void AddLoadFunction(const std::string& name, int version, LoadFunc func);
|
|
|
|
// Adds a function that is called when saving. This should only be called once for each function, the version is
|
|
// filled in automatically.
|
|
int AddSaveFunction(const std::string& name, int version, SaveFunc func, bool saveWithBase, int parentSection);
|
|
|
|
// Adds a function to be called after loading is complete. This is to handle any cleanup required from loading old
|
|
// versions.
|
|
void AddPostFunction(const std::string& name, PostFunc func);
|
|
|
|
void CopyZeldaFile(int from, int to);
|
|
void DeleteZeldaFile(int fileNum);
|
|
bool IsRandoFile();
|
|
|
|
// Use a name of "" to save to an array. You must be in a SaveArray callback.
|
|
template <typename T> void SaveData(const std::string& name, const T& data) {
|
|
if (name == "") {
|
|
assert((*currentJsonContext).is_array());
|
|
(*currentJsonContext).push_back(data);
|
|
} else {
|
|
(*currentJsonContext)[name.c_str()] = data;
|
|
}
|
|
}
|
|
|
|
// In the SaveArrayFunc func, the name must be "" to save to the array.
|
|
using SaveArrayFunc = std::function<void(size_t)>;
|
|
void SaveArray(const std::string& name, const size_t size, SaveArrayFunc func);
|
|
|
|
using SaveStructFunc = std::function<void()>;
|
|
void SaveStruct(const std::string& name, SaveStructFunc func);
|
|
|
|
// Use a name of "" to load from an array. You must be in a LoadArray callback.
|
|
template <typename T> void LoadData(const std::string& name, T& data, const T& defaultValue = T{}) {
|
|
if (name == "") {
|
|
if (currentJsonArrayContext == currentJsonContext->end()) {
|
|
// This array member is past the data in the json file. Therefore, default construct it
|
|
data = defaultValue;
|
|
} else {
|
|
currentJsonArrayContext.value().get_to(data);
|
|
}
|
|
} else if (!currentJsonContext->contains(name.c_str())) {
|
|
data = defaultValue;
|
|
} else {
|
|
(*currentJsonContext)[name.c_str()].get_to(data);
|
|
}
|
|
}
|
|
|
|
void LoadCharArray(const std::string& name, char* destination, size_t size);
|
|
|
|
// In the LoadArrayFunc func, the name must be "" to load from the array.
|
|
using LoadArrayFunc = std::function<void(size_t)>;
|
|
void LoadArray(const std::string& name, const size_t size, LoadArrayFunc func);
|
|
|
|
using LoadStructFunc = std::function<void()>;
|
|
void LoadStruct(const std::string& name, LoadStructFunc func);
|
|
|
|
static const int MaxFiles = 3;
|
|
std::array<SaveFileMetaInfo, MaxFiles> fileMetaInfo;
|
|
|
|
private:
|
|
std::filesystem::path GetFileName(int fileNum);
|
|
std::filesystem::path GetFileTempName(int fileNum);
|
|
nlohmann::json saveBlock;
|
|
|
|
void ConvertFromUnversioned();
|
|
void CreateDefaultGlobal();
|
|
|
|
void SaveFileThreaded(int fileNum, SaveContext* saveContext, int sectionID);
|
|
|
|
void InitMeta(int slotNum);
|
|
static void InitFileImpl(bool isDebug);
|
|
static void InitFileNormal();
|
|
static void InitFileDebug();
|
|
static void InitFileMaxed();
|
|
|
|
static void LoadRandomizerVersion1();
|
|
static void LoadRandomizerVersion2();
|
|
static void LoadRandomizerVersion3();
|
|
static void LoadTrackerData();
|
|
static void SaveTrackerData(SaveContext* saveContext, int sectionID, bool fullSave);
|
|
static void SaveRandomizer(SaveContext* saveContext, int sectionID, bool fullSave);
|
|
|
|
static void LoadBaseVersion1();
|
|
static void LoadBaseVersion2();
|
|
static void LoadBaseVersion3();
|
|
static void LoadBaseVersion4();
|
|
static void SaveBase(SaveContext* saveContext, int sectionID, bool fullSave);
|
|
|
|
std::vector<InitFunc> initFuncs;
|
|
|
|
using SectionLoadHandler = std::map<int, LoadFunc>;
|
|
std::map<std::string, SectionLoadHandler> sectionLoadHandlers;
|
|
|
|
int sectionIndex = SECTION_ID_MAX;
|
|
std::map<std::string, int> coreSectionIDsByName;
|
|
std::map<int, SaveFuncInfo> sectionSaveHandlers;
|
|
std::map<std::string, int> sectionRegistry;
|
|
|
|
std::map<std::string, PostFunc> postHandlers;
|
|
|
|
nlohmann::json* currentJsonContext = nullptr;
|
|
nlohmann::json::iterator currentJsonArrayContext;
|
|
std::shared_ptr<BS::thread_pool> smThreadPool;
|
|
std::mutex saveMtx;
|
|
};
|
|
|
|
#else
|
|
|
|
// TODO feature parity to the C++ interface. We need Save_AddInitFunction and Save_AddPostFunction at least
|
|
|
|
typedef void (*Save_LoadFunc)(void);
|
|
typedef void (*Save_SaveFunc)(const SaveContext* saveContext, int sectionID);
|
|
|
|
void Save_Init(void);
|
|
void Save_InitFile(int isDebug);
|
|
void Save_SaveFile(void);
|
|
void Save_SaveSection(int sectionID);
|
|
void Save_SaveGlobal(void);
|
|
void Save_LoadGlobal(void);
|
|
void Save_AddLoadFunction(char* name, int version, Save_LoadFunc func);
|
|
void Save_AddSaveFunction(char* name, int version, Save_SaveFunc func, bool saveWithBase, int parentSection);
|
|
SaveFileMetaInfo* Save_GetSaveMetaInfo(int fileNum);
|
|
void Save_CopyFile(int from, int to);
|
|
void Save_DeleteFile(int fileNum);
|
|
bool Save_Exist(int fileNum);
|
|
#endif
|