diff --git a/src/acs/CMakeLists.txt b/src/acs/CMakeLists.txt index 8eb668570..e684675af 100644 --- a/src/acs/CMakeLists.txt +++ b/src/acs/CMakeLists.txt @@ -5,6 +5,8 @@ target_sources(SRB2SDL2 PRIVATE thread.hpp call-funcs.cpp call-funcs.hpp + stream.cpp + stream.hpp interface.cpp interface.h ) diff --git a/src/acs/interface.cpp b/src/acs/interface.cpp index 1e10e4425..6094c430c 100644 --- a/src/acs/interface.cpp +++ b/src/acs/interface.cpp @@ -21,6 +21,7 @@ extern "C" { #include "../r_defs.h" #include "../g_game.h" #include "../i_system.h" +#include "../p_saveg.h" } #include @@ -39,6 +40,7 @@ extern "C" { #include "environment.hpp" #include "thread.hpp" +#include "stream.hpp" #include "../cxxutil.hpp" @@ -230,3 +232,56 @@ void ACS_Tick(void) env->exec(); } } + +/*-------------------------------------------------- + void ACS_Archive(savebuffer_t *save) + + See header file for description. +--------------------------------------------------*/ +void ACS_Archive(savebuffer_t *save) +{ + Environment *env = &ACSEnv; + + SaveBuffer buffer{save}; + std::ostream stream{&buffer}; + ACSVM::Serial serial{stream}; + + // Enable debug signatures. + serial.signs = true; + + try + { + serial.saveHead(); + env->saveState(serial); + serial.saveTail(); + } + catch (ACSVM::SerialError const &e) + { + I_Error("ACS_Archive: %s\n", e.what()); + } +} + +/*-------------------------------------------------- + void ACS_UnArchive(savebuffer_t *save) + + See header file for description. +--------------------------------------------------*/ +void ACS_UnArchive(savebuffer_t *save) +{ + Environment *env = &ACSEnv; + + SaveBuffer buffer{save}; + std::istream stream{&buffer}; + ACSVM::Serial serial{stream}; + + try + { + serial.loadHead(); + env->loadState(serial); + serial.loadTail(); + } + catch (ACSVM::SerialError const &e) + { + I_Error("ACS_UnArchive: %s\n", e.what()); + } +} diff --git a/src/acs/interface.h b/src/acs/interface.h index 9f0cf9d5c..96ca834fa 100644 --- a/src/acs/interface.h +++ b/src/acs/interface.h @@ -113,4 +113,34 @@ void ACS_RunLapScript(mobj_t *mo, line_t *line); void ACS_Tick(void); +/*-------------------------------------------------- + void ACS_Archive(savebuffer_t *save); + + Saves the ACS VM state into a save buffer. + + Input Arguments:- + save: Pointer to the save buffer from P_SaveNetGame. + + Return:- + None +--------------------------------------------------*/ + +void ACS_Archive(savebuffer_t *save); + + +/*-------------------------------------------------- + void ACS_UnArchive(savebuffer_t *save); + + Loads the ACS VM state from a save buffer. + + Input Arguments:- + save: Pointer to the save buffer from P_LoadNetGame. + + Return:- + None +--------------------------------------------------*/ + +void ACS_UnArchive(savebuffer_t *save); + + #endif // __SRB2_ACS_INTERFACE_H__ diff --git a/src/acs/stream.cpp b/src/acs/stream.cpp new file mode 100644 index 000000000..ed49b6a62 --- /dev/null +++ b/src/acs/stream.cpp @@ -0,0 +1,71 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity) +// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2022 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file stream.cpp +/// \brief Action Code Script: Dummy stream buffer to +/// interact with P_Save/LoadNetGame + +// TODO? Maybe untie this file from ACS? + +extern "C" { +#include "../doomtype.h" +#include "../doomdef.h" +#include "../doomstat.h" + +#include "../p_saveg.h" +} + +#include "stream.hpp" +#include "../cxxutil.hpp" + +#include +#include +#include + +using namespace srb2::acs; + +SaveBuffer::SaveBuffer(savebuffer_t *save_) : + save{save_} +{ +} + +SaveBuffer::int_type SaveBuffer::overflow(SaveBuffer::int_type ch) +{ + if (save->p == save->end) + { + return traits_type::eof(); + } + + *save->p = static_cast(ch); + save->p++; + + return ch; +} + +SaveBuffer::int_type SaveBuffer::underflow() +{ + if (save->p == save->end) + { + return traits_type::eof(); + } + + UINT8 ret = *save->p; + save->p++; + + // Allow the streambuf internal funcs to work + buf[0] = ret; + setg( + reinterpret_cast(buf), + reinterpret_cast(buf), + reinterpret_cast(buf + 1) + ); + + return static_cast(ret); +} diff --git a/src/acs/stream.hpp b/src/acs/stream.hpp new file mode 100644 index 000000000..7e24e288b --- /dev/null +++ b/src/acs/stream.hpp @@ -0,0 +1,59 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2016 by James Haley, David Hill, et al. (Team Eternity) +// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2022 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file stream.hpp +/// \brief Action Code Script: Dummy stream buffer to +/// interact with P_Save/LoadNetGame + +// TODO? Maybe untie this file from ACS? + +#ifndef __SRB2_ACS_STREAM_HPP__ +#define __SRB2_ACS_STREAM_HPP__ + +extern "C" { +#include "../doomtype.h" +#include "../doomdef.h" +#include "../doomstat.h" +#include "../p_saveg.h" +} + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace srb2::acs { + +class SaveBuffer : public std::streambuf +{ +public: + savebuffer_t *save; + UINT8 buf[1]; + + explicit SaveBuffer(savebuffer_t *save_); + +private: + virtual int_type overflow(int_type ch); + virtual int_type underflow(); +}; + +} + +#endif // __SRB2_ACS_STREAM_HPP__ diff --git a/src/p_saveg.c b/src/p_saveg.c index e7eabf4b3..2ac14329e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -41,6 +41,7 @@ #include "k_battle.h" #include "k_pwrlv.h" #include "k_terrain.h" +#include "acs/interface.h" savedata_t savedata; @@ -5176,6 +5177,8 @@ void P_SaveNetGame(savebuffer_t *save, boolean resending) P_NetArchiveTubeWaypoints(save); P_NetArchiveWaypoints(save); } + + ACS_Archive(save); LUA_Archive(save, true); P_NetArchiveRNG(save); @@ -5226,6 +5229,7 @@ boolean P_LoadNetGame(savebuffer_t *save, boolean reloading) P_FinishMobjs(); } + ACS_UnArchive(save); LUA_UnArchive(save, true); P_NetUnArchiveRNG(save);