libretro: implement save/load state.

Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
Andrea Odetti 2021-11-27 21:27:46 +00:00
parent 741849a026
commit 7037e20c0f
4 changed files with 160 additions and 4 deletions

View file

@ -11,9 +11,11 @@ set(SOURCE_FILES
retroregistry.cpp
retroframe.cpp
diskcontrol.cpp
serialisation.cpp
)
set(HEADER_FILES
libretro-common/include/libretro.h
environment.h
rdirectsound.h
game.h
@ -25,7 +27,7 @@ set(HEADER_FILES
retroregistry.h
retroframe.h
diskcontrol.h
libretro-common/include/libretro.h
serialisation.h
)
add_library(applewin_libretro SHARED

View file

@ -19,6 +19,7 @@
#include "frontends/libretro/joypad.h"
#include "frontends/libretro/analog.h"
#include "frontends/libretro/mouse.h"
#include "frontends/libretro/serialisation.h"
namespace
{
@ -362,19 +363,22 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
size_t retro_serialize_size(void)
{
ra2::log_cb(RETRO_LOG_INFO, "RA2: %s\n", __FUNCTION__);
return 0;
const size_t size = ra2::RetroSerialisation::getSize();
// we cannot guarantee exact file size, so we allow for a small grace buffer
const size_t buffer = 4096;
return size + buffer;
}
bool retro_serialize(void *data, size_t size)
{
ra2::log_cb(RETRO_LOG_INFO, "RA2: %s\n", __FUNCTION__);
return false;
return ra2::RetroSerialisation::serialise(static_cast<char *>(data), size);
}
bool retro_unserialize(const void *data, size_t size)
{
ra2::log_cb(RETRO_LOG_INFO, "RA2: %s\n", __FUNCTION__);
return false;
return ra2::RetroSerialisation::deserialise(static_cast<const char *>(data), size);
}
void retro_cheat_reset(void)

View file

@ -0,0 +1,136 @@
#include "StdAfx.h"
#include "SaveState.h"
#include "frontends/libretro/serialisation.h"
#include "frontends/libretro/environment.h"
#include <cstdio>
#include <fstream>
namespace
{
class AutoFile
{
public:
AutoFile();
~AutoFile();
std::string getFilename() const; // only if true
operator bool() const;
protected:
const char * myFilename;
};
AutoFile::AutoFile()
{
// massive race condition, but without changes to AW, little can we do here
myFilename = std::tmpnam(nullptr);
}
AutoFile::~AutoFile()
{
std::remove(myFilename);
}
AutoFile::operator bool() const
{
return myFilename;
}
std::string AutoFile::getFilename() const
{
return myFilename;
}
void saveToFile(const std::string & filename) // cannot be null!
{
Snapshot_SetFilename(filename);
Snapshot_SaveState();
}
}
namespace ra2
{
size_t RetroSerialisation::getSize()
{
AutoFile autoFile;
if (!autoFile)
{
return 0;
}
const std::string filename = autoFile.getFilename();
saveToFile(filename);
std::ifstream ifs(filename, std::ios::binary | std::ios::ate);
const std::ifstream::pos_type fileSize = ifs.tellg();
return sizeof(uint32_t) + fileSize;
}
bool RetroSerialisation::serialise(char * data, size_t size)
{
AutoFile autoFile;
if (!autoFile)
{
return 0;
}
const std::string filename = autoFile.getFilename();
saveToFile(filename);
std::ifstream ifs(filename, std::ios::binary | std::ios::ate);
const std::ifstream::pos_type fileSize = ifs.tellg();
if (sizeof(uint32_t) + fileSize > size)
{
return false;
}
else
{
uint32_t * sizePtr = reinterpret_cast<uint32_t *>(data);
*sizePtr = fileSize;
char * dataPtr = data + sizeof(uint32_t);
ifs.seekg(0, std::ios::beg);
ifs.read(dataPtr, fileSize);
return true;
}
}
bool RetroSerialisation::deserialise(const char * data, size_t size)
{
AutoFile autoFile;
if (!autoFile)
{
return false;
}
const uint32_t * sizePtr = reinterpret_cast<const uint32_t *>(data);
const size_t fileSize = *sizePtr;
if (sizeof(uint32_t) + fileSize > size)
{
return false;
}
else
{
const char * dataPtr = data + sizeof(uint32_t);
const std::string filename = autoFile.getFilename();
// do not remove the {} scope below!
{
std::ofstream ofs(filename, std::ios::binary);
ofs.write(dataPtr, fileSize);
}
Snapshot_SetFilename(filename);
Snapshot_LoadState();
return true;
}
}
}

View file

@ -0,0 +1,14 @@
#include <cstddef>
namespace ra2
{
class RetroSerialisation
{
public:
static size_t getSize();
static bool serialise(char * data, size_t size);
static bool deserialise(const char * data, size_t size);
};
}