From 288c8d98541ad42983628458a89b4d26481f5f86 Mon Sep 17 00:00:00 2001 From: Chris Spegal Date: Thu, 31 Aug 2023 19:02:10 -0400 Subject: [PATCH] Map mem range as needed; save/restore for coreinit; add logging for save states --- src/Cafe/CafeSystem.cpp | 46 ++++--- src/Cafe/HW/MMU/MMU.cpp | 7 +- src/Cafe/IOSU/fsa/iosu_fsa.cpp | 6 + src/Cafe/OS/libs/coreinit/coreinit.cpp | 50 +++++++ src/Cafe/OS/libs/coreinit/coreinit.h | 9 ++ src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp | 66 ++++++++- src/Cafe/OS/libs/coreinit/coreinit_Alarm.h | 3 + .../OS/libs/coreinit/coreinit_Callbacks.cpp | 57 ++++++++ .../OS/libs/coreinit/coreinit_CodeGen.cpp | 15 ++ src/Cafe/OS/libs/coreinit/coreinit_CodeGen.h | 3 + .../OS/libs/coreinit/coreinit_DynLoad.cpp | 22 +++ src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h | 3 + src/Cafe/OS/libs/coreinit/coreinit_FG.cpp | 20 +++ src/Cafe/OS/libs/coreinit/coreinit_FG.h | 3 + src/Cafe/OS/libs/coreinit/coreinit_FS.cpp | 28 +++- src/Cafe/OS/libs/coreinit/coreinit_FS.h | 4 +- src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp | 20 +++ src/Cafe/OS/libs/coreinit/coreinit_GHS.h | 3 + src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp | 29 +++- src/Cafe/OS/libs/coreinit/coreinit_IPC.h | 3 + src/Cafe/OS/libs/coreinit/coreinit_Init.cpp | 22 +++ .../OS/libs/coreinit/coreinit_LockedCache.cpp | 20 +++ .../OS/libs/coreinit/coreinit_LockedCache.h | 3 + src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp | 40 ++++++ src/Cafe/OS/libs/coreinit/coreinit_MEM.h | 3 + .../libs/coreinit/coreinit_MemoryMapping.cpp | 23 ++++ .../OS/libs/coreinit/coreinit_MemoryMapping.h | 3 + .../libs/coreinit/coreinit_MessageQueue.cpp | 18 +++ .../OS/libs/coreinit/coreinit_MessageQueue.h | 3 + .../libs/coreinit/coreinit_OverlayArena.cpp | 15 ++ .../OS/libs/coreinit/coreinit_OverlayArena.h | 3 + .../coreinit/coreinit_Synchronization.cpp | 16 +++ .../OS/libs/coreinit/coreinit_SysHeap.cpp | 20 +++ src/Cafe/OS/libs/coreinit/coreinit_SysHeap.h | 3 + .../OS/libs/coreinit/coreinit_SystemInfo.cpp | 16 +++ .../OS/libs/coreinit/coreinit_SystemInfo.h | 5 +- src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp | 128 ++++++++++++++---- src/Cafe/OS/libs/coreinit/coreinit_Thread.h | 11 +- src/Cemu/Logging/CemuLogging.h | 2 + src/Common/SysAllocator.h | 12 ++ src/gui/MainWindow.cpp | 1 + 41 files changed, 704 insertions(+), 60 deletions(-) diff --git a/src/Cafe/CafeSystem.cpp b/src/Cafe/CafeSystem.cpp index 76bce1b14..891d17387 100644 --- a/src/Cafe/CafeSystem.cpp +++ b/src/Cafe/CafeSystem.cpp @@ -981,7 +981,8 @@ namespace CafeSystem { if (!sSystemRunning) return; - coreinit::SuspendAllThreads(); + coreinit::SuspendActiveThreads(); + iosu::pdm::Stop(); sSystemRunning = false; } @@ -989,13 +990,14 @@ namespace CafeSystem { if (sSystemRunning) return; - coreinit::ResumeAllThreads(); + coreinit::ResumeActiveThreads(); + iosu::pdm::StartTrackingTime(GetForegroundTitleId()); sSystemRunning = true; } void SaveState(std::string path) { - cemuLog_log(LogType::Force, "[SAVESTATE] Saving state..."); + cemuLog_log(LogType::SaveStates, "Saving state..."); MemStreamWriter writer(0); // pause game PauseTitle(); @@ -1006,45 +1008,53 @@ namespace CafeSystem writer.writeData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister)); writer.writeData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t)); // cpu - for (auto& thr : activeThread) - { - writer.writeBE(thr); - } - // fs - coreinit::FSSave(writer); + ci_Save(writer); + coreinit::ci_Alarm_Save(writer); + ci_Callbacks_Save(writer); + coreinit::ci_FS_Save(writer); + ci_Init_Save(writer); + coreinit::ci_Thread_Save(writer); iosu::fsa::Save(writer); FileStream* stream = FileStream::createFile(path); stream->writeData(writer.getResult().data(), writer.getResult().size_bytes()); delete stream; - cemuLog_log(LogType::Force, "[SAVESTATE] Saved state to {}.", path); + cemuLog_log(LogType::SaveStates, "Saved state to {}.", path); + ResumeTitle(/*isThreadRunning*/); } void LoadState(std::string path) { + PauseTitle(); - cemuLog_log(LogType::Force, "[SAVESTATE] Loading state...", path); + cemuLog_log(LogType::SaveStates, "Loading state...", path); auto data = FileStream::LoadIntoMemory(path); assert(data.has_value()); MemStreamReader reader(data->data(), data->size()); + + bool recreate = false; + if (recreate) + coreinit::__OSDeleteAllActivePPCThreads(); + // memory + DestroyMemorySpace(); memory_Deserialize(reader); // gpu reader.readData(LatteGPUState.contextRegister, sizeof(LatteGPUState.contextRegister)); reader.readData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister)); reader.readData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t)); // cpu - for (size_t i = 0; i < 256; i++) - { - activeThread[i] = reader.readBE(); - } - // fs - coreinit::FSRestore(reader); + ci_Restore(reader); + coreinit::ci_Alarm_Restore(reader); + ci_Callbacks_Restore(reader); + coreinit::ci_FS_Restore(reader); + ci_Init_Restore(reader); + coreinit::ci_Thread_Restore(reader, recreate); iosu::fsa::Restore(reader); - cemuLog_log(LogType::Force, "[SAVESTATE] Loaded state from {}.", path); + cemuLog_log(LogType::SaveStates, "Loaded state from {}.", path); ResumeTitle(/*isThreadRunning*/); } diff --git a/src/Cafe/HW/MMU/MMU.cpp b/src/Cafe/HW/MMU/MMU.cpp index 443607e93..508b9cc24 100644 --- a/src/Cafe/HW/MMU/MMU.cpp +++ b/src/Cafe/HW/MMU/MMU.cpp @@ -110,13 +110,16 @@ void MemStreamWriter::writeBE(const MMURange& v) template <> void MemStreamReader::readBE(MMURange& mmuRange) { - mmuRange.m_isMapped = readBE(); + bool needsMapped = readBE(); + mmuRange.m_isMapped = false; mmuRange.baseAddress = readBE(); mmuRange.areaId = (MMU_MEM_AREA_ID)readBE(); mmuRange.flags = (MMURange::MFLAG)readBE(); mmuRange.name = readBE(); mmuRange.size = readBE(); mmuRange.initSize = readBE(); + if (needsMapped) + mmuRange.mapMem(); } bool MMURange::deserializeImpl(MemStreamReader& streamReader) @@ -470,7 +473,6 @@ void memory_createDump() void memory_Serialize(MemStreamWriter& s) { - s.writeBE(g_mmuRanges.size()); for (auto& itr : g_mmuRanges) { s.writeBE(*itr); @@ -483,7 +485,6 @@ void memory_Serialize(MemStreamWriter& s) void memory_Deserialize(MemStreamReader& s) { - size_t cnt = s.readBE(); for (auto& itr : g_mmuRanges) { s.readBE(*itr); diff --git a/src/Cafe/IOSU/fsa/iosu_fsa.cpp b/src/Cafe/IOSU/fsa/iosu_fsa.cpp index e2cf8988e..903aa881b 100644 --- a/src/Cafe/IOSU/fsa/iosu_fsa.cpp +++ b/src/Cafe/IOSU/fsa/iosu_fsa.cpp @@ -992,6 +992,8 @@ namespace iosu::fsa void Save(MemStreamWriter& writer) { + writer.writeData("iosu_fsa_S", 15); + writer.writeBE(sFSAIoMsgQueue); for (size_t i = 0; i < 352; i++) { @@ -1003,6 +1005,10 @@ namespace iosu::fsa void Restore(MemStreamReader& reader) { + char section[16] = { '\0' }; + reader.readData(section, 15); + cemu_assert_debug(strcmp(section, "iosu_fsa_S") == 0); + sFSAIoMsgQueue = reader.readBE(); for (size_t i = 0; i < 352; i++) { diff --git a/src/Cafe/OS/libs/coreinit/coreinit.cpp b/src/Cafe/OS/libs/coreinit/coreinit.cpp index e8e4ce1f2..ce2588bc4 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit.cpp @@ -316,6 +316,56 @@ namespace coreinit } }; +void ci_Save(MemStreamWriter& s) +{ + s.writeData("ci_S", 15); + + s.writeData(gCoreinitData, sizeof(coreinitData_t)); + s.writeBE(placeholderFont); + s.writeBE(placeholderFontSize); + + using namespace coreinit; + ci_CodeGen_Save(s); + ci_DynLoad_Save(s); + ci_FG_Save(s); + ci_GHS_Save(s); + ci_IPC_Save(s); + ci_LockedCache_Save(s); + ci_MEM_Save(s); + ci_MemoryMapping_Save(s); + ci_MessageQueue_Save(s); + ci_OverlayArena_Save(s); + ci_Sync_Save(s); + ci_SysHeap_Save(s); + ci_SystemInfo_Save(s); +} + +void ci_Restore(MemStreamReader& s) +{ + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_S") == 0); + + s.readData(gCoreinitData, sizeof(coreinitData_t)); + placeholderFont = s.readBE(); + placeholderFontSize = s.readBE(); + + using namespace coreinit; + ci_CodeGen_Restore(s); + ci_DynLoad_Restore(s); + ci_FG_Restore(s); + ci_GHS_Restore(s); + ci_IPC_Restore(s); + ci_LockedCache_Restore(s); + ci_MEM_Restore(s); + ci_MemoryMapping_Restore(s); + ci_MessageQueue_Restore(s); + ci_OverlayArena_Restore(s); + ci_Sync_Restore(s); + ci_SysHeap_Restore(s); + ci_SystemInfo_Restore(s); +} + void coreinit_load() { coreinit::InitializeCore(); diff --git a/src/Cafe/OS/libs/coreinit/coreinit.h b/src/Cafe/OS/libs/coreinit/coreinit.h index 046ffe1e4..81d80f089 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit.h +++ b/src/Cafe/OS/libs/coreinit/coreinit.h @@ -11,10 +11,16 @@ void InitializeAsyncCallback(); void coreinitAsyncCallback_add(MPTR functionMPTR, uint32 numParameters, uint32 r3 = 0, uint32 r4 = 0, uint32 r5 = 0, uint32 r6 = 0, uint32 r7 = 0, uint32 r8 = 0, uint32 r9 = 0, uint32 r10 = 0); void coreinitAsyncCallback_addWithLock(MPTR functionMPTR, uint32 numParameters, uint32 r3 = 0, uint32 r4 = 0, uint32 r5 = 0, uint32 r6 = 0, uint32 r7 = 0, uint32 r8 = 0, uint32 r9 = 0, uint32 r10 = 0); +void ci_Callbacks_Save(MemStreamWriter& s); +void ci_Callbacks_Restore(MemStreamReader& s); + // misc void coreinit_load(); +void ci_Save(MemStreamWriter& s); +void ci_Restore(MemStreamReader& s); + // coreinit shared memory typedef struct @@ -35,6 +41,9 @@ extern coreinitData_t* gCoreinitData; // coreinit init void coreinit_start(PPCInterpreter_t* hCPU); +void ci_Init_Save(MemStreamWriter& s); +void ci_Init_Restore(MemStreamReader& s); + MPTR OSAllocFromSystem(uint32 size, uint32 alignment); void OSFreeToSystem(MPTR mem); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp index f7e581155..d379d49c2 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp @@ -247,7 +247,7 @@ namespace coreinit } else { - alarm->nextTime = _swapEndianU64(startTime); + alarm->nextTime = _swapEndianU64(nextTime); alarm->period = 0; alarm->handler = _swapEndianU32(handlerFunc); } @@ -305,6 +305,70 @@ namespace coreinit __OSUnlockScheduler(); } + void ci_Alarm_Save(MemStreamWriter& s) + { + s.writeData("ci_A_S", 15); + + s.writeBE(g_alarmEvent.GetMPTR()); + s.writeBE(g_alarmThread.GetMPTR()); + s.writeBE(_g_alarmThreadStack.GetMPTR()); + s.writeBE(_g_alarmThreadName.GetMPTR()); + + s.writeBE(coreinit_getOSTime()); + + s.writeBE(g_activeAlarms.size()); + for (auto& itr : g_activeAlarms) + { + s.writeBE(memory_getVirtualOffsetFromPointer(itr.first)); + s.writeBE(itr.second->getNextFire()); + } + } + + void ci_Alarm_Restore(MemStreamReader& s) + { + OSAlarm_Shutdown(); + + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_A_S") == 0); + + g_alarmEvent = (OSEvent*)memory_getPointerFromVirtualOffset(s.readBE()); + g_alarmThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE()); + _g_alarmThreadStack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE()); + _g_alarmThreadName = (char*)memory_getPointerFromVirtualOffset(s.readBE()); + + uint64 currentTime = coreinit_getOSTime(); + uint64_t timeOffset = currentTime - s.readBE(); + + size_t alms = s.readBE(); + for (size_t alm = 0; alm < alms; alm++) + { + OSAlarm_t* alarm = (OSAlarm_t*)memory_getPointerFromVirtualOffset(s.readBE()); + + uint64 startTime = _swapEndianU64(alarm->startTime) + timeOffset; + uint64 nextTime = _swapEndianU64(alarm->nextTime) + timeOffset; + //uint64 nextTime = startTime; + + uint64 period = _swapEndianU64(alarm->period); + + if (period != 0) + { + //uint64 ticksSinceStart = currentTime - startTime; + //uint64 numPeriods = ticksSinceStart / period; + + //nextTime = startTime + (numPeriods + 1ull) * period; + + alarm->startTime = _swapEndianU64(startTime); + } + alarm->nextTime = _swapEndianU64(nextTime); + + uint64 nextFire = s.readBE() + timeOffset; + __OSLockScheduler(); + g_activeAlarms[alarm] = OSHostAlarmCreate(nextFire, period, __OSHostAlarmTriggered, nullptr); + __OSUnlockScheduler(); + } + } + void _OSAlarmThread(PPCInterpreter_t* hCPU) { while( true ) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.h b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.h index 472d4f21c..93523d68d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Alarm.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_Alarm.h @@ -47,6 +47,9 @@ namespace coreinit void OSAlarm_Shutdown(); + void ci_Alarm_Save(MemStreamWriter& s); + void ci_Alarm_Restore(MemStreamReader& s); + void alarm_update(); void InitializeAlarm(); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp index aef7e5aa0..9507249d4 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp @@ -31,6 +31,19 @@ struct CoreinitAsyncCallback s_asyncCallbackSpinlock.unlock(); } + static std::vector* getPoolPtr() + { + return &s_asyncCallbackPool; + } + + static std::vector* getQueuePtr() + { + return &s_asyncCallbackQueue; + } + + friend void ci_Callbacks_Save(MemStreamWriter& s); + friend void ci_Callbacks_Restore(MemStreamReader& s); + private: void doCall() { @@ -104,6 +117,50 @@ void coreinitAsyncCallback_add(MPTR functionMPTR, uint32 numParameters, uint32 r coreinitAsyncCallback_addWithLock(functionMPTR, numParameters, r3, r4, r5, r6, r7, r8, r9, r10); } +void ci_Callbacks_Save(MemStreamWriter& s) +{ + s.writeData("ci_C_S", 15); + + s.writeBE(g_coreinitCallbackThread.GetMPTR()); + s.writeBE(_g_coreinitCallbackThreadStack.GetMPTR()); + s.writeBE(g_asyncCallbackAsync.GetMPTR()); + s.writeBE(_g_coreinitCBThreadName.GetMPTR()); + + std::vector* pool = CoreinitAsyncCallback::getPoolPtr(); + size_t poolSize = pool->size(); + s.writeBE(poolSize); + s.writeData(pool, sizeof(CoreinitAsyncCallback) * poolSize); + + std::vector* queue = CoreinitAsyncCallback::getQueuePtr(); + size_t queueSize = queue->size(); + s.writeBE(queueSize); + s.writeData(queue, sizeof(CoreinitAsyncCallback) * queueSize); +} + +void ci_Callbacks_Restore(MemStreamReader& s) +{ + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_C_S") == 0); + + g_coreinitCallbackThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE()); + _g_coreinitCallbackThreadStack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE()); + g_asyncCallbackAsync = (coreinit::OSSemaphore*)memory_getPointerFromVirtualOffset(s.readBE()); + _g_coreinitCBThreadName = (char*)memory_getPointerFromVirtualOffset(s.readBE()); + + std::vector* pool = CoreinitAsyncCallback::getPoolPtr(); + size_t poolSize = s.readBE(); + pool->clear(); + pool->resize(poolSize); + s.readData(pool, sizeof(CoreinitAsyncCallback) * poolSize); + + std::vector* queue = CoreinitAsyncCallback::getPoolPtr(); + size_t queueSize = s.readBE(); + queue->clear(); + queue->resize(queueSize); + s.readData(queue, sizeof(CoreinitAsyncCallback) * queueSize); +} + void InitializeAsyncCallback() { coreinit::OSInitSemaphore(g_asyncCallbackAsync.GetPtr(), 0); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.cpp b/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.cpp index f0e0bd809..c27c1a529 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.cpp @@ -136,6 +136,21 @@ namespace coreinit return true; } + void ci_CodeGen_Save(MemStreamWriter& s) + { + s.writeData("ci_CG_S", 15); + s.writeData(&coreinitCodeGen, sizeof(coreinitCodeGen)); + } + + void ci_CodeGen_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_CG_S") == 0); + + s.readData(&coreinitCodeGen, sizeof(coreinitCodeGen)); + } + void InitializeCodeGen() { cafeExportRegister("coreinit", OSGetCodegenVirtAddrRange, LogType::Placeholder); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.h b/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.h index ba41dd879..f7bdff040 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_CodeGen.h @@ -6,5 +6,8 @@ namespace coreinit void codeGenHandleICBI(uint32 ea); bool codeGenShouldAvoid(); + void ci_CodeGen_Save(MemStreamWriter& s); + void ci_CodeGen_Restore(MemStreamReader& s); + void InitializeCodeGen(); } \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.cpp b/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.cpp index c8b051241..4a3db30e2 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.cpp @@ -129,6 +129,28 @@ namespace coreinit return 0; } + void ci_DynLoad_Save(MemStreamWriter& s) + { + s.writeData("ci_DL_S", 15); + + s.writeBE(_osDynLoadFuncAlloc); + s.writeBE(_osDynLoadFuncFree); + s.writeBE(_osDynLoadTLSFuncAlloc); + s.writeBE(_osDynLoadTLSFuncFree); + } + + void ci_DynLoad_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_DL_S") == 0); + + _osDynLoadFuncAlloc = s.readBE(); + _osDynLoadFuncFree = s.readBE(); + _osDynLoadTLSFuncAlloc = s.readBE(); + _osDynLoadTLSFuncFree = s.readBE(); + } + void InitializeDynLoad() { cafeExportRegister("coreinit", OSDynLoad_SetAllocator, LogType::Placeholder); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h b/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h index 0be8226c6..c31040a90 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_DynLoad.h @@ -14,5 +14,8 @@ namespace coreinit void OSDynLoad_Release(uint32 moduleHandle); uint32 OSDynLoad_FindExport(uint32 moduleHandle, uint32 isData, const char* exportName, betype* addrOut); + void ci_DynLoad_Save(MemStreamWriter& s); + void ci_DynLoad_Restore(MemStreamReader& s); + void InitializeDynLoad(); } \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp index 15dcd6da7..457aa01e1 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FG.cpp @@ -191,6 +191,26 @@ namespace coreinit osLib_returnFromFunction(hCPU, r ? 1 : 0); } + void ci_FG_Save(MemStreamWriter& s) + { + s.writeData("ci_FG_S", 15); + + s.writeBE(fgAddr.GetMPTR()); + s.writeBE(fgSaveAreaAddr.GetMPTR()); + s.writeData(&fgAreaEntries, sizeof(fgAreaEntries) * FG_BUCKET_AREA_COUNT); + } + + void ci_FG_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_FG_S") == 0); + + fgAddr = memory_getPointerFromVirtualOffset(s.readBE()); + fgSaveAreaAddr = memory_getPointerFromVirtualOffset(s.readBE()); + s.readData(&fgAreaEntries, sizeof(fgAreaEntries) * FG_BUCKET_AREA_COUNT); + } + void InitializeFG() { osLib_addFunction("coreinit", "OSGetForegroundBucket", coreinitExport_OSGetForegroundBucket); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FG.h b/src/Cafe/OS/libs/coreinit/coreinit_FG.h index 846001b97..fcc88b4f4 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FG.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_FG.h @@ -13,5 +13,8 @@ namespace coreinit void InitForegroundBucket(); + void ci_FG_Save(MemStreamWriter& s); + void ci_FG_Restore(MemStreamReader& s); + void InitializeFG(); } \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp index 70c047a4f..c230d14f0 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.cpp @@ -2638,14 +2638,38 @@ namespace coreinit return FSA_RESULT::OK; } - void FSSave(MemStreamWriter& s) + void ci_FS_Save(MemStreamWriter& s) { + s.writeData("ci_FS_S", 15); s.writeData(g_fsRegisteredClientBodies, sizeof(FSClientBody_t)); + s.writeBE(_sdCard01Mounted); + s.writeBE(_mlc01Mounted); + s.writeBE(_tempFSSpace.GetMPTR()); + size_t s_fsa_activeClients_size = s_fsa_activeClients.size(); + s.writeBE(s_fsa_activeClients_size); + s.writeData(&s_fsa_activeClients, sizeof(FSAClientHandle) * s_fsa_activeClients_size); + s.writeBE(s_fsaIpcPool.GetMPTR()); + s.writeBE(s_fsaIpcPoolBuffer.GetMPTR()); + s.writeBE(s_fsaIpcPoolBufferNumItems.GetMPTR()); } - void FSRestore(MemStreamReader& s) + void ci_FS_Restore(MemStreamReader& s) { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_FS_S") == 0); + s.readData(g_fsRegisteredClientBodies, sizeof(FSClientBody_t)); + _sdCard01Mounted = s.readBE(); + _mlc01Mounted = s.readBE(); + _tempFSSpace = memory_getPointerFromVirtualOffset(s.readBE()); + size_t s_fsa_activeClients_size = s.readBE(); + s_fsa_activeClients.clear(); + s_fsa_activeClients.resize(s_fsa_activeClients_size); + s.readData(&s_fsa_activeClients, sizeof(FSAClientHandle) * s_fsa_activeClients_size); + s_fsaIpcPool = (IPCBufPool_t*)memory_getPointerFromVirtualOffset(s.readBE()); + s_fsaIpcPoolBuffer = memory_getPointerFromVirtualOffset(s.readBE()); + s_fsaIpcPoolBufferNumItems = (uint32be*)memory_getPointerFromVirtualOffset(s.readBE()); } void InitializeFS() diff --git a/src/Cafe/OS/libs/coreinit/coreinit_FS.h b/src/Cafe/OS/libs/coreinit/coreinit_FS.h index 6a0bf9b3e..0b5761261 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_FS.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_FS.h @@ -308,8 +308,8 @@ namespace coreinit FS_VOLSTATE FSGetVolumeState(FSClient_t* fsClient); - void FSSave(MemStreamWriter& s); - void FSRestore(MemStreamReader& s); + void ci_FS_Save(MemStreamWriter& s); + void ci_FS_Restore(MemStreamReader& s); void InitializeFS(); }; // namespace coreinit diff --git a/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp b/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp index 5699e3e7e..f967781fe 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_GHS.cpp @@ -258,6 +258,26 @@ namespace coreinit return memory_getPointerFromVirtualOffset(_swapEndianU32(tlsBlock->addr) + _swapEndianU32(tlsIndex->ukn04)); } + void ci_GHS_Save(MemStreamWriter& s) + { + s.writeData("ci_GHS_S", 15); + + s.writeBE(g_ghs_data.GetMPTR()); + s.writeBE(_flockMutexArray.GetMPTR()); + s.writeData(_flockMutexMask, sizeof(bool) * GHS_FOPEN_MAX); + } + + void ci_GHS_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_GHS_S") == 0); + + g_ghs_data = (GHSAccessibleData*)memory_getPointerFromVirtualOffset(s.readBE()); + _flockMutexArray = (coreinit::OSMutex*)memory_getPointerFromVirtualOffset(s.readBE()); + s.readData(_flockMutexMask, sizeof(bool) * GHS_FOPEN_MAX); + } + void InitializeGHS() { cafeExportRegister("coreinit", __ghs_flock_create, LogType::Placeholder); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_GHS.h b/src/Cafe/OS/libs/coreinit/coreinit_GHS.h index 0ac09e944..3cc644454 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_GHS.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_GHS.h @@ -4,5 +4,8 @@ namespace coreinit { void PrepareGHSRuntime(); + void ci_GHS_Save(MemStreamWriter& s); + void ci_GHS_Restore(MemStreamReader& s); + void InitializeGHS(); }; \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp b/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp index ef847f269..6a582203a 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_IPC.cpp @@ -462,6 +462,34 @@ namespace coreinit return r; } + void ci_IPC_Save(MemStreamWriter& s) + { + s.writeData("ci_IPC_S", 15); + + s.writeBE(s_ipcResourceBuffers.GetMPTR()); + s.writeBE(s_ipcDriver.GetMPTR()); + s.writeBE(gIPCThread.GetMPTR()); + s.writeBE(_gIPCThreadStack.GetMPTR()); + s.writeBE(_gIPCThreadNameStorage.GetMPTR()); + s.writeBE(gIPCThreadMsgQueue.GetMPTR()); + s.writeBE(_gIPCThreadSemaphoreStorage.GetMPTR()); + } + + void ci_IPC_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_IPC_S") == 0); + + s_ipcResourceBuffers = (IPCResourceBuffer*)memory_getPointerFromVirtualOffset(s.readBE()); + s_ipcDriver = (IPCDriver*)memory_getPointerFromVirtualOffset(s.readBE()); + gIPCThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE()); + _gIPCThreadStack = memory_getPointerFromVirtualOffset(s.readBE()); + _gIPCThreadNameStorage = memory_getPointerFromVirtualOffset(s.readBE()); + gIPCThreadMsgQueue = (OSMessageQueue*)memory_getPointerFromVirtualOffset(s.readBE()); + _gIPCThreadSemaphoreStorage = (OSMessage*)memory_getPointerFromVirtualOffset(s.readBE()); + } + void InitializeIPC() { for (uint32 i = 0; i < Espresso::CORE_COUNT; i++) @@ -478,5 +506,4 @@ namespace coreinit cafeExportRegister("coreinit", IOS_Ioctlv, LogType::PPC_IPC); cafeExportRegister("coreinit", IOS_IoctlvAsync, LogType::PPC_IPC); } - }; diff --git a/src/Cafe/OS/libs/coreinit/coreinit_IPC.h b/src/Cafe/OS/libs/coreinit/coreinit_IPC.h index 362c47257..f379773e9 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_IPC.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_IPC.h @@ -12,5 +12,8 @@ namespace coreinit IOS_ERROR IOS_Ioctlv(IOSDevHandle devHandle, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec); IOS_ERROR IOS_IoctlvAsync(IOSDevHandle devHandle, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec, MEMPTR asyncResultFunc, MEMPTR asyncResultUserParam); + void ci_IPC_Save(MemStreamWriter& s); + void ci_IPC_Restore(MemStreamReader& s); + void InitializeIPC(); }; \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp index 51a3f5426..591a3c614 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Init.cpp @@ -215,3 +215,25 @@ void coreinit_start(PPCInterpreter_t* hCPU) hCPU->gpr[3] = _coreinitInfo->argc; hCPU->instructionPointer = _coreinitTitleEntryPoint; } + +void ci_Init_Save(MemStreamWriter& s) +{ + s.writeData("ci_Init_S", 15); + + s.writeData(_coreinitInfo, sizeof(coreinitInit_t)); + s.writeBE(argStorageIndex); + s.writeBE(g_preinitUserParam.GetMPTR()); + s.writeBE(_coreinitTitleEntryPoint); +} + +void ci_Init_Restore(MemStreamReader& s) +{ + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_Init_S") == 0); + + s.readData(_coreinitInfo, sizeof(coreinitInit_t)); + argStorageIndex = s.readBE(); + g_preinitUserParam = (PreinitUserHeapStruct*)memory_getPointerFromVirtualOffset(s.readBE()); + _coreinitTitleEntryPoint = s.readBE(); +} \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp b/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp index a051fce1d..b330f979c 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp @@ -271,6 +271,26 @@ namespace coreinit osLib_returnFromFunction(hCPU, 0); } + void ci_LockedCache_Save(MemStreamWriter& s) + { + s.writeData("ci_LC_S", 15); + + s.writeData(lcCacheMask, sizeof(uint8) * PPC_CORE_COUNT * (LC_LOCKED_CACHE_SIZE + LC_LOCKED_CACHE_GRANULARITY - 1) / LC_LOCKED_CACHE_GRANULARITY); + s.writeData(lcAllocatedBlocks, sizeof(uint32) * PPC_CORE_COUNT); + s.writeBE(_lcDisableErrorCounter); + } + + void ci_LockedCache_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_LC_S") == 0); + + s.readData(lcCacheMask, sizeof(uint8) * PPC_CORE_COUNT * (LC_LOCKED_CACHE_SIZE + LC_LOCKED_CACHE_GRANULARITY - 1) / LC_LOCKED_CACHE_GRANULARITY); + s.readData(lcAllocatedBlocks, sizeof(uint32) * PPC_CORE_COUNT); + _lcDisableErrorCounter = s.readBE(); + } + void InitializeLC() { for (sint32 f = 0; f < PPC_CORE_COUNT; f++) diff --git a/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.h b/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.h index d2fbcbdfd..89d2b11cf 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.h @@ -2,5 +2,8 @@ namespace coreinit { + void ci_LockedCache_Save(MemStreamWriter& s); + void ci_LockedCache_Restore(MemStreamReader& s); + void InitializeLC(); } \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp index dc82f7724..cfbeee5ee 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MEM.cpp @@ -630,6 +630,46 @@ namespace coreinit memset(&g_list3, 0, sizeof(g_list3)); } + void ci_MEM_Save(MemStreamWriter& s) + { + s.writeData("ci_MEM_S", 15); + + s.writeBE(sysAreaAllocatorOffset); + s.writeBE(g_heapTableCount); + s.writeData(g_heapTable, sizeof(MEMHeapBase) * MEM_MAX_HEAP_TABLE); + s.writeBE(g_slockInitialized); + s.writeBE(g_listsInitialized); + s.writeData(&g_list1, sizeof(MEMList)); + s.writeData(&g_list2, sizeof(MEMList)); + s.writeData(&g_list3, sizeof(MEMList)); + s.writeData(&gHeapFillValues, sizeof(uint32) * 3); + s.writeBE(gHeapGlobalLock.GetMPTR()); + s.writeData(&gDefaultHeap, sizeof(MEMHeapBase)); + s.writeData(&sHeapBaseHandle, sizeof(MEMHeapBase) * 9); + s.writeBE(gDefaultHeapAllocator.GetMPTR()); + } + + void ci_MEM_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_MEM_S") == 0); + + sysAreaAllocatorOffset = s.readBE(); + g_heapTableCount = s.readBE(); + s.readData(g_heapTable, sizeof(MEMHeapBase) * MEM_MAX_HEAP_TABLE); + g_slockInitialized = s.readBE(); + g_listsInitialized = s.readBE(); + s.readData(&g_list1, sizeof(MEMList)); + s.readData(&g_list2, sizeof(MEMList)); + s.readData(&g_list3, sizeof(MEMList)); + s.readData(&gHeapFillValues, sizeof(uint32) * 3); + gHeapGlobalLock = (OSSpinLock*)memory_getPointerFromVirtualOffset(s.readBE()); + s.readData(&gDefaultHeap, sizeof(MEMHeapBase)); + s.readData(&sHeapBaseHandle, sizeof(MEMHeapBase) * 9); + gDefaultHeapAllocator = (MEMAllocatorFunc*)memory_getPointerFromVirtualOffset(s.readBE()); + } + void InitializeMEM() { MEMResetToDefaultState(); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MEM.h b/src/Cafe/OS/libs/coreinit/coreinit_MEM.h index 7e5831951..f057fa0fd 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MEM.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_MEM.h @@ -179,5 +179,8 @@ namespace coreinit void InitializeMEMUnitHeap(); + void ci_MEM_Save(MemStreamWriter& s); + void ci_MEM_Restore(MemStreamReader& s); + void InitializeMEM(); } diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.cpp index d32a105ce..cfeb94b79 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.cpp @@ -16,6 +16,8 @@ namespace coreinit struct OSVirtMemoryEntry { + OSVirtMemoryEntry() : virtualAddress(0), size(0), alignment(0) {}; + OSVirtMemoryEntry(MPTR virtualAddress, uint32 size, uint32 alignment) : virtualAddress(virtualAddress), size(size), alignment(alignment) {}; MPTR virtualAddress; @@ -151,6 +153,27 @@ namespace coreinit return 1; } + void ci_MemoryMapping_Save(MemStreamWriter& s) + { + s.writeData("ci_MemMap_S", 15); + + size_t s_allocatedVirtMemorySize = s_allocatedVirtMemory.size(); + s.writeBE(s_allocatedVirtMemorySize); + s.writeData(&s_allocatedVirtMemory, sizeof(OSVirtMemoryEntry) * s_allocatedVirtMemorySize); + } + + void ci_MemoryMapping_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_MemMap_S") == 0); + + size_t s_allocatedVirtMemorySize = s.readBE(); + s_allocatedVirtMemory.clear(); + s_allocatedVirtMemory.resize(s_allocatedVirtMemorySize); + s.readData(&s_allocatedVirtMemory, sizeof(OSVirtMemoryEntry) * s_allocatedVirtMemorySize); + } + void InitializeMemoryMapping() { s_allocatedVirtMemory.clear(); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.h b/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.h index f51d9a6a6..5988fa39d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_MemoryMapping.h @@ -1,5 +1,8 @@ namespace coreinit { + void ci_MemoryMapping_Save(MemStreamWriter& s); + void ci_MemoryMapping_Restore(MemStreamReader& s); + void InitializeMemoryMapping(); } diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp index 6e6a7bc15..dce041e17 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.cpp @@ -117,6 +117,24 @@ namespace coreinit return g_systemMessageQueue.GetPtr(); } + void ci_MessageQueue_Save(MemStreamWriter& s) + { + s.writeData("ci_MessQue_S", 15); + + s.writeBE(g_systemMessageQueue.GetMPTR()); + s.writeBE(_systemMessageQueueArray.GetMPTR()); + } + + void ci_MessageQueue_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_MessQue_S") == 0); + + g_systemMessageQueue = (OSMessageQueue*)memory_getPointerFromVirtualOffset(s.readBE()); + _systemMessageQueueArray = (OSMessage*)memory_getPointerFromVirtualOffset(s.readBE()); + } + void InitializeMessageQueue() { OSInitMessageQueue(g_systemMessageQueue.GetPtr(), _systemMessageQueueArray.GetPtr(), _systemMessageQueueArray.GetCount()); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h index 6741ab842..97343c137 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_MessageQueue.h @@ -36,5 +36,8 @@ namespace coreinit bool OSPeekMessage(OSMessageQueue* msgQueue, OSMessage* msg); sint32 OSSendMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags); + void ci_MessageQueue_Save(MemStreamWriter& s); + void ci_MessageQueue_Restore(MemStreamReader& s); + void InitializeMessageQueue(); }; \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.cpp b/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.cpp index 5e5d88520..962a9a94d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.cpp @@ -25,6 +25,21 @@ namespace coreinit *areaSize = MEMORY_OVERLAY_AREA_SIZE; } + void ci_OverlayArena_Save(MemStreamWriter& s) + { + s.writeData("ci_OverArea_S", 15); + + s.writeData(&g_coreinitOverlayArena, sizeof(g_coreinitOverlayArena)); + } + void ci_OverlayArena_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_OverArea_S") == 0); + + s.readData(&g_coreinitOverlayArena, sizeof(g_coreinitOverlayArena)); + } + void InitializeOverlayArena() { cafeExportRegister("coreinit", OSIsEnabledOverlayArena, LogType::Placeholder); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.h b/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.h index d9d5868fb..52cb4dbcc 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_OverlayArena.h @@ -1,4 +1,7 @@ namespace coreinit { + void ci_OverlayArena_Save(MemStreamWriter& s); + void ci_OverlayArena_Restore(MemStreamReader& s); + void InitializeOverlayArena(); }; \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp index 92c90a9de..4e818e240 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Synchronization.cpp @@ -614,6 +614,22 @@ namespace coreinit OSWakeupThread(&fastCond->threadQueue); } + void ci_Sync_Save(MemStreamWriter& s) + { + s.writeData("ci_Sync_S", 15); + + s.writeBE(g_rendezvousEvent.GetMPTR()); + } + + void ci_Sync_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_Sync_S") == 0); + + g_rendezvousEvent = (OSEvent*)memory_getPointerFromVirtualOffset(s.readBE()); + } + /************* init ************/ void InitializeConcurrency() diff --git a/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.cpp b/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.cpp index e37949d77..41a47295d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.cpp @@ -32,6 +32,26 @@ namespace coreinit _sysHeapFreeCounter = 0; } + void ci_SysHeap_Save(MemStreamWriter& s) + { + s.writeData("ci_SysHeap_S", 15); + + s.writeData(_sysHeapHandle, sizeof(MEMHeapBase)); + s.writeBE(_sysHeapAllocCounter); + s.writeBE(_sysHeapFreeCounter); + } + + void ci_SysHeap_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_SysHeap_S") == 0); + + s.readData(_sysHeapHandle, sizeof(MEMHeapBase)); + _sysHeapAllocCounter = s.readBE(); + _sysHeapFreeCounter = s.readBE(); + } + void InitializeSysHeap() { osLib_addFunction("coreinit", "OSAllocFromSystem", export_OSAllocFromSystem); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.h b/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.h index 428224af2..3001438ac 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_SysHeap.h @@ -4,5 +4,8 @@ namespace coreinit { void InitSysHeap(); + void ci_SysHeap_Save(MemStreamWriter& s); + void ci_SysHeap_Restore(MemStreamReader& s); + void InitializeSysHeap(); } \ No newline at end of file diff --git a/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp b/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp index 83925acdf..64bb4ff95 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.cpp @@ -10,6 +10,22 @@ namespace coreinit return *g_system_info.GetPtr(); } + void ci_SystemInfo_Save(MemStreamWriter& s) + { + s.writeData("ci_SysInfo_S", 15); + + s.writeBE(g_system_info.GetMPTR()); + } + + void ci_SystemInfo_Restore(MemStreamReader& s) + { + char section[16] = { '\0' }; + s.readData(section, 15); + cemu_assert_debug(strcmp(section, "ci_SysInfo_S") == 0); + + g_system_info = (OSSystemInfo*)memory_getPointerFromVirtualOffset(s.readBE()); + } + void InitializeSystemInfo() { cemu_assert(ppcCyclesSince2000 != 0); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.h b/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.h index b2c50069c..49a52625d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_SystemInfo.h @@ -15,7 +15,10 @@ namespace coreinit static_assert(sizeof(OSSystemInfo) == 0x20); const OSSystemInfo& OSGetSystemInfo(); - + + void ci_SystemInfo_Save(MemStreamWriter& s); + void ci_SystemInfo_Restore(MemStreamReader& s); + void InitializeSystemInfo(); }; diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp index 0ba237088..590f625c2 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.cpp @@ -196,36 +196,6 @@ namespace coreinit return __currentCoreThread[currentInstance->spr.UPIR]; } - void SuspendAllThreads() - { - for (auto& thr : activeThread) - { - auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(thr); - if (thr != 0) - { - OSSuspendThread(ptr); - } - } - } - - void ResumeAllThreads() - { - for (auto& thr : activeThread) - { - auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(thr); - if (thr != 0) - { - if (s_threadToFiber.find(ptr) == s_threadToFiber.end()) - { - __OSLockScheduler(); - __OSCreateHostThread(ptr); - __OSUnlockScheduler(); - } - OSResumeThread(ptr); - } - } - } - void threadEntry(PPCInterpreter_t* hCPU) { OSThread_t* currentThread = coreinitThread_getCurrentThreadDepr(hCPU); @@ -1361,6 +1331,104 @@ namespace coreinit } } + void ci_Thread_Save(MemStreamWriter& s) + { + s.writeData("ci_T_S", 15); + + s.writeBE(g_activeThreadQueue.GetMPTR()); + s.writeBE(g_coreRunQueue.GetMPTR()); + + s.writeBE(activeThreadCount); + for (sint32 i = 0; i < activeThreadCount; i++) + { + s.writeBE(activeThread[i]); + } + for (sint32 i = 0; i < PPC_CORE_COUNT; i++) + { + s.writeBE(memory_getVirtualOffsetFromPointer(__currentCoreThread[i])); + s.writeBE(s_lehmer_lcg[i]); + s.writeBE(s_terminatorThreads[i].terminatorThread.GetMPTR()); + s.writeBE(s_terminatorThreads[i].threadStack.GetMPTR()); + s.writeBE(s_terminatorThreads[i].threadName.GetMPTR()); + s.writeBE(s_terminatorThreads[i].semaphoreQueuedDeallocators.GetMPTR()); + } + s.writeBE(s_defaultThreads.GetMPTR()); + s.writeBE(s_stack.GetMPTR()); + } + + void ci_Thread_Restore(MemStreamReader& s, bool recreate) + { + char section[16] = { '\0' }; + s.readData(section,15); + cemu_assert_debug(strcmp(section, "ci_T_S") == 0); + + g_activeThreadQueue = (OSThreadQueue*)memory_getPointerFromVirtualOffset(s.readBE()); + g_coreRunQueue = (OSThreadQueue*)memory_getPointerFromVirtualOffset(s.readBE()); + + sint32 prevActiveThreadCount = s.readBE(); + for (sint32 i = 0; i < prevActiveThreadCount; i++) + { + MPTR threadMPTR = s.readBE(); + if (recreate) + { + __OSLockScheduler(); + __OSActivateThread((OSThread_t*)memory_getPointerFromVirtualOffset(threadMPTR)); + __OSUnlockScheduler(); + } + else + { + activeThreadCount = prevActiveThreadCount; + activeThread[i] = threadMPTR; + } + } + for (sint32 i = 0; i < PPC_CORE_COUNT; i++) + { + __currentCoreThread[i] = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE()); + s_lehmer_lcg[i] = s.readBE(); + s_terminatorThreads[i].terminatorThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE()); + s_terminatorThreads[i].threadStack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE()); + s_terminatorThreads[i].threadName = (char*)memory_getPointerFromVirtualOffset(s.readBE()); + s_terminatorThreads[i].semaphoreQueuedDeallocators = (OSSemaphore*)memory_getPointerFromVirtualOffset(s.readBE()); + } + s_defaultThreads = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE()); + s_stack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE()); + } + + void SuspendActiveThreads() + { + + for (auto& thr : activeThread) + { + if (thr != MPTR_NULL) + { + auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(thr); + cemuLog_log(LogType::SaveStates, "Before State: {}", ptr->state.value()); + cemuLog_log(LogType::SaveStates, "Before SusCnt: {}", ptr->suspendCounter); + OSSuspendThread(ptr); + cemuLog_log(LogType::SaveStates, "After State: {}", ptr->state.value()); + cemuLog_log(LogType::SaveStates, "After SusCnt: {}", ptr->suspendCounter); + } + } + } + + void ResumeActiveThreads() + { + for (auto& thr : activeThread) + { + if (thr != MPTR_NULL) + { + auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(thr); + if (s_threadToFiber.find(ptr) == s_threadToFiber.end()) + { + __OSLockScheduler(); + __OSCreateHostThread(ptr); + __OSUnlockScheduler(); + } + OSResumeThread(ptr); + } + } + } + void InitializeThread() { cafeExportRegister("coreinit", OSCreateThreadType, LogType::CoreinitThread); diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Thread.h b/src/Cafe/OS/libs/coreinit/coreinit_Thread.h index 74e27d8fc..321ddb3f4 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Thread.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_Thread.h @@ -496,7 +496,16 @@ static_assert(sizeof(OSThread_t) == 0x6A0-4); // todo - determine correct size namespace coreinit { + void ci_Thread_Save(MemStreamWriter& s); + void ci_Thread_Restore(MemStreamReader& s, bool recreate); + void SuspendActiveThreads(); + void ResumeActiveThreads(); + void InitializeThread(); + + void ci_Sync_Save(MemStreamWriter& s); + void ci_Sync_Restore(MemStreamReader& s); + void InitializeConcurrency(); bool __CemuIsMulticoreMode(); @@ -524,8 +533,6 @@ namespace coreinit sint32 __OSResumeThreadInternal(OSThread_t* thread, sint32 resumeCount); sint32 OSResumeThread(OSThread_t* thread); - void SuspendAllThreads(); - void ResumeAllThreads(); void OSContinueThread(OSThread_t* thread); void __OSSuspendThreadInternal(OSThread_t* thread); void __OSSuspendThreadNolock(OSThread_t* thread); diff --git a/src/Cemu/Logging/CemuLogging.h b/src/Cemu/Logging/CemuLogging.h index d55256c9d..fe9f941a4 100644 --- a/src/Cemu/Logging/CemuLogging.h +++ b/src/Cemu/Logging/CemuLogging.h @@ -35,6 +35,8 @@ enum class LogType : sint32 ProcUi = 40, + SaveStates = 50, + APIErrors = 0, // alias for Force. Logs bad parameters or other API errors in OS libs diff --git a/src/Common/SysAllocator.h b/src/Common/SysAllocator.h index 7930a16b3..921409497 100644 --- a/src/Common/SysAllocator.h +++ b/src/Common/SysAllocator.h @@ -56,6 +56,12 @@ class SysAllocator : public SysAllocatorBase m_tempData.insert(m_tempData.begin(), str, str + N); } + SysAllocator& operator=(T* value) + { + m_sysMem = value; + return *this; + } + constexpr uint32 GetCount() const { return count; @@ -165,6 +171,12 @@ class SysAllocator : public SysAllocatorBase return *this; } + SysAllocator& operator=(T* value) + { + m_sysMem = value; + return *this; + } + operator T() { return *GetPtr(); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index d6688ef39..2a7237f24 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -2250,6 +2250,7 @@ void MainWindow::RecreateMenu() debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::Patches), _("&Graphic pack patches"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::Patches)); debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::TextureCache), _("&Texture cache warnings"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::TextureCache)); debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::TextureReadback), _("&Texture readback"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::TextureReadback)); + debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::SaveStates), _("&Save states"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::SaveStates)); debugLoggingMenu->AppendSeparator(); debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::OpenGLLogging), _("&OpenGL debug output"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::OpenGLLogging)); debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::VulkanValidation), _("&Vulkan validation layer (slow)"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::VulkanValidation));