From dd8445a2b9c4c65c4d72f094584d6c7fab39b4b2 Mon Sep 17 00:00:00 2001 From: Marco Satti Date: Sun, 5 Aug 2018 23:46:55 +0800 Subject: [PATCH] Testing a serialization solution, useful for debugging state. --- .clang-format | 5 +- .gitignore | 1 + .gitmodules | 3 + liborbum/CMakeLists.txt | 546 +++++++++--------- liborbum/src/Common/Constants.hpp | 2 + .../Common/Types/FifoQueue/DmaFifoQueue.hpp | 8 + .../Common/Types/Memory/ArrayByteMemory.hpp | 13 + .../Common/Types/Memory/ArrayHwordMemory.hpp | 16 +- .../src/Common/Types/Mips/BranchDelaySlot.hpp | 10 + liborbum/src/Common/Types/Primitive.hpp | 9 + .../Types/Register/SizedByteRegister.hpp | 8 + .../Types/Register/SizedDwordRegister.hpp | 8 + .../Types/Register/SizedHwordRegister.hpp | 8 + .../Types/Register/SizedQwordRegister.hpp | 8 + .../Types/Register/SizedWordRegister.hpp | 8 + liborbum/src/Core.cpp | 62 +- liborbum/src/Core.hpp | 13 + liborbum/src/Resources/Cdvd/CdvdNvrams.hpp | 13 + liborbum/src/Resources/Cdvd/CdvdRegisters.hpp | 9 + liborbum/src/Resources/Cdvd/CdvdRtc.hpp | 15 + liborbum/src/Resources/Cdvd/RCdvd.hpp | 43 ++ liborbum/src/Resources/Ee/Core/EeCoreCop0.hpp | 49 +- liborbum/src/Resources/Ee/Core/EeCoreFpu.hpp | 16 +- .../src/Resources/Ee/Core/EeCoreR5900.hpp | 13 + liborbum/src/Resources/Ee/Core/EeCoreTlb.hpp | 9 + .../src/Resources/Ee/Core/EeCoreTlbEntry.hpp | 35 ++ liborbum/src/Resources/Ee/Core/REeCore.hpp | 12 + .../src/Resources/Ee/Dmac/EeDmacChannels.hpp | 11 + liborbum/src/Resources/Ee/Dmac/REeDmac.hpp | 42 ++ liborbum/src/Resources/Ee/Gif/RGif.hpp | 19 + liborbum/src/Resources/Ee/Intc/REeIntc.hpp | 10 + liborbum/src/Resources/Ee/Ipu/RIpu.hpp | 12 + liborbum/src/Resources/Ee/REe.hpp | 22 + .../src/Resources/Ee/Timers/EeTimersUnits.hpp | 10 + .../src/Resources/Ee/Timers/REeTimers.hpp | 11 + liborbum/src/Resources/Ee/Vpu/RVpu.hpp | 10 + liborbum/src/Resources/Ee/Vpu/Vif/RVif.hpp | 9 + .../src/Resources/Ee/Vpu/Vif/VifUnits.hpp | 31 + liborbum/src/Resources/Ee/Vpu/Vu/RVu.hpp | 10 + liborbum/src/Resources/Ee/Vpu/Vu/VuUnits.hpp | 18 + liborbum/src/Resources/Gs/Crtc/RCrtc.hpp | 4 + liborbum/src/Resources/Gs/RGs.hpp | 33 ++ .../src/Resources/Iop/Core/IopCoreCop0.hpp | 24 + .../src/Resources/Iop/Core/IopCoreR3000.hpp | 12 + liborbum/src/Resources/Iop/Core/RIopCore.hpp | 10 + .../Resources/Iop/Dmac/IopDmacChannels.hpp | 10 + liborbum/src/Resources/Iop/Dmac/RIopDmac.hpp | 25 + liborbum/src/Resources/Iop/Intc/RIopIntc.hpp | 10 + liborbum/src/Resources/Iop/RIop.hpp | 42 ++ liborbum/src/Resources/Iop/Sio0/RSio0.hpp | 11 + .../src/Resources/Iop/Sio0/Sio0Registers.hpp | 9 + liborbum/src/Resources/Iop/Sio2/RSio2.hpp | 30 + liborbum/src/Resources/Iop/Sio2/Sio2Ports.hpp | 18 + .../Resources/Iop/Timers/IopTimersUnits.hpp | 11 + .../src/Resources/Iop/Timers/RIopTimers.hpp | 13 + liborbum/src/Resources/RResources.hpp | 45 +- liborbum/src/Resources/Spu2/RSpu2.hpp | 21 + liborbum/src/Resources/Spu2/Spu2CoreVoice.hpp | 21 + liborbum/src/Resources/Spu2/Spu2Cores.hpp | 128 ++++ orbumfront/CMakeLists.txt | 24 +- orbumfront/src/OrbumFront.cpp | 72 ++- utilities/CMakeLists.txt | 36 +- utilities/src/Console.cpp | 1 - utilities/src/Datetime.cpp | 11 + utilities/src/Datetime.hpp | 6 + utilities/src/Queues.hpp | 31 + 66 files changed, 1484 insertions(+), 331 deletions(-) create mode 100644 utilities/src/Datetime.cpp create mode 100644 utilities/src/Datetime.hpp diff --git a/.clang-format b/.clang-format index 957e1090..04b34519 100644 --- a/.clang-format +++ b/.clang-format @@ -31,9 +31,12 @@ IncludeBlocks: 'Regroup' IncludeCategories: # C++ Standard Library - Regex: '<[A-Za-z]+>' - Priority: -3 + Priority: -4 # Boost Library - Regex: ' positive. static constexpr uword FMAX_NEG = 0xFF7FFFFF; // Sign bit = 1 -> negative. diff --git a/liborbum/src/Common/Types/FifoQueue/DmaFifoQueue.hpp b/liborbum/src/Common/Types/FifoQueue/DmaFifoQueue.hpp index ab31f1ab..91a5b25f 100644 --- a/liborbum/src/Common/Types/FifoQueue/DmaFifoQueue.hpp +++ b/liborbum/src/Common/Types/FifoQueue/DmaFifoQueue.hpp @@ -52,6 +52,14 @@ public: return fifo_queue.has_write_available(n_bytes); } + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(fifo_queue) + ); + } + private: /// The backend for the FIFO queue. QueueTy fifo_queue; diff --git a/liborbum/src/Common/Types/Memory/ArrayByteMemory.hpp b/liborbum/src/Common/Types/Memory/ArrayByteMemory.hpp index 510956ed..eb1057ec 100644 --- a/liborbum/src/Common/Types/Memory/ArrayByteMemory.hpp +++ b/liborbum/src/Common/Types/Memory/ArrayByteMemory.hpp @@ -176,4 +176,17 @@ private: /// Read-only flag. /// Writes are silently discarded if turned on. bool read_only; + +public: + template + void save(Archive & archive) const + { + archive.saveBinaryValue(memory.data(), memory.size(), "memory"); + } + + template + void load(Archive & archive) + { + archive.loadBinaryValue(memory.data(), memory.size(), "memory"); + } }; diff --git a/liborbum/src/Common/Types/Memory/ArrayHwordMemory.hpp b/liborbum/src/Common/Types/Memory/ArrayHwordMemory.hpp index 5b803419..b041db5f 100644 --- a/liborbum/src/Common/Types/Memory/ArrayHwordMemory.hpp +++ b/liborbum/src/Common/Types/Memory/ArrayHwordMemory.hpp @@ -1,7 +1,8 @@ #pragma once #include -#include + +#include #include "Common/Types/Memory/HwordMemory.hpp" @@ -149,4 +150,17 @@ private: /// Read-only flag. /// Writes are silently discarded if turned on. bool read_only; + +public: + template + void save(Archive & archive) const + { + archive.saveBinaryValue(reinterpret_cast(memory.data()), memory.size() * sizeof(uhword), "memory"); + } + + template + void load(Archive & archive) + { + archive.loadBinaryValue(reinterpret_cast(memory.data()), memory.size() * sizeof(uhword), "memory"); + } }; diff --git a/liborbum/src/Common/Types/Mips/BranchDelaySlot.hpp b/liborbum/src/Common/Types/Mips/BranchDelaySlot.hpp index ef7e66d5..3d8ae5e9 100644 --- a/liborbum/src/Common/Types/Mips/BranchDelaySlot.hpp +++ b/liborbum/src/Common/Types/Mips/BranchDelaySlot.hpp @@ -77,4 +77,14 @@ public: private: size_t current_slot; uptr branch_pc; + +public: + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(current_slot), + CEREAL_NVP(branch_pc) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Common/Types/Primitive.hpp b/liborbum/src/Common/Types/Primitive.hpp index 5b5758b5..843f165f 100644 --- a/liborbum/src/Common/Types/Primitive.hpp +++ b/liborbum/src/Common/Types/Primitive.hpp @@ -76,6 +76,15 @@ struct uqword uw{uw0, uw1, uw2, uw3} { } + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(hi), + CEREAL_NVP(lo) + ); + } }; /// Primitive type min/max values. diff --git a/liborbum/src/Common/Types/Register/SizedByteRegister.hpp b/liborbum/src/Common/Types/Register/SizedByteRegister.hpp index 6179f677..cac6b82f 100644 --- a/liborbum/src/Common/Types/Register/SizedByteRegister.hpp +++ b/liborbum/src/Common/Types/Register/SizedByteRegister.hpp @@ -31,6 +31,14 @@ public: b = value; } + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(b) + ); + } + private: /// Primitive (sized) storage for register. union { diff --git a/liborbum/src/Common/Types/Register/SizedDwordRegister.hpp b/liborbum/src/Common/Types/Register/SizedDwordRegister.hpp index 9bcd2175..13a42839 100644 --- a/liborbum/src/Common/Types/Register/SizedDwordRegister.hpp +++ b/liborbum/src/Common/Types/Register/SizedDwordRegister.hpp @@ -97,6 +97,14 @@ public: d = value; } + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(d) + ); + } + private: /// Primitive (sized) storage for register. union { diff --git a/liborbum/src/Common/Types/Register/SizedHwordRegister.hpp b/liborbum/src/Common/Types/Register/SizedHwordRegister.hpp index dc080cd4..fadf6ed9 100644 --- a/liborbum/src/Common/Types/Register/SizedHwordRegister.hpp +++ b/liborbum/src/Common/Types/Register/SizedHwordRegister.hpp @@ -55,6 +55,14 @@ public: h = value; } + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(h) + ); + } + private: /// Primitive (sized) storage for register. union { diff --git a/liborbum/src/Common/Types/Register/SizedQwordRegister.hpp b/liborbum/src/Common/Types/Register/SizedQwordRegister.hpp index 098a2479..d100282e 100644 --- a/liborbum/src/Common/Types/Register/SizedQwordRegister.hpp +++ b/liborbum/src/Common/Types/Register/SizedQwordRegister.hpp @@ -118,6 +118,14 @@ public: q = value; } + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(q) + ); + } + private: /// Primitive (sized) storage for register. union { diff --git a/liborbum/src/Common/Types/Register/SizedWordRegister.hpp b/liborbum/src/Common/Types/Register/SizedWordRegister.hpp index 9558a38b..f52ee937 100644 --- a/liborbum/src/Common/Types/Register/SizedWordRegister.hpp +++ b/liborbum/src/Common/Types/Register/SizedWordRegister.hpp @@ -76,6 +76,14 @@ public: w = value; } + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(w) + ); + } + private: /// Primitive (sized) storage for register. union { diff --git a/liborbum/src/Core.cpp b/liborbum/src/Core.cpp index af34d7ff..b1fecc48 100644 --- a/liborbum/src/Core.cpp +++ b/liborbum/src/Core.cpp @@ -13,6 +13,7 @@ #include #include +#include #include "Core.hpp" @@ -44,6 +45,7 @@ CoreOptions CoreOptions::make_default() "./logs/", "./bios/", "./dumps/", + "./saves/", "scph10000.bin", "", "", @@ -71,6 +73,31 @@ CoreOptions CoreOptions::make_default() 1.0}; } +CoreApi::CoreApi(const CoreOptions& options) +{ + impl = new Core(options); +} + +CoreApi::~CoreApi() +{ + delete impl; +} + +void CoreApi::run() +{ + impl->run(); +} + +void CoreApi::dump_all_memory() const +{ + impl->dump_all_memory(); +} + +void CoreApi::save_state() +{ + impl->save_state(); +} + Core::Core(const CoreOptions& options) : options(options) { @@ -200,11 +227,10 @@ void Core::dump_all_memory() const { const std::string dumps_dir_path = options.dumps_dir_path; boost::filesystem::create_directory(dumps_dir_path); - get_resources().ee.main_memory.write_to_file(dumps_dir_path + "End_Dump_EE.bin"); - get_resources().iop.main_memory.write_to_file(dumps_dir_path + "End_Dump_IOP.bin"); - get_resources().spu2.main_memory.write_to_file(dumps_dir_path + "End_Dump_SPU2.bin"); - get_resources().cdvd.nvram.memory.write_to_file(dumps_dir_path + "End_Dump_CDVD_NVRAM.bin"); - BOOST_LOG(get_logger()) << "Dumped all memory objects ok"; + get_resources().ee.main_memory.write_to_file(dumps_dir_path + "dump_ee_" + datetime_fmt(Core::DATETIME_FORMAT) + ".bin"); + get_resources().iop.main_memory.write_to_file(dumps_dir_path + "dump_iop_" + datetime_fmt(Core::DATETIME_FORMAT) + ".bin"); + get_resources().spu2.main_memory.write_to_file(dumps_dir_path + "dump_spu2_" + datetime_fmt(Core::DATETIME_FORMAT) + ".bin"); + get_resources().cdvd.nvram.memory.write_to_file(dumps_dir_path + "dump_cdvd_nvram_" + datetime_fmt(Core::DATETIME_FORMAT) + ".bin"); } void Core::init_logging() @@ -212,30 +238,24 @@ void Core::init_logging() const std::string logs_dir_path = options.logs_dir_path; boost::filesystem::create_directory(logs_dir_path); boost::log::add_common_attributes(); + boost::log::add_file_log( - boost::log::keywords::file_name = logs_dir_path + "liborbum_%Y-%m-%d_%H-%M-%S.log", + boost::log::keywords::file_name = logs_dir_path + "log_" + datetime_fmt(Core::DATETIME_FORMAT) + ".log", boost::log::keywords::format = "[%TimeStamp%]: %Message%"); boost::log::add_console_log( std::cout, boost::log::keywords::format = "[%TimeStamp%]: %Message%"); } -CoreApi::CoreApi(const CoreOptions& options) +void Core::save_state() { - impl = new Core(options); -} + const std::string save_states_dir_path = options.save_states_dir_path; + boost::filesystem::create_directory(save_states_dir_path); -CoreApi::~CoreApi() -{ - delete impl; -} + std::ofstream fout(save_states_dir_path + "save_" + datetime_fmt(Core::DATETIME_FORMAT) + ".json", std::ios_base::out); + if (!fout) + throw std::runtime_error("Unable to write file"); -void CoreApi::run() -{ - impl->run(); -} - -void CoreApi::dump_all_memory() const -{ - impl->dump_all_memory(); + cereal::JSONOutputArchive oarchive(fout); + oarchive(get_resources()); } diff --git a/liborbum/src/Core.hpp b/liborbum/src/Core.hpp index 974c5982..1397c074 100644 --- a/liborbum/src/Core.hpp +++ b/liborbum/src/Core.hpp @@ -9,6 +9,8 @@ #include #include +#include + #include #include #include @@ -42,6 +44,7 @@ struct CORE_API CoreOptions /* Log dir path. */ const char* logs_dir_path; /* Roms dir path. */ const char* roms_dir_path; /* Memory dumps dir path. */ const char* dumps_dir_path; + /* Save states dir path. */ const char* save_states_dir_path; /* Boot ROM file name. */ const char* boot_rom_file_name; /* ROM1 file name. */ const char* rom1_file_name; /* ROM2 file name. */ const char* rom2_file_name; @@ -80,6 +83,7 @@ public: void run(); void dump_all_memory() const; + void save_state(); private: class Core* impl; @@ -92,6 +96,8 @@ private: class Core { public: + static constexpr const char * DATETIME_FORMAT = "%Y-%m-%d_%H-%M-%S"; + Core(const CoreOptions& options); ~Core(); @@ -155,4 +161,11 @@ private: /// Task executor. std::unique_ptr task_executor; + +public: + /// Save the current emulator state. JSON is used for debugging purposes + /// (makes it easy to view state). + /// TODO: for debugging only for now - some things are not serialized, + /// but most of the important stuff is. + void save_state(); }; diff --git a/liborbum/src/Resources/Cdvd/CdvdNvrams.hpp b/liborbum/src/Resources/Cdvd/CdvdNvrams.hpp index 62c81bab..a630d4f9 100644 --- a/liborbum/src/Resources/Cdvd/CdvdNvrams.hpp +++ b/liborbum/src/Resources/Cdvd/CdvdNvrams.hpp @@ -83,6 +83,19 @@ protected: int access_area_index; int access_max_block_index; int access_block_index; + +public: + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(memory), + CEREAL_NVP(access_read_write), + CEREAL_NVP(access_area_index), + CEREAL_NVP(access_max_block_index), + CEREAL_NVP(access_block_index) + ); + } }; /// Class representing the NVRAM for bios versions v0.00 <= x < 1.70. diff --git a/liborbum/src/Resources/Cdvd/CdvdRegisters.hpp b/liborbum/src/Resources/Cdvd/CdvdRegisters.hpp index ac727ae1..1d1b763c 100644 --- a/liborbum/src/Resources/Cdvd/CdvdRegisters.hpp +++ b/liborbum/src/Resources/Cdvd/CdvdRegisters.hpp @@ -27,6 +27,15 @@ public: /// Resources. SizedByteRegister ready; DmaFifoQueue<> data_in; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(ready), + CEREAL_NVP(data_in) + ); + } }; /// CDVD N/S command FIFO register. diff --git a/liborbum/src/Resources/Cdvd/CdvdRtc.hpp b/liborbum/src/Resources/Cdvd/CdvdRtc.hpp index 1f189b02..d24ea4e2 100644 --- a/liborbum/src/Resources/Cdvd/CdvdRtc.hpp +++ b/liborbum/src/Resources/Cdvd/CdvdRtc.hpp @@ -21,4 +21,19 @@ public: private: /// Number of microseconds that have passed, used by emulator. double microseconds; + +public: + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(second), + CEREAL_NVP(minute), + CEREAL_NVP(hour), + CEREAL_NVP(day), + CEREAL_NVP(month), + CEREAL_NVP(year), + CEREAL_NVP(microseconds) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Cdvd/RCdvd.hpp b/liborbum/src/Resources/Cdvd/RCdvd.hpp index 3146e796..bd767aff 100644 --- a/liborbum/src/Resources/Cdvd/RCdvd.hpp +++ b/liborbum/src/Resources/Cdvd/RCdvd.hpp @@ -63,4 +63,47 @@ struct RCdvd /// CDVD RTC state. CdvdRtc rtc; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(n_command), + CEREAL_NVP(n_rdy_din), + CEREAL_NVP(n_data_out), + CEREAL_NVP(break_), + CEREAL_NVP(intr_stat), + CEREAL_NVP(status), + CEREAL_NVP(tray_state), + CEREAL_NVP(crt_minute), + CEREAL_NVP(crt_second), + CEREAL_NVP(crt_frame), + CEREAL_NVP(type), + CEREAL_NVP(register_2013), + CEREAL_NVP(rsv), + CEREAL_NVP(s_command), + CEREAL_NVP(s_rdy_din), + CEREAL_NVP(s_data_out), + CEREAL_NVP(key_20), + CEREAL_NVP(key_21), + CEREAL_NVP(key_22), + CEREAL_NVP(key_23), + CEREAL_NVP(key_24), + CEREAL_NVP(key_28), + CEREAL_NVP(key_29), + CEREAL_NVP(key_2a), + CEREAL_NVP(key_2b), + CEREAL_NVP(key_2c), + CEREAL_NVP(key_30), + CEREAL_NVP(key_31), + CEREAL_NVP(key_32), + CEREAL_NVP(key_33), + CEREAL_NVP(key_34), + CEREAL_NVP(key_38), + CEREAL_NVP(key_xor), + CEREAL_NVP(dec_set), + CEREAL_NVP(nvram), + CEREAL_NVP(rtc) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Core/EeCoreCop0.hpp b/liborbum/src/Resources/Ee/Core/EeCoreCop0.hpp index f35c05a6..a5ff9174 100644 --- a/liborbum/src/Resources/Ee/Core/EeCoreCop0.hpp +++ b/liborbum/src/Resources/Ee/Core/EeCoreCop0.hpp @@ -73,4 +73,51 @@ public: /// Array of PCR0/PCR1, used by the MFPC/MTPC instructions. SizedWordRegister* pcr_registers[Constants::EE::EECore::COP0::NUMBER_PCR_REGISTERS]; -}; \ No newline at end of file + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(index), + CEREAL_NVP(random), + CEREAL_NVP(entrylo0), + CEREAL_NVP(entrylo1), + CEREAL_NVP(context), + CEREAL_NVP(pagemask), + CEREAL_NVP(wired), + CEREAL_NVP(reserved7), + CEREAL_NVP(badvaddr), + CEREAL_NVP(count), + CEREAL_NVP(entryhi), + CEREAL_NVP(cause), + CEREAL_NVP(compare), + CEREAL_NVP(status), + CEREAL_NVP(epc), + CEREAL_NVP(prid), + CEREAL_NVP(config), + CEREAL_NVP(reserved17), + CEREAL_NVP(reserved18), + CEREAL_NVP(reserved19), + CEREAL_NVP(reserved20), + CEREAL_NVP(reserved21), + CEREAL_NVP(reserved22), + CEREAL_NVP(badpaddr), + CEREAL_NVP(reserved26), + CEREAL_NVP(reserved27), + CEREAL_NVP(taglo), + CEREAL_NVP(taghi), + CEREAL_NVP(errorepc), + CEREAL_NVP(reserved31), + CEREAL_NVP(bpc), + CEREAL_NVP(iab), + CEREAL_NVP(iabm), + CEREAL_NVP(dab), + CEREAL_NVP(dabm), + CEREAL_NVP(dvb), + CEREAL_NVP(dvbm), + CEREAL_NVP(pccr), + CEREAL_NVP(pcr0), + CEREAL_NVP(pcr1) + ); + } +}; diff --git a/liborbum/src/Resources/Ee/Core/EeCoreFpu.hpp b/liborbum/src/Resources/Ee/Core/EeCoreFpu.hpp index 7b1077c0..59f6b480 100644 --- a/liborbum/src/Resources/Ee/Core/EeCoreFpu.hpp +++ b/liborbum/src/Resources/Ee/Core/EeCoreFpu.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Common/Constants.hpp" #include "Common/Types/Mips/MipsCoprocessor.hpp" #include "Common/Types/Register/SizedWordRegister.hpp" #include "Resources/Ee/Core/EeCoreCop0.hpp" @@ -18,7 +19,7 @@ public: /// 32 general purpose registers, called FPR's. /// See EE Core Users Manual, page 157. - SizedWordRegister fpr[32]; + SizedWordRegister fpr[Constants::EE::EECore::FPU::NUMBER_REGISTERS]; /// Accumulator register, used for multiply-accumulate type instructions. /// See EE Core Users Manual, page 157. @@ -31,8 +32,19 @@ public: /// Array of control registers. /// Only FCR[0] and [31] are defined. - SizedWordRegister* fcr[32]; + SizedWordRegister* fcr[Constants::EE::EECore::FPU::NUMBER_REGISTERS]; /// Pointer to the EE Core COP0 coprocessor, needed for the Status register. EeCoreCop0* cop0; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(fpr), + CEREAL_NVP(acc), + CEREAL_NVP(irr), + CEREAL_NVP(csr) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Core/EeCoreR5900.hpp b/liborbum/src/Resources/Ee/Core/EeCoreR5900.hpp index 294e67af..cf358cf9 100644 --- a/liborbum/src/Resources/Ee/Core/EeCoreR5900.hpp +++ b/liborbum/src/Resources/Ee/Core/EeCoreR5900.hpp @@ -37,4 +37,17 @@ public: /// The SA register is used for holding funnel shift instruction results. /// See the EE Core instruction QFSRV for more details (SA is only used for this instruction). SizedWordRegister sa; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(pc), + CEREAL_NVP(bdelay), + CEREAL_NVP(gpr), + CEREAL_NVP(hi), + CEREAL_NVP(lo), + CEREAL_NVP(sa) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Core/EeCoreTlb.hpp b/liborbum/src/Resources/Ee/Core/EeCoreTlb.hpp index eb31b73d..f383b8b7 100644 --- a/liborbum/src/Resources/Ee/Core/EeCoreTlb.hpp +++ b/liborbum/src/Resources/Ee/Core/EeCoreTlb.hpp @@ -39,4 +39,13 @@ private: /// Checks whether the given virtual address matches the TLB entry by index. bool is_match(const uptr vaddress, const int index) const; + +public: + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(tlb_entries) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Core/EeCoreTlbEntry.hpp b/liborbum/src/Resources/Ee/Core/EeCoreTlbEntry.hpp index d38e3662..417cd5a1 100644 --- a/liborbum/src/Resources/Ee/Core/EeCoreTlbEntry.hpp +++ b/liborbum/src/Resources/Ee/Core/EeCoreTlbEntry.hpp @@ -44,6 +44,16 @@ struct Mask uword pagemask; uword evenodd_mask; uword tlb_mask; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(pagemask), + CEREAL_NVP(evenodd_mask), + CEREAL_NVP(tlb_mask) + ); + } }; /// EE Core TLB entry, similar to a MIPS TLB entry. @@ -66,5 +76,30 @@ struct EeCoreTlbEntry bool c; bool d; bool v; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(pfn), + CEREAL_NVP(c), + CEREAL_NVP(d), + CEREAL_NVP(v) + ); + } } physical_info[2]; // Index 0 = Even, index 1 = Odd. + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(mask), + CEREAL_NVP(vpn2), + CEREAL_NVP(g), + CEREAL_NVP(asid), + CEREAL_NVP(s), + CEREAL_NVP(physical_info[0]), + CEREAL_NVP(physical_info[1]) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Core/REeCore.hpp b/liborbum/src/Resources/Ee/Core/REeCore.hpp index 9dee8fe8..386f1d87 100644 --- a/liborbum/src/Resources/Ee/Core/REeCore.hpp +++ b/liborbum/src/Resources/Ee/Core/REeCore.hpp @@ -27,4 +27,16 @@ struct REeCore /// Scratchpad memory. ArrayByteMemory scratchpad_memory; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(r5900), + CEREAL_NVP(cop0), + CEREAL_NVP(fpu), + CEREAL_NVP(tlb), + CEREAL_NVP(scratchpad_memory) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Dmac/EeDmacChannels.hpp b/liborbum/src/Resources/Ee/Dmac/EeDmacChannels.hpp index 1c0e35db..f7bc5f22 100644 --- a/liborbum/src/Resources/Ee/Dmac/EeDmacChannels.hpp +++ b/liborbum/src/Resources/Ee/Dmac/EeDmacChannels.hpp @@ -46,6 +46,17 @@ public: EeDmacChannelRegister_Addr madr; SizedWordRegister qwc; EeDmacChannelRegister_Chcr_Ty chcr; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(channel_id), + CEREAL_NVP(madr), + CEREAL_NVP(qwc), + CEREAL_NVP(chcr) + ); + } }; /// TADR EE DMAC channel, contains normal registers plus TADR register. diff --git a/liborbum/src/Resources/Ee/Dmac/REeDmac.hpp b/liborbum/src/Resources/Ee/Dmac/REeDmac.hpp index c71b76bd..5b134e55 100644 --- a/liborbum/src/Resources/Ee/Dmac/REeDmac.hpp +++ b/liborbum/src/Resources/Ee/Dmac/REeDmac.hpp @@ -55,4 +55,46 @@ struct REeDmac ArrayByteMemory memory_f500; ArrayByteMemory memory_f530; ArrayByteMemory memory_f5a0; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(channel_vif0), + CEREAL_NVP(channel_vif1), + CEREAL_NVP(channel_gif), + CEREAL_NVP(channel_fromipu), + CEREAL_NVP(channel_toipu), + CEREAL_NVP(channel_sif0), + CEREAL_NVP(channel_sif1), + CEREAL_NVP(channel_sif2), + CEREAL_NVP(channel_fromspr), + CEREAL_NVP(channel_tospr), + CEREAL_NVP(ctrl), + CEREAL_NVP(stat), + CEREAL_NVP(pcr), + CEREAL_NVP(sqwc), + CEREAL_NVP(rbsr), + CEREAL_NVP(rbor), + CEREAL_NVP(stadr), + CEREAL_NVP(enable_r), + CEREAL_NVP(enable_w), + CEREAL_NVP(memory_8060), + CEREAL_NVP(memory_9060), + CEREAL_NVP(memory_a060), + CEREAL_NVP(memory_b030), + CEREAL_NVP(memory_b440), + CEREAL_NVP(memory_c030), + CEREAL_NVP(memory_c440), + CEREAL_NVP(memory_c830), + CEREAL_NVP(memory_d030), + CEREAL_NVP(memory_d090), + CEREAL_NVP(memory_d440), + CEREAL_NVP(memory_d490), + CEREAL_NVP(memory_e070), + CEREAL_NVP(memory_f500), + CEREAL_NVP(memory_f530), + CEREAL_NVP(memory_f5a0) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Gif/RGif.hpp b/liborbum/src/Resources/Ee/Gif/RGif.hpp index 6404c023..056c7473 100644 --- a/liborbum/src/Resources/Ee/Gif/RGif.hpp +++ b/liborbum/src/Resources/Ee/Gif/RGif.hpp @@ -20,4 +20,23 @@ struct RGif SizedWordRegister p3cnt; SizedWordRegister p3tag; ArrayByteMemory memory_30b0; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(ctrl), + CEREAL_NVP(mode), + CEREAL_NVP(stat), + CEREAL_NVP(memory_3030), + CEREAL_NVP(tag0), + CEREAL_NVP(tag1), + CEREAL_NVP(tag2), + CEREAL_NVP(tag3), + CEREAL_NVP(cnt), + CEREAL_NVP(p3cnt), + CEREAL_NVP(p3tag), + CEREAL_NVP(memory_30b0) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Intc/REeIntc.hpp b/liborbum/src/Resources/Ee/Intc/REeIntc.hpp index 89daee62..91f410c8 100644 --- a/liborbum/src/Resources/Ee/Intc/REeIntc.hpp +++ b/liborbum/src/Resources/Ee/Intc/REeIntc.hpp @@ -11,4 +11,14 @@ struct REeIntc EeIntcRegister_Mask mask; EeIntcRegister_Stat stat; ArrayByteMemory memory_f020; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(mask), + CEREAL_NVP(stat), + CEREAL_NVP(memory_f020) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Ipu/RIpu.hpp b/liborbum/src/Resources/Ee/Ipu/RIpu.hpp index 737e9f5e..ad86e637 100644 --- a/liborbum/src/Resources/Ee/Ipu/RIpu.hpp +++ b/liborbum/src/Resources/Ee/Ipu/RIpu.hpp @@ -16,4 +16,16 @@ struct RIpu IpuRegister_Bp bp; IpuRegister_Top top; ArrayByteMemory memory_2040; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(cmd), + CEREAL_NVP(ctrl), + CEREAL_NVP(bp), + CEREAL_NVP(top), + CEREAL_NVP(memory_2040) + ); + } }; diff --git a/liborbum/src/Resources/Ee/REe.hpp b/liborbum/src/Resources/Ee/REe.hpp index 07a33c0d..805ecb3b 100644 --- a/liborbum/src/Resources/Ee/REe.hpp +++ b/liborbum/src/Resources/Ee/REe.hpp @@ -56,4 +56,26 @@ public: SizedWordRegister register_f420; EeRegister_Mch memory_mch; // No documentation (except for name)! From old PCSX2. Needed by the BIOS for RDRAM initialisation. ArrayByteMemory memory_f450; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(core), + CEREAL_NVP(dmac), + CEREAL_NVP(intc), + CEREAL_NVP(timers), + CEREAL_NVP(ipu), + CEREAL_NVP(gif), + CEREAL_NVP(vpu), + CEREAL_NVP(main_memory), + CEREAL_NVP(unknown_1a000000), + CEREAL_NVP(memory_sio), + CEREAL_NVP(register_f400), + CEREAL_NVP(memory_f410), + CEREAL_NVP(register_f420), + CEREAL_NVP(memory_mch), + CEREAL_NVP(memory_f450) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Timers/EeTimersUnits.hpp b/liborbum/src/Resources/Ee/Timers/EeTimersUnits.hpp index f4521aad..05e97c69 100644 --- a/liborbum/src/Resources/Ee/Timers/EeTimersUnits.hpp +++ b/liborbum/src/Resources/Ee/Timers/EeTimersUnits.hpp @@ -30,6 +30,16 @@ public: EeTimersUnitRegister_Count count; EeTimersUnitRegister_Mode mode; SizedWordRegister compare; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(count), + CEREAL_NVP(mode), + CEREAL_NVP(compare) + ); + } }; /// EE Timer with HOLD register, for timers 0 and 1. diff --git a/liborbum/src/Resources/Ee/Timers/REeTimers.hpp b/liborbum/src/Resources/Ee/Timers/REeTimers.hpp index e313c95b..a8ed3103 100644 --- a/liborbum/src/Resources/Ee/Timers/REeTimers.hpp +++ b/liborbum/src/Resources/Ee/Timers/REeTimers.hpp @@ -16,4 +16,15 @@ struct REeTimers /// Timer abstractions. EeTimersUnit units[Constants::EE::Timers::NUMBER_TIMERS]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(unit_0), + CEREAL_NVP(unit_1), + CEREAL_NVP(unit_2), + CEREAL_NVP(unit_3) + ); + } }; diff --git a/liborbum/src/Resources/Ee/Vpu/RVpu.hpp b/liborbum/src/Resources/Ee/Vpu/RVpu.hpp index 7a66349c..7e7f3992 100644 --- a/liborbum/src/Resources/Ee/Vpu/RVpu.hpp +++ b/liborbum/src/Resources/Ee/Vpu/RVpu.hpp @@ -16,4 +16,14 @@ public: /// VU structure. RVu vu; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(stat), + CEREAL_NVP(vif), + CEREAL_NVP(vu) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Vpu/Vif/RVif.hpp b/liborbum/src/Resources/Ee/Vpu/Vif/RVif.hpp index 96d5e931..613e9d0a 100644 --- a/liborbum/src/Resources/Ee/Vpu/Vif/RVif.hpp +++ b/liborbum/src/Resources/Ee/Vpu/Vif/RVif.hpp @@ -13,4 +13,13 @@ public: VifUnit_Base unit_0; VifUnit_Base unit_1; VifUnit_Base* units[Constants::EE::VPU::VIF::NUMBER_VIF_CORES]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(unit_0), + CEREAL_NVP(unit_1) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Vpu/Vif/VifUnits.hpp b/liborbum/src/Resources/Ee/Vpu/Vif/VifUnits.hpp index b0da1a5f..ef26f5b3 100644 --- a/liborbum/src/Resources/Ee/Vpu/Vif/VifUnits.hpp +++ b/liborbum/src/Resources/Ee/Vpu/Vif/VifUnits.hpp @@ -39,4 +39,35 @@ public: VifUnitRegister_Stat stat; VifUnitRegister_Fbrst fbrst; VifUnitRegister_Err err; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(core_id), + CEREAL_NVP(r0), + CEREAL_NVP(r1), + CEREAL_NVP(r2), + CEREAL_NVP(r3), + CEREAL_NVP(c0), + CEREAL_NVP(c1), + CEREAL_NVP(c2), + CEREAL_NVP(c3), + CEREAL_NVP(cycle), + CEREAL_NVP(mask), + CEREAL_NVP(mode), + CEREAL_NVP(itop), + CEREAL_NVP(itops), + CEREAL_NVP(base), + CEREAL_NVP(ofst), + CEREAL_NVP(top), + CEREAL_NVP(tops), + CEREAL_NVP(mark), + CEREAL_NVP(num), + CEREAL_NVP(code), + CEREAL_NVP(stat), + CEREAL_NVP(fbrst), + CEREAL_NVP(err) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Vpu/Vu/RVu.hpp b/liborbum/src/Resources/Ee/Vpu/Vu/RVu.hpp index 9eb73218..3912c703 100644 --- a/liborbum/src/Resources/Ee/Vpu/Vu/RVu.hpp +++ b/liborbum/src/Resources/Ee/Vpu/Vu/RVu.hpp @@ -17,4 +17,14 @@ public: /// Shared VU registers. VuRegister_Fbrst fbrst; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(unit_0), + CEREAL_NVP(unit_1), + CEREAL_NVP(fbrst) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Ee/Vpu/Vu/VuUnits.hpp b/liborbum/src/Resources/Ee/Vpu/Vu/VuUnits.hpp index 5854de77..16cf1933 100644 --- a/liborbum/src/Resources/Ee/Vpu/Vu/VuUnits.hpp +++ b/liborbum/src/Resources/Ee/Vpu/Vu/VuUnits.hpp @@ -72,6 +72,24 @@ public: /// Mappers for the VI (Hword) registers to WordRegisters. /// Used by different things, eg: ccr registers for VU0 and bus mappings for VU1. MapperHwordWordRegister vi_32[Constants::EE::VPU::VU::NUMBER_VI_REGISTERS]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(core_id), + CEREAL_NVP(acc), + CEREAL_NVP(i), + CEREAL_NVP(q), + CEREAL_NVP(r), + CEREAL_NVP(p), + CEREAL_NVP(status), + CEREAL_NVP(mac), + CEREAL_NVP(clipping), + CEREAL_NVP(pc), + CEREAL_NVP(cmsar) + ); + } }; /// Represents VU0. diff --git a/liborbum/src/Resources/Gs/Crtc/RCrtc.hpp b/liborbum/src/Resources/Gs/Crtc/RCrtc.hpp index 452489dd..31c07318 100644 --- a/liborbum/src/Resources/Gs/Crtc/RCrtc.hpp +++ b/liborbum/src/Resources/Gs/Crtc/RCrtc.hpp @@ -4,4 +4,8 @@ class RCrtc { public: + template + void serialize(Archive & archive) + { + } }; diff --git a/liborbum/src/Resources/Gs/RGs.hpp b/liborbum/src/Resources/Gs/RGs.hpp index d58c93eb..5f3223e9 100644 --- a/liborbum/src/Resources/Gs/RGs.hpp +++ b/liborbum/src/Resources/Gs/RGs.hpp @@ -44,4 +44,37 @@ public: // 0x12002000. ArrayByteMemory memory_2000; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(crtc), + CEREAL_NVP(pmode), + CEREAL_NVP(smode1), + CEREAL_NVP(smode2), + CEREAL_NVP(srfsh), + CEREAL_NVP(synch1), + CEREAL_NVP(synch2), + CEREAL_NVP(syncv), + CEREAL_NVP(dispfb1), + CEREAL_NVP(display1), + CEREAL_NVP(dispfb2), + CEREAL_NVP(display2), + CEREAL_NVP(extbuf), + CEREAL_NVP(extdata), + CEREAL_NVP(extwrite), + CEREAL_NVP(bgcolor), + CEREAL_NVP(memory_00f0), + CEREAL_NVP(csr), + CEREAL_NVP(imr), + CEREAL_NVP(memory_1020), + CEREAL_NVP(busdir), + CEREAL_NVP(memory_1050), + CEREAL_NVP(siglblid), + CEREAL_NVP(memory_1090), + CEREAL_NVP(memory_1100), + CEREAL_NVP(memory_2000) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Core/IopCoreCop0.hpp b/liborbum/src/Resources/Iop/Core/IopCoreCop0.hpp index 60bc110a..f2448bbd 100644 --- a/liborbum/src/Resources/Iop/Core/IopCoreCop0.hpp +++ b/liborbum/src/Resources/Iop/Core/IopCoreCop0.hpp @@ -41,4 +41,28 @@ public: /// Array of COP0 registers. SizedWordRegister* registers[Constants::IOP::IOPCore::COP0::NUMBER_REGISTERS]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(indx), + CEREAL_NVP(rand), + CEREAL_NVP(tlbl), + CEREAL_NVP(bpc), + CEREAL_NVP(context), + CEREAL_NVP(bda), + CEREAL_NVP(pidmask), + CEREAL_NVP(dcic), + CEREAL_NVP(badv), + CEREAL_NVP(bdam), + CEREAL_NVP(tlbh), + CEREAL_NVP(bpcm), + CEREAL_NVP(status), + CEREAL_NVP(cause), + CEREAL_NVP(epc), + CEREAL_NVP(prid), + CEREAL_NVP(erreg) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Core/IopCoreR3000.hpp b/liborbum/src/Resources/Iop/Core/IopCoreR3000.hpp index 3d100e6d..e2043d87 100644 --- a/liborbum/src/Resources/Iop/Core/IopCoreR3000.hpp +++ b/liborbum/src/Resources/Iop/Core/IopCoreR3000.hpp @@ -30,4 +30,16 @@ public: /// They are 32-bit long. SizedWordRegister hi; SizedWordRegister lo; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(pc), + CEREAL_NVP(bdelay), + CEREAL_NVP(gpr), + CEREAL_NVP(hi), + CEREAL_NVP(lo) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Core/RIopCore.hpp b/liborbum/src/Resources/Iop/Core/RIopCore.hpp index 6246e78d..ee19ff2e 100644 --- a/liborbum/src/Resources/Iop/Core/RIopCore.hpp +++ b/liborbum/src/Resources/Iop/Core/RIopCore.hpp @@ -16,4 +16,14 @@ struct RIopCore /// Scratchpad memory (1KB). Allocated at 0x1F800000. ArrayByteMemory scratchpad_memory; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(r3000), + CEREAL_NVP(cop0), + CEREAL_NVP(scratchpad_memory) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Dmac/IopDmacChannels.hpp b/liborbum/src/Resources/Iop/Dmac/IopDmacChannels.hpp index 54d64c8e..f06ee15b 100644 --- a/liborbum/src/Resources/Iop/Dmac/IopDmacChannels.hpp +++ b/liborbum/src/Resources/Iop/Dmac/IopDmacChannels.hpp @@ -42,6 +42,16 @@ public: SizedWordRegister madr; IopDmacChannelRegister_Bcr bcr; IopDmacChannelRegister_Chcr_Ty chcr; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(madr), + CEREAL_NVP(bcr), + CEREAL_NVP(chcr) + ); + } }; /// TADR IOP DMAC channel, contains normal registers plus TADR register. diff --git a/liborbum/src/Resources/Iop/Dmac/RIopDmac.hpp b/liborbum/src/Resources/Iop/Dmac/RIopDmac.hpp index a445caa0..bedb1cc4 100644 --- a/liborbum/src/Resources/Iop/Dmac/RIopDmac.hpp +++ b/liborbum/src/Resources/Iop/Dmac/RIopDmac.hpp @@ -40,4 +40,29 @@ struct RIopDmac /// IOP DMA channel abstrations. /// There are 14 channels in total (to make it even), with the last one being undefined. IopDmacChannel channels[Constants::IOP::DMAC::NUMBER_DMAC_CHANNELS - 1]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(pcr0), + CEREAL_NVP(icr0), + CEREAL_NVP(pcr1), + CEREAL_NVP(icr1), + CEREAL_NVP(gctrl), + CEREAL_NVP(channel_tomdec), + CEREAL_NVP(channel_frommdec), + CEREAL_NVP(channel_sif2), + CEREAL_NVP(channel_cdvd), + CEREAL_NVP(channel_spu2c0), + CEREAL_NVP(channel_pio), + CEREAL_NVP(channel_otclear), + CEREAL_NVP(channel_spu2c1), + CEREAL_NVP(channel_dev9), + CEREAL_NVP(channel_sif0), + CEREAL_NVP(channel_sif1), + CEREAL_NVP(channel_tosio2), + CEREAL_NVP(channel_fromsio2) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Iop/Intc/RIopIntc.hpp b/liborbum/src/Resources/Iop/Intc/RIopIntc.hpp index 5f6eda8a..f020b29a 100644 --- a/liborbum/src/Resources/Iop/Intc/RIopIntc.hpp +++ b/liborbum/src/Resources/Iop/Intc/RIopIntc.hpp @@ -8,4 +8,14 @@ struct RIopIntc IopIntcRegister_Ctrl ctrl; IopIntcRegister_Mask mask; IopIntcRegister_Stat stat; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(ctrl), + CEREAL_NVP(mask), + CEREAL_NVP(stat) + ); + } }; diff --git a/liborbum/src/Resources/Iop/RIop.hpp b/liborbum/src/Resources/Iop/RIop.hpp index 713926a7..479144b2 100644 --- a/liborbum/src/Resources/Iop/RIop.hpp +++ b/liborbum/src/Resources/Iop/RIop.hpp @@ -66,4 +66,46 @@ struct RIop SizedWordRegister register_15f0; SizedWordRegister register_2070; SizedWordRegister register_3800; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(core), + CEREAL_NVP(dmac), + CEREAL_NVP(intc), + CEREAL_NVP(timers), + CEREAL_NVP(sio0), + CEREAL_NVP(sio2), + CEREAL_NVP(main_memory), + CEREAL_NVP(parallel_port), + CEREAL_NVP(hw_ssbus_spd_addr), + CEREAL_NVP(hw_ssbus_pio_addr), + CEREAL_NVP(hw_ssbus_spd_delay), + CEREAL_NVP(hw_ssbus_dev1_delay), + CEREAL_NVP(hw_ssbus_rom_delay), + CEREAL_NVP(hw_ssbus_spu_delay), + CEREAL_NVP(hw_ssbus_dev5_delay), + CEREAL_NVP(hw_ssbus_pio_delay), + CEREAL_NVP(hw_ssbus_com_delay), + CEREAL_NVP(hw_ram_size), + CEREAL_NVP(hw_ssbus_dev1_addr), + CEREAL_NVP(hw_ssbus_spu_addr), + CEREAL_NVP(hw_ssbus_dev5_addr), + CEREAL_NVP(hw_ssbus_spu1_addr), + CEREAL_NVP(hw_ssbus_dev9_addr3), + CEREAL_NVP(hw_ssbus_spu1_delay), + CEREAL_NVP(hw_ssbus_dev9_delay2), + CEREAL_NVP(hw_ssbus_dev9_delay3), + CEREAL_NVP(hw_ssbus_dev9_delay1), + CEREAL_NVP(hw_icfg), + CEREAL_NVP(register_1470), + CEREAL_NVP(register_1560), + CEREAL_NVP(register_1564), + CEREAL_NVP(register_1568), + CEREAL_NVP(register_15f0), + CEREAL_NVP(register_2070), + CEREAL_NVP(register_3800) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Sio0/RSio0.hpp b/liborbum/src/Resources/Iop/Sio0/RSio0.hpp index f5cbd5a0..e74c0bfd 100644 --- a/liborbum/src/Resources/Iop/Sio0/RSio0.hpp +++ b/liborbum/src/Resources/Iop/Sio0/RSio0.hpp @@ -11,4 +11,15 @@ struct RSio0 Sio0Register_Stat stat; SizedHwordRegister mode; Sio0Register_Ctrl ctrl; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(data), + CEREAL_NVP(stat), + CEREAL_NVP(mode), + CEREAL_NVP(ctrl) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Iop/Sio0/Sio0Registers.hpp b/liborbum/src/Resources/Iop/Sio0/Sio0Registers.hpp index df0a6148..66e0bbe1 100644 --- a/liborbum/src/Resources/Iop/Sio0/Sio0Registers.hpp +++ b/liborbum/src/Resources/Iop/Sio0/Sio0Registers.hpp @@ -64,4 +64,13 @@ public: /// Reference to the SIO0 stat register, needed to change status bits /// depending on the different FIFO queue states (tx full/rx empty). Sio0Register_Stat* stat; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(command_queue), + CEREAL_NVP(response_queue) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Sio2/RSio2.hpp b/liborbum/src/Resources/Iop/Sio2/RSio2.hpp index a4d20baa..65a8723c 100644 --- a/liborbum/src/Resources/Iop/Sio2/RSio2.hpp +++ b/liborbum/src/Resources/Iop/Sio2/RSio2.hpp @@ -41,4 +41,34 @@ struct RSio2 SizedWordRegister register_8278; SizedWordRegister register_827c; SizedWordRegister intr; // Also known as the STAT register. + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(port_0), + CEREAL_NVP(port_1), + CEREAL_NVP(port_2), + CEREAL_NVP(port_3), + CEREAL_NVP(port_4), + CEREAL_NVP(port_5), + CEREAL_NVP(port_6), + CEREAL_NVP(port_7), + CEREAL_NVP(port_8), + CEREAL_NVP(port_9), + CEREAL_NVP(port_a), + CEREAL_NVP(port_b), + CEREAL_NVP(port_c), + CEREAL_NVP(port_d), + CEREAL_NVP(port_e), + CEREAL_NVP(port_f), + CEREAL_NVP(ctrl), + CEREAL_NVP(recv1), + CEREAL_NVP(recv2), + CEREAL_NVP(recv3), + CEREAL_NVP(register_8278), + CEREAL_NVP(register_827c), + CEREAL_NVP(intr) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Iop/Sio2/Sio2Ports.hpp b/liborbum/src/Resources/Iop/Sio2/Sio2Ports.hpp index f0ffc98b..673b750c 100644 --- a/liborbum/src/Resources/Iop/Sio2/Sio2Ports.hpp +++ b/liborbum/src/Resources/Iop/Sio2/Sio2Ports.hpp @@ -18,6 +18,16 @@ public: Sio2PortRegister_Ctrl1 ctrl_1; Sio2PortRegister_Ctrl2 ctrl_2; Sio2PortRegister_Ctrl3 ctrl_3; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(ctrl_1), + CEREAL_NVP(ctrl_2), + CEREAL_NVP(ctrl_3) + ); + } }; /// Port that contains only 1 CTRL register (ctrl_3). @@ -25,4 +35,12 @@ class Sio2Port_Slim { public: Sio2PortRegister_Ctrl3 ctrl_3; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(ctrl_3) + ); + } }; diff --git a/liborbum/src/Resources/Iop/Timers/IopTimersUnits.hpp b/liborbum/src/Resources/Iop/Timers/IopTimersUnits.hpp index 10d30650..27e64fd0 100644 --- a/liborbum/src/Resources/Iop/Timers/IopTimersUnits.hpp +++ b/liborbum/src/Resources/Iop/Timers/IopTimersUnits.hpp @@ -15,4 +15,15 @@ public: IopTimersUnitRegister_Count count; IopTimersUnitRegister_Mode mode; SizedWordRegister compare; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(unit_id), + CEREAL_NVP(count), + CEREAL_NVP(mode), + CEREAL_NVP(compare) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Iop/Timers/RIopTimers.hpp b/liborbum/src/Resources/Iop/Timers/RIopTimers.hpp index 4e43a693..e3e1c3b9 100644 --- a/liborbum/src/Resources/Iop/Timers/RIopTimers.hpp +++ b/liborbum/src/Resources/Iop/Timers/RIopTimers.hpp @@ -18,4 +18,17 @@ struct RIopTimers /// Timer abstractions. IopTimersUnit_Base* units[Constants::IOP::Timers::NUMBER_TIMERS]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(unit_0), + CEREAL_NVP(unit_1), + CEREAL_NVP(unit_2), + CEREAL_NVP(unit_3), + CEREAL_NVP(unit_4), + CEREAL_NVP(unit_5) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/RResources.hpp b/liborbum/src/Resources/RResources.hpp index 3f240ef7..c22a9b6a 100644 --- a/liborbum/src/Resources/RResources.hpp +++ b/liborbum/src/Resources/RResources.hpp @@ -70,9 +70,52 @@ struct RResources DmaFifoQueue<> fifo_dev9; DmaFifoQueue<> fifo_fromsio2; DmaFifoQueue<> fifo_tosio2; + + template + void serialize(Archive& archive) + { + archive( + CEREAL_NVP(ee), + CEREAL_NVP(gs), + CEREAL_NVP(iop), + CEREAL_NVP(spu2), + CEREAL_NVP(cdvd), + CEREAL_NVP(boot_rom), + CEREAL_NVP(rom1), + CEREAL_NVP(erom), + CEREAL_NVP(rom2), + CEREAL_NVP(sbus_mscom), + CEREAL_NVP(sbus_smcom), + CEREAL_NVP(sbus_msflg), + CEREAL_NVP(sbus_smflg), + CEREAL_NVP(sbus_f240), + CEREAL_NVP(sbus_f250), + CEREAL_NVP(sbus_f260), + CEREAL_NVP(sbus_f300), + CEREAL_NVP(sbus_f380), + CEREAL_NVP(fifo_vif0), + CEREAL_NVP(fifo_vif1), + CEREAL_NVP(fifo_gif), + CEREAL_NVP(fifo_fromipu), + CEREAL_NVP(fifo_toipu), + CEREAL_NVP(fifo_sif0), + CEREAL_NVP(fifo_sif1), + CEREAL_NVP(fifo_sif2), + CEREAL_NVP(fifo_frommdec), + CEREAL_NVP(fifo_tomdec), + CEREAL_NVP(fifo_cdvd), + CEREAL_NVP(fifo_spu2c0), + CEREAL_NVP(fifo_pio), + CEREAL_NVP(fifo_otclear), + CEREAL_NVP(fifo_spu2c1), + CEREAL_NVP(fifo_dev9), + CEREAL_NVP(fifo_fromsio2), + CEREAL_NVP(fifo_tosio2) + ); + } }; /// Initialises the resources by filling in references, performing bus mappings, etc. /// Only perform after RResources struct has been allocated! /// Done by the core after a reset. -void initialise_resources(const std::unique_ptr& r); \ No newline at end of file +void initialise_resources(const std::unique_ptr& r); diff --git a/liborbum/src/Resources/Spu2/RSpu2.hpp b/liborbum/src/Resources/Spu2/RSpu2.hpp index 4d50bacd..ff5b805b 100644 --- a/liborbum/src/Resources/Spu2/RSpu2.hpp +++ b/liborbum/src/Resources/Spu2/RSpu2.hpp @@ -40,4 +40,25 @@ struct RSpu2 ArrayByteMemory memory_0746; ArrayByteMemory memory_07b0; ArrayByteMemory memory_07ce; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(core_0), + CEREAL_NVP(core_1), + CEREAL_NVP(spdif_out), + CEREAL_NVP(spdif_irqinfo), + CEREAL_NVP(spdif_07c4), + CEREAL_NVP(spdif_mode), + CEREAL_NVP(spdif_media), + CEREAL_NVP(spdif_07ca), + CEREAL_NVP(spdif_protect), + CEREAL_NVP(main_memory), + CEREAL_NVP(memory_0346), + CEREAL_NVP(memory_0746), + CEREAL_NVP(memory_07b0), + CEREAL_NVP(memory_07ce) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Spu2/Spu2CoreVoice.hpp b/liborbum/src/Resources/Spu2/Spu2CoreVoice.hpp index 7df70ab7..bf8c1f4b 100644 --- a/liborbum/src/Resources/Spu2/Spu2CoreVoice.hpp +++ b/liborbum/src/Resources/Spu2/Spu2CoreVoice.hpp @@ -21,4 +21,25 @@ public: SizedHwordRegister lsaxl; SizedHwordRegister naxh; SizedHwordRegister naxl; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(voll), + CEREAL_NVP(volr), + CEREAL_NVP(pitch), + CEREAL_NVP(adsr1), + CEREAL_NVP(adsr2), + CEREAL_NVP(envx), + CEREAL_NVP(volxl), + CEREAL_NVP(volxr), + CEREAL_NVP(ssah), + CEREAL_NVP(ssal), + CEREAL_NVP(lsaxh), + CEREAL_NVP(lsaxl), + CEREAL_NVP(naxh), + CEREAL_NVP(naxl) + ); + } }; \ No newline at end of file diff --git a/liborbum/src/Resources/Spu2/Spu2Cores.hpp b/liborbum/src/Resources/Spu2/Spu2Cores.hpp index 6a3659ad..2267806b 100644 --- a/liborbum/src/Resources/Spu2/Spu2Cores.hpp +++ b/liborbum/src/Resources/Spu2/Spu2Cores.hpp @@ -144,4 +144,132 @@ public: Spu2CoreVoice voice_22; Spu2CoreVoice voice_23; Spu2CoreVoice* voices[Constants::SPU2::NUMBER_CORE_VOICES]; + + template + void serialize(Archive & archive) + { + archive( + CEREAL_NVP(core_id), + CEREAL_NVP(pmon0), + CEREAL_NVP(pmon1), + CEREAL_NVP(non0), + CEREAL_NVP(non1), + CEREAL_NVP(vmixl0), + CEREAL_NVP(vmixl1), + CEREAL_NVP(vmixel0), + CEREAL_NVP(vmixel1), + CEREAL_NVP(vmixr0), + CEREAL_NVP(vmixr1), + CEREAL_NVP(vmixer0), + CEREAL_NVP(vmixer1), + CEREAL_NVP(mmix), + CEREAL_NVP(attr), + CEREAL_NVP(irqah), + CEREAL_NVP(irqal), + CEREAL_NVP(kon0), + CEREAL_NVP(kon1), + CEREAL_NVP(kof0), + CEREAL_NVP(kof1), + CEREAL_NVP(tsah), + CEREAL_NVP(tsal), + CEREAL_NVP(data0), + CEREAL_NVP(data1), + CEREAL_NVP(admas), + CEREAL_NVP(esah), + CEREAL_NVP(esal), + CEREAL_NVP(apf1_sizeh), + CEREAL_NVP(apf1_sizel), + CEREAL_NVP(apf2_sizeh), + CEREAL_NVP(apf2_sizel), + CEREAL_NVP(same_l_dsth), + CEREAL_NVP(same_l_dstl), + CEREAL_NVP(same_r_dsth), + CEREAL_NVP(same_r_dstl), + CEREAL_NVP(comb1_l_srch), + CEREAL_NVP(comb1_l_srcl), + CEREAL_NVP(comb1_r_srch), + CEREAL_NVP(comb1_r_srcl), + CEREAL_NVP(comb2_l_srch), + CEREAL_NVP(comb2_l_srcl), + CEREAL_NVP(comb2_r_srch), + CEREAL_NVP(comb2_r_srcl), + CEREAL_NVP(same_l_srch), + CEREAL_NVP(same_l_srcl), + CEREAL_NVP(same_r_srch), + CEREAL_NVP(same_r_srcl), + CEREAL_NVP(diff_l_dsth), + CEREAL_NVP(diff_l_dstl), + CEREAL_NVP(diff_r_dsth), + CEREAL_NVP(diff_r_dstl), + CEREAL_NVP(comb3_l_srch), + CEREAL_NVP(comb3_l_srcl), + CEREAL_NVP(comb3_r_srch), + CEREAL_NVP(comb3_r_srcl), + CEREAL_NVP(comb4_l_srch), + CEREAL_NVP(comb4_l_srcl), + CEREAL_NVP(comb4_r_srch), + CEREAL_NVP(comb4_r_srcl), + CEREAL_NVP(diff_l_srch), + CEREAL_NVP(diff_l_srcl), + CEREAL_NVP(diff_r_srch), + CEREAL_NVP(diff_r_srcl), + CEREAL_NVP(apf1_l_dsth), + CEREAL_NVP(apf1_l_dstl), + CEREAL_NVP(apf1_r_dsth), + CEREAL_NVP(apf1_r_dstl), + CEREAL_NVP(apf2_l_dsth), + CEREAL_NVP(apf2_l_dstl), + CEREAL_NVP(apf2_r_dsth), + CEREAL_NVP(apf2_r_dstl), + CEREAL_NVP(eeah), + CEREAL_NVP(eeal), + CEREAL_NVP(endx0), + CEREAL_NVP(endx1), + CEREAL_NVP(statx), + CEREAL_NVP(mvoll), + CEREAL_NVP(mvolr), + CEREAL_NVP(evoll), + CEREAL_NVP(evolr), + CEREAL_NVP(avoll), + CEREAL_NVP(avolr), + CEREAL_NVP(bvoll), + CEREAL_NVP(bvolr), + CEREAL_NVP(mvolxl), + CEREAL_NVP(mvolxr), + CEREAL_NVP(iir_vol), + CEREAL_NVP(comb1_vol), + CEREAL_NVP(comb2_vol), + CEREAL_NVP(comb3_vol), + CEREAL_NVP(comb4_vol), + CEREAL_NVP(wall_vol), + CEREAL_NVP(apf1_vol), + CEREAL_NVP(apf2_vol), + CEREAL_NVP(in_coef_l), + CEREAL_NVP(in_coef_r), + CEREAL_NVP(voice_0), + CEREAL_NVP(voice_1), + CEREAL_NVP(voice_2), + CEREAL_NVP(voice_3), + CEREAL_NVP(voice_4), + CEREAL_NVP(voice_5), + CEREAL_NVP(voice_6), + CEREAL_NVP(voice_7), + CEREAL_NVP(voice_8), + CEREAL_NVP(voice_9), + CEREAL_NVP(voice_10), + CEREAL_NVP(voice_11), + CEREAL_NVP(voice_12), + CEREAL_NVP(voice_13), + CEREAL_NVP(voice_14), + CEREAL_NVP(voice_15), + CEREAL_NVP(voice_16), + CEREAL_NVP(voice_17), + CEREAL_NVP(voice_18), + CEREAL_NVP(voice_19), + CEREAL_NVP(voice_20), + CEREAL_NVP(voice_21), + CEREAL_NVP(voice_22), + CEREAL_NVP(voice_23) + ); + } }; diff --git a/orbumfront/CMakeLists.txt b/orbumfront/CMakeLists.txt index e0af4239..dcc1cff8 100644 --- a/orbumfront/CMakeLists.txt +++ b/orbumfront/CMakeLists.txt @@ -4,29 +4,29 @@ cmake_policy(SET CMP0069 NEW) # Link time optimization support project(orbumfront CXX) set(COMMON_SRC_FILES - "${CMAKE_SOURCE_DIR}/orbumfront/src/OrbumFront.cpp" + "${CMAKE_SOURCE_DIR}/orbumfront/src/OrbumFront.cpp" ) add_executable(orbumfront "${COMMON_SRC_FILES}") target_link_libraries( - orbumfront - PUBLIC - "${CMAKE_THREAD_LIBS_INIT}" - utilities - orbum + orbumfront + PUBLIC + "${CMAKE_THREAD_LIBS_INIT}" + utilities + orbum ) # TODO: Sort out later into proper build configurations. # Also disable MSVC non-safe copy warnings. target_compile_definitions( - orbumfront - PUBLIC - "_SCL_SECURE_NO_WARNINGS" - "BUILD_DEBUG" + orbumfront + PUBLIC + "_SCL_SECURE_NO_WARNINGS" + "BUILD_DEBUG" ) install( - TARGETS orbumfront - RUNTIME DESTINATION "bin" + TARGETS orbumfront + RUNTIME DESTINATION "bin" ) diff --git a/orbumfront/src/OrbumFront.cpp b/orbumfront/src/OrbumFront.cpp index d946d561..6981bdb3 100644 --- a/orbumfront/src/OrbumFront.cpp +++ b/orbumfront/src/OrbumFront.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -6,11 +7,67 @@ #include #include -volatile bool DEBUG_RUN = true; +bool quit = false; +volatile bool show_main_menu = false; void signal_handler(int signal) { - DEBUG_RUN = false; + show_main_menu = true; + + // This is a win32 specific thing? Otherwise subsequent signals are not caught... + // https://stackoverflow.com/questions/43959514/why-the-second-sigint-cant-be-captured-on-win32 + std::signal(SIGINT, signal_handler); + std::signal(SIGBREAK, signal_handler); +} + +void main_menu(CoreApi& core) +{ + char c = '\0'; + do + { + switch (c) + { + case '1': + case 's': + { + puts("Saving state..."); + core.save_state(); + puts("Saved state ok"); + break; + } + case '2': + case 'd': + { + puts("Dumping memory..."); + core.dump_all_memory(); + puts("Dumped memory ok"); + break; + } + case '3': + case 'c': + { + goto exit_menu; + } + case '4': + case 'q': + { + quit = true; + goto exit_menu; + } + } + + puts("Orbum main menu"); + puts(" 1. (s)ave state (json)"); + puts(" 2. (d)ump all memory (binary)"); + puts(" 3. (c)ontinue"); + puts(" 4. (q)uit"); + fputs("Select an option: ", stdout); + + } while ((c = getchar())); + +exit_menu: + puts(""); + show_main_menu = false; } int main(int argc, char* argv[]) @@ -18,9 +75,12 @@ int main(int argc, char* argv[]) std::cout << "Command line: "; for (int i = 0; i < argc; i++) std::cout << argv[i] << ", "; + std::cout << std::endl << "Working directory: " << boost::filesystem::initial_path() << std::endl; + std::signal(SIGINT, signal_handler); + std::signal(SIGBREAK, signal_handler); try { @@ -28,15 +88,17 @@ int main(int argc, char* argv[]) try { - while (DEBUG_RUN) + while (!quit) + { core.run(); + if (show_main_menu) + main_menu(core); + } } catch (const std::runtime_error& e) { std::cout << "Core running fatal error: " << e.what() << std::endl; } - - core.dump_all_memory(); } catch (const std::exception& e) { diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index ac35c63f..cbc8120a 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -4,26 +4,34 @@ cmake_policy(SET CMP0069 NEW) # Link time optimization support project(utilities CXX) set(COMMON_SRC_FILES - "${CMAKE_SOURCE_DIR}/utilities/src/Macros.hpp" - "${CMAKE_SOURCE_DIR}/utilities/src/TaskExecutor.hpp" - "${CMAKE_SOURCE_DIR}/utilities/src/Queues.hpp" - "${CMAKE_SOURCE_DIR}/utilities/src/EnumMap.hpp" - "${CMAKE_SOURCE_DIR}/utilities/src/Caches.hpp" - "${CMAKE_SOURCE_DIR}/utilities/src/Console.hpp" - "${CMAKE_SOURCE_DIR}/utilities/src/Console.cpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Macros.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/TaskExecutor.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Queues.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/EnumMap.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Caches.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Console.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Console.cpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Datetime.hpp" + "${CMAKE_SOURCE_DIR}/utilities/src/Datetime.cpp" ) add_library(utilities STATIC "${COMMON_SRC_FILES}") target_sources( - utilities - PUBLIC - "${COMMON_SRC_FILES}" + utilities + PUBLIC + "${COMMON_SRC_FILES}" ) target_include_directories( - utilities - PUBLIC - "${Boost_INCLUDE_DIR}" - "${CMAKE_SOURCE_DIR}/utilities/src" + utilities + PUBLIC + "${Boost_INCLUDE_DIR}" + "${CMAKE_SOURCE_DIR}/utilities/src" ) + +target_compile_definitions( + utilities + PUBLIC + "_CRT_SECURE_NO_WARNINGS" +) \ No newline at end of file diff --git a/utilities/src/Console.cpp b/utilities/src/Console.cpp index c9d25e77..a2da878f 100644 --- a/utilities/src/Console.cpp +++ b/utilities/src/Console.cpp @@ -1,5 +1,4 @@ #include "Console.hpp" - #include "Macros.hpp" #if defined(ENV_WINDOWS) diff --git a/utilities/src/Datetime.cpp b/utilities/src/Datetime.cpp new file mode 100644 index 00000000..3d5c6fe0 --- /dev/null +++ b/utilities/src/Datetime.cpp @@ -0,0 +1,11 @@ +#include "Datetime.hpp" + +std::string datetime_fmt(const char* format, const std::time_t datetime) +{ + char buf[100]; + + if (!std::strftime(buf, sizeof(buf), format, std::localtime(&datetime))) + throw std::runtime_error("Failed to print current time"); + + return std::string(buf); +} \ No newline at end of file diff --git a/utilities/src/Datetime.hpp b/utilities/src/Datetime.hpp new file mode 100644 index 00000000..00edad3b --- /dev/null +++ b/utilities/src/Datetime.hpp @@ -0,0 +1,6 @@ +#include +#include + +/// Returns a string of the given date and time with the specified format string. +/// Defaults to the current time. +std::string datetime_fmt(const char* format, const std::time_t datetime = std::time(nullptr)); diff --git a/utilities/src/Queues.hpp b/utilities/src/Queues.hpp index 9dc31a06..5b09f53a 100644 --- a/utilities/src/Queues.hpp +++ b/utilities/src/Queues.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -140,6 +141,36 @@ private: std::condition_variable empty_cv; std::condition_variable full_cv; QueueTy queue; + +public: + template + void save(Archive & archive) const + { + size_t length = queue.read_available(); + std::vector vec(length); + + for (size_t i = 0; i < length; i++) + vec[i] = *(&queue.front() + i * sizeof(ItemTy)); + + archive(CEREAL_NVP(length)); + archive.saveBinaryValue(vec.data(), vec.size(), "data"); + } + + template + void load(Archive & archive) + { + queue.reset(); + + size_t length; + archive(CEREAL_NVP(length)); + + std::vector vec(length); + + archive.loadBinaryValue(vec.data(), vec.size(), "data"); + + for (const auto& item : vec) + queue.push(item); + } }; /// MPSC blocking/try queue.