scummvm/engines/sci/engine/script.h

256 lines
7.8 KiB
C
Raw Normal View History

/* 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$
*
*/
#ifndef SCI_ENGINE_SCRIPT_H
#define SCI_ENGINE_SCRIPT_H
2009-02-25 02:05:43 +00:00
#include "common/str.h"
#include "sci/engine/segment.h"
namespace Sci {
2009-02-25 02:05:43 +00:00
struct EngineState;
class ResourceManager;
2009-02-25 02:05:43 +00:00
#define SCI_SCRIPTS_NR 1000
enum ScriptObjectTypes {
SCI_OBJ_TERMINATOR,
SCI_OBJ_OBJECT,
SCI_OBJ_CODE,
SCI_OBJ_SYNONYMS,
SCI_OBJ_SAID,
SCI_OBJ_STRINGS,
SCI_OBJ_CLASS,
SCI_OBJ_EXPORTS,
SCI_OBJ_POINTERS,
SCI_OBJ_PRELOAD_TEXT, /* This is really just a flag. */
SCI_OBJ_LOCALVARS
};
typedef Common::HashMap<uint16, Object> ObjMap;
class Script : public SegmentObj {
public:
int _nr; /**< Script number */
byte *_buf; /**< Static data buffer, or NULL if not used */
byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */
uint32 getScriptSize() { return _scriptSize; }
uint32 getHeapSize() { return _heapSize; }
uint32 getBufSize() { return _bufSize; }
protected:
int _lockers; /**< Number of classes and objects that require this script */
private:
size_t _scriptSize;
size_t _heapSize;
uint16 _bufSize;
const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */
uint16 _numExports; /**< Number of entries in the exports table */
const byte *_synonyms; /**< Synonyms block or 0 if not present*/
uint16 _numSynonyms; /**< Number of entries in the synonyms block */
int _localsOffset;
uint16 _localsCount;
public:
/**
* Table for objects, contains property variables.
* Indexed by the TODO offset.
*/
ObjMap _objects;
int getLocalsOffset() const { return _localsOffset; }
uint16 getLocalsCount() const { return _localsCount; }
SegmentId _localsSegment; /**< The local variable segment */
LocalVariables *_localsBlock;
bool _markedAsDeleted;
public:
Script();
~Script();
void freeScript();
void init(int script_nr, ResourceManager *resMan);
void load(ResourceManager *resMan);
virtual bool isValidOffset(uint16 offset) const;
virtual SegmentRef dereference(reg_t pointer);
virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const;
virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const;
virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
Object *allocateObject(uint16 offset);
Object *getObject(uint16 offset);
const Object *getObject(uint16 offset) const;
/**
* 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, bool fullObjectInit = true);
/**
* Removes a script object
* @param obj_pos Location (segment, offset) of the object.
*/
void scriptObjRemove(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 relocate(reg_t block);
private:
bool relocateLocal(SegmentId segment, int location);
public:
// 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 exports of this script
* @return pointer to the exports.
*/
const uint16 *getExportTable() const { return _exportTable; }
/**
* Retrieves the number of exports of script.
* @return the number of exports of this script
*/
uint16 getExportsNr() const { return _numExports; }
/**
* Retrieves a pointer to the synonyms associated with this script
* @return pointer to the synonyms, in non-parsed format.
*/
const byte *getSynonyms() const { return _synonyms; }
/**
* Retrieves the number of synonyms associated with this script.
* @return the number of synonyms associated with this script
*/
uint16 getSynonymsNr() const { return _numSynonyms; }
/**
* Validate whether the specified public function is exported by
* the script in the specified segment.
* @param pubfunct Index of the function to validate
* @return NULL if the public function is invalid, its
* offset into the script's segment otherwise
*/
uint16 validateExportFunc(int pubfunct);
/**
* 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;
}
/**
* Determines whether the script is marked as being deleted.
*/
bool isMarkedAsDeleted() const {
return _markedAsDeleted;
}
/**
* 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);
/**
* Finds the pointer where a block of a specific type starts from
*/
byte *findBlock(int type);
};
/**
* Makes sure that a script and its superclasses get loaded to the heap.
* If the script already has been loaded, only the number of lockers is
* increased. All scripts containing superclasses of this script are loaded
* recursively as well, unless 'recursive' is set to zero. The
* complementary function is "script_uninstantiate()" below.
* @param[in] resMan The resource manager
* @param[in] segMan The segment manager
* @param[in] script_nr The script number to load
* @return The script's segment ID or 0 if out of heap
*/
int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr);
/**
* Decreases the numer of lockers of a script and unloads it if that number
* reaches zero.
* This function will recursively unload scripts containing its
* superclasses, if those aren't locked by other scripts as well.
* @param[in] segMan The segment manager
* @param[in] version The SCI version to use
* @param[in] script_nr The script number that is requestet to be unloaded
*/
void script_uninstantiate(SegManager *segMan, int script_nr);
} // End of namespace Sci
#endif // SCI_ENGINE_SCRIPT_H