diff options
Diffstat (limited to 'engines/sci/engine/script.h')
-rw-r--r-- | engines/sci/engine/script.h | 359 |
1 files changed, 206 insertions, 153 deletions
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index e94e9f64e6..3817f8aae1 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -27,14 +27,13 @@ #define SCI_ENGINE_SCRIPT_H #include "common/str.h" +#include "sci/engine/segment.h" namespace Sci { struct EngineState; class ResourceManager; -#define SCI_SCRIPTS_NR 1000 - enum ScriptObjectTypes { SCI_OBJ_TERMINATOR, SCI_OBJ_OBJECT, @@ -49,160 +48,214 @@ enum ScriptObjectTypes { SCI_OBJ_LOCALVARS }; -// Opcode formats -enum opcode_format { - Script_Invalid = -1, - Script_None = 0, - Script_Byte, - Script_SByte, - Script_Word, - Script_SWord, - Script_Variable, - Script_SVariable, - Script_SRelative, - Script_Property, - Script_Global, - Script_Local, - Script_Temp, - Script_Param, - Script_Offset, - Script_End -}; +typedef Common::HashMap<uint16, Object> ObjMap; -enum sci_opcodes { - op_bnot = 0x00, // 000 - op_add = 0x01, // 001 - op_sub = 0x02, // 002 - op_mul = 0x03, // 003 - op_div = 0x04, // 004 - op_mod = 0x05, // 005 - op_shr = 0x06, // 006 - op_shl = 0x07, // 007 - op_xor = 0x08, // 008 - op_and = 0x09, // 009 - op_or = 0x0a, // 010 - op_neg = 0x0b, // 011 - op_not = 0x0c, // 012 - op_eq_ = 0x0d, // 013 - op_ne_ = 0x0e, // 014 - op_gt_ = 0x0f, // 015 - op_ge_ = 0x10, // 016 - op_lt_ = 0x11, // 017 - op_le_ = 0x12, // 018 - op_ugt_ = 0x13, // 019 - op_uge_ = 0x14, // 020 - op_ult_ = 0x15, // 021 - op_ule_ = 0x16, // 022 - op_bt = 0x17, // 023 - op_bnt = 0x18, // 024 - op_jmp = 0x19, // 025 - op_ldi = 0x1a, // 026 - op_push = 0x1b, // 027 - op_pushi = 0x1c, // 028 - op_toss = 0x1d, // 029 - op_dup = 0x1e, // 030 - op_link = 0x1f, // 031 - op_call = 0x20, // 032 - op_callk = 0x21, // 033 - op_callb = 0x22, // 034 - op_calle = 0x23, // 035 - op_ret = 0x24, // 036 - op_send = 0x25, // 037 - // dummy 0x26, // 038 - // dummy 0x27, // 039 - op_class = 0x28, // 040 - // dummy 0x29, // 041 - op_self = 0x2a, // 042 - op_super = 0x2b, // 043 - op_rest = 0x2c, // 044 - op_lea = 0x2d, // 045 - op_selfID = 0x2e, // 046 - // dummy 0x2f // 047 - op_pprev = 0x30, // 048 - op_pToa = 0x31, // 049 - op_aTop = 0x32, // 050 - op_pTos = 0x33, // 051 - op_sTop = 0x34, // 052 - op_ipToa = 0x35, // 053 - op_dpToa = 0x36, // 054 - op_ipTos = 0x37, // 055 - op_dpTos = 0x38, // 056 - op_lofsa = 0x39, // 057 - op_lofss = 0x3a, // 058 - op_push0 = 0x3b, // 059 - op_push1 = 0x3c, // 060 - op_push2 = 0x3d, // 061 - op_pushSelf = 0x3e, // 062 - op_line = 0x3f, // 063 - op_lag = 0x40, // 064 - op_lal = 0x41, // 065 - op_lat = 0x42, // 066 - op_lap = 0x43, // 067 - op_lsg = 0x44, // 068 - op_lsl = 0x45, // 069 - op_lst = 0x46, // 070 - op_lsp = 0x47, // 071 - op_lagi = 0x48, // 072 - op_lali = 0x49, // 073 - op_lati = 0x4a, // 074 - op_lapi = 0x4b, // 075 - op_lsgi = 0x4c, // 076 - op_lsli = 0x4d, // 077 - op_lsti = 0x4e, // 078 - op_lspi = 0x4f, // 079 - op_sag = 0x50, // 080 - op_sal = 0x51, // 081 - op_sat = 0x52, // 082 - op_sap = 0x53, // 083 - op_ssg = 0x54, // 084 - op_ssl = 0x55, // 085 - op_sst = 0x56, // 086 - op_ssp = 0x57, // 087 - op_sagi = 0x58, // 088 - op_sali = 0x59, // 089 - op_sati = 0x5a, // 090 - op_sapi = 0x5b, // 091 - op_ssgi = 0x5c, // 092 - op_ssli = 0x5d, // 093 - op_ssti = 0x5e, // 094 - op_sspi = 0x5f, // 095 - op_plusag = 0x60, // 096 - op_plusal = 0x61, // 097 - op_plusat = 0x62, // 098 - op_plusap = 0x63, // 099 - op_plussg = 0x64, // 100 - op_plussl = 0x65, // 101 - op_plusst = 0x66, // 102 - op_plussp = 0x67, // 103 - op_plusagi = 0x68, // 104 - op_plusali = 0x69, // 105 - op_plusati = 0x6a, // 106 - op_plusapi = 0x6b, // 107 - op_plussgi = 0x6c, // 108 - op_plussli = 0x6d, // 109 - op_plussti = 0x6e, // 110 - op_plusspi = 0x6f, // 111 - op_minusag = 0x70, // 112 - op_minusal = 0x71, // 113 - op_minusat = 0x72, // 114 - op_minusap = 0x73, // 115 - op_minussg = 0x74, // 116 - op_minussl = 0x75, // 117 - op_minusst = 0x76, // 118 - op_minussp = 0x77, // 119 - op_minusagi = 0x78, // 120 - op_minusali = 0x79, // 121 - op_minusati = 0x7a, // 122 - op_minusapi = 0x7b, // 123 - op_minussgi = 0x7c, // 124 - op_minussli = 0x7d, // 125 - op_minussti = 0x7e, // 126 - op_minusspi = 0x7f // 127 -}; +class Script : public SegmentObj { +private: + int _nr; /**< Script number */ + byte *_buf; /**< Static data buffer, or NULL if not used */ + byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */ + + int _lockers; /**< Number of classes and objects that require this script */ + 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; + + bool _markedAsDeleted; + +public: + /** + * Table for objects, contains property variables. + * Indexed by the TODO offset. + */ + ObjMap _objects; + SegmentId _localsSegment; /**< The local variable segment */ + LocalVariables *_localsBlock; + +public: + int getLocalsOffset() const { return _localsOffset; } + uint16 getLocalsCount() const { return _localsCount; } + + uint32 getScriptSize() const { return _scriptSize; } + uint32 getHeapSize() const { return _heapSize; } + uint32 getBufSize() const { return _bufSize; } + const byte *getBuf(uint offset = 0) const { return _buf + offset; } + + int getScriptNumber() const { return _nr; } + +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 Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; + + /** + * Return a list of all references to objects in this script + * (and also to the locals segment, if any). + * Used by the garbage collector. + * @return a list of outgoing references within the object + */ + Common::Array<reg_t> listObjectReferences() const; + + virtual void saveLoadWithSerializer(Common::Serializer &ser); + + 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); -extern opcode_format g_opcode_formats[128][4]; + /** + * Initializes the script's local variables + * @param segMan A reference to the segment manager + */ + void initialiseLocals(SegManager *segMan); -void script_adjust_opcode_formats(EngineState *s); + /** + * Adds the script's classes to the segment manager's class table + * @param segMan A reference to the segment manager + */ + void initialiseClasses(SegManager *segMan); + + /** + * Initializes the script's objects (SCI0) + * @param segMan A reference to the segment manager + * @param segmentId The script's segment id + */ + void initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId); + + /** + * Initializes the script's objects (SCI1.1+) + * @param segMan A reference to the segment manager + * @param segmentId The script's segment id + */ + void initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId); + + // 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); + +private: + /** + * 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); + + bool relocateLocal(SegmentId segment, int location); +}; } // End of namespace Sci |