mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-19 00:15:30 +00:00
SCUMM: Modified version of patch #1687041 (Scumm: Load-/Save-support for the original save-dialog)
svn-id: r39438
This commit is contained in:
parent
ffa97e6626
commit
e44f07f988
@ -410,6 +410,11 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
|
||||
// Fall back to default behavior
|
||||
ScummEngine::processKeyboard(lastKeyHit);
|
||||
|
||||
// On Alt-F5 prepare savegame for the original save/load dialog.
|
||||
if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == Common::KBD_ALT) {
|
||||
prepareSavegame();
|
||||
}
|
||||
|
||||
if (VAR_KEYPRESS != 0xFF && _mouseAndKeyboardStat) { // Key Input
|
||||
if (315 <= _mouseAndKeyboardStat && _mouseAndKeyboardStat <= 323) {
|
||||
// Convert F-Keys for V1/V2 games (they start at 1)
|
||||
@ -424,8 +429,13 @@ void ScummEngine_v3::processKeyboard(Common::KeyState lastKeyHit) {
|
||||
// Fall back to default behavior
|
||||
ScummEngine::processKeyboard(lastKeyHit);
|
||||
|
||||
// 'i' brings up an IQ dialog in Indy3
|
||||
if (lastKeyHit.ascii == 'i' && _game.id == GID_INDY3) {
|
||||
// On Alt-F5 prepare savegame for the original save/load dialog.
|
||||
if (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == Common::KBD_ALT) {
|
||||
prepareSavegame();
|
||||
}
|
||||
|
||||
// 'i' brings up an IQ dialog in Indy3 (disabled in save/load dialog for input)
|
||||
if (lastKeyHit.ascii == 'i' && _game.id == GID_INDY3 && _currentRoom != 14) {
|
||||
// SCUMM var 244 is the episode score
|
||||
// and var 245 is the series score
|
||||
char text[50];
|
||||
@ -496,7 +506,7 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
|
||||
messageDialog("Snap scroll on");
|
||||
} else {
|
||||
messageDialog("Snap scroll off");
|
||||
}
|
||||
}
|
||||
|
||||
if (VAR_CAMERA_FAST_X != 0xFF)
|
||||
VAR(VAR_CAMERA_FAST_X) = _snapScroll;
|
||||
|
@ -237,8 +237,26 @@ protected:
|
||||
* Engine for version 3 SCUMM games; GF_SMALL_NAMES is always set for these.
|
||||
*/
|
||||
class ScummEngine_v3 : public ScummEngine_v4 {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Prepared savegame used by the orginal save/load dialog.
|
||||
* Must be valid as long as the savescreen is active. As we are not
|
||||
* notified when the savescreen is closed, memory is only freed on a game
|
||||
* reset, at the destruction of the engine or when the original save/load
|
||||
* dialog is entered the next time.
|
||||
*/
|
||||
Common::SeekableReadStream *_savePreparedSavegame;
|
||||
|
||||
void prepareSavegame();
|
||||
bool savePreparedSavegame(int slot, char *desc);
|
||||
|
||||
|
||||
public:
|
||||
ScummEngine_v3(OSystem *syst, const DetectorResult &dr);
|
||||
~ScummEngine_v3();
|
||||
|
||||
virtual void resetScumm();
|
||||
|
||||
protected:
|
||||
virtual void readRoomsOffsets();
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "common/config-manager.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/zlib.h"
|
||||
|
||||
#include "scumm/actor.h"
|
||||
#include "scumm/charset.h"
|
||||
@ -129,10 +130,27 @@ static bool saveSaveGameHeader(Common::OutSaveFile *out, SaveGameHeader &hdr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScummEngine::saveState(Common::OutSaveFile *out, bool writeHeader) {
|
||||
SaveGameHeader hdr;
|
||||
|
||||
if (writeHeader) {
|
||||
memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
|
||||
saveSaveGameHeader(out, hdr);
|
||||
}
|
||||
#if !defined(__DS__)
|
||||
Graphics::saveThumbnail(*out);
|
||||
#endif
|
||||
saveInfos(out);
|
||||
|
||||
Serializer ser(0, out, CURRENT_VER);
|
||||
saveOrLoad(&ser);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScummEngine::saveState(int slot, bool compat) {
|
||||
bool saveFailed;
|
||||
Common::String filename;
|
||||
Common::OutSaveFile *out;
|
||||
SaveGameHeader hdr;
|
||||
|
||||
if (_saveLoadSlot == 255) {
|
||||
// Allow custom filenames for save game system in HE Games
|
||||
@ -143,26 +161,108 @@ bool ScummEngine::saveState(int slot, bool compat) {
|
||||
if (!(out = _saveFileMan->openForSaving(filename.c_str())))
|
||||
return false;
|
||||
|
||||
memcpy(hdr.name, _saveLoadName, sizeof(hdr.name));
|
||||
saveSaveGameHeader(out, hdr);
|
||||
#if !defined(__DS__)
|
||||
Graphics::saveThumbnail(*out);
|
||||
#endif
|
||||
saveInfos(out);
|
||||
saveFailed = false;
|
||||
if (!saveState(out))
|
||||
saveFailed = true;
|
||||
|
||||
Serializer ser(0, out, CURRENT_VER);
|
||||
saveOrLoad(&ser);
|
||||
out->finalize();
|
||||
if (out->err()) {
|
||||
delete out;
|
||||
if (out->err())
|
||||
saveFailed = true;
|
||||
delete out;
|
||||
|
||||
if (saveFailed) {
|
||||
debug(1, "State save as '%s' FAILED", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
delete out;
|
||||
debug(1, "State saved as '%s'", filename.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ScummEngine_v3::prepareSavegame() {
|
||||
Common::MemoryWriteStreamDynamic *memStream;
|
||||
Common::WriteStream *writeStream;
|
||||
|
||||
// free memory of the last prepared savegame
|
||||
delete _savePreparedSavegame;
|
||||
_savePreparedSavegame = NULL;
|
||||
|
||||
// store headerless savegame in a compressed memory stream
|
||||
memStream = new Common::MemoryWriteStreamDynamic();
|
||||
writeStream = Common::wrapCompressedWriteStream(memStream);
|
||||
if (saveState(writeStream, false)) {
|
||||
// we have to finalize the compression-stream first, otherwise the internal
|
||||
// memory-stream pointer will be zero (Important: flush() does not work here!).
|
||||
writeStream->finalize();
|
||||
if (!writeStream->err()) {
|
||||
// wrap uncompressing MemoryReadStream around the savegame data
|
||||
_savePreparedSavegame = Common::wrapCompressedReadStream(
|
||||
new Common::MemoryReadStream(memStream->getData(), memStream->size(), true));
|
||||
}
|
||||
}
|
||||
// free the CompressedWriteStream and MemoryWriteStreamDynamic
|
||||
// but not the memory stream's internal buffer
|
||||
delete writeStream;
|
||||
}
|
||||
|
||||
bool ScummEngine_v3::savePreparedSavegame(int slot, char *desc) {
|
||||
bool success;
|
||||
Common::String filename;
|
||||
Common::OutSaveFile *out;
|
||||
SaveGameHeader hdr;
|
||||
uint32 nread, nwritten;
|
||||
|
||||
out = 0;
|
||||
success = true;
|
||||
|
||||
// check if savegame was successfully stored in memory
|
||||
if (!_savePreparedSavegame)
|
||||
success = false;
|
||||
|
||||
// open savegame file
|
||||
if (success) {
|
||||
filename = makeSavegameName(slot, false);
|
||||
if (!(out = _saveFileMan->openForSaving(filename.c_str()))) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
// write header to file
|
||||
if (success) {
|
||||
memset(hdr.name, 0, sizeof(hdr.name));
|
||||
strncpy(hdr.name, desc, sizeof(hdr.name)-1);
|
||||
success = saveSaveGameHeader(out, hdr);
|
||||
}
|
||||
|
||||
// copy savegame from memory-stream to file
|
||||
if (success) {
|
||||
_savePreparedSavegame->seek(0, SEEK_SET);
|
||||
byte buffer[1024];
|
||||
while ((nread = _savePreparedSavegame->read(buffer, sizeof(buffer)))) {
|
||||
nwritten = out->write(buffer, nread);
|
||||
if (nwritten < nread) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (out) {
|
||||
out->finalize();
|
||||
if (out->err())
|
||||
success = false;
|
||||
delete out;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
debug(1, "State save as '%s' FAILED", filename.c_str());
|
||||
return false;
|
||||
} else {
|
||||
debug(1, "State saved as '%s'", filename.c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool loadSaveGameHeader(Common::SeekableReadStream *in, SaveGameHeader &hdr) {
|
||||
hdr.type = in->readUint32BE();
|
||||
hdr.size = in->readUint32LE();
|
||||
|
@ -869,7 +869,12 @@ enum StringIds {
|
||||
// which matches the original Indy3 save/load code. See also the notes
|
||||
// on Feature Request #1666521.
|
||||
STRINGID_IQ_EPISODE = 7,
|
||||
STRINGID_IQ_SERIES = 9
|
||||
STRINGID_IQ_SERIES = 9,
|
||||
// The string IDs of the first savegame name, used as an offset to determine
|
||||
// the IDs of all savenames.
|
||||
// Loom is the only game whose savenames start with a different ID.
|
||||
STRINGID_SAVENAME1 = 10,
|
||||
STRINGID_SAVENAME1_LOOM = 9
|
||||
};
|
||||
|
||||
void ScummEngine_v5::o5_saveLoadVars() {
|
||||
@ -1235,26 +1240,43 @@ void ScummEngine_v5::o5_saveLoadGame() {
|
||||
result = 100;
|
||||
break;
|
||||
case 0x20: // drive
|
||||
if (_game.id == GID_INDY3) {
|
||||
// 0 = hard drive
|
||||
// 1 = disk drive
|
||||
result = 0;
|
||||
if (_game.version <= 3) {
|
||||
// 0 = ???
|
||||
// [1,2] = disk drive [A:,B:]
|
||||
// 3 = hard drive
|
||||
result = 3;
|
||||
} else {
|
||||
// set current drive
|
||||
result = 1;
|
||||
}
|
||||
break;
|
||||
case 0x40: // load
|
||||
if (loadState(slot, _saveTemporaryState))
|
||||
if (loadState(slot, false))
|
||||
result = 3; // sucess
|
||||
else
|
||||
result = 5; // failed to load
|
||||
break;
|
||||
case 0x80: // save
|
||||
//if (saveState(slot, _saveTemporaryState))
|
||||
// result = 0; // sucess
|
||||
//else
|
||||
if (_game.version <= 3) {
|
||||
char name[32];
|
||||
if (_game.version <= 2) {
|
||||
// use generic name
|
||||
sprintf(name, "Game %c", 'A'+slot-1);
|
||||
} else {
|
||||
// use name entered by the user
|
||||
char* ptr;
|
||||
int firstSlot = (_game.id == GID_LOOM) ? STRINGID_SAVENAME1_LOOM : STRINGID_SAVENAME1;
|
||||
ptr = (char*)getStringAddress(slot + firstSlot - 1);
|
||||
strncpy(name, ptr, sizeof(name));
|
||||
}
|
||||
|
||||
if (((ScummEngine_v3 *)this)->savePreparedSavegame(slot, name))
|
||||
result = 0;
|
||||
else
|
||||
result = 2;
|
||||
} else {
|
||||
result = 2; // failed to save
|
||||
}
|
||||
break;
|
||||
case 0xC0: // test if save exists
|
||||
{
|
||||
|
@ -631,6 +631,12 @@ ScummEngine_v3::ScummEngine_v3(OSystem *syst, const DetectorResult &dr)
|
||||
// All v3 and older games only used 16 colors with exception of the GF_OLD256 games.
|
||||
if (!(_game.features & GF_OLD256))
|
||||
_game.features |= GF_16COLOR;
|
||||
|
||||
_savePreparedSavegame = NULL;
|
||||
}
|
||||
|
||||
ScummEngine_v3::~ScummEngine_v3() {
|
||||
delete _savePreparedSavegame;
|
||||
}
|
||||
|
||||
ScummEngine_v3old::ScummEngine_v3old(OSystem *syst, const DetectorResult &dr)
|
||||
@ -1426,7 +1432,7 @@ void ScummEngine_v0::resetScumm() {
|
||||
}
|
||||
|
||||
void ScummEngine_v2::resetScumm() {
|
||||
ScummEngine::resetScumm();
|
||||
ScummEngine_v3::resetScumm();
|
||||
|
||||
if (_game.platform == Common::kPlatformNES) {
|
||||
initNESMouseOver();
|
||||
@ -1442,6 +1448,13 @@ void ScummEngine_v2::resetScumm() {
|
||||
_inventoryOffset = 0;
|
||||
}
|
||||
|
||||
void ScummEngine_v3::resetScumm() {
|
||||
ScummEngine_v4::resetScumm();
|
||||
|
||||
delete _savePreparedSavegame;
|
||||
_savePreparedSavegame = NULL;
|
||||
}
|
||||
|
||||
void ScummEngine_v4::resetScumm() {
|
||||
ScummEngine::resetScumm();
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "engines/engine.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/file.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/keyboard.h"
|
||||
#include "common/rect.h"
|
||||
#include "common/str.h"
|
||||
@ -628,6 +629,7 @@ protected:
|
||||
char _saveLoadFileName[32];
|
||||
char _saveLoadName[32];
|
||||
|
||||
bool saveState(Common::OutSaveFile *out, bool writeHeader = true);
|
||||
bool saveState(int slot, bool compat);
|
||||
bool loadState(int slot, bool compat);
|
||||
virtual void saveOrLoad(Serializer *s);
|
||||
|
Loading…
x
Reference in New Issue
Block a user