diff --git a/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj b/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj
index b74fe75f9..81df37e72 100644
--- a/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj
+++ b/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj
@@ -29,26 +29,26 @@
StaticLibrary
false
- v142
+ v143
Unicode
StaticLibrary
false
- v142
+ v143
true
Unicode
StaticLibrary
true
- v142
+ v143
MultiByte
StaticLibrary
false
- v142
+ v143
true
Unicode
diff --git a/libultraship/libultraship/ConfigFile.h b/libultraship/libultraship/ConfigFile.h
index 17e3720f8..b94e22f88 100644
--- a/libultraship/libultraship/ConfigFile.h
+++ b/libultraship/libultraship/ConfigFile.h
@@ -1,3 +1,6 @@
+#ifndef CONFIG_FILE_H
+#define CONFIG_FILE_H
+
#pragma once
#include
@@ -35,3 +38,5 @@ namespace Ship {
mINI::INIFile File;
};
}
+
+#endif
diff --git a/libultraship/libultraship/GameVersions.h b/libultraship/libultraship/GameVersions.h
index a25463bf4..8d3753b21 100644
--- a/libultraship/libultraship/GameVersions.h
+++ b/libultraship/libultraship/GameVersions.h
@@ -1,3 +1,6 @@
+#ifndef GAME_VERSION_H
+#define GAME_VERSION_H
+
#pragma once
#define OOT_NTSC_10 0xEC7011B7
@@ -17,4 +20,6 @@
#define OOT_PAL_GC_MQ_DBG 0x917D18F6
#define OOT_IQUE_TW 0x3D81FB3E
#define OOT_IQUE_CN 0xB1E1E07B
-#define OOT_UNKNOWN 0xFFFFFFFF
\ No newline at end of file
+#define OOT_UNKNOWN 0xFFFFFFFF
+
+#endif
diff --git a/libultraship/libultraship/GlobalCtx2.h b/libultraship/libultraship/GlobalCtx2.h
index a10421ec0..1ed512347 100644
--- a/libultraship/libultraship/GlobalCtx2.h
+++ b/libultraship/libultraship/GlobalCtx2.h
@@ -1,3 +1,6 @@
+#ifndef GLOBAL_CTX_2
+#define GLOBAL_CTX_2
+
#pragma once
#ifdef __cplusplus
@@ -38,4 +41,6 @@ namespace Ship {
std::string PatchesPath;
};
}
-#endif
\ No newline at end of file
+#endif
+
+#endif
diff --git a/libultraship/libultraship/libultraship.vcxproj b/libultraship/libultraship/libultraship.vcxproj
index b3448e7b0..da4ffa3a5 100644
--- a/libultraship/libultraship/libultraship.vcxproj
+++ b/libultraship/libultraship/libultraship.vcxproj
@@ -38,19 +38,19 @@
StaticLibrary
true
- v142
+ v143
Unicode
StaticLibrary
true
- v142
+ v143
Unicode
StaticLibrary
false
- v142
+ v143
true
Unicode
diff --git a/soh/include/functions.h b/soh/include/functions.h
index 4cbc285a3..6d76617f7 100644
--- a/soh/include/functions.h
+++ b/soh/include/functions.h
@@ -2405,6 +2405,7 @@ void Heaps_Free(void);
#ifdef __cplusplus
};
+#undef this
#endif
#endif
diff --git a/soh/include/libc/stddef.h b/soh/include/libc/stddef.h
index c30e392f8..e5fbe2d22 100644
--- a/soh/include/libc/stddef.h
+++ b/soh/include/libc/stddef.h
@@ -1,7 +1,12 @@
#ifndef STDDEF_H
#define STDDEF_H
+#ifndef __cplusplus
#define NULL ((void*)0)
+#else
+#define NULL nullptr
+#endif
+
#if 0
#define size_t unsigned long
#define ssize_t long
diff --git a/soh/soh.vcxproj b/soh/soh.vcxproj
index 418fdd057..c3419d7cb 100644
--- a/soh/soh.vcxproj
+++ b/soh/soh.vcxproj
@@ -29,14 +29,14 @@
Application
true
- v142
+ v143
Unicode
false
Application
false
- v142
+ v143
true
Unicode
false
@@ -44,13 +44,13 @@
Application
true
- v142
+ v143
Unicode
Application
false
- v142
+ v143
true
Unicode
@@ -180,6 +180,7 @@
+
@@ -926,6 +927,7 @@
+
diff --git a/soh/soh.vcxproj.filters b/soh/soh.vcxproj.filters
index a8455a4c8..4f77fdb7c 100644
--- a/soh/soh.vcxproj.filters
+++ b/soh/soh.vcxproj.filters
@@ -2190,6 +2190,9 @@
Source Files\soh\Enhancements\debugger
+
+ Source Files\soh\Enhancements
+
@@ -3740,6 +3743,9 @@
Header Files\soh
+
+ Header Files\soh\Enhancements
+
Header Files\soh\Enhancements\debugger
diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp
index 189230798..91fc0a2a4 100644
--- a/soh/soh/Enhancements/debugconsole.cpp
+++ b/soh/soh/Enhancements/debugconsole.cpp
@@ -1,8 +1,11 @@
#include "debugconsole.h"
#include "../libultraship/SohImGuiImpl.h"
+#include "savestates.h"
+
#include
#include
+
#define Path _Path
#define PATH_HACK
#include
@@ -303,6 +306,17 @@ static bool EntranceHandler(const std::vector& args) {
gSaveContext.nextTransition = 11;
}
+static bool SaveStateHandler(const std::vector& args) {
+ SaveState::Save(0);
+ return CMD_SUCCESS;
+}
+
+static bool LoadStateHandler(const std::vector& args) {
+ SaveState::Load(0);
+ return CMD_SUCCESS;
+}
+
+
#define VARTYPE_INTEGER 0
#define VARTYPE_FLOAT 1
#define VARTYPE_STRING 2
@@ -416,11 +430,10 @@ void DebugConsole_Init(void) {
{ { "slot", ArgumentType::NUMBER }, { "item id", ArgumentType::NUMBER } } });
CMD_REGISTER("entrance",
{ EntranceHandler, "Sends player to the entered entrance (hex)", { { "entrance", ArgumentType::NUMBER } } });
-}
-template bool is_number(const std::string& s) {
- Numeric n;
- return ((std::istringstream(s) >> n >> std::ws).eof());
+ CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." });
+ CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." });
+ DebugConsole_LoadCVars();
}
void DebugConsole_LoadCVars()
diff --git a/soh/soh/Enhancements/savestates.cpp b/soh/soh/Enhancements/savestates.cpp
new file mode 100644
index 000000000..9eca20db1
--- /dev/null
+++ b/soh/soh/Enhancements/savestates.cpp
@@ -0,0 +1,84 @@
+#include "savestates.h"
+
+#include "GameVersions.h"
+#include
+//#include "global.h"
+//#include
+
+std::array gSaveStates;
+
+
+SaveState::SaveState() {
+
+}
+#if 0
+
+SaveState::~SaveState() {
+}
+#endif
+
+void SaveState::Init(void) {
+ gSaveStates[0] = nullptr;
+ gSaveStates[1] = nullptr;
+ gSaveStates[2] = nullptr;
+}
+
+void SaveState::WriteHeader(SaveStateHeader& header) {
+ //OTRGlobals::Instance->context->GetResourceManager()->GetGameVersion();
+ // header.gameVersion = ResourceMgr_GetGameVersion();
+}
+
+extern "C" MtxF* sMatrixStack; // "Matrix_stack"
+extern "C" MtxF* sCurrentMatrix; // "Matrix_now"
+extern "C" LightsBuffer sLightsBuffer;
+
+extern "C" SaveStateReturn SaveState::Save(unsigned int slot) {
+ if (slot > 2) {
+ return SaveStateReturn::FAIL_INVALID_SLOT;
+ }
+ if (gSaveStates[slot] == nullptr) {
+ gSaveStates[slot] = new SaveState;
+ if (gSaveStates[slot] == nullptr) {
+ return SaveStateReturn::FAIL_NO_MEMORY;
+ }
+ }
+
+ gSaveStates[slot]->stateHeader.gameVersion = 0;
+ gSaveStates[slot]->stateHeader.stateVersion = 0;
+
+ memcpy(&gSaveStates[slot]->sysHeapCopy, &gSystemHeap, 1024 * 1024 * 4 /* sizeof(gSystemHeap) */);
+ memcpy(&gSaveStates[slot]->saveContextCopy, &gSaveContext, sizeof(gSaveContext));
+ memcpy(&gSaveStates[slot]->gameInfoCopy, gGameInfo, sizeof(*gGameInfo));
+ // memcpy(&gSaveStates[slot]->audioContextCopy, &gAudioContext, sizeof(AudioContext));
+ memcpy(&gSaveStates[slot]->lightBufferCopy, &sLightsBuffer, sizeof(sLightsBuffer));
+ memcpy(&gSaveStates[slot]->mtxStackCopy, &sMatrixStack, sizeof(MtxF) * 20);
+ memcpy(&gSaveStates[slot]->currentMtxCopy, &sCurrentMatrix, sizeof(MtxF));
+ //TODO RNG seed
+
+ return SaveStateReturn::SUCCESS;
+
+}
+
+SaveStateReturn SaveState::Load(unsigned int slot) {
+ if (slot > 2) {
+ return SaveStateReturn::FAIL_INVALID_SLOT;
+ }
+ if (gSaveStates[slot] == nullptr) {
+ return SaveStateReturn::FAIL_STATE_EMPTY;
+ }
+
+ //gSaveStates[slot]->stateHeader.gameVersion = 0;
+ //gSaveStates[slot]->stateHeader.stateVersion = 0;
+
+ memcpy(&gSystemHeap, &gSaveStates[slot]->sysHeapCopy, 1024 * 1024 * 4);
+ memcpy(&gSaveContext, &gSaveStates[slot]->saveContextCopy, sizeof(gSaveContext));
+ memcpy(gGameInfo, &gSaveStates[slot]->gameInfoCopy, sizeof(*gGameInfo));
+ //memcpy(&gAudioContext, &gSaveStates[slot]->audioContextCopy, sizeof(AudioContext));
+ memcpy(&sLightsBuffer, &gSaveStates[slot]->lightBufferCopy, sizeof(sLightsBuffer));
+ memcpy(&sMatrixStack, &gSaveStates[slot]->mtxStackCopy, sizeof(MtxF) * 20);
+ memcpy(&sCurrentMatrix, &gSaveStates[slot]->currentMtxCopy, sizeof(MtxF));
+ //TODO RNG seed
+
+
+ return SaveStateReturn::SUCCESS;
+}
diff --git a/soh/soh/Enhancements/savestates.h b/soh/soh/Enhancements/savestates.h
new file mode 100644
index 000000000..cfc9f6e31
--- /dev/null
+++ b/soh/soh/Enhancements/savestates.h
@@ -0,0 +1,60 @@
+#ifndef SAVE_STATES_H
+#define SAVE_STATES_H
+#include "z64.h"
+#include "z64save.h"
+
+#include
+#include
+
+// FROM z_lights.c
+// I didn't feel like moving it into a header file.
+#define LIGHTS_BUFFER_SIZE 32
+//#define LIGHTS_BUFFER_SIZE 1024 // Kill me
+
+typedef struct {
+ /* 0x000 */ s32 numOccupied;
+ /* 0x004 */ s32 searchIndex;
+ /* 0x008 */ LightNode buf[LIGHTS_BUFFER_SIZE];
+} LightsBuffer; // size = 0x188
+
+
+enum class SaveStateReturn {
+ SUCCESS,
+ FAIL_INVALID_SLOT,
+ FAIL_NO_MEMORY,
+ FAIL_STATE_EMPTY,
+};
+
+typedef struct SaveStateHeader {
+ uint32_t stateVersion;
+ uint32_t gameVersion;
+} SaveStateHeader;
+
+class SaveState {
+ public:
+ SaveState();
+ ~SaveState() = delete;
+ SaveState& operator=(const SaveState& rhs) = delete;
+ SaveState(const SaveState& rhs) = delete;
+
+ void Init(void);
+ static SaveStateReturn Save(unsigned int slot);
+ static SaveStateReturn Load(unsigned int slot);
+
+ private:
+ static void WriteHeader(SaveStateHeader& header);
+ static void ReadHeader(SaveStateHeader& header);
+ SaveStateHeader stateHeader;
+ unsigned char sysHeapCopy[1024 * 1024 * 4]; //TODO, make a macro for this
+ SaveContext saveContextCopy;
+ GameInfo gameInfoCopy;
+ LightsBuffer lightBufferCopy;
+ //AudioContext audioContextCopy;
+ std::array mtxStackCopy; // always 20 matricies
+ MtxF currentMtxCopy;
+ uint32_t rngSeed;
+
+
+};
+
+#endif
diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h
index 339613b25..a09dcf6ef 100644
--- a/soh/soh/OTRGlobals.h
+++ b/soh/soh/OTRGlobals.h
@@ -1,3 +1,6 @@
+#ifndef OTR_GLOBALS_H
+#define OTR_GLOBALS_H
+
#pragma once
#include "GlobalCtx2.h"
@@ -68,3 +71,5 @@ void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
int Controller_ShouldRumble(size_t i);
#endif
+
+#endif
\ No newline at end of file