1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
|
/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef SCI_ENGINE_OBJECT_H
#define SCI_ENGINE_OBJECT_H
#include "common/array.h"
#include "common/serializer.h"
#include "common/textconsole.h"
#include "sci/sci.h" // for the SCI versions
#include "sci/engine/vm_types.h" // for reg_t
#include "sci/util.h"
namespace Sci {
class SegManager;
class Script;
enum infoSelectorFlags {
kInfoFlagClone = 0x0001,
#ifdef ENABLE_SCI32
/**
* When set, indicates to game scripts that a screen
* item can be updated.
*/
kInfoFlagViewVisible = 0x0008,
/**
* When set, the VM object has an associated ScreenItem in
* the rendering tree.
*/
kInfoFlagViewInserted = 0x0010,
#endif
kInfoFlagClass = 0x8000
};
enum ObjectOffsets {
kOffsetHeaderSize = 6,
kOffsetHeaderLocalVariables = 0,
kOffsetHeaderFunctionArea = 2,
kOffsetHeaderSelectorCounter = 4,
kOffsetSelectorSegment = 0,
kOffsetInfoSelectorSci0 = 4,
kOffsetNamePointerSci0 = 6,
kOffsetInfoSelectorSci11 = 14,
kOffsetNamePointerSci11 = 16
};
class Object : public Common::Serializable {
public:
Object() :
_name(NULL_REG),
_offset(getSciVersion() < SCI_VERSION_1_1 ? 0 : 5),
_isFreed(false),
_baseObj(),
_baseVars(),
_methodCount(0)
#ifdef ENABLE_SCI32
,
_propertyOffsetsSci3()
#endif
{}
Object &operator=(const Object &other) {
_name = other._name;
_baseObj = other._baseObj;
_baseMethod = other._baseMethod;
_variables = other._variables;
_methodCount = other._methodCount;
_isFreed = other._isFreed;
_offset = other._offset;
_pos = other._pos;
_baseVars = other._baseVars;
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3) {
_propertyOffsetsSci3 = other._propertyOffsetsSci3;
_superClassPosSci3 = other._superClassPosSci3;
_speciesSelectorSci3 = other._speciesSelectorSci3;
_infoSelectorSci3 = other._infoSelectorSci3;
_mustSetViewVisible = other._mustSetViewVisible;
}
#endif
return *this;
}
reg_t getSpeciesSelector() const {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
return _speciesSelectorSci3;
else
#endif
return _variables[_offset];
}
void setSpeciesSelector(reg_t value) {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
_speciesSelectorSci3 = value;
else
#endif
_variables[_offset] = value;
}
reg_t getSuperClassSelector() const {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
return _superClassPosSci3;
else
#endif
return _variables[_offset + 1];
}
void setSuperClassSelector(reg_t value) {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
_superClassPosSci3 = value;
else
#endif
_variables[_offset + 1] = value;
}
reg_t getInfoSelector() const {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
return _infoSelectorSci3;
else
#endif
return _variables[_offset + 2];
}
void setInfoSelector(reg_t info) {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
_infoSelectorSci3 = info;
else
#endif
_variables[_offset + 2] = info;
}
#ifdef ENABLE_SCI32
void setInfoSelectorFlag(infoSelectorFlags flag) {
if (getSciVersion() == SCI_VERSION_3) {
_infoSelectorSci3 |= flag;
} else {
_variables[_offset + 2] |= flag;
}
}
void clearInfoSelectorFlag(infoSelectorFlags flag) {
if (getSciVersion() == SCI_VERSION_3) {
_infoSelectorSci3 &= ~flag;
} else {
_variables[_offset + 2] &= ~flag;
}
}
bool isInserted() const {
return getInfoSelector().toUint16() & kInfoFlagViewInserted;
}
#endif
reg_t getNameSelector() const {
return _name;
}
// No setter for the name selector
reg_t getPropDictSelector() const {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
// This should never occur, this is called from a SCI1.1 - SCI2.1 only function
error("getPropDictSelector called for SCI3");
else
#endif
return _variables[2];
}
void setPropDictSelector(reg_t value) {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
// This should never occur, this is called from a SCI1.1 - SCI2.1 only function
error("setPropDictSelector called for SCI3");
else
#endif
_variables[2] = value;
}
reg_t getClassScriptSelector() const {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
return make_reg(0, _baseObj.getUint16SEAt(6));
else
#endif
return _variables[4];
}
void setClassScriptSelector(reg_t value) {
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3)
// This should never occur, this is called from a SCI1.1 - SCI2.1 only function
error("setClassScriptSelector called for SCI3");
else
#endif
_variables[4] = value;
}
Selector getVarSelector(uint16 i) const { return _baseVars[i]; }
/**
* @returns A pointer to the code for the method at the given index.
*/
reg_t getFunction(const uint16 index) const {
return make_reg32(_pos.getSegment(), _baseMethod[index * 2 + 1]);
}
/**
* @returns The selector for the method at the given index.
*/
Selector getFuncSelector(const uint16 index) const {
return _baseMethod[index * 2];
}
/**
* Determines if this object is a class and explicitly defines the
* selector as a funcselector. Does NOT say anything about the object's
* superclasses, i.e. failure may be returned even if one of the
* superclasses defines the funcselector
*/
int funcSelectorPosition(Selector sel) const {
for (uint i = 0; i < _methodCount; i++)
if (getFuncSelector(i) == sel)
return i;
return -1;
}
/**
* Determines if the object explicitly defines slc as a varselector.
* Returns -1 if not found.
*/
int locateVarSelector(SegManager *segMan, Selector slc) const;
bool isClass() const { return (getInfoSelector().getOffset() & kInfoFlagClass); }
const Object *getClass(SegManager *segMan) const;
void markAsFreed() { _isFreed = true; }
bool isFreed() const { return _isFreed; }
uint getVarCount() const { return _variables.size(); }
void init(const Script &owner, reg_t obj_pos, bool initVariables = true);
reg_t getVariable(uint var) const { return _variables[var]; }
reg_t &getVariableRef(uint var) { return _variables[var]; }
uint16 getMethodCount() const { return _methodCount; }
reg_t getPos() const { return _pos; }
void saveLoadWithSerializer(Common::Serializer &ser) override;
void cloneFromObject(const Object *obj) {
_name = obj ? obj->_name : NULL_REG;
_baseObj = obj ? obj->_baseObj : SciSpan<const byte>();
_baseMethod = obj ? obj->_baseMethod : Common::Array<uint32>();
_baseVars = obj ? obj->_baseVars : Common::Array<uint16>();
#ifdef ENABLE_SCI32
if (getSciVersion() == SCI_VERSION_3) {
_mustSetViewVisible = obj ? obj->_mustSetViewVisible : Common::Array<bool>();
}
#endif
}
bool relocateSci0Sci21(SegmentId segment, int location, uint32 heapOffset);
#ifdef ENABLE_SCI32
bool relocateSci3(SegmentId segment, uint32 location, int offset, uint32 scriptSize);
#endif
int propertyOffsetToId(SegManager *segMan, int propertyOffset) const;
void initSpecies(SegManager *segMan, reg_t addr, bool applyScriptPatches);
void initSuperClass(SegManager *segMan, reg_t addr, bool applyScriptPatches);
bool initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass = true, bool applyScriptPatches = true);
#ifdef ENABLE_SCI32
bool mustSetViewVisible(const int index, const bool fromPropertyOp) const;
#endif
private:
#ifdef ENABLE_SCI32
void initSelectorsSci3(const SciSpan<const byte> &buf, const bool initVariables);
#endif
/**
* The name of the object.
*/
reg_t _name;
/**
* A pointer to the raw object data within the object's owner script.
*/
SciSpan<const byte> _baseObj;
/**
* A lookup table from a property index to its corresponding selector
* number.
*/
Common::Array<uint16> _baseVars;
/**
* A lookup table from a method index to its corresponding selector number
* or offset to code. The table contains selector + offset in pairs.
*/
Common::Array<uint32> _baseMethod;
/**
* A lookup table from a property index to the property's current value.
*/
Common::Array<reg_t> _variables;
#ifdef ENABLE_SCI32
/**
* A lookup table from a property index to the property's original absolute
* offset within the raw script data. This absolute offset is coded into the
* script's relocation table, and is used to look up 32-bit values for
* properties in the relocation table (which is used to break the 16-bit
* barrier, since the script format still only holds 16-bit values inline).
*/
Common::Array<uint32> _propertyOffsetsSci3;
#endif
/**
* The number of methods on the object.
*/
uint16 _methodCount;
/**
* Whether or not a clone object has been marked as 'freed'.
*/
bool _isFreed;
/**
* For SCI0 through SCI2.1, an extra index offset used when looking up
* special object properties -species-, -super-, -info-, and name.
*/
uint16 _offset;
reg_t _pos; /**< Object offset within its script; for clones, this is their base */
#ifdef ENABLE_SCI32
reg_t _superClassPosSci3; /**< reg_t pointing to superclass for SCI3 */
reg_t _speciesSelectorSci3; /**< reg_t containing species "selector" for SCI3 */
reg_t _infoSelectorSci3; /**< reg_t containing info "selector" for SCI3 */
Common::Array<bool> _mustSetViewVisible; /** cached bit of info to make lookup fast, SCI3 only */
#endif
};
} // End of namespace Sci
#endif // SCI_ENGINE_OBJECT_H
|