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
|
retroregistry.cpp
|
||||||
retroframe.cpp
|
retroframe.cpp
|
||||||
diskcontrol.cpp
|
diskcontrol.cpp
|
||||||
|
serialisation.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
|
libretro-common/include/libretro.h
|
||||||
environment.h
|
environment.h
|
||||||
rdirectsound.h
|
rdirectsound.h
|
||||||
game.h
|
game.h
|
||||||
|
@ -25,7 +27,7 @@ set(HEADER_FILES
|
||||||
retroregistry.h
|
retroregistry.h
|
||||||
retroframe.h
|
retroframe.h
|
||||||
diskcontrol.h
|
diskcontrol.h
|
||||||
libretro-common/include/libretro.h
|
serialisation.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(applewin_libretro SHARED
|
add_library(applewin_libretro SHARED
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "frontends/libretro/joypad.h"
|
#include "frontends/libretro/joypad.h"
|
||||||
#include "frontends/libretro/analog.h"
|
#include "frontends/libretro/analog.h"
|
||||||
#include "frontends/libretro/mouse.h"
|
#include "frontends/libretro/mouse.h"
|
||||||
|
#include "frontends/libretro/serialisation.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -362,19 +363,22 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
|
||||||
size_t retro_serialize_size(void)
|
size_t retro_serialize_size(void)
|
||||||
{
|
{
|
||||||
ra2::log_cb(RETRO_LOG_INFO, "RA2: %s\n", __FUNCTION__);
|
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)
|
bool retro_serialize(void *data, size_t size)
|
||||||
{
|
{
|
||||||
ra2::log_cb(RETRO_LOG_INFO, "RA2: %s\n", __FUNCTION__);
|
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)
|
bool retro_unserialize(const void *data, size_t size)
|
||||||
{
|
{
|
||||||
ra2::log_cb(RETRO_LOG_INFO, "RA2: %s\n", __FUNCTION__);
|
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)
|
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