diff --git a/externals/boost b/externals/boost index 19ccdcc6f..f4850c297 160000 --- a/externals/boost +++ b/externals/boost @@ -1 +1 @@ -Subproject commit 19ccdcc6fbd026f98ed83dea32ff0398120fbb32 +Subproject commit f4850c2975a0d977b7479664b8d4a6f03300a042 diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index b0577f9d9..c0182ed48 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -91,6 +91,7 @@ add_library(common STATIC scm_rev.h scope_exit.h serialization/atomic.h + serialization/boost_flat_set.h serialization/boost_vector.hpp string_util.cpp string_util.h diff --git a/src/common/serialization/boost_flat_set.h b/src/common/serialization/boost_flat_set.h new file mode 100644 index 000000000..9a0ae77b0 --- /dev/null +++ b/src/common/serialization/boost_flat_set.h @@ -0,0 +1,37 @@ +#pragma once + +#include "common/common_types.h" +#include +#include + +namespace boost::serialization { + +template +void save(Archive& ar, const boost::container::flat_set& set, const unsigned int file_version) +{ + ar << static_cast(set.size()); + for (auto &v : set) { + ar << v; + } +} + +template +void load(Archive& ar, boost::container::flat_set& set, const unsigned int file_version) +{ + u64 count{}; + ar >> count; + set.clear(); + for (auto i = 0; i < count; i++) { + T value{}; + ar >> value; + set.insert(value); + } +} + +template +void serialize(Archive& ar, boost::container::flat_set& set, const unsigned int file_version) +{ + boost::serialization::split_free(ar, set, file_version); +} + +} diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h index 3e3d04b4d..ce57c01e9 100644 --- a/src/common/thread_queue_list.h +++ b/src/common/thread_queue_list.h @@ -6,6 +6,9 @@ #include #include +#include +#include +#include "common/common_types.h" namespace Common { @@ -156,6 +159,34 @@ private: Queue* first; // The priority level queues of thread ids. std::array queues; + + friend class boost::serialization::access; + template + void save(Archive& ar, const unsigned int file_version) const + { + s32 idx = first == UnlinkedTag() ? -1 : static_cast(first - &queues[0]); + ar << idx; + for (auto i = 0; i < NUM_QUEUES; i++) { + s32 idx1 = first == UnlinkedTag() ? -1 : static_cast(queues[i].next_nonempty - &queues[0]); + ar << idx1; + ar << queues[i].data; + } + } + + template + void load(Archive& ar, const unsigned int file_version) + { + s32 idx; + ar >> idx; + first = idx < 0 ? UnlinkedTag() : &queues[idx]; + for (auto i = 0; i < NUM_QUEUES; i++) { + ar >> idx; + queues[i].next_nonempty = idx < 0 ? UnlinkedTag() : &queues[idx]; + ar >> queues[i].data; + } + } + + BOOST_SERIALIZATION_SPLIT_MEMBER() }; } // namespace Common diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 6e6da8626..483ba4371 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -6,6 +6,7 @@ #include #include +#include #include "common/common_types.h" #include "core/arm/skyeye_common/arm_regformat.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h" @@ -16,6 +17,48 @@ public: virtual ~ARM_Interface() {} class ThreadContext { + friend class boost::serialization::access; + + template + void save(Archive& ar, const unsigned int file_version) const + { + for (auto i = 0; i < 16; i++) { + auto r = GetCpuRegister(i); + ar << r; + } + for (auto i = 0; i < 16; i++) { + auto r = GetFpuRegister(i); + ar << r; + } + auto r1 = GetCpsr(); + ar << r1; + auto r2 = GetFpscr(); + ar << r2; + auto r3 = GetFpexc(); + ar << r3; + } + + template + void load(Archive& ar, const unsigned int file_version) + { + u32 r; + for (auto i = 0; i < 16; i++) { + ar >> r; + SetCpuRegister(i, r); + } + for (auto i = 0; i < 16; i++) { + ar >> r; + SetFpuRegister(i, r); + } + ar >> r; + SetCpsr(r); + ar >> r; + SetFpscr(r); + ar >> r; + SetFpexc(r); + } + + BOOST_SERIALIZATION_SPLIT_MEMBER() public: virtual ~ThreadContext() = default; @@ -143,7 +186,7 @@ public: * @param reg The CP15 register to retrieve the value from. * @return the value stored in the given CP15 register. */ - virtual u32 GetCP15Register(CP15Register reg) = 0; + virtual u32 GetCP15Register(CP15Register reg) const = 0; /** * Stores the given value into the indicated CP15 register. @@ -172,4 +215,61 @@ public: /// Prepare core for thread reschedule (if needed to correctly handle state) virtual void PrepareReschedule() = 0; + +private: + friend class boost::serialization::access; + + template + void save(Archive& ar, const unsigned int file_version) const + { + for (auto i = 0; i < 15; i++) { + auto r = GetReg(i); + ar << r; + } + auto pc = GetPC(); + ar << pc; + auto cpsr = GetCPSR(); + ar << cpsr; + for (auto i = 0; i < 32; i++) { + auto r = GetVFPReg(i); + ar << r; + } + for (auto i = 0; i < VFPSystemRegister::VFP_SYSTEM_REGISTER_COUNT; i++) { + auto r = GetVFPSystemReg(static_cast(i)); + ar << r; + } + for (auto i = 0; i < CP15Register::CP15_REGISTER_COUNT; i++) { + auto r = GetCP15Register(static_cast(i)); + ar << r; + } + } + + template + void load(Archive& ar, const unsigned int file_version) + { + u32 r; + for (auto i = 0; i < 15; i++) { + ar >> r; + SetReg(i, r); + } + ar >> r; + SetPC(r); + ar >> r; + SetCPSR(r); + for (auto i = 0; i < 32; i++) { + ar >> r; + SetVFPReg(i, r); + } + for (auto i = 0; i < VFPSystemRegister::VFP_SYSTEM_REGISTER_COUNT; i++) { + ar >> r; + SetVFPSystemReg(static_cast(i), r); + } + for (auto i = 0; i < CP15Register::CP15_REGISTER_COUNT; i++) { + ar >> r; + SetCP15Register(static_cast(i), r); + } + // TODO: Clear caches etc? + } + + BOOST_SERIALIZATION_SPLIT_MEMBER() }; diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index f494b5228..a422db6af 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -235,7 +235,7 @@ void ARM_Dynarmic::SetCPSR(u32 cpsr) { jit->SetCpsr(cpsr); } -u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) { +u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) const { return interpreter_state->CP15[reg]; } diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 559dbf5a8..ff9a104b5 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -40,7 +40,7 @@ public: void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override; u32 GetCPSR() const override; void SetCPSR(u32 cpsr) override; - u32 GetCP15Register(CP15Register reg) override; + u32 GetCP15Register(CP15Register reg) const override; void SetCP15Register(CP15Register reg, u32 value) override; std::unique_ptr NewContext() const override; diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index d54b0cb95..6b67644e7 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -138,7 +138,7 @@ void ARM_DynCom::SetCPSR(u32 cpsr) { state->Cpsr = cpsr; } -u32 ARM_DynCom::GetCP15Register(CP15Register reg) { +u32 ARM_DynCom::GetCP15Register(CP15Register reg) const { return state->CP15[reg]; } diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 99c6ab460..7497b765f 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -41,7 +41,7 @@ public: void SetVFPSystemReg(VFPSystemRegister reg, u32 value) override; u32 GetCPSR() const override; void SetCPSR(u32 cpsr) override; - u32 GetCP15Register(CP15Register reg) override; + u32 GetCP15Register(CP15Register reg) const override; void SetCP15Register(CP15Register reg, u32 value) override; std::unique_ptr NewContext() const override; diff --git a/src/core/hle/kernel/config_mem.h b/src/core/hle/kernel/config_mem.h index ecb97c6bd..26fc0bccb 100644 --- a/src/core/hle/kernel/config_mem.h +++ b/src/core/hle/kernel/config_mem.h @@ -9,6 +9,7 @@ // bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm // putting this as a subset of HLE for now. +#include #include "common/common_funcs.h" #include "common/common_types.h" #include "common/swap.h" @@ -56,6 +57,14 @@ public: private: ConfigMemDef config_mem; + + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int file_version) + { + auto o_config_mem = boost::serialization::binary_object(&config_mem, sizeof(config_mem)); + ar & o_config_mem; + } }; } // namespace ConfigMem diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d8bd0f034..32d76d0d3 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -109,17 +109,17 @@ template void KernelSystem::serialize(Archive& ar, const unsigned int file_version) { ar & named_ports; - // TODO: CPU + ar & *current_cpu.get(); // NB: subsystem references and prepare_reschedule_callback are constant ar & *resource_limits.get(); ar & next_object_id; - //ar & *timer_manager.get(); + ar & *timer_manager.get(); ar & next_process_id; ar & process_list; ar & current_process; - // ar & *thread_manager.get(); - //ar & *config_mem_handler.get(); - //ar & *shared_page_handler.get(); + ar & *thread_manager.get(); + ar & *config_mem_handler.get(); + ar & *shared_page_handler.get(); } SERIALIZE_IMPL(KernelSystem) diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 467b1ae1e..b9a32ef23 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -23,11 +23,12 @@ void ReleaseThreadMutexes(Thread* thread) { thread->held_mutexes.clear(); } -Mutex::Mutex(KernelSystem& kernel) : WaitObject(kernel), kernel(kernel) {} +Mutex::Mutex() : kernel(*g_kernel) {} Mutex::~Mutex() {} std::shared_ptr KernelSystem::CreateMutex(bool initial_locked, std::string name) { - auto mutex{std::make_shared(*this)}; + auto mutex{std::make_shared()}; + mutex->Init(*this); mutex->lock_count = 0; mutex->name = std::move(name); diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 618685451..4f0c2c2b5 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -17,7 +17,7 @@ class Thread; class Mutex final : public WaitObject { public: - explicit Mutex(KernelSystem& kernel); + explicit Mutex(); ~Mutex() override; std::string GetTypeName() const override { @@ -68,7 +68,6 @@ private: ar & priority; ar & name; ar & holding_thread; - ar & kernel; // TODO: Check that this works! } }; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 63a5c3b68..49de1e69e 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -4,9 +4,13 @@ #include #include +#include +#include +#include "common/archives.h" #include "common/assert.h" #include "common/common_funcs.h" #include "common/logging/log.h" +#include "common/serialization/boost_vector.hpp" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" @@ -17,6 +21,28 @@ namespace Kernel { +template +void Process::serialize(Archive& ar, const unsigned int file_version) +{ + ar & boost::serialization::base_object(*this); + ar & handle_table; + ar & codeset; + ar & resource_limit; + ar & svc_access_mask; + ar & handle_table_size; + ar & (boost::container::vector >&)address_mappings; + ar & flags.raw; + ar & kernel_version; + ar & ideal_processor; + ar & process_id; + ar & vm_manager; + ar & memory_used; + ar & memory_region; + ar & tls_slots; +} + +SERIALIZE_IMPL(Process) + std::shared_ptr KernelSystem::CreateCodeSet(std::string name, u64 program_id) { auto codeset{std::make_shared()}; codeset->Init(*this); diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 6defd42c6..edda20c1f 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -11,13 +11,10 @@ #include #include #include -#include -#include -#include #include +#include #include "common/bit_field.h" #include "common/common_types.h" -#include "common/serialization/boost_vector.hpp" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/vm_manager.h" @@ -234,23 +231,6 @@ private: friend class boost::serialization::access; template - void serialize(Archive& ar, const unsigned int file_version) - { - ar & boost::serialization::base_object(*this); - ar & handle_table; - ar & codeset; - ar & resource_limit; - ar & svc_access_mask; - ar & handle_table_size; - ar & (boost::container::vector >&)address_mappings; - ar & flags.raw; - ar & kernel_version; - ar & ideal_processor; - ar & process_id; - ar & vm_manager; - ar & memory_used; - ar & memory_region; - ar & tls_slots; - } + void serialize(Archive& ar, const unsigned int file_version); }; } // namespace Kernel diff --git a/src/core/hle/kernel/shared_page.h b/src/core/hle/kernel/shared_page.h index 5092b4869..58cd46334 100644 --- a/src/core/hle/kernel/shared_page.h +++ b/src/core/hle/kernel/shared_page.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" @@ -104,6 +105,14 @@ private: std::chrono::seconds init_time; SharedPageDef shared_page; + + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int file_version) + { + auto o_shared_page = boost::serialization::binary_object(&shared_page, sizeof(shared_page)); + ar & o_shared_page; + } }; } // namespace SharedPage diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 4c2344dcb..9fa5df33a 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -6,10 +6,12 @@ #include #include #include +#include "common/archives.h" #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" #include "common/math_util.h" +#include "common/serialization/boost_flat_set.h" #include "core/arm/arm_interface.h" #include "core/arm/skyeye_common/armstate.h" #include "core/core.h" @@ -25,6 +27,30 @@ namespace Kernel { +template +void Thread::serialize(Archive& ar, const unsigned int file_version) +{ + ar & *context.get(); + ar & thread_id; + ar & status; + ar & entry_point; + ar & stack_top; + ar & nominal_priority; + ar & current_priority; + ar & last_running_ticks; + ar & processor_id; + ar & tls_address; + ar & held_mutexes; + ar & pending_mutexes; + ar & owner_process; + ar & wait_objects; + ar & wait_address; + ar & name; + // TODO: How the hell to do wakeup_callback +} + +SERIALIZE_IMPL(Thread) + bool Thread::ShouldWait(const Thread* thread) const { return status != ThreadStatus::Dead; } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 2db5dda91..fc9170675 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include "common/common_types.h" #include "common/thread_queue_list.h" #include "core/arm/arm_interface.h" @@ -145,6 +148,17 @@ private: friend class Thread; friend class KernelSystem; + + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int file_version) + { + ar & next_thread_id; + ar & current_thread; + ar & ready_queue; + ar & wakeup_callback_table; + ar & thread_list; + } }; class Thread final : public WaitObject { @@ -305,6 +319,10 @@ public: private: ThreadManager& thread_manager; + + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int file_version); }; /** diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 9c3d0f725..f073c3312 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -14,15 +14,15 @@ namespace Kernel { -Timer::Timer(KernelSystem& kernel) - : WaitObject(kernel), kernel(kernel), timer_manager(kernel.GetTimerManager()) {} +Timer::Timer() : kernel(*g_kernel), timer_manager(g_kernel->GetTimerManager()) {} Timer::~Timer() { Cancel(); timer_manager.timer_callback_table.erase(callback_id); } std::shared_ptr KernelSystem::CreateTimer(ResetType reset_type, std::string name) { - auto timer{std::make_shared(*this)}; + auto timer{std::make_shared()}; + timer->Init(*this); timer->reset_type = reset_type; timer->signaled = false; diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 6865f5243..690350611 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -4,6 +4,7 @@ #pragma once +#include #include "common/common_types.h" #include "core/core_timing.h" #include "core/hle/kernel/object.h" @@ -33,11 +34,19 @@ private: friend class Timer; friend class KernelSystem; + + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int file_version) + { + ar & next_timer_callback_id; + ar & timer_callback_table; + } }; class Timer final : public WaitObject { public: - explicit Timer(KernelSystem& kernel); + explicit Timer(); ~Timer() override; std::string GetTypeName() const override { @@ -103,6 +112,18 @@ private: TimerManager& timer_manager; friend class KernelSystem; + + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int file_version) + { + ar & reset_type; + ar & initial_delay; + ar & interval_delay; + ar & signaled; + ar & name; + ar & callback_id; + } }; } // namespace Kernel