Map mem range as needed; save/restore for coreinit; add logging for save states

This commit is contained in:
Chris Spegal 2023-08-31 19:02:10 -04:00
parent 739b33f733
commit 288c8d9854
41 changed files with 704 additions and 60 deletions

View file

@ -981,7 +981,8 @@ namespace CafeSystem
{ {
if (!sSystemRunning) if (!sSystemRunning)
return; return;
coreinit::SuspendAllThreads(); coreinit::SuspendActiveThreads();
iosu::pdm::Stop();
sSystemRunning = false; sSystemRunning = false;
} }
@ -989,13 +990,14 @@ namespace CafeSystem
{ {
if (sSystemRunning) if (sSystemRunning)
return; return;
coreinit::ResumeAllThreads(); coreinit::ResumeActiveThreads();
iosu::pdm::StartTrackingTime(GetForegroundTitleId());
sSystemRunning = true; sSystemRunning = true;
} }
void SaveState(std::string path) void SaveState(std::string path)
{ {
cemuLog_log(LogType::Force, "[SAVESTATE] Saving state..."); cemuLog_log(LogType::SaveStates, "Saving state...");
MemStreamWriter writer(0); MemStreamWriter writer(0);
// pause game // pause game
PauseTitle(); PauseTitle();
@ -1006,45 +1008,53 @@ namespace CafeSystem
writer.writeData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister)); writer.writeData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister));
writer.writeData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t)); writer.writeData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t));
// cpu // cpu
for (auto& thr : activeThread) ci_Save(writer);
{ coreinit::ci_Alarm_Save(writer);
writer.writeBE(thr); ci_Callbacks_Save(writer);
} coreinit::ci_FS_Save(writer);
// fs ci_Init_Save(writer);
coreinit::FSSave(writer); coreinit::ci_Thread_Save(writer);
iosu::fsa::Save(writer); iosu::fsa::Save(writer);
FileStream* stream = FileStream::createFile(path); FileStream* stream = FileStream::createFile(path);
stream->writeData(writer.getResult().data(), writer.getResult().size_bytes()); stream->writeData(writer.getResult().data(), writer.getResult().size_bytes());
delete stream; delete stream;
cemuLog_log(LogType::Force, "[SAVESTATE] Saved state to {}.", path); cemuLog_log(LogType::SaveStates, "Saved state to {}.", path);
ResumeTitle(/*isThreadRunning*/); ResumeTitle(/*isThreadRunning*/);
} }
void LoadState(std::string path) void LoadState(std::string path)
{ {
PauseTitle(); PauseTitle();
cemuLog_log(LogType::Force, "[SAVESTATE] Loading state...", path); cemuLog_log(LogType::SaveStates, "Loading state...", path);
auto data = FileStream::LoadIntoMemory(path); auto data = FileStream::LoadIntoMemory(path);
assert(data.has_value()); assert(data.has_value());
MemStreamReader reader(data->data(), data->size()); MemStreamReader reader(data->data(), data->size());
bool recreate = false;
if (recreate)
coreinit::__OSDeleteAllActivePPCThreads();
// memory // memory
DestroyMemorySpace();
memory_Deserialize(reader); memory_Deserialize(reader);
// gpu // gpu
reader.readData(LatteGPUState.contextRegister, sizeof(LatteGPUState.contextRegister)); reader.readData(LatteGPUState.contextRegister, sizeof(LatteGPUState.contextRegister));
reader.readData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister)); reader.readData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister));
reader.readData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t)); reader.readData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t));
// cpu // cpu
for (size_t i = 0; i < 256; i++) ci_Restore(reader);
{ coreinit::ci_Alarm_Restore(reader);
activeThread[i] = reader.readBE<uint32>(); ci_Callbacks_Restore(reader);
} coreinit::ci_FS_Restore(reader);
// fs ci_Init_Restore(reader);
coreinit::FSRestore(reader); coreinit::ci_Thread_Restore(reader, recreate);
iosu::fsa::Restore(reader); iosu::fsa::Restore(reader);
cemuLog_log(LogType::Force, "[SAVESTATE] Loaded state from {}.", path); cemuLog_log(LogType::SaveStates, "Loaded state from {}.", path);
ResumeTitle(/*isThreadRunning*/); ResumeTitle(/*isThreadRunning*/);
} }

View file

@ -110,13 +110,16 @@ void MemStreamWriter::writeBE<MMURange>(const MMURange& v)
template <> template <>
void MemStreamReader::readBE<MMURange>(MMURange& mmuRange) void MemStreamReader::readBE<MMURange>(MMURange& mmuRange)
{ {
mmuRange.m_isMapped = readBE<bool>(); bool needsMapped = readBE<bool>();
mmuRange.m_isMapped = false;
mmuRange.baseAddress = readBE<uint32>(); mmuRange.baseAddress = readBE<uint32>();
mmuRange.areaId = (MMU_MEM_AREA_ID)readBE<uint8>(); mmuRange.areaId = (MMU_MEM_AREA_ID)readBE<uint8>();
mmuRange.flags = (MMURange::MFLAG)readBE<uint8>(); mmuRange.flags = (MMURange::MFLAG)readBE<uint8>();
mmuRange.name = readBE<std::string>(); mmuRange.name = readBE<std::string>();
mmuRange.size = readBE<uint32>(); mmuRange.size = readBE<uint32>();
mmuRange.initSize = readBE<uint32>(); mmuRange.initSize = readBE<uint32>();
if (needsMapped)
mmuRange.mapMem();
} }
bool MMURange::deserializeImpl(MemStreamReader& streamReader) bool MMURange::deserializeImpl(MemStreamReader& streamReader)
@ -470,7 +473,6 @@ void memory_createDump()
void memory_Serialize(MemStreamWriter& s) void memory_Serialize(MemStreamWriter& s)
{ {
s.writeBE<uint64>(g_mmuRanges.size());
for (auto& itr : g_mmuRanges) for (auto& itr : g_mmuRanges)
{ {
s.writeBE(*itr); s.writeBE(*itr);
@ -483,7 +485,6 @@ void memory_Serialize(MemStreamWriter& s)
void memory_Deserialize(MemStreamReader& s) void memory_Deserialize(MemStreamReader& s)
{ {
size_t cnt = s.readBE<uint64>();
for (auto& itr : g_mmuRanges) for (auto& itr : g_mmuRanges)
{ {
s.readBE<MMURange>(*itr); s.readBE<MMURange>(*itr);

View file

@ -992,6 +992,8 @@ namespace iosu::fsa
void Save(MemStreamWriter& writer) void Save(MemStreamWriter& writer)
{ {
writer.writeData("iosu_fsa_S", 15);
writer.writeBE(sFSAIoMsgQueue); writer.writeBE(sFSAIoMsgQueue);
for (size_t i = 0; i < 352; i++) for (size_t i = 0; i < 352; i++)
{ {
@ -1003,6 +1005,10 @@ namespace iosu::fsa
void Restore(MemStreamReader& reader) void Restore(MemStreamReader& reader)
{ {
char section[16] = { '\0' };
reader.readData(section, 15);
cemu_assert_debug(strcmp(section, "iosu_fsa_S") == 0);
sFSAIoMsgQueue = reader.readBE<IOSMsgQueueId>(); sFSAIoMsgQueue = reader.readBE<IOSMsgQueueId>();
for (size_t i = 0; i < 352; i++) for (size_t i = 0; i < 352; i++)
{ {

View file

@ -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<MPTR>();
placeholderFontSize = s.readBE<sint32>();
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() void coreinit_load()
{ {
coreinit::InitializeCore(); coreinit::InitializeCore();

View file

@ -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_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 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 // misc
void coreinit_load(); void coreinit_load();
void ci_Save(MemStreamWriter& s);
void ci_Restore(MemStreamReader& s);
// coreinit shared memory // coreinit shared memory
typedef struct typedef struct
@ -35,6 +41,9 @@ extern coreinitData_t* gCoreinitData;
// coreinit init // coreinit init
void coreinit_start(PPCInterpreter_t* hCPU); void coreinit_start(PPCInterpreter_t* hCPU);
void ci_Init_Save(MemStreamWriter& s);
void ci_Init_Restore(MemStreamReader& s);
MPTR OSAllocFromSystem(uint32 size, uint32 alignment); MPTR OSAllocFromSystem(uint32 size, uint32 alignment);
void OSFreeToSystem(MPTR mem); void OSFreeToSystem(MPTR mem);

View file

@ -247,7 +247,7 @@ namespace coreinit
} }
else else
{ {
alarm->nextTime = _swapEndianU64(startTime); alarm->nextTime = _swapEndianU64(nextTime);
alarm->period = 0; alarm->period = 0;
alarm->handler = _swapEndianU32(handlerFunc); alarm->handler = _swapEndianU32(handlerFunc);
} }
@ -305,6 +305,70 @@ namespace coreinit
__OSUnlockScheduler(); __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<MPTR>());
g_alarmThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_g_alarmThreadStack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_g_alarmThreadName = (char*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
uint64 currentTime = coreinit_getOSTime();
uint64_t timeOffset = currentTime - s.readBE<uint64_t>();
size_t alms = s.readBE<size_t>();
for (size_t alm = 0; alm < alms; alm++)
{
OSAlarm_t* alarm = (OSAlarm_t*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
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<uint64>() + timeOffset;
__OSLockScheduler();
g_activeAlarms[alarm] = OSHostAlarmCreate(nextFire, period, __OSHostAlarmTriggered, nullptr);
__OSUnlockScheduler();
}
}
void _OSAlarmThread(PPCInterpreter_t* hCPU) void _OSAlarmThread(PPCInterpreter_t* hCPU)
{ {
while( true ) while( true )

View file

@ -47,6 +47,9 @@ namespace coreinit
void OSAlarm_Shutdown(); void OSAlarm_Shutdown();
void ci_Alarm_Save(MemStreamWriter& s);
void ci_Alarm_Restore(MemStreamReader& s);
void alarm_update(); void alarm_update();
void InitializeAlarm(); void InitializeAlarm();

View file

@ -31,6 +31,19 @@ struct CoreinitAsyncCallback
s_asyncCallbackSpinlock.unlock(); s_asyncCallbackSpinlock.unlock();
} }
static std::vector<struct CoreinitAsyncCallback*>* getPoolPtr()
{
return &s_asyncCallbackPool;
}
static std::vector<struct CoreinitAsyncCallback*>* getQueuePtr()
{
return &s_asyncCallbackQueue;
}
friend void ci_Callbacks_Save(MemStreamWriter& s);
friend void ci_Callbacks_Restore(MemStreamReader& s);
private: private:
void doCall() 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); 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<struct CoreinitAsyncCallback*>* pool = CoreinitAsyncCallback::getPoolPtr();
size_t poolSize = pool->size();
s.writeBE(poolSize);
s.writeData(pool, sizeof(CoreinitAsyncCallback) * poolSize);
std::vector<struct CoreinitAsyncCallback*>* 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<MPTR>());
_g_coreinitCallbackThreadStack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
g_asyncCallbackAsync = (coreinit::OSSemaphore*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_g_coreinitCBThreadName = (char*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
std::vector<struct CoreinitAsyncCallback*>* pool = CoreinitAsyncCallback::getPoolPtr();
size_t poolSize = s.readBE<size_t>();
pool->clear();
pool->resize(poolSize);
s.readData(pool, sizeof(CoreinitAsyncCallback) * poolSize);
std::vector<struct CoreinitAsyncCallback*>* queue = CoreinitAsyncCallback::getPoolPtr();
size_t queueSize = s.readBE<size_t>();
queue->clear();
queue->resize(queueSize);
s.readData(queue, sizeof(CoreinitAsyncCallback) * queueSize);
}
void InitializeAsyncCallback() void InitializeAsyncCallback()
{ {
coreinit::OSInitSemaphore(g_asyncCallbackAsync.GetPtr(), 0); coreinit::OSInitSemaphore(g_asyncCallbackAsync.GetPtr(), 0);

View file

@ -136,6 +136,21 @@ namespace coreinit
return true; 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() void InitializeCodeGen()
{ {
cafeExportRegister("coreinit", OSGetCodegenVirtAddrRange, LogType::Placeholder); cafeExportRegister("coreinit", OSGetCodegenVirtAddrRange, LogType::Placeholder);

View file

@ -6,5 +6,8 @@ namespace coreinit
void codeGenHandleICBI(uint32 ea); void codeGenHandleICBI(uint32 ea);
bool codeGenShouldAvoid(); bool codeGenShouldAvoid();
void ci_CodeGen_Save(MemStreamWriter& s);
void ci_CodeGen_Restore(MemStreamReader& s);
void InitializeCodeGen(); void InitializeCodeGen();
} }

View file

@ -129,6 +129,28 @@ namespace coreinit
return 0; 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<MPTR>();
_osDynLoadFuncFree = s.readBE<MPTR>();
_osDynLoadTLSFuncAlloc = s.readBE<MPTR>();
_osDynLoadTLSFuncFree = s.readBE<MPTR>();
}
void InitializeDynLoad() void InitializeDynLoad()
{ {
cafeExportRegister("coreinit", OSDynLoad_SetAllocator, LogType::Placeholder); cafeExportRegister("coreinit", OSDynLoad_SetAllocator, LogType::Placeholder);

View file

@ -14,5 +14,8 @@ namespace coreinit
void OSDynLoad_Release(uint32 moduleHandle); void OSDynLoad_Release(uint32 moduleHandle);
uint32 OSDynLoad_FindExport(uint32 moduleHandle, uint32 isData, const char* exportName, betype<MPTR>* addrOut); uint32 OSDynLoad_FindExport(uint32 moduleHandle, uint32 isData, const char* exportName, betype<MPTR>* addrOut);
void ci_DynLoad_Save(MemStreamWriter& s);
void ci_DynLoad_Restore(MemStreamReader& s);
void InitializeDynLoad(); void InitializeDynLoad();
} }

View file

@ -191,6 +191,26 @@ namespace coreinit
osLib_returnFromFunction(hCPU, r ? 1 : 0); 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<MPTR>());
fgSaveAreaAddr = memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s.readData(&fgAreaEntries, sizeof(fgAreaEntries) * FG_BUCKET_AREA_COUNT);
}
void InitializeFG() void InitializeFG()
{ {
osLib_addFunction("coreinit", "OSGetForegroundBucket", coreinitExport_OSGetForegroundBucket); osLib_addFunction("coreinit", "OSGetForegroundBucket", coreinitExport_OSGetForegroundBucket);

View file

@ -13,5 +13,8 @@ namespace coreinit
void InitForegroundBucket(); void InitForegroundBucket();
void ci_FG_Save(MemStreamWriter& s);
void ci_FG_Restore(MemStreamReader& s);
void InitializeFG(); void InitializeFG();
} }

View file

@ -2638,14 +2638,38 @@ namespace coreinit
return FSA_RESULT::OK; 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.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)); s.readData(g_fsRegisteredClientBodies, sizeof(FSClientBody_t));
_sdCard01Mounted = s.readBE<bool>();
_mlc01Mounted = s.readBE<bool>();
_tempFSSpace = memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
size_t s_fsa_activeClients_size = s.readBE<size_t>();
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<MPTR>());
s_fsaIpcPoolBuffer = memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s_fsaIpcPoolBufferNumItems = (uint32be*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
} }
void InitializeFS() void InitializeFS()

View file

@ -308,8 +308,8 @@ namespace coreinit
FS_VOLSTATE FSGetVolumeState(FSClient_t* fsClient); FS_VOLSTATE FSGetVolumeState(FSClient_t* fsClient);
void FSSave(MemStreamWriter& s); void ci_FS_Save(MemStreamWriter& s);
void FSRestore(MemStreamReader& s); void ci_FS_Restore(MemStreamReader& s);
void InitializeFS(); void InitializeFS();
}; // namespace coreinit }; // namespace coreinit

View file

@ -258,6 +258,26 @@ namespace coreinit
return memory_getPointerFromVirtualOffset(_swapEndianU32(tlsBlock->addr) + _swapEndianU32(tlsIndex->ukn04)); 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<MPTR>());
_flockMutexArray = (coreinit::OSMutex*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s.readData(_flockMutexMask, sizeof(bool) * GHS_FOPEN_MAX);
}
void InitializeGHS() void InitializeGHS()
{ {
cafeExportRegister("coreinit", __ghs_flock_create, LogType::Placeholder); cafeExportRegister("coreinit", __ghs_flock_create, LogType::Placeholder);

View file

@ -4,5 +4,8 @@ namespace coreinit
{ {
void PrepareGHSRuntime(); void PrepareGHSRuntime();
void ci_GHS_Save(MemStreamWriter& s);
void ci_GHS_Restore(MemStreamReader& s);
void InitializeGHS(); void InitializeGHS();
}; };

View file

@ -462,6 +462,34 @@ namespace coreinit
return r; 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<MPTR>());
s_ipcDriver = (IPCDriver*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
gIPCThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_gIPCThreadStack = memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_gIPCThreadNameStorage = memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
gIPCThreadMsgQueue = (OSMessageQueue*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_gIPCThreadSemaphoreStorage = (OSMessage*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
}
void InitializeIPC() void InitializeIPC()
{ {
for (uint32 i = 0; i < Espresso::CORE_COUNT; i++) 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_Ioctlv, LogType::PPC_IPC);
cafeExportRegister("coreinit", IOS_IoctlvAsync, LogType::PPC_IPC); cafeExportRegister("coreinit", IOS_IoctlvAsync, LogType::PPC_IPC);
} }
}; };

View file

@ -12,5 +12,8 @@ namespace coreinit
IOS_ERROR IOS_Ioctlv(IOSDevHandle devHandle, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec); 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<void> asyncResultFunc, MEMPTR<void> asyncResultUserParam); IOS_ERROR IOS_IoctlvAsync(IOSDevHandle devHandle, uint32 requestId, uint32 numIn, uint32 numOut, IPCIoctlVector* vec, MEMPTR<void> asyncResultFunc, MEMPTR<void> asyncResultUserParam);
void ci_IPC_Save(MemStreamWriter& s);
void ci_IPC_Restore(MemStreamReader& s);
void InitializeIPC(); void InitializeIPC();
}; };

View file

@ -215,3 +215,25 @@ void coreinit_start(PPCInterpreter_t* hCPU)
hCPU->gpr[3] = _coreinitInfo->argc; hCPU->gpr[3] = _coreinitInfo->argc;
hCPU->instructionPointer = _coreinitTitleEntryPoint; 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<sint32>();
g_preinitUserParam = (PreinitUserHeapStruct*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
_coreinitTitleEntryPoint = s.readBE<sint32>();
}

View file

@ -271,6 +271,26 @@ namespace coreinit
osLib_returnFromFunction(hCPU, 0); 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<sint32>();
}
void InitializeLC() void InitializeLC()
{ {
for (sint32 f = 0; f < PPC_CORE_COUNT; f++) for (sint32 f = 0; f < PPC_CORE_COUNT; f++)

View file

@ -2,5 +2,8 @@
namespace coreinit namespace coreinit
{ {
void ci_LockedCache_Save(MemStreamWriter& s);
void ci_LockedCache_Restore(MemStreamReader& s);
void InitializeLC(); void InitializeLC();
} }

View file

@ -630,6 +630,46 @@ namespace coreinit
memset(&g_list3, 0, sizeof(g_list3)); 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<MPTR>();
g_heapTableCount = s.readBE<sint32>();
s.readData(g_heapTable, sizeof(MEMHeapBase) * MEM_MAX_HEAP_TABLE);
g_slockInitialized = s.readBE<bool>();
g_listsInitialized = s.readBE<bool>();
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<MPTR>());
s.readData(&gDefaultHeap, sizeof(MEMHeapBase));
s.readData(&sHeapBaseHandle, sizeof(MEMHeapBase) * 9);
gDefaultHeapAllocator = (MEMAllocatorFunc*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
}
void InitializeMEM() void InitializeMEM()
{ {
MEMResetToDefaultState(); MEMResetToDefaultState();

View file

@ -179,5 +179,8 @@ namespace coreinit
void InitializeMEMUnitHeap(); void InitializeMEMUnitHeap();
void ci_MEM_Save(MemStreamWriter& s);
void ci_MEM_Restore(MemStreamReader& s);
void InitializeMEM(); void InitializeMEM();
} }

View file

@ -16,6 +16,8 @@ namespace coreinit
struct OSVirtMemoryEntry struct OSVirtMemoryEntry
{ {
OSVirtMemoryEntry() : virtualAddress(0), size(0), alignment(0) {};
OSVirtMemoryEntry(MPTR virtualAddress, uint32 size, uint32 alignment) : virtualAddress(virtualAddress), size(size), alignment(alignment) {}; OSVirtMemoryEntry(MPTR virtualAddress, uint32 size, uint32 alignment) : virtualAddress(virtualAddress), size(size), alignment(alignment) {};
MPTR virtualAddress; MPTR virtualAddress;
@ -151,6 +153,27 @@ namespace coreinit
return 1; 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<size_t>();
s_allocatedVirtMemory.clear();
s_allocatedVirtMemory.resize(s_allocatedVirtMemorySize);
s.readData(&s_allocatedVirtMemory, sizeof(OSVirtMemoryEntry) * s_allocatedVirtMemorySize);
}
void InitializeMemoryMapping() void InitializeMemoryMapping()
{ {
s_allocatedVirtMemory.clear(); s_allocatedVirtMemory.clear();

View file

@ -1,5 +1,8 @@
namespace coreinit namespace coreinit
{ {
void ci_MemoryMapping_Save(MemStreamWriter& s);
void ci_MemoryMapping_Restore(MemStreamReader& s);
void InitializeMemoryMapping(); void InitializeMemoryMapping();
} }

View file

@ -117,6 +117,24 @@ namespace coreinit
return g_systemMessageQueue.GetPtr(); 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<MPTR>());
_systemMessageQueueArray = (OSMessage*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
}
void InitializeMessageQueue() void InitializeMessageQueue()
{ {
OSInitMessageQueue(g_systemMessageQueue.GetPtr(), _systemMessageQueueArray.GetPtr(), _systemMessageQueueArray.GetCount()); OSInitMessageQueue(g_systemMessageQueue.GetPtr(), _systemMessageQueueArray.GetPtr(), _systemMessageQueueArray.GetCount());

View file

@ -36,5 +36,8 @@ namespace coreinit
bool OSPeekMessage(OSMessageQueue* msgQueue, OSMessage* msg); bool OSPeekMessage(OSMessageQueue* msgQueue, OSMessage* msg);
sint32 OSSendMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags); sint32 OSSendMessage(OSMessageQueue* msgQueue, OSMessage* msg, uint32 flags);
void ci_MessageQueue_Save(MemStreamWriter& s);
void ci_MessageQueue_Restore(MemStreamReader& s);
void InitializeMessageQueue(); void InitializeMessageQueue();
}; };

View file

@ -25,6 +25,21 @@ namespace coreinit
*areaSize = MEMORY_OVERLAY_AREA_SIZE; *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() void InitializeOverlayArena()
{ {
cafeExportRegister("coreinit", OSIsEnabledOverlayArena, LogType::Placeholder); cafeExportRegister("coreinit", OSIsEnabledOverlayArena, LogType::Placeholder);

View file

@ -1,4 +1,7 @@
namespace coreinit namespace coreinit
{ {
void ci_OverlayArena_Save(MemStreamWriter& s);
void ci_OverlayArena_Restore(MemStreamReader& s);
void InitializeOverlayArena(); void InitializeOverlayArena();
}; };

View file

@ -614,6 +614,22 @@ namespace coreinit
OSWakeupThread(&fastCond->threadQueue); 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<MPTR>());
}
/************* init ************/ /************* init ************/
void InitializeConcurrency() void InitializeConcurrency()

View file

@ -32,6 +32,26 @@ namespace coreinit
_sysHeapFreeCounter = 0; _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<sint32>();
_sysHeapFreeCounter = s.readBE<sint32>();
}
void InitializeSysHeap() void InitializeSysHeap()
{ {
osLib_addFunction("coreinit", "OSAllocFromSystem", export_OSAllocFromSystem); osLib_addFunction("coreinit", "OSAllocFromSystem", export_OSAllocFromSystem);

View file

@ -4,5 +4,8 @@ namespace coreinit
{ {
void InitSysHeap(); void InitSysHeap();
void ci_SysHeap_Save(MemStreamWriter& s);
void ci_SysHeap_Restore(MemStreamReader& s);
void InitializeSysHeap(); void InitializeSysHeap();
} }

View file

@ -10,6 +10,22 @@ namespace coreinit
return *g_system_info.GetPtr(); 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<MPTR>());
}
void InitializeSystemInfo() void InitializeSystemInfo()
{ {
cemu_assert(ppcCyclesSince2000 != 0); cemu_assert(ppcCyclesSince2000 != 0);

View file

@ -16,6 +16,9 @@ namespace coreinit
const OSSystemInfo& OSGetSystemInfo(); const OSSystemInfo& OSGetSystemInfo();
void ci_SystemInfo_Save(MemStreamWriter& s);
void ci_SystemInfo_Restore(MemStreamReader& s);
void InitializeSystemInfo(); void InitializeSystemInfo();
}; };

View file

@ -196,36 +196,6 @@ namespace coreinit
return __currentCoreThread[currentInstance->spr.UPIR]; 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) void threadEntry(PPCInterpreter_t* hCPU)
{ {
OSThread_t* currentThread = coreinitThread_getCurrentThreadDepr(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<MPTR>());
g_coreRunQueue = (OSThreadQueue*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
sint32 prevActiveThreadCount = s.readBE<sint32>();
for (sint32 i = 0; i < prevActiveThreadCount; i++)
{
MPTR threadMPTR = s.readBE<MPTR>();
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<MPTR>());
s_lehmer_lcg[i] = s.readBE<uint32>();
s_terminatorThreads[i].terminatorThread = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s_terminatorThreads[i].threadStack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s_terminatorThreads[i].threadName = (char*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s_terminatorThreads[i].semaphoreQueuedDeallocators = (OSSemaphore*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
}
s_defaultThreads = (OSThread_t*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
s_stack = (uint8*)memory_getPointerFromVirtualOffset(s.readBE<MPTR>());
}
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() void InitializeThread()
{ {
cafeExportRegister("coreinit", OSCreateThreadType, LogType::CoreinitThread); cafeExportRegister("coreinit", OSCreateThreadType, LogType::CoreinitThread);

View file

@ -496,7 +496,16 @@ static_assert(sizeof(OSThread_t) == 0x6A0-4); // todo - determine correct size
namespace coreinit namespace coreinit
{ {
void ci_Thread_Save(MemStreamWriter& s);
void ci_Thread_Restore(MemStreamReader& s, bool recreate);
void SuspendActiveThreads();
void ResumeActiveThreads();
void InitializeThread(); void InitializeThread();
void ci_Sync_Save(MemStreamWriter& s);
void ci_Sync_Restore(MemStreamReader& s);
void InitializeConcurrency(); void InitializeConcurrency();
bool __CemuIsMulticoreMode(); bool __CemuIsMulticoreMode();
@ -524,8 +533,6 @@ namespace coreinit
sint32 __OSResumeThreadInternal(OSThread_t* thread, sint32 resumeCount); sint32 __OSResumeThreadInternal(OSThread_t* thread, sint32 resumeCount);
sint32 OSResumeThread(OSThread_t* thread); sint32 OSResumeThread(OSThread_t* thread);
void SuspendAllThreads();
void ResumeAllThreads();
void OSContinueThread(OSThread_t* thread); void OSContinueThread(OSThread_t* thread);
void __OSSuspendThreadInternal(OSThread_t* thread); void __OSSuspendThreadInternal(OSThread_t* thread);
void __OSSuspendThreadNolock(OSThread_t* thread); void __OSSuspendThreadNolock(OSThread_t* thread);

View file

@ -35,6 +35,8 @@ enum class LogType : sint32
ProcUi = 40, ProcUi = 40,
SaveStates = 50,
APIErrors = 0, // alias for Force. Logs bad parameters or other API errors in OS libs APIErrors = 0, // alias for Force. Logs bad parameters or other API errors in OS libs

View file

@ -56,6 +56,12 @@ public:
m_tempData.insert(m_tempData.begin(), str, str + N); m_tempData.insert(m_tempData.begin(), str, str + N);
} }
SysAllocator& operator=(T* value)
{
m_sysMem = value;
return *this;
}
constexpr uint32 GetCount() const constexpr uint32 GetCount() const
{ {
return count; return count;
@ -165,6 +171,12 @@ public:
return *this; return *this;
} }
SysAllocator& operator=(T* value)
{
m_sysMem = value;
return *this;
}
operator T() operator T()
{ {
return *GetPtr(); return *GetPtr();

View file

@ -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::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::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::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->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::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)); debugLoggingMenu->AppendCheckItem(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + stdx::to_underlying(LogType::VulkanValidation), _("&Vulkan validation layer (slow)"), wxEmptyString)->Check(cemuLog_isLoggingEnabled(LogType::VulkanValidation));