Skip to content

Commit

Permalink
Map mem range as needed; save/restore for coreinit; add logging for s…
Browse files Browse the repository at this point in the history
…ave states
  • Loading branch information
Spegs21 committed Aug 31, 2023
1 parent 739b33f commit 288c8d9
Show file tree
Hide file tree
Showing 41 changed files with 704 additions and 60 deletions.
46 changes: 28 additions & 18 deletions src/Cafe/CafeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,21 +981,23 @@ namespace CafeSystem
{
if (!sSystemRunning)
return;
coreinit::SuspendAllThreads();
coreinit::SuspendActiveThreads();
iosu::pdm::Stop();
sSystemRunning = false;
}

void ResumeTitle()
{
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();
Expand All @@ -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<uint32>();
}
// 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*/);
}
Expand Down
7 changes: 4 additions & 3 deletions src/Cafe/HW/MMU/MMU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,16 @@ void MemStreamWriter::writeBE<MMURange>(const MMURange& v)
template <>
void MemStreamReader::readBE<MMURange>(MMURange& mmuRange)
{
mmuRange.m_isMapped = readBE<bool>();
bool needsMapped = readBE<bool>();
mmuRange.m_isMapped = false;
mmuRange.baseAddress = readBE<uint32>();
mmuRange.areaId = (MMU_MEM_AREA_ID)readBE<uint8>();
mmuRange.flags = (MMURange::MFLAG)readBE<uint8>();
mmuRange.name = readBE<std::string>();
mmuRange.size = readBE<uint32>();
mmuRange.initSize = readBE<uint32>();
if (needsMapped)
mmuRange.mapMem();
}

bool MMURange::deserializeImpl(MemStreamReader& streamReader)
Expand Down Expand Up @@ -470,7 +473,6 @@ void memory_createDump()

void memory_Serialize(MemStreamWriter& s)
{
s.writeBE<uint64>(g_mmuRanges.size());
for (auto& itr : g_mmuRanges)
{
s.writeBE(*itr);
Expand All @@ -483,7 +485,6 @@ void memory_Serialize(MemStreamWriter& s)

void memory_Deserialize(MemStreamReader& s)
{
size_t cnt = s.readBE<uint64>();
for (auto& itr : g_mmuRanges)
{
s.readBE<MMURange>(*itr);
Expand Down
6 changes: 6 additions & 0 deletions src/Cafe/IOSU/fsa/iosu_fsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++)
{
Expand All @@ -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<IOSMsgQueueId>();
for (size_t i = 0; i < 352; i++)
{
Expand Down
50 changes: 50 additions & 0 deletions src/Cafe/OS/libs/coreinit/coreinit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
coreinit::InitializeCore();
Expand Down
9 changes: 9 additions & 0 deletions src/Cafe/OS/libs/coreinit/coreinit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);

Expand Down
66 changes: 65 additions & 1 deletion src/Cafe/OS/libs/coreinit/coreinit_Alarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ namespace coreinit
}
else
{
alarm->nextTime = _swapEndianU64(startTime);
alarm->nextTime = _swapEndianU64(nextTime);
alarm->period = 0;
alarm->handler = _swapEndianU32(handlerFunc);
}
Expand Down Expand Up @@ -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<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)
{
while( true )
Expand Down
3 changes: 3 additions & 0 deletions src/Cafe/OS/libs/coreinit/coreinit_Alarm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
57 changes: 57 additions & 0 deletions src/Cafe/OS/libs/coreinit/coreinit_Callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ struct CoreinitAsyncCallback
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:
void doCall()
{
Expand Down Expand Up @@ -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<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()
{
coreinit::OSInitSemaphore(g_asyncCallbackAsync.GetPtr(), 0);
Expand Down
Loading

0 comments on commit 288c8d9

Please sign in to comment.