libretro: implement save/load state.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
741849a026
commit
7037e20c0f
4 changed files with 160 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
136
source/frontends/libretro/serialisation.cpp
Normal file
136
source/frontends/libretro/serialisation.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
14
source/frontends/libretro/serialisation.h
Normal file
14
source/frontends/libretro/serialisation.h
Normal 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);
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue