[Scummvm-git-logs] scummvm master -> 13c3d6cddcf08dd0f2e3e4d41711ff1e26ba3acd
criezy
noreply at scummvm.org
Wed Jun 15 21:13:11 UTC 2022
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
98bb288bbe AGS: Fixed BufferedStream may overwrite dest with clear buffer
74416f547f AGS: Removed redundant arrays keeping copies of obj script names
5d9ae41cd6 AGS: Store room objects in std::vector
13c3d6cddc AGS: Increased Room Objects limit to 256
Commit: 98bb288bbe117cf2cedb28c04551c9183aac1f07
https://github.com/scummvm/scummvm/commit/98bb288bbe117cf2cedb28c04551c9183aac1f07
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-06-15T22:13:02+01:00
Commit Message:
AGS: Fixed BufferedStream may overwrite dest with clear buffer
>From upstream 39c8f628575eeabff1ed583b43bd6c58530c6b24
Changed paths:
engines/ags/shared/util/buffered_stream.cpp
diff --git a/engines/ags/shared/util/buffered_stream.cpp b/engines/ags/shared/util/buffered_stream.cpp
index 398302d3309..95c8cb8a29b 100644
--- a/engines/ags/shared/util/buffered_stream.cpp
+++ b/engines/ags/shared/util/buffered_stream.cpp
@@ -133,7 +133,10 @@ int32_t BufferedStream::ReadByte() {
size_t BufferedStream::Write(const void *buffer, size_t size) {
const uint8_t *from = static_cast<const uint8_t*>(buffer);
while (size > 0) {
- if (_position < _bufferPosition || _position >= _bufferPosition + BufferSize) {
+ if (_position < _bufferPosition || // seeked before buffer pos
+ _position > _bufferPosition + _buffer.size() || // seeked beyond buffer pos
+ _position >= _bufferPosition + BufferSize) // seeked, or exceeded buffer limit
+ {
FlushBuffer(_position);
}
size_t pos_in_buff = static_cast<size_t>(_position - _bufferPosition);
Commit: 74416f547f517828561354cf2b02bdcbf962d450
https://github.com/scummvm/scummvm/commit/74416f547f517828561354cf2b02bdcbf962d450
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-06-15T22:13:02+01:00
Commit Message:
AGS: Removed redundant arrays keeping copies of obj script names
>From upstream f0887ba798b9df7aa70125b432efd5d62c64a622
Changed paths:
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/globals.cpp
engines/ags/globals.h
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index dc8202979e6..1c6ecbdfef6 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -361,7 +361,6 @@ void unload_game_file() {
_GP(play).FreeViewportsAndCameras();
- _GP(characterScriptObjNames).clear();
_GP(charextra).clear();
_GP(mls).clear();
@@ -426,7 +425,6 @@ void unload_game_file() {
delete[] _G(scrDialog);
_G(scrDialog) = nullptr;
- _GP(guiScriptObjNames).clear();
_GP(guis).clear();
free(_G(scrGui));
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index cb4be1cc741..8dd038c14e5 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -279,10 +279,10 @@ void unload_old_room() {
for (ff = 0; ff < _G(croom)->numobj; ff++) {
// un-export the object's script object
- if (_G(objectScriptObjNames)[ff].IsEmpty())
+ if (_GP(thisroom).Objects[ff].ScriptName.IsEmpty())
continue;
- ccRemoveExternalSymbol(_G(objectScriptObjNames)[ff]);
+ ccRemoveExternalSymbol(_GP(thisroom).Objects[ff].ScriptName);
}
for (ff = 0; ff < MAX_ROOM_HOTSPOTS; ff++) {
@@ -622,16 +622,11 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(objs) = &_G(croom)->obj[0];
- for (cc = 0; cc < MAX_ROOM_OBJECTS; cc++) {
- _G(objectScriptObjNames)[cc].Free();
- }
-
for (cc = 0; cc < _G(croom)->numobj; cc++) {
// export the object's script object
if (_GP(thisroom).Objects[cc].ScriptName.IsEmpty())
continue;
- _G(objectScriptObjNames)[cc] = _GP(thisroom).Objects[cc].ScriptName;
- ccAddExternalDynamicObject(_G(objectScriptObjNames)[cc], &_G(scrObj)[cc], &_GP(ccDynamicObject));
+ ccAddExternalDynamicObject(_GP(thisroom).Objects[cc].ScriptName, &_G(scrObj)[cc], &_GP(ccDynamicObject));
}
for (cc = 0; cc < MAX_ROOM_HOTSPOTS; cc++) {
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index e7f12572ad0..313fe477ae8 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -106,7 +106,6 @@ void InitAndRegisterAudioObjects(GameSetupStruct &game) {
// Initializes characters and registers them in the script system
void InitAndRegisterCharacters(GameSetupStruct &game) {
- _GP(characterScriptObjNames).resize(game.numcharacters);
for (int i = 0; i < game.numcharacters; ++i) {
game.chars[i].walking = 0;
game.chars[i].animating = 0;
@@ -124,8 +123,7 @@ void InitAndRegisterCharacters(GameSetupStruct &game) {
ccRegisterManagedObject(&game.chars[i], &_GP(ccDynamicCharacter));
// export the character's script object
- _GP(characterScriptObjNames)[i] = game.chars[i].scrname;
- ccAddExternalDynamicObject(_GP(characterScriptObjNames)[i], &game.chars[i], &_GP(ccDynamicCharacter));
+ ccAddExternalDynamicObject(game.chars[i].scrname, &game.chars[i], &_GP(ccDynamicCharacter));
}
}
@@ -159,7 +157,6 @@ HError InitAndRegisterGUI(GameSetupStruct &game) {
_G(scrGui)[i].id = -1;
}
- _GP(guiScriptObjNames).resize(game.numgui);
for (int i = 0; i < game.numgui; ++i) {
// link controls to their parent guis
HError err = _GP(guis)[i].RebuildArray();
@@ -167,11 +164,8 @@ HError InitAndRegisterGUI(GameSetupStruct &game) {
return err;
// export all the GUI's controls
export_gui_controls(i);
- // copy the script name to its own memory location
- // because ccAddExtSymbol only keeps a reference
- _GP(guiScriptObjNames)[i] = _GP(guis)[i].Name;
_G(scrGui)[i].id = i;
- ccAddExternalDynamicObject(_GP(guiScriptObjNames)[i], &_G(scrGui)[i], &_GP(ccDynamicGUI));
+ ccAddExternalDynamicObject(_GP(guis)[i].Name, &_G(scrGui)[i], &_GP(ccDynamicGUI));
ccRegisterManagedObject(&_G(scrGui)[i], &_GP(ccDynamicGUI));
}
return HError::None();
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 1aec36ddcf1..7917dd43ded 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -356,9 +356,6 @@ Globals::Globals() {
_moduleInst = new std::vector<ccInstance *>();
_moduleInstFork = new std::vector<ccInstance *>();
_moduleRepExecAddr = new std::vector<RuntimeScriptValue>();
- _characterScriptObjNames = new std::vector<String>();
- _objectScriptObjNames = new String[MAX_ROOM_OBJECTS];
- _guiScriptObjNames = new std::vector<String>();
// script_runtime.cpp globals
Common::fill(_loadedInstances, _loadedInstances + MAX_LOADED_INSTANCES,
@@ -606,9 +603,6 @@ Globals::~Globals() {
delete _moduleInst;
delete _moduleInstFork;
delete _moduleRepExecAddr;
- delete _characterScriptObjNames;
- delete[] _objectScriptObjNames;
- delete _guiScriptObjNames;
// system_imports.cpp globals
delete _simp;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 82b3e80d9aa..71a0a20b6b9 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1267,12 +1267,6 @@ public:
std::vector<RuntimeScriptValue> *_moduleRepExecAddr;
size_t _numScriptModules = 0;
- // TODO: find out if these extra arrays are really necessary. This may be remains from the
- // time when the symbol import table was holding raw pointers to char array.
- std::vector<String> *_characterScriptObjNames;
- String *_objectScriptObjNames;
- std::vector<String> *_guiScriptObjNames;
-
/**@}*/
/**
Commit: 5d9ae41cd6569f046ec2113e7d3bd213a90e5cce
https://github.com/scummvm/scummvm/commit/5d9ae41cd6569f046ec2113e7d3bd213a90e5cce
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-06-15T22:13:02+01:00
Commit Message:
AGS: Store room objects in std::vector
>From upstream 5f3b8eb509c9535c75b401f9b7257f7c7acd0e6d
Changed paths:
engines/ags/engine/ac/dynobj/script_object.h
engines/ags/engine/ac/room.cpp
engines/ags/engine/ac/room_status.cpp
engines/ags/engine/ac/room_status.h
engines/ags/engine/game/savegame.cpp
engines/ags/engine/game/savegame_components.cpp
engines/ags/shared/game/room_file.cpp
engines/ags/shared/game/room_struct.cpp
engines/ags/shared/game/room_struct.h
diff --git a/engines/ags/engine/ac/dynobj/script_object.h b/engines/ags/engine/ac/dynobj/script_object.h
index c9583fadd00..761e474257a 100644
--- a/engines/ags/engine/ac/dynobj/script_object.h
+++ b/engines/ags/engine/ac/dynobj/script_object.h
@@ -26,10 +26,9 @@
namespace AGS3 {
-// 64 bit: Struct size must be 8 byte for scripts to work
+// WARNING: struct size must be 8 byte for old scripts to work
struct ScriptObject {
- int id = 0;
- //RoomObject *obj;
+ int id = -1;
int __padding = 0;
};
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 8dd038c14e5..f4c088e4ed1 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -314,11 +314,11 @@ void convert_room_coordinates_to_data_res(RoomStruct *rstruc) {
return;
const int mul = _GP(game).GetDataUpscaleMult();
- for (size_t i = 0; i < rstruc->ObjectCount; ++i) {
- rstruc->Objects[i].X /= mul;
- rstruc->Objects[i].Y /= mul;
- if (rstruc->Objects[i].Baseline > 0) {
- rstruc->Objects[i].Baseline /= mul;
+ for (auto &obj : rstruc->Objects) {
+ obj.X /= mul;
+ obj.Y /= mul;
+ if (obj.Baseline > 0) {
+ obj.Baseline /= mul;
}
}
@@ -405,8 +405,6 @@ HError LoadRoomScript(RoomStruct *room, int newnum) {
}
static void reset_temp_room() {
- _GP(troom).FreeScriptData();
- _GP(troom).FreeProperties();
_GP(troom) = RoomStatus();
}
@@ -537,7 +535,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_GP(thisroom).Interaction->CopyTimesRun(_G(croom)->intrRoom);
for (cc = 0; cc < MAX_ROOM_HOTSPOTS; cc++)
_GP(thisroom).Hotspots[cc].Interaction->CopyTimesRun(_G(croom)->intrHotspot[cc]);
- for (cc = 0; cc < MAX_ROOM_OBJECTS; cc++)
+ for (cc = 0; cc < _GP(thisroom).Objects.size(); cc++)
_GP(thisroom).Objects[cc].Interaction->CopyTimesRun(_G(croom)->intrObject[cc]);
for (cc = 0; cc < MAX_ROOM_REGIONS; cc++)
_GP(thisroom).Regions[cc].Interaction->CopyTimesRun(_G(croom)->intrRegion[cc]);
@@ -547,39 +545,44 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
// 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) {
- for (cc = 0; cc < _G(croom)->numobj; ++cc)
+ for (cc = 0; cc < _GP(thisroom).Objects.size(); ++cc)
_G(croom)->obj[cc].name = _GP(thisroom).Objects[cc].Name;
for (cc = 0; cc < MAX_ROOM_HOTSPOTS; cc++)
_G(croom)->hotspot[cc].Name = _GP(thisroom).Hotspots[cc].Name;
}
} else {
// If we have not been in this room before, then copy necessary fields from _GP(thisroom)
- _G(croom)->numobj = _GP(thisroom).ObjectCount;
+ _G(croom)->numobj = _GP(thisroom).Objects.size();
_G(croom)->tsdatasize = 0;
+ _G(croom)->obj.resize(_G(croom)->numobj);
+ _G(croom)->objProps.resize(_G(croom)->numobj);
+ _G(croom)->intrObject.resize(_G(croom)->numobj);
for (cc = 0; cc < _G(croom)->numobj; cc++) {
- _G(croom)->obj[cc].x = _GP(thisroom).Objects[cc].X;
- _G(croom)->obj[cc].y = _GP(thisroom).Objects[cc].Y;
- _G(croom)->obj[cc].num = Math::InRangeOrDef<uint16_t>(_GP(thisroom).Objects[cc].Sprite, 0);
- _G(croom)->obj[cc].on = _GP(thisroom).Objects[cc].IsOn;
- _G(croom)->obj[cc].view = RoomObject::NoView;
- _G(croom)->obj[cc].loop = 0;
- _G(croom)->obj[cc].frame = 0;
- _G(croom)->obj[cc].wait = 0;
- _G(croom)->obj[cc].transparent = 0;
- _G(croom)->obj[cc].moving = -1;
- _G(croom)->obj[cc].flags = _GP(thisroom).Objects[cc].Flags;
- _G(croom)->obj[cc].baseline = -1;
- _G(croom)->obj[cc].zoom = 100;
- _G(croom)->obj[cc].last_width = 0;
- _G(croom)->obj[cc].last_height = 0;
- _G(croom)->obj[cc].blocking_width = 0;
- _G(croom)->obj[cc].blocking_height = 0;
- _G(croom)->obj[cc].name = _GP(thisroom).Objects[cc].Name;
- if (_GP(thisroom).Objects[cc].Baseline >= 0)
- _G(croom)->obj[cc].baseline = _GP(thisroom).Objects[cc].Baseline;
- if (_GP(thisroom).Objects[cc].Sprite > UINT16_MAX)
+ const auto &trobj = _GP(thisroom).Objects[cc];
+ auto &crobj = _G(croom)->obj[cc];
+ crobj.x = trobj.X;
+ crobj.y = trobj.Y;
+ crobj.num = Math::InRangeOrDef<uint16_t>(trobj.Sprite, 0);
+ crobj.on = trobj.IsOn;
+ crobj.view = RoomObject::NoView;
+ crobj.loop = 0;
+ crobj.frame = 0;
+ crobj.wait = 0;
+ crobj.transparent = 0;
+ crobj.moving = -1;
+ crobj.flags = trobj.Flags;
+ crobj.baseline = -1;
+ crobj.zoom = 100;
+ crobj.last_width = 0;
+ crobj.last_height = 0;
+ crobj.blocking_width = 0;
+ crobj.blocking_height = 0;
+ crobj.name = trobj.Name;
+ if (trobj.Baseline >= 0)
+ crobj.baseline = trobj.Baseline;
+ if (trobj.Sprite > UINT16_MAX)
debug_script_warn("Warning: object's (id %d) sprite %d outside of internal range (%d), reset to 0",
- cc, _GP(thisroom).Objects[cc].Sprite, UINT16_MAX);
+ cc, trobj.Sprite, UINT16_MAX);
}
for (size_t i = 0; i < (size_t)MAX_WALK_BEHINDS; ++i)
_G(croom)->walkbehind_base[i] = _GP(thisroom).WalkBehinds[i].Baseline;
@@ -614,13 +617,13 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(croom)->intrRoom = *_GP(thisroom).Interaction;
for (cc = 0; cc < MAX_ROOM_HOTSPOTS; cc++)
_G(croom)->intrHotspot[cc] = *_GP(thisroom).Hotspots[cc].Interaction;
- for (cc = 0; cc < MAX_ROOM_OBJECTS; cc++)
+ for (cc = 0; cc < _GP(thisroom).Objects.size(); cc++)
_G(croom)->intrObject[cc] = *_GP(thisroom).Objects[cc].Interaction;
for (cc = 0; cc < MAX_ROOM_REGIONS; cc++)
_G(croom)->intrRegion[cc] = *_GP(thisroom).Regions[cc].Interaction;
}
- _G(objs) = &_G(croom)->obj[0];
+ _G(objs) = _G(croom)->obj.size() > 0 ? &_G(croom)->obj[0] : nullptr;
for (cc = 0; cc < _G(croom)->numobj; cc++) {
// export the object's script object
diff --git a/engines/ags/engine/ac/room_status.cpp b/engines/ags/engine/ac/room_status.cpp
index b1625f0bae9..c424544a983 100644
--- a/engines/ags/engine/ac/room_status.cpp
+++ b/engines/ags/engine/ac/room_status.cpp
@@ -73,23 +73,28 @@ void RoomStatus::FreeProperties() {
for (int i = 0; i < MAX_ROOM_HOTSPOTS; ++i) {
hsProps[i].clear();
}
- for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
- objProps[i].clear();
- }
+ objProps.clear();
}
void RoomStatus::ReadFromFile_v321(Stream *in) {
+ FreeScriptData();
+ FreeProperties();
+
beenhere = in->ReadInt32();
numobj = in->ReadInt32();
+ obj.resize(numobj);
+ objProps.resize(numobj);
+ intrObject.resize(numobj);
ReadRoomObjects_Aligned(in);
+
in->Seek(MAX_LEGACY_ROOM_FLAGS * sizeof(int16_t)); // flagstates (OBSOLETE)
tsdatasize = in->ReadInt32();
in->ReadInt32(); // tsdata
for (int i = 0; i < MAX_ROOM_HOTSPOTS; ++i) {
intrHotspot[i].ReadFromSavedgame_v321(in);
}
- for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
- intrObject[i].ReadFromSavedgame_v321(in);
+ for (auto &intr : intrObject) {
+ intr.ReadFromSavedgame_v321(in);
}
for (int i = 0; i < MAX_ROOM_REGIONS; ++i) {
intrRegion[i].ReadFromSavedgame_v321(in);
@@ -106,16 +111,16 @@ void RoomStatus::ReadFromFile_v321(Stream *in) {
for (int i = 0; i < MAX_ROOM_HOTSPOTS; ++i) {
Properties::ReadValues(hsProps[i], in);
}
- for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
- Properties::ReadValues(objProps[i], in);
+ for (auto &props : objProps) {
+ Properties::ReadValues(props, in);
}
}
}
void RoomStatus::ReadRoomObjects_Aligned(Shared::Stream *in) {
AlignedStream align_s(in, Shared::kAligned_Read);
- for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
- obj[i].ReadFromSavegame(&align_s, 0);
+ for (auto &o : obj) {
+ o.ReadFromSavegame(&align_s, 0);
align_s.Reset();
}
}
@@ -126,7 +131,10 @@ void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
beenhere = in->ReadInt8();
numobj = in->ReadInt32();
- for (int i = 0; i < numobj; ++i) {
+ obj.resize(numobj);
+ objProps.resize(numobj);
+ intrObject.resize(numobj);
+ for (size_t i = 0; i < numobj; ++i) {
obj[i].ReadFromSavegame(in, save_ver);
Properties::ReadValues(objProps[i], in);
if (_G(loaded_game_file_version) <= kGameVersion_272)
@@ -163,7 +171,7 @@ void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
void RoomStatus::WriteToSavegame(Stream *out) const {
out->WriteInt8(beenhere);
out->WriteInt32(numobj);
- for (int i = 0; i < numobj; ++i) {
+ for (size_t i = 0; i < numobj; ++i) {
obj[i].WriteToSavegame(out);
Properties::WriteValues(objProps[i], out);
if (_G(loaded_game_file_version) <= kGameVersion_272)
diff --git a/engines/ags/engine/ac/room_status.h b/engines/ags/engine/ac/room_status.h
index ee8d2e79f14..bf17316e336 100644
--- a/engines/ags/engine/ac/room_status.h
+++ b/engines/ags/engine/ac/room_status.h
@@ -52,17 +52,17 @@ struct HotspotState {
struct RoomStatus {
int beenhere = 0;
int numobj = 0;
- RoomObject obj[MAX_ROOM_OBJECTS];
+ std::vector<RoomObject> obj;
int tsdatasize = 0;
char *tsdata = nullptr;
Interaction intrHotspot[MAX_ROOM_HOTSPOTS];
- Interaction intrObject[MAX_ROOM_OBJECTS];
+ std::vector<Interaction> intrObject;
Interaction intrRegion[MAX_ROOM_REGIONS];
Interaction intrRoom;
Shared::StringIMap roomProps;
Shared::StringIMap hsProps[MAX_ROOM_HOTSPOTS];
- Shared::StringIMap objProps[MAX_ROOM_OBJECTS];
+ std::vector<Shared::StringIMap> objProps;
HotspotState hotspot[MAX_ROOM_HOTSPOTS];
int8 region_enabled[MAX_ROOM_REGIONS];
short walkbehind_base[MAX_WALK_BEHINDS];
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 3f2c81cc643..63c69626c34 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -374,8 +374,7 @@ void DoBeforeRestore(PreservedParams &pp) {
_G(dialogScriptsInst) = nullptr;
resetRoomStatuses();
- _GP(troom).FreeScriptData();
- _GP(troom).FreeProperties();
+ _GP(troom) = RoomStatus(); // reset temp room state
free_do_once_tokens();
// unregister gui controls from API exports
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 4bc8a5ae073..277cf1adf3c 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -917,8 +917,9 @@ HSaveError WriteThisRoom(Stream *out) {
}
// room object movement paths cache
- out->WriteInt32(_GP(thisroom).ObjectCount + 1);
- for (size_t i = 0; i < _GP(thisroom).ObjectCount + 1; ++i) {
+ // CHECKME: not sure why it saves (object count + 1) move lists
+ out->WriteInt32(_GP(thisroom).Objects.size() + 1);
+ for (size_t i = 0; i < _GP(thisroom).Objects.size() + 1; ++i) {
_GP(mls)[i].WriteToFile(out);
}
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index 0db9e4bd203..de5529dfae7 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -149,12 +149,13 @@ HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
room->Edges.Right = in->ReadInt16();
// Room objects
- room->ObjectCount = in->ReadInt16();
- if (room->ObjectCount > MAX_ROOM_OBJECTS)
- return new RoomFileError(kRoomFileErr_IncompatibleEngine, String::FromFormat("Too many objects (in room: %d, max: %d).", room->ObjectCount, MAX_ROOM_OBJECTS));
+ uint16_t obj_count = in->ReadInt16();
+ if (obj_count > MAX_ROOM_OBJECTS)
+ return new RoomFileError(kRoomFileErr_IncompatibleEngine, String::FromFormat("Too many objects (in room: %d, max: %d).", obj_count, MAX_ROOM_OBJECTS));
- for (size_t i = 0; i < room->ObjectCount; ++i)
- ReadRoomObject(room->Objects[i], in);
+ room->Objects.resize(obj_count);
+ for (auto &obj : room->Objects)
+ ReadRoomObject(obj, in);
// Legacy interactions
if (data_ver >= kRoomVersion_253) {
@@ -169,8 +170,8 @@ HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
if (data_ver >= kRoomVersion_241 && data_ver < kRoomVersion_300a) {
for (size_t i = 0; i < room->HotspotCount; ++i)
room->Hotspots[i].Interaction.reset(Interaction::CreateFromStream(in));
- for (size_t i = 0; i < room->ObjectCount; ++i)
- room->Objects[i].Interaction.reset(Interaction::CreateFromStream(in));
+ for (auto &obj : room->Objects)
+ obj.Interaction.reset(Interaction::CreateFromStream(in));
room->Interaction.reset(Interaction::CreateFromStream(in));
}
@@ -190,22 +191,22 @@ HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
room->EventHandlers.reset(InteractionScripts::CreateFromStream(in));
for (size_t i = 0; i < room->HotspotCount; ++i)
room->Hotspots[i].EventHandlers.reset(InteractionScripts::CreateFromStream(in));
- for (size_t i = 0; i < room->ObjectCount; ++i)
- room->Objects[i].EventHandlers.reset(InteractionScripts::CreateFromStream(in));
+ for (auto &obj : room->Objects)
+ obj.EventHandlers.reset(InteractionScripts::CreateFromStream(in));
for (size_t i = 0; i < room->RegionCount; ++i)
room->Regions[i].EventHandlers.reset(InteractionScripts::CreateFromStream(in));
}
if (data_ver >= kRoomVersion_200_alpha) {
- for (size_t i = 0; i < room->ObjectCount; ++i)
- room->Objects[i].Baseline = in->ReadInt32();
+ for (auto &obj : room->Objects)
+ obj.Baseline = in->ReadInt32();
room->Width = in->ReadInt16();
room->Height = in->ReadInt16();
}
if (data_ver >= kRoomVersion_262)
- for (size_t i = 0; i < room->ObjectCount; ++i)
- room->Objects[i].Flags = in->ReadInt16();
+ for (auto &obj : room->Objects)
+ obj.Flags = in->ReadInt16();
if (data_ver >= kRoomVersion_200_final)
room->MaskResolution = in->ReadInt16();
@@ -339,15 +340,15 @@ HError ReadCompSc3Block(RoomStruct *room, Stream *in, RoomFileVersion /*data_ver
// Room object names
HError ReadObjNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
size_t name_count = static_cast<uint8_t>(in->ReadInt8());
- if (name_count != room->ObjectCount)
+ if (name_count != room->Objects.size())
return new RoomFileError(kRoomFileErr_InconsistentData,
- String::FromFormat("In the object names block, expected name count: %zu, got %zu", room->ObjectCount, name_count));
+ String::FromFormat("In the object names block, expected name count: %zu, got %zu", room->Objects.size(), name_count));
- for (size_t i = 0; i < room->ObjectCount; ++i) {
+ for (auto &obj : room->Objects) {
if (data_ver >= kRoomVersion_3415)
- room->Objects[i].Name = StrUtil::ReadString(in);
+ obj.Name = StrUtil::ReadString(in);
else
- room->Objects[i].Name.ReadCount(in, LEGACY_MAXOBJNAMELEN);
+ obj.Name.ReadCount(in, LEGACY_MAXOBJNAMELEN);
}
return HError::None();
}
@@ -355,15 +356,15 @@ HError ReadObjNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver)
// Room object script names
HError ReadObjScNamesBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
size_t name_count = static_cast<uint8_t>(in->ReadInt8());
- if (name_count != room->ObjectCount)
+ if (name_count != room->Objects.size())
return new RoomFileError(kRoomFileErr_InconsistentData,
- String::FromFormat("In the object script names block, expected name count: %zu, got %zu", room->ObjectCount, name_count));
+ String::FromFormat("In the object script names block, expected name count: %zu, got %zu", room->Objects.size(), name_count));
- for (size_t i = 0; i < room->ObjectCount; ++i) {
+ for (auto &obj : room->Objects) {
if (data_ver >= kRoomVersion_3415)
- room->Objects[i].ScriptName = StrUtil::ReadString(in);
+ obj.ScriptName = StrUtil::ReadString(in);
else
- room->Objects[i].ScriptName.ReadCount(in, MAX_SCRIPT_NAME_LEN);
+ obj.ScriptName.ReadCount(in, MAX_SCRIPT_NAME_LEN);
}
return HError::None();
}
@@ -398,8 +399,8 @@ HError ReadPropertiesBlock(RoomStruct *room, Stream *in, RoomFileVersion /*data_
errors += Properties::ReadValues(room->Properties, in);
for (size_t i = 0; i < room->HotspotCount; ++i)
errors += Properties::ReadValues(room->Hotspots[i].Properties, in);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- errors += Properties::ReadValues(room->Objects[i].Properties, in);
+ for (auto &obj : room->Objects)
+ errors += Properties::ReadValues(obj.Properties, in);
if (errors > 0)
return new RoomFileError(kRoomFileErr_InvalidPropertyValues);
@@ -525,9 +526,9 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
for (size_t i = 0; i < (size_t)MAX_ROOM_HOTSPOTS; ++i)
if (!room->Hotspots[i].Interaction)
room->Hotspots[i].Interaction.reset(new Interaction());
- for (size_t i = 0; i < (size_t)MAX_ROOM_OBJECTS; ++i)
- if (!room->Objects[i].Interaction)
- room->Objects[i].Interaction.reset(new Interaction());
+ for (auto &obj : room->Objects)
+ if (!obj.Interaction)
+ obj.Interaction.reset(new Interaction());
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i)
if (!room->Regions[i].Interaction)
room->Regions[i].Interaction.reset(new Interaction());
@@ -535,14 +536,14 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
// Upgade room object script names
if (data_ver < kRoomVersion_300a) {
- for (size_t i = 0; i < room->ObjectCount; ++i) {
- if (room->Objects[i].ScriptName.GetLength() > 0) {
+ for (auto &obj : room->Objects) {
+ if (obj.ScriptName.GetLength() > 0) {
String jibbledScriptName;
- jibbledScriptName.Format("o%s", room->Objects[i].ScriptName.GetCStr());
+ jibbledScriptName.Format("o%s", obj.ScriptName.GetCStr());
jibbledScriptName.MakeLower();
if (jibbledScriptName.GetLength() >= 2)
jibbledScriptName.SetAt(1, toupper(jibbledScriptName[1u]));
- room->Objects[i].ScriptName = jibbledScriptName;
+ obj.ScriptName = jibbledScriptName;
}
}
}
@@ -553,11 +554,11 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
// function in the engine
if (data_ver < kRoomVersion_303b && game_is_hires) {
const int mul = HIRES_COORD_MULTIPLIER;
- for (size_t i = 0; i < room->ObjectCount; ++i) {
- room->Objects[i].X *= mul;
- room->Objects[i].Y *= mul;
- if (room->Objects[i].Baseline > 0) {
- room->Objects[i].Baseline *= mul;
+ for (auto &obj : room->Objects) {
+ obj.X *= mul;
+ obj.Y *= mul;
+ if (obj.Baseline > 0) {
+ obj.Baseline *= mul;
}
}
@@ -582,8 +583,8 @@ HRoomFileError UpdateRoomData(RoomStruct *room, RoomFileVersion data_ver, bool g
// NOTE: this is impossible to do without game sprite information loaded beforehand
// NOTE: this should be done after coordinate conversion above for simplicity
if (data_ver < kRoomVersion_300a) {
- for (size_t i = 0; i < room->ObjectCount; ++i)
- room->Objects[i].Y += sprinfos[room->Objects[i].Sprite].Height;
+ for (auto &obj : room->Objects)
+ obj.Y += sprinfos[obj.Sprite].Height;
}
if (data_ver >= kRoomVersion_251) {
@@ -681,9 +682,9 @@ void WriteMainBlock(const RoomStruct *room, Stream *out) {
out->WriteInt16(room->Edges.Left);
out->WriteInt16(room->Edges.Right);
- out->WriteInt16((int16_t)room->ObjectCount);
- for (size_t i = 0; i < room->ObjectCount; ++i) {
- WriteRoomObject(room->Objects[i], out);
+ out->WriteInt16((int16_t)room->Objects.size());
+ for (const auto &obj : room->Objects) {
+ WriteRoomObject(obj, out);
}
out->WriteInt32(0); // legacy interaction vars
@@ -692,17 +693,17 @@ void WriteMainBlock(const RoomStruct *room, Stream *out) {
WriteInteractionScripts(room->EventHandlers.get(), out);
for (size_t i = 0; i < room->HotspotCount; ++i)
WriteInteractionScripts(room->Hotspots[i].EventHandlers.get(), out);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- WriteInteractionScripts(room->Objects[i].EventHandlers.get(), out);
+ for (const auto &obj : room->Objects)
+ WriteInteractionScripts(obj.EventHandlers.get(), out);
for (size_t i = 0; i < room->RegionCount; ++i)
WriteInteractionScripts(room->Regions[i].EventHandlers.get(), out);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- out->WriteInt32(room->Objects[i].Baseline);
+ for (const auto &obj : room->Objects)
+ out->WriteInt32(obj.Baseline);
out->WriteInt16(room->Width);
out->WriteInt16(room->Height);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- out->WriteInt16(room->Objects[i].Flags);
+ for (const auto &obj : room->Objects)
+ out->WriteInt16(obj.Flags);
out->WriteInt16(room->MaskResolution);
out->WriteInt32(MAX_WALK_AREAS + 1);
@@ -755,15 +756,15 @@ void WriteCompSc3Block(const RoomStruct *room, Stream *out) {
}
void WriteObjNamesBlock(const RoomStruct *room, Stream *out) {
- out->WriteByte((int8_t)room->ObjectCount);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- Shared::StrUtil::WriteString(room->Objects[i].Name, out);
+ out->WriteByte((uint8_t)room->Objects.size());
+ for (const auto &obj : room->Objects)
+ Shared::StrUtil::WriteString(obj.Name, out);
}
void WriteObjScNamesBlock(const RoomStruct *room, Stream *out) {
- out->WriteByte((int8_t)room->ObjectCount);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- Shared::StrUtil::WriteString(room->Objects[i].ScriptName, out);
+ out->WriteByte((uint8_t)room->Objects.size());
+ for (const auto &obj : room->Objects)
+ Shared::StrUtil::WriteString(obj.ScriptName, out);
}
void WriteAnimBgBlock(const RoomStruct *room, Stream *out) {
@@ -781,8 +782,8 @@ void WritePropertiesBlock(const RoomStruct *room, Stream *out) {
Properties::WriteValues(room->Properties, out);
for (size_t i = 0; i < room->HotspotCount; ++i)
Properties::WriteValues(room->Hotspots[i].Properties, out);
- for (size_t i = 0; i < room->ObjectCount; ++i)
- Properties::WriteValues(room->Objects[i].Properties, out);
+ for (const auto &obj : room->Objects)
+ Properties::WriteValues(obj.Properties, out);
}
void WriteStrOptions(const RoomStruct *room, Stream *out) {
@@ -801,7 +802,7 @@ HRoomFileError WriteRoomData(const RoomStruct *room, Stream *out, RoomFileVersio
if (room->CompiledScript)
WriteRoomBlock(room, kRoomFblk_CompScript3, WriteCompSc3Block, out);
// Object names
- if (room->ObjectCount > 0) {
+ if (room->Objects.size() > 0) {
WriteRoomBlock(room, kRoomFblk_ObjectNames, WriteObjNamesBlock, out);
WriteRoomBlock(room, kRoomFblk_ObjectScNames, WriteObjScNamesBlock, out);
}
diff --git a/engines/ags/shared/game/room_struct.cpp b/engines/ags/shared/game/room_struct.cpp
index a2f76d3f8c5..e5cd1915e1f 100644
--- a/engines/ags/shared/game/room_struct.cpp
+++ b/engines/ags/shared/game/room_struct.cpp
@@ -112,10 +112,7 @@ void RoomStruct::Free() {
Hotspots[i].Interaction.reset();
Hotspots[i].Properties.clear();
}
- for (size_t i = 0; i < (size_t)MAX_ROOM_OBJECTS; ++i) {
- Objects[i].Interaction.reset();
- Objects[i].Properties.clear();
- }
+ Objects.clear();
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i) {
Regions[i].Interaction.reset();
Regions[i].Properties.clear();
@@ -139,8 +136,8 @@ void RoomStruct::FreeScripts() {
EventHandlers.reset();
for (size_t i = 0; i < HotspotCount; ++i)
Hotspots[i].EventHandlers.reset();
- for (size_t i = 0; i < ObjectCount; ++i)
- Objects[i].EventHandlers.reset();
+ for (auto &obj : Objects)
+ obj.EventHandlers.reset();
for (size_t i = 0; i < RegionCount; ++i)
Regions[i].EventHandlers.reset();
}
@@ -159,7 +156,6 @@ void RoomStruct::InitDefaults() {
BgFrameCount = 1;
HotspotCount = 0;
- ObjectCount = 0;
RegionCount = 0;
WalkAreaCount = 0;
WalkBehindCount = 0;
@@ -167,8 +163,6 @@ void RoomStruct::InitDefaults() {
for (size_t i = 0; i < (size_t)MAX_ROOM_HOTSPOTS; ++i)
Hotspots[i] = RoomHotspot();
- for (size_t i = 0; i < (size_t)MAX_ROOM_OBJECTS; ++i)
- Objects[i] = RoomObjectInfo();
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i)
Regions[i] = RoomRegion();
for (size_t i = 0; i <= (size_t)MAX_WALK_AREAS; ++i)
diff --git a/engines/ags/shared/game/room_struct.h b/engines/ags/shared/game/room_struct.h
index 89b1a182b50..e54322f4e0b 100644
--- a/engines/ags/shared/game/room_struct.h
+++ b/engines/ags/shared/game/room_struct.h
@@ -349,8 +349,7 @@ public:
// Room entities
size_t HotspotCount;
RoomHotspot Hotspots[MAX_ROOM_HOTSPOTS];
- size_t ObjectCount;
- RoomObjectInfo Objects[MAX_ROOM_OBJECTS];
+ std::vector<RoomObjectInfo> Objects;
size_t RegionCount;
RoomRegion Regions[MAX_ROOM_REGIONS];
size_t WalkAreaCount;
Commit: 13c3d6cddcf08dd0f2e3e4d41711ff1e26ba3acd
https://github.com/scummvm/scummvm/commit/13c3d6cddcf08dd0f2e3e4d41711ff1e26ba3acd
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2022-06-15T22:13:02+01:00
Commit Message:
AGS: Increased Room Objects limit to 256
>From upstream b71f820c992d70ffef8f40b783ee4b53df634254
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/runtime_defines.h
engines/ags/engine/game/savegame_components.cpp
engines/ags/engine/game/savegame_v321.cpp
engines/ags/globals.h
engines/ags/shared/game/room_struct.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 830e6e22675..22106aacce6 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1141,7 +1141,6 @@ static bool scale_and_flip_sprite(int useindx, int sppic, int newwidth, int newh
// returns 1 if nothing at all has changed and actsps is still
// intact from last time; 0 otherwise
int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware) {
- int useindx = aa;
bool hardwareAccelerated = !alwaysUseSoftware && _G(gfxDriver)->HasAcceleratedTransform();
if (_GP(spriteset)[_G(objs)[aa].num] == nullptr)
@@ -1215,6 +1214,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
isMirrored = true;
}
+ const int useindx = aa; // actsps array index
auto &actsp = _GP(actsps)[useindx];
actsp.SpriteID = _G(objs)[aa].num; // for texture sharing
if ((hardwareAccelerated) &&
@@ -1322,10 +1322,10 @@ void prepare_objects_for_drawing() {
if ((_G(objs)[aa].x >= _GP(thisroom).Width) || (_G(objs)[aa].y < 1))
continue;
- const int useindx = aa;
int tehHeight;
int actspsIntact = construct_object_gfx(aa, nullptr, &tehHeight, false);
+ const int useindx = aa; // actsps array index
auto &actsp = _GP(actsps)[useindx];
// update the cache for next time
@@ -1437,7 +1437,6 @@ void prepare_characters_for_drawing() {
if (_GP(game).chars[aa].on == 0) continue;
if (_GP(game).chars[aa].room != _G(displayed_room)) continue;
_G(eip_guinum) = aa;
- const int useindx = aa + MAX_ROOM_OBJECTS;
CharacterInfo *chin = &_GP(game).chars[aa];
_G(our_eip) = 330;
@@ -1512,6 +1511,7 @@ void prepare_characters_for_drawing() {
_G(our_eip) = 3331;
+ const int useindx = aa + ACTSP_OBJSOFF; // actsps array index
auto &actsp = _GP(actsps)[useindx];
actsp.SpriteID = sppic; // for texture sharing
@@ -1666,7 +1666,7 @@ void prepare_characters_for_drawing() {
}
Bitmap *get_cached_character_image(int charid) {
- return _GP(actsps)[charid + MAX_ROOM_OBJECTS].Bmp.get();
+ return _GP(actsps)[charid + ACTSP_OBJSOFF].Bmp.get();
}
Bitmap *get_cached_object_image(int objid) {
diff --git a/engines/ags/engine/ac/runtime_defines.h b/engines/ags/engine/ac/runtime_defines.h
index 3899dfb4881..6bfcf23e9e7 100644
--- a/engines/ags/engine/ac/runtime_defines.h
+++ b/engines/ags/engine/ac/runtime_defines.h
@@ -125,7 +125,10 @@ const int LegacyRoomVolumeFactor = 30;
#define FOR_ANIMATION 1
#define FOR_SCRIPT 2
#define FOR_EXITLOOP 3
-#define CHMLSOFFS (MAX_ROOM_OBJECTS+1) // reserve this many movelists for objects & stuff
+// an actsps index offset for characters
+#define ACTSP_OBJSOFF (MAX_ROOM_OBJECTS)
+// a 1-based movelist index offset for characters
+#define CHMLSOFFS (1 + MAX_ROOM_OBJECTS)
#define MAX_SCRIPT_AT_ONCE 10
#define EVENT_NONE 0
#define EVENT_INPROGRESS 1
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index 277cf1adf3c..90df78e729b 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -967,7 +967,7 @@ HSaveError ReadThisRoom(Stream *in, int32_t cmp_ver, const PreservedParams & /*p
if (!AssertCompatLimit(err, objmls_count, CHMLSOFFS, "room object move lists"))
return err;
for (int i = 0; i < objmls_count; ++i) {
- err = _GP(mls)[i].ReadFromFile(in, cmp_ver > 0 ? 1 : 0); // FIXME!!
+ err = _GP(mls)[i].ReadFromFile(in, cmp_ver > 0 ? 1 : 0); // FIXME cmp_ver, ugly
if (!err)
return err;
}
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 4cfb35d240a..5236b595a9e 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -175,7 +175,6 @@ static void ReadMoveList_Aligned(Stream *in) {
AlignedStream align_s(in, Shared::kAligned_Read);
for (int i = 0; i < _GP(game).numcharacters + MAX_ROOM_OBJECTS + 1; ++i) {
_GP(mls)[i].ReadFromFile_Legacy(&align_s);
-
align_s.Reset();
}
}
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 71a0a20b6b9..982f4dbc695 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -575,8 +575,9 @@ public:
AGS::Engine::IDriverDependantBitmap *_blankSidebarImage = nullptr;
AGS::Engine::IDriverDependantBitmap *_debugConsole = nullptr;
- // actsps is used for temporary storage of the bitamp image
- // of the latest version of the sprite
+ // actsps is used for temporary storage of the bitamp and texture
+ // of the latest version of the sprite (room objects and characters);
+ // objects sprites begin with index 0, characters are after MAX_ROOM_OBJECTS
std::vector<ObjTexture> *_actsps;
// Walk-behind textures (3D renderers only)
std::vector<ObjTexture> *_walkbehindobj;
@@ -758,6 +759,8 @@ public:
ObjectCache *_objcache;
std::vector<Point> *_screenovercache;
std::vector<CharacterExtras> *_charextra;
+ // MoveLists for characters and room objects; NOTE: 1-based array!
+ // object sprites begin with index 1, characters are after MAX_ROOM_OBJECTS + 1
std::vector<MoveList> *_mls;
GameSetup *_usetup;
diff --git a/engines/ags/shared/game/room_struct.h b/engines/ags/shared/game/room_struct.h
index e54322f4e0b..7852e895cea 100644
--- a/engines/ags/shared/game/room_struct.h
+++ b/engines/ags/shared/game/room_struct.h
@@ -101,8 +101,8 @@ enum RoomFlags {
#define MAX_ROOM_BGFRAMES 5 // max number of frames in animating bg scene
-#define MAX_ROOM_HOTSPOTS 50 // v2.62 increased from 20 to 30; v2.8 to 50
-#define MAX_ROOM_OBJECTS 40
+#define MAX_ROOM_HOTSPOTS 50 // v2.62: 20 -> 30; v2.8: -> 50
+#define MAX_ROOM_OBJECTS 256 // v3.6.0: 40 -> 256 (now limited by room format)
#define MAX_ROOM_REGIONS 16
// TODO: this is remains of the older code, MAX_WALK_AREAS = real number - 1, where
// -1 is for the solid wall. When fixing this you need to be careful, because some
More information about the Scummvm-git-logs
mailing list