mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-02 13:01:18 +12:00
Merge cbfb5c519b
into 35ecfa3f54
This commit is contained in:
commit
d5eda5501c
99 changed files with 2029 additions and 115 deletions
|
@ -68,6 +68,8 @@
|
|||
// dependency to be removed
|
||||
#include "gui/guiWrapper.h"
|
||||
|
||||
#include "Cafe/OS/libs/coreinit/coreinit_FS.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if BOOST_OS_LINUX
|
||||
|
@ -1008,6 +1010,87 @@ namespace CafeSystem
|
|||
sSystemRunning = false;
|
||||
}
|
||||
|
||||
void PauseTitle()
|
||||
{
|
||||
if (!sSystemRunning)
|
||||
return;
|
||||
coreinit::SuspendActiveThreads();
|
||||
iosu::pdm::Stop();
|
||||
sSystemRunning = false;
|
||||
}
|
||||
|
||||
void ResumeTitle()
|
||||
{
|
||||
if (sSystemRunning)
|
||||
return;
|
||||
coreinit::ResumeActiveThreads();
|
||||
iosu::pdm::StartTrackingTime(GetForegroundTitleId());
|
||||
sSystemRunning = true;
|
||||
}
|
||||
|
||||
void SaveState(std::string path)
|
||||
{
|
||||
cemuLog_log(LogType::SaveStates, "Saving state...");
|
||||
MemStreamWriter writer(0);
|
||||
// pause game
|
||||
PauseTitle();
|
||||
// memory
|
||||
memory_Serialize(writer);
|
||||
|
||||
|
||||
nn::temp::save(writer);
|
||||
nn::aoc::save(writer);
|
||||
osLib_save(writer);
|
||||
iosu::kernel::save(writer);
|
||||
iosu::fsa::save(writer);
|
||||
iosu::odm::save(writer);
|
||||
|
||||
// gpu
|
||||
writer.writeData(LatteGPUState.contextRegister, sizeof(LatteGPUState.contextRegister));
|
||||
writer.writeData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister));
|
||||
writer.writeData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t));
|
||||
|
||||
FileStream* stream = FileStream::createFile(path);
|
||||
stream->writeData(writer.getResult().data(), writer.getResult().size_bytes());
|
||||
delete stream;
|
||||
cemuLog_log(LogType::SaveStates, "Saved state to {}.", path);
|
||||
|
||||
ResumeTitle(/*isThreadRunning*/);
|
||||
}
|
||||
|
||||
void LoadState(std::string path)
|
||||
{
|
||||
PauseTitle();
|
||||
//coreinit::__OSDeleteAllActivePPCThreads();
|
||||
DestroyMemorySpace();
|
||||
|
||||
cemuLog_log(LogType::SaveStates, "Loading state...", path);
|
||||
|
||||
auto data = FileStream::LoadIntoMemory(path);
|
||||
assert(data.has_value());
|
||||
MemStreamReader reader(data->data(), data->size());
|
||||
|
||||
// memory
|
||||
|
||||
memory_Deserialize(reader);
|
||||
|
||||
nn::temp::restore(reader);
|
||||
nn::aoc::restore(reader);
|
||||
osLib_restore(reader);
|
||||
iosu::kernel::restore(reader);
|
||||
iosu::fsa::restore(reader);
|
||||
iosu::odm::restore(reader);
|
||||
|
||||
// gpu
|
||||
reader.readData(LatteGPUState.contextRegister, sizeof(LatteGPUState.contextRegister));
|
||||
reader.readData(LatteGPUState.contextRegisterShadowAddr, sizeof(LatteGPUState.contextRegister));
|
||||
reader.readData(LatteGPUState.sharedArea, sizeof(gx2GPUSharedArea_t));
|
||||
|
||||
cemuLog_log(LogType::SaveStates, "Loaded state from {}.", path);
|
||||
|
||||
ResumeTitle(/*isThreadRunning*/);
|
||||
}
|
||||
|
||||
/* Virtual mlc storage */
|
||||
|
||||
void InitVirtualMlcStorage()
|
||||
|
|
|
@ -47,6 +47,12 @@ namespace CafeSystem
|
|||
|
||||
void ShutdownTitle();
|
||||
|
||||
void PauseTitle();
|
||||
void ResumeTitle();
|
||||
|
||||
void SaveState(std::string path);
|
||||
void LoadState(std::string path);
|
||||
|
||||
std::string GetMlcStoragePath(TitleId titleId);
|
||||
void MlcStorageMountAllTitles();
|
||||
|
||||
|
|
|
@ -338,6 +338,8 @@ public:
|
|||
dirIterator->dirEntries.emplace_back(dirEntry);
|
||||
}
|
||||
|
||||
void Save(MemStreamWriter& writer) override;
|
||||
|
||||
private:
|
||||
void PopulateIterationList()
|
||||
{
|
||||
|
@ -733,3 +735,76 @@ void fsc_init()
|
|||
{
|
||||
fsc_reset();
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamWriter::write<FSCVirtualFile::FSCDirIteratorState>(const FSCVirtualFile::FSCDirIteratorState& v)
|
||||
{
|
||||
write(v.index);
|
||||
writePODVector(v.dirEntries);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(FSCVirtualFile::FSCDirIteratorState& v)
|
||||
{
|
||||
read(v.index);
|
||||
readPODVector(v.dirEntries);
|
||||
}
|
||||
|
||||
void FSCVirtualFile::Save(MemStreamWriter& writer)
|
||||
{
|
||||
writer.writeBool(dirIterator != nullptr);
|
||||
if (dirIterator) writer.write(*dirIterator);
|
||||
writer.writeBool(m_isAppend);
|
||||
}
|
||||
|
||||
void FSCVirtualFileDirectoryIterator::Save(MemStreamWriter& writer)
|
||||
{
|
||||
writer.write<uint32>((uint32)Child::DIRECTORY_ITERATOR);
|
||||
writer.write(m_path);
|
||||
writer.write<uint32>(m_folders.size());
|
||||
for (auto& folder : m_folders)
|
||||
{
|
||||
folder->Save(writer);
|
||||
}
|
||||
FSCVirtualFile::Save(writer);
|
||||
}
|
||||
|
||||
#include "Cafe/Filesystem/fscDeviceHostFS.h"
|
||||
|
||||
FSCVirtualFile* FSCVirtualFile::Restore(MemStreamReader& reader)
|
||||
{
|
||||
FSCVirtualFile* file;
|
||||
switch ((Child)reader.read<uint32>())
|
||||
{
|
||||
case Child::DIRECTORY_ITERATOR:
|
||||
{
|
||||
std::string path = reader.read<std::string>();
|
||||
std::vector<FSCVirtualFile*> folders{};
|
||||
size_t size = reader.read<uint32>();
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
folders.push_back(Restore(reader));
|
||||
}
|
||||
file = new FSCVirtualFileDirectoryIterator(path, folders);
|
||||
break;
|
||||
}
|
||||
case Child::HOST:
|
||||
{
|
||||
std::string path = reader.read<std::string>();
|
||||
FSC_ACCESS_FLAG flags = (FSC_ACCESS_FLAG)reader.read<uint32>();
|
||||
sint32 status{};
|
||||
file = FSCVirtualFile_Host::OpenFile(path, flags, status);
|
||||
file->fscSetSeek(reader.read<uint64>());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::exception("Not implemented");
|
||||
}
|
||||
if (reader.readBool())
|
||||
{
|
||||
file->dirIterator = new FSCDirIteratorState;
|
||||
reader.read(*file->dirIterator);
|
||||
}
|
||||
reader.readBool(file->m_isAppend);
|
||||
return file;
|
||||
}
|
|
@ -89,12 +89,20 @@ public:
|
|||
|
||||
struct FSCVirtualFile
|
||||
{
|
||||
enum class Child : uint32
|
||||
{
|
||||
DIRECTORY_ITERATOR, HOST, WUACTX, WUDCTX, NONE
|
||||
};
|
||||
|
||||
struct FSCDirIteratorState
|
||||
{
|
||||
sint32 index;
|
||||
std::vector<FSCDirEntry> dirEntries;
|
||||
};
|
||||
|
||||
virtual void Save(MemStreamWriter& writer);
|
||||
static FSCVirtualFile* Restore(MemStreamReader& reader);
|
||||
|
||||
FSCVirtualFile()
|
||||
{
|
||||
|
||||
|
|
|
@ -191,9 +191,11 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F
|
|||
if (fs)
|
||||
{
|
||||
FSCVirtualFile_Host* vf = new FSCVirtualFile_Host(FSC_TYPE_FILE);
|
||||
vf->m_path.reset(new std::filesystem::path(path));
|
||||
vf->m_fs = fs;
|
||||
vf->m_isWritable = writeAccessRequested;
|
||||
vf->m_fileSize = fs->GetSize();
|
||||
vf->m_accessFlags = accessFlags;
|
||||
fscStatus = FSC_STATUS_OK;
|
||||
return vf;
|
||||
}
|
||||
|
@ -208,6 +210,7 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F
|
|||
{
|
||||
FSCVirtualFile_Host* vf = new FSCVirtualFile_Host(FSC_TYPE_DIRECTORY);
|
||||
vf->m_path.reset(new std::filesystem::path(path));
|
||||
vf->m_accessFlags = accessFlags;
|
||||
fscStatus = FSC_STATUS_OK;
|
||||
return vf;
|
||||
}
|
||||
|
@ -292,4 +295,13 @@ public:
|
|||
bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority)
|
||||
{
|
||||
return fsc_mount(mountPath, hostTargetPath, &fscDeviceHostFSC::instance(), nullptr, priority) == FSC_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void FSCVirtualFile_Host::Save(MemStreamWriter& writer)
|
||||
{
|
||||
writer.write<uint32>((uint32)Child::HOST);
|
||||
writer.write(m_path->string());
|
||||
writer.write((uint32)m_accessFlags);
|
||||
writer.write(m_seek);
|
||||
FSCVirtualFile::Save(writer);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
void fscSetFileLength(uint64 endOffset) override;
|
||||
bool fscDirNext(FSCDirEntry* dirEntry) override;
|
||||
|
||||
void Save(MemStreamWriter& writer) override;
|
||||
|
||||
private:
|
||||
FSCVirtualFile_Host(uint32 type) : m_type(type) {};
|
||||
|
||||
|
@ -31,4 +33,6 @@ private:
|
|||
// directory
|
||||
std::unique_ptr<std::filesystem::path> m_path{};
|
||||
std::unique_ptr<std::filesystem::directory_iterator> m_dirIterator{};
|
||||
// serialization
|
||||
FSC_ACCESS_FLAG m_accessFlags;
|
||||
};
|
|
@ -107,6 +107,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void Save(MemStreamWriter& writer) override
|
||||
{
|
||||
throw std::exception("Not implemented");
|
||||
}
|
||||
|
||||
private:
|
||||
ZArchiveReader* m_archive{nullptr};
|
||||
sint32 m_fscType;
|
||||
|
|
|
@ -108,6 +108,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void Save(MemStreamWriter& writer) override
|
||||
{
|
||||
throw std::exception("Not implemented");
|
||||
}
|
||||
|
||||
private:
|
||||
FSTVolume* m_volume{nullptr};
|
||||
sint32 m_fscType;
|
||||
|
|
|
@ -412,6 +412,57 @@ void memory_createDump()
|
|||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::write(const MMURange& v)
|
||||
{
|
||||
writeBool(v.m_isMapped);
|
||||
write(v.baseAddress);
|
||||
write((uint8)v.areaId);
|
||||
write((uint8)v.flags);
|
||||
write(v.name);
|
||||
write(v.size);
|
||||
write(v.initSize);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(MMURange& v)
|
||||
{
|
||||
bool needsMapped = readBool();
|
||||
v.m_isMapped = false;
|
||||
read(v.baseAddress);
|
||||
v.areaId = (MMU_MEM_AREA_ID)read<uint8>();
|
||||
v.flags = (MMURange::MFLAG)read<uint8>();
|
||||
read(v.name);
|
||||
read(v.size);
|
||||
read(v.initSize);
|
||||
if (needsMapped)
|
||||
v.mapMem();
|
||||
}
|
||||
|
||||
void memory_Serialize(MemStreamWriter& s)
|
||||
{
|
||||
for (auto& itr : g_mmuRanges)
|
||||
{
|
||||
s.write(*itr);
|
||||
if (itr->isMapped())
|
||||
{
|
||||
s.writeData(memory_base + itr->getBase(), itr->getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void memory_Deserialize(MemStreamReader& s)
|
||||
{
|
||||
for (auto& itr : g_mmuRanges)
|
||||
{
|
||||
s.read(*itr);
|
||||
if (itr->isMapped())
|
||||
{
|
||||
s.readData(memory_base + itr->getBase(), itr->getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace MMU
|
||||
{
|
||||
// MMIO access handler
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/helpers/Serializer.h"
|
||||
|
||||
void memory_init();
|
||||
void memory_mapForCurrentTitle();
|
||||
void memory_unmapForCurrentTitle();
|
||||
|
@ -108,14 +110,16 @@ struct MMURange
|
|||
bool isOptional() const { return (flags & MFLAG::FLAG_OPTIONAL) != 0; };
|
||||
bool isMappedEarly() const { return (flags & MFLAG::FLAG_MAP_EARLY) != 0; };
|
||||
|
||||
const uint32 baseAddress;
|
||||
const uint32 initSize; // initial size
|
||||
const std::string name;
|
||||
const MFLAG flags;
|
||||
const MMU_MEM_AREA_ID areaId;
|
||||
uint32 baseAddress;
|
||||
uint32 initSize; // initial size
|
||||
std::string name;
|
||||
MFLAG flags;
|
||||
MMU_MEM_AREA_ID areaId;
|
||||
// runtime parameters
|
||||
uint32 size;
|
||||
bool m_isMapped{};
|
||||
friend class MemStreamWriter;
|
||||
friend class MemStreamReader;
|
||||
};
|
||||
|
||||
|
||||
|
@ -203,6 +207,9 @@ uint8 memory_readU8(uint32 address);
|
|||
|
||||
void memory_createDump();
|
||||
|
||||
void memory_Serialize(MemStreamWriter& s);
|
||||
void memory_Deserialize(MemStreamReader& s);
|
||||
|
||||
template<size_t count>
|
||||
void memory_readBytes(VAddr address, std::array<uint8, count>& buffer)
|
||||
{
|
||||
|
|
|
@ -135,6 +135,26 @@ namespace iosu
|
|||
s_threadInitialized = false;
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("iosu_odm");
|
||||
s.writeAtomic(s_requestStop);
|
||||
s.writeAtomic(s_isRunning);
|
||||
s.writeAtomic(s_threadInitialized);
|
||||
s.write(s_msgQueueId);
|
||||
s.writeMPTR(_s_msgBuffer);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("iosu_odm");
|
||||
s.readAtomic(s_requestStop);
|
||||
s.readAtomic(s_isRunning);
|
||||
s.readAtomic(s_threadInitialized);
|
||||
s.read(s_msgQueueId);
|
||||
s.readMPTR(_s_msgBuffer);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
if (s_isRunning.exchange(true))
|
||||
|
|
|
@ -4,6 +4,9 @@ namespace iosu
|
|||
{
|
||||
namespace odm
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
}
|
||||
|
|
|
@ -409,6 +409,15 @@ namespace iosu
|
|||
}
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
|
||||
}
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class : public ::IOSUModule
|
||||
{
|
||||
void PDMLoadAll()
|
||||
|
|
|
@ -5,6 +5,9 @@ namespace iosu
|
|||
{
|
||||
namespace pdm
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
inline constexpr size_t NUM_PLAY_STATS_ENTRIES = 256;
|
||||
inline constexpr size_t NUM_PLAY_DIARY_ENTRIES_MAX = 18250; // 0x474A
|
||||
|
||||
|
|
|
@ -36,7 +36,9 @@ namespace iosu
|
|||
}
|
||||
};
|
||||
|
||||
std::array<FSAClient, 624> sFSAClientArray;
|
||||
static constexpr int const sFSAClientArraySize = 624;
|
||||
|
||||
std::array<FSAClient, sFSAClientArraySize> sFSAClientArray;
|
||||
|
||||
IOS_ERROR FSAAllocateClient(sint32& indexOut)
|
||||
{
|
||||
|
@ -169,6 +171,8 @@ namespace iosu
|
|||
}
|
||||
|
||||
class _FSAHandleTable {
|
||||
friend class MemStreamWriter;
|
||||
friend class MemStreamReader;
|
||||
struct _FSAHandleResource
|
||||
{
|
||||
bool isAllocated{false};
|
||||
|
@ -227,9 +231,10 @@ namespace iosu
|
|||
return it.fscFile;
|
||||
}
|
||||
|
||||
static constexpr int const m_handleTableSize = 0x3C0;
|
||||
private:
|
||||
uint32 m_currentCounter = 1;
|
||||
std::array<_FSAHandleResource, 0x3C0> m_handleTable;
|
||||
std::array<_FSAHandleResource, m_handleTableSize> m_handleTable;
|
||||
};
|
||||
|
||||
_FSAHandleTable sFileHandleTable;
|
||||
|
@ -904,3 +909,85 @@ namespace iosu
|
|||
}
|
||||
} // namespace fsa
|
||||
} // namespace iosu
|
||||
|
||||
template <>
|
||||
void MemStreamWriter::write(const iosu::fsa::FSAClient& v)
|
||||
{
|
||||
write(v.workingDirectory);
|
||||
writeBool(v.isAllocated);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(iosu::fsa::FSAClient& v)
|
||||
{
|
||||
read(v.workingDirectory);
|
||||
readBool(v.isAllocated);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamWriter::write(const iosu::fsa::_FSAHandleTable& v)
|
||||
{
|
||||
write(v.m_currentCounter);
|
||||
for (sint32 i = 0; i < v.m_handleTable.size(); i++)
|
||||
{
|
||||
write(v.m_handleTable[i].handleCheckValue);
|
||||
writeBool(v.m_handleTable[i].isAllocated);
|
||||
|
||||
writeBool(v.m_handleTable[i].fscFile != nullptr);
|
||||
if (v.m_handleTable[i].fscFile != nullptr) v.m_handleTable[i].fscFile->Save(*this);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(iosu::fsa::_FSAHandleTable& v)
|
||||
{
|
||||
read(v.m_currentCounter);
|
||||
for (sint32 i = 0; i < v.m_handleTable.size(); i++)
|
||||
{
|
||||
read(v.m_handleTable[i].handleCheckValue);
|
||||
readBool(v.m_handleTable[i].isAllocated);
|
||||
|
||||
if (readBool())
|
||||
{
|
||||
v.m_handleTable[i].fscFile = FSCVirtualFile::Restore(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.m_handleTable[i].fscFile = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace iosu
|
||||
{
|
||||
namespace fsa
|
||||
{
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("iosu_fsa");
|
||||
s.write(sFSAIoMsgQueue);
|
||||
s.writeMPTR(_m_sFSAIoMsgQueueMsgBuffer);
|
||||
|
||||
for (sint32 i = 0; i < sFSAClientArraySize; i++)
|
||||
{
|
||||
s.write(sFSAClientArray[i]);
|
||||
}
|
||||
s.write(sDirHandleTable);
|
||||
s.write(sFileHandleTable);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("iosu_fsa");
|
||||
s.read(sFSAIoMsgQueue);
|
||||
s.readMPTR(_m_sFSAIoMsgQueueMsgBuffer);
|
||||
|
||||
for (sint32 i = 0; i < sFSAClientArraySize; i++)
|
||||
{
|
||||
s.read(sFSAClientArray[i]);
|
||||
}
|
||||
s.read(sDirHandleTable);
|
||||
s.read(sFileHandleTable);
|
||||
}
|
||||
} // namespace fsa
|
||||
} // namespace iosu
|
|
@ -213,5 +213,8 @@ namespace iosu
|
|||
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
|
||||
void save(MemStreamWriter& writer);
|
||||
void restore(MemStreamReader& reader);
|
||||
} // namespace fsa
|
||||
} // namespace iosu
|
||||
|
|
|
@ -379,11 +379,13 @@ namespace iosu
|
|||
|
||||
/* IPC */
|
||||
|
||||
static constexpr size_t IOCTLV_VECTOR_ARRAY_SIZE = 8;
|
||||
|
||||
struct IOSDispatchableCommand
|
||||
{
|
||||
// stores a copy of incoming IPC requests with some extra information required for replies
|
||||
IPCCommandBody body; // our dispatchable copy
|
||||
IPCIoctlVector vecCopy[8]; // our copy of the Ioctlv vector array
|
||||
IPCIoctlVector vecCopy[IOCTLV_VECTOR_ARRAY_SIZE]; // our copy of the Ioctlv vector array
|
||||
IPCCommandBody* originalBody; // the original command that was sent to us
|
||||
uint32 ppcCoreIndex;
|
||||
IOSDevHandle replyHandle; // handle for outgoing replies
|
||||
|
@ -775,6 +777,131 @@ namespace iosu
|
|||
return static_cast<IOSUModule*>(&sIOSUModuleKernel);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamWriter::write(const iosu::kernel::IOSMessageQueue& v)
|
||||
{
|
||||
write(v.ukn00);
|
||||
write(v.ukn04);
|
||||
write(v.numQueuedMessages);
|
||||
write(v.readIndex);
|
||||
write(v.msgArraySize);
|
||||
writeMPTR(v.msgArray);
|
||||
write(v.queueHandle);
|
||||
write(v.ukn1C);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(iosu::kernel::IOSMessageQueue& v)
|
||||
{
|
||||
read(v.ukn00);
|
||||
read(v.ukn04);
|
||||
read(v.numQueuedMessages);
|
||||
read(v.readIndex);
|
||||
read(v.msgArraySize);
|
||||
readMPTR(v.msgArray);
|
||||
read(v.queueHandle);
|
||||
read(v.ukn1C);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamWriter::write(const iosu::kernel::IOSResourceManager& v)
|
||||
{
|
||||
writeBool(v.isSet);
|
||||
write(v.path);
|
||||
write(v.msgQueueId);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(iosu::kernel::IOSResourceManager& v)
|
||||
{
|
||||
readBool(v.isSet);
|
||||
read(v.path);
|
||||
read(v.msgQueueId);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamWriter::write(const iosu::kernel::IPCActiveDeviceHandle& v)
|
||||
{
|
||||
writeBool(v.isSet);
|
||||
write(v.handleCheckValue);
|
||||
write(v.path);
|
||||
write(v.msgQueueId);
|
||||
writeBool(v.hasDispatchTargetHandle);
|
||||
write(v.dispatchTargetHandle);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(iosu::kernel::IPCActiveDeviceHandle& v)
|
||||
{
|
||||
readBool(v.isSet);
|
||||
read(v.handleCheckValue);
|
||||
read(v.path);
|
||||
read(v.msgQueueId);
|
||||
readBool(v.hasDispatchTargetHandle);
|
||||
read(v.dispatchTargetHandle);
|
||||
}
|
||||
|
||||
namespace iosu
|
||||
{
|
||||
namespace kernel
|
||||
{
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.write<uint32>(sMsgQueuePool.size());
|
||||
for (const auto& i : sMsgQueuePool)
|
||||
s.write(i);
|
||||
|
||||
s.write<uint32>(sDeviceResources.size());
|
||||
for (const auto& i : sDeviceResources)
|
||||
s.write(i);
|
||||
|
||||
s.writeMPTR(sIPCDispatchableCommandPool);
|
||||
|
||||
size_t sIPCFreeDispatchableCommandsSize = sIPCFreeDispatchableCommands.size();
|
||||
s.write<uint32>(sIPCFreeDispatchableCommandsSize);
|
||||
while (sIPCFreeDispatchableCommandsSize)
|
||||
{
|
||||
IOSDispatchableCommand* front = sIPCFreeDispatchableCommands.front();
|
||||
sIPCFreeDispatchableCommands.pop();
|
||||
s.writePTR(front);
|
||||
sIPCFreeDispatchableCommands.push(front);
|
||||
sIPCFreeDispatchableCommandsSize--;
|
||||
}
|
||||
|
||||
s.write<uint32>(MAX_NUM_ACTIVE_DEV_HANDLES);
|
||||
for (uint32 i = 0; i < MAX_NUM_ACTIVE_DEV_HANDLES; i++)
|
||||
s.write(sActiveDeviceHandles[i]);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
cemu_assert(s.read<uint32>() == sMsgQueuePool.size());
|
||||
for (auto& i : sMsgQueuePool)
|
||||
s.read(i);
|
||||
|
||||
cemu_assert(s.read<uint32>() == sDeviceResources.size());
|
||||
for (auto& i : sDeviceResources)
|
||||
s.read(i);
|
||||
|
||||
s.readMPTR(sIPCDispatchableCommandPool);
|
||||
|
||||
size_t sIPCFreeDispatchableCommandsSize = s.read<uint32>();
|
||||
cemu_assert(sIPCFreeDispatchableCommandsSize == sIPCFreeDispatchableCommands.size());
|
||||
while (!sIPCFreeDispatchableCommands.empty())
|
||||
sIPCFreeDispatchableCommands.pop();
|
||||
for (uint32 i = 0; i < sIPCFreeDispatchableCommandsSize; i++)
|
||||
{
|
||||
IOSDispatchableCommand* cmd = nullptr;
|
||||
s.readPTR(cmd);
|
||||
sIPCFreeDispatchableCommands.push(cmd);
|
||||
}
|
||||
|
||||
cemu_assert(s.read<uint32>() == MAX_NUM_ACTIVE_DEV_HANDLES);
|
||||
for (uint32 i = 0; i < MAX_NUM_ACTIVE_DEV_HANDLES; i++)
|
||||
s.read(sActiveDeviceHandles[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,5 +24,8 @@ namespace iosu
|
|||
void IPCSubmitFromCOS(uint32 ppcCoreIndex, IPCCommandBody* cmd);
|
||||
|
||||
IOSUModule* GetModule();
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
}
|
||||
}
|
|
@ -187,6 +187,47 @@ void osLib_returnFromFunction64(PPCInterpreter_t* hCPU, uint64 returnValue64)
|
|||
hCPU->instructionPointer = hCPU->spr.LR;
|
||||
}
|
||||
|
||||
void osLib_save(MemStreamWriter& s)
|
||||
{
|
||||
coreinit_save(s);
|
||||
dmae_save(s);
|
||||
padscore::save(s);
|
||||
nnAct_save(s);
|
||||
nn::acp::save(s);
|
||||
nnBoss_save(s);
|
||||
nn::nfp::save(s);
|
||||
nnUds_save(s);
|
||||
nn::ndm::save(s);
|
||||
nn::save::save(s);
|
||||
nsysnet_save(s);
|
||||
nn::fp::save(s);
|
||||
nn::olv::save(s);
|
||||
nlibcurl::save(s);
|
||||
nsyshid::save(s);
|
||||
camera::save(s);
|
||||
proc_ui::save(s);
|
||||
}
|
||||
void osLib_restore(MemStreamReader& s)
|
||||
{
|
||||
coreinit_restore(s);
|
||||
dmae_restore(s);
|
||||
padscore::restore(s);
|
||||
nnAct_restore(s);
|
||||
nn::acp::restore(s);
|
||||
nnBoss_restore(s);
|
||||
nn::nfp::restore(s);
|
||||
nnUds_restore(s);
|
||||
nn::ndm::restore(s);
|
||||
nn::save::restore(s);
|
||||
nsysnet_restore(s);
|
||||
nn::fp::restore(s);
|
||||
nn::olv::restore(s);
|
||||
nlibcurl::restore(s);
|
||||
nsyshid::restore(s);
|
||||
camera::restore(s);
|
||||
proc_ui::restore(s);
|
||||
}
|
||||
|
||||
void osLib_load()
|
||||
{
|
||||
// load HLE modules
|
||||
|
|
|
@ -6,6 +6,9 @@ struct PPCInterpreter_t;
|
|||
#define OSLIB_FUNCTIONTABLE_TYPE_FUNCTION (1)
|
||||
#define OSLIB_FUNCTIONTABLE_TYPE_POINTER (2)
|
||||
|
||||
void osLib_save(MemStreamWriter& s);
|
||||
void osLib_restore(MemStreamReader& s);
|
||||
|
||||
void osLib_load();
|
||||
void osLib_generateHashFromName(const char* name, uint32* hashA, uint32* hashB);
|
||||
sint32 osLib_getFunctionIndex(const char* libraryName, const char* functionName);
|
||||
|
|
|
@ -242,6 +242,29 @@ namespace camera
|
|||
g_cameraCounter = 0;
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("camera");
|
||||
|
||||
s.writePODVector(g_table_cameraHandles);
|
||||
s.writePODVector(g_activeCameraInstances);
|
||||
s.writeAtomic(g_cameraCounter);
|
||||
s.writeMPTR(g_alarm_camera);
|
||||
s.writeMPTR(g_cameraHandlerParam);
|
||||
}
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("camera");
|
||||
|
||||
std::unique_lock<std::recursive_mutex> _lock(g_mutex_camera);
|
||||
|
||||
s.readPODVector(g_table_cameraHandles);
|
||||
s.readPODVector(g_activeCameraInstances);
|
||||
s.readAtomic(g_cameraCounter);
|
||||
s.readMPTR(g_alarm_camera);
|
||||
s.readMPTR(g_cameraHandlerParam);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
reset();
|
||||
|
@ -253,5 +276,4 @@ namespace camera
|
|||
cafeExportRegister("camera", CAMClose, LogType::Placeholder);
|
||||
cafeExportRegister("camera", CAMSubmitTargetSurface, LogType::Placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,5 +6,8 @@ namespace camera
|
|||
sint32 CAMOpen(sint32 camHandle);
|
||||
sint32 CAMClose(sint32 camHandle);
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
};
|
|
@ -303,6 +303,60 @@ namespace coreinit
|
|||
}
|
||||
};
|
||||
|
||||
void coreinit_save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit");
|
||||
s.writeNullableData(gCoreinitData, sizeof(coreinitData_t));
|
||||
s.write(placeholderFont);
|
||||
s.write(placeholderFontSize);
|
||||
|
||||
coreinit_Init_Save(s);
|
||||
coreinit::SysHeap_Save(s);
|
||||
coreinit::Thread_Save(s);
|
||||
coreinit::MEM_Save(s);
|
||||
coreinit::FG_Save(s);
|
||||
coreinit::OverlayArena_Save(s);
|
||||
coreinit::DynLoad_Save(s);
|
||||
coreinit::GHS_Save(s);
|
||||
coreinit::LockedCache_Save(s);
|
||||
coreinit::Alarm_Save(s);
|
||||
coreinit::FS_Save(s);
|
||||
coreinit::SystemInfo_Save(s);
|
||||
coreinit::Synchronization_Save(s);
|
||||
coreinit::MessageQueue_Save(s);
|
||||
coreinit::IPC_Save(s);
|
||||
coreinit::MemoryMapping_Save(s);
|
||||
coreinit::CodeGen_Save(s);
|
||||
coreinit_Callbacks_Save(s);
|
||||
}
|
||||
|
||||
void coreinit_restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit");
|
||||
s.readNullableData(gCoreinitData, sizeof(coreinitData_t));
|
||||
s.read(placeholderFont);
|
||||
s.read(placeholderFontSize);
|
||||
|
||||
coreinit_Init_Restore(s);
|
||||
coreinit::SysHeap_Restore(s);
|
||||
coreinit::Thread_Restore(s);
|
||||
coreinit::MEM_Restore(s);
|
||||
coreinit::FG_Restore(s);
|
||||
coreinit::OverlayArena_Restore(s);
|
||||
coreinit::DynLoad_Restore(s);
|
||||
coreinit::GHS_Restore(s);
|
||||
coreinit::LockedCache_Restore(s);
|
||||
coreinit::Alarm_Restore(s);
|
||||
coreinit::FS_Restore(s);
|
||||
coreinit::SystemInfo_Restore(s);
|
||||
coreinit::Synchronization_Restore(s);
|
||||
coreinit::MessageQueue_Restore(s);
|
||||
coreinit::IPC_Restore(s);
|
||||
coreinit::MemoryMapping_Restore(s);
|
||||
coreinit::CodeGen_Restore(s);
|
||||
coreinit_Callbacks_Restore(s);
|
||||
}
|
||||
|
||||
void coreinit_load()
|
||||
{
|
||||
coreinit::InitializeCore();
|
||||
|
|
|
@ -11,8 +11,14 @@ 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 coreinit_Callbacks_Save(MemStreamWriter& s);
|
||||
void coreinit_Callbacks_Restore(MemStreamReader& s);
|
||||
|
||||
// misc
|
||||
|
||||
void coreinit_save(MemStreamWriter& s);
|
||||
void coreinit_restore(MemStreamReader& s);
|
||||
|
||||
void coreinit_load();
|
||||
|
||||
// coreinit shared memory
|
||||
|
@ -32,6 +38,9 @@ extern CoreinitSharedData* gCoreinitData;
|
|||
// coreinit init
|
||||
void coreinit_start(PPCInterpreter_t* hCPU);
|
||||
|
||||
void coreinit_Init_Save(MemStreamWriter& s);
|
||||
void coreinit_Init_Restore(MemStreamReader& s);
|
||||
|
||||
MPTR OSAllocFromSystem(uint32 size, uint32 alignment);
|
||||
void OSFreeToSystem(MPTR mem);
|
||||
|
||||
|
|
|
@ -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,68 @@ namespace coreinit
|
|||
__OSUnlockScheduler();
|
||||
}
|
||||
|
||||
void Alarm_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_Alarm");
|
||||
|
||||
s.writeMPTR(g_alarmEvent);
|
||||
s.writeMPTR(g_alarmThread);
|
||||
s.writeMPTR(_g_alarmThreadStack);
|
||||
s.writeMPTR(_g_alarmThreadName);
|
||||
|
||||
s.write(coreinit_getOSTime());
|
||||
|
||||
s.write((uint64)g_activeAlarms.size());
|
||||
for (auto& itr : g_activeAlarms)
|
||||
{
|
||||
s.write(memory_getVirtualOffsetFromPointer(itr.first));
|
||||
s.write(itr.second->getNextFire());
|
||||
}
|
||||
}
|
||||
|
||||
void Alarm_Restore(MemStreamReader& s)
|
||||
{
|
||||
OSAlarm_Shutdown();
|
||||
|
||||
s.readSection("coreinit_Alarm");
|
||||
|
||||
s.readMPTR(g_alarmEvent);
|
||||
s.readMPTR(g_alarmThread);
|
||||
s.readMPTR(_g_alarmThreadStack);
|
||||
s.readMPTR(_g_alarmThreadName);
|
||||
|
||||
uint64 currentTime = coreinit_getOSTime();
|
||||
uint64_t timeOffset = currentTime - s.read<uint64_t>();
|
||||
|
||||
size_t alms = s.read<uint64>();
|
||||
for (size_t alm = 0; alm < alms; alm++)
|
||||
{
|
||||
OSAlarm_t* alarm = (OSAlarm_t*)memory_getPointerFromVirtualOffset(s.read<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.read<uint64>() + timeOffset;
|
||||
__OSLockScheduler();
|
||||
g_activeAlarms[alarm] = OSHostAlarmCreate(nextFire, period, __OSHostAlarmTriggered, nullptr);
|
||||
__OSUnlockScheduler();
|
||||
}
|
||||
}
|
||||
|
||||
void _OSAlarmThread(PPCInterpreter_t* hCPU)
|
||||
{
|
||||
while( true )
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace coreinit
|
|||
|
||||
void OSAlarm_Shutdown();
|
||||
|
||||
void Alarm_Save(MemStreamWriter& s);
|
||||
void Alarm_Restore(MemStreamReader& s);
|
||||
|
||||
void alarm_update();
|
||||
|
||||
void InitializeAlarm();
|
||||
|
|
|
@ -31,6 +31,19 @@ struct CoreinitAsyncCallback
|
|||
s_asyncCallbackSpinlock.unlock();
|
||||
}
|
||||
|
||||
static std::vector<struct CoreinitAsyncCallback*>& getPool()
|
||||
{
|
||||
return s_asyncCallbackPool;
|
||||
}
|
||||
|
||||
static std::vector<struct CoreinitAsyncCallback*>& getQueue()
|
||||
{
|
||||
return s_asyncCallbackQueue;
|
||||
}
|
||||
|
||||
friend void ci_Callbacks_Save(MemStreamWriter& s);
|
||||
friend void ci_Callbacks_Restore(MemStreamReader& s);
|
||||
|
||||
private:
|
||||
void doCall()
|
||||
{
|
||||
|
@ -104,6 +117,28 @@ void coreinitAsyncCallback_add(MPTR functionMPTR, uint32 numParameters, uint32 r
|
|||
coreinitAsyncCallback_addWithLock(functionMPTR, numParameters, r3, r4, r5, r6, r7, r8, r9, r10);
|
||||
}
|
||||
|
||||
void coreinit_Callbacks_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_Callbacks");
|
||||
s.writeMPTR(g_coreinitCallbackThread);
|
||||
s.writeMPTR(_g_coreinitCallbackThreadStack);
|
||||
s.writeMPTR(g_asyncCallbackAsync);
|
||||
s.writeMPTR(_g_coreinitCBThreadName);
|
||||
s.writePODVector(CoreinitAsyncCallback::getPool());
|
||||
s.writePODVector(CoreinitAsyncCallback::getQueue());
|
||||
}
|
||||
|
||||
void coreinit_Callbacks_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_Callbacks");
|
||||
s.readMPTR(g_coreinitCallbackThread);
|
||||
s.readMPTR(_g_coreinitCallbackThreadStack);
|
||||
s.readMPTR(g_asyncCallbackAsync);
|
||||
s.readMPTR(_g_coreinitCBThreadName);
|
||||
s.readPODVector(CoreinitAsyncCallback::getPool());
|
||||
s.readPODVector(CoreinitAsyncCallback::getQueue());
|
||||
}
|
||||
|
||||
void InitializeAsyncCallback()
|
||||
{
|
||||
coreinit::OSInitSemaphore(g_asyncCallbackAsync.GetPtr(), 0);
|
||||
|
|
|
@ -25,9 +25,10 @@ namespace coreinit
|
|||
}
|
||||
}
|
||||
|
||||
static constexpr uint32 const codegenSize = 0x01000000; // todo: Read from cos.xml
|
||||
|
||||
void OSGetCodegenVirtAddrRange(betype<uint32>* rangeStart, betype<uint32>* rangeSize)
|
||||
{
|
||||
uint32 codegenSize = 0x01000000; // todo: Read from cos.xml
|
||||
//debug_printf("OSGetCodegenVirtAddrRange(0x%08x,0x%08x)\n", hCPU->gpr[3], hCPU->gpr[4]);
|
||||
// on first call, allocate range
|
||||
if( coreinitCodeGen.rangeIsAllocated == false )
|
||||
|
@ -136,6 +137,26 @@ namespace coreinit
|
|||
return true;
|
||||
}
|
||||
|
||||
void CodeGen_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_CodeGen");
|
||||
s.writeBool(coreinitCodeGen.rangeIsAllocated);
|
||||
s.write(coreinitCodeGen.rangeStart);
|
||||
s.write(coreinitCodeGen.rangeSize);
|
||||
s.write(codegenSize);
|
||||
s.writeNullableData(coreinitCodeGen.cacheStateCopy, codegenSize);
|
||||
}
|
||||
|
||||
void CodeGen_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_CodeGen");
|
||||
s.readBool(coreinitCodeGen.rangeIsAllocated);
|
||||
s.read(coreinitCodeGen.rangeStart);
|
||||
s.read(coreinitCodeGen.rangeSize);
|
||||
cemu_assert(s.read<uint32>() == codegenSize);
|
||||
s.readNullableData(coreinitCodeGen.cacheStateCopy, codegenSize);
|
||||
}
|
||||
|
||||
void InitializeCodeGen()
|
||||
{
|
||||
cafeExportRegister("coreinit", OSGetCodegenVirtAddrRange, LogType::Placeholder);
|
||||
|
|
|
@ -6,5 +6,8 @@ namespace coreinit
|
|||
void codeGenHandleICBI(uint32 ea);
|
||||
bool codeGenShouldAvoid();
|
||||
|
||||
void CodeGen_Save(MemStreamWriter& s);
|
||||
void CodeGen_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeCodeGen();
|
||||
}
|
|
@ -131,6 +131,24 @@ namespace coreinit
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DynLoad_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_DynLoad");
|
||||
s.write(_osDynLoadFuncAlloc);
|
||||
s.write(_osDynLoadFuncFree);
|
||||
s.write(_osDynLoadTLSFuncAlloc);
|
||||
s.write(_osDynLoadTLSFuncFree);
|
||||
}
|
||||
|
||||
void DynLoad_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_DynLoad");
|
||||
s.read(_osDynLoadFuncAlloc);
|
||||
s.read(_osDynLoadFuncFree);
|
||||
s.read(_osDynLoadTLSFuncAlloc);
|
||||
s.read(_osDynLoadTLSFuncFree);
|
||||
}
|
||||
|
||||
void InitializeDynLoad()
|
||||
{
|
||||
cafeExportRegister("coreinit", OSDynLoad_SetAllocator, LogType::Placeholder);
|
||||
|
|
|
@ -20,5 +20,8 @@ namespace coreinit
|
|||
void OSDynLoad_Release(uint32 moduleHandle);
|
||||
uint32 OSDynLoad_FindExport(uint32 moduleHandle, uint32 isData, const char* exportName, betype<MPTR>* addrOut);
|
||||
|
||||
void DynLoad_Save(MemStreamWriter& s);
|
||||
void DynLoad_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeDynLoad();
|
||||
}
|
|
@ -181,6 +181,22 @@ namespace coreinit
|
|||
osLib_returnFromFunction(hCPU, r ? 1 : 0);
|
||||
}
|
||||
|
||||
void FG_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_FG");
|
||||
s.writeMPTR(fgAddr);
|
||||
s.writeMPTR(fgSaveAreaAddr);
|
||||
s.writeData(&fgAreaEntries, sizeof(fgAreaEntries) * FG_BUCKET_AREA_COUNT);
|
||||
}
|
||||
|
||||
void FG_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_FG");
|
||||
s.readMPTR(fgAddr);
|
||||
s.readMPTR(fgSaveAreaAddr);
|
||||
s.readData(&fgAreaEntries, sizeof(fgAreaEntries) * FG_BUCKET_AREA_COUNT);
|
||||
}
|
||||
|
||||
void InitializeFG()
|
||||
{
|
||||
osLib_addFunction("coreinit", "OSGetForegroundBucket", coreinitExport_OSGetForegroundBucket);
|
||||
|
|
|
@ -13,5 +13,8 @@ namespace coreinit
|
|||
|
||||
void InitForegroundBucket();
|
||||
|
||||
void FG_Save(MemStreamWriter& s);
|
||||
void FG_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeFG();
|
||||
}
|
|
@ -2645,6 +2645,32 @@ namespace coreinit
|
|||
return FSA_RESULT::OK;
|
||||
}
|
||||
|
||||
void FS_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_FS");
|
||||
s.writePTR(g_fsRegisteredClientBodies);
|
||||
s.writeBool(_sdCard01Mounted);
|
||||
s.writeBool(_mlc01Mounted);
|
||||
s.writeMPTR(_tempFSSpace);
|
||||
s.writePODVector(s_fsa_activeClients);
|
||||
s.writeMPTR(s_fsaIpcPool);
|
||||
s.writeMPTR(s_fsaIpcPoolBuffer);
|
||||
s.writeMPTR(s_fsaIpcPoolBufferNumItems);
|
||||
}
|
||||
|
||||
void FS_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_FS");
|
||||
s.readPTR(g_fsRegisteredClientBodies);
|
||||
s.readBool(_sdCard01Mounted);
|
||||
s.readBool(_mlc01Mounted);
|
||||
s.readMPTR(_tempFSSpace);
|
||||
s.readPODVector(s_fsa_activeClients);
|
||||
s.readMPTR(s_fsaIpcPool);
|
||||
s.readMPTR(s_fsaIpcPoolBuffer);
|
||||
s.readMPTR(s_fsaIpcPoolBufferNumItems);
|
||||
}
|
||||
|
||||
void InitializeFS()
|
||||
{
|
||||
OSInitMutex(&s_fsGlobalMutex);
|
||||
|
|
|
@ -298,5 +298,8 @@ namespace coreinit
|
|||
|
||||
FS_VOLSTATE FSGetVolumeState(FSClient_t* fsClient);
|
||||
|
||||
void FS_Save(MemStreamWriter& s);
|
||||
void FS_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeFS();
|
||||
}; // namespace coreinit
|
||||
|
|
|
@ -268,6 +268,24 @@ namespace coreinit
|
|||
return memory_getPointerFromVirtualOffset(_swapEndianU32(tlsBlock->addr) + _swapEndianU32(tlsIndex->ukn04));
|
||||
}
|
||||
|
||||
void GHS_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_GHS");
|
||||
s.writeMPTR(g_ghs_data);
|
||||
s.writeMPTR(_flockMutexArray);
|
||||
s.writeData(reinterpret_cast<uint8*>(_flockMutexMask), sizeof(uint8) * GHS_FOPEN_MAX);
|
||||
}
|
||||
|
||||
void GHS_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_GHS");
|
||||
s.readMPTR(g_ghs_data);
|
||||
s.readMPTR(_flockMutexArray);
|
||||
uint8 _flockMutexMaskTmp[GHS_FOPEN_MAX] = { 0 };
|
||||
s.readData(_flockMutexMaskTmp, sizeof(uint8) * GHS_FOPEN_MAX);
|
||||
memcpy(_flockMutexMask, reinterpret_cast<bool*>(_flockMutexMaskTmp), sizeof(bool) * GHS_FOPEN_MAX);
|
||||
}
|
||||
|
||||
void InitializeGHS()
|
||||
{
|
||||
cafeExportRegister("coreinit", __ghs_flock_create, LogType::Placeholder);
|
||||
|
|
|
@ -8,5 +8,8 @@ namespace coreinit
|
|||
void __gh_set_errno(sint32 errNo);
|
||||
sint32 __gh_get_errno();
|
||||
|
||||
void GHS_Save(MemStreamWriter& s);
|
||||
void GHS_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeGHS();
|
||||
};
|
|
@ -445,6 +445,30 @@ namespace coreinit
|
|||
return r;
|
||||
}
|
||||
|
||||
void IPC_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_IPC");
|
||||
s.writeMPTR(s_ipcResourceBuffers);
|
||||
s.writeMPTR(s_ipcDriver);
|
||||
s.writeMPTR(gIPCThread);
|
||||
s.writeMPTR(_gIPCThreadStack);
|
||||
s.writeMPTR(_gIPCThreadNameStorage);
|
||||
s.writeMPTR(gIPCThreadMsgQueue);
|
||||
s.writeMPTR(_gIPCThreadSemaphoreStorage);
|
||||
}
|
||||
|
||||
void IPC_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_IPC");
|
||||
s.readMPTR(s_ipcResourceBuffers);
|
||||
s.readMPTR(s_ipcDriver);
|
||||
s.readMPTR(gIPCThread);
|
||||
s.readMPTR(_gIPCThreadStack);
|
||||
s.readMPTR(_gIPCThreadNameStorage);
|
||||
s.readMPTR(gIPCThreadMsgQueue);
|
||||
s.readMPTR(_gIPCThreadSemaphoreStorage);
|
||||
}
|
||||
|
||||
void InitializeIPC()
|
||||
{
|
||||
for (uint32 i = 0; i < Espresso::CORE_COUNT; i++)
|
||||
|
@ -461,5 +485,4 @@ namespace coreinit
|
|||
cafeExportRegister("coreinit", IOS_Ioctlv, LogType::PPC_IPC);
|
||||
cafeExportRegister("coreinit", IOS_IoctlvAsync, LogType::PPC_IPC);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -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<void> asyncResultFunc, MEMPTR<void> asyncResultUserParam);
|
||||
|
||||
void IPC_Save(MemStreamWriter& s);
|
||||
void IPC_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeIPC();
|
||||
};
|
|
@ -216,3 +216,21 @@ void coreinit_start(PPCInterpreter_t* hCPU)
|
|||
hCPU->gpr[3] = _coreinitInfo->argc;
|
||||
hCPU->instructionPointer = _coreinitTitleEntryPoint;
|
||||
}
|
||||
|
||||
void coreinit_Init_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_Init");
|
||||
s.writeNullableData(_coreinitInfo, sizeof(coreinitInit_t));
|
||||
s.write(argStorageIndex);
|
||||
s.writeMPTR(g_preinitUserParam);
|
||||
s.write(_coreinitTitleEntryPoint);
|
||||
}
|
||||
|
||||
void coreinit_Init_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_Init");
|
||||
s.readNullableData(_coreinitInfo, sizeof(coreinitInit_t));
|
||||
s.read(argStorageIndex);
|
||||
s.readMPTR(g_preinitUserParam);
|
||||
s.read(_coreinitTitleEntryPoint);
|
||||
}
|
|
@ -271,6 +271,22 @@ namespace coreinit
|
|||
osLib_returnFromFunction(hCPU, 0);
|
||||
}
|
||||
|
||||
void LockedCache_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_LockedCache");
|
||||
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.write(_lcDisableErrorCounter);
|
||||
}
|
||||
|
||||
void LockedCache_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_LockedCache");
|
||||
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);
|
||||
s.read(_lcDisableErrorCounter);
|
||||
}
|
||||
|
||||
void InitializeLC()
|
||||
{
|
||||
for (sint32 f = 0; f < PPC_CORE_COUNT; f++)
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
|
||||
namespace coreinit
|
||||
{
|
||||
void LockedCache_Save(MemStreamWriter& s);
|
||||
void LockedCache_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeLC();
|
||||
}
|
|
@ -630,6 +630,42 @@ namespace coreinit
|
|||
memset(&g_list3, 0, sizeof(g_list3));
|
||||
}
|
||||
|
||||
void MEM_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_MEM");
|
||||
s.write(sysAreaAllocatorOffset);
|
||||
s.write(g_heapTableCount);
|
||||
s.writeData(g_heapTable, sizeof(MEMHeapBase) * MEM_MAX_HEAP_TABLE);
|
||||
s.writeBool(g_slockInitialized);
|
||||
s.writeBool(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.writeMPTR(gHeapGlobalLock);
|
||||
s.writeData(&gDefaultHeap, sizeof(MEMHeapBase));
|
||||
s.writeData(&sHeapBaseHandle, sizeof(MEMHeapBase) * 9);
|
||||
s.writeMPTR(gDefaultHeapAllocator);
|
||||
}
|
||||
|
||||
void MEM_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_MEM");
|
||||
s.read(sysAreaAllocatorOffset);
|
||||
s.read(g_heapTableCount);
|
||||
s.readData(g_heapTable, sizeof(MEMHeapBase) * MEM_MAX_HEAP_TABLE);
|
||||
s.readBool(g_slockInitialized);
|
||||
s.readBool(g_listsInitialized);
|
||||
s.readData(&g_list1, sizeof(MEMList));
|
||||
s.readData(&g_list2, sizeof(MEMList));
|
||||
s.readData(&g_list3, sizeof(MEMList));
|
||||
s.readData(&gHeapFillValues, sizeof(uint32) * 3);
|
||||
s.readMPTR(gHeapGlobalLock);
|
||||
s.readData(&gDefaultHeap, sizeof(MEMHeapBase));
|
||||
s.readData(&sHeapBaseHandle, sizeof(MEMHeapBase) * 9);
|
||||
s.readMPTR(gDefaultHeapAllocator);
|
||||
}
|
||||
|
||||
void InitializeMEM()
|
||||
{
|
||||
MEMResetToDefaultState();
|
||||
|
|
|
@ -179,5 +179,8 @@ namespace coreinit
|
|||
|
||||
void InitializeMEMUnitHeap();
|
||||
|
||||
void MEM_Save(MemStreamWriter& s);
|
||||
void MEM_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeMEM();
|
||||
}
|
||||
|
|
|
@ -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,30 @@ namespace coreinit
|
|||
return 1;
|
||||
}
|
||||
|
||||
void MemoryMapping_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_MemoryMapping");
|
||||
s.write<uint32>(s_allocatedVirtMemory.size());
|
||||
for (auto i : s_allocatedVirtMemory)
|
||||
{
|
||||
s.write(i.virtualAddress);
|
||||
s.write(i.size);
|
||||
s.write(i.alignment);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryMapping_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_MemoryMapping");
|
||||
uint32 s_allocatedVirtMemorySize = s.read<uint32>();
|
||||
s_allocatedVirtMemory.clear();
|
||||
s_allocatedVirtMemory.reserve(s_allocatedVirtMemorySize);
|
||||
for (sint32 i = 0; i < s_allocatedVirtMemorySize; i++)
|
||||
{
|
||||
s_allocatedVirtMemory.emplace_back(s.read<MPTR>(), s.read<uint32>(), s.read<uint32>());
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeMemoryMapping()
|
||||
{
|
||||
s_allocatedVirtMemory.clear();
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
|
||||
namespace coreinit
|
||||
{
|
||||
void MemoryMapping_Save(MemStreamWriter& s);
|
||||
void MemoryMapping_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeMemoryMapping();
|
||||
}
|
||||
|
|
|
@ -124,6 +124,20 @@ namespace coreinit
|
|||
return g_systemMessageQueue.GetPtr();
|
||||
}
|
||||
|
||||
void MessageQueue_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_MessageQueue");
|
||||
s.writeMPTR(g_systemMessageQueue);
|
||||
s.writeMPTR(_systemMessageQueueArray);
|
||||
}
|
||||
|
||||
void MessageQueue_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_MessageQueue");
|
||||
s.readMPTR(g_systemMessageQueue);
|
||||
s.readMPTR(_systemMessageQueueArray);
|
||||
}
|
||||
|
||||
void InitializeMessageQueue()
|
||||
{
|
||||
OSInitMessageQueue(g_systemMessageQueue.GetPtr(), _systemMessageQueueArray.GetPtr(), _systemMessageQueueArray.GetCount());
|
||||
|
|
|
@ -47,5 +47,8 @@ namespace coreinit
|
|||
|
||||
OSMessageQueue* OSGetSystemMessageQueue();
|
||||
|
||||
void MessageQueue_Save(MemStreamWriter& s);
|
||||
void MessageQueue_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeMessageQueue();
|
||||
};
|
|
@ -25,6 +25,17 @@ namespace coreinit
|
|||
*areaSize = MEMORY_OVERLAY_AREA_SIZE;
|
||||
}
|
||||
|
||||
void OverlayArena_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_OverlayArena");
|
||||
s.writeBool(g_coreinitOverlayArena.isEnabled);
|
||||
}
|
||||
void OverlayArena_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_OverlayArena");
|
||||
s.readBool(g_coreinitOverlayArena.isEnabled);
|
||||
}
|
||||
|
||||
void InitializeOverlayArena()
|
||||
{
|
||||
cafeExportRegister("coreinit", OSIsEnabledOverlayArena, LogType::Placeholder);
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace coreinit
|
||||
{
|
||||
void OverlayArena_Save(MemStreamWriter& s);
|
||||
void OverlayArena_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeOverlayArena();
|
||||
};
|
|
@ -612,6 +612,18 @@ namespace coreinit
|
|||
OSWakeupThread(&fastCond->threadQueue);
|
||||
}
|
||||
|
||||
void Synchronization_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_Synchronization");
|
||||
s.writeMPTR(g_rendezvousEvent);
|
||||
}
|
||||
|
||||
void Synchronization_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_Synchronization");
|
||||
s.readMPTR(g_rendezvousEvent);
|
||||
}
|
||||
|
||||
/************* init ************/
|
||||
|
||||
void InitializeConcurrency()
|
||||
|
|
|
@ -29,6 +29,22 @@ namespace coreinit
|
|||
_sysHeapFreeCounter = 0;
|
||||
}
|
||||
|
||||
void SysHeap_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_SysHeap");
|
||||
s.writePTR(_sysHeapHandle);
|
||||
s.write(_sysHeapAllocCounter);
|
||||
s.write(_sysHeapFreeCounter);
|
||||
}
|
||||
|
||||
void SysHeap_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_SysHeap");
|
||||
s.readPTR(_sysHeapHandle);
|
||||
s.read(_sysHeapAllocCounter);
|
||||
s.read(_sysHeapFreeCounter);
|
||||
}
|
||||
|
||||
void InitializeSysHeap()
|
||||
{
|
||||
cafeExportRegister("h264", OSAllocFromSystem, LogType::CoreinitMem);
|
||||
|
|
|
@ -7,5 +7,8 @@ namespace coreinit
|
|||
void* OSAllocFromSystem(uint32 size, uint32 alignment);
|
||||
void OSFreeToSystem(void* ptr);
|
||||
|
||||
void SysHeap_Save(MemStreamWriter& s);
|
||||
void SysHeap_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeSysHeap();
|
||||
}
|
|
@ -10,6 +10,18 @@ namespace coreinit
|
|||
return *g_system_info.GetPtr();
|
||||
}
|
||||
|
||||
void SystemInfo_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_SysInfo");
|
||||
s.writeMPTR(g_system_info);
|
||||
}
|
||||
|
||||
void SystemInfo_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_SysInfo");
|
||||
s.readMPTR(g_system_info);
|
||||
}
|
||||
|
||||
void InitializeSystemInfo()
|
||||
{
|
||||
cemu_assert(ppcCyclesSince2000 != 0);
|
||||
|
|
|
@ -15,7 +15,10 @@ namespace coreinit
|
|||
static_assert(sizeof(OSSystemInfo) == 0x20);
|
||||
|
||||
const OSSystemInfo& OSGetSystemInfo();
|
||||
|
||||
|
||||
void SystemInfo_Save(MemStreamWriter& s);
|
||||
void SystemInfo_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeSystemInfo();
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "util/Fiber/Fiber.h"
|
||||
|
||||
#include "util/helpers/helpers.h"
|
||||
#include "Common/FileStream.h"
|
||||
|
||||
SlimRWLock srwlock_activeThreadList;
|
||||
|
||||
|
@ -1564,6 +1565,133 @@ namespace coreinit
|
|||
}
|
||||
}
|
||||
|
||||
void DumpActiveThreads(std::string v)
|
||||
{
|
||||
for (auto& thr : activeThread)
|
||||
{
|
||||
if (thr != MPTR_NULL)
|
||||
{
|
||||
auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(thr);
|
||||
MemStreamWriter writer(0);
|
||||
writer.writeData(ptr, sizeof(OSThread_t));
|
||||
FileStream* stream = FileStream::createFile(std::to_string(thr) + "_" + v + ".bin");
|
||||
stream->writeData(writer.getResult().data(), writer.getResult().size_bytes());
|
||||
delete stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Thread_Save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("coreinit_Thread");
|
||||
|
||||
s.writeAtomic(sSchedulerActive);
|
||||
s.writeMPTR(g_activeThreadQueue);
|
||||
s.writeMPTR(g_coreRunQueue);
|
||||
|
||||
s.write(activeThreadCount);
|
||||
for (sint32 i = 0; i < activeThreadCount; i++)
|
||||
{
|
||||
s.write(activeThread[i]);
|
||||
auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(activeThread[i]);
|
||||
//s.write((uint8)ptr->state.value());
|
||||
}
|
||||
for (sint32 i = 0; i < PPC_CORE_COUNT; i++)
|
||||
{
|
||||
s.writePTR(__currentCoreThread[i]);
|
||||
s.write(s_lehmer_lcg[i]);
|
||||
s.writeMPTR(s_terminatorThreads[i].terminatorThread);
|
||||
s.writeMPTR(s_terminatorThreads[i].threadStack);
|
||||
s.writeMPTR(s_terminatorThreads[i].threadName);
|
||||
s.writeMPTR(s_terminatorThreads[i].semaphoreQueuedDeallocators);
|
||||
s.writeMPTR(_defaultThreadName[i]);
|
||||
}
|
||||
s.writeMPTR(s_defaultThreads);
|
||||
s.writeMPTR(s_stack);
|
||||
|
||||
DumpActiveThreads("save");
|
||||
}
|
||||
|
||||
void Thread_Restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("coreinit_Thread");
|
||||
|
||||
s.readAtomic(sSchedulerActive);
|
||||
s.readMPTR(g_activeThreadQueue);
|
||||
s.readMPTR(g_coreRunQueue);
|
||||
|
||||
bool recreate = false;
|
||||
|
||||
sint32 prevActiveThreadCount = s.read<sint32>();
|
||||
for (sint32 i = 0; i < prevActiveThreadCount; i++)
|
||||
{
|
||||
MPTR threadMPTR = s.read<MPTR>();
|
||||
if (recreate)
|
||||
{
|
||||
auto* ptr = (OSThread_t*)memory_getPointerFromVirtualOffset(threadMPTR);
|
||||
|
||||
__OSLockScheduler();
|
||||
__OSActivateThread(ptr);
|
||||
__OSUnlockScheduler();
|
||||
//ptr->state = betype((OSThread_t::THREAD_STATE)s.read<uint8>());
|
||||
}
|
||||
else
|
||||
{
|
||||
activeThreadCount = prevActiveThreadCount;
|
||||
activeThread[i] = threadMPTR;
|
||||
}
|
||||
}
|
||||
for (sint32 i = 0; i < PPC_CORE_COUNT; i++)
|
||||
{
|
||||
s.readPTR(__currentCoreThread[i]);
|
||||
s.read(s_lehmer_lcg[i]);
|
||||
s.readMPTR(s_terminatorThreads[i].terminatorThread);
|
||||
s.readMPTR(s_terminatorThreads[i].threadStack);
|
||||
s.readMPTR(s_terminatorThreads[i].threadName);
|
||||
s.readMPTR(s_terminatorThreads[i].semaphoreQueuedDeallocators);
|
||||
s.readMPTR(_defaultThreadName[i]);
|
||||
}
|
||||
s.readMPTR(s_defaultThreads);
|
||||
s.readMPTR(s_stack);
|
||||
|
||||
DumpActiveThreads("restore");
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -503,7 +503,16 @@ static_assert(sizeof(OSThread_t) == 0x6A0);
|
|||
|
||||
namespace coreinit
|
||||
{
|
||||
void Thread_Save(MemStreamWriter& s);
|
||||
void Thread_Restore(MemStreamReader& s);
|
||||
void SuspendActiveThreads();
|
||||
void ResumeActiveThreads();
|
||||
|
||||
void InitializeThread();
|
||||
|
||||
void Synchronization_Save(MemStreamWriter& s);
|
||||
void Synchronization_Restore(MemStreamReader& s);
|
||||
|
||||
void InitializeConcurrency();
|
||||
|
||||
bool __CemuIsMulticoreMode();
|
||||
|
|
|
@ -118,6 +118,17 @@ void dmaeExport_DMAEGetRetiredTimeStamp(PPCInterpreter_t* hCPU)
|
|||
osLib_returnFromFunction64(hCPU, dmaeRetiredTimestamp);
|
||||
}
|
||||
|
||||
void dmae_save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("dmae");
|
||||
s.write(dmaeRetiredTimestamp);
|
||||
}
|
||||
|
||||
void dmae_restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("dmae");
|
||||
s.read(dmaeRetiredTimestamp);
|
||||
}
|
||||
|
||||
void dmae_load()
|
||||
{
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
void dmae_save(MemStreamWriter& s);
|
||||
void dmae_restore(MemStreamReader& s);
|
||||
|
||||
void dmae_load();
|
|
@ -1503,6 +1503,29 @@ CURLcode curl_global_init_mem(uint32 flags, MEMPTR<curl_malloc_callback> malloc_
|
|||
return result;
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nlibcurl");
|
||||
s.write(g_nlibcurl.initialized);
|
||||
s.writeMPTR(g_nlibcurl.proxyConfig);
|
||||
s.writeMPTR(g_nlibcurl.malloc);
|
||||
s.writeMPTR(g_nlibcurl.free);
|
||||
s.writeMPTR(g_nlibcurl.realloc);
|
||||
s.writeMPTR(g_nlibcurl.strdup);
|
||||
s.writeMPTR(g_nlibcurl.calloc);
|
||||
}
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nlibcurl");
|
||||
s.read(g_nlibcurl.initialized);
|
||||
s.readMPTR(g_nlibcurl.proxyConfig);
|
||||
s.readMPTR(g_nlibcurl.malloc);
|
||||
s.readMPTR(g_nlibcurl.free);
|
||||
s.readMPTR(g_nlibcurl.realloc);
|
||||
s.readMPTR(g_nlibcurl.strdup);
|
||||
s.readMPTR(g_nlibcurl.calloc);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
cafeExportRegister("nlibcurl", curl_global_init_mem, LogType::nlibcurl);
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
|
||||
namespace nlibcurl
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
}
|
|
@ -335,6 +335,18 @@ namespace acp
|
|||
osLib_returnFromFunction(hCPU, 0);
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_acp");
|
||||
s.writeBool(sSaveDirMounted);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_acp");
|
||||
s.readBool(sSaveDirMounted);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
cafeExportRegister("nn_acp", ACPCheckApplicationDeviceEmulation, LogType::Placeholder);
|
||||
|
|
|
@ -18,6 +18,9 @@ namespace acp
|
|||
ACPStatus ACPCreateSaveDir(uint32 persistentId, iosu::acp::ACPDeviceType type);
|
||||
ACPStatus ACPUpdateSaveTimeStamp(uint32 persistentId, uint64 titleId, iosu::acp::ACPDeviceType deviceType);
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -683,6 +683,19 @@ void nnActExport_AcquirePrincipalIdByAccountId(PPCInterpreter_t* hCPU)
|
|||
osLib_returnFromFunction(hCPU, result);
|
||||
}
|
||||
|
||||
void nnAct_save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_act");
|
||||
s.write(nn::act::g_initializeCount);
|
||||
s.write((uint32)g_isParentalControlCheckEnabled);
|
||||
}
|
||||
void nnAct_restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_act");
|
||||
s.read(nn::act::g_initializeCount);
|
||||
g_isParentalControlCheckEnabled = s.read<uint32>();
|
||||
}
|
||||
|
||||
// register account functions
|
||||
void nnAct_load()
|
||||
{
|
||||
|
|
|
@ -33,4 +33,7 @@ namespace act
|
|||
}
|
||||
}
|
||||
|
||||
void nnAct_save(MemStreamWriter& s);
|
||||
void nnAct_restore(MemStreamReader& s);
|
||||
|
||||
void nnAct_load();
|
|
@ -149,6 +149,30 @@ namespace nn
|
|||
return AOC_RESULT::ERROR_OK;
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_aoc");
|
||||
s.write<uint32>(sAocCache.size());
|
||||
for (auto i : sAocCache)
|
||||
{
|
||||
s.write(i.aocTitleId);
|
||||
}
|
||||
s.writeBool(sAocCacheGenerated);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_aoc");
|
||||
uint32 sAocCacheSize = s.read<uint32>();
|
||||
sAocCache.clear();
|
||||
sAocCache.reserve(sAocCacheSize);
|
||||
for (sint32 i = 0; i < sAocCacheSize; i++)
|
||||
{
|
||||
sAocCache.emplace_back(s.read<uint64>());
|
||||
}
|
||||
s.readBool(sAocCacheGenerated);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
cafeExportRegister("nn_aoc", AOC_CalculateWorkBufferSize, LogType::NN_AOC);
|
||||
|
|
|
@ -2,6 +2,9 @@ namespace nn
|
|||
{
|
||||
namespace aoc
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void Initialize();
|
||||
}
|
||||
}
|
|
@ -1617,6 +1617,22 @@ bossBufferVector->buffer = (uint8*)bossRequest;
|
|||
|
||||
}
|
||||
}
|
||||
void nnBoss_save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_boss");
|
||||
s.writeMPTR(nn::boss::g_mutex);
|
||||
s.write(nn::boss::g_initCounter);
|
||||
s.writeBool(nn::boss::g_isInitialized);
|
||||
}
|
||||
|
||||
void nnBoss_restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_boss");
|
||||
s.readMPTR(nn::boss::g_mutex);
|
||||
s.read(nn::boss::g_initCounter);
|
||||
s.readBool(nn::boss::g_isInitialized);
|
||||
}
|
||||
|
||||
void nnBoss_load()
|
||||
{
|
||||
OSInitMutexEx(&nn::boss::g_mutex, nullptr);
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
void nnBoss_save(MemStreamWriter& s);
|
||||
void nnBoss_restore(MemStreamReader& s);
|
||||
|
||||
void nnBoss_load();
|
|
@ -758,6 +758,20 @@ namespace nn
|
|||
return ipcCtx->SubmitAsync(std::move(ipcCtx), funcPtr, customParam);
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_fp");
|
||||
s.writeBool(g_fp.isAdminMode);
|
||||
s.writeBool(g_fp.isInitialized);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_fp");
|
||||
s.readBool(g_fp.isAdminMode);
|
||||
s.readBool(g_fp.isInitialized);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
g_fp.initCounter = 0;
|
||||
|
|
|
@ -3,6 +3,9 @@ namespace nn
|
|||
{
|
||||
namespace fp
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
}
|
||||
}
|
|
@ -74,6 +74,20 @@ namespace nn
|
|||
return BUILD_NN_RESULT(NN_RESULT_LEVEL_SUCCESS, NN_RESULT_MODULE_NN_NDM, 0);
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_ndm");
|
||||
s.writeData(s_daemonStatus, sizeof(DAEMON_STATUS) * NUM_DAEMONS);
|
||||
s.write(s_initializeRefCount);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_ndm");
|
||||
s.readData(s_daemonStatus, sizeof(DAEMON_STATUS) * NUM_DAEMONS);
|
||||
s.read(s_initializeRefCount);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
for(size_t i=0; i<NUM_DAEMONS; i++)
|
||||
|
|
|
@ -2,6 +2,9 @@ namespace nn
|
|||
{
|
||||
namespace ndm
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1040,6 +1040,50 @@ namespace nn::nfp
|
|||
osLib_addFunction("nn_nfp", "GetAmiiboSettingsArgs__Q2_2nn3nfpFPQ3_2nn3nfp18AmiiboSettingsArgs", nnNfpExport_GetAmiiboSettingsArgs);
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_nfp");
|
||||
s.writeBool(nfp_data.nfpIsInitialized);
|
||||
s.write(nfp_data.activateEvent);
|
||||
s.write(nfp_data.deactivateEvent);
|
||||
s.writeBool(nfp_data.isDetecting);
|
||||
s.writeBool(nfp_data.isMounted);
|
||||
s.writeBool(nfp_data.isReadOnly);
|
||||
s.writeBool(nfp_data.hasOpenApplicationArea);
|
||||
s.writeBool(nfp_data.hasActiveAmiibo);
|
||||
|
||||
s.writeBool(nfp_data.hasInvalidHMAC);
|
||||
s.write(nfp_data.amiiboTouchTime);
|
||||
s.write<uint32>(sizeof(AmiiboRawNFCData));
|
||||
s.writeData(&nfp_data.amiiboNFCData, sizeof(AmiiboRawNFCData));
|
||||
s.write<uint32>(sizeof(AmiiboInternal));
|
||||
s.writeData(&nfp_data.amiiboInternal, sizeof(AmiiboInternal));
|
||||
s.write<uint32>(sizeof(AmiiboProcessedData));
|
||||
s.writeData(&nfp_data.amiiboProcessedData, sizeof(AmiiboProcessedData));
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_nfp");
|
||||
s.readBool(nfp_data.nfpIsInitialized);
|
||||
s.read(nfp_data.activateEvent);
|
||||
s.read(nfp_data.deactivateEvent);
|
||||
s.readBool(nfp_data.isDetecting);
|
||||
s.readBool(nfp_data.isMounted);
|
||||
s.readBool(nfp_data.isReadOnly);
|
||||
s.readBool(nfp_data.hasOpenApplicationArea);
|
||||
s.readBool(nfp_data.hasActiveAmiibo);
|
||||
|
||||
s.readBool(nfp_data.hasInvalidHMAC);
|
||||
s.read(nfp_data.amiiboTouchTime);
|
||||
cemu_assert(s.read<uint32>() == sizeof(AmiiboRawNFCData));
|
||||
s.readData(&nfp_data.amiiboNFCData, sizeof(AmiiboRawNFCData));
|
||||
cemu_assert(s.read<uint32>() == sizeof(AmiiboInternal));
|
||||
s.readData(&nfp_data.amiiboInternal, sizeof(AmiiboInternal));
|
||||
cemu_assert(s.read<uint32>() == sizeof(AmiiboProcessedData));
|
||||
s.readData(&nfp_data.amiiboProcessedData, sizeof(AmiiboProcessedData));
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
nnNfp_load(); // legacy interface, update these to use cafeExportRegister / cafeExportRegisterFunc
|
||||
|
|
|
@ -4,6 +4,9 @@ namespace nn::nfp
|
|||
{
|
||||
uint32 NFCGetTagInfo(uint32 index, uint32 timeout, MPTR functionPtr, void* userParam);
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
}
|
||||
|
||||
|
|
|
@ -111,6 +111,44 @@ namespace nn
|
|||
|
||||
static_assert(GetErrorCodeImpl(0xa119c600) == 1155004);
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_olv");
|
||||
s.writeMPTR(s_OlvReleaseBgThread);
|
||||
s.writeMPTR(s_OlvReleaseBgThreadStack);
|
||||
s.writeMPTR(s_OlvReleaseBgThreadName);
|
||||
s.write<uint32>(sizeof(ParamPackStorage));
|
||||
s.writeData(&g_ParamPack, sizeof(ParamPackStorage));
|
||||
s.write<uint32>(sizeof(DiscoveryResultStorage));
|
||||
s.writeData(&g_DiscoveryResults, sizeof(DiscoveryResultStorage));
|
||||
s.write(g_ReportTypes);
|
||||
s.writeBool(g_IsInitialized);
|
||||
s.writeBool(g_IsOnlineMode);
|
||||
s.writeBool(g_IsOfflineDBMode);
|
||||
s.writeBool(OfflineDB_Initialized());
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_olv");
|
||||
s.readMPTR(s_OlvReleaseBgThread);
|
||||
s.readMPTR(s_OlvReleaseBgThreadStack);
|
||||
s.readMPTR(s_OlvReleaseBgThreadName);
|
||||
cemu_assert(s.read<uint32>() == sizeof(ParamPackStorage));
|
||||
s.readData(&g_ParamPack, sizeof(ParamPackStorage));
|
||||
cemu_assert(s.read<uint32>() == sizeof(DiscoveryResultStorage));
|
||||
s.readData(&g_DiscoveryResults, sizeof(DiscoveryResultStorage));
|
||||
s.read(g_ReportTypes);
|
||||
s.readBool(g_IsInitialized);
|
||||
s.readBool(g_IsOnlineMode);
|
||||
s.readBool(g_IsOfflineDBMode);
|
||||
if (s.readBool())
|
||||
{
|
||||
OfflineDB_Shutdown();
|
||||
OfflineDB_LazyInit();
|
||||
}
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
g_ReportTypes = 0;
|
||||
|
|
|
@ -18,6 +18,9 @@ namespace nn
|
|||
|
||||
sint32 GetOlvAccessKey(uint32_t* pOutKey);
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@ namespace nn
|
|||
bool g_offlineDBInitialized = false;
|
||||
ZArchiveReader* g_offlineDBArchive{nullptr};
|
||||
|
||||
bool OfflineDB_Initialized()
|
||||
{
|
||||
return g_offlineDBInitialized;
|
||||
}
|
||||
|
||||
void OfflineDB_LazyInit()
|
||||
{
|
||||
std::scoped_lock _l(g_offlineDBMutex);
|
||||
|
|
|
@ -6,7 +6,9 @@ namespace nn
|
|||
{
|
||||
namespace olv
|
||||
{
|
||||
void OfflineDB_Init();
|
||||
bool OfflineDB_Initialized();
|
||||
|
||||
void OfflineDB_LazyInit();
|
||||
void OfflineDB_Shutdown();
|
||||
|
||||
nnResult OfflineDB_DownloadPostDataListParam_DownloadPostDataList(DownloadedTopicData* downloadedTopicData, DownloadedPostData* downloadedPostData, uint32be* postCountOut, uint32 maxCount, DownloadPostDataListParam* param);
|
||||
|
|
|
@ -840,6 +840,18 @@ namespace save
|
|||
return asyncData->GetResult();
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_save");
|
||||
s.writeMPTR(g_nn_save);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_save");
|
||||
s.readMPTR(g_nn_save);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
cafeExportRegister("nn_save", SAVEInit, LogType::Save);
|
||||
|
|
|
@ -4,6 +4,9 @@ namespace nn
|
|||
{
|
||||
namespace save
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
void ResetToDefaultState();
|
||||
|
||||
|
|
|
@ -16,6 +16,18 @@ namespace nn::temp
|
|||
osLib_returnFromFunction(hCPU, 0);
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_temp");
|
||||
s.write(tempIdGenerator);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_temp");
|
||||
s.read(tempIdGenerator);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
osLib_addFunction("nn_temp", "TEMPCreateAndInitTempDir", nnTempExport_TEMPCreateAndInitTempDir);
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
|
||||
namespace nn::temp
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void Initialize();
|
||||
};
|
|
@ -15,6 +15,18 @@ void nnUdsExport___sti___11_uds_Api_cpp_f5d9abb2(PPCInterpreter_t* hCPU)
|
|||
osLib_returnFromFunction(hCPU, memory_getVirtualOffsetFromPointer(udsWorkspace));
|
||||
}
|
||||
|
||||
void nnUds_save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nn_uds");
|
||||
s.writeNullableData(udsWorkspace, sizeof(udsWorkspace_t));
|
||||
}
|
||||
|
||||
void nnUds_restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nn_uds");
|
||||
s.readNullableData(udsWorkspace, sizeof(udsWorkspace_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Load UDS functions
|
||||
*/
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
void nnUds_save(MemStreamWriter& s);
|
||||
void nnUds_restore(MemStreamReader& s);
|
||||
|
||||
void nnUds_load();
|
|
@ -944,6 +944,28 @@ namespace nsyshid
|
|||
this->m_hid = hid;
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nsyshid");
|
||||
s.writePTR(firstDevice);
|
||||
s.writeNullableData(firstHIDClient, sizeof(HIDClient_t));
|
||||
s.write(_lastGeneratedHidHandle);
|
||||
s.writeMPTR(_devicePool);
|
||||
s.write(_devicePoolMask.count());
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nsyshid");
|
||||
s.readPTR(firstDevice);
|
||||
s.readNullableData(firstHIDClient, sizeof(HIDClient_t));
|
||||
s.read(_lastGeneratedHidHandle);
|
||||
s.readMPTR(_devicePool);
|
||||
_devicePoolMask.reset();
|
||||
for (size_t i = 0; i < s.read<size_t>(); i++)
|
||||
_devicePoolMask.set(i);
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
osLib_addFunction("nsyshid", "HIDAddClient", export_HIDAddClient);
|
||||
|
|
|
@ -8,5 +8,8 @@ namespace nsyshid
|
|||
|
||||
void DetachBackend(const std::shared_ptr<Backend>& backend);
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void load();
|
||||
} // namespace nsyshid
|
||||
|
|
|
@ -2223,6 +2223,83 @@ namespace nsysnet
|
|||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::write(const nsysnet::NSSLInternalState_t& v)
|
||||
{
|
||||
writeBool(v.destroyed);
|
||||
write(v.sslVersion);
|
||||
write(v.clientPKI);
|
||||
|
||||
write<uint32>(v.serverPKIs.size());
|
||||
for (auto i : v.serverPKIs)
|
||||
write<uint32>(i);
|
||||
|
||||
write<uint32>(v.serverCustomPKIs.size());
|
||||
for (auto i : v.serverCustomPKIs)
|
||||
writePODVector(i);
|
||||
}
|
||||
|
||||
template<>
|
||||
void MemStreamReader::read(nsysnet::NSSLInternalState_t& v)
|
||||
{
|
||||
readBool(v.destroyed);
|
||||
read(v.sslVersion);
|
||||
read(v.clientPKI);
|
||||
|
||||
uint32 serverPKIsSize = read<uint32>();
|
||||
v.serverPKIs.clear();
|
||||
for (uint32 i = 0; i < serverPKIsSize; i++)
|
||||
v.serverPKIs.insert(read<uint32>());
|
||||
|
||||
uint32 serverCustomPKIsSize = read<uint32>();
|
||||
v.serverCustomPKIs.clear();
|
||||
v.serverCustomPKIs.resize(serverCustomPKIsSize);
|
||||
for (uint32 i = 0; i < serverCustomPKIsSize; i++)
|
||||
{
|
||||
std::vector<uint8> pki;
|
||||
readPODVector(pki);
|
||||
v.serverCustomPKIs.push_back(pki);
|
||||
}
|
||||
}
|
||||
|
||||
void nsysnet_save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("nsysnet");
|
||||
s.writeMPTR(_ntoa_tempString);
|
||||
s.writeMPTR(_staticHostent);
|
||||
s.writeMPTR(_staticHostentName);
|
||||
s.writeMPTR(_staticHostentPtrList);
|
||||
s.writeMPTR(_staticHostentEntries);
|
||||
s.write<uint32>(nsysnet::g_nsslInternalStates.size());
|
||||
for (auto i : nsysnet::g_nsslInternalStates)
|
||||
s.write(i);
|
||||
s.writeBool(sockLibReady);
|
||||
s.write<uint32>(sizeof(virtualSocket_t) * WU_SOCKET_LIMIT);
|
||||
s.writeData(virtualSocketTable, sizeof(virtualSocket_t) * WU_SOCKET_LIMIT);
|
||||
}
|
||||
|
||||
void nsysnet_restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("nsysnet");
|
||||
s.readMPTR(_ntoa_tempString);
|
||||
s.readMPTR(_staticHostent);
|
||||
s.readMPTR(_staticHostentName);
|
||||
s.readMPTR(_staticHostentPtrList);
|
||||
s.readMPTR(_staticHostentEntries);
|
||||
uint32 g_nsslInternalStatesSize = s.read<uint32>();
|
||||
nsysnet::g_nsslInternalStates.clear();
|
||||
nsysnet::g_nsslInternalStates.resize(g_nsslInternalStatesSize);
|
||||
for (uint32 i = 0; i < g_nsslInternalStatesSize; i++)
|
||||
{
|
||||
nsysnet::NSSLInternalState_t t;
|
||||
s.read(t);
|
||||
nsysnet::g_nsslInternalStates.push_back(t);
|
||||
}
|
||||
s.readBool(sockLibReady);
|
||||
cemu_assert(s.read<uint32>() == sizeof(virtualSocket_t) * WU_SOCKET_LIMIT);
|
||||
s.readData(virtualSocketTable, sizeof(virtualSocket_t) * WU_SOCKET_LIMIT);
|
||||
}
|
||||
|
||||
// register nsysnet functions
|
||||
void nsysnet_load()
|
||||
{
|
||||
|
@ -2283,3 +2360,4 @@ void nsysnet_load()
|
|||
osLib_addFunction("nsysnet", "NSSLExportInternalServerCertificate", nsysnet::export_NSSLExportInternalServerCertificate);
|
||||
osLib_addFunction("nsysnet", "NSSLExportInternalClientCertificate", nsysnet::export_NSSLExportInternalClientCertificate);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
typedef signed int WUSOCKET;
|
||||
|
||||
void nsysnet_save(MemStreamWriter& s);
|
||||
void nsysnet_restore(MemStreamReader& s);
|
||||
|
||||
void nsysnet_load();
|
||||
WUSOCKET nsysnet_createVirtualSocketFromExistingSocket(SOCKET existingSocket);
|
||||
void nsysnet_notifyCloseSharedSocket(SOCKET existingSocket);
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace padscore
|
|||
|
||||
WPADState_t g_wpad_state = kWPADStateMaster;
|
||||
|
||||
struct {
|
||||
typedef struct _g_padscore_t
|
||||
{
|
||||
SysAllocator<coreinit::OSAlarm_t> alarm;
|
||||
bool kpad_initialized = false;
|
||||
|
||||
|
@ -72,7 +73,9 @@ namespace padscore
|
|||
} controller_data[InputManager::kMaxWPADControllers] = {};
|
||||
|
||||
int max_controllers = kWPADMaxControllers; // max bt controllers?
|
||||
} g_padscore;
|
||||
} g_padscore_t;
|
||||
|
||||
g_padscore_t g_padscore;
|
||||
}
|
||||
|
||||
|
||||
|
@ -808,3 +811,73 @@ namespace padscore
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::write(const padscore::g_padscore_t& v)
|
||||
{
|
||||
writeMPTR(v.alarm);
|
||||
writeBool(v.kpad_initialized);
|
||||
write<uint32>(InputManager::kMaxWPADControllers);
|
||||
for (auto i : v.controller_data)
|
||||
{
|
||||
writeMPTR(i.extension_callback);
|
||||
writeMPTR(i.connectCallback);
|
||||
writeMPTR(i.sampling_callback);
|
||||
writeMPTR(i.dpd_callback);
|
||||
writeBool(i.dpd_enabled);
|
||||
writeBool(i.disconnectCalled);
|
||||
writeBool(i.disconnectCalled);
|
||||
write(i.btn_repeat.delay);
|
||||
write(i.btn_repeat.pulse);
|
||||
}
|
||||
write(v.max_controllers);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MemStreamReader::read(padscore::g_padscore_t& v)
|
||||
{
|
||||
readMPTR(v.alarm);
|
||||
readBool(v.kpad_initialized);
|
||||
cemu_assert(read<uint32>() == InputManager::kMaxWPADControllers);
|
||||
for (auto i : v.controller_data)
|
||||
{
|
||||
readMPTR(i.extension_callback);
|
||||
readMPTR(i.connectCallback);
|
||||
readMPTR(i.sampling_callback);
|
||||
readMPTR(i.dpd_callback);
|
||||
readBool(i.dpd_enabled);
|
||||
readBool(i.disconnectCalled);
|
||||
readBool(i.disconnectCalled);
|
||||
read(i.btn_repeat.delay);
|
||||
read(i.btn_repeat.pulse);
|
||||
}
|
||||
read(v.max_controllers);
|
||||
}
|
||||
|
||||
namespace padscore
|
||||
{
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("padscore");
|
||||
s.writeBool(debugUseDRC1);
|
||||
s.writeBool(g_kpadIsInited);
|
||||
s.write(g_padscore);
|
||||
s.writePTR(g_kpad_ringbuffer);
|
||||
s.write(g_kpad_ringbuffer_length);
|
||||
s.writeBool(g_wpad_callback_by_kpad);
|
||||
s.write((uint32)g_wpad_state);
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("padscore");
|
||||
s.readBool(debugUseDRC1);
|
||||
s.readBool(g_kpadIsInited);
|
||||
s.read(g_padscore);
|
||||
s.readPTR(g_kpad_ringbuffer);
|
||||
s.read(g_kpad_ringbuffer_length);
|
||||
s.readBool(g_wpad_callback_by_kpad);
|
||||
g_wpad_state = (WPADState_t)s.read<uint32>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
namespace padscore
|
||||
{
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
|
||||
void start();
|
||||
void load();
|
||||
}
|
||||
|
|
|
@ -875,6 +875,16 @@ namespace proc_ui
|
|||
s_driverInBackground = false;
|
||||
}
|
||||
|
||||
void save(MemStreamWriter& s)
|
||||
{
|
||||
s.writeSection("proc_ui");
|
||||
}
|
||||
|
||||
void restore(MemStreamReader& s)
|
||||
{
|
||||
s.readSection("proc_ui");
|
||||
}
|
||||
|
||||
void load()
|
||||
{
|
||||
reset();
|
||||
|
|
|
@ -40,5 +40,7 @@ namespace proc_ui
|
|||
ProcUIStatus ProcUIProcessMessages(bool isBlockingInBackground);
|
||||
ProcUIStatus ProcUISubProcessMessages(bool isBlockingInBackground);
|
||||
|
||||
void save(MemStreamWriter& s);
|
||||
void restore(MemStreamReader& s);
|
||||
void load();
|
||||
}
|
|
@ -42,6 +42,8 @@ enum class LogType : sint32
|
|||
ProcUi = 39,
|
||||
nlibcurl = 41,
|
||||
|
||||
SaveStates = 50,
|
||||
|
||||
PRUDP = 40,
|
||||
|
||||
NFC = 41,
|
||||
|
|
|
@ -54,6 +54,12 @@ public:
|
|||
m_tempData.insert(m_tempData.begin(), str, str + N);
|
||||
}
|
||||
|
||||
SysAllocator& operator=(T* value)
|
||||
{
|
||||
m_sysMem = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr uint32 GetCount() const
|
||||
{
|
||||
return count;
|
||||
|
@ -175,6 +181,12 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
SysAllocator& operator=(T* value)
|
||||
{
|
||||
m_sysMem = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T()
|
||||
{
|
||||
return *GetPtr();
|
||||
|
|
|
@ -78,6 +78,8 @@ enum
|
|||
MAINFRAME_MENU_ID_FILE_OPEN_CEMU_FOLDER,
|
||||
MAINFRAME_MENU_ID_FILE_OPEN_MLC_FOLDER,
|
||||
MAINFRAME_MENU_ID_FILE_OPEN_SHADERCACHE_FOLDER,
|
||||
MAINFRAME_MENU_ID_FILE_SAVESTATE,
|
||||
MAINFRAME_MENU_ID_FILE_LOADSTATE,
|
||||
MAINFRAME_MENU_ID_FILE_EXIT,
|
||||
MAINFRAME_MENU_ID_FILE_END_EMULATION,
|
||||
MAINFRAME_MENU_ID_FILE_RECENT_0,
|
||||
|
@ -128,6 +130,13 @@ enum
|
|||
MAINFRAME_MENU_ID_NFC_TOUCH_NFC_FILE = 21000,
|
||||
MAINFRAME_MENU_ID_NFC_RECENT_0,
|
||||
MAINFRAME_MENU_ID_NFC_RECENT_LAST = MAINFRAME_MENU_ID_NFC_RECENT_0 + 15,
|
||||
|
||||
// savestates
|
||||
MAINFRAME_MENU_ID_SAVESTATES_PAUSE_TITLE,
|
||||
MAINFRAME_MENU_ID_SAVESTATES_RESUME_TITLE,
|
||||
MAINFRAME_MENU_ID_SAVESTATES_SAVE_STATE,
|
||||
MAINFRAME_MENU_ID_SAVESTATES_LOAD_STATE,
|
||||
|
||||
// debug
|
||||
MAINFRAME_MENU_ID_DEBUG_RENDER_UPSIDE_DOWN = 21100,
|
||||
MAINFRAME_MENU_ID_DEBUG_VIEW_LOGGING_WINDOW,
|
||||
|
@ -206,6 +215,11 @@ EVT_MENU(MAINFRAME_MENU_ID_TIMER_SPEED_0125X, MainWindow::OnDebugSetting)
|
|||
// nfc menu
|
||||
EVT_MENU(MAINFRAME_MENU_ID_NFC_TOUCH_NFC_FILE, MainWindow::OnNFCMenu)
|
||||
EVT_MENU_RANGE(MAINFRAME_MENU_ID_NFC_RECENT_0 + 0, MAINFRAME_MENU_ID_NFC_RECENT_LAST, MainWindow::OnNFCMenu)
|
||||
// savestates menu
|
||||
EVT_MENU(MAINFRAME_MENU_ID_SAVESTATES_PAUSE_TITLE, MainWindow::OnSavestatesMenu)
|
||||
EVT_MENU(MAINFRAME_MENU_ID_SAVESTATES_RESUME_TITLE, MainWindow::OnSavestatesMenu)
|
||||
EVT_MENU(MAINFRAME_MENU_ID_SAVESTATES_SAVE_STATE, MainWindow::OnSavestatesMenu)
|
||||
EVT_MENU(MAINFRAME_MENU_ID_SAVESTATES_LOAD_STATE, MainWindow::OnSavestatesMenu)
|
||||
// debug -> logging menu
|
||||
EVT_MENU_RANGE(MAINFRAME_MENU_ID_DEBUG_LOGGING0 + 0, MAINFRAME_MENU_ID_DEBUG_LOGGING0 + 98, MainWindow::OnDebugLoggingToggleFlagGeneric)
|
||||
EVT_MENU(MAINFRAME_MENU_ID_DEBUG_ADVANCED_PPC_INFO, MainWindow::OnPPCInfoToggle)
|
||||
|
@ -787,6 +801,27 @@ void MainWindow::OnNFCMenu(wxCommandEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnSavestatesMenu(wxCommandEvent& event)
|
||||
{
|
||||
const auto menuId = event.GetId();
|
||||
if (menuId == MAINFRAME_MENU_ID_SAVESTATES_PAUSE_TITLE)
|
||||
{
|
||||
CafeSystem::PauseTitle();
|
||||
}
|
||||
if (menuId == MAINFRAME_MENU_ID_SAVESTATES_RESUME_TITLE)
|
||||
{
|
||||
CafeSystem::ResumeTitle();
|
||||
}
|
||||
else if (menuId == MAINFRAME_MENU_ID_SAVESTATES_SAVE_STATE)
|
||||
{
|
||||
CafeSystem::SaveState("state.bin");
|
||||
}
|
||||
else if (menuId == MAINFRAME_MENU_ID_SAVESTATES_LOAD_STATE)
|
||||
{
|
||||
CafeSystem::LoadState("state.bin");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnFileExit(wxCommandEvent& event)
|
||||
{
|
||||
// todo: Safely clean up everything
|
||||
|
@ -2226,6 +2261,16 @@ void MainWindow::RecreateMenu()
|
|||
nfcMenu->Append(MAINFRAME_MENU_ID_NFC_TOUCH_NFC_FILE, _("&Scan NFC tag from file"))->Enable(false);
|
||||
m_menuBar->Append(nfcMenu, _("&NFC"));
|
||||
m_nfcMenuSeparator0 = nullptr;
|
||||
|
||||
// savestates menu
|
||||
wxMenu* savestatesMenu = new wxMenu;
|
||||
savestatesMenu->Append(MAINFRAME_MENU_ID_SAVESTATES_PAUSE_TITLE, _("&Pause"), wxEmptyString);
|
||||
savestatesMenu->Append(MAINFRAME_MENU_ID_SAVESTATES_RESUME_TITLE, _("&Resume"), wxEmptyString);
|
||||
savestatesMenu->AppendSeparator();
|
||||
savestatesMenu->Append(MAINFRAME_MENU_ID_SAVESTATES_SAVE_STATE, _("&Save state"), wxEmptyString);
|
||||
savestatesMenu->Append(MAINFRAME_MENU_ID_SAVESTATES_LOAD_STATE, _("&Load state"), wxEmptyString);
|
||||
m_menuBar->Append(savestatesMenu, _("&Savestates"));
|
||||
|
||||
// debug->logging submenu
|
||||
wxMenu* debugLoggingMenu = new wxMenu();
|
||||
|
||||
|
@ -2260,6 +2305,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));
|
||||
|
|
|
@ -99,6 +99,7 @@ public:
|
|||
void OnInstallUpdate(wxCommandEvent& event);
|
||||
void OnFileExit(wxCommandEvent& event);
|
||||
void OnNFCMenu(wxCommandEvent& event);
|
||||
void OnSavestatesMenu(wxCommandEvent& event);
|
||||
void OnOptionsInput(wxCommandEvent& event);
|
||||
void OnAccountSelect(wxCommandEvent& event);
|
||||
void OnConsoleLanguage(wxCommandEvent& event);
|
||||
|
@ -231,6 +232,12 @@ private:
|
|||
wxMenu* m_nfcMenu{};
|
||||
wxMenuItem* m_nfcMenuSeparator0{};
|
||||
|
||||
// savestates
|
||||
//wxMenuItem* m_pause;
|
||||
//wxMenuItem* m_resume;
|
||||
//wxMenuItem* m_saveState;
|
||||
//wxMenuItem* m_loadState;
|
||||
|
||||
// debug
|
||||
wxMenu* m_debugMenu{};
|
||||
wxMenu* m_loggingSubmenu{};
|
||||
|
|
|
@ -1,53 +1,110 @@
|
|||
#include "Serializer.h"
|
||||
|
||||
template<>
|
||||
uint8 MemStreamReader::readBE()
|
||||
// read return
|
||||
|
||||
template<typename T>
|
||||
T MemStreamReader::read()
|
||||
{
|
||||
if (!reserveReadLength(sizeof(uint8)))
|
||||
if (!reserveReadLength(sizeof(T)))
|
||||
return 0;
|
||||
uint8 v = m_data[m_cursorPos];
|
||||
m_cursorPos += sizeof(uint8);
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
T v;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
m_cursorPos += sizeof(T);
|
||||
return v;
|
||||
}
|
||||
|
||||
template uint8 MemStreamReader::read<uint8>();
|
||||
template uint16 MemStreamReader::read<uint16>();
|
||||
template uint32 MemStreamReader::read<uint32>();
|
||||
template uint32be MemStreamReader::read<uint32be>();
|
||||
template uint64 MemStreamReader::read<uint64>();
|
||||
template int MemStreamReader::read<int>();
|
||||
|
||||
template<>
|
||||
uint16 MemStreamReader::readBE()
|
||||
std::string MemStreamReader::read()
|
||||
{
|
||||
if (!reserveReadLength(sizeof(uint16)))
|
||||
std::string s;
|
||||
uint32 stringSize = read<uint32>();
|
||||
if (hasError())
|
||||
return s;
|
||||
if (stringSize >= (32 * 1024 * 1024))
|
||||
{
|
||||
// out of bounds read or suspiciously large string
|
||||
m_hasError = true;
|
||||
return std::string();
|
||||
}
|
||||
s.resize(stringSize);
|
||||
readData(s.data(), stringSize);
|
||||
return s;
|
||||
}
|
||||
|
||||
// read void
|
||||
|
||||
template<typename T>
|
||||
void MemStreamReader::read(T& v)
|
||||
{
|
||||
if (reserveReadLength(sizeof(T)))
|
||||
{
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
m_cursorPos += sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template void MemStreamReader::read(uint8& v);
|
||||
template void MemStreamReader::read(uint16& v);
|
||||
template void MemStreamReader::read(uint32& v);
|
||||
template void MemStreamReader::read(uint32be& v);
|
||||
template void MemStreamReader::read(uint64& v);
|
||||
template void MemStreamReader::read(int& v);
|
||||
|
||||
template<>
|
||||
void MemStreamReader::read(std::string& v)
|
||||
{
|
||||
uint32 stringSize = read<uint32>();
|
||||
if (!hasError())
|
||||
{
|
||||
if (stringSize >= (32 * 1024 * 1024))
|
||||
{
|
||||
// out of bounds read or suspiciously large string
|
||||
m_hasError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
v.resize(stringSize);
|
||||
readData(v.data(), stringSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// readSection
|
||||
|
||||
void MemStreamReader::readSection(const char* sec)
|
||||
{
|
||||
std::string sec_str = std::string(sec);
|
||||
cemu_assert_debug(read<std::string>() == sec_str);
|
||||
}
|
||||
|
||||
// readBE return
|
||||
|
||||
template<typename T>
|
||||
T MemStreamReader::readBE()
|
||||
{
|
||||
if (!reserveReadLength(sizeof(T)))
|
||||
return 0;
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
uint16 v;
|
||||
T v;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
v = _BE(v);
|
||||
m_cursorPos += sizeof(uint16);
|
||||
m_cursorPos += sizeof(T);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
uint32 MemStreamReader::readBE()
|
||||
{
|
||||
if (!reserveReadLength(sizeof(uint32)))
|
||||
return 0;
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
uint32 v;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
v = _BE(v);
|
||||
m_cursorPos += sizeof(uint32);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
uint64 MemStreamReader::readBE()
|
||||
{
|
||||
if (!reserveReadLength(sizeof(uint64)))
|
||||
return 0;
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
uint64 v;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
v = _BE(v);
|
||||
m_cursorPos += sizeof(uint64);
|
||||
return v;
|
||||
}
|
||||
template uint8 MemStreamReader::readBE<uint8>();
|
||||
template uint16 MemStreamReader::readBE<uint16>();
|
||||
template uint32 MemStreamReader::readBE<uint32>();
|
||||
template uint64 MemStreamReader::readBE<uint64>();
|
||||
|
||||
template<>
|
||||
std::string MemStreamReader::readBE()
|
||||
|
@ -67,73 +124,72 @@ std::string MemStreamReader::readBE()
|
|||
return s;
|
||||
}
|
||||
|
||||
template<>
|
||||
uint8 MemStreamReader::readLE()
|
||||
{
|
||||
return readBE<uint8>();
|
||||
}
|
||||
// readLE return
|
||||
|
||||
template<>
|
||||
uint32 MemStreamReader::readLE()
|
||||
template<typename T>
|
||||
T MemStreamReader::readLE()
|
||||
{
|
||||
if (!reserveReadLength(sizeof(uint32)))
|
||||
if (!reserveReadLength(sizeof(T)))
|
||||
return 0;
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
uint32 v;
|
||||
T v;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
v = _LE(v);
|
||||
m_cursorPos += sizeof(uint32);
|
||||
m_cursorPos += sizeof(T);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
uint64 MemStreamReader::readLE()
|
||||
template uint8 MemStreamReader::readLE<uint8>();
|
||||
template uint32 MemStreamReader::readLE<uint32>();
|
||||
template uint64 MemStreamReader::readLE<uint64>();
|
||||
|
||||
// write void
|
||||
|
||||
template<typename T>
|
||||
void MemStreamWriter::write(const T& v)
|
||||
{
|
||||
if (!reserveReadLength(sizeof(uint64)))
|
||||
return 0;
|
||||
const uint8* p = m_data + m_cursorPos;
|
||||
uint64 v;
|
||||
std::memcpy(&v, p, sizeof(v));
|
||||
v = _LE(v);
|
||||
m_cursorPos += sizeof(uint64);
|
||||
return v;
|
||||
m_buffer.resize(m_buffer.size() + sizeof(T));
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - sizeof(T);
|
||||
std::memcpy(p, &v, sizeof(v));
|
||||
}
|
||||
|
||||
template void MemStreamWriter::write(const int& v);
|
||||
template void MemStreamWriter::write(const uint64& v);
|
||||
template void MemStreamWriter::write(const uint32be& v);
|
||||
template void MemStreamWriter::write(const uint32& v);
|
||||
template void MemStreamWriter::write(const uint16& v);
|
||||
template void MemStreamWriter::write(const uint8& v);
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeBE<uint64>(const uint64& v)
|
||||
void MemStreamWriter::write<std::string>(const std::string& v)
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() + 8);
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - 8;
|
||||
uint64 tmp = _BE(v);
|
||||
write<uint32>((uint32)v.size());
|
||||
writeData(v.data(), v.size());
|
||||
}
|
||||
|
||||
// writeSection
|
||||
|
||||
void MemStreamWriter::writeSection(const char* sec)
|
||||
{
|
||||
std::string sec_str = std::string(sec);
|
||||
write(sec_str);
|
||||
}
|
||||
|
||||
// writeBE void
|
||||
|
||||
template<typename T>
|
||||
void MemStreamWriter::writeBE(const T& v)
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() + sizeof(T));
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - sizeof(T);
|
||||
T tmp = _BE(v);
|
||||
std::memcpy(p, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeBE<uint32>(const uint32& v)
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() + 4);
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - 4;
|
||||
uint32 tmp = _BE(v);
|
||||
std::memcpy(p, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeBE<uint16>(const uint16& v)
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() + 2);
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - 2;
|
||||
uint16 tmp = _BE(v);
|
||||
std::memcpy(p, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeBE<uint8>(const uint8& v)
|
||||
{
|
||||
m_buffer.emplace_back(v);
|
||||
}
|
||||
|
||||
template void MemStreamWriter::writeBE(const uint64& v);
|
||||
template void MemStreamWriter::writeBE(const uint32& v);
|
||||
template void MemStreamWriter::writeBE(const uint16& v);
|
||||
template void MemStreamWriter::writeBE(const uint8& v);
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeBE<std::string>(const std::string& v)
|
||||
|
@ -142,21 +198,17 @@ void MemStreamWriter::writeBE<std::string>(const std::string& v)
|
|||
writeData(v.data(), v.size());
|
||||
}
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeLE<uint64>(const uint64& v)
|
||||
// writeLE void
|
||||
|
||||
template<typename T>
|
||||
void MemStreamWriter::writeLE(const T& v)
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() + 8);
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - 8;
|
||||
uint64 tmp = _LE(v);
|
||||
m_buffer.resize(m_buffer.size() + sizeof(T));
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - sizeof(T);
|
||||
T tmp = _LE(v);
|
||||
std::memcpy(p, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
template void MemStreamWriter::writeLE(const uint64& v);
|
||||
template void MemStreamWriter::writeLE(const uint32& v);
|
||||
|
||||
template<>
|
||||
void MemStreamWriter::writeLE<uint32>(const uint32& v)
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() + 4);
|
||||
uint8* p = m_buffer.data() + m_buffer.size() - 4;
|
||||
uint32 tmp = _LE(v);
|
||||
std::memcpy(p, &tmp, sizeof(tmp));
|
||||
}
|
|
@ -8,9 +8,23 @@ public:
|
|||
m_cursorPos = 0;
|
||||
}
|
||||
|
||||
template<typename T> T read();
|
||||
template<typename T> void read(T& v);
|
||||
template<typename T> T readBE();
|
||||
template<typename T> void readBE(T& v);
|
||||
template<typename T> T readLE();
|
||||
|
||||
void readAtomic(std::atomic<bool>& v)
|
||||
{
|
||||
v.store(readBool());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void readAtomic(std::atomic<T>& v)
|
||||
{
|
||||
v.store(read<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::vector<T> readPODVector()
|
||||
{
|
||||
|
@ -26,6 +40,48 @@ public:
|
|||
return v;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void readPODVector(std::vector<T>& v)
|
||||
{
|
||||
uint32 numElements = readBE<uint32>();
|
||||
if (!hasError())
|
||||
{
|
||||
v.reserve(numElements);
|
||||
v.resize(numElements);
|
||||
readData(v.data(), v.size() * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void readPTR(T& v)
|
||||
{
|
||||
v = (T)(memory_base + read<uint32>());
|
||||
}
|
||||
|
||||
template<template<typename> class C, typename T>
|
||||
void readMPTR(C<T>& v)
|
||||
{
|
||||
v = (T*)(memory_base + read<MPTR>());
|
||||
}
|
||||
|
||||
template<template<typename, size_t, size_t> class C, typename T, size_t c, size_t a>
|
||||
void readMPTR(C<T,c,a>& v)
|
||||
{
|
||||
v = (T*)(memory_base + read<MPTR>());
|
||||
}
|
||||
|
||||
void readBool(bool& v)
|
||||
{
|
||||
v = read<uint8>();
|
||||
}
|
||||
|
||||
bool readBool()
|
||||
{
|
||||
return read<uint8>();
|
||||
}
|
||||
|
||||
void readSection(const char* sec);
|
||||
|
||||
// read string terminated by newline character (or end of stream)
|
||||
// will also trim off any carriage return
|
||||
std::string_view readLine()
|
||||
|
@ -81,6 +137,19 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool readNullableData(void* ptr, size_t size)
|
||||
{
|
||||
if (readBE<uint8>())
|
||||
{
|
||||
ptr = NULL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return readData(ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
std::span<uint8> readDataNoCopy(size_t size)
|
||||
{
|
||||
if (m_cursorPos + size > m_size)
|
||||
|
@ -151,16 +220,55 @@ public:
|
|||
memcpy(p, ptr, size);
|
||||
}
|
||||
|
||||
void writeNullableData(void* ptr, size_t size)
|
||||
{
|
||||
writeBE((uint8)(ptr == NULL));
|
||||
if (ptr)
|
||||
writeData(ptr, size);
|
||||
}
|
||||
|
||||
template<typename T> void write(const T& v);
|
||||
template<typename T> void writeBE(const T& v);
|
||||
template<typename T> void writeLE(const T& v);
|
||||
|
||||
void writeAtomic(const std::atomic<bool>& v)
|
||||
{
|
||||
writeBool(v.load());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writeAtomic(const std::atomic<T>& v)
|
||||
{
|
||||
write(v.load());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writePODVector(const std::vector<T>& v)
|
||||
{
|
||||
cemu_assert(std::is_trivial_v<T>);
|
||||
writeBE<uint32>(v.size());
|
||||
writeData(v.data(), v.size() * sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writePTR(const T& v)
|
||||
{
|
||||
write((uint32)((uint8*)v - (uint8*)memory_base));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void writeMPTR(const T& v)
|
||||
{
|
||||
write(v.GetMPTR());
|
||||
}
|
||||
|
||||
void writeBool(const bool& v)
|
||||
{
|
||||
write((uint8)v);
|
||||
}
|
||||
|
||||
void writeSection(const char* sec);
|
||||
|
||||
// get result buffer without copy
|
||||
// resets internal state
|
||||
void getResultAndReset(std::vector<uint8>& data)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue