mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 14:18:37 +00:00
TOLTECS: - Listing savestates via command line or Launcher
- Loading/Saving during run time Other savestate functions yet todo. I'll probably remove the "original" in-game menu and move everything to the GMM.
This commit is contained in:
parent
47ae908589
commit
9e78b5d393
@ -56,7 +56,7 @@ namespace Toltecs {
|
||||
static const ToltecsGameDescription gameDescriptions[] = {
|
||||
|
||||
{
|
||||
// Toltecs English version
|
||||
// 3 Skulls of the Toltecs English version
|
||||
{
|
||||
"toltecs",
|
||||
0,
|
||||
@ -67,8 +67,8 @@ static const ToltecsGameDescription gameDescriptions[] = {
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
// 3 Skulls of the Toltecs Russian version
|
||||
{
|
||||
"toltecs",
|
||||
0,
|
||||
@ -115,9 +115,30 @@ public:
|
||||
return "Toltecs Engine (C) 1996";
|
||||
}
|
||||
|
||||
virtual bool hasFeature(MetaEngineFeature f) const;
|
||||
virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
|
||||
SaveStateList listSaves(const char *target) const;
|
||||
virtual int getMaximumSaveSlot() const;
|
||||
void removeSaveState(const char *target, int slot) const;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
|
||||
};
|
||||
|
||||
bool ToltecsMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return
|
||||
(f == kSupportsListSaves) ||
|
||||
// (f == kSupportsLoadingDuringStartup) ||
|
||||
// (f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail);
|
||||
}
|
||||
|
||||
bool Toltecs::ToltecsEngine::hasFeature(EngineFeature f) const {
|
||||
return
|
||||
// (f == kSupportsRTL) ||
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
bool ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
|
||||
const Toltecs::ToltecsGameDescription *gd = (const Toltecs::ToltecsGameDescription *)desc;
|
||||
if (gd) {
|
||||
@ -126,6 +147,100 @@ bool ToltecsMetaEngine::createInstance(OSystem *syst, Engine **engine, const Com
|
||||
return gd != 0;
|
||||
}
|
||||
|
||||
SaveStateList ToltecsMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Toltecs::ToltecsEngine::SaveHeader header;
|
||||
Common::String pattern = target;
|
||||
pattern += ".???";
|
||||
|
||||
Common::StringList filenames;
|
||||
filenames = saveFileMan->listSavefiles(pattern.c_str());
|
||||
Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
|
||||
|
||||
SaveStateList saveList;
|
||||
for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(file->c_str() + file->size() - 3);
|
||||
|
||||
if (slotNum >= 0 && slotNum <= 999) {
|
||||
Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str());
|
||||
if (in) {
|
||||
if (Toltecs::ToltecsEngine::readSaveHeader(in, false, header) == Toltecs::ToltecsEngine::kRSHENoError) {
|
||||
saveList.push_back(SaveStateDescriptor(slotNum, header.description));
|
||||
}
|
||||
delete in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return saveList;
|
||||
}
|
||||
|
||||
int ToltecsMetaEngine::getMaximumSaveSlot() const {
|
||||
return 999;
|
||||
}
|
||||
|
||||
void ToltecsMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
// Slot 0 can't be deleted, it's for restarting the game(s)
|
||||
if (slot == 0)
|
||||
return;
|
||||
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::String filename = Toltecs::ToltecsEngine::getSavegameFilename(target, slot);
|
||||
|
||||
saveFileMan->removeSavefile(filename.c_str());
|
||||
|
||||
Common::StringList filenames;
|
||||
Common::String pattern = target;
|
||||
pattern += ".???";
|
||||
filenames = saveFileMan->listSavefiles(pattern.c_str());
|
||||
Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
|
||||
|
||||
for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(file->c_str() + file->size() - 3);
|
||||
|
||||
// Rename every slot greater than the deleted slot,
|
||||
// Also do not rename quicksaves.
|
||||
if (slotNum > slot && slotNum < 990) {
|
||||
// FIXME: Our savefile renaming done here is inconsitent with what we do in
|
||||
// GUI_v2::deleteMenu. While here we rename every slot with a greater equal
|
||||
// number of the deleted slot to deleted slot, deleted slot + 1 etc.,
|
||||
// we only rename the following slots in GUI_v2::deleteMenu until a slot
|
||||
// is missing.
|
||||
saveFileMan->renameSavefile(file->c_str(), filename.c_str());
|
||||
|
||||
filename = Toltecs::ToltecsEngine::getSavegameFilename(target, ++slot);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SaveStateDescriptor ToltecsMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String filename = Toltecs::ToltecsEngine::getSavegameFilename(target, slot);
|
||||
Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str());
|
||||
|
||||
if (in) {
|
||||
Toltecs::ToltecsEngine::SaveHeader header;
|
||||
Toltecs::ToltecsEngine::kReadSaveHeaderError error;
|
||||
|
||||
error = Toltecs::ToltecsEngine::readSaveHeader(in, true, header);
|
||||
delete in;
|
||||
|
||||
if (error == Toltecs::ToltecsEngine::kRSHENoError) {
|
||||
SaveStateDescriptor desc(slot, header.description);
|
||||
|
||||
desc.setDeletableFlag(false);
|
||||
desc.setWriteProtectedFlag(false);
|
||||
desc.setThumbnail(header.thumbnail);
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(TOLTECS)
|
||||
REGISTER_PLUGIN_DYNAMIC(TOLTECS, PLUGIN_TYPE_ENGINE, ToltecsMetaEngine);
|
||||
#else
|
||||
|
@ -52,6 +52,8 @@ void MoviePlayer::playMovie(uint resIndex) {
|
||||
uint32 subtitleSlot;
|
||||
byte moviePalette[768];
|
||||
|
||||
_vm->_isSaveAllowed = false;
|
||||
|
||||
memset(moviePalette, 0, sizeof(moviePalette));
|
||||
|
||||
_vm->_screen->finishTalkTextItems();
|
||||
@ -176,6 +178,8 @@ void MoviePlayer::playMovie(uint resIndex) {
|
||||
|
||||
debug(0, "playMovie() done");
|
||||
|
||||
_vm->_isSaveAllowed = true;
|
||||
|
||||
}
|
||||
|
||||
void MoviePlayer::fetchAudioChunks() {
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "base/plugins.h"
|
||||
#include "base/version.h"
|
||||
|
||||
#include "graphics/thumbnail.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "toltecs/toltecs.h"
|
||||
@ -44,14 +46,43 @@ namespace Toltecs {
|
||||
|
||||
/* TODO:
|
||||
- Saveload is working so far but only one slot is supported until the game menu is implemented
|
||||
- Save with F6; Load with F9
|
||||
- Save with F7; Load with F9
|
||||
- Saving during an animation (AnimationPlayer) is not working correctly yet
|
||||
- Maybe switch to SCUMM/Tinsel serialization approach?
|
||||
*/
|
||||
|
||||
#define SAVEGAME_VERSION 0 // 0 is dev version until in official SVN
|
||||
|
||||
void ToltecsEngine::savegame(const char *filename) {
|
||||
ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) {
|
||||
|
||||
header.version = in->readUint32LE();
|
||||
if (header.version != SAVEGAME_VERSION)
|
||||
return kRSHEInvalidVersion;
|
||||
|
||||
byte descriptionLen = in->readByte();
|
||||
header.description = "";
|
||||
while (descriptionLen--)
|
||||
header.description += (char)in->readByte();
|
||||
|
||||
if (loadThumbnail) {
|
||||
header.thumbnail = new Graphics::Surface();
|
||||
assert(header.thumbnail);
|
||||
if (!Graphics::loadThumbnail(*in, *header.thumbnail)) {
|
||||
delete header.thumbnail;
|
||||
header.thumbnail = 0;
|
||||
}
|
||||
} else {
|
||||
Graphics::skipThumbnailHeader(*in);
|
||||
}
|
||||
|
||||
// Not used yet, reserved for future usage
|
||||
header.gameID = in->readByte();
|
||||
header.flags = in->readUint32LE();
|
||||
|
||||
return (in->ioFailed() ? kRSHEIoError : kRSHENoError);
|
||||
}
|
||||
|
||||
void ToltecsEngine::savegame(const char *filename, const char *description) {
|
||||
|
||||
Common::OutSaveFile *out;
|
||||
if (!(out = g_system->getSavefileManager()->openForSaving(filename))) {
|
||||
@ -61,6 +92,16 @@ void ToltecsEngine::savegame(const char *filename) {
|
||||
|
||||
out->writeUint32LE(SAVEGAME_VERSION);
|
||||
|
||||
byte descriptionLen = strlen(description);
|
||||
out->writeByte(descriptionLen);
|
||||
out->write(description, descriptionLen);
|
||||
|
||||
Graphics::saveThumbnail(*out);
|
||||
|
||||
// Not used yet, reserved for future usage
|
||||
out->writeByte(0);
|
||||
out->writeUint32LE(0);
|
||||
|
||||
out->writeUint16LE(_cameraX);
|
||||
out->writeUint16LE(_cameraY);
|
||||
out->writeUint16LE(_cameraHeight);
|
||||
@ -99,10 +140,14 @@ void ToltecsEngine::loadgame(const char *filename) {
|
||||
warning("Can't open file '%s', game not loaded", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
SaveHeader header;
|
||||
|
||||
kReadSaveHeaderError errorCode = readSaveHeader(in, false, header);
|
||||
|
||||
uint32 version = in->readUint32LE();
|
||||
if (version != SAVEGAME_VERSION) {
|
||||
warning("Savegame '%s' too old, game not loaded (got v%d, need v%d)", filename, version, SAVEGAME_VERSION);
|
||||
if (errorCode != kRSHENoError) {
|
||||
warning("Error loading savegame '%s'", filename);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -145,4 +190,29 @@ void ToltecsEngine::loadgame(const char *filename) {
|
||||
|
||||
}
|
||||
|
||||
Common::Error ToltecsEngine::loadGameState(int slot) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
loadgame(fileName);
|
||||
}
|
||||
|
||||
Common::Error ToltecsEngine::saveGameState(int slot, const char *description) {
|
||||
const char *fileName = getSavegameFilename(slot);
|
||||
savegame(fileName, description);
|
||||
}
|
||||
|
||||
const char *ToltecsEngine::getSavegameFilename(int num) {
|
||||
static Common::String filename;
|
||||
filename = getSavegameFilename(_targetName, num);
|
||||
return filename.c_str();
|
||||
}
|
||||
|
||||
Common::String ToltecsEngine::getSavegameFilename(const Common::String &target, int num) {
|
||||
assert(num >= 0 && num <= 999);
|
||||
|
||||
char extension[5];
|
||||
sprintf(extension, "%03d", num);
|
||||
|
||||
return target + "." + extension;
|
||||
}
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
@ -79,16 +79,28 @@ ToltecsEngine::~ToltecsEngine() {
|
||||
delete _rnd;
|
||||
}
|
||||
|
||||
int ToltecsEngine::init() {
|
||||
Common::Error ToltecsEngine::init() {
|
||||
// Initialize backend
|
||||
_system->beginGFXTransaction();
|
||||
initCommonGFX(true);
|
||||
_system->initSize(640, 400);
|
||||
_system->endGFXTransaction();
|
||||
return 0;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
int ToltecsEngine::go() {
|
||||
void ToltecsEngine::syncSoundSettings() {
|
||||
/*
|
||||
_music->setVolume(ConfMan.getInt("music_volume"));
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("sfx_volume"));
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
|
||||
*/
|
||||
}
|
||||
|
||||
Common::Error ToltecsEngine::go() {
|
||||
|
||||
_isSaveAllowed = true;
|
||||
|
||||
_quitGame = false;
|
||||
_counter01 = 0;
|
||||
@ -140,16 +152,6 @@ int ToltecsEngine::go() {
|
||||
|
||||
_system->showMouse(true);
|
||||
|
||||
//#define TEST_MOVIE
|
||||
#ifdef TEST_MOVIE
|
||||
_screen->registerFont(0, 0x0D);
|
||||
_screen->registerFont(1, 0x0E);
|
||||
//_moviePlayer->playMovie(0x000012D8);
|
||||
//_moviePlayer->playMovie(0x000012D7);
|
||||
//_moviePlayer->playMovie(0x);
|
||||
_moviePlayer->playMovie(0x000012E0);
|
||||
#endif
|
||||
|
||||
//#define TEST_MENU
|
||||
#ifdef TEST_MENU
|
||||
_screen->registerFont(0, 0x0D);
|
||||
@ -183,7 +185,7 @@ int ToltecsEngine::go() {
|
||||
|
||||
delete _sound;
|
||||
|
||||
return 0;
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void ToltecsEngine::loadScene(uint resIndex) {
|
||||
@ -259,7 +261,7 @@ void ToltecsEngine::updateInput() {
|
||||
// FIXME: This is just for debugging
|
||||
switch (event.kbd.keycode) {
|
||||
case Common::KEYCODE_F7:
|
||||
savegame("toltecs.001");
|
||||
savegame("toltecs.001", "Quicksave");
|
||||
break;
|
||||
case Common::KEYCODE_F9:
|
||||
loadgame("toltecs.001");
|
||||
|
@ -43,10 +43,6 @@
|
||||
|
||||
namespace Toltecs {
|
||||
|
||||
enum ToltecsGameFeatures {
|
||||
GF_PACKED = (1 << 0)
|
||||
};
|
||||
|
||||
struct ToltecsGameDescription;
|
||||
|
||||
class AnimationPlayer;
|
||||
@ -65,14 +61,17 @@ class ToltecsEngine : public ::Engine {
|
||||
Common::KeyState _keyPressed;
|
||||
|
||||
protected:
|
||||
int init();
|
||||
int go();
|
||||
Common::Error init();
|
||||
Common::Error go();
|
||||
// void shutdown();
|
||||
|
||||
public:
|
||||
ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc);
|
||||
virtual ~ToltecsEngine();
|
||||
|
||||
virtual bool hasFeature(EngineFeature f) const;
|
||||
virtual void syncSoundSettings();
|
||||
|
||||
Common::RandomSource *_rnd;
|
||||
const ToltecsGameDescription *_gameDescription;
|
||||
uint32 getFeatures() const;
|
||||
@ -99,10 +98,8 @@ public:
|
||||
|
||||
int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize);
|
||||
|
||||
void savegame(const char *filename);
|
||||
void loadgame(const char *filename);
|
||||
|
||||
public:
|
||||
|
||||
AnimationPlayer *_anim;
|
||||
ArchiveReader *_arc;
|
||||
Input *_input;
|
||||
@ -140,6 +137,37 @@ public:
|
||||
int16 _mouseDisabled;
|
||||
bool _leftButtonDown, _rightButtonDown;
|
||||
|
||||
/* Save/load */
|
||||
|
||||
enum kReadSaveHeaderError {
|
||||
kRSHENoError = 0,
|
||||
kRSHEInvalidType = 1,
|
||||
kRSHEInvalidVersion = 2,
|
||||
kRSHEIoError = 3
|
||||
};
|
||||
|
||||
struct SaveHeader {
|
||||
Common::String description;
|
||||
uint32 version;
|
||||
byte gameID;
|
||||
uint32 flags;
|
||||
Graphics::Surface *thumbnail;
|
||||
};
|
||||
|
||||
bool _isSaveAllowed;
|
||||
|
||||
bool canLoadGameStateCurrently() { return _isSaveAllowed; }
|
||||
bool canSaveGameStateCurrently() { return _isSaveAllowed; }
|
||||
Common::Error loadGameState(int slot);
|
||||
Common::Error saveGameState(int slot, const char *description);
|
||||
void savegame(const char *filename, const char *description);
|
||||
void loadgame(const char *filename);
|
||||
|
||||
const char *getSavegameFilename(int num);
|
||||
static Common::String getSavegameFilename(const Common::String &target, int num);
|
||||
|
||||
static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Toltecs
|
||||
|
Loading…
Reference in New Issue
Block a user