Files
scummvm/engines/sci/engine/object.h
T
Filippos Karapetis 941869c466 SCI32: Remove reg32_t and use reg_t in all cases
reg32_t was a transitive solution, before reg_t's were
adapted to use 32-bit addresses internally, and before
support for SCI3 was added. It was introduced as another
way to handle large script offsets in SCI3, and was only
used for the program counter (PC). It's no longer
needed, as we now support SCI3 script offsets using
reg_t's, so we can use make_reg32 in all cases where
we need to access offsets over 64KB
2018-08-25 12:39:12 +03:00

383 lines
10 KiB
C++

/* 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);
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);
void initSuperClass(SegManager *segMan, reg_t addr);
bool initBaseObject(SegManager *segMan, reg_t addr, bool doInitSuperClass = 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