From e3768d2fac74e0c49e76d7e3dcb403e2b5766dc3 Mon Sep 17 00:00:00 2001 From: Dextinfire <> Date: Wed, 18 Sep 2024 01:32:37 -0700 Subject: [PATCH 1/2] Fix CCLCC save/load --- src/data/savesystem.cpp | 8 ++- src/data/savesystem.h | 8 ++- src/games/cclcc/savesystem.cpp | 117 ++++++++++++++++----------------- src/games/cclcc/savesystem.h | 3 +- src/games/chlcc/savesystem.cpp | 2 +- src/games/chlcc/savesystem.h | 2 +- src/games/mo6tw/savesystem.cpp | 2 +- src/games/mo6tw/savesystem.h | 2 +- src/vm/inst_misc.cpp | 10 ++- 9 files changed, 80 insertions(+), 74 deletions(-) diff --git a/src/data/savesystem.cpp b/src/data/savesystem.cpp index d0280839..a9c16e2b 100644 --- a/src/data/savesystem.cpp +++ b/src/data/savesystem.cpp @@ -24,8 +24,12 @@ void SaveMemory() { if (Implementation) Implementation->SaveMemory(); } -void LoadMemory(SaveType type, int id) { - if (Implementation) Implementation->LoadMemory(type, id); +void LoadEntry(SaveType type, int id) { + if (Implementation) Implementation->LoadEntry(type, id); +} + +void LoadMemoryNew(LoadProcess load) { + if (Implementation) Implementation->LoadMemoryNew(load); } void FlushWorkingSaveEntry(SaveType type, int id) { diff --git a/src/data/savesystem.h b/src/data/savesystem.h index 700a6279..5a8cd33b 100644 --- a/src/data/savesystem.h +++ b/src/data/savesystem.h @@ -25,6 +25,8 @@ enum SaveError { enum SaveType { SaveFull = 0, SaveQuick = 1 }; +enum LoadProcess { LoadVars = 0, LoadThread = 1 }; + int constexpr MaxSaveEntries = 48; uint8_t const Flbit[] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; @@ -66,7 +68,8 @@ class SaveSystemBase { public: virtual SaveError MountSaveFile() = 0; virtual void SaveMemory() = 0; - virtual void LoadMemory(SaveType type, int id) = 0; + virtual void LoadEntry(SaveType type, int id) = 0; + virtual void LoadMemoryNew(LoadProcess){}; virtual void FlushWorkingSaveEntry(SaveType type, int id) = 0; virtual void WriteSaveFile() = 0; virtual uint32_t GetSavePlayTime(SaveType type, int id) = 0; @@ -104,7 +107,8 @@ void Init(); SaveError MountSaveFile(); void SaveMemory(); -void LoadMemory(SaveType type, int id); +void LoadEntry(SaveType type, int id); +void LoadMemoryNew(LoadProcess process); void FlushWorkingSaveEntry(SaveType type, int id); void WriteSaveFile(); uint32_t GetSavePlayTime(SaveType type, int id); diff --git a/src/games/cclcc/savesystem.cpp b/src/games/cclcc/savesystem.cpp index 2c76fbf5..db177a0e 100644 --- a/src/games/cclcc/savesystem.cpp +++ b/src/games/cclcc/savesystem.cpp @@ -460,80 +460,79 @@ void SaveSystem::SaveMemory() { } } -void SaveSystem::LoadMemory(SaveType type, int id) { - SaveFileEntry* entry = 0; +void SaveSystem::LoadEntry(SaveType type, int id) { + if (WorkingSaveEntry != 0) { + delete WorkingSaveEntry; + WorkingSaveEntry = 0; + } switch (type) { case SaveQuick: - entry = (SaveFileEntry*)QuickSaveEntries[id]; + WorkingSaveEntry = (SaveFileEntry*)QuickSaveEntries[id]; break; case SaveFull: - entry = (SaveFileEntry*)FullSaveEntries[id]; + WorkingSaveEntry = (SaveFileEntry*)FullSaveEntries[id]; break; default: ImpLog(LL_Error, LC_IO, "Failed to load save memory: unknown save type, doing nothing\n"); return; } +} - if (entry != 0) - if (entry->Status) { - ScrWork[SW_PLAYTIME] = entry->PlayTime; - ScrWork[SW_TITLE] = entry->SwTitle; - - memcpy(&FlagWork[50], entry->FlagWorkScript1, 50); - memcpy(&FlagWork[300], entry->FlagWorkScript2, 100); - memcpy(&ScrWork[1000], entry->ScrWorkScript1, 2400); - memcpy(&ScrWork[4300], entry->ScrWorkScript2, 12000); - UI::MapSystem::MapLoad(entry->MapLoadData); - CCLCC::YesNoTrigger::YesNoTriggerPtr->Load(entry->YesNoData); - // TODO: What to do about this mess I wonder... - ScrWork[SW_SVSENO] = ScrWork[SW_SEREQNO]; - ScrWork[SW_SVSENO + 1] = ScrWork[SW_SEREQNO + 1]; - ScrWork[SW_SVSENO + 2] = ScrWork[SW_SEREQNO + 2]; - ScrWork[SW_SVBGMNO] = ScrWork[SW_BGMREQNO]; - ScrWork[SW_SVBGM2NO] = ScrWork[SW_BGMREQNO2]; - ScrWork[SW_SVSCRNO1] = ScrWork[SW_SCRIPTNO2]; - ScrWork[SW_SVSCRNO2] = ScrWork[SW_SCRIPTNO3]; - ScrWork[SW_SVSCRNO3] = ScrWork[SW_SCRIPTNO4]; - ScrWork[SW_SVSCRNO4] = ScrWork[SW_SCRIPTNO5]; - for (int i = 0; i < 8; i++) { - ScrWork[SW_SVBGNO1 + i] = ScrWork[SW_BG1NO + i * ScrWorkBgStructSize]; - ScrWork[SW_SVCHANO1 + i] = - ScrWork[SW_CHA1NO + i * ScrWorkChaStructSize]; - } +void SaveSystem::LoadMemoryNew(LoadProcess load) { + if (!WorkingSaveEntry->Status) { + ImpLog(LL_Error, LC_IO, "Failed to load entry: save is empty\n"); + return; + } + if (load == LoadProcess::LoadVars) { + ScrWork[SW_PLAYTIME] = WorkingSaveEntry->PlayTime; + ScrWork[SW_TITLE] = WorkingSaveEntry->SwTitle; + + memcpy(&FlagWork[50], WorkingSaveEntry->FlagWorkScript1, 50); + memcpy(&FlagWork[300], WorkingSaveEntry->FlagWorkScript2, 100); + memcpy(&ScrWork[1000], WorkingSaveEntry->ScrWorkScript1, 2400); + memcpy(&ScrWork[4300], WorkingSaveEntry->ScrWorkScript2, 12000); + UI::MapSystem::MapLoad(WorkingSaveEntry->MapLoadData); + CCLCC::YesNoTrigger::YesNoTriggerPtr->Load(WorkingSaveEntry->YesNoData); + // TODO: What to do about this mess I wonder... + ScrWork[SW_SVSENO] = ScrWork[SW_SEREQNO]; + ScrWork[SW_SVSENO + 1] = ScrWork[SW_SEREQNO + 1]; + ScrWork[SW_SVSENO + 2] = ScrWork[SW_SEREQNO + 2]; + ScrWork[SW_SVBGMNO] = ScrWork[SW_BGMREQNO]; + ScrWork[SW_SVBGM2NO] = ScrWork[SW_BGMREQNO2]; + ScrWork[SW_SVSCRNO1] = ScrWork[SW_SCRIPTNO2]; + ScrWork[SW_SVSCRNO2] = ScrWork[SW_SCRIPTNO3]; + ScrWork[SW_SVSCRNO3] = ScrWork[SW_SCRIPTNO4]; + ScrWork[SW_SVSCRNO4] = ScrWork[SW_SCRIPTNO5]; + for (int i = 0; i < 8; i++) { + ScrWork[SW_SVBGNO1 + i] = ScrWork[SW_BG1NO + i * ScrWorkBgStructSize]; + ScrWork[SW_SVCHANO1 + i] = ScrWork[SW_CHA1NO + i * ScrWorkChaStructSize]; + } + } else if (ScrWork[SW_MAINTHDP] != 0) { + int threadId = ScrWork[SW_MAINTHDP]; + Sc3VmThread* thd = &ThreadPool[threadId & 0x7FFFFFFF]; - int threadId = ScrWork[SW_MAINTHDP]; - Sc3VmThread* thd = &ThreadPool[threadId & 0x7FFFFFFF]; - - // Load scripts - if (ScrWork[SW_SVSCRNO1] != 65535) LoadScript(2, ScrWork[SW_SVSCRNO1]); - if (ScrWork[SW_SVSCRNO2] != 65535) LoadScript(3, ScrWork[SW_SVSCRNO2]); - if (ScrWork[SW_SVSCRNO4] != 65535) LoadScript(5, ScrWork[SW_SVSCRNO4]); - - ScrWork[SW_SVSCRNO1] = 65535; - ScrWork[SW_SVSCRNO2] = 65535; - ScrWork[SW_SVSCRNO4] = 65535; - - if (thd->GroupId - 5 < 3) { - thd->ExecPriority = entry->MainThreadExecPriority; - thd->WaitCounter = entry->MainThreadWaitCounter; - thd->ScriptParam = entry->MainThreadScriptParam; - thd->GroupId = entry->MainThreadGroupId; - thd->ScriptBufferId = entry->MainThreadScriptBufferId; - thd->Ip = - ScriptGetRetAddress(ScriptBuffers[entry->MainThreadScriptBufferId], - entry->MainThreadIp); - thd->CallStackDepth = entry->MainThreadCallStackDepth; - - for (int i = 0; i < thd->CallStackDepth; i++) { - thd->ReturnScriptBufferIds[i] = entry->MainThreadReturnBufIds[i]; - thd->ReturnIds[i] = entry->MainThreadReturnIds[i]; - } + if (thd->GroupId - 5 < 3) { + thd->ExecPriority = WorkingSaveEntry->MainThreadExecPriority; + thd->WaitCounter = WorkingSaveEntry->MainThreadWaitCounter; + thd->ScriptParam = WorkingSaveEntry->MainThreadScriptParam; + thd->GroupId = WorkingSaveEntry->MainThreadGroupId; + thd->ScriptBufferId = WorkingSaveEntry->MainThreadScriptBufferId; + thd->Ip = ScriptGetRetAddress( + ScriptBuffers[WorkingSaveEntry->MainThreadScriptBufferId], + WorkingSaveEntry->MainThreadIp); + thd->CallStackDepth = WorkingSaveEntry->MainThreadCallStackDepth; - memcpy(thd->Variables, entry->MainThreadVariables, 64); - thd->DialoguePageId = entry->MainThreadDialoguePageId; + for (int i = 0; i < thd->CallStackDepth; i++) { + thd->ReturnScriptBufferIds[i] = + WorkingSaveEntry->MainThreadReturnBufIds[i]; + thd->ReturnIds[i] = WorkingSaveEntry->MainThreadReturnIds[i]; } + + memcpy(thd->Variables, WorkingSaveEntry->MainThreadVariables, 64); + thd->DialoguePageId = WorkingSaveEntry->MainThreadDialoguePageId; } + } } uint8_t SaveSystem::GetSaveStatus(SaveType type, int id) { diff --git a/src/games/cclcc/savesystem.h b/src/games/cclcc/savesystem.h index 811353f9..7ab7c108 100644 --- a/src/games/cclcc/savesystem.h +++ b/src/games/cclcc/savesystem.h @@ -26,7 +26,8 @@ class SaveSystem : public SaveSystemBase { public: SaveError MountSaveFile() override; void SaveMemory() override; - void LoadMemory(SaveType type, int id) override; + void LoadEntry(SaveType type, int id) override; + void LoadMemoryNew(LoadProcess load) override; void FlushWorkingSaveEntry(SaveType type, int id) override; void WriteSaveFile() override; uint32_t GetSavePlayTime(SaveType type, int id) override; diff --git a/src/games/chlcc/savesystem.cpp b/src/games/chlcc/savesystem.cpp index aaceb344..0be2abcb 100644 --- a/src/games/chlcc/savesystem.cpp +++ b/src/games/chlcc/savesystem.cpp @@ -330,7 +330,7 @@ void SaveSystem::SaveMemory() { } } -void SaveSystem::LoadMemory(SaveType type, int id) { +void SaveSystem::LoadEntry(SaveType type, int id) { SaveFileEntry* entry = 0; switch (type) { case SaveQuick: diff --git a/src/games/chlcc/savesystem.h b/src/games/chlcc/savesystem.h index 7c5b7163..1b9a174b 100644 --- a/src/games/chlcc/savesystem.h +++ b/src/games/chlcc/savesystem.h @@ -19,7 +19,7 @@ class SaveSystem : public SaveSystemBase { public: SaveError MountSaveFile() override; void SaveMemory() override; - void LoadMemory(SaveType type, int id) override; + void LoadEntry(SaveType type, int id) override; void FlushWorkingSaveEntry(SaveType type, int id) override; void WriteSaveFile() override; uint32_t GetSavePlayTime(SaveType type, int id) override; diff --git a/src/games/mo6tw/savesystem.cpp b/src/games/mo6tw/savesystem.cpp index b9000e36..c62edaa0 100644 --- a/src/games/mo6tw/savesystem.cpp +++ b/src/games/mo6tw/savesystem.cpp @@ -426,7 +426,7 @@ void SaveSystem::SaveMemory() { } } -void SaveSystem::LoadMemory(SaveType type, int id) { +void SaveSystem::LoadEntry(SaveType type, int id) { SaveFileEntry* entry = 0; switch (type) { case SaveQuick: diff --git a/src/games/mo6tw/savesystem.h b/src/games/mo6tw/savesystem.h index d7657af5..19c1f372 100644 --- a/src/games/mo6tw/savesystem.h +++ b/src/games/mo6tw/savesystem.h @@ -19,7 +19,7 @@ class SaveSystem : public SaveSystemBase { public: SaveError MountSaveFile() override; void SaveMemory() override; - void LoadMemory(SaveType type, int id) override; + void LoadEntry(SaveType type, int id) override; void FlushWorkingSaveEntry(SaveType type, int id) override; void WriteSaveFile() override; uint32_t GetSavePlayTime(SaveType type, int id) override; diff --git a/src/vm/inst_misc.cpp b/src/vm/inst_misc.cpp index b70d71d6..953e0822 100644 --- a/src/vm/inst_misc.cpp +++ b/src/vm/inst_misc.cpp @@ -436,11 +436,8 @@ VmInstruction(InstLoadData) { case 0: case 10: { PopExpression(arg1); - if (Profile::Vm::GameInstructionSet == +InstructionSet::CC) { - PopExpression(arg2); - SaveSystem::LoadMemory(static_cast(arg1), arg2); - } - + PopExpression(arg2); + SaveSystem::LoadEntry(static_cast(arg1), arg2); ImpLogSlow(LL_Warning, LC_VMStub, "STUB instruction LoadData(type: %i, arg1: %i)\n", type, arg1); } break; @@ -451,11 +448,12 @@ VmInstruction(InstLoadData) { type); break; } + SaveSystem::LoadMemoryNew(static_cast(type)); } VmInstruction(InstLoadDataOld) { StartInstruction; PopExpression(arg1); - SaveSystem::LoadMemory(SaveSystem::SaveFull, arg1); + SaveSystem::LoadEntry(SaveSystem::SaveFull, arg1); if (ScrWork[SW_MESWINDOW_COLOR] == 0) ScrWork[SW_MESWINDOW_COLOR] = 0xFFFFFF; } VmInstruction(InstTitleMenu) { From b5a67ad226418cc08594c64c967c4d182fc12a92 Mon Sep 17 00:00:00 2001 From: Dextinfire <> Date: Wed, 18 Sep 2024 02:14:00 -0700 Subject: [PATCH 2/2] Replace the working set save ptr with an optional --- src/games/cclcc/savesystem.cpp | 70 ++++++++++++++++------------------ src/games/cclcc/savesystem.h | 2 + 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/games/cclcc/savesystem.cpp b/src/games/cclcc/savesystem.cpp index db177a0e..7a9a1fed 100644 --- a/src/games/cclcc/savesystem.cpp +++ b/src/games/cclcc/savesystem.cpp @@ -23,8 +23,6 @@ using namespace Impacto::Profile::SaveSystem; using namespace Impacto::Profile::ScriptVars; using namespace Impacto::Profile::Vm; -SaveFileEntry* WorkingSaveEntry = 0; - SaveError SaveSystem::MountSaveFile() { Io::Stream* stream; IoError err = Io::PhysicalFileStream::Create(SaveFilePath, &stream); @@ -37,8 +35,7 @@ SaveError SaveSystem::MountSaveFile() { case IoError_OK: break; }; - - WorkingSaveEntry = new SaveFileEntry(); + WorkingSaveEntry = std::optional(SaveFileEntry()); WorkingSaveThumbnail.Sheet = SpriteSheet(Window->WindowWidth, Window->WindowHeight); WorkingSaveThumbnail.Bounds = @@ -209,33 +206,30 @@ void SaveSystem::FlushWorkingSaveEntry(SaveType type, int id) { break; } - if (WorkingSaveEntry != 0) { - if (entry != 0) { - Renderer->FreeTexture(entry->SaveThumbnail.Sheet.Texture); - *entry = *WorkingSaveEntry; - time_t rawtime; - time(&rawtime); - entry->SaveDate = *localtime(&rawtime); - auto captureBuffer = Renderer->GetImageFromTexture( - WorkingSaveThumbnail.Sheet.Texture, WorkingSaveThumbnail.Bounds); - - Texture tex; - tex.Init(TexFmt_RGBA, SaveThumbnailWidth, SaveThumbnailHeight); - - entry->SaveThumbnail.Sheet = - SpriteSheet(SaveThumbnailWidth, SaveThumbnailHeight); - entry->SaveThumbnail.Bounds = - RectF(0.0f, 0.0f, SaveThumbnailWidth, SaveThumbnailHeight); - - int result = ResizeImage( - WorkingSaveThumbnail.Bounds, entry->SaveThumbnail.Bounds, - captureBuffer, - tcb::span{tex.Buffer, static_cast(tex.BufferSize)}, true); - if (result < 0) { - ImpLog(LL_Error, LC_General, "Failed to resize save thumbnail\n"); - } - entry->SaveThumbnail.Sheet.Texture = tex.Submit(); + if (entry != 0) { + Renderer->FreeTexture(entry->SaveThumbnail.Sheet.Texture); + *entry = *WorkingSaveEntry; + time_t rawtime; + time(&rawtime); + entry->SaveDate = *localtime(&rawtime); + auto captureBuffer = Renderer->GetImageFromTexture( + WorkingSaveThumbnail.Sheet.Texture, WorkingSaveThumbnail.Bounds); + + Texture tex; + tex.Init(TexFmt_RGBA, SaveThumbnailWidth, SaveThumbnailHeight); + + entry->SaveThumbnail.Sheet = + SpriteSheet(SaveThumbnailWidth, SaveThumbnailHeight); + entry->SaveThumbnail.Bounds = + RectF(0.0f, 0.0f, SaveThumbnailWidth, SaveThumbnailHeight); + + int result = ResizeImage( + WorkingSaveThumbnail.Bounds, entry->SaveThumbnail.Bounds, captureBuffer, + tcb::span{tex.Buffer, static_cast(tex.BufferSize)}, true); + if (result < 0) { + ImpLog(LL_Error, LC_General, "Failed to resize save thumbnail\n"); } + entry->SaveThumbnail.Sheet.Texture = tex.Submit(); } } @@ -423,7 +417,7 @@ tm const& SaveSystem::GetSaveDate(SaveType type, int id) { void SaveSystem::SaveMemory() { // TODO: Sys save data - if (WorkingSaveEntry != 0) { + if (WorkingSaveEntry) { WorkingSaveEntry->Status = 1; WorkingSaveEntry->Checksum = 0; // CalculateChecksum(0); time_t rawtime; @@ -461,16 +455,16 @@ void SaveSystem::SaveMemory() { } void SaveSystem::LoadEntry(SaveType type, int id) { - if (WorkingSaveEntry != 0) { - delete WorkingSaveEntry; - WorkingSaveEntry = 0; + if (!WorkingSaveEntry) { + ImpLog(LL_Error, LC_IO, "Failed to load save memory: no working save\n"); + return; } switch (type) { case SaveQuick: - WorkingSaveEntry = (SaveFileEntry*)QuickSaveEntries[id]; + WorkingSaveEntry = *static_cast(QuickSaveEntries[id]); break; case SaveFull: - WorkingSaveEntry = (SaveFileEntry*)FullSaveEntries[id]; + WorkingSaveEntry = *static_cast(FullSaveEntries[id]); break; default: ImpLog(LL_Error, LC_IO, @@ -480,7 +474,7 @@ void SaveSystem::LoadEntry(SaveType type, int id) { } void SaveSystem::LoadMemoryNew(LoadProcess load) { - if (!WorkingSaveEntry->Status) { + if (!WorkingSaveEntry || WorkingSaveEntry->Status == 0) { ImpLog(LL_Error, LC_IO, "Failed to load entry: save is empty\n"); return; } @@ -662,7 +656,7 @@ bool SaveSystem::GetEVVariationIsUnlocked(int evId, int variationIdx) { bool SaveSystem::GetBgmFlag(int id) { return BGMFlags[id]; } void SaveSystem::SetCheckpointId(int id) { - if (WorkingSaveEntry != nullptr) WorkingSaveEntry->MainThreadIp = id; + if (WorkingSaveEntry) WorkingSaveEntry->MainThreadIp = id; } Sprite const& SaveSystem::GetSaveThumbnail(SaveType type, int id) { diff --git a/src/games/cclcc/savesystem.h b/src/games/cclcc/savesystem.h index 7ab7c108..c06a5e23 100644 --- a/src/games/cclcc/savesystem.h +++ b/src/games/cclcc/savesystem.h @@ -3,6 +3,7 @@ #include "../../data/savesystem.h" #include "../../texture/texture.h" #include "../../spritesheet.h" +#include namespace Impacto { namespace CCLCC { @@ -55,6 +56,7 @@ class SaveSystem : public SaveSystemBase { uint8_t MessageFlags[10000]; bool EVFlags[1200]; uint8_t BGMFlags[200]; + std::optional WorkingSaveEntry; }; } // namespace CCLCC