From 3980bd73ea7a00de469ae64d90485dcd197689fa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 8 Dec 2007 18:25:00 +0000 Subject: Saving and loading in Winnie the Pooh should now be endian and alignment safe. Note that this breaks older saved games and it's no longer possible to use saved games from the original game interpreter svn-id: r29771 --- engines/agi/preagi_winnie.cpp | 66 +++++++++++++++++++++++++++++++++++-------- engines/agi/preagi_winnie.h | 25 ++++++---------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index 893742b05c..82be15a0d0 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -31,12 +31,14 @@ #include "common/events.h" #include "common/savefile.h" +#include "common/stream.h" namespace Agi { // default attributes -#define IDA_DEFAULT 0x0F -#define IDA_DEFAULT_REV 0xF0 +#define IDA_DEFAULT 0x0F +#define IDA_DEFAULT_REV 0xF0 +#define WTP_SAVEGAME_VERSION 1 void Winnie::parseRoomHeader(WTP_ROOM_HDR *roomHdr, byte *buffer, int len) { bool isBigEndian = (_vm->getPlatform() == Common::kPlatformAmiga); @@ -1192,33 +1194,73 @@ void Winnie::gameOver() { } void Winnie::saveGame() { - uint8 *buffer = (uint8 *)malloc(sizeof(WTP_SAVE_GAME)); - memcpy(buffer, &_game, sizeof(WTP_SAVE_GAME)); Common::OutSaveFile* outfile; char szFile[256] = {0}; + int i = 0; sprintf(szFile, IDS_WTP_FILE_SAVEGAME); if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile))) return; - outfile->write(buffer, sizeof(WTP_SAVE_GAME)); - delete outfile; - free(buffer); + outfile->writeUint32BE(MKID_BE('WINN')); // header + outfile->writeByte(WTP_SAVEGAME_VERSION); + + outfile->writeByte(_game.fSound); + outfile->writeByte(_game.nMoves); + outfile->writeByte(_game.nObjMiss); + outfile->writeByte(_game.nObjRet); + outfile->writeByte(_game.iObjHave); + + for(i = 0; i < IDI_WTP_MAX_FLAG; i++) + outfile->writeByte(_game.fGame[i]); + + for(i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) + outfile->writeByte(_game.iUsedObj[i]); + + for(i = 0; i < IDI_WTP_MAX_ROOM_OBJ; i++) + outfile->writeByte(_game.iObjRoom[i]); + + outfile->finalize(); + + if (outfile->ioFailed()) + warning("Can't write file '%s'. (Disk full?)", szFile); + + delete outfile; } void Winnie::loadGame() { - uint8 *buffer = (uint8 *)malloc(sizeof(WTP_SAVE_GAME)); Common::InSaveFile* infile; char szFile[256] = {0}; + int saveVersion = 0; + int i = 0; sprintf(szFile, IDS_WTP_FILE_SAVEGAME); if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile))) return; - infile->read(buffer, sizeof(WTP_SAVE_GAME)); - delete infile; - memcpy(&_game, buffer, sizeof(WTP_SAVE_GAME)); - free(buffer); + if (infile->readUint32BE() != MKID_BE('WINN')) + error("Winnie::loadGame wrong save game format"); + + saveVersion = infile->readByte(); + if (saveVersion != WTP_SAVEGAME_VERSION) + warning("Old save game version (%d, current version is %d). Will try and read anyway, but don't be surprised if bad things happen", saveVersion, WTP_SAVEGAME_VERSION); + + _game.fSound = infile->readByte(); + _game.nMoves = infile->readByte(); + _game.nObjMiss = infile->readByte(); + _game.nObjRet = infile->readByte(); + _game.iObjHave = infile->readByte(); + + for(i = 0; i < IDI_WTP_MAX_FLAG; i++) + _game.fGame[i] = infile->readByte(); + + for(i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) + _game.iUsedObj[i] = infile->readByte(); + + for(i = 0; i < IDI_WTP_MAX_ROOM_OBJ; i++) + _game.iObjRoom[i] = infile->readByte(); + + delete infile; } // Console-related functions diff --git a/engines/agi/preagi_winnie.h b/engines/agi/preagi_winnie.h index 9783992d48..045ab66ad8 100644 --- a/engines/agi/preagi_winnie.h +++ b/engines/agi/preagi_winnie.h @@ -274,23 +274,14 @@ struct WTP_OBJ_HDR { // savegame struct WTP_SAVE_GAME { - uint16 reserved0; // 10c2 unused - uint16 fSound; // 10c4 - uint16 nMoves; // 10c6 - uint16 nObjMiss; // 10c8 - uint16 nObjRet; // 10ca - uint16 reserved1; // 10ce unused - uint16 reserved2; // 10cf unused - uint16 reserved3; // 10d0 unused - uint16 iObjHave; // 10d2 - uint16 o10d4; // 10d4 can be ignored - uint16 o10d6; // 10d6 can be ignored - uint16 o10d8; // 10d8 can be ignored - uint8 fGame[IDI_WTP_MAX_FLAG]; // 10da - uint8 iUsedObj[IDI_WTP_MAX_OBJ_MISSING]; // 1102 - uint8 iObjRoom[IDI_WTP_MAX_ROOM_OBJ]; // 110c - uint16 o1136; // 1136 can be ignored - uint16 o1138; // 1138 can be ignored + uint8 fSound; + uint8 nMoves; + uint8 nObjMiss; + uint8 nObjRet; + uint8 iObjHave; + uint8 fGame[IDI_WTP_MAX_FLAG]; + uint8 iUsedObj[IDI_WTP_MAX_OBJ_MISSING]; + uint8 iObjRoom[IDI_WTP_MAX_ROOM_OBJ]; }; #define IDI_XOR_KEY 0x80 -- cgit v1.2.3