2009-06-04 11:45:17 +00:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-09-17 13:22:46 +00:00
|
|
|
#ifndef SCI_ENGINE_SEGMENT_H
|
|
|
|
#define SCI_ENGINE_SEGMENT_H
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
#include "common/serializer.h"
|
2009-08-17 07:36:08 +00:00
|
|
|
#include "sci/engine/vm.h"
|
2009-06-04 11:45:17 +00:00
|
|
|
#include "sci/engine/vm_types.h" // for reg_t
|
|
|
|
|
|
|
|
//#include "common/util.h"
|
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
2009-09-17 00:45:12 +00:00
|
|
|
enum SegmentType {
|
|
|
|
SEG_TYPE_INVALID = 0,
|
|
|
|
SEG_TYPE_SCRIPT = 1,
|
|
|
|
SEG_TYPE_CLONES = 2,
|
|
|
|
SEG_TYPE_LOCALS = 3,
|
|
|
|
SEG_TYPE_STACK = 4,
|
|
|
|
SEG_TYPE_SYS_STRINGS = 5,
|
|
|
|
SEG_TYPE_LISTS = 6,
|
|
|
|
SEG_TYPE_NODES = 7,
|
|
|
|
SEG_TYPE_HUNK = 8,
|
|
|
|
SEG_TYPE_DYNMEM = 9,
|
|
|
|
SEG_TYPE_STRING_FRAG = 10,
|
|
|
|
|
|
|
|
SEG_TYPE_MAX // For sanity checking
|
2009-06-04 11:45:17 +00:00
|
|
|
};
|
|
|
|
|
2009-09-17 00:45:12 +00:00
|
|
|
struct SegmentObj : public Common::Serializable {
|
|
|
|
SegmentType _type;
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
|
|
|
|
|
|
|
|
public:
|
2009-09-17 00:45:12 +00:00
|
|
|
static SegmentObj *createSegmentObj(SegmentType type);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
public:
|
2009-09-17 00:45:12 +00:00
|
|
|
virtual ~SegmentObj() {}
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-09-17 00:45:12 +00:00
|
|
|
inline SegmentType getType() const { return _type; }
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
/**
|
|
|
|
* Check whether the given offset into this memory object is valid,
|
|
|
|
* i.e., suitable for passing to dereference.
|
|
|
|
*/
|
|
|
|
virtual bool isValidOffset(uint16 offset) const = 0;
|
|
|
|
|
2009-06-04 11:45:17 +00:00
|
|
|
/**
|
|
|
|
* Dereferences a raw memory pointer.
|
2009-06-04 20:51:40 +00:00
|
|
|
* @param reg reference to dereference
|
|
|
|
* @param size if not NULL, set to the theoretical maximum size of the referenced data block
|
|
|
|
* @return the data block referenced
|
2009-06-04 11:45:17 +00:00
|
|
|
*/
|
|
|
|
virtual byte *dereference(reg_t pointer, int *size);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Finds the canonic address associated with sub_reg.
|
|
|
|
*
|
|
|
|
* For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)).
|
|
|
|
* This address "governs" a in the sense that deallocating c(a) will deallocate a.
|
|
|
|
*
|
|
|
|
* @param sub_addr base address whose canonic address is to be found
|
|
|
|
*/
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) { return sub_addr; }
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Deallocates all memory associated with the specified address.
|
|
|
|
* @param sub_addr address (within the given segment) to deallocate
|
|
|
|
*/
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {}
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterates over and reports all addresses within the current segment.
|
|
|
|
* @param note Invoked for each address on which free_at_address() makes sense
|
|
|
|
* @param param parameter passed to 'note'
|
|
|
|
*/
|
|
|
|
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterates over all references reachable from the specified object.
|
|
|
|
* @param object object (within the current segment) to analyse
|
|
|
|
* @param param parameter passed to 'note'
|
|
|
|
* @param note Invoked for each outgoing reference within the object
|
|
|
|
* Note: This function may also choose to report numbers (segment 0) as adresses
|
|
|
|
*/
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) {}
|
2009-06-04 11:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Implement the following class
|
2009-09-17 00:45:12 +00:00
|
|
|
struct StringFrag : public SegmentObj {
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const { return false; }
|
|
|
|
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IntMapper;
|
|
|
|
|
|
|
|
enum {
|
|
|
|
SYS_STRINGS_MAX = 4,
|
|
|
|
|
|
|
|
SYS_STRING_SAVEDIR = 0,
|
|
|
|
SYS_STRING_PARSER_BASE = 1,
|
|
|
|
|
|
|
|
MAX_PARSER_BASE = 64
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SystemString {
|
|
|
|
char *name;
|
|
|
|
int max_size;
|
|
|
|
reg_t *value;
|
|
|
|
};
|
|
|
|
|
2009-09-17 00:45:12 +00:00
|
|
|
struct SystemStrings : public SegmentObj {
|
2009-06-04 11:45:17 +00:00
|
|
|
SystemString strings[SYS_STRINGS_MAX];
|
|
|
|
|
|
|
|
public:
|
|
|
|
SystemStrings() {
|
|
|
|
memset(strings, 0, sizeof(strings));
|
|
|
|
}
|
|
|
|
~SystemStrings() {
|
|
|
|
for (int i = 0; i < SYS_STRINGS_MAX; i++) {
|
|
|
|
SystemString *str = &strings[i];
|
|
|
|
if (str->name) {
|
|
|
|
free(str->name);
|
|
|
|
str->name = NULL;
|
|
|
|
|
|
|
|
free(str->value);
|
|
|
|
str->value = NULL;
|
|
|
|
|
|
|
|
str->max_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const;
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual byte *dereference(reg_t pointer, int *size);
|
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
2009-09-17 00:45:12 +00:00
|
|
|
struct LocalVariables : public SegmentObj {
|
2009-06-04 11:45:17 +00:00
|
|
|
int script_id; /**< Script ID this local variable block belongs to */
|
|
|
|
Common::Array<reg_t> _locals;
|
|
|
|
|
|
|
|
public:
|
|
|
|
LocalVariables() {
|
|
|
|
script_id = 0;
|
|
|
|
}
|
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const;
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual byte *dereference(reg_t pointer, int *size);
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Clone has been marked as 'freed' */
|
|
|
|
#define OBJECT_FLAG_FREED (0x1 << 0)
|
|
|
|
|
2009-09-17 08:51:38 +00:00
|
|
|
// TODO: convert to class, perhaps?
|
2009-06-04 11:45:17 +00:00
|
|
|
struct Object {
|
2009-09-21 21:35:43 +00:00
|
|
|
int _flags;
|
|
|
|
reg_t _pos; /**< Object offset within its script; for clones, this is their base */
|
2009-06-04 11:45:17 +00:00
|
|
|
int variable_names_nr; /**< Number of variable names, may be less than variables_nr */
|
|
|
|
int methods_nr;
|
|
|
|
byte *base; /**< Points to a buffer all relative references (code, strings) point to */
|
|
|
|
byte *base_obj; /**< base + object offset within base */
|
|
|
|
uint16 *base_method; /**< Pointer to the method selector area for this object */
|
|
|
|
uint16 *base_vars; /**< Pointer to the varselector area for this object */
|
|
|
|
Common::Array<reg_t> _variables;
|
2009-09-17 08:51:38 +00:00
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
uint16 getVarSelector(uint16 i) {
|
|
|
|
if (getSciVersion() < SCI_VERSION_1_1)
|
2009-09-17 08:51:38 +00:00
|
|
|
return READ_LE_UINT16(base_obj + _variables.size() * 2 + i * 2);
|
|
|
|
else
|
|
|
|
return *(base_vars + i);
|
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
reg_t getSpeciesSelector() {
|
|
|
|
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 0 : 5];
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
void setSpeciesSelector(reg_t value) {
|
|
|
|
_variables[getSciVersion() < SCI_VERSION_1_1 ? 0 : 5] = value;
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
reg_t getSuperClassSelector() {
|
|
|
|
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 1 : 6];
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
void setSuperClassSelector(reg_t value) {
|
|
|
|
_variables[getSciVersion() < SCI_VERSION_1_1 ? 1 : 6] = value;
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
reg_t getInfoSelector() {
|
|
|
|
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 2 : 7];
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
void setInfoSelector(reg_t value) {
|
|
|
|
_variables[getSciVersion() < SCI_VERSION_1_1 ? 2 : 7] = value;
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
reg_t getNameSelector() {
|
|
|
|
return _variables[getSciVersion() < SCI_VERSION_1_1 ? 3 : 8];
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
void setNameSelector(reg_t value) {
|
|
|
|
_variables[getSciVersion() < SCI_VERSION_1_1 ? 3 : 8] = value;
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
reg_t getClassScriptSelector() {
|
|
|
|
return _variables[4];
|
|
|
|
}
|
|
|
|
|
|
|
|
void setClassScriptSelector(reg_t value) {
|
|
|
|
_variables[4] = value;
|
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
uint16 getFuncSelector(uint16 i) {
|
|
|
|
uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? i : i * 2 + 1;
|
2009-09-17 08:51:38 +00:00
|
|
|
return READ_LE_UINT16((byte *) (base_method + offset));
|
|
|
|
}
|
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
reg_t getFunction(uint16 i) {
|
|
|
|
uint16 offset = (getSciVersion() < SCI_VERSION_1_1) ? methods_nr + 1 + i : i * 2 + 2;
|
2009-09-21 21:35:43 +00:00
|
|
|
return make_reg(_pos.segment, READ_LE_UINT16((byte *) (base_method + offset)));
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
2009-09-17 13:22:46 +00:00
|
|
|
|
2009-09-17 16:50:53 +00:00
|
|
|
bool isClass() {
|
|
|
|
return (getInfoSelector().offset & SCRIPT_INFO_CLASS);
|
2009-09-17 08:51:38 +00:00
|
|
|
}
|
2009-06-04 11:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CodeBlock {
|
|
|
|
reg_t pos;
|
|
|
|
int size;
|
|
|
|
};
|
|
|
|
|
2009-09-17 00:45:12 +00:00
|
|
|
class Script : public SegmentObj {
|
2009-09-16 23:32:27 +00:00
|
|
|
public:
|
|
|
|
int _nr; /**< Script number */
|
|
|
|
byte *_buf; /**< Static data buffer, or NULL if not used */
|
|
|
|
size_t _bufSize;
|
|
|
|
size_t _scriptSize;
|
|
|
|
size_t _heapSize;
|
|
|
|
|
|
|
|
byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */
|
|
|
|
|
|
|
|
uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */
|
|
|
|
int _numExports; /**< Number of entries in the exports table */
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-09-16 23:32:27 +00:00
|
|
|
byte *_synonyms; /**< Synonyms block or 0 if not present*/
|
|
|
|
int _numSynonyms; /**< Number of entries in the synonyms block */
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-09-06 13:01:00 +00:00
|
|
|
protected:
|
2009-09-16 23:32:27 +00:00
|
|
|
int _lockers; /**< Number of classes and objects that require this script */
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-09-16 23:32:27 +00:00
|
|
|
IntMapper *_objIndices;
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-09-16 23:32:27 +00:00
|
|
|
public:
|
2009-06-04 11:45:17 +00:00
|
|
|
/**
|
|
|
|
* Table for objects, contains property variables.
|
|
|
|
* Indexed by the value stored at SCRIPT_LOCALVARPTR_OFFSET,
|
|
|
|
* see VM_OBJECT_[GS]ET_INDEX()
|
|
|
|
*/
|
|
|
|
Common::Array<Object> _objects;
|
|
|
|
|
2009-09-16 23:32:27 +00:00
|
|
|
int _localsOffset;
|
2009-09-17 00:46:01 +00:00
|
|
|
SegmentId _localsSegment; /**< The local variable segment */
|
2009-09-16 23:32:27 +00:00
|
|
|
LocalVariables *_localsBlock;
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
Common::Array<CodeBlock> _codeBlocks;
|
2009-09-16 23:32:27 +00:00
|
|
|
bool _relocated;
|
2009-06-04 11:45:17 +00:00
|
|
|
bool _markedAsDeleted;
|
|
|
|
|
|
|
|
public:
|
2009-09-16 23:32:27 +00:00
|
|
|
Script();
|
|
|
|
~Script();
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
void freeScript();
|
2009-09-16 23:32:48 +00:00
|
|
|
bool init(int script_nr, ResourceManager *resMan);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const;
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual byte *dereference(reg_t pointer, int *size);
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
|
|
|
|
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
|
2009-09-06 13:01:00 +00:00
|
|
|
Object *allocateObject(uint16 offset);
|
|
|
|
Object *getObject(uint16 offset);
|
|
|
|
|
2009-09-16 23:32:48 +00:00
|
|
|
/**
|
|
|
|
* Informs the segment manager that a code block must be relocated
|
|
|
|
* @param location Start of block to relocate
|
|
|
|
*/
|
|
|
|
void scriptAddCodeBlock(reg_t location);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes an object within the segment manager
|
|
|
|
* @param obj_pos Location (segment, offset) of the object. It must
|
|
|
|
* point to the beginning of the script/class block
|
|
|
|
* (as opposed to what the VM considers to be the
|
|
|
|
* object location)
|
|
|
|
* @returns A newly created Object describing the object,
|
|
|
|
* stored within the relevant script
|
|
|
|
*/
|
|
|
|
Object *scriptObjInit(reg_t obj_pos);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Processes a relocation block witin a script
|
|
|
|
* This function is idempotent, but it must only be called after all
|
|
|
|
* objects have been instantiated, or a run-time error will occur.
|
|
|
|
* @param obj_pos Location (segment, offset) of the block
|
|
|
|
* @return Location of the relocation block
|
|
|
|
*/
|
|
|
|
void scriptRelocate(reg_t block);
|
|
|
|
|
|
|
|
void heapRelocate(reg_t block);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int relocateLocal(SegmentId segment, int location);
|
|
|
|
int relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location);
|
|
|
|
int relocateObject(Object *obj, SegmentId segment, int location);
|
|
|
|
|
|
|
|
Object *scriptObjInit0(reg_t obj_pos);
|
|
|
|
Object *scriptObjInit11(reg_t obj_pos);
|
|
|
|
|
|
|
|
public:
|
2009-06-04 11:45:17 +00:00
|
|
|
// script lock operations
|
|
|
|
|
|
|
|
/** Increments the number of lockers of this script by one. */
|
|
|
|
void incrementLockers();
|
|
|
|
|
|
|
|
/** Decrements the number of lockers of this script by one. */
|
|
|
|
void decrementLockers();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves the number of locks held on this script.
|
|
|
|
* @return the number of locks held on the previously identified script
|
|
|
|
*/
|
|
|
|
int getLockers() const;
|
|
|
|
|
|
|
|
/** Sets the number of locks held on this script. */
|
|
|
|
void setLockers(int lockers);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves a pointer to the synonyms associated with this script
|
|
|
|
* @return pointer to the synonyms, in non-parsed format.
|
|
|
|
*/
|
|
|
|
byte *getSynonyms() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves the number of synonyms associated with this script.
|
|
|
|
* @return the number of synonyms associated with this script
|
|
|
|
*/
|
|
|
|
int getSynonymsNr() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the script-relative offset of the exports table.
|
|
|
|
* @param offset script-relative exports table offset
|
|
|
|
*/
|
|
|
|
void setExportTableOffset(int offset);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the script-relative offset of the synonyms associated with this script.
|
|
|
|
* @param offset script-relative offset of the synonyms block
|
|
|
|
*/
|
|
|
|
void setSynonymsOffset(int offset);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the number of synonyms associated with this script,
|
|
|
|
* @param nr number of synonyms, as to be stored within the script
|
|
|
|
*/
|
|
|
|
void setSynonymsNr(int nr);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Marks the script as deleted.
|
|
|
|
* This will not actually delete the script. If references remain present on the
|
|
|
|
* heap or the stack, the script will stay in memory in a quasi-deleted state until
|
|
|
|
* either unreachable (resulting in its eventual deletion) or reloaded (resulting
|
|
|
|
* in its data being updated).
|
|
|
|
*/
|
|
|
|
void markDeleted() {
|
|
|
|
_markedAsDeleted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Marks the script as not deleted.
|
|
|
|
*/
|
|
|
|
void unmarkDeleted() {
|
|
|
|
_markedAsDeleted = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines whether the script is marked as being deleted.
|
|
|
|
*/
|
|
|
|
bool isMarkedAsDeleted() const {
|
|
|
|
return _markedAsDeleted;
|
|
|
|
}
|
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
/**
|
|
|
|
* Copies a byte string into a script's heap representation.
|
|
|
|
* @param dst script-relative offset of the destination area
|
|
|
|
* @param src pointer to the data source location
|
|
|
|
* @param n number of bytes to copy
|
|
|
|
*/
|
|
|
|
void mcpyInOut(int dst, const void *src, size_t n);
|
|
|
|
|
|
|
|
|
2009-06-04 11:45:17 +00:00
|
|
|
/**
|
|
|
|
* Retrieves a 16 bit value from within a script's heap representation.
|
|
|
|
* @param offset offset to read from
|
|
|
|
* @return the value read from the specified location
|
|
|
|
*/
|
|
|
|
int16 getHeap(uint16 offset) const;
|
2009-09-16 23:32:48 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
void setScriptSize(int script_nr, ResourceManager *resMan);
|
2009-06-04 11:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/** Data stack */
|
2009-09-17 00:45:12 +00:00
|
|
|
struct DataStack : SegmentObj {
|
2009-06-04 11:45:17 +00:00
|
|
|
int nr; /**< Number of stack entries */
|
|
|
|
reg_t *entries;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DataStack() {
|
|
|
|
nr = 0;
|
|
|
|
entries = NULL;
|
|
|
|
}
|
|
|
|
~DataStack() {
|
|
|
|
free(entries);
|
|
|
|
entries = NULL;
|
|
|
|
}
|
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const;
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual byte *dereference(reg_t pointer, int *size);
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
#define CLONE_USED -1
|
|
|
|
#define CLONE_NONE -1
|
|
|
|
|
|
|
|
typedef Object Clone;
|
|
|
|
|
|
|
|
struct Node {
|
|
|
|
reg_t pred; /**< Predecessor node */
|
|
|
|
reg_t succ; /**< Successor node */
|
|
|
|
reg_t key;
|
|
|
|
reg_t value;
|
|
|
|
}; /* List nodes */
|
|
|
|
|
|
|
|
struct List {
|
|
|
|
reg_t first;
|
|
|
|
reg_t last;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Hunk {
|
|
|
|
void *mem;
|
|
|
|
unsigned int size;
|
|
|
|
const char *type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
2009-09-17 00:45:12 +00:00
|
|
|
struct Table : public SegmentObj {
|
2009-06-04 11:45:17 +00:00
|
|
|
typedef T value_type;
|
|
|
|
struct Entry : public T {
|
|
|
|
int next_free; /* Only used for free entries */
|
|
|
|
};
|
|
|
|
enum { HEAPENTRY_INVALID = -1 };
|
|
|
|
|
|
|
|
|
|
|
|
int first_free; /**< Beginning of a singly linked list for entries */
|
|
|
|
int entries_used; /**< Statistical information */
|
|
|
|
|
|
|
|
Common::Array<Entry> _table;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Table() {
|
|
|
|
initTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
void initTable() {
|
|
|
|
entries_used = 0;
|
|
|
|
first_free = HEAPENTRY_INVALID;
|
|
|
|
_table.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
int allocEntry() {
|
|
|
|
entries_used++;
|
|
|
|
if (first_free != HEAPENTRY_INVALID) {
|
|
|
|
int oldff = first_free;
|
|
|
|
first_free = _table[oldff].next_free;
|
|
|
|
|
|
|
|
_table[oldff].next_free = oldff;
|
|
|
|
return oldff;
|
|
|
|
} else {
|
|
|
|
uint newIdx = _table.size();
|
|
|
|
_table.push_back(Entry());
|
|
|
|
_table[newIdx].next_free = newIdx; // Tag as 'valid'
|
|
|
|
return newIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const {
|
|
|
|
return isValidEntry(offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isValidEntry(int idx) const {
|
2009-06-04 11:45:17 +00:00
|
|
|
return idx >= 0 && (uint)idx < _table.size() && _table[idx].next_free == idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void freeEntry(int idx) {
|
|
|
|
if (idx < 0 || (uint)idx >= _table.size())
|
|
|
|
::error("Table::freeEntry: Attempt to release invalid table index %d", idx);
|
|
|
|
|
|
|
|
_table[idx].next_free = first_free;
|
|
|
|
first_free = idx;
|
|
|
|
entries_used--;
|
|
|
|
}
|
|
|
|
|
2009-06-13 13:27:21 +00:00
|
|
|
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
|
|
|
|
for (uint i = 0; i < _table.size(); i++)
|
|
|
|
if (isValidEntry(i))
|
|
|
|
(*note)(param, make_reg(segId, i));
|
|
|
|
}
|
2009-06-04 11:45:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* CloneTable */
|
|
|
|
struct CloneTable : public Table<Clone> {
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* NodeTable */
|
|
|
|
struct NodeTable : public Table<Node> {
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* ListTable */
|
|
|
|
struct ListTable : public Table<List> {
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
|
2009-09-17 16:50:53 +00:00
|
|
|
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note);
|
2009-06-04 11:45:17 +00:00
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* HunkTable */
|
|
|
|
struct HunkTable : public Table<Hunk> {
|
|
|
|
virtual void freeEntry(int idx) {
|
|
|
|
Table<Hunk>::freeEntry(idx);
|
|
|
|
|
|
|
|
free(_table[idx].mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Free-style memory
|
2009-09-17 00:45:12 +00:00
|
|
|
struct DynMem : public SegmentObj {
|
2009-06-04 11:45:17 +00:00
|
|
|
int _size;
|
2009-09-14 22:34:53 +00:00
|
|
|
Common::String _description;
|
2009-06-04 11:45:17 +00:00
|
|
|
byte *_buf;
|
|
|
|
|
|
|
|
public:
|
2009-09-14 22:34:53 +00:00
|
|
|
DynMem() : _size(0), _buf(0) {}
|
2009-06-04 11:45:17 +00:00
|
|
|
~DynMem() {
|
|
|
|
free(_buf);
|
|
|
|
_buf = NULL;
|
|
|
|
}
|
|
|
|
|
2009-06-04 20:51:40 +00:00
|
|
|
virtual bool isValidOffset(uint16 offset) const;
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual byte *dereference(reg_t pointer, int *size);
|
2009-09-06 12:57:42 +00:00
|
|
|
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
|
2009-06-04 11:45:17 +00:00
|
|
|
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
|
|
|
|
|
|
|
|
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} // End of namespace Sci
|
|
|
|
|
2009-09-17 13:22:46 +00:00
|
|
|
#endif // SCI_ENGINE_SEGMENT_H
|