mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-22 06:13:45 -07:00
IT WORKS BUT WOW ITS AWFUL LOOKING
This commit is contained in:
parent
354dc78425
commit
c289791df1
10 changed files with 238 additions and 49 deletions
|
@ -30,6 +30,9 @@
|
||||||
#include "ichain.h"
|
#include "ichain.h"
|
||||||
#include "regs.h"
|
#include "regs.h"
|
||||||
|
|
||||||
|
#define AUDIO_HEAP_SIZE 0x38000
|
||||||
|
#define SYSTEM_HEAP_SIZE (1024 * 1024 * 4)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
namespace Ship
|
namespace Ship
|
||||||
{
|
{
|
||||||
|
|
|
@ -932,6 +932,7 @@
|
||||||
<ClInclude Include="soh\Enhancements\debugger\debugSaveEditor.h" />
|
<ClInclude Include="soh\Enhancements\debugger\debugSaveEditor.h" />
|
||||||
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h" />
|
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h" />
|
||||||
<ClInclude Include="soh\gameconsole.h" />
|
<ClInclude Include="soh\gameconsole.h" />
|
||||||
|
<ClInclude Include="soh\OTRAudio.h" />
|
||||||
<ClInclude Include="soh\OTRGlobals.h" />
|
<ClInclude Include="soh\OTRGlobals.h" />
|
||||||
<ClInclude Include="soh\util.h" />
|
<ClInclude Include="soh\util.h" />
|
||||||
<ClInclude Include="src\overlays\actors\ovl_Arms_Hook\z_arms_hook.h" />
|
<ClInclude Include="src\overlays\actors\ovl_Arms_Hook\z_arms_hook.h" />
|
||||||
|
@ -1411,4 +1412,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -3751,6 +3751,8 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h">
|
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h">
|
||||||
<Filter>Header Files\soh\Enhancements\debugger</Filter>
|
<Filter>Header Files\soh\Enhancements\debugger</Filter>
|
||||||
|
<ClInclude Include="soh\OTRAudio.h">
|
||||||
|
<Filter>Source Files\soh</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -307,8 +307,8 @@ static bool EntranceHandler(const std::vector<std::string>& args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SaveStateHandler(const std::vector<std::string>& args) {
|
static bool SaveStateHandler(const std::vector<std::string>& args) {
|
||||||
const SaveStateReturn rtn = SaveState::Save(gCurrentSlot);
|
const SaveStateReturn rtn = SaveState::RequestSaveState(gCurrentSlot);
|
||||||
|
|
||||||
switch (rtn) {
|
switch (rtn) {
|
||||||
case SaveStateReturn::SUCCESS:
|
case SaveStateReturn::SUCCESS:
|
||||||
INFO("[SOH] Saved state to slot %u", gCurrentSlot);
|
INFO("[SOH] Saved state to slot %u", gCurrentSlot);
|
||||||
|
@ -316,14 +316,11 @@ static bool SaveStateHandler(const std::vector<std::string>& args) {
|
||||||
case SaveStateReturn::FAIL_INVALID_SLOT:
|
case SaveStateReturn::FAIL_INVALID_SLOT:
|
||||||
ERROR("[SOH] Invalid State Slot Number (%u)", gCurrentSlot);
|
ERROR("[SOH] Invalid State Slot Number (%u)", gCurrentSlot);
|
||||||
return CMD_FAILED;
|
return CMD_FAILED;
|
||||||
case SaveStateReturn::FAIL_NO_MEMORY:
|
|
||||||
ERROR("[SOH] No Memory to save state to slot %u", gCurrentSlot);
|
|
||||||
return CMD_FAILED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool LoadStateHandler(const std::vector<std::string>& args) {
|
static bool LoadStateHandler(const std::vector<std::string>& args) {
|
||||||
const SaveStateReturn rtn = SaveState::Load(gCurrentSlot);
|
const SaveStateReturn rtn = SaveState::RequestLoadState(gCurrentSlot);
|
||||||
|
|
||||||
switch (rtn) {
|
switch (rtn) {
|
||||||
case SaveStateReturn::SUCCESS:
|
case SaveStateReturn::SUCCESS:
|
||||||
|
|
|
@ -4,15 +4,21 @@
|
||||||
#include <variables.h>
|
#include <variables.h>
|
||||||
|
|
||||||
#include <cstdio> // std::sprintf
|
#include <cstdio> // std::sprintf
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "soh/OTRAudio.h"
|
||||||
|
//#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
//#include "global.h"
|
//#include "global.h"
|
||||||
//#include <soh/OTRGlobals.h>
|
//#include <soh/OTRGlobals.h>
|
||||||
|
|
||||||
|
|
||||||
//TODO is there a better way?
|
//TODO is there a better way?
|
||||||
unsigned int gCurrentSlot = 0;
|
unsigned int gCurrentSlot = 0;
|
||||||
|
|
||||||
static std::array<SaveState*, SaveState::SAVE_SLOT_MAX + 1> gSaveStates;
|
static std::array<SaveStateInfo*, SaveState::SAVE_SLOT_MAX + 1> gSaveStates;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SaveState::SaveState(){}
|
SaveState::SaveState(){}
|
||||||
SaveState::~SaveState() {}
|
SaveState::~SaveState() {}
|
||||||
|
@ -77,7 +83,7 @@ SaveStateReturn SaveState::Import(const unsigned int slot) {
|
||||||
if (inFile == nullptr) {
|
if (inFile == nullptr) {
|
||||||
return SaveStateReturn::FAIL_FILE_NOT_OPENED;
|
return SaveStateReturn::FAIL_FILE_NOT_OPENED;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fseek(inFile, 0, SEEK_END);
|
std::fseek(inFile, 0, SEEK_END);
|
||||||
const size_t inFileSize = std::ftell(inFile);
|
const size_t inFileSize = std::ftell(inFile);
|
||||||
|
|
||||||
|
@ -86,7 +92,7 @@ SaveStateReturn SaveState::Import(const unsigned int slot) {
|
||||||
return SaveStateReturn::FAIL_INVALID_SIZE;
|
return SaveStateReturn::FAIL_INVALID_SIZE;
|
||||||
}
|
}
|
||||||
std::fseek(inFile, 0, SEEK_SET);
|
std::fseek(inFile, 0, SEEK_SET);
|
||||||
|
|
||||||
SaveStateHeader tempHeader;
|
SaveStateHeader tempHeader;
|
||||||
std::fread(&tempHeader, sizeof(SaveStateHeader), 1, inFile);
|
std::fread(&tempHeader, sizeof(SaveStateHeader), 1, inFile);
|
||||||
|
|
||||||
|
@ -96,7 +102,7 @@ SaveStateReturn SaveState::Import(const unsigned int slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gSaveStates[slot] == nullptr) {
|
if (gSaveStates[slot] == nullptr) {
|
||||||
gSaveStates[slot] = new SaveState;
|
gSaveStates[slot] = new SaveStateInfo;
|
||||||
if (gSaveStates[slot] == nullptr) {
|
if (gSaveStates[slot] == nullptr) {
|
||||||
fclose(inFile);
|
fclose(inFile);
|
||||||
return SaveStateReturn::FAIL_NO_MEMORY;
|
return SaveStateReturn::FAIL_NO_MEMORY;
|
||||||
|
@ -104,7 +110,7 @@ SaveStateReturn SaveState::Import(const unsigned int slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fseek(inFile, 0, SEEK_SET);
|
std::fseek(inFile, 0, SEEK_SET);
|
||||||
std::fread(gSaveStates[slot], sizeof(SaveState), 1, inFile);
|
std::fread(gSaveStates[slot], sizeof(SaveStateInfo), 1, inFile);
|
||||||
std::fclose(inFile);
|
std::fclose(inFile);
|
||||||
//TODO version system
|
//TODO version system
|
||||||
//if (gSaveStates[slot]->stateHeader.stateVersion != 0) {
|
//if (gSaveStates[slot]->stateHeader.stateVersion != 0) {
|
||||||
|
@ -115,39 +121,139 @@ SaveStateReturn SaveState::Import(const unsigned int slot) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SaveState::BackupSeqScriptState(SaveStateInfo* state) {
|
||||||
|
for (unsigned int i = 0; i < 4; i++) {
|
||||||
|
state->seqScriptStateCopy[i].value = gAudioContext.seqPlayers[i].scriptState.value;
|
||||||
|
|
||||||
|
state->seqScriptStateCopy[i].remLoopIters[0] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[0];
|
||||||
|
state->seqScriptStateCopy[i].remLoopIters[1] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[1];
|
||||||
|
state->seqScriptStateCopy[i].remLoopIters[2] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[2];
|
||||||
|
state->seqScriptStateCopy[i].remLoopIters[3] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[3];
|
||||||
|
|
||||||
|
state->seqScriptStateCopy[i].depth = gAudioContext.seqPlayers[i].scriptState.depth;
|
||||||
|
|
||||||
|
state->seqScriptStateCopy[i].pc = (u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.pc - (uintptr_t)gAudioHeap);
|
||||||
|
|
||||||
|
state->seqScriptStateCopy[i].stack[0] =
|
||||||
|
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[0] - (uintptr_t)gAudioHeap);
|
||||||
|
state->seqScriptStateCopy[i].stack[1] =
|
||||||
|
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[1] - (uintptr_t)gAudioHeap);
|
||||||
|
state->seqScriptStateCopy[i].stack[2] =
|
||||||
|
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[2] - (uintptr_t)gAudioHeap);
|
||||||
|
state->seqScriptStateCopy[i].stack[3] =
|
||||||
|
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[3] - (uintptr_t)gAudioHeap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveState::LoadSeqScriptState(SaveStateInfo* state) {
|
||||||
|
for (unsigned int i = 0; i < 4; i++) {
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.value = state->seqScriptStateCopy[i].value;
|
||||||
|
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.remLoopIters[0] = state->seqScriptStateCopy[i].remLoopIters[0];
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.remLoopIters[1] = state->seqScriptStateCopy[i].remLoopIters[1];
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.remLoopIters[2] = state->seqScriptStateCopy[i].remLoopIters[2];
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.remLoopIters[3] = state->seqScriptStateCopy[i].remLoopIters[3];
|
||||||
|
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.depth = state->seqScriptStateCopy[i].depth;
|
||||||
|
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.pc =
|
||||||
|
(u8*)((uintptr_t)state->seqScriptStateCopy[i].pc + (uintptr_t)gAudioHeap);
|
||||||
|
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.stack[0] =
|
||||||
|
(u8*)((uintptr_t)state->seqScriptStateCopy[i].stack[0] + (uintptr_t)gAudioHeap);
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.stack[1] =
|
||||||
|
(u8*)((uintptr_t)state->seqScriptStateCopy[i].stack[1] + (uintptr_t)gAudioHeap);
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.stack[2] =
|
||||||
|
(u8*)((uintptr_t)state->seqScriptStateCopy[i].stack[2] + (uintptr_t)gAudioHeap);
|
||||||
|
gAudioContext.seqPlayers[i].scriptState.stack[3] =
|
||||||
|
(u8*)((uintptr_t)state->seqScriptStateCopy[i].stack[3] + (uintptr_t)gAudioHeap);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" MtxF* sMatrixStack;
|
extern "C" MtxF* sMatrixStack;
|
||||||
extern "C" MtxF* sCurrentMatrix;
|
extern "C" MtxF* sCurrentMatrix;
|
||||||
extern "C" LightsBuffer sLightsBuffer;
|
extern "C" LightsBuffer sLightsBuffer;
|
||||||
extern "C" s16 sWarpTimerTarget;
|
extern "C" s16 sWarpTimerTarget;
|
||||||
|
|
||||||
extern "C" SaveStateReturn SaveState::Save(const unsigned int slot) {
|
std::queue<SaveStateRequest> SaveState::requests;
|
||||||
|
|
||||||
|
extern "C" void ProcessSaveStateRequests(void) {
|
||||||
|
SaveState::ProcessSaveStateRequestsImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveState::ProcessSaveStateRequestsImpl(void) {
|
||||||
|
while (!requests.empty()) {
|
||||||
|
if (requests.front().type == RequestType::SAVE) {
|
||||||
|
SaveState::Save(requests.front().slot);
|
||||||
|
} else if (requests.front().type == RequestType::LOAD) {
|
||||||
|
SaveState::Load(requests.front().slot);
|
||||||
|
} else {
|
||||||
|
// SPDLOG_ERROR("Invalid Request type for SaveState: {}", requests.front().type);
|
||||||
|
}
|
||||||
|
requests.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveStateReturn SaveState::RequestSaveState(const unsigned int slot) {
|
||||||
if (slot > SaveState::SAVE_SLOT_MAX) {
|
if (slot > SaveState::SAVE_SLOT_MAX) {
|
||||||
return SaveStateReturn::FAIL_INVALID_SLOT;
|
return SaveStateReturn::FAIL_INVALID_SLOT;
|
||||||
}
|
}
|
||||||
if (gSaveStates[slot] == nullptr) {
|
if (gSaveStates[slot] == nullptr) {
|
||||||
gSaveStates[slot] = new SaveState;
|
gSaveStates[slot] = new SaveStateInfo;
|
||||||
if (gSaveStates[slot] == nullptr) {
|
if (gSaveStates[slot] == nullptr) {
|
||||||
return SaveStateReturn::FAIL_NO_MEMORY;
|
return SaveStateReturn::FAIL_NO_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SaveState::requests.push({ slot, RequestType::SAVE });
|
||||||
|
return SaveStateReturn::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void SaveState::Save(const unsigned int slot) {
|
||||||
|
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||||
|
|
||||||
|
|
||||||
SaveState::SetHeader(gSaveStates[slot]->stateHeader);
|
SaveState::SetHeader(gSaveStates[slot]->stateHeader);
|
||||||
|
|
||||||
memcpy(&gSaveStates[slot]->sysHeapCopy, &gSystemHeap, 1024 * 1024 * 4 /* sizeof(gSystemHeap) */);
|
memcpy(&gSaveStates[slot]->sysHeapCopy, gSystemHeap, SYSTEM_HEAP_SIZE /* sizeof(gSystemHeap) */);
|
||||||
|
memcpy(&gSaveStates[slot]->audioHeapCopy, gAudioHeap, AUDIO_HEAP_SIZE /* sizeof(gAudioContext) */);
|
||||||
|
|
||||||
|
memcpy(&gSaveStates[slot]->audioContextCopy, &gAudioContext, sizeof(AudioContext));
|
||||||
|
memcpy(&gSaveStates[slot]->unk_D_8016E750Copy, D_8016E750, sizeof(gSaveStates[slot]->unk_D_8016E750Copy));
|
||||||
|
BackupSeqScriptState(gSaveStates[slot]);
|
||||||
|
|
||||||
|
memcpy(gSaveStates[slot]->gActiveSoundsCopy, gActiveSounds, sizeof(gActiveSounds));
|
||||||
|
memcpy(&gSaveStates[slot]->gSoundBankMutedCopy, gSoundBankMuted, sizeof(gSaveStates[0]->gSoundBankMutedCopy));
|
||||||
|
gSaveStates[slot]->D_801333F0_copy = D_801333F0;
|
||||||
|
gSaveStates[slot]->gAudioSfxSwapOff_copy = gAudioSfxSwapOff;
|
||||||
|
|
||||||
|
memcpy(&gSaveStates[slot]->gAudioSfxSwapSource_copy, gAudioSfxSwapSource,
|
||||||
|
sizeof(gSaveStates[slot]->gAudioSfxSwapSource_copy));
|
||||||
|
memcpy(&gSaveStates[slot]->gAudioSfxSwapTarget_copy, gAudioSfxSwapTarget,
|
||||||
|
sizeof(gSaveStates[slot]->gAudioSfxSwapTarget_copy));
|
||||||
|
memcpy(&gSaveStates[slot]->gAudioSfxSwapMode_copy, gAudioSfxSwapMode,
|
||||||
|
sizeof(&gSaveStates[slot]->gAudioSfxSwapMode_copy));
|
||||||
|
|
||||||
|
gSaveStates[slot]->D_801755D0_copy = D_801755D0;
|
||||||
|
|
||||||
|
|
||||||
|
// gSaveStates[slot]->seqIdCopy[0] = gAudioContext.seqPlayers[0].seqId;
|
||||||
|
// gSaveStates[slot]->seqIdCopy[1] = gAudioContext.seqPlayers[1].seqId;
|
||||||
|
// gSaveStates[slot]->seqIdCopy[2] = gAudioContext.seqPlayers[2].seqId;
|
||||||
|
// gSaveStates[slot]->seqIdCopy[3] = gAudioContext.seqPlayers[3].seqId;
|
||||||
|
|
||||||
|
|
||||||
memcpy(&gSaveStates[slot]->saveContextCopy, &gSaveContext, sizeof(gSaveContext));
|
memcpy(&gSaveStates[slot]->saveContextCopy, &gSaveContext, sizeof(gSaveContext));
|
||||||
memcpy(&gSaveStates[slot]->gameInfoCopy, gGameInfo, sizeof(*gGameInfo));
|
memcpy(&gSaveStates[slot]->gameInfoCopy, gGameInfo, sizeof(*gGameInfo));
|
||||||
// memcpy(&gSaveStates[slot]->audioContextCopy, &gAudioContext, sizeof(AudioContext));
|
|
||||||
memcpy(&gSaveStates[slot]->lightBufferCopy, &sLightsBuffer, sizeof(sLightsBuffer));
|
memcpy(&gSaveStates[slot]->lightBufferCopy, &sLightsBuffer, sizeof(sLightsBuffer));
|
||||||
memcpy(&gSaveStates[slot]->mtxStackCopy, &sMatrixStack, sizeof(MtxF) * 20);
|
memcpy(&gSaveStates[slot]->mtxStackCopy, &sMatrixStack, sizeof(MtxF) * 20);
|
||||||
memcpy(&gSaveStates[slot]->currentMtxCopy, &sCurrentMatrix, sizeof(MtxF));
|
memcpy(&gSaveStates[slot]->currentMtxCopy, &sCurrentMatrix, sizeof(MtxF));
|
||||||
gSaveStates[slot]->blueWarpTimerCopy = sWarpTimerTarget;
|
gSaveStates[slot]->blueWarpTimerCopy = sWarpTimerTarget;
|
||||||
//TODO RNG seed
|
|
||||||
|
|
||||||
return SaveStateReturn::SUCCESS;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveStateReturn SaveState::Load(const unsigned int slot) {
|
SaveStateReturn SaveState::RequestLoadState(const unsigned int slot) {
|
||||||
if (slot > SaveState::SAVE_SLOT_MAX) {
|
if (slot > SaveState::SAVE_SLOT_MAX) {
|
||||||
return SaveStateReturn::FAIL_INVALID_SLOT;
|
return SaveStateReturn::FAIL_INVALID_SLOT;
|
||||||
}
|
}
|
||||||
|
@ -155,19 +261,50 @@ SaveStateReturn SaveState::Load(const unsigned int slot) {
|
||||||
return SaveStateReturn::FAIL_STATE_EMPTY;
|
return SaveStateReturn::FAIL_STATE_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SaveState::requests.push({ slot, RequestType::LOAD });
|
||||||
|
return SaveStateReturn::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveState::Load(const unsigned int slot) {
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//gSaveStates[slot]->stateHeader.gameVersion = 0;
|
//gSaveStates[slot]->stateHeader.gameVersion = 0;
|
||||||
//gSaveStates[slot]->stateHeader.stateVersion = 0;
|
//gSaveStates[slot]->stateHeader.stateVersion = 0;
|
||||||
|
|
||||||
memcpy(&gSystemHeap, &gSaveStates[slot]->sysHeapCopy, 1024 * 1024 * 4);
|
memcpy(gSystemHeap, &gSaveStates[slot]->sysHeapCopy, SYSTEM_HEAP_SIZE);
|
||||||
|
memcpy(gAudioHeap, &gSaveStates[slot]->audioHeapCopy, AUDIO_HEAP_SIZE);
|
||||||
|
|
||||||
|
memcpy(&gAudioContext, &gSaveStates[slot]->audioContextCopy, sizeof(AudioContext));
|
||||||
|
memcpy(D_8016E750, &gSaveStates[slot]->unk_D_8016E750Copy, sizeof(gSaveStates[slot]->unk_D_8016E750Copy));
|
||||||
|
LoadSeqScriptState(gSaveStates[slot]);
|
||||||
|
//gAudioContext.seqPlayers[0].seqId = gSaveStates[slot]->seqIdCopy[0];
|
||||||
|
//gAudioContext.seqPlayers[1].seqId = gSaveStates[slot]->seqIdCopy[1];
|
||||||
|
//gAudioContext.seqPlayers[2].seqId = gSaveStates[slot]->seqIdCopy[2];
|
||||||
|
//gAudioContext.seqPlayers[3].seqId = gSaveStates[slot]->seqIdCopy[3];
|
||||||
|
|
||||||
memcpy(&gSaveContext, &gSaveStates[slot]->saveContextCopy, sizeof(gSaveContext));
|
memcpy(&gSaveContext, &gSaveStates[slot]->saveContextCopy, sizeof(gSaveContext));
|
||||||
memcpy(gGameInfo, &gSaveStates[slot]->gameInfoCopy, sizeof(*gGameInfo));
|
memcpy(gGameInfo, &gSaveStates[slot]->gameInfoCopy, sizeof(*gGameInfo));
|
||||||
//memcpy(&gAudioContext, &gSaveStates[slot]->audioContextCopy, sizeof(AudioContext));
|
|
||||||
memcpy(&sLightsBuffer, &gSaveStates[slot]->lightBufferCopy, sizeof(sLightsBuffer));
|
memcpy(&sLightsBuffer, &gSaveStates[slot]->lightBufferCopy, sizeof(sLightsBuffer));
|
||||||
memcpy(&sMatrixStack, &gSaveStates[slot]->mtxStackCopy, sizeof(MtxF) * 20);
|
memcpy(&sMatrixStack, &gSaveStates[slot]->mtxStackCopy, sizeof(MtxF) * 20);
|
||||||
memcpy(&sCurrentMatrix, &gSaveStates[slot]->currentMtxCopy, sizeof(MtxF));
|
memcpy(&sCurrentMatrix, &gSaveStates[slot]->currentMtxCopy, sizeof(MtxF));
|
||||||
sWarpTimerTarget = gSaveStates[slot]->blueWarpTimerCopy;
|
sWarpTimerTarget = gSaveStates[slot]->blueWarpTimerCopy;
|
||||||
//TODO RNG seed
|
//TODO RNG seed
|
||||||
|
|
||||||
|
memcpy(gActiveSounds, gSaveStates[slot]->gActiveSoundsCopy, sizeof(gActiveSounds));
|
||||||
|
memcpy(gSoundBankMuted, &gSaveStates[slot]->gSoundBankMutedCopy, sizeof(gSaveStates[0]->gSoundBankMutedCopy));
|
||||||
|
D_801333F0 = gSaveStates[slot]->D_801333F0_copy;
|
||||||
|
gAudioSfxSwapOff = gSaveStates[slot]->gAudioSfxSwapOff_copy;
|
||||||
|
|
||||||
|
memcpy(gAudioSfxSwapSource, &gSaveStates[slot]->gAudioSfxSwapSource_copy,
|
||||||
|
sizeof(&gSaveStates[slot]->gAudioSfxSwapSource_copy));
|
||||||
|
memcpy(gAudioSfxSwapTarget, &gSaveStates[slot]->gAudioSfxSwapTarget_copy,
|
||||||
|
sizeof(&gSaveStates[slot]->gAudioSfxSwapTarget_copy));
|
||||||
|
memcpy(gAudioSfxSwapMode, &gSaveStates[slot]->gAudioSfxSwapMode_copy,
|
||||||
|
sizeof(&gSaveStates[slot]->gAudioSfxSwapMode_copy));
|
||||||
|
|
||||||
|
D_801755D0 = gSaveStates[slot]->D_801755D0_copy;
|
||||||
|
|
||||||
return SaveStateReturn::SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
// FROM z_lights.c
|
// FROM z_lights.c
|
||||||
// I didn't feel like moving it into a header file.
|
// I didn't feel like moving it into a header file.
|
||||||
|
@ -35,11 +36,53 @@ typedef struct SaveStateHeader {
|
||||||
//uint32_t gameVersion;
|
//uint32_t gameVersion;
|
||||||
} SaveStateHeader;
|
} SaveStateHeader;
|
||||||
|
|
||||||
|
enum class RequestType {
|
||||||
|
SAVE,
|
||||||
|
LOAD,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct SaveStateInfo {
|
||||||
|
SaveStateHeader stateHeader;
|
||||||
|
|
||||||
|
unsigned char sysHeapCopy[SYSTEM_HEAP_SIZE];
|
||||||
|
unsigned char audioHeapCopy[AUDIO_HEAP_SIZE];
|
||||||
|
|
||||||
|
SaveContext saveContextCopy;
|
||||||
|
GameInfo gameInfoCopy;
|
||||||
|
LightsBuffer lightBufferCopy;
|
||||||
|
AudioContext audioContextCopy;
|
||||||
|
std::array<MtxF, 20> mtxStackCopy; // always 20 matricies
|
||||||
|
MtxF currentMtxCopy;
|
||||||
|
uint32_t rngSeed;
|
||||||
|
int16_t blueWarpTimerCopy; /* From door_warp_1 */
|
||||||
|
|
||||||
|
std::array<SeqScriptState, 4> seqScriptStateCopy; // Unrelocated
|
||||||
|
// std::array<u8, 4> seqIdCopy;
|
||||||
|
std::array<unk_D_8016E750, 4> unk_D_8016E750Copy;
|
||||||
|
|
||||||
|
ActiveSound gActiveSoundsCopy[7][MAX_CHANNELS_PER_BANK];
|
||||||
|
std::array<u8, 7> gSoundBankMutedCopy;
|
||||||
|
u8 D_801333F0_copy;
|
||||||
|
u8 gAudioSfxSwapOff_copy;
|
||||||
|
std::array<u16, 10> gAudioSfxSwapSource_copy;
|
||||||
|
std::array<u16, 10> gAudioSfxSwapTarget_copy;
|
||||||
|
std::array<u8, 10> gAudioSfxSwapMode_copy;
|
||||||
|
void (*D_801755D0_copy)(void);
|
||||||
|
} SaveStateInfo;
|
||||||
|
|
||||||
extern unsigned int gCurrentSlot;
|
extern unsigned int gCurrentSlot;
|
||||||
|
|
||||||
|
typedef struct SaveStateRequest {
|
||||||
|
unsigned int slot;
|
||||||
|
RequestType type;
|
||||||
|
} SaveStateRequest;
|
||||||
|
|
||||||
class SaveState {
|
class SaveState {
|
||||||
public:
|
public:
|
||||||
static constexpr unsigned int SAVE_SLOT_MAX = 2;
|
static constexpr unsigned int SAVE_SLOT_MAX = 2;
|
||||||
|
|
||||||
|
static std::queue <SaveStateRequest> requests;
|
||||||
|
|
||||||
SaveState();
|
SaveState();
|
||||||
~SaveState();
|
~SaveState();
|
||||||
|
|
||||||
|
@ -47,27 +90,29 @@ class SaveState {
|
||||||
SaveState(const SaveState& rhs) = delete;
|
SaveState(const SaveState& rhs) = delete;
|
||||||
|
|
||||||
void Init(void);
|
void Init(void);
|
||||||
static SaveStateReturn Save(const unsigned int slot);
|
|
||||||
static SaveStateReturn Load(const unsigned int slot);
|
|
||||||
static SaveStateReturn Export(const unsigned int slot);
|
static SaveStateReturn Export(const unsigned int slot);
|
||||||
static SaveStateReturn Import(const unsigned int slot);
|
static SaveStateReturn Import(const unsigned int slot);
|
||||||
static SaveStateReturn Delete(const unsigned int slot);
|
static SaveStateReturn Delete(const unsigned int slot);
|
||||||
|
SaveStateInfo* GetSaveStateInfo(const unsigned int slot);
|
||||||
|
static SaveStateReturn RequestSaveState(const unsigned int slot);
|
||||||
|
static SaveStateReturn RequestLoadState(const unsigned int slot);
|
||||||
|
|
||||||
|
static void ProcessSaveStateRequestsImpl(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void Save(const unsigned int slot);
|
||||||
|
static void Load(const unsigned int slot);
|
||||||
static void SetHeader(SaveStateHeader& header);
|
static void SetHeader(SaveStateHeader& header);
|
||||||
static void GetHeader(SaveStateHeader& header);
|
static void GetHeader(SaveStateHeader& header);
|
||||||
SaveStateHeader stateHeader;
|
static void BackupSeqScriptState(SaveStateInfo* state);
|
||||||
unsigned char sysHeapCopy[1024 * 1024 * 4]; //TODO, make a macro for this
|
static void LoadSeqScriptState(SaveStateInfo* state);
|
||||||
SaveContext saveContextCopy;
|
|
||||||
GameInfo gameInfoCopy;
|
SaveStateInfo saveStateInfo;
|
||||||
LightsBuffer lightBufferCopy;
|
|
||||||
//AudioContext audioContextCopy;
|
|
||||||
std::array<MtxF,20> mtxStackCopy; // always 20 matricies
|
|
||||||
MtxF currentMtxCopy;
|
|
||||||
uint32_t rngSeed;
|
|
||||||
int16_t blueWarpTimerCopy; /* From door_warp_1 */
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
8
soh/soh/OTRAudio.h
Normal file
8
soh/soh/OTRAudio.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
std::condition_variable cv_to_thread, cv_from_thread;
|
||||||
|
std::mutex mutex;
|
||||||
|
bool initialized;
|
||||||
|
bool processing;
|
||||||
|
} audio;
|
|
@ -1,4 +1,5 @@
|
||||||
#include "OTRGlobals.h"
|
#include "OTRGlobals.h"
|
||||||
|
#include "OTRAudio.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
@ -35,13 +36,6 @@
|
||||||
|
|
||||||
OTRGlobals* OTRGlobals::Instance;
|
OTRGlobals* OTRGlobals::Instance;
|
||||||
|
|
||||||
static struct {
|
|
||||||
std::condition_variable cv_to_thread, cv_from_thread;
|
|
||||||
std::mutex mutex;
|
|
||||||
bool initialized;
|
|
||||||
bool processing;
|
|
||||||
} audio;
|
|
||||||
|
|
||||||
OTRGlobals::OTRGlobals() {
|
OTRGlobals::OTRGlobals() {
|
||||||
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian");
|
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian");
|
||||||
context->GetWindow()->Init();
|
context->GetWindow()->Init();
|
||||||
|
@ -131,6 +125,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
||||||
audio.cv_to_thread.wait(Lock);
|
audio.cv_to_thread.wait(Lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||||
//AudioMgr_ThreadEntry(&gAudioMgr);
|
//AudioMgr_ThreadEntry(&gAudioMgr);
|
||||||
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
|
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
|
||||||
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
|
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
|
||||||
|
@ -156,10 +151,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
||||||
// printf("Audio samples before submitting: %d\n", audio_api->buffered());
|
// printf("Audio samples before submitting: %d\n", audio_api->buffered());
|
||||||
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
|
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
|
||||||
|
|
||||||
{
|
audio.processing = false;
|
||||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
|
||||||
audio.processing = false;
|
|
||||||
}
|
|
||||||
audio.cv_from_thread.notify_one();
|
audio.cv_from_thread.notify_one();
|
||||||
}
|
}
|
||||||
}).detach();
|
}).detach();
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AUDIO_HEAP_SIZE 0x38000
|
//#ifdef _MSC_VER
|
||||||
#define SYSTEM_HEAP_SIZE (1024 * 1024 * 128)
|
//#include <Windows.h>
|
||||||
|
//#include <>
|
||||||
|
|
||||||
u8* gAudioHeap;
|
u8* gAudioHeap;
|
||||||
u8* gSystemHeap;
|
u8* gSystemHeap;
|
||||||
|
|
|
@ -431,6 +431,8 @@ static struct RunFrameContext {
|
||||||
|
|
||||||
extern AudioMgr gAudioMgr;
|
extern AudioMgr gAudioMgr;
|
||||||
|
|
||||||
|
extern void ProcessSaveStateRequests(void);
|
||||||
|
|
||||||
static void RunFrame()
|
static void RunFrame()
|
||||||
{
|
{
|
||||||
u32 size;
|
u32 size;
|
||||||
|
@ -487,6 +489,7 @@ static void RunFrame()
|
||||||
//uint64_t diff = (ticksB - ticksA) / (freq / 1000);
|
//uint64_t diff = (ticksB - ticksA) / (freq / 1000);
|
||||||
//printf("Frame simulated in %ims\n", diff);
|
//printf("Frame simulated in %ims\n", diff);
|
||||||
runFrameContext.state = 1;
|
runFrameContext.state = 1;
|
||||||
|
ProcessSaveStateRequests();
|
||||||
return;
|
return;
|
||||||
nextFrame:;
|
nextFrame:;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue