mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-05 17:57:14 +00:00
AGS: Engine: support fixing up RoomStatuses restored from older save formats
This allows to properly fixup (upgrade) RoomStatus structs restored from a older format save in an upgraded game. For example: game was upgraded from 3.4.0 to 3.6.0, but player tries loading 3.4.0 save. In this situation the engine must know and keep track of what version each RoomStatus was saved in. This is necessary, because RoomStatus can only be updated upon loading a corresponding room file (when entering a room). This means that multiple RoomStatus objects will be staying in memory not being upgraded yet, until player enters particular room. From upstream 205232af5909e0a257494ff404f36003b004ebc4
This commit is contained in:
parent
2daaef2d48
commit
9a469f1e2b
@ -533,7 +533,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
|
||||
_GP(thisroom).LocalVariables[i].Value = _G(croom)->interactionVariableValues[i];
|
||||
|
||||
// Always copy object and hotspot names for < 3.6.0 games, because they were not settable
|
||||
if (_G(loaded_game_file_version) < kGameVersion_360_16) {
|
||||
if ((_G(loaded_game_file_version) < kGameVersion_360_16) || (_G(croom)->contentFormat < kRoomStatSvgVersion_36025)) {
|
||||
for (size_t cc = 0; cc < _GP(thisroom).Objects.size(); ++cc)
|
||||
_G(croom)->obj[cc].name = _GP(thisroom).Objects[cc].Name;
|
||||
for (int cc = 0; cc < MAX_ROOM_HOTSPOTS; cc++)
|
||||
@ -597,6 +597,8 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
|
||||
_G(croom)->beenhere = 1;
|
||||
_G(in_new_room) = 2;
|
||||
}
|
||||
// Reset contentFormat hint to avoid doing fixups later
|
||||
_G(croom)->contentFormat = kRoomStatSvgVersion_Current;
|
||||
|
||||
if (_GP(thisroom).EventHandlers == nullptr) {
|
||||
// legacy interactions
|
||||
|
@ -46,6 +46,7 @@ void HotspotState::WriteToSavegame(Shared::Stream *out) const {
|
||||
}
|
||||
|
||||
RoomStatus::RoomStatus() {
|
||||
contentFormat = kRoomStatSvgVersion_Current; // set current to avoid fixups
|
||||
beenhere = 0;
|
||||
numobj = 0;
|
||||
tsdatasize = 0;
|
||||
@ -74,6 +75,7 @@ void RoomStatus::ReadFromFile_v321(Stream *in) {
|
||||
FreeScriptData();
|
||||
FreeProperties();
|
||||
|
||||
contentFormat = kRoomStatSvgVersion_Initial;
|
||||
beenhere = in->ReadInt32();
|
||||
numobj = in->ReadInt32();
|
||||
obj.resize(MAX_ROOM_OBJECTS_v300);
|
||||
@ -120,7 +122,7 @@ void RoomStatus::ReadRoomObjects_Aligned(Shared::Stream *in) {
|
||||
}
|
||||
}
|
||||
|
||||
void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
|
||||
void RoomStatus::ReadFromSavegame(Stream *in, RoomStatSvgVersion save_ver) {
|
||||
FreeScriptData();
|
||||
FreeProperties();
|
||||
|
||||
@ -161,6 +163,14 @@ void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
|
||||
tsdata.resize(tsdatasize);
|
||||
in->Read(tsdata.data(), tsdatasize);
|
||||
}
|
||||
|
||||
contentFormat = save_ver;
|
||||
if (save_ver >= kRoomStatSvgVersion_36041) {
|
||||
contentFormat = (RoomStatSvgVersion)in->ReadInt32();
|
||||
in->ReadInt32(); // reserved
|
||||
in->ReadInt32();
|
||||
in->ReadInt32();
|
||||
}
|
||||
}
|
||||
|
||||
void RoomStatus::WriteToSavegame(Stream *out) const {
|
||||
@ -196,6 +206,12 @@ void RoomStatus::WriteToSavegame(Stream *out) const {
|
||||
out->WriteInt32(static_cast<int32_t>(tsdatasize));
|
||||
if (tsdatasize)
|
||||
out->Write(tsdata.data(), tsdatasize);
|
||||
|
||||
// kRoomStatSvgVersion_36041
|
||||
out->WriteInt32(contentFormat);
|
||||
out->WriteInt32(0); // reserved
|
||||
out->WriteInt32(0);
|
||||
out->WriteInt32(0);
|
||||
}
|
||||
|
||||
// JJS: Replacement for the global roomstats array in the original engine.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define AGS_ENGINE_AC_ROOM_STATUS_H
|
||||
|
||||
#include "ags/engine/ac/room_object.h"
|
||||
#include "ags/engine/game/savegame.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/game/interactions.h"
|
||||
#include "ags/shared/util/string_types.h"
|
||||
@ -47,8 +48,16 @@ struct HotspotState {
|
||||
void WriteToSavegame(Shared::Stream *out) const;
|
||||
};
|
||||
|
||||
// This struct is saved in the save games - it contains everything about
|
||||
// a room that could change
|
||||
// Savegame data format for RoomStatus
|
||||
// TODO: fill in other versions (lookup the code history)
|
||||
enum RoomStatSvgVersion {
|
||||
kRoomStatSvgVersion_Initial = 0,
|
||||
kRoomStatSvgVersion_36025 = 3,
|
||||
kRoomStatSvgVersion_36041 = 4,
|
||||
kRoomStatSvgVersion_Current = kRoomStatSvgVersion_36041
|
||||
};
|
||||
|
||||
// RoomStatus contains everything about a room that could change at runtime.
|
||||
struct RoomStatus {
|
||||
int beenhere = 0;
|
||||
uint32_t numobj = 0;
|
||||
@ -76,6 +85,13 @@ struct RoomStatus {
|
||||
EventBlock misccond;
|
||||
#endif
|
||||
|
||||
// A version of a save this RoomStatus was restored from.
|
||||
// This is used as a hint when merging RoomStatus with the loaded room file (upon room enter).
|
||||
// We need this for cases when an old format save is restored within an upgraded game
|
||||
// (for example, game was upgraded from 3.4.0 to 3.6.0, but player tries loading 3.4.0 save),
|
||||
// because room files are only loaded once entered, so we cannot fixup all RoomStatuses at once.
|
||||
RoomStatSvgVersion contentFormat;
|
||||
|
||||
RoomStatus();
|
||||
~RoomStatus();
|
||||
|
||||
@ -84,7 +100,7 @@ struct RoomStatus {
|
||||
|
||||
void ReadFromFile_v321(Shared::Stream *in);
|
||||
void ReadRoomObjects_Aligned(Shared::Stream *in);
|
||||
void ReadFromSavegame(Shared::Stream *in, int save_ver);
|
||||
void ReadFromSavegame(Shared::Stream *in, RoomStatSvgVersion save_ver);
|
||||
void WriteToSavegame(Shared::Stream *out) const;
|
||||
};
|
||||
|
||||
|
@ -883,7 +883,7 @@ HSaveError ReadRoomStates(Stream *in, int32_t cmp_ver, const PreservedParams & /
|
||||
if (!AssertFormatTagStrict(err, in, "RoomState", true))
|
||||
return err;
|
||||
RoomStatus *roomstat = getRoomStatus(id);
|
||||
roomstat->ReadFromSavegame(in, cmp_ver);
|
||||
roomstat->ReadFromSavegame(in, (RoomStatSvgVersion)cmp_ver);
|
||||
if (!AssertFormatTagStrict(err, in, "RoomState", false))
|
||||
return err;
|
||||
}
|
||||
@ -977,7 +977,7 @@ HSaveError ReadThisRoom(Stream *in, int32_t cmp_ver, const PreservedParams & /*p
|
||||
|
||||
// read the current troom state, in case they saved in temporary room
|
||||
if (!in->ReadBool())
|
||||
_GP(troom).ReadFromSavegame(in, cmp_ver);
|
||||
_GP(troom).ReadFromSavegame(in, (RoomStatSvgVersion)cmp_ver);
|
||||
|
||||
return HSaveError::None();
|
||||
}
|
||||
@ -1110,15 +1110,15 @@ struct ComponentHandlers {
|
||||
},
|
||||
{
|
||||
"Room States",
|
||||
3,
|
||||
0,
|
||||
kRoomStatSvgVersion_36041,
|
||||
kRoomStatSvgVersion_Initial,
|
||||
WriteRoomStates,
|
||||
ReadRoomStates
|
||||
},
|
||||
{
|
||||
"Loaded Room State",
|
||||
3, // must correspond to "Room States"
|
||||
0,
|
||||
kRoomStatSvgVersion_36041, // must correspond to "Room States"
|
||||
kRoomStatSvgVersion_Initial,
|
||||
WriteThisRoom,
|
||||
ReadThisRoom
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user