Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_ALL_DYNAMIC_CLASSES_H
#define AGS_ENGINE_AC_DYNOBJ_ALL_DYNAMIC_CLASSES_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/engine/ac/dynobj/cc_audio_channel.h"
#include "ags/engine/ac/dynobj/cc_audio_clip.h"
#include "ags/engine/ac/dynobj/cc_character.h"
#include "ags/engine/ac/dynobj/cc_dialog.h"
#include "ags/engine/ac/dynobj/cc_gui.h"
#include "ags/engine/ac/dynobj/cc_gui_object.h"
#include "ags/engine/ac/dynobj/cc_hotspot.h"
#include "ags/engine/ac/dynobj/cc_inventory.h"
#include "ags/engine/ac/dynobj/cc_object.h"
#include "ags/engine/ac/dynobj/cc_region.h"
#include "ags/engine/ac/dynobj/cc_serializer.h"
#endif

View File

@@ -0,0 +1,41 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_ALL_SCRIPT_CLASSES_H
#define AGS_ENGINE_AC_DYNOBJ_ALL_SCRIPT_CLASSES_H
#include "ags/engine/ac/dynobj/script_date_time.h"
#include "ags/engine/ac/dynobj/script_dialog.h"
#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
#include "ags/engine/ac/dynobj/script_gui.h"
#include "ags/engine/ac/dynobj/script_hotspot.h"
#include "ags/engine/ac/dynobj/script_inv_item.h"
#include "ags/engine/ac/dynobj/script_mouse.h"
#include "ags/engine/ac/dynobj/script_object.h"
#include "ags/engine/ac/dynobj/script_overlay.h"
#include "ags/engine/ac/dynobj/script_region.h"
#include "ags/engine/ac/dynobj/script_string.h"
#include "ags/engine/ac/dynobj/script_system.h"
#include "ags/engine/ac/dynobj/script_view_frame.h"
#endif

View File

@@ -0,0 +1,95 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/shared/core/types.h"
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/util/memory_stream.h"
namespace AGS3 {
using namespace AGS::Shared;
int CCBasicObject::Dispose(void * /*address*/, bool /*force*/) {
return 0; // cannot be removed from memory
}
int CCBasicObject::Serialize(void * /*address*/, uint8_t * /*buffer*/, int /*bufsize*/) {
return 0; // does not save data
}
void *CCBasicObject::GetFieldPtr(void *address, intptr_t offset) {
return static_cast<uint8_t *>(address) + offset;
}
void CCBasicObject::Read(void *address, intptr_t offset, uint8_t *dest, size_t size) {
memcpy(dest, static_cast<uint8_t *>(address) + offset, size);
}
uint8_t CCBasicObject::ReadInt8(void *address, intptr_t offset) {
return *(uint8_t *)(static_cast<uint8_t *>(address) + offset);
}
int16_t CCBasicObject::ReadInt16(void *address, intptr_t offset) {
return *(int16_t *)(static_cast<uint8_t *>(address) + offset);
}
int32_t CCBasicObject::ReadInt32(void *address, intptr_t offset) {
return *(int32_t *)(static_cast<uint8_t *>(address) + offset);
}
float CCBasicObject::ReadFloat(void *address, intptr_t offset) {
return *(float *)(static_cast<uint8_t *>(address) + offset);
}
void CCBasicObject::Write(void *address, intptr_t offset, const uint8_t *src, size_t size) {
memcpy(static_cast<uint8_t *>(address) + offset, src, size);
}
void CCBasicObject::WriteInt8(void *address, intptr_t offset, uint8_t val) {
*(uint8_t *)(static_cast<uint8_t *>(address) + offset) = val;
}
void CCBasicObject::WriteInt16(void *address, intptr_t offset, int16_t val) {
*(int16_t *)(static_cast<uint8_t *>(address) + offset) = val;
}
void CCBasicObject::WriteInt32(void *address, intptr_t offset, int32_t val) {
*(int32_t *)(static_cast<uint8_t *>(address) + offset) = val;
}
void CCBasicObject::WriteFloat(void *address, intptr_t offset, float val) {
*(float *)(static_cast<uint8_t *>(address) + offset) = val;
}
int AGSCCDynamicObject::Serialize(void *address, uint8_t *buffer, int bufsize) {
// If the required space is larger than the provided buffer,
// then return negated required space, notifying the caller that a larger buffer is necessary
size_t req_size = CalcSerializeSize(address);
assert(req_size <= INT32_MAX); // dynamic object API does not support size > int32
if (bufsize < 0 || req_size > static_cast<size_t>(bufsize))
return -(static_cast<int32_t>(req_size));
MemoryStream mems(reinterpret_cast<uint8_t *>(buffer), bufsize, kStream_Write);
Serialize(address, &mems);
return static_cast<int32_t>(mems.GetPosition());
}
} // namespace AGS3

View File

@@ -0,0 +1,117 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// This is a collection of common implementations of the IScriptObject
// interface. Intended to be used as parent classes for majority of the
// script object managers.
//
// CCBasicObject: parent for managers that treat object contents as raw
// byte buffer.
//
// AGSCCDynamicObject, extends CCBasicObject: parent for built-in dynamic
// object managers; provides simpler serialization methods working with
// streams instead of a raw memory buffer.
//
// AGSCCStaticObject, extends CCBasicObject: a formal stub, intended as
// a parent for built-in static object managers.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_CCDYNAMIC_OBJECT_H
#define AGS_ENGINE_AC_DYNOBJ_CCDYNAMIC_OBJECT_H
#include "ags/engine/ac/dynobj/cc_script_object.h"
namespace AGS3 {
namespace AGS { namespace Shared { class Stream; } }
// CCBasicObject: basic implementation of the script object interface,
// intended to be used as a parent for object/manager classes that do not
// require specific implementation.
// * Dispose ignored, never deletes any data on its own;
// * Serialization skipped, does not save or load anything;
// * Provides default implementation for reading and writing data fields,
// treats the contents of an object as a raw byte buffer.
struct CCBasicObject : public IScriptObject {
public:
virtual ~CCBasicObject() = default;
// Dispose the object
int Dispose(void * /*address*/, bool /*force*/) override;
// Serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
int Serialize(void * /*address*/, uint8_t * /*buffer*/, int /*bufsize*/) override;
//
// Legacy support for reading and writing object fields by their relative offset
//
void *GetFieldPtr(void *address, intptr_t offset) override;
void Read(void *address, intptr_t offset, uint8_t *dest, size_t size) override;
uint8_t ReadInt8(void *address, intptr_t offset) override;
int16_t ReadInt16(void *address, intptr_t offset) override;
int32_t ReadInt32(void *address, intptr_t offset) override;
float ReadFloat(void *address, intptr_t offset) override;
void Write(void *address, intptr_t offset, const uint8_t *src, size_t size) override;
void WriteInt8(void *address, intptr_t offset, uint8_t val) override;
void WriteInt16(void *address, intptr_t offset, int16_t val) override;
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
void WriteFloat(void *address, intptr_t offset, float val) override;
};
// AGSCCDynamicObject: standard parent implementation for the built-in
// script objects/manager.
// * Serialization from a raw buffer; provides a virtual function that
// accepts Stream, to be implemented in children instead.
// * Provides Unserialize interface that accepts Stream.
struct AGSCCDynamicObject : public CCBasicObject {
public:
virtual ~AGSCCDynamicObject() = default;
// TODO: pass savegame format version
int Serialize(void *address, uint8_t *buffer, int bufsize) override;
// Try unserializing the object from the given input stream
virtual void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) = 0;
protected:
// Savegame serialization
// Calculate and return required space for serialization, in bytes
virtual size_t CalcSerializeSize(const void *address) = 0;
// Write object data into the provided stream
virtual void Serialize(const void *address, AGS::Shared::Stream *out) = 0;
};
// CCStaticObject is a base class for managing static global objects in script.
// The static objects can never be disposed, and do not support serialization
// through IScriptObject interface.
struct AGSCCStaticObject : public CCBasicObject {
public:
virtual ~AGSCCStaticObject() = default;
const char *GetType() override { return "StaticObject"; }
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,51 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/shared/util/stream.h"
#include "ags/engine/ac/dynobj/cc_audio_channel.h"
#include "ags/engine/ac/dynobj/script_audio_channel.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/media/audio/audio_system.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
const char *CCAudioChannel::GetType() {
return "AudioChannel";
}
size_t CCAudioChannel::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
void CCAudioChannel::Serialize(const void *address, Stream *out) {
const ScriptAudioChannel *ach = static_cast<const ScriptAudioChannel *>(address);
out->WriteInt32(ach->id);
}
void CCAudioChannel::Unserialize(int index, Stream *in, size_t data_sz) {
int id = in->ReadInt32();
ccRegisterUnserializedObject(index, &_G(scrAudioChannel)[id], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,41 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ_CC_AUDIO_CHANNEL_H
#define AGS_ENGINE_DYNOBJ_CC_AUDIO_CHANNEL_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCAudioChannel final : AGSCCDynamicObject {
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,50 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_audio_clip.h"
#include "ags/shared/ac/dynobj/script_audio_clip.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/game_setup_struct.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
using namespace AGS::Shared;
const char *CCAudioClip::GetType() {
return "AudioClip";
}
size_t CCAudioClip::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
void CCAudioClip::Serialize(const void *address, Stream *out) {
const ScriptAudioClip *ach = static_cast<const ScriptAudioClip *>(address);
out->WriteInt32(ach->id);
}
void CCAudioClip::Unserialize(int index, Stream *in, size_t data_sz) {
int id = in->ReadInt32();
ccRegisterUnserializedObject(index, &_GP(game).audioClips[id], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,41 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ_CC_AUDIO_CLIP_H
#define AGS_ENGINE_DYNOBJ_CC_AUDIO_CLIP_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCAudioClip final : AGSCCDynamicObject {
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,370 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_character.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/character_info.h"
#include "ags/engine/ac/global_character.h"
#include "ags/shared/ac/game_setup_struct.h"
#include "ags/shared/script/cc_common.h" // cc_error
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCCharacter::GetType() {
return "Character";
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
size_t CCCharacter::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCCharacter::Serialize(const void *address, Stream *out) {
const CharacterInfo *chaa = static_cast<const CharacterInfo *>(address);
out->WriteInt32(chaa->index_id);
}
void CCCharacter::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_GP(game).chars[num], this);
}
uint8_t CCCharacter::ReadInt8(void *address, intptr_t offset) {
const CharacterInfo *ci = static_cast<CharacterInfo *>(address);
const int on_offset = 28 * sizeof(int32_t) /* first var group */
+ 301 * sizeof(int16_t) /* inventory */ + sizeof(int16_t) * 2 /* two shorts */ + 40 /* name */ + 20 /* scrname */;
if (offset == on_offset)
return ci->on;
cc_error("ScriptCharacter: unsupported 'char' variable offset %d", offset);
return 0;
}
void CCCharacter::WriteInt8(void *address, intptr_t offset, uint8_t val) {
CharacterInfo *ci = static_cast<CharacterInfo *>(address);
const int on_offset = 28 * sizeof(int32_t) /* first var group */
+ 301 * sizeof(int16_t) /* inventory */ + sizeof(int16_t) * 2 /* two shorts */ + 40 /* name */ + 20 /* scrname */;
if (offset == on_offset)
ci->on = val;
else
cc_error("ScriptCharacter: unsupported 'char' variable offset %d", offset);
}
int16_t CCCharacter::ReadInt16(void *address, intptr_t offset) {
const CharacterInfo *ci = static_cast<CharacterInfo *>(address);
// Handle inventory fields
const int invoffset = 112;
if (offset >= invoffset && offset < (uint)(invoffset + MAX_INV * sizeof(short))) {
return ci->inv[(offset - invoffset) / sizeof(short)];
}
switch (offset) {
// +9 int32 = 36
case 36:
return ci->following;
case 38:
return ci->followinfo;
// 40 +1 int32 = 44
case 44:
return ci->idletime;
case 46:
return ci->idleleft;
case 48:
return ci->transparency;
case 50:
return ci->baseline;
// 52 +3 int32 = 64
case 64:
return ci->blinkview;
case 66:
return ci->blinkinterval;
case 68:
return ci->blinktimer;
case 70:
return ci->blinkframe;
case 72:
return ci->walkspeed_y;
case 74:
return ci->pic_yoffs;
// 76 +2 int32 = 84
case 84:
return ci->speech_anim_speed;
case 86:
return ci->idle_anim_speed;
case 88:
return ci->blocking_width;
case 90:
return ci->blocking_height;
// 92 +1 int32 = 96
case 96:
return ci->pic_xoffs;
case 98:
return ci->walkwaitcounter;
case 100:
return ci->loop;
case 102:
return ci->frame;
case 104:
return ci->walking;
case 106:
return ci->animating;
case 108:
return ci->walkspeed;
case 110:
return ci->animspeed;
// 112 +301 int16 = 714 (skip inventory)
case 714:
return ci->actx;
case 716:
return ci->acty;
default:
cc_error("ScriptCharacter: unsupported 'short' variable offset %d", offset);
return 0;
}
}
void CCCharacter::WriteInt16(void *address, intptr_t offset, int16_t val) {
CharacterInfo *ci = static_cast<CharacterInfo *>(address);
// Detect when a game directly modifies the inventory, which causes the displayed
// and actual inventory to diverge since 2.70. Force an update of the displayed
// inventory for older games that rely on this behaviour.
const int invoffset = 112;
if (offset >= invoffset && offset < (uint)(invoffset + MAX_INV * sizeof(short))) {
ci->inv[(offset - invoffset) / sizeof(short)] = val;
update_invorder();
return;
}
// TODO: for safety, find out which of the following fields
// must be readonly, and add assertions for them, i.e.:
// cc_error("ScriptCharacter: attempt to write readonly 'short' variable at offset %d", offset);
switch (offset) {
// +9 int32 = 36
case 36:
ci->following = val;
break;
case 38:
ci->followinfo = val;
break;
// 40 +1 int32 = 44
case 44:
ci->idletime = val;
break;
case 46:
ci->idleleft = val;
break;
case 48:
ci->transparency = val;
break;
case 50:
ci->baseline = val;
break;
// 52 +3 int32 = 64
case 64:
ci->blinkview = val;
break;
case 66:
ci->blinkinterval = val;
break;
case 68:
ci->blinktimer = val;
break;
case 70:
ci->blinkframe = val;
break;
case 72:
ci->walkspeed_y = val;
break;
case 74:
ci->pic_yoffs = val;
break;
// 76 +2 int32 = 84
case 84:
ci->speech_anim_speed = val;
break;
case 86:
ci->idle_anim_speed = val;
break;
case 88:
ci->blocking_width = val;
break;
case 90:
ci->blocking_height = val;
break;
// 92 +1 int32 = 96
case 96:
ci->pic_xoffs = val;
break;
case 98:
ci->walkwaitcounter = val;
break;
case 100:
ci->loop = val;
break;
case 102:
ci->frame = val;
break;
case 104:
ci->walking = val;
break;
case 106:
ci->animating = val;
break;
case 108:
ci->walkspeed = val;
break;
case 110:
ci->animspeed = val;
break;
// 112 +301 int16 = 714 (skip inventory)
case 714:
ci->actx = val;
break;
case 716:
ci->acty = val;
break;
default:
cc_error("ScriptCharacter: unsupported 'short' variable offset %d", offset);
break;
}
}
int32_t CCCharacter::ReadInt32(void *address, intptr_t offset) {
const CharacterInfo *ci = static_cast<CharacterInfo *>(address);
switch (offset) {
case 0:
return ci->defview;
case 4:
return ci->talkview;
case 8:
return ci->view;
case 12:
return ci->room;
case 16:
return ci->prevroom;
case 20:
return ci->x;
case 24:
return ci->y;
case 28:
return ci->wait;
case 32:
return ci->flags;
// 36 +2 int16 = 40
case 40:
return ci->idleview;
// 44 +4 int16 = 52
case 52:
return ci->activeinv;
case 56:
return ci->talkcolor;
case 60:
return ci->thinkview;
// 64 +6 int16 = 76
case 76:
return ci->z;
case 80:
return ci->walkwait;
// 84 +4 int16 = 100
case 92:
return ci->index_id;
default:
cc_error("ScriptCharacter: unsupported 'int' variable offset %d", offset);
return 0;
}
}
void CCCharacter::WriteInt32(void *address, intptr_t offset, int32_t val) {
CharacterInfo *ci = static_cast<CharacterInfo *>(address);
// TODO: for safety, find out which of the following fields
// must be readonly, and add assertions for them, i.e.:
// cc_error("ScriptCharacter: attempt to write readonly 'int' variable at offset %d", offset);
switch (offset) {
case 0:
ci->defview = val;
break;
case 4:
ci->talkview = val;
break;
case 8:
ci->view = val;
break;
case 12:
ci->room = val;
break;
case 16:
ci->prevroom = val;
break;
case 20:
ci->x = val;
break;
case 24:
ci->y = val;
break;
case 28:
ci->wait = val;
break;
case 32:
ci->flags = val;
break;
// 36 +2 int16 = 40
case 40:
ci->idleview = val;
break;
// 44 +4 int16 = 52
case 52:
ci->activeinv = val;
break;
case 56:
ci->talkcolor = val;
break;
case 60:
ci->thinkview = val;
break;
// 64 +6 int16 = 76
case 76:
ci->z = val;
break;
case 80:
ci->walkwait = val;
break;
// 84 +4 int16 = 100
case 92:
ci->index_id = val;
break;
default:
cc_error("ScriptCharacter: unsupported 'int' variable offset %d", offset);
break;
}
}
} // namespace AGS3

View File

@@ -0,0 +1,58 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Wrapper around script "Character" struct, managing access to its variables.
// Assumes object data contains CharacterInfo object.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_CHARACTER_H
#define AGS_ENGINE_AC_DYNOBJ_CC_CHARACTER_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCCharacter final : AGSCCDynamicObject {
public:
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
uint8_t ReadInt8(void *address, intptr_t offset) override;
int16_t ReadInt16(void *address, intptr_t offset) override;
int32_t ReadInt32(void *address, intptr_t offset) override;
void WriteInt8(void *address, intptr_t offset, uint8_t val) override;
void WriteInt16(void *address, intptr_t offset, int16_t val) override;
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_dialog.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/ac/dialog.h"
#include "ags/shared/ac/dialog_topic.h"
#include "ags/shared/ac/game_struct_defines.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCDialog::GetType() {
return "Dialog";
}
size_t CCDialog::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCDialog::Serialize(const void *address, Stream *out) {
const ScriptDialog *shh = static_cast<const ScriptDialog *>(address);
out->WriteInt32(shh->id);
}
void CCDialog::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_GP(scrDialog)[num], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DIALOG_H
#define AGS_ENGINE_AC_DYNOBJ_CC_DIALOG_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCDialog final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,114 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/ac/dynobj/script_string.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
const char *CCDynamicArray::TypeName = "CCDynamicArray";
// return the type name of the object
const char *CCDynamicArray::GetType() {
return TypeName;
}
int CCDynamicArray::Dispose(void *address, bool force) {
// If it's an array of managed objects, release their ref counts;
// except if this array is forcefully removed from the managed pool,
// in which case just ignore these.
if (!force) {
const Header &hdr = GetHeader(address);
bool is_managed = (hdr.ElemCount & ARRAY_MANAGED_TYPE_FLAG) != 0;
const uint32_t el_count = hdr.ElemCount & (~ARRAY_MANAGED_TYPE_FLAG);
if (is_managed) { // Dynamic array of managed pointers: subref them directly
const uint32_t *handles = reinterpret_cast<const uint32_t *>(address);
for (uint32_t i = 0; i < el_count; ++i) {
if (handles[i] > 0)
ccReleaseObjectReference(handles[i]);
}
}
}
delete[] (static_cast<uint8_t *>(address) - MemHeaderSz);
return 1;
}
size_t CCDynamicArray::CalcSerializeSize(const void *address) {
const Header &hdr = GetHeader(address);
return hdr.TotalSize + FileHeaderSz;
}
void CCDynamicArray::Serialize(const void *address, Stream *out) {
const Header &hdr = GetHeader(address);
out->WriteInt32(hdr.ElemCount);
out->WriteInt32(hdr.TotalSize);
out->Write(address, hdr.TotalSize); // elements
}
void CCDynamicArray::Unserialize(int index, Stream *in, size_t data_sz) {
uint8_t *new_arr = new uint8_t[(data_sz - FileHeaderSz) + MemHeaderSz];
Header &hdr = reinterpret_cast<Header &>(*new_arr);
hdr.ElemCount = in->ReadInt32();
hdr.TotalSize = in->ReadInt32();
in->Read(new_arr + MemHeaderSz, data_sz - FileHeaderSz);
ccRegisterUnserializedObject(index, &new_arr[MemHeaderSz], this);
}
/* static */ DynObjectRef CCDynamicArray::Create(int numElements, int elementSize, bool isManagedType) {
uint8_t *new_arr = new uint8_t[numElements * elementSize + MemHeaderSz];
memset(new_arr, 0, numElements * elementSize + MemHeaderSz);
Header &hdr = reinterpret_cast<Header &>(*new_arr);
hdr.ElemCount = numElements | (ARRAY_MANAGED_TYPE_FLAG * isManagedType);
hdr.TotalSize = elementSize * numElements;
void *obj_ptr = &new_arr[MemHeaderSz];
int32_t handle = ccRegisterManagedObject(obj_ptr, &_GP(globalDynamicArray));
if (handle == 0) {
delete[] new_arr;
return DynObjectRef();
}
return DynObjectRef(handle, obj_ptr, &_GP(globalDynamicArray));
}
DynObjectRef DynamicArrayHelpers::CreateStringArray(const std::vector<const char *> items) {
// NOTE: we need element size of "handle" for array of managed pointers
DynObjectRef arr = _GP(globalDynamicArray).Create(items.size(), sizeof(int32_t), true);
if (!arr.Obj)
return arr;
// Create script strings and put handles into array
int32_t *slots = static_cast<int32_t *>(arr.Obj);
for (auto s : items) {
DynObjectRef str = ScriptString::Create(s);
// We must add reference count, because the string is going to be saved
// within another object (array), not returned to script directly
ccAddObjectReference(str.Handle);
*(slots++) = str.Handle;
}
return arr;
}
} // namespace AGS3

View File

@@ -0,0 +1,80 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_DYNAMICARRAY_H
#define AGS_ENGINE_AC_DYNOBJ_CC_DYNAMICARRAY_H
#include "common/std/vector.h"
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
#define ARRAY_MANAGED_TYPE_FLAG 0x80000000
struct CCDynamicArray final : AGSCCDynamicObject {
public:
static const char *TypeName;
struct Header {
// May contain ARRAY_MANAGED_TYPE_FLAG
uint32_t ElemCount = 0u;
// TODO: refactor and store "elem size" instead
uint32_t TotalSize = 0u;
};
CCDynamicArray() = default;
~CCDynamicArray() = default;
inline static const Header &GetHeader(const void *address) {
return reinterpret_cast<const Header &>(*(static_cast<const uint8_t *>(address) - MemHeaderSz));
}
// Create managed array object and return a pointer to the beginning of a buffer
static DynObjectRef Create(int numElements, int elementSize, bool isManagedType);
// return the type name of the object
const char *GetType() override;
int Dispose(void *address, bool force) override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
private:
// The size of the array's header in memory, prepended to the element data
static const size_t MemHeaderSz = sizeof(Header);
// The size of the serialized header
static const size_t FileHeaderSz = sizeof(uint32_t) * 2;
// Savegame serialization
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
// Helper functions for setting up dynamic arrays.
namespace DynamicArrayHelpers {
// Create array of managed strings
DynObjectRef CreateStringArray(const std::vector<const char *>);
} // namespace DynamicArrayHelpers
} // namespace AGS3
#endif

View File

@@ -0,0 +1,53 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_gui.h"
#include "ags/engine/ac/dynobj/script_gui.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCGUI::GetType() {
return "GUI";
}
size_t CCGUI::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCGUI::Serialize(const void *address, Stream *out) {
const ScriptGUI *shh = static_cast<const ScriptGUI *>(address);
out->WriteInt32(shh->id);
}
void CCGUI::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_GP(scrGui)[num], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CCGUI_H
#define AGS_ENGINE_AC_DYNOBJ_CCGUI_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCGUI final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,57 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_gui_object.h"
#include "ags/engine/ac/dynobj/script_gui.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/gui/gui_main.h"
#include "ags/shared/gui/gui_object.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCGUIObject::GetType() {
return "GUIObject";
}
size_t CCGUIObject::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t) * 2;
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCGUIObject::Serialize(const void *address, Stream *out) {
const GUIObject *guio = static_cast<const GUIObject *>(address);
out->WriteInt32(guio->ParentId);
out->WriteInt32(guio->Id);
}
void CCGUIObject::Unserialize(int index, Stream *in, size_t data_sz) {
int guinum = in->ReadInt32();
int objnum = in->ReadInt32();
ccRegisterUnserializedObject(index, _GP(guis)[guinum].GetControl(objnum), this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_GUI_OBJECT_H
#define AGS_ENGINE_AC_DYNOBJ_CC_GUI_OBJECT_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCGUIObject final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_hotspot.h"
#include "ags/engine/ac/dynobj/script_hotspot.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/common_defines.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCHotspot::GetType() {
return "Hotspot";
}
size_t CCHotspot::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCHotspot::Serialize(const void *address, Stream *out) {
const ScriptHotspot *shh = static_cast<const ScriptHotspot *>(address);
out->WriteInt32(shh->id);
}
void CCHotspot::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_G(scrHotspot)[num], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_HOTSPOT_H
#define AGS_ENGINE_AC_DYNOBJ_CC_HOTSPOT_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCHotspot final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,54 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_inventory.h"
#include "ags/engine/ac/dynobj/script_inv_item.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/character_info.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCInventory::GetType() {
return "Inventory";
}
size_t CCInventory::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCInventory::Serialize(const void *address, Stream *out) {
const ScriptInvItem *shh = static_cast<const ScriptInvItem *>(address);
out->WriteInt32(shh->id);
}
void CCInventory::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_G(scrInv)[num], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CCINVENTORY_H
#define AGS_ENGINE_AC_DYNOBJ_CCINVENTORY_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCInventory final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_object.h"
#include "ags/engine/ac/dynobj/script_object.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/common_defines.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCObject::GetType() {
return "Object";
}
size_t CCObject::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCObject::Serialize(const void *address, Stream *out) {
const ScriptObject *shh = static_cast<const ScriptObject *>(address);
out->WriteInt32(shh->id);
}
void CCObject::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_G(scrObj)[num], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CCOBJECT_H
#define AGS_ENGINE_AC_DYNOBJ_CCOBJECT_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCObject final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_region.h"
#include "ags/engine/ac/dynobj/script_region.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/common_defines.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *CCRegion::GetType() {
return "Region";
}
size_t CCRegion::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void CCRegion::Serialize(const void *address, Stream *out) {
const ScriptRegion *shh = static_cast<const ScriptRegion *>(address);
out->WriteInt32(shh->id);
}
void CCRegion::Unserialize(int index, Stream *in, size_t data_sz) {
int num = in->ReadInt32();
ccRegisterUnserializedObject(index, &_G(scrRegion)[num], this);
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CCREGION_H
#define AGS_ENGINE_AC_DYNOBJ_CCREGION_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCRegion final : AGSCCDynamicObject {
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,128 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// IScriptObject: script managed object interface.
// Provides interaction with a object which allocation and lifetime is
// managed by the engine and/or the managed pool rather than the script VM.
// These may be both static objects existing throughout the game, and
// dynamic objects allocated by the script command.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_SCRIPT_OBJECT_H
#define AGS_ENGINE_AC_DYNOBJ_CC_SCRIPT_OBJECT_H
#include "common/std/utility.h"
#include "ags/shared/core/types.h"
namespace AGS3 {
// Forward declaration
namespace AGS {
namespace Shared {
class Stream;
} // namespace Shared
} // namespace AGS
struct IScriptObject;
// A convenience struct for grouping handle and dynamic object
struct DynObjectRef {
const int Handle = 0;
void *const Obj = nullptr;
IScriptObject *const Mgr = nullptr;
DynObjectRef() = default;
DynObjectRef(int handle, void *obj, IScriptObject *mgr)
: Handle(handle), Obj(obj), Mgr(mgr) {}
};
struct IScriptObject {
// WARNING: The first section of this interface is also a part of the AGS plugin API!
// when a ref count reaches 0, this is called with the address
// of the object. Return 1 to remove the object from memory, 0 to
// leave it
// The "force" flag tells system to detach the object, breaking any links and references
// to other managed objects or game resources (instead of disposing these too).
// TODO: it might be better to rewrite the managed pool and remove this flag at all,
// because it makes the use of this interface prone to mistakes.
virtual int Dispose(void *address, bool force = false) = 0;
// return the type name of the object
virtual const char *GetType() = 0;
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
// TODO: pass savegame format version
virtual int Serialize(void *address, uint8_t *buffer, int bufsize) = 0;
// WARNING: following section is not a part of plugin API, therefore these methods
// should **never** be called for kScValPluginObject script objects!
// Legacy support for reading and writing object values by their relative offset.
// These methods allow to "remap" script struct field access, by taking the
// legacy offset, and using it rather as a field ID than an address, for example.
// Consequently these also let trigger side-effects, such as updating an object
// after a field value is written to.
// RE: GetFieldPtr() -
// According to AGS script specification, when the old-string pointer or char array is passed
// as an argument, the byte-code does not include any specific command for the member variable
// retrieval and instructs to pass an address of the object itself with certain offset.
// This results in functions like StrCopy writing directly over object address.
// There may be other implementations, but the big question is: how to detect when this is
// necessary, because byte-code does not contain any distinct operation for this case.
// The worst thing here is that with the current byte-code structure we can never tell whether
// offset 0 means getting pointer to whole object or a pointer to its first field.
virtual void *GetFieldPtr(void *address, intptr_t offset) = 0;
virtual void Read(void *address, intptr_t offset, uint8_t *dest, size_t size) = 0;
virtual uint8_t ReadInt8(void *address, intptr_t offset) = 0;
virtual int16_t ReadInt16(void *address, intptr_t offset) = 0;
virtual int32_t ReadInt32(void *address, intptr_t offset) = 0;
virtual float ReadFloat(void *address, intptr_t offset) = 0;
virtual void Write(void *address, intptr_t offset, const uint8_t *src, size_t size) = 0;
virtual void WriteInt8(void *address, intptr_t offset, uint8_t val) = 0;
virtual void WriteInt16(void *address, intptr_t offset, int16_t val) = 0;
virtual void WriteInt32(void *address, intptr_t offset, int32_t val) = 0;
virtual void WriteFloat(void *address, intptr_t offset, float val) = 0;
protected:
IScriptObject() {}
virtual ~IScriptObject() {}
};
// The interface of a script objects deserializer that handles multiple types.
struct ICCObjectCollectionReader {
virtual ~ICCObjectCollectionReader() {}
// TODO: pass savegame format version
virtual void Unserialize(int32_t handle, const char *objectType, const char *serializedData, int dataSize) = 0;
};
// The interface of a script objects deserializer that handles a single type.
// WARNING: a part of the plugin API.
struct ICCObjectReader {
virtual ~ICCObjectReader() {}
virtual void Unserialize(int32_t handle, const char *serializedData, int dataSize) = 0;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,140 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/shared/util/memory_stream.h"
#include "ags/engine/ac/dynobj/cc_serializer.h"
#include "ags/engine/ac/dynobj/all_dynamic_classes.h"
#include "ags/engine/ac/dynobj/all_script_classes.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/ac/dynobj/cc_dynamic_array.h"
#include "ags/engine/ac/dynobj/script_user_object.h"
#include "ags/engine/ac/dynobj/script_camera.h"
#include "ags/engine/ac/dynobj/script_containers.h"
#include "ags/engine/ac/dynobj/script_file.h"
#include "ags/engine/ac/dynobj/script_viewport.h"
#include "ags/engine/ac/game.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/plugins/plugin_engine.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// *** De-serialization of script objects
void AGSDeSerializer::Unserialize(int32_t index, const char *objectType, const char *serializedData, int dataSize) {
if (dataSize < 0) {
quitprintf("Unserialise: invalid data size (%d) for object type '%s'", dataSize, objectType);
return; // TODO: don't quit, return error
}
// Note that while our builtin classes may accept Stream object,
// classes registered by plugin cannot, because streams are not (yet)
// part of the plugin API.
size_t data_sz = static_cast<size_t>(dataSize);
assert(data_sz <= INT32_MAX); // dynamic object API does not support size > int32
MemoryStream mems(reinterpret_cast<const uint8_t *>(serializedData), dataSize);
// TODO: consider this: there are object types that are part of the
// script's foundation, because they are created by the bytecode ops:
// such as DynamicArray and UserObject. *Maybe* these should be moved
// to certain "base serializer" class which guarantees their restoration.
//
// TODO: should we support older save versions here (DynArray, UserObj)?
// might have to use older class names to distinguish save formats
if (strcmp(objectType, CCDynamicArray::TypeName) == 0) {
_GP(globalDynamicArray).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, ScriptUserObject::TypeName) == 0) {
ScriptUserObject *suo = new ScriptUserObject();
suo->Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "GUIObject") == 0) {
_GP(ccDynamicGUIObject).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Character") == 0) {
_GP(ccDynamicCharacter).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Hotspot") == 0) {
_GP(ccDynamicHotspot).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Region") == 0) {
_GP(ccDynamicRegion).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Inventory") == 0) {
_GP(ccDynamicInv).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Dialog") == 0) {
_GP(ccDynamicDialog).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "GUI") == 0) {
_GP(ccDynamicGUI).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Object") == 0) {
_GP(ccDynamicObject).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "String") == 0) {
_GP(myScriptStringImpl).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "File") == 0) {
// files cannot be restored properly -- so just recreate
// the object; attempting any operations on it will fail
sc_File *scf = new sc_File();
ccRegisterUnserializedObject(index, scf, scf);
} else if (strcmp(objectType, "Overlay") == 0) {
ScriptOverlay *scf = new ScriptOverlay();
scf->Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "DateTime") == 0) {
ScriptDateTime *scf = new ScriptDateTime();
scf->Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "ViewFrame") == 0) {
ScriptViewFrame *scf = new ScriptViewFrame();
scf->Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "DynamicSprite") == 0) {
ScriptDynamicSprite *scf = new ScriptDynamicSprite();
scf->Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "DrawingSurface") == 0) {
ScriptDrawingSurface *sds = new ScriptDrawingSurface();
sds->Unserialize(index, &mems, data_sz);
if (sds->isLinkedBitmapOnly) {
_G(dialogOptionsRenderingSurface) = sds;
}
} else if (strcmp(objectType, "DialogOptionsRendering") == 0) {
_GP(ccDialogOptionsRendering).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "StringDictionary") == 0) {
Dict_Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "StringSet") == 0) {
Set_Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Viewport2") == 0) {
Viewport_Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "Camera2") == 0) {
Camera_Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "AudioChannel") == 0) {
_GP(ccDynamicAudio).Unserialize(index, &mems, data_sz);
} else if (strcmp(objectType, "AudioClip") == 0) {
_GP(ccDynamicAudioClip).Unserialize(index, &mems, data_sz);
} else {
// check if the type is read by a plugin
for (const auto &pr : _GP(pluginReaders)) {
if (pr.Type == objectType) {
if (dataSize == 0) { // avoid unserializing stubbed plugins
debug(0, "Skipping %s plugin unserialization (dataSize = 0)", objectType);
return;
}
pr.Reader->Unserialize(index, serializedData, dataSize);
return;
}
}
quitprintf("Unserialise: unknown object type: '%s'", objectType);
}
}
} // namespace AGS3

View File

@@ -0,0 +1,35 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SERIALIZER_H
#define AGS_ENGINE_AC_DYNOBJ_SERIALIZER_H
#include "ags/engine/ac/dynobj/cc_script_object.h"
namespace AGS3 {
struct AGSDeSerializer : ICCObjectCollectionReader {
void Unserialize(int32_t index, const char *objectType, const char *serializedData, int dataSize) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,88 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/cc_static_array.h"
#include "ags/engine/ac/dynobj/cc_script_object.h"
namespace AGS3 {
void CCStaticArray::Create(IScriptObject *mgr, size_t elem_script_size, size_t elem_mem_size, size_t elem_count) {
_mgr = mgr;
_elemScriptSize = elem_script_size;
_elemMemSize = elem_mem_size;
_elemCount = elem_count;
}
void *CCStaticArray::GetFieldPtr(void *address, intptr_t offset) {
return GetElementPtr(address, offset);
}
void CCStaticArray::Read(void *address, intptr_t offset, uint8_t *dest, size_t size) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->Read(el_ptr, offset % _elemScriptSize, dest, size);
}
uint8_t CCStaticArray::ReadInt8(void *address, intptr_t offset) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->ReadInt8(el_ptr, offset % _elemScriptSize);
}
int16_t CCStaticArray::ReadInt16(void *address, intptr_t offset) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->ReadInt16(el_ptr, offset % _elemScriptSize);
}
int32_t CCStaticArray::ReadInt32(void *address, intptr_t offset) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->ReadInt32(el_ptr, offset % _elemScriptSize);
}
float CCStaticArray::ReadFloat(void *address, intptr_t offset) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->ReadFloat(el_ptr, offset % _elemScriptSize);
}
void CCStaticArray::Write(void *address, intptr_t offset, const uint8_t *src, size_t size) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->Write(el_ptr, offset % _elemScriptSize, src, size);
}
void CCStaticArray::WriteInt8(void *address, intptr_t offset, uint8_t val) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->WriteInt8(el_ptr, offset % _elemScriptSize, val);
}
void CCStaticArray::WriteInt16(void *address, intptr_t offset, int16_t val) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->WriteInt16(el_ptr, offset % _elemScriptSize, val);
}
void CCStaticArray::WriteInt32(void *address, intptr_t offset, int32_t val) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->WriteInt32(el_ptr, offset % _elemScriptSize, val);
}
void CCStaticArray::WriteFloat(void *address, intptr_t offset, float val) {
void *el_ptr = GetElementPtr(address, offset);
return _mgr->WriteFloat(el_ptr, offset % _elemScriptSize, val);
}
} // namespace AGS3

View File

@@ -0,0 +1,96 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// CCStaticArray manages access to an array of script objects,
// where an element's size counted by script's bytecode may differ from the
// real element size in the engine's memory.
// The purpose of this is to remove size restriction from the engine's structs
// exposed to scripts.
//
// FIXME: [ivan-mogilko] the above was meant to work, but in reality it doesn't
// and won't, at least not without some extra workarounds.
// The problem that I missed here is following:
// when the script compiler is told to get an Nth element of a global struct
// array, such as character[n], it calculates the memory address as
// array address + sizeof(Character) * n.
// If this address is used for the read/write operations, these ops can be
// intercepted by interpreter and remapped into the real fields
// (see IScriptObject::ReadN, WriteN interface)
// But if this address is used IN POINTER COMPARISON, then we cannot do
// anything. And if our real struct in the engine is stored on a different
// relative memory offset than one expected by compiler, then this pointer
// comparison will fail, e.g. script expression like
// if (player == character[n])
//
// NOTE: on the other hand, similar effect could be achieved by separating
// object data into two or more structs, where "base" structs are stored in
// the exposed arrays (part of API), while extending structs are stored
// separately. This is more an issue of engine data design.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_STATIC_ARRAY_H
#define AGS_ENGINE_AC_DYNOBJ_STATIC_ARRAY_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCStaticArray : public AGSCCStaticObject {
public:
~CCStaticArray() override {}
void Create(IScriptObject *mgr, size_t elem_script_size, size_t elem_mem_size, size_t elem_count = SIZE_MAX /*unknown*/);
inline IScriptObject *GetObjectManager() const {
return _mgr;
}
// Legacy support for reading and writing object values by their relative offset
inline void *GetElementPtr(void *address, intptr_t legacy_offset) {
return static_cast<uint8_t *>(address) + (legacy_offset / _elemScriptSize) * _elemMemSize;
}
void *GetFieldPtr(void *address, intptr_t offset) override;
void Read(void *address, intptr_t offset, uint8_t *dest, size_t size) override;
uint8_t ReadInt8(void *address, intptr_t offset) override;
int16_t ReadInt16(void *address, intptr_t offset) override;
int32_t ReadInt32(void *address, intptr_t offset) override;
float ReadFloat(void *address, intptr_t offset) override;
void Write(void *address, intptr_t offset, const uint8_t *src, size_t size) override;
void WriteInt8(void *address, intptr_t offset, uint8_t val) override;
void WriteInt16(void *address, intptr_t offset, int16_t val) override;
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
void WriteFloat(void *address, intptr_t offset, float val) override;
private:
IScriptObject *_mgr = nullptr;
size_t _elemScriptSize = 0u;
size_t _elemMemSize = 0u;
size_t _elemCount = 0u;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,154 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// C-Script run-time interpreter (c) 2001 Chris Jones
//
// You must DISABLE OPTIMIZATIONS AND REGISTER VARIABLES in your compiler
// when compiling this, or strange results can happen.
//
// There is a problem with importing functions on 16-bit compilers: the
// script system assumes that all parameters are passed as 4 bytes, which
// ints are not on 16-bit systems. Be sure to define all parameters as longs,
// or join the 21st century and switch to DJGPP or Visual C++.
//
//=============================================================================
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/core/platform.h"
#include "ags/engine/ac/dynobj/managed_object_pool.h"
#include "ags/shared/debugging/out.h"
#include "ags/shared/script/cc_common.h"
#include "ags/shared/script/cc_internal.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
// register a memory handle for the object and allow script
// pointers to point to it
int32_t ccRegisterManagedObject(void *object, IScriptObject *callback, ScriptValueType obj_type) {
int32_t handl = _GP(pool).AddObject(object, callback, obj_type);
ManagedObjectLog("Register managed object type '%s' handle=%d addr=%08X",
((callback == NULL) ? "(unknown)" : callback->GetType()), handl, object);
return handl;
}
// register a de-serialized object
int32_t ccRegisterUnserializedObject(int index, void *object, IScriptObject *callback, ScriptValueType obj_type) {
return _GP(pool).AddUnserializedObject(object, callback, obj_type, index);
}
// unregister a particular object
int ccUnRegisterManagedObject(void *object) {
return _GP(pool).RemoveObject(object);
}
// remove all registered objects
void ccUnregisterAllObjects() {
_GP(pool).reset();
}
// serialize all objects to disk
void ccSerializeAllObjects(Stream *out) {
_GP(pool).WriteToDisk(out);
}
// un-serialise all objects (will remove all currently registered ones)
int ccUnserializeAllObjects(Stream *in, ICCObjectCollectionReader *callback) {
return _GP(pool).ReadFromDisk(in, callback);
}
// dispose the object if RefCount==0
void ccAttemptDisposeObject(int32_t handle) {
_GP(pool).CheckDispose(handle);
}
// translate between object handles and memory addresses
int32_t ccGetObjectHandleFromAddress(void *address) {
// set to null
if (address == nullptr)
return 0;
int32_t handl = _GP(pool).AddressToHandle(address);
ManagedObjectLog("Line %d WritePtr: %08X to %d", _G(currentline), address, handl);
if (handl == 0) {
cc_error("Pointer cast failure: the object being pointed to is not in the managed object pool");
return -1;
}
return handl;
}
void *ccGetObjectAddressFromHandle(int32_t handle) {
if (handle == 0) {
return nullptr;
}
void *addr = _GP(pool).HandleToAddress(handle);
ManagedObjectLog("Line %d ReadPtr: %d to %08X", _G(currentline), handle, addr);
if (addr == nullptr) {
cc_error("Error retrieving pointer: invalid handle %d", handle);
return nullptr;
}
return addr;
}
ScriptValueType ccGetObjectAddressAndManagerFromHandle(int32_t handle, void *&object, IScriptObject *&manager) {
if (handle == 0) {
object = nullptr;
manager = nullptr;
return kScValUndefined;
}
ScriptValueType obj_type = _GP(pool).HandleToAddressAndManager(handle, object, manager);
if (obj_type == kScValUndefined) {
cc_error("Error retrieving pointer: invalid handle %d", handle);
}
return obj_type;
}
int ccAddObjectReference(int32_t handle) {
if (handle == 0)
return 0;
return _GP(pool).AddRef(handle);
}
int ccReleaseObjectReference(int32_t handle) {
if (handle == 0)
return 0;
if (_GP(pool).HandleToAddress(handle) == nullptr) {
cc_error("Error releasing pointer: invalid handle %d", handle);
return -1;
}
return _GP(pool).SubRef(handle);
}
} // namespace AGS3

View File

@@ -0,0 +1,73 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Dynamic object management utilities.
// TODO: frankly, many of these functions could be factored out by a direct
// use of ManagedPool class.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_MANAGER_H
#define AGS_ENGINE_AC_DYNOBJ_MANAGER_H
#include "ags/shared/core/types.h"
#include "ags/engine/script/runtime_script_value.h"
#include "ags/engine/ac/dynobj/cc_script_object.h"
namespace AGS3 {
// Forward declaration
namespace AGS {
namespace Shared {
class Stream;
} // namespace Shared
} // namespace AGS
using namespace AGS; // FIXME later
// register a memory handle for the object and allow script
// pointers to point to it
extern int32_t ccRegisterManagedObject(void *object, IScriptObject *, ScriptValueType obj_type = kScValScriptObject);
// register a de-serialized object
extern int32_t ccRegisterUnserializedObject(int index, void *object, IScriptObject *, ScriptValueType obj_type = kScValScriptObject);
// unregister a particular object
extern int ccUnRegisterManagedObject(void *object);
// remove all registered objects
extern void ccUnregisterAllObjects();
// serialize all objects to disk
extern void ccSerializeAllObjects(Shared::Stream *out);
// un-serialise all objects (will remove all currently registered ones)
extern int ccUnserializeAllObjects(Shared::Stream *in, ICCObjectCollectionReader *callback);
// dispose the object if RefCount==0
extern void ccAttemptDisposeObject(int32_t handle);
// translate between object handles and memory addresses
extern int32_t ccGetObjectHandleFromAddress(void *address);
extern void *ccGetObjectAddressFromHandle(int32_t handle);
extern ScriptValueType ccGetObjectAddressAndManagerFromHandle(int32_t handle, void *&object, IScriptObject *&manager);
extern int ccAddObjectReference(int32_t handle);
extern int ccReleaseObjectReference(int32_t handle);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,347 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/std/vector.h"
#include "ags/engine/ac/dynobj/managed_object_pool.h"
#include "ags/shared/debugging/out.h"
#include "ags/shared/util/string_utils.h" // fputstring, etc
#include "ags/shared/script/cc_common.h"
#include "ags/shared/script/cc_internal.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
const auto OBJECT_CACHE_MAGIC_NUMBER = 0xa30b;
const auto SERIALIZE_BUFFER_SIZE = 10240;
const auto GARBAGE_COLLECTION_INTERVAL = 1024;
const auto RESERVED_SIZE = 2048;
int ManagedObjectPool::Remove(ManagedObject &o, bool force) {
const bool can_remove = o.callback->Dispose(o.addr, force) != 0;
if (!(can_remove || force))
return 0;
available_ids.push(o.handle);
handleByAddress.erase(o.addr);
ManagedObjectLog("Line %d Disposed managed object handle=%d", currentline, o.handle);
o = ManagedObject();
return 1;
}
int32_t ManagedObjectPool::AddRef(int32_t handle) {
if (handle < 1 || (size_t)handle >= objects.size())
return 0;
auto &o = objects[handle];
if (!o.isUsed())
return 0;
o.refCount++;
ManagedObjectLog("Line %d AddRef: handle=%d new refcount=%d", _G(currentline), o.handle, o.refCount);
return o.refCount;
}
int ManagedObjectPool::CheckDispose(int32_t handle) {
if (handle < 1 || (size_t)handle >= objects.size())
return 1;
auto &o = objects[handle];
if (!o.isUsed()) {
return 1;
}
if (o.refCount >= 1) {
return 0;
}
return Remove(o);
}
int32_t ManagedObjectPool::SubRef(int32_t handle) {
if (handle < 1 || (size_t)handle >= objects.size()) {
return 0;
}
auto &o = objects[handle];
if (!o.isUsed()) {
return 0;
}
o.refCount--;
const auto newRefCount = o.refCount;
const auto canBeDisposed = (o.addr != disableDisposeForObject);
if (canBeDisposed && o.refCount <= 0) {
Remove(o);
}
// object could be removed at this point, don't use any values.
ManagedObjectLog("Line %d SubRef: handle=%d new refcount=%d canBeDisposed=%d", _G(currentline), handle, newRefCount, canBeDisposed);
return newRefCount;
}
int32_t ManagedObjectPool::AddressToHandle(void *addr) {
if (addr == nullptr) {
return 0;
}
auto it = handleByAddress.find(addr);
if (it == handleByAddress.end()) {
return 0;
}
return it->_value;
}
// this function is called often (whenever a pointer is used)
void *ManagedObjectPool::HandleToAddress(int32_t handle) {
if (handle < 1 || (size_t)handle >= objects.size()) {
return nullptr;
}
auto &o = objects[handle];
if (!o.isUsed()) {
return nullptr;
}
return o.addr;
}
// this function is called often (whenever a pointer is used)
ScriptValueType ManagedObjectPool::HandleToAddressAndManager(int32_t handle, void *&object, IScriptObject *&manager) {
if ((handle < 1 || (size_t)handle >= objects.size()) || !objects[handle].isUsed()) {
object = nullptr;
manager = nullptr;
return kScValUndefined;
}
auto &o = objects[handle];
object = (void *)(o.addr); // WARNING: This strips the const from the char* pointer.
manager = o.callback;
return o.obj_type;
}
int ManagedObjectPool::RemoveObject(void *address) {
if (address == nullptr) {
return 0;
}
auto it = handleByAddress.find(address);
if (it == handleByAddress.end()) {
return 0;
}
auto &o = objects[it->_value];
return Remove(o, true);
}
void ManagedObjectPool::RunGarbageCollectionIfAppropriate() {
if (objectCreationCounter <= GARBAGE_COLLECTION_INTERVAL) {
return;
}
RunGarbageCollection();
objectCreationCounter = 0;
}
void ManagedObjectPool::RunGarbageCollection() {
for (int i = 1; i < nextHandle; i++) {
auto &o = objects[i];
if (!o.isUsed()) {
continue;
}
if (o.refCount < 1) {
Remove(o);
}
}
ManagedObjectLog("Ran garbage collection");
}
int ManagedObjectPool::Add(int handle, void *address, IScriptObject *callback, ScriptValueType obj_type)
{
auto &o = objects[handle];
assert(!o.isUsed());
o = ManagedObject(obj_type, handle, address, callback);
handleByAddress.insert({address, handle});
ManagedObjectLog("Allocated managed object type=%s, handle=%d, addr=%08X", callback->GetType(), handle, address);
return handle;
}
int ManagedObjectPool::AddObject(void *address, IScriptObject *callback, ScriptValueType obj_type) {
int32_t handle;
if (!available_ids.empty()) {
handle = available_ids.front();
available_ids.pop();
} else {
handle = nextHandle++;
if ((size_t)handle >= objects.size()) {
objects.resize(handle + 1024, ManagedObject());
}
}
objectCreationCounter++;
return Add(handle, address, callback, obj_type);
}
int ManagedObjectPool::AddUnserializedObject(void *address, IScriptObject *callback, ScriptValueType obj_type, int handle) {
if (handle < 1) {
cc_error("Attempt to assign invalid handle: %d", handle);
return 0;
}
if ((size_t)handle >= objects.size()) {
objects.resize(handle + 1024, ManagedObject());
}
return Add(handle, address, callback, obj_type);
}
void ManagedObjectPool::WriteToDisk(Stream *out) {
// use this opportunity to clean up any non-referenced pointers
RunGarbageCollection();
std::vector<uint8_t> serializeBuffer;
serializeBuffer.resize(SERIALIZE_BUFFER_SIZE);
out->WriteInt32(OBJECT_CACHE_MAGIC_NUMBER);
out->WriteInt32(2); // version
int size = 0;
for (int i = 1; i < nextHandle; i++) {
auto const &o = objects[i];
if (o.isUsed()) {
size += 1;
}
}
out->WriteInt32(size);
for (int i = 1; i < nextHandle; i++) {
auto const &o = objects[i];
if (!o.isUsed()) {
continue;
}
// handle
out->WriteInt32(o.handle);
// write the type of the object
StrUtil::WriteCStr(o.callback->GetType(), out);
// now write the object data
int bytesWritten = o.callback->Serialize(o.addr, &serializeBuffer.front(), serializeBuffer.size());
if ((bytesWritten < 0) && ((size_t)(-bytesWritten) > serializeBuffer.size())) {
// buffer not big enough, re-allocate with requested size
serializeBuffer.resize(-bytesWritten);
bytesWritten = o.callback->Serialize(o.addr, &serializeBuffer.front(), serializeBuffer.size());
}
assert(bytesWritten >= 0);
out->WriteInt32(bytesWritten);
out->Write(&serializeBuffer.front(), bytesWritten);
out->WriteInt32(o.refCount);
ManagedObjectLog("Wrote handle = %d", o.handle);
}
}
int ManagedObjectPool::ReadFromDisk(Stream *in, ICCObjectCollectionReader *reader) {
if (in->ReadInt32() != OBJECT_CACHE_MAGIC_NUMBER) {
cc_error("Data was not written by ccSeralize");
return -1;
}
char typeNameBuffer[200];
std::vector<char> serializeBuffer;
serializeBuffer.resize(SERIALIZE_BUFFER_SIZE);
auto version = in->ReadInt32();
switch (version) {
case 1: {
// IMPORTANT: numObjs is "nextHandleId", which is why we iterate from 1 to numObjs-1
int numObjs = in->ReadInt32();
for (int i = 1; i < numObjs; i++) {
StrUtil::ReadCStr(typeNameBuffer, in, sizeof(typeNameBuffer));
if (typeNameBuffer[0] != 0) {
size_t numBytes = in->ReadInt32();
if (numBytes > serializeBuffer.size()) {
serializeBuffer.resize(numBytes);
}
in->Read(&serializeBuffer.front(), numBytes);
// Delegate work to ICCObjectReader
reader->Unserialize(i, typeNameBuffer, &serializeBuffer.front(), numBytes);
objects[i].refCount = in->ReadInt32();
ManagedObjectLog("Read handle = %d", objects[i].handle);
}
}
}
break;
case 2: {
// This is actually number of objects written.
int objectsSize = in->ReadInt32();
for (int i = 0; i < objectsSize; i++) {
auto handle = in->ReadInt32();
assert(handle >= 1);
StrUtil::ReadCStr(typeNameBuffer, in, sizeof(typeNameBuffer));
assert(typeNameBuffer[0] != 0);
size_t numBytes = in->ReadInt32();
if (numBytes > serializeBuffer.size()) {
serializeBuffer.resize(numBytes);
}
in->Read(&serializeBuffer.front(), numBytes);
// Delegate work to ICCObjectReader
reader->Unserialize(handle, typeNameBuffer, &serializeBuffer.front(), numBytes);
objects[handle].refCount = in->ReadInt32();
ManagedObjectLog("Read handle = %d", objects[i].handle);
}
}
break;
default:
cc_error("Invalid data version: %d", version);
return -1;
}
// re-adjust next handles. (in case saved in random order)
available_ids = std::queue<int32_t>();
nextHandle = 1;
for (const auto &o : objects) {
if (o.isUsed()) {
nextHandle = o.handle + 1;
}
}
for (int i = 1; i < nextHandle; i++) {
if (!objects[i].isUsed()) {
available_ids.push(i);
}
}
return 0;
}
// de-allocate all objects
void ManagedObjectPool::reset() {
for (int i = 1; i < nextHandle; i++) {
auto &o = objects[i];
if (!o.isUsed()) {
continue;
}
Remove(o, true);
}
available_ids = std::queue<int32_t>();
nextHandle = 1;
}
ManagedObjectPool::ManagedObjectPool() : objectCreationCounter(0), nextHandle(1), available_ids(), objects(RESERVED_SIZE, ManagedObject()), handleByAddress() {
handleByAddress.reserve(RESERVED_SIZE);
}
} // namespace AGS3

View File

@@ -0,0 +1,113 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_CC_MANAGED_OBJECT_POOL_H
#define AGS_ENGINE_AC_DYNOBJ_CC_MANAGED_OBJECT_POOL_H
#include "common/std/vector.h"
#include "common/std/queue.h"
#include "common/std/map.h"
#include "ags/shared/core/platform.h"
#include "ags/engine/script/runtime_script_value.h"
#include "ags/engine/ac/dynobj/cc_script_object.h" // IScriptObject
namespace AGS3 {
namespace AGS {
namespace Shared {
class Stream;
} // namespace Shared
} // namespace AGS
using namespace AGS; // FIXME later
struct Pointer_Hash {
uint operator()(void *v) const {
return static_cast<uint>(reinterpret_cast<uintptr>(v));
}
};
struct ManagedObjectPool final {
private:
// TODO: find out if we can make handle size_t
struct ManagedObject {
ScriptValueType obj_type;
int32_t handle;
void *addr;
IScriptObject *callback;
int refCount;
bool isUsed() const {
return obj_type != kScValUndefined;
}
ManagedObject() : obj_type(kScValUndefined), handle(0), addr(nullptr),
callback(nullptr), refCount(0) {}
ManagedObject(ScriptValueType theType, int32_t theHandle,
void *theAddr, IScriptObject *theCallback)
: obj_type(theType), handle(theHandle), addr(theAddr),
callback(theCallback), refCount(0) {
}
};
int objectCreationCounter; // used to do garbage collection every so often
int32_t nextHandle{}; // TODO: manage nextHandle's going over INT32_MAX !
std::queue<int32_t> available_ids;
std::vector<ManagedObject> objects;
std::unordered_map<void *, int32_t, Pointer_Hash> handleByAddress;
int Add(int handle, void *address, IScriptObject *callback, ScriptValueType obj_type);
int Remove(ManagedObject &o, bool force = false);
void RunGarbageCollection();
public:
int32_t AddRef(int32_t handle);
int CheckDispose(int32_t handle);
int32_t SubRef(int32_t handle);
int32_t AddressToHandle(void *addr);
void *HandleToAddress(int32_t handle);
ScriptValueType HandleToAddressAndManager(int32_t handle, void *&object, IScriptObject *&manager);
int RemoveObject(void *address);
void RunGarbageCollectionIfAppropriate();
int AddObject(void *address, IScriptObject *callback, ScriptValueType obj_type);
int AddUnserializedObject(void *address, IScriptObject *callback, ScriptValueType obj_type, int handle);
void WriteToDisk(Shared::Stream *out);
int ReadFromDisk(Shared::Stream *in, ICCObjectCollectionReader *reader);
void reset();
ManagedObjectPool();
void *disableDisposeForObject{ nullptr };
};
// Extreme(!!) verbosity managed memory pool log
#if DEBUG_MANAGED_OBJECTS
#define ManagedObjectLog(...) Debug::Printf(kDbgGroup_ManObj, kDbgMsg_Debug, __VA_ARGS__)
#else
#define ManagedObjectLog(...)
#endif
} // namespace AGS3
#endif

View File

@@ -0,0 +1,34 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
#define AGS_ENGINE_DYNOBJ__SCRIPTAUDIOCHANNEL_H
namespace AGS3 {
struct ScriptAudioChannel {
int id = 0;
int reserved = 0;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,74 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_camera.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/ac/game_state.h"
#include "ags/shared/util/bbop.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
ScriptCamera::ScriptCamera(int id) : _id(id) {
}
const char *ScriptCamera::GetType() {
return "Camera2";
}
int ScriptCamera::Dispose(void *address, bool force) {
// Note that ScriptCamera is a reference to actual Camera object,
// and this deletes the reference, while camera may remain in GameState.
delete this;
return 1;
}
size_t ScriptCamera::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
void ScriptCamera::Serialize(const void *address, Stream *out) {
out->WriteInt32(_id);
}
void ScriptCamera::Unserialize(int index, Stream *in, size_t data_sz) {
_id = in->ReadInt32();
ccRegisterUnserializedObject(index, this, this);
}
ScriptCamera *Camera_Unserialize(int handle, Stream *in, size_t data_sz) {
// The way it works now, we must not create a new script object,
// but acquire one from the GameState, which keeps the first reference.
// This is essential because GameState should be able to invalidate any
// script references when Camera gets removed.
const int id = in->ReadInt32();
if (id >= 0) {
auto scam = _GP(play).RegisterRoomCamera(id, handle);
if (scam)
return scam;
}
return new ScriptCamera(-1); // make invalid reference
}
} // namespace AGS3

View File

@@ -0,0 +1,64 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_CAMERA_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_CAMERA_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
// ScriptCamera keeps a reference to actual room Camera in script.
struct ScriptCamera final : AGSCCDynamicObject {
public:
ScriptCamera(int id);
// Get camera index; negative means the camera was deleted
int GetID() const {
return _id;
}
void SetID(int id) {
_id = id;
}
// Reset camera index to indicate that this reference is no longer valid
void Invalidate() {
_id = -1;
}
const char *GetType() override;
int Dispose(void *address, bool force) override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
private:
int _id = -1; // index of camera in the game state array
};
// Unserialize camera from the memory stream
ScriptCamera *Camera_Unserialize(int handle, AGS::Shared::Stream *in, size_t data_sz);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,41 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTCONTAINERS_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTCONTAINERS_H
namespace AGS3 {
class ScriptDictBase;
class ScriptSetBase;
// Create and register new dictionary
ScriptDictBase *Dict_Create(bool sorted, bool case_sensitive);
// Unserialize dictionary from the memory stream
ScriptDictBase *Dict_Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz);
// Create and register new set
ScriptSetBase *Set_Create(bool sorted, bool case_sensitive);
// Unserialize set from the memory stream
ScriptSetBase *Set_Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz);
} // namespace AGS3
#endif

View File

@@ -0,0 +1,71 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_date_time.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
using namespace AGS::Shared;
int ScriptDateTime::Dispose(void *address, bool force) {
// always dispose a DateTime
delete this;
return 1;
}
const char *ScriptDateTime::GetType() {
return "DateTime";
}
size_t ScriptDateTime::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t) * 7;
}
void ScriptDateTime::Serialize(const void *address, Stream *out) {
out->WriteInt32(year);
out->WriteInt32(month);
out->WriteInt32(day);
out->WriteInt32(hour);
out->WriteInt32(minute);
out->WriteInt32(second);
out->WriteInt32(rawUnixTime);
}
void ScriptDateTime::Unserialize(int index, Stream *in, size_t data_sz) {
year = in->ReadInt32();
month = in->ReadInt32();
day = in->ReadInt32();
hour = in->ReadInt32();
minute = in->ReadInt32();
second = in->ReadInt32();
rawUnixTime = in->ReadInt32();
ccRegisterUnserializedObject(index, this, this);
}
ScriptDateTime::ScriptDateTime() {
year = month = day = 0;
hour = minute = second = 0;
rawUnixTime = 0;
}
} // namespace AGS3

View File

@@ -0,0 +1,49 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_DATE_TIME_H
#define AGS_ENGINE_DYNOBJ_SCRIPT_DATE_TIME_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptDateTime final : AGSCCDynamicObject {
int year, month, day;
int hour, minute, second;
int rawUnixTime;
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
ScriptDateTime();
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,34 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTDIALOG_H
#define AGS_ENGINE_DYNOBJ__SCRIPTDIALOG_H
namespace AGS3 {
struct ScriptDialog {
int id;
int reserved;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_dialog_options_rendering.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
using namespace AGS::Shared;
// return the type name of the object
const char *ScriptDialogOptionsRendering::GetType() {
return "DialogOptionsRendering";
}
size_t ScriptDialogOptionsRendering::CalcSerializeSize(const void * /*address*/) {
return 0;
}
// serialize the object into BUFFER (which is BUFSIZE bytes)
// return number of bytes used
void ScriptDialogOptionsRendering::Serialize(const void *address, Stream *out) {
}
void ScriptDialogOptionsRendering::Unserialize(int index, Stream *in, size_t data_sz) {
ccRegisterUnserializedObject(index, this, this);
}
void ScriptDialogOptionsRendering::Reset() {
x = 0;
y = 0;
width = 0;
height = 0;
hasAlphaChannel = false;
parserTextboxX = 0;
parserTextboxY = 0;
parserTextboxWidth = 0;
dialogID = 0;
surfaceToRenderTo = nullptr;
surfaceAccessed = false;
activeOptionID = -1;
chosenOptionID = -1;
needRepaint = false;
}
ScriptDialogOptionsRendering::ScriptDialogOptionsRendering() {
Reset();
}
} // namespace AGS3

View File

@@ -0,0 +1,59 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_DIALOG_OPTIONS_RENDERING_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_DIALOG_OPTIONS_RENDERING_H
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
namespace AGS3 {
struct ScriptDialogOptionsRendering final : AGSCCDynamicObject {
int x, y, width, height;
bool hasAlphaChannel;
int parserTextboxX, parserTextboxY;
int parserTextboxWidth;
int dialogID;
int activeOptionID;
int chosenOptionID;
ScriptDrawingSurface *surfaceToRenderTo;
bool surfaceAccessed;
bool needRepaint;
// return the type name of the object
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
void Reset();
ScriptDialogOptionsRendering();
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,54 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_dict.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
namespace AGS3 {
int ScriptDictBase::Dispose(void *address, bool force) {
Clear();
delete this;
return 1;
}
const char *ScriptDictBase::GetType() {
return "StringDictionary";
}
size_t ScriptDictBase::CalcSerializeSize(const void * /*address*/) {
return CalcContainerSize();
}
void ScriptDictBase::Serialize(const void *address, Stream *out) {
out->WriteInt32(IsSorted());
out->WriteInt32(IsCaseSensitive());
SerializeContainer(out);
}
void ScriptDictBase::Unserialize(int index, Stream *in, size_t data_sz) {
// NOTE: we expect sorted/case flags are read by external reader;
// this is awkward, but I did not find better design solution atm
UnserializeContainer(in);
ccRegisterUnserializedObject(index, this, this);
}
} // namespace AGS3

View File

@@ -0,0 +1,193 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Managed script object wrapping std::map<String, String> and
// unordered_map<String, String>.
//
// TODO: support wrapping non-owned Dictionary, passed by the reference, -
// that would let expose internal engine's dicts using same interface.
// TODO: maybe optimize key lookup operations further by not creating a String
// object from const char*. It seems, C++14 standard allows to use convertible
// types as keys; need to research what performance impact that would make.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDICT_H
#include "common/std/map.h"
#include "common/std/map.h"
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/util/stream.h"
#include "ags/shared/util/string.h"
#include "ags/shared/util/string_types.h"
namespace AGS3 {
using namespace AGS::Shared;
class ScriptDictBase : public AGSCCDynamicObject {
public:
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
virtual bool IsCaseSensitive() const = 0;
virtual bool IsSorted() const = 0;
virtual void Clear() = 0;
virtual bool Contains(const char *key) = 0;
virtual const char *Get(const char *key) = 0;
virtual bool Remove(const char *key) = 0;
virtual bool Set(const char *key, const char *value) = 0;
virtual int GetItemCount() = 0;
virtual void GetKeys(std::vector<const char *> &buf) const = 0;
virtual void GetValues(std::vector<const char *> &buf) const = 0;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
private:
virtual size_t CalcContainerSize() = 0;
virtual void SerializeContainer(AGS::Shared::Stream *out) = 0;
virtual void UnserializeContainer(AGS::Shared::Stream *in) = 0;
};
template <typename TDict, bool is_sorted, bool is_casesensitive>
class ScriptDictImpl final : public ScriptDictBase {
public:
typedef typename TDict::const_iterator ConstIterator;
ScriptDictImpl() {}
bool IsCaseSensitive() const override {
return is_casesensitive;
}
bool IsSorted() const override {
return is_sorted;
}
void Clear() override {
for (auto it = _dic.begin(); it != _dic.end(); ++it)
DeleteItem(it);
_dic.clear();
}
bool Contains(const char *key) override {
#ifdef AGS_PLATFORM_SCUMMVM
return _dic.find(String::Wrapper(key)) != _dic.end();
#else
return _dic.count(String::Wrapper(key)) != 0;
#endif
}
const char *Get(const char *key) override {
auto it = _dic.find(String::Wrapper(key));
if (it == _dic.end()) return nullptr;
return it->_value.GetCStr();
}
bool Remove(const char *key) override {
auto it = _dic.find(String::Wrapper(key));
if (it == _dic.end()) return false;
DeleteItem(it);
_dic.erase(it);
return true;
}
bool Set(const char *key, const char *value) override {
if (!key)
return false;
if (!value) {
// Remove keys with null value
Remove(key);
return true;
}
return TryAddItem(String(key), String(value));
}
int GetItemCount() override {
return _dic.size();
}
void GetKeys(std::vector<const char *> &buf) const override {
for (auto it = _dic.begin(); it != _dic.end(); ++it)
buf.push_back(it->_key.GetCStr());
}
void GetValues(std::vector<const char *> &buf) const override {
for (auto it = _dic.begin(); it != _dic.end(); ++it)
buf.push_back(it->_value.GetCStr());
}
private:
bool TryAddItem(const String &key, const String &value) {
_dic[key] = value;
return true;
}
void DeleteItem(ConstIterator /*it*/) { /* do nothing */ }
size_t CalcContainerSize() override {
// 2 class properties + item count
size_t total_sz = sizeof(int32_t) * 3;
// (int32 + string buffer) per item
for (auto it = _dic.begin(); it != _dic.end(); ++it) {
total_sz += sizeof(int32_t) + it->_key.GetLength();
total_sz += sizeof(int32_t) + it->_value.GetLength();
}
return total_sz;
}
void SerializeContainer(AGS::Shared::Stream *out) override
{
out->WriteInt32((int)_dic.size());
for (auto it = _dic.begin(); it != _dic.end(); ++it)
{
out->WriteInt32((int)it->_key.GetLength());
out->Write(it->_key.GetCStr(), it->_key.GetLength());
out->WriteInt32((int)it->_value.GetLength());
out->Write(it->_value.GetCStr(), it->_value.GetLength());
}
}
void UnserializeContainer(AGS::Shared::Stream *in) override {
size_t item_count = in->ReadInt32();
for (size_t i = 0; i < item_count; ++i) {
size_t key_len = in->ReadInt32();
String key = String::FromStreamCount(in, key_len);
size_t value_len = in->ReadInt32();
if (value_len != (size_t)-1) // do not restore keys with null value (old format)
{
String value = String::FromStreamCount(in, value_len);
TryAddItem(key, value);
}
}
}
TDict _dic;
};
typedef ScriptDictImpl< std::map<String, String>, true, true > ScriptDict;
typedef ScriptDictImpl< std::map<String, String, IgnoreCase_LessThan>, true, false > ScriptDictCI;
typedef ScriptDictImpl< std::unordered_map<String, String>, false, true > ScriptHashDict;
typedef ScriptDictImpl< std::unordered_map<String, String, IgnoreCase_Hash, IgnoreCase_EqualTo>, false, false > ScriptHashDictCI;
} // namespace AGS3
#endif

View File

@@ -0,0 +1,138 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_drawing_surface.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/sprite_cache.h"
#include "ags/engine/ac/runtime_defines.h"
#include "ags/shared/ac/common.h"
#include "ags/engine/ac/draw.h"
#include "ags/engine/ac/drawing_surface.h"
#include "ags/engine/ac/game_state.h"
#include "ags/shared/ac/game_setup_struct.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
Bitmap *ScriptDrawingSurface::GetBitmapSurface() {
// TODO: consider creating weak_ptr here, and store one in the DrawingSurface!
if (roomBackgroundNumber >= 0)
return _GP(thisroom).BgFrames[roomBackgroundNumber].Graphic.get();
else if (dynamicSpriteNumber >= 0)
return _GP(spriteset)[dynamicSpriteNumber];
else if (dynamicSurfaceNumber >= 0)
return _G(dynamicallyCreatedSurfaces)[dynamicSurfaceNumber].get();
else if (linkedBitmapOnly != nullptr)
return linkedBitmapOnly;
else if (roomMaskType > kRoomAreaNone)
return _GP(thisroom).GetMask(roomMaskType);
quit("!DrawingSurface: attempted to use surface after Release was called");
return nullptr;
}
Bitmap *ScriptDrawingSurface::StartDrawing() {
return this->GetBitmapSurface();
}
void ScriptDrawingSurface::FinishedDrawingReadOnly() {
}
void ScriptDrawingSurface::FinishedDrawing() {
FinishedDrawingReadOnly();
modified = 1;
}
int ScriptDrawingSurface::Dispose(void *address, bool force) {
// dispose the drawing surface
DrawingSurface_Release(this);
delete this;
return 1;
}
const char *ScriptDrawingSurface::GetType() {
return "DrawingSurface";
}
size_t ScriptDrawingSurface::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t) * 9;
}
void ScriptDrawingSurface::Serialize(const void *address, Stream *out) {
// pack mask type in the last byte of a negative integer
// note: (-1) is reserved for "unused", for backward compatibility
if (roomMaskType > 0)
out->WriteInt32(0xFFFFFF00 | roomMaskType);
else
out->WriteInt32(roomBackgroundNumber);
out->WriteInt32(dynamicSpriteNumber);
out->WriteInt32(dynamicSurfaceNumber);
out->WriteInt32(currentColour);
out->WriteInt32(currentColourScript);
out->WriteInt32(highResCoordinates);
out->WriteInt32(modified);
out->WriteInt32(hasAlphaChannel);
out->WriteInt32(isLinkedBitmapOnly ? 1 : 0);
}
void ScriptDrawingSurface::Unserialize(int index, Stream *in, size_t data_sz) {
int room_ds = in->ReadInt32();
if (room_ds >= 0)
roomBackgroundNumber = room_ds;
// negative value may contain a mask type
else if ((room_ds & 0xFF) != 0xFF)
roomMaskType = (RoomAreaMask)(room_ds & 0xFF);
dynamicSpriteNumber = in->ReadInt32();
dynamicSurfaceNumber = in->ReadInt32();
currentColour = in->ReadInt32();
currentColourScript = in->ReadInt32();
highResCoordinates = in->ReadInt32();
modified = in->ReadInt32();
hasAlphaChannel = in->ReadInt32();
isLinkedBitmapOnly = (in->ReadInt32() != 0);
ccRegisterUnserializedObject(index, this, this);
}
ScriptDrawingSurface::ScriptDrawingSurface() {
roomBackgroundNumber = -1;
roomMaskType = kRoomAreaNone;
dynamicSpriteNumber = -1;
dynamicSurfaceNumber = -1;
isLinkedBitmapOnly = false;
linkedBitmapOnly = nullptr;
currentColour = _GP(play).raw_color;
currentColourScript = 0;
modified = 0;
hasAlphaChannel = 0;
highResCoordinates = 0;
// NOTE: Normally in contemporary games coordinates ratio will always be 1:1.
// But we still support legacy drawing, so have to set this up even for modern games,
// otherwise we'd have to complicate conversion conditions further.
if (_GP(game).IsLegacyHiRes() && _GP(game).IsDataInNativeCoordinates()) {
highResCoordinates = 1;
}
}
} // namespace AGS3

View File

@@ -0,0 +1,71 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_DRAWING_SURFACE_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_DRAWING_SURFACE_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
struct ScriptDrawingSurface final : AGSCCDynamicObject {
// These numbers and types are used to determine the source of this drawing surface;
// only one of them can be valid for this surface.
int roomBackgroundNumber;
RoomAreaMask roomMaskType;
int dynamicSpriteNumber;
int dynamicSurfaceNumber;
bool isLinkedBitmapOnly;
AGS::Shared::Bitmap *linkedBitmapOnly;
int currentColour;
int currentColourScript;
int highResCoordinates;
int modified;
int hasAlphaChannel;
//Shared::Bitmap* abufBackup;
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
AGS::Shared::Bitmap *GetBitmapSurface();
AGS::Shared::Bitmap *StartDrawing();
void PointToGameResolution(int *xcoord, int *ycoord);
void SizeToGameResolution(int *width, int *height);
void SizeToGameResolution(int *adjustValue);
void SizeToDataResolution(int *adjustValue);
void FinishedDrawing();
void FinishedDrawingReadOnly();
ScriptDrawingSurface();
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_dynamic_sprite.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/util/stream.h"
#include "ags/engine/ac/dynamic_sprite.h"
namespace AGS3 {
using namespace AGS::Shared;
int ScriptDynamicSprite::Dispose(void *address, bool force) {
// always dispose
if ((slot) && (!force))
free_dynamic_sprite(slot);
delete this;
return 1;
}
const char *ScriptDynamicSprite::GetType() {
return "DynamicSprite";
}
size_t ScriptDynamicSprite::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
void ScriptDynamicSprite::Serialize(const void *address, Stream *out) {
out->WriteInt32(slot);
}
void ScriptDynamicSprite::Unserialize(int index, Stream *in, size_t data_sz) {
slot = in->ReadInt32();
ccRegisterUnserializedObject(index, this, this);
}
ScriptDynamicSprite::ScriptDynamicSprite(int theSlot) {
slot = theSlot;
ccRegisterManagedObject(this, this);
}
ScriptDynamicSprite::ScriptDynamicSprite() {
slot = 0;
}
} // namespace AGS3

View File

@@ -0,0 +1,48 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTDYNAMICSPRITE_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTDYNAMICSPRITE_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptDynamicSprite final : AGSCCDynamicObject {
int slot;
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
ScriptDynamicSprite(int slot);
ScriptDynamicSprite();
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,66 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_file.h"
#include "ags/engine/ac/global_file.h"
namespace AGS3 {
// CHECKME: actually NULLs here will be equal to kFile_Open & kFile_Read
const Shared::FileOpenMode sc_File::fopenModes[] =
{ Shared::kFile_Open/*CHECKME, was undefined*/, Shared::kFile_Open, Shared::kFile_CreateAlways, Shared::kFile_Create };
const Shared::FileWorkMode sc_File::fworkModes[] =
{ Shared::kFile_Read/*CHECKME, was undefined*/, Shared::kFile_Read, Shared::kFile_Write, Shared::kFile_Write };
int sc_File::Dispose(void *address, bool force) {
Close();
delete this;
return 1;
}
const char *sc_File::GetType() {
return "File";
}
int sc_File::Serialize(void *address, uint8_t *buffer, int bufsize) {
// we cannot serialize an open file, so it will get closed
return 0;
}
int sc_File::OpenFile(const char *filename, int mode) {
handle = FileOpen(filename, fopenModes[mode], fworkModes[mode]);
if (handle <= 0)
return 0;
return 1;
}
void sc_File::Close() {
if (handle > 0) {
FileClose(handle);
handle = 0;
}
}
sc_File::sc_File() {
handle = 0;
}
} // namespace AGS3

View File

@@ -0,0 +1,56 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTFILE_H
#define AGS_ENGINE_DYNOBJ__SCRIPTFILE_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/util/file.h"
namespace AGS3 {
using namespace AGS; // FIXME later
#define scFileRead 1
#define scFileWrite 2
#define scFileAppend 3
struct sc_File final : CCBasicObject {
int32_t handle;
static const Shared::FileOpenMode fopenModes[];
static const Shared::FileWorkMode fworkModes[];
int Dispose(void *address, bool force) override;
const char *GetType() override;
int Serialize(void *address, uint8_t *buffer, int bufsize) override;
int OpenFile(const char *filename, int mode);
void Close();
sc_File();
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,442 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/ac/dynobj/script_game.h"
#include "ags/engine/ac/game.h"
#include "ags/engine/ac/game_state.h"
#include "ags/shared/ac/game_setup_struct.h"
#include "ags/shared/gui/gui_main.h"
#include "ags/shared/script/cc_common.h" // cc_error
#include "ags/globals.h"
namespace AGS3 {
int32_t CCScriptGame::ReadInt32(void *address, intptr_t offset) {
const int index = offset / sizeof(int32_t);
if (index >= 5 && index < 5 + MAXGLOBALVARS)
return _GP(play).globalvars[index - 5];
switch (index) {
case 0:
return _GP(play).score;
case 1:
return _GP(play).usedmode;
case 2:
return _GP(play).disabled_user_interface;
case 3:
return _GP(play).gscript_timer;
case 4:
return _GP(play).debug_mode;
// 5 -> 54: _GP(play).globalvars
case 55:
return _GP(play).messagetime;
case 56:
return _GP(play).usedinv;
case 57:
return _GP(play).inv_top;
case 58:
return _GP(play).inv_numdisp;
case 59:
return _GP(play).inv_numorder;
case 60:
return _GP(play).inv_numinline;
case 61:
return _GP(play).text_speed;
case 62:
return _GP(play).sierra_inv_color;
case 63:
return _GP(play).talkanim_speed;
case 64:
return _GP(play).inv_item_wid;
case 65:
return _GP(play).inv_item_hit;
case 66:
return _GP(play).speech_text_shadow;
case 67:
return _GP(play).swap_portrait_side;
case 68:
return _GP(play).speech_textwindow_gui;
case 69:
return _GP(play).follow_change_room_timer;
case 70:
return _GP(play).totalscore;
case 71:
return _GP(play).skip_display;
case 72:
return _GP(play).no_multiloop_repeat;
case 73:
return _GP(play).roomscript_finished;
case 74:
return _GP(play).used_inv_on;
case 75:
return _GP(play).no_textbg_when_voice;
case 76:
return _GP(play).max_dialogoption_width;
case 77:
return _GP(play).no_hicolor_fadein;
case 78:
return _GP(play).bgspeech_game_speed;
case 79:
return _GP(play).bgspeech_stay_on_display;
case 80:
return _GP(play).unfactor_speech_from_textlength;
case 81:
return _GP(play).mp3_loop_before_end;
case 82:
return _GP(play).speech_music_drop;
case 83:
return _GP(play).in_cutscene;
case 84:
return _GP(play).fast_forward;
case 85:
return _GP(play).room_width;
case 86:
return _GP(play).room_height;
case 87:
return _GP(play).game_speed_modifier;
case 88:
return _GP(play).score_sound;
case 89:
return _GP(play).takeover_data;
case 90:
return 0; // _GP(play).replay_hotkey
case 91:
return _GP(play).dialog_options_x;
case 92:
return _GP(play).dialog_options_y;
case 93:
return _GP(play).narrator_speech;
case 94:
return _GP(play).ambient_sounds_persist;
case 95:
return _GP(play).lipsync_speed;
case 96:
return _GP(play).close_mouth_speech_time;
case 97:
return _GP(play).disable_antialiasing;
case 98:
return _GP(play).text_speed_modifier;
case 99:
return _GP(play).text_align;
case 100:
return _GP(play).speech_bubble_width;
case 101:
return _GP(play).min_dialogoption_width;
case 102:
return _GP(play).disable_dialog_parser;
case 103:
return _GP(play).anim_background_speed;
case 104:
return _GP(play).top_bar_backcolor;
case 105:
return _GP(play).top_bar_textcolor;
case 106:
return _GP(play).top_bar_bordercolor;
case 107:
return _GP(play).top_bar_borderwidth;
case 108:
return _GP(play).top_bar_ypos;
case 109:
return _GP(play).screenshot_width;
case 110:
return _GP(play).screenshot_height;
case 111:
return _GP(play).top_bar_font;
case 112:
return _GP(play).speech_text_align;
case 113:
return _GP(play).auto_use_walkto_points;
case 114:
return _GP(play).inventory_greys_out;
case 115:
return _GP(play).skip_speech_specific_key;
case 116:
return _GP(play).abort_key;
case 117:
return _GP(play).fade_to_red;
case 118:
return _GP(play).fade_to_green;
case 119:
return _GP(play).fade_to_blue;
case 120:
return _GP(play).show_single_dialog_option;
case 121:
return _GP(play).keep_screen_during_instant_transition;
case 122:
return _GP(play).read_dialog_option_colour;
case 123:
return _GP(play).stop_dialog_at_end;
case 124:
return _GP(play).speech_portrait_placement;
case 125:
return _GP(play).speech_portrait_x;
case 126:
return _GP(play).speech_portrait_y;
case 127:
return _GP(play).speech_display_post_time_ms;
case 128:
return _GP(play).dialog_options_highlight_color;
default:
cc_error("ScriptGame: unsupported variable offset %d", offset);
return 0;
}
}
void CCScriptGame::WriteInt32(void *address, intptr_t offset, int32_t val) {
const int index = offset / sizeof(int32_t);
if (index >= 5 && index < 5 + MAXGLOBALVARS) {
_GP(play).globalvars[index - 5] = val;
return;
}
switch (index) {
case 0:
_GP(play).score = val;
break;
case 1:
_GP(play).usedmode = val;
break;
case 2:
_GP(play).disabled_user_interface = val;
break;
case 3:
_GP(play).gscript_timer = val;
break;
case 4:
set_debug_mode(val != 0);
break; // _GP(play).debug_mode
// 5 -> 54: _GP(play).globalvars
case 55:
_GP(play).messagetime = val;
break;
case 56:
_GP(play).usedinv = val;
break;
case 57:
_GP(play).inv_top = val;
GUI::MarkInventoryForUpdate(_GP(game).playercharacter, true);
break;
case 58: // play.inv_numdisp
case 59: // play.inv_numorder
case 60: // play.inv_numinline
debug_script_warn("ScriptGame: attempt to write in readonly variable at offset %d, value %d", offset, val);
break;
case 61:
_GP(play).text_speed = val;
break;
case 62:
_GP(play).sierra_inv_color = val;
break;
case 63:
_GP(play).talkanim_speed = val;
break;
case 64:
_GP(play).inv_item_wid = val;
break;
case 65:
_GP(play).inv_item_hit = val;
break;
case 66:
_GP(play).speech_text_shadow = val;
break;
case 67:
_GP(play).swap_portrait_side = val;
break;
case 68:
_GP(play).speech_textwindow_gui = val;
break;
case 69:
_GP(play).follow_change_room_timer = val;
break;
case 70:
_GP(play).totalscore = val;
break;
case 71:
_GP(play).skip_display = val;
break;
case 72:
_GP(play).no_multiloop_repeat = val;
break;
case 73:
_GP(play).roomscript_finished = val;
break;
case 74:
_GP(play).used_inv_on = val;
break;
case 75:
_GP(play).no_textbg_when_voice = val;
break;
case 76:
_GP(play).max_dialogoption_width = val;
break;
case 77:
_GP(play).no_hicolor_fadein = val;
break;
case 78:
_GP(play).bgspeech_game_speed = val;
break;
case 79:
_GP(play).bgspeech_stay_on_display = val;
break;
case 80:
_GP(play).unfactor_speech_from_textlength = val;
break;
case 81:
_GP(play).mp3_loop_before_end = val;
break;
case 82:
_GP(play).speech_music_drop = val;
break;
case 83: // _GP(play).in_cutscene
case 84: // _GP(play).fast_forward;
case 85: // _GP(play).room_width;
case 86: // _GP(play).room_height;
debug_script_warn("ScriptGame: attempt to write in readonly variable at offset %d, value %d", offset, val);
break;
case 87:
_GP(play).game_speed_modifier = val;
break;
case 88:
_GP(play).score_sound = val;
break;
case 89:
_GP(play).takeover_data = val;
break;
case 90:
break; // _GP(play).replay_hotkey
case 91:
_GP(play).dialog_options_x = val;
break;
case 92:
_GP(play).dialog_options_y = val;
break;
case 93:
_GP(play).narrator_speech = val;
break;
case 94:
_GP(play).ambient_sounds_persist = val;
break;
case 95:
_GP(play).lipsync_speed = val;
break;
case 96:
_GP(play).close_mouth_speech_time = val;
break;
case 97:
_GP(play).disable_antialiasing = val;
break;
case 98:
_GP(play).text_speed_modifier = val;
break;
case 99:
_GP(play).text_align = ReadScriptAlignment(val);
break;
case 100:
_GP(play).speech_bubble_width = val;
break;
case 101:
_GP(play).min_dialogoption_width = val;
break;
case 102:
_GP(play).disable_dialog_parser = val;
break;
case 103:
_GP(play).anim_background_speed = val;
break;
case 104:
_GP(play).top_bar_backcolor = val;
break;
case 105:
_GP(play).top_bar_textcolor = val;
break;
case 106:
_GP(play).top_bar_bordercolor = val;
break;
case 107:
_GP(play).top_bar_borderwidth = val;
break;
case 108:
_GP(play).top_bar_ypos = val;
break;
case 109:
_GP(play).screenshot_width = val;
break;
case 110:
_GP(play).screenshot_height = val;
break;
case 111:
_GP(play).top_bar_font = val;
break;
case 112:
_GP(play).speech_text_align = ReadScriptAlignment(val);
break;
case 113:
_GP(play).auto_use_walkto_points = val;
break;
case 114:
_GP(play).inventory_greys_out = val;
break;
case 115:
_GP(play).skip_speech_specific_key = val;
break;
case 116:
_GP(play).abort_key = val;
break;
case 117: // _GP(play).fade_to_red;
case 118: // _GP(play).fade_to_green;
case 119: // _GP(play).fade_to_blue;
debug_script_warn("ScriptGame: attempt to write in readonly variable at offset %d, value %d", offset, val);
break;
case 120:
_GP(play).show_single_dialog_option = val;
break;
case 121:
_GP(play).keep_screen_during_instant_transition = val;
break;
case 122:
_GP(play).read_dialog_option_colour = val;
break;
case 123:
_GP(play).stop_dialog_at_end = val;
break;
case 124:
_GP(play).speech_portrait_placement = val;
break;
case 125:
_GP(play).speech_portrait_x = val;
break;
case 126:
_GP(play).speech_portrait_y = val;
break;
case 127:
_GP(play).speech_display_post_time_ms = val;
break;
case 128:
_GP(play).dialog_options_highlight_color = val;
break;
default:
cc_error("ScriptGame: unsupported variable offset %d", offset);
break;
}
}
} // namespace AGS3

View File

@@ -0,0 +1,42 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Wrapper around script "GameState" struct, managing access to its variables.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_AGS_SCRIPT_GAME_H
#define AGS_ENGINE_AC_DYNOBJ_AGS_SCRIPT_GAME_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct CCScriptGame : public AGSCCStaticObject {
int32_t ReadInt32(void *address, intptr_t offset) override;
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,35 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTGUI_H
#define AGS_ENGINE_DYNOBJ__SCRIPTGUI_H
namespace AGS3 {
// 64 bit: This struct must be 8 byte long
struct ScriptGUI {
int id;
int __padding;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,34 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTHOTSPOT_H
#define AGS_ENGINE_DYNOBJ__SCRIPTHOTSPOT_H
namespace AGS3 {
struct ScriptHotspot {
int id = 0;
int reserved = 0;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,34 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTINVITEM_H
#define AGS_ENGINE_DYNOBJ__SCRIPTINVITEM_H
namespace AGS3 {
struct ScriptInvItem {
int id = 0;
int reserved = 0;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,52 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/ac/dynobj/script_mouse.h"
#include "ags/shared/script/cc_common.h" // cc_error
namespace AGS3 {
int32_t ScriptMouse::ReadInt32(void *address, intptr_t offset) {
switch (offset) {
case 0:
return x;
case 4:
return y;
default:
cc_error("ScriptMouse: unsupported variable offset %d", offset);
return 0;
}
}
void ScriptMouse::WriteInt32(void *address, intptr_t offset, int32_t val) {
switch (offset) {
case 0:
case 4:
debug_script_warn("ScriptMouse: attempt to write in readonly variable at offset %d, value", offset, val);
break;
default:
cc_error("ScriptMouse: unsupported variable offset %d", offset);
break;
}
}
} // namespace AGS3

View File

@@ -0,0 +1,44 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Wrapper around script "Mouse" struct, managing access to its variables.
//
//=============================================================================
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTMOUSE_H
#define AGS_ENGINE_DYNOBJ__SCRIPTMOUSE_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptMouse : public AGSCCStaticObject {
int x;
int y;
int32_t ReadInt32(void *address, intptr_t offset) override;
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,37 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_OBJECT_H
#define AGS_ENGINE_DYNOBJ_SCRIPT_OBJECT_H
#include "ags/engine/ac/room_object.h"
namespace AGS3 {
// WARNING: struct size must be 8 byte for old scripts to work
struct ScriptObject {
int id = -1;
int __padding = 0;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,90 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_overlay.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/ac/common.h"
#include "ags/shared/util/stream.h"
#include "ags/engine/ac/overlay.h"
#include "ags/engine/ac/runtime_defines.h"
#include "ags/engine/ac/screen_overlay.h"
#include "ags/engine/debugging/debug_log.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
int ScriptOverlay::Dispose(void * /*address*/, bool force) {
// since the managed object is being deleted, remove the
// reference so it doesn't try and dispose something else
// with that handle later
if (overlayId >= 0) {
auto *over = get_overlay(overlayId);
if (over) {
over->associatedOverlayHandle = 0;
}
}
// if this is being removed voluntarily (ie. pointer out of
// scope) then remove the associateed overlay
// Otherwise, it's a Restore Game or something so don't
if ((!force) && (Overlay_GetValid(this))) {
Remove();
}
delete this;
return 1;
}
const char *ScriptOverlay::GetType() {
return "Overlay";
}
size_t ScriptOverlay::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t) * 4;
}
void ScriptOverlay::Serialize(const void * /*address*/, Stream *out) {
out->WriteInt32(overlayId);
out->WriteInt32(0); // unused (was text window x padding)
out->WriteInt32(0); // unused (was text window y padding)
out->WriteInt32(0); // unused (was internal ref flag)
}
void ScriptOverlay::Unserialize(int index, Stream *in, size_t data_sz) {
overlayId = in->ReadInt32();
in->ReadInt32(); // unused (was text window x padding)
in->ReadInt32(); // unused (was text window y padding)
in->ReadInt32(); // unused (was internal ref flag)
ccRegisterUnserializedObject(index, this, this);
}
void ScriptOverlay::Remove() {
if (overlayId < 0) {
debug_script_warn("Overlay.Remove: overlay is invalid, could have been removed earlier.");
return;
}
remove_screen_overlay(overlayId);
overlayId = -1;
}
} // namespace AGS3

View File

@@ -0,0 +1,47 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_OVERLAY_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_OVERLAY_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptOverlay final : AGSCCDynamicObject {
int overlayId = -1;
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
void Remove();
ScriptOverlay() = default;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,34 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTREGION_H
#define AGS_ENGINE_DYNOBJ__SCRIPTREGION_H
namespace AGS3 {
struct ScriptRegion {
int id = 0;
int reserved = 0;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_set.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
int ScriptSetBase::Dispose(void * /*address*/, bool force) {
Clear();
delete this;
return 1;
}
const char *ScriptSetBase::GetType() {
return "StringSet";
}
size_t ScriptSetBase::CalcSerializeSize(const void * /*address*/) {
return CalcContainerSize();
}
void ScriptSetBase::Serialize(const void * /*address*/, Stream *out) {
out->WriteInt32(IsSorted());
out->WriteInt32(IsCaseSensitive());
SerializeContainer(out);
}
void ScriptSetBase::Unserialize(int index, Stream *in, size_t data_sz) {
// NOTE: we expect sorted/case flags are read by external reader;
// this is awkward, but I did not find better design solution atm
UnserializeContainer(in);
ccRegisterUnserializedObject(index, this, this);
}
} // namespace AGS3

View File

@@ -0,0 +1,159 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Managed script object wrapping std::set<String> and unordered_set<String>.
//
// TODO: support wrapping non-owned Set, passed by the reference, -
// that would let expose internal engine's sets using same interface.
// TODO: maybe optimize key lookup operations further by not creating a String
// object from const char*. It seems, C++14 standard allows to use convertible
// types as keys; need to research what performance impact that would make.
//
//=============================================================================
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTSET_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTSET_H
#include "common/std/set.h"
#include "common/std/unordered_set.h"
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/util/stream.h"
#include "ags/shared/util/string.h"
#include "ags/shared/util/string_types.h"
namespace AGS3 {
using namespace AGS::Shared;
class ScriptSetBase : public AGSCCDynamicObject {
public:
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
virtual bool IsCaseSensitive() const = 0;
virtual bool IsSorted() const = 0;
virtual bool Add(const char *item) = 0;
virtual void Clear() = 0;
virtual bool Contains(const char *item) const = 0;
virtual bool Remove(const char *item) = 0;
virtual int GetItemCount() const = 0;
virtual void GetItems(std::vector<const char *> &buf) const = 0;
protected:
// Calculate and return required space for serialization, in bytes
virtual size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
private:
virtual size_t CalcContainerSize() = 0;
virtual void SerializeContainer(AGS::Shared::Stream *out) = 0;
virtual void UnserializeContainer(AGS::Shared::Stream *in) = 0;
};
template <typename TSet, bool is_sorted, bool is_casesensitive>
class ScriptSetImpl final : public ScriptSetBase {
public:
typedef typename TSet::const_iterator ConstIterator;
ScriptSetImpl() {}
bool IsCaseSensitive() const override {
return is_casesensitive;
}
bool IsSorted() const override {
return is_sorted;
}
bool Add(const char *item) override {
if (!item) return false;
return TryAddItem(String(item));
}
void Clear() override {
for (auto it = _set.begin(); it != _set.end(); ++it)
DeleteItem(it);
_set.clear();
}
bool Contains(const char *item) const override {
return _set.count(String::Wrapper(item)) != 0;
}
bool Remove(const char *item) override {
auto it = _set.find(String::Wrapper(item));
if (it == _set.end()) return false;
DeleteItem(it);
_set.erase(it);
return true;
}
int GetItemCount() const override {
return _set.size();
}
void GetItems(std::vector<const char *> &buf) const override {
for (auto it = _set.begin(); it != _set.end(); ++it)
buf.push_back(it->GetCStr());
}
private:
bool TryAddItem(const String &s) {
return _set.insert(s)._value;
}
void DeleteItem(ConstIterator /*it*/) { /* do nothing */ }
size_t CalcContainerSize() override {
// 2 class properties + item count
size_t total_sz = sizeof(int32_t) * 3;
// (int32 + string buffer) per item
for (auto it = _set.begin(); it != _set.end(); ++it)
total_sz += sizeof(int32_t) + it->GetLength();
return total_sz;
}
void SerializeContainer(AGS::Shared::Stream *out) override {
out->WriteInt32((int)_set.size());
for (auto it = _set.begin(); it != _set.end(); ++it) {
out->WriteInt32((int)it->GetLength());
out->Write(it->GetCStr(), it->GetLength());
}
}
void UnserializeContainer(AGS::Shared::Stream *in) override {
size_t item_count = in->ReadInt32();
for (size_t i = 0; i < item_count; ++i) {
size_t len = in->ReadInt32();
String item = String::FromStreamCount(in, len);
TryAddItem(item);
}
}
TSet _set;
};
typedef ScriptSetImpl< std::set<String>, true, true > ScriptSet;
typedef ScriptSetImpl< std::set<String, IgnoreCase_LessThan>, true, false > ScriptSetCI;
typedef ScriptSetImpl< std::unordered_set<String>, false, true > ScriptHashSet;
typedef ScriptSetImpl< std::unordered_set<String, IgnoreCase_Hash, IgnoreCase_EqualTo>, false, false > ScriptHashSetCI;
} // namespace AGS3
#endif

View File

@@ -0,0 +1,79 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_string.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/ac/string.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
const char *ScriptString::GetType() {
return "String";
}
int ScriptString::Dispose(void *address, bool /*force*/) {
delete[] (static_cast<uint8_t *>(address) - MemHeaderSz);
return 1;
}
size_t ScriptString::CalcSerializeSize(const void *address) {
const Header &hdr = GetHeader(address);
return hdr.Length + 1 + FileHeaderSz;
}
void ScriptString::Serialize(const void *address, Stream *out) {
const Header &hdr = GetHeader(address);
out->WriteInt32(hdr.Length);
out->Write(address, hdr.Length + 1); // it was writing trailing 0 for some reason
}
void ScriptString::Unserialize(int index, Stream *in, size_t /*data_sz*/) {
size_t len = in->ReadInt32();
uint8_t *buf = new uint8_t[len + 1 + MemHeaderSz];
Header &hdr = reinterpret_cast<Header &>(*buf);
hdr.Length = len;
char *text_ptr = reinterpret_cast<char *>(buf + MemHeaderSz);
in->Read(text_ptr, len + 1); // it was writing trailing 0 for some reason
text_ptr[len] = 0; // for safety
ccRegisterUnserializedObject(index, text_ptr, this);
}
DynObjectRef ScriptString::CreateImpl(const char *text, size_t buf_len) {
size_t len = text ? strlen(text) : buf_len;
uint8_t *buf = new uint8_t[len + 1 + MemHeaderSz];
Header &hdr = reinterpret_cast<Header &>(*buf);
hdr.Length = len;
char *text_ptr = reinterpret_cast<char *>(buf + MemHeaderSz);
if (text)
memcpy(text_ptr, text, len + 1);
int32_t handle = ccRegisterManagedObject(text_ptr, &_GP(myScriptStringImpl));
if (handle == 0) {
delete[] buf;
return DynObjectRef();
}
return DynObjectRef(handle, text_ptr, &_GP(myScriptStringImpl));
}
} // namespace AGS3

View File

@@ -0,0 +1,68 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_STRING_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_STRING_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptString final : AGSCCDynamicObject {
public:
struct Header {
uint32_t Length = 0u;
};
ScriptString() = default;
~ScriptString() = default;
inline static const Header &GetHeader(const void *address) {
return reinterpret_cast<const Header &>(*(static_cast<const uint8_t *>(address) - MemHeaderSz));
}
// Create a new script string by copying the given text
static DynObjectRef Create(const char *text) { return CreateImpl(text, 0); }
// Create a new script string with a buffer of at least the given text length
static DynObjectRef Create(size_t buf_len) { return CreateImpl(nullptr, buf_len); }
const char *GetType() override;
int Dispose(void *address, bool force) override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
private:
// The size of the array's header in memory, prepended to the element data
static const size_t MemHeaderSz = sizeof(Header);
// The size of the serialized header
static const size_t FileHeaderSz = sizeof(uint32_t);
static DynObjectRef CreateImpl(const char *text, size_t buf_len);
// Savegame serialization
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,74 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/debugging/debug_log.h"
#include "ags/engine/ac/dynobj/script_system.h"
#include "ags/shared/script/cc_common.h" // cc_error
namespace AGS3 {
int32_t ScriptSystem::ReadInt32(void *address, intptr_t offset) {
const int index = offset / sizeof(int32_t);
switch (index) {
case 0:
return width;
case 1:
return height;
case 2:
return coldepth;
case 3:
return os;
case 4:
return windowed;
case 5:
return vsync;
case 6:
return viewport_width;
case 7:
return viewport_height;
default:
cc_error("ScriptSystem: unsupported variable offset %d", offset);
return 0;
}
}
void ScriptSystem::WriteInt32(void *address, intptr_t offset, int32_t val) {
const int index = offset / sizeof(int32_t);
switch (index) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 6:
case 7:
debug_script_warn("ScriptSystem: attempt to write in readonly variable at offset %d, value %d", offset, val);
break;
case 5:
vsync = val;
break;
default:
cc_error("ScriptSystem: unsupported variable offset %d", offset);
break;
}
}
} // namespace AGS3

View File

@@ -0,0 +1,55 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Wrapper around script "System" struct, managing access to its variables.
// ScriptSystem is a readable/writeable struct which had been exposed to
// script in older versions of API (deprecated).
// WARNING: it *MUST* keep its size exact to avoid breaking address offsets
// when running old scripts. In case of emergency you may use its reserved
// fields, but it's not recommended to do, as this struct is not a part of
// the modern API anymore.
#ifndef AGS_ENGINE_DYNOBJ_SCRIPT_SYSTEM_H
#define AGS_ENGINE_DYNOBJ_SCRIPT_SYSTEM_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptSystem : AGSCCStaticObject {
int width = 0; // game screen width
int height = 0; // game screen height
int coldepth = 0; // game's color depth, in bits per pixel (8, 16, 32)
int os = 0; // operating system's code (see eScriptSystemOSID)
int windowed = 0; // windowed/fullscreen flag
int vsync = 0; // vertical sync flag
int viewport_width = 0; // game viewport width (normal or letterboxed)
int viewport_height = 0; // game viewport height (normal or letterboxed)
char aci_version[10]{}; // engine version string (informational)
int reserved[5]{}; // reserved fields
int32_t ReadInt32(void *address, intptr_t offset) override;
void WriteInt32(void *address, intptr_t offset, int32_t val) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,85 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/std/memory.h"
#include "ags/shared/util/stream.h"
#include "ags/engine/ac/dynobj/script_user_object.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
const char *ScriptUserObject::TypeName = "UserObject";
// return the type name of the object
const char *ScriptUserObject::GetType() {
return TypeName;
}
/* static */ DynObjectRef ScriptUserObject::Create(size_t size) {
uint8_t *new_data = new uint8_t[size + MemHeaderSz];
memset(new_data, 0, size + MemHeaderSz);
Header &hdr = reinterpret_cast<Header &>(*new_data);
hdr.Size = size;
void *obj_ptr = &new_data[MemHeaderSz];
int32_t handle = ccRegisterManagedObject(obj_ptr, &_G(globalDynamicStruct));
if (handle == 0) {
delete[] new_data;
return DynObjectRef();
}
return DynObjectRef(handle, obj_ptr, &_G(globalDynamicStruct));
}
int ScriptUserObject::Dispose(void *address, bool /*force*/) {
delete[] (static_cast<uint8_t *>(address) - MemHeaderSz);
return 1;
}
size_t ScriptUserObject::CalcSerializeSize(const void *address) {
const Header &hdr = GetHeader(address);
return hdr.Size + FileHeaderSz;
}
void ScriptUserObject::Serialize(const void *address, AGS::Shared::Stream *out) {
const Header &hdr = GetHeader(address);
// NOTE: we only write the data, no header at the moment
out->Write(address, hdr.Size);
}
void ScriptUserObject::Unserialize(int index, Stream *in, size_t data_sz) {
uint8_t *new_data = new uint8_t[(data_sz - FileHeaderSz) + MemHeaderSz];
Header &hdr = reinterpret_cast<Header &>(*new_data);
hdr.Size = data_sz - FileHeaderSz;
in->Read(new_data + MemHeaderSz, data_sz - FileHeaderSz);
ccRegisterUnserializedObject(index, &new_data[MemHeaderSz], this);
}
// Allocates managed struct containing two ints: X and Y
ScriptUserObject *ScriptStructHelpers::CreatePoint(int x, int y) {
DynObjectRef ref = ScriptUserObject::Create(sizeof(int32_t) * 2);
ref.Mgr->WriteInt32(ref.Obj, 0, x);
ref.Mgr->WriteInt32(ref.Obj, sizeof(int32_t), y);
return static_cast<ScriptUserObject *>(ref.Obj);
}
} // namespace AGS3

View File

@@ -0,0 +1,86 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// ScriptUserObject is a dynamic (managed) struct manager.
//
//=============================================================================
#ifndef AGS_ENGINE_DYNOBJ__SCRIPTUSERSTRUCT_H
#define AGS_ENGINE_DYNOBJ__SCRIPTUSERSTRUCT_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
struct ScriptUserObject final : AGSCCDynamicObject {
public:
static const char *TypeName;
struct Header {
uint32_t Size = 0u;
// NOTE: we use signed int for Size at the moment, because the managed
// object interface's Serialize() function requires the object to return
// negative value of size in case the provided buffer was not large
// enough. Since this interface is also a part of Plugin API, we would
// need more significant change to program before we could use different
// approach.
};
ScriptUserObject() = default;
~ScriptUserObject() = default;
inline static const Header &GetHeader(const void *address) {
return reinterpret_cast<const Header &>(*(static_cast<const uint8_t *>(address) - MemHeaderSz));
}
// Create managed struct object and return a pointer to the beginning of a buffer
static DynObjectRef Create(size_t size);
// return the type name of the object
const char *GetType() override;
int Dispose(void *address, bool force) override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
private:
// The size of the array's header in memory, prepended to the element data
static const size_t MemHeaderSz = sizeof(Header);
// The size of the serialized header
static const size_t FileHeaderSz = sizeof(uint32_t) * 0; // no header serialized
// Savegame serialization
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
// Helper functions for setting up custom managed structs based on ScriptUserObject.
namespace ScriptStructHelpers {
// Creates a managed Point object, represented as a pair of X and Y coordinates.
ScriptUserObject *CreatePoint(int x, int y);
} // namespace ScriptStructHelpers
} // namespace AGS3
#endif

View File

@@ -0,0 +1,69 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_view_frame.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/shared/util/stream.h"
namespace AGS3 {
using namespace AGS::Shared;
int ScriptViewFrame::Dispose(void * /*address*/, bool force) {
// always dispose a ViewFrame
delete this;
return 1;
}
const char *ScriptViewFrame::GetType() {
return "ViewFrame";
}
size_t ScriptViewFrame::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t) * 3;
}
void ScriptViewFrame::Serialize(const void * /*address*/, Stream *out) {
out->WriteInt32(view);
out->WriteInt32(loop);
out->WriteInt32(frame);
}
void ScriptViewFrame::Unserialize(int index, Stream *in, size_t data_sz) {
view = in->ReadInt32();
loop = in->ReadInt32();
frame = in->ReadInt32();
ccRegisterUnserializedObject(index, this, this);
}
ScriptViewFrame::ScriptViewFrame(int p_view, int p_loop, int p_frame) {
view = p_view;
loop = p_loop;
frame = p_frame;
}
ScriptViewFrame::ScriptViewFrame() {
view = -1;
loop = -1;
frame = -1;
}
} // namespace AGS3

View File

@@ -0,0 +1,48 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPTVIEWFRAME_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPTVIEWFRAME_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
struct ScriptViewFrame final : AGSCCDynamicObject {
int view, loop, frame;
int Dispose(void *address, bool force) override;
const char *GetType() override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
ScriptViewFrame(int p_view, int p_loop, int p_frame);
ScriptViewFrame();
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
};
} // namespace AGS3
#endif

View File

@@ -0,0 +1,74 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/engine/ac/dynobj/script_viewport.h"
#include "ags/engine/ac/dynobj/dynobj_manager.h"
#include "ags/engine/ac/game_state.h"
#include "ags/shared/util/bbop.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
namespace AGS3 {
using namespace AGS::Shared;
ScriptViewport::ScriptViewport(int id) : _id(id) {
}
const char *ScriptViewport::GetType() {
return "Viewport2";
}
int ScriptViewport::Dispose(void * /*address*/, bool force) {
// Note that ScriptViewport is a reference to actual Viewport object,
// and this deletes the reference, while viewport may remain in GameState.
delete this;
return 1;
}
size_t ScriptViewport::CalcSerializeSize(const void * /*address*/) {
return sizeof(int32_t);
}
void ScriptViewport::Serialize(const void * /*address*/, Stream *out) {
out->WriteInt32(_id);
}
void ScriptViewport::Unserialize(int index, Stream *in, size_t data_sz) {
_id = in->ReadInt32();
ccRegisterUnserializedObject(index, this, this);
}
ScriptViewport *Viewport_Unserialize(int handle, Stream *in, size_t data_sz) {
// The way it works now, we must not create a new script object,
// but acquire one from the GameState, which keeps the first reference.
// This is essential because GameState should be able to invalidate any
// script references when Viewport gets removed.
const int id = in->ReadInt32();
if (id >= 0) {
auto scview = _GP(play).RegisterRoomViewport(id, handle);
if (scview)
return scview;
}
return new ScriptViewport(-1); // make invalid reference
}
} // namespace AGS3

View File

@@ -0,0 +1,64 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_ENGINE_AC_DYNOBJ_SCRIPT_VIEWPORT_H
#define AGS_ENGINE_AC_DYNOBJ_SCRIPT_VIEWPORT_H
#include "ags/engine/ac/dynobj/cc_ags_dynamic_object.h"
namespace AGS3 {
// ScriptViewport keeps a reference to actual room Viewport in script.
struct ScriptViewport final : AGSCCDynamicObject {
public:
ScriptViewport(int id);
// Get viewport index; negative means the viewport was deleted
int GetID() const {
return _id;
}
void SetID(int id) {
_id = id;
}
// Reset viewport index to indicate that this reference is no longer valid
void Invalidate() {
_id = -1;
}
const char *GetType() override;
int Dispose(void *address, bool force) override;
void Unserialize(int index, AGS::Shared::Stream *in, size_t data_sz) override;
protected:
// Calculate and return required space for serialization, in bytes
size_t CalcSerializeSize(const void *address) override;
// Write object data into the provided stream
void Serialize(const void *address, AGS::Shared::Stream *out) override;
private:
int _id = -1; // index of viewport in the game state array
};
// Unserialize viewport from the memory stream
ScriptViewport *Viewport_Unserialize(int handle, AGS::Shared::Stream *in, size_t data_sz);
} // namespace AGS3
#endif