diff --git a/TODO b/TODO index 83603d1c6..9cc333d46 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,10 @@ ☐ Save/load UI ✔ Basic version @done(20-01-03 15:27) ☐ Multiple slots etc. +☐ Add 'force flush all' to Rasterizer interface + impls ☐ Custom texture cache ☐ Review constructor/initialization code -☐ Core timing events +✔ Core timing events @done(20-01-12 15:14) ☐ Serialize codeset with an apploader reference instead ✔ Review base class serialization everywhere @done(20-01-10 23:47) Make sure that all base/derived relationships are registered diff --git a/src/core/core.cpp b/src/core/core.cpp index fcd1268da..fa60035dc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -434,6 +434,7 @@ void System::Reset() { template void System::serialize(Archive& ar, const unsigned int file_version) { Memory::RasterizerFlushAndInvalidateRegion(0, 0xFFFFFFFF); + ar&* timing.get(); ar&* cpu_core.get(); ar&* service_manager.get(); ar& GPU::g_regs; diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 976a6f3ba..4b2729a76 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -11,6 +11,8 @@ namespace Core { +Timing* Timing::deserializing = nullptr; + // Sort by time, unless the times are the same, in which case sort by the order added to the queue bool Timing::Event::operator>(const Event& right) const { return std::tie(time, fifo_order) > std::tie(right.time, right.fifo_order); @@ -26,7 +28,9 @@ TimingEventType* Timing::RegisterEvent(const std::string& name, TimedCallback ca auto info = event_types.emplace(name, TimingEventType{}); TimingEventType* event_type = &info.first->second; event_type->name = &info.first->first; - event_type->callback = callback; + if (callback != nullptr) { + event_type->callback = callback; + } return event_type; } @@ -129,7 +133,9 @@ void Timing::Advance() { LOG_ERROR(Core, "Unknown queued event"); continue; } - evt.type->callback(evt.userdata, global_timer - evt.time); + if (evt.type->callback != nullptr) { + evt.type->callback(evt.userdata, global_timer - evt.time); + } } is_global_timer_sane = false; diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 229fc37f4..1e6a3b021 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "common/common_types.h" #include "common/logging/log.h" #include "common/threadsafe_queue.h" @@ -190,6 +192,8 @@ public: s64 GetDowncount() const; private: + static Timing* deserializing; + struct Event { s64 time; u64 fifo_order; @@ -198,6 +202,29 @@ private: bool operator>(const Event& right) const; bool operator<(const Event& right) const; + + private: + template + void save(Archive& ar, const unsigned int) const { + ar& time; + ar& fifo_order; + ar& userdata; + std::string name = *(type->name); + ar << name; + } + + template + void load(Archive& ar, const unsigned int) { + ar& time; + ar& fifo_order; + ar& userdata; + std::string name; + ar >> name; + type = Timing::deserializing->RegisterEvent(name, nullptr); + } + friend class boost::serialization::access; + + BOOST_SERIALIZATION_SPLIT_MEMBER() }; static constexpr int MAX_SLICE_LENGTH = 20000; @@ -229,6 +256,21 @@ private: // executing the first cycle of each slice to prepare the slice length and downcount for // that slice. bool is_global_timer_sane = true; + + template + void serialize(Archive& ar, const unsigned int) { + // event_types set during initialization of other things + deserializing = this; + MoveEvents(); + ar& global_timer; + ar& slice_length; + ar& downcount; + ar& event_queue; + ar& event_fifo_id; + ar& idled_cycles; + deserializing = nullptr; + } + friend class boost::serialization::access; }; } // namespace Core diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index c64e24071..0286e210d 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -172,6 +172,7 @@ private: ar& ready_queue; ar& wakeup_callback_table; ar& thread_list; + SwitchContext(current_thread.get()); } };