[Scummvm-cvs-logs] SF.net SVN: scummvm:[44155] scummvm/trunk
fingolfin at users.sourceforge.net
fingolfin at users.sourceforge.net
Thu Sep 17 15:22:47 CEST 2009
Revision: 44155
http://scummvm.svn.sourceforge.net/scummvm/?rev=44155&view=rev
Author: fingolfin
Date: 2009-09-17 13:22:46 +0000 (Thu, 17 Sep 2009)
Log Message:
-----------
SCI: Rename engine/memobj.* to engine/segment.*
Modified Paths:
--------------
scummvm/trunk/dists/iphone/scummvm.xcodeproj/project.pbxproj
scummvm/trunk/dists/msvc8/sci.vcproj
scummvm/trunk/dists/msvc9/sci.vcproj
scummvm/trunk/engines/sci/engine/savegame.cpp
scummvm/trunk/engines/sci/engine/seg_manager.h
scummvm/trunk/engines/sci/module.mk
Added Paths:
-----------
scummvm/trunk/engines/sci/engine/segment.cpp
scummvm/trunk/engines/sci/engine/segment.h
Removed Paths:
-------------
scummvm/trunk/engines/sci/engine/memobj.cpp
scummvm/trunk/engines/sci/engine/memobj.h
Modified: scummvm/trunk/dists/iphone/scummvm.xcodeproj/project.pbxproj
===================================================================
--- scummvm/trunk/dists/iphone/scummvm.xcodeproj/project.pbxproj 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/dists/iphone/scummvm.xcodeproj/project.pbxproj 2009-09-17 13:22:46 UTC (rev 44155)
@@ -1017,11 +1017,11 @@
DF6118360FE3A7D20042AD3F /* res_view.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF61182F0FE3A7D20042AD3F /* res_view.cpp */; };
DF6118370FE3A7D20042AD3F /* seq_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */; };
DF61183C0FE3A8080042AD3F /* kmisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118380FE3A8080042AD3F /* kmisc.cpp */; };
- DF61183D0FE3A8080042AD3F /* memobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* memobj.cpp */; };
+ DF61183D0FE3A8080042AD3F /* segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* segment.cpp */; };
DF61183E0FE3A8080042AD3F /* kmisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118380FE3A8080042AD3F /* kmisc.cpp */; };
- DF61183F0FE3A8080042AD3F /* memobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* memobj.cpp */; };
+ DF61183F0FE3A8080042AD3F /* segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* segment.cpp */; };
DF6118400FE3A8080042AD3F /* kmisc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118380FE3A8080042AD3F /* kmisc.cpp */; };
- DF6118410FE3A8080042AD3F /* memobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* memobj.cpp */; };
+ DF6118410FE3A8080042AD3F /* segment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118390FE3A8080042AD3F /* segment.cpp */; };
DF6118490FE3A8250042AD3F /* decompressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118430FE3A8250042AD3F /* decompressor.cpp */; };
DF61184A0FE3A8250042AD3F /* resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118450FE3A8250042AD3F /* resource.cpp */; };
DF61184B0FE3A8250042AD3F /* vocabulary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF6118470FE3A8250042AD3F /* vocabulary.cpp */; };
@@ -3169,8 +3169,8 @@
DF6118300FE3A7D20042AD3F /* seq_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = seq_decoder.cpp; sourceTree = "<group>"; };
DF6118310FE3A7D20042AD3F /* seq_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seq_decoder.h; sourceTree = "<group>"; };
DF6118380FE3A8080042AD3F /* kmisc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kmisc.cpp; sourceTree = "<group>"; };
- DF6118390FE3A8080042AD3F /* memobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = memobj.cpp; sourceTree = "<group>"; };
- DF61183A0FE3A8080042AD3F /* memobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memobj.h; sourceTree = "<group>"; };
+ DF6118390FE3A8080042AD3F /* segment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = segment.cpp; sourceTree = "<group>"; };
+ DF61183A0FE3A8080042AD3F /* segment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = segment.h; sourceTree = "<group>"; };
DF61183B0FE3A8080042AD3F /* savegame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = savegame.h; sourceTree = "<group>"; };
DF6118420FE3A8250042AD3F /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
DF6118430FE3A8250042AD3F /* decompressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = decompressor.cpp; sourceTree = "<group>"; };
@@ -6425,8 +6425,8 @@
children = (
DF7585F6100CB75800CC3324 /* static_selectors.cpp */,
DF6118380FE3A8080042AD3F /* kmisc.cpp */,
- DF6118390FE3A8080042AD3F /* memobj.cpp */,
- DF61183A0FE3A8080042AD3F /* memobj.h */,
+ DF6118390FE3A8080042AD3F /* segment.cpp */,
+ DF61183A0FE3A8080042AD3F /* segment.h */,
DF61183B0FE3A8080042AD3F /* savegame.h */,
DF5CEB3A0F75540700DEA624 /* stringfrag.cpp */,
DF89C2A30F62D79E00D756B6 /* script.cpp */,
@@ -8098,7 +8098,7 @@
DF6118340FE3A7D20042AD3F /* res_view.cpp in Sources */,
DF6118350FE3A7D20042AD3F /* seq_decoder.cpp in Sources */,
DF61183E0FE3A8080042AD3F /* kmisc.cpp in Sources */,
- DF61183F0FE3A8080042AD3F /* memobj.cpp in Sources */,
+ DF61183F0FE3A8080042AD3F /* segment.cpp in Sources */,
DF61184C0FE3A8250042AD3F /* decompressor.cpp in Sources */,
DF61184D0FE3A8250042AD3F /* resource.cpp in Sources */,
DF61184E0FE3A8250042AD3F /* vocabulary.cpp in Sources */,
@@ -9059,7 +9059,7 @@
DF6118320FE3A7D20042AD3F /* res_view.cpp in Sources */,
DF6118330FE3A7D20042AD3F /* seq_decoder.cpp in Sources */,
DF61183C0FE3A8080042AD3F /* kmisc.cpp in Sources */,
- DF61183D0FE3A8080042AD3F /* memobj.cpp in Sources */,
+ DF61183D0FE3A8080042AD3F /* segment.cpp in Sources */,
DF6118490FE3A8250042AD3F /* decompressor.cpp in Sources */,
DF61184A0FE3A8250042AD3F /* resource.cpp in Sources */,
DF61184B0FE3A8250042AD3F /* vocabulary.cpp in Sources */,
@@ -10014,7 +10014,7 @@
DF6118360FE3A7D20042AD3F /* res_view.cpp in Sources */,
DF6118370FE3A7D20042AD3F /* seq_decoder.cpp in Sources */,
DF6118400FE3A8080042AD3F /* kmisc.cpp in Sources */,
- DF6118410FE3A8080042AD3F /* memobj.cpp in Sources */,
+ DF6118410FE3A8080042AD3F /* segment.cpp in Sources */,
DF61184F0FE3A8250042AD3F /* decompressor.cpp in Sources */,
DF6118500FE3A8250042AD3F /* resource.cpp in Sources */,
DF6118510FE3A8250042AD3F /* vocabulary.cpp in Sources */,
Modified: scummvm/trunk/dists/msvc8/sci.vcproj
===================================================================
--- scummvm/trunk/dists/msvc8/sci.vcproj 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/dists/msvc8/sci.vcproj 2009-09-17 13:22:46 UTC (rev 44155)
@@ -38,8 +38,8 @@
<File RelativePath="..\..\engines\sci\engine\kscripts.cpp" />
<File RelativePath="..\..\engines\sci\engine\ksound.cpp" />
<File RelativePath="..\..\engines\sci\engine\kstring.cpp" />
- <File RelativePath="..\..\engines\sci\engine\memobj.cpp" />
- <File RelativePath="..\..\engines\sci\engine\memobj.h" />
+ <File RelativePath="..\..\engines\sci\engine\segment.cpp" />
+ <File RelativePath="..\..\engines\sci\engine\segment.h" />
<File RelativePath="..\..\engines\sci\engine\message.cpp" />
<File RelativePath="..\..\engines\sci\engine\message.h" />
<File RelativePath="..\..\engines\sci\engine\said.cpp" />
Modified: scummvm/trunk/dists/msvc9/sci.vcproj
===================================================================
--- scummvm/trunk/dists/msvc9/sci.vcproj 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/dists/msvc9/sci.vcproj 2009-09-17 13:22:46 UTC (rev 44155)
@@ -39,8 +39,8 @@
<File RelativePath="..\..\engines\sci\engine\kscripts.cpp" />
<File RelativePath="..\..\engines\sci\engine\ksound.cpp" />
<File RelativePath="..\..\engines\sci\engine\kstring.cpp" />
- <File RelativePath="..\..\engines\sci\engine\memobj.cpp" />
- <File RelativePath="..\..\engines\sci\engine\memobj.h" />
+ <File RelativePath="..\..\engines\sci\engine\segment.cpp" />
+ <File RelativePath="..\..\engines\sci\engine\segment.h" />
<File RelativePath="..\..\engines\sci\engine\message.cpp" />
<File RelativePath="..\..\engines\sci\engine\message.h" />
<File RelativePath="..\..\engines\sci\engine\said.cpp" />
Deleted: scummvm/trunk/engines/sci/engine/memobj.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/memobj.cpp 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/engines/sci/engine/memobj.cpp 2009-09-17 13:22:46 UTC (rev 44155)
@@ -1,481 +0,0 @@
-/* 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$
- *
- */
-
-#include "common/endian.h"
-
-#include "sci/sci.h"
-#include "sci/engine/memobj.h"
-#include "sci/engine/intmap.h"
-#include "sci/engine/seg_manager.h"
-#include "sci/engine/state.h"
-#include "sci/tools.h"
-
-namespace Sci {
-
-//#define GC_DEBUG // Debug garbage collection
-//#define GC_DEBUG_VERBOSE // Debug garbage verbosely
-
-
-SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
- SegmentObj *mem = 0;
- switch (type) {
- case SEG_TYPE_SCRIPT:
- mem = new Script();
- break;
- case SEG_TYPE_CLONES:
- mem = new CloneTable();
- break;
- case SEG_TYPE_LOCALS:
- mem = new LocalVariables();
- break;
- case SEG_TYPE_SYS_STRINGS:
- mem = new SystemStrings();
- break;
- case SEG_TYPE_STACK:
- mem = new DataStack();
- break;
- case SEG_TYPE_HUNK:
- mem = new HunkTable();
- break;
- case SEG_TYPE_STRING_FRAG:
- mem = new StringFrag();
- break;
- case SEG_TYPE_LISTS:
- mem = new ListTable();
- break;
- case SEG_TYPE_NODES:
- mem = new NodeTable();
- break;
- case SEG_TYPE_DYNMEM:
- mem = new DynMem();
- break;
- default:
- error("Unknown SegmentObj type %d", type);
- break;
- }
-
- assert(mem);
- mem->_type = type;
- return mem;
-}
-
-Script::Script() {
- _nr = 0;
- _buf = NULL;
- _bufSize = 0;
- _scriptSize = 0;
- _heapSize = 0;
-
- _synonyms = NULL;
- _heapStart = NULL;
- _exportTable = NULL;
-
- _objIndices = NULL;
-
- _localsOffset = 0;
- _localsSegment = 0;
- _localsBlock = NULL;
-
- _relocated = false;
- _markedAsDeleted = 0;
-}
-
-Script::~Script() {
- freeScript();
-}
-
-void Script::freeScript() {
- free(_buf);
- _buf = NULL;
- _bufSize = 0;
-
- _objects.clear();
-
- delete _objIndices;
- _objIndices = 0;
- _codeBlocks.clear();
-}
-
-bool Script::init(int script_nr, ResourceManager *resMan) {
- _sciVersion = resMan->sciVersion();
-
- setScriptSize(script_nr, resMan);
-
- _buf = (byte *)malloc(_bufSize);
-
-#ifdef DEBUG_segMan
- printf("_buf = %p ", _buf);
-#endif
- if (!_buf) {
- freeScript();
- warning("Not enough memory space for script size");
- _bufSize = 0;
- return false;
- }
-
- _localsOffset = 0;
- _localsBlock = NULL;
-
- _codeBlocks.clear();
-
- _relocated = false;
- _markedAsDeleted = false;
-
- _objIndices = new IntMapper();
-
- _nr = script_nr;
-
- if (_sciVersion >= SCI_VERSION_1_1)
- _heapStart = _buf + _scriptSize;
- else
- _heapStart = _buf;
-
- return true;
-}
-
-Object *Script::allocateObject(uint16 offset) {
- int idx = _objIndices->checkKey(offset, true);
- if ((uint)idx == _objects.size())
- _objects.push_back(Object());
-
- return &_objects[idx];
-}
-
-Object *Script::getObject(uint16 offset) {
- int idx = _objIndices->checkKey(offset, false);
- if (idx >= 0 && (uint)idx < _objects.size())
- return &_objects[idx];
- else
- return 0;
-}
-
-void Script::incrementLockers() {
- _lockers++;
-}
-
-void Script::decrementLockers() {
- if (_lockers > 0)
- _lockers--;
-}
-
-int Script::getLockers() const {
- return _lockers;
-}
-
-void Script::setLockers(int lockers) {
- _lockers = lockers;
-}
-
-void Script::setExportTableOffset(int offset) {
- if (offset) {
- _exportTable = (uint16 *)(_buf + offset + 2);
- _numExports = READ_LE_UINT16((byte *)(_exportTable - 1));
- } else {
- _exportTable = NULL;
- _numExports = 0;
- }
-}
-
-void Script::setSynonymsOffset(int offset) {
- _synonyms = _buf + offset;
-}
-
-byte *Script::getSynonyms() const {
- return _synonyms;
-}
-
-void Script::setSynonymsNr(int n) {
- _numSynonyms = n;
-}
-
-int Script::getSynonymsNr() const {
- return _numSynonyms;
-}
-
-// memory operations
-
-void Script::mcpyInOut(int dst, const void *src, size_t n) {
- if (_buf) {
- assert(dst + n <= _bufSize);
- memcpy(_buf + dst, src, n);
- }
-}
-
-int16 Script::getHeap(uint16 offset) const {
- assert(offset + 1 < (int)_bufSize);
- return READ_LE_UINT16(_buf + offset);
-// return (_buf[offset] | (_buf[offset+1]) << 8);
-}
-
-byte *SegmentObj::dereference(reg_t pointer, int *size) {
- error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
- PRINT_REG(pointer));
- return NULL;
-}
-
-bool Script::isValidOffset(uint16 offset) const {
- return offset < _bufSize;
-}
-
-byte *Script::dereference(reg_t pointer, int *size) {
- if (pointer.offset > _bufSize) {
- warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n",
- PRINT_REG(pointer), (uint)_bufSize);
- return NULL;
- }
- if (size)
- *size = _bufSize - pointer.offset;
- return _buf + pointer.offset;
-}
-
-bool LocalVariables::isValidOffset(uint16 offset) const {
- return offset < _locals.size() * sizeof(reg_t);
-}
-
-byte *LocalVariables::dereference(reg_t pointer, int *size) {
- if (size)
- *size = _locals.size() * sizeof(reg_t);
-
- // FIXME: The following doesn't seem to be endian safe.
- // To fix this, we'd have to always treat the reg_t
- // values stored here as in the little endian format.
- byte *base = (byte *)&_locals[0];
- return base + pointer.offset;
-}
-
-bool DataStack::isValidOffset(uint16 offset) const {
- return offset < nr * sizeof(reg_t);
-}
-
-byte *DataStack::dereference(reg_t pointer, int *size) {
- if (size)
- *size = nr * sizeof(reg_t);
-
- byte *base = (byte *)entries;
- return base + pointer.offset;
-}
-
-bool DynMem::isValidOffset(uint16 offset) const {
- return offset < _size;
-}
-
-byte *DynMem::dereference(reg_t pointer, int *size) {
- if (size)
- *size = _size;
-
- byte *base = (byte *)_buf;
- return base + pointer.offset;
-}
-
-bool SystemStrings::isValidOffset(uint16 offset) const {
- return offset < SYS_STRINGS_MAX && strings[offset].name;
-}
-
-byte *SystemStrings::dereference(reg_t pointer, int *size) {
- if (size)
- *size = strings[pointer.offset].max_size;
- if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name)
- return (byte *)(strings[pointer.offset].value);
-
- // This occurs in KQ5CD when interacting with certain objects
- warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
- return NULL;
-}
-
-
-//-------------------- script --------------------
-reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void Script::freeAtAddress(SegManager *segMan, reg_t addr) {
- /*
- debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x\n", PRINT_REG(addr));
- if (_localsSegment)
- debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000\n", _localsSegment);
- */
-
- if (_markedAsDeleted)
- segMan->deallocateScript(_nr);
-}
-
-void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- (*note)(param, make_reg(segId, 0));
-}
-
-void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
- if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) {
- Object *obj = getObject(addr.offset);
- if (obj) {
- // Note all local variables, if we have a local variable environment
- if (_localsSegment)
- (*note)(param, make_reg(_localsSegment, 0));
-
- for (uint i = 0; i < obj->_variables.size(); i++)
- (*note)(param, obj->_variables[i]);
- } else {
- warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr));
- }
- } else {
- /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
- /* Happens e.g. when we're looking into strings */
- }
-}
-
-
-//-------------------- clones --------------------
-
-void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
- Clone *clone;
-
-// assert(addr.segment == _segId);
-
- if (!isValidEntry(addr.offset)) {
- error("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr));
- }
-
- clone = &(_table[addr.offset]);
-
- // Emit all member variables (including references to the 'super' delegate)
- for (uint i = 0; i < clone->_variables.size(); i++)
- (*note)(param, clone->_variables[i]);
-
- // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals.
- (*note)(param, clone->pos);
- //debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos));
-}
-
-void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
-#ifdef GC_DEBUG
- Object *victim_obj;
-
-// assert(addr.segment == _segId);
-
- victim_obj = &(_table[addr.offset]);
-
- if (!(victim_obj->flags & OBJECT_FLAG_FREED))
- warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr));
-#ifdef GC_DEBUG_VERBOSE
- else
- warning("[GC-DEBUG] Clone %04x:%04x: Freeing", PRINT_REG(addr));
-#endif
-#endif
- /*
- warning("[GC] Clone %04x:%04x: Freeing", PRINT_REG(addr));
- warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos));
- */
- freeEntry(addr.offset);
-}
-
-
-//-------------------- locals --------------------
-reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) {
- // Reference the owning script
- SegmentId owner_seg = segMan->getScriptSegment(script_id);
-
- assert(owner_seg > 0);
-
- return make_reg(owner_seg, 0);
-}
-
-void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
-// assert(addr.segment == _segId);
-
- for (uint i = 0; i < _locals.size(); i++)
- (*note)(param, _locals[i]);
-}
-
-
-//-------------------- stack --------------------
-reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
- fprintf(stderr, "Emitting %d stack entries\n", nr);
- for (int i = 0; i < nr; i++)
- (*note)(param, entries[i]);
- fprintf(stderr, "DONE");
-}
-
-
-//-------------------- lists --------------------
-void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
-
-void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
- if (!isValidEntry(addr.offset)) {
- warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
- }
-
- List *list = &(_table[addr.offset]);
-
- note(param, list->first);
- note(param, list->last);
- // We could probably get away with just one of them, but
- // let's be conservative here.
-}
-
-
-//-------------------- nodes --------------------
-void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
- freeEntry(sub_addr.offset);
-}
-
-void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
- if (!isValidEntry(addr.offset)) {
- warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
- return;
- }
- Node *node = &(_table[addr.offset]);
-
- // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us
- // to walk around from any given node
- note(param, node->pred);
- note(param, node->succ);
- note(param, node->key);
- note(param, node->value);
-}
-
-
-//-------------------- hunk --------------------
-
-//-------------------- dynamic memory --------------------
-
-reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) {
- addr.offset = 0;
- return addr;
-}
-
-void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
- (*note)(param, make_reg(segId, 0));
-}
-
-
-} // End of namespace Sci
Deleted: scummvm/trunk/engines/sci/engine/memobj.h
===================================================================
--- scummvm/trunk/engines/sci/engine/memobj.h 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/engines/sci/engine/memobj.h 2009-09-17 13:22:46 UTC (rev 44155)
@@ -1,644 +0,0 @@
-/* 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_MEMOBJ_H
-#define SCI_ENGINE_MEMOBJ_H
-
-#include "common/serializer.h"
-#include "sci/engine/vm.h"
-#include "sci/engine/vm_types.h" // for reg_t
-
-//#include "common/util.h"
-
-namespace Sci {
-
-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
-};
-
-struct SegmentObj : public Common::Serializable {
- SegmentType _type;
-
- typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
-
-public:
- static SegmentObj *createSegmentObj(SegmentType type);
-
-public:
- virtual ~SegmentObj() {}
-
- inline SegmentType getType() const { return _type; }
-
- /**
- * 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;
-
- /**
- * Dereferences a raw memory pointer.
- * @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
- */
- 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
- */
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) { return sub_addr; }
-
- /**
- * Deallocates all memory associated with the specified address.
- * @param sub_addr address (within the given segment) to deallocate
- */
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {}
-
- /**
- * 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
- */
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version) {}
-};
-
-
-// TODO: Implement the following class
-struct StringFrag : public SegmentObj {
- virtual bool isValidOffset(uint16 offset) const { return false; }
-
- 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;
-};
-
-struct SystemStrings : public SegmentObj {
- 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;
- }
- }
- }
-
- virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-/** This struct is used to buffer the list of send calls in send_selector() */
-struct CallsStruct {
- reg_t addr_func;
- reg_t varp_objp;
- union {
- reg_t func;
- ObjVarRef var;
- } address;
- StackPtr argp;
- int argc;
- Selector selector;
- StackPtr sp; /**< Stack pointer */
- int type; /**< Same as ExecStack.type */
-};
-
-struct LocalVariables : public SegmentObj {
- int script_id; /**< Script ID this local variable block belongs to */
- Common::Array<reg_t> _locals;
-
-public:
- LocalVariables() {
- script_id = 0;
- }
-
- virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-/** Clone has been marked as 'freed' */
-#define OBJECT_FLAG_FREED (0x1 << 0)
-
-// TODO: convert to class, perhaps?
-struct Object {
- int flags;
- reg_t pos; /**< Object offset within its script; for clones, this is their base */
- 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;
-
- uint16 getVarSelector(uint16 i, SciVersion version) {
- if (version < SCI_VERSION_1_1)
- return READ_LE_UINT16(base_obj + _variables.size() * 2 + i * 2);
- else
- return *(base_vars + i);
- }
-
- reg_t getSpeciesSelector(SciVersion version) {
- return _variables[version < SCI_VERSION_1_1 ? 0 : 5];
- }
-
- void setSpeciesSelector(reg_t value, SciVersion version) {
- _variables[version < SCI_VERSION_1_1 ? 0 : 5] = value;
- }
-
- reg_t getSuperClassSelector(SciVersion version) {
- return _variables[version < SCI_VERSION_1_1 ? 1 : 6];
- }
-
- void setSuperClassSelector(reg_t value, SciVersion version) {
- _variables[version < SCI_VERSION_1_1 ? 1 : 6] = value;
- }
-
- reg_t getInfoSelector(SciVersion version) {
- return _variables[version < SCI_VERSION_1_1 ? 2 : 7];
- }
-
- void setInfoSelector(reg_t value, SciVersion version) {
- _variables[version < SCI_VERSION_1_1 ? 2 : 7] = value;
- }
-
- reg_t getNameSelector(SciVersion version) {
- return _variables[version < SCI_VERSION_1_1 ? 3 : 8];
- }
-
- void setNameSelector(reg_t value, SciVersion version) {
- _variables[version < SCI_VERSION_1_1 ? 3 : 8] = value;
- }
-
- reg_t getClassScriptSelector() {
- return _variables[4];
- }
-
- void setClassScriptSelector(reg_t value) {
- _variables[4] = value;
- }
-
- uint16 getFuncSelector(uint16 i, SciVersion version) {
- uint16 offset = (version < SCI_VERSION_1_1) ? i : i * 2 + 1;
- return READ_LE_UINT16((byte *) (base_method + offset));
- }
-
- reg_t getFunction(uint16 i, SciVersion version) {
- uint16 offset = (version < SCI_VERSION_1_1) ? methods_nr + 1 + i : i * 2 + 2;
- return make_reg(pos.segment, READ_LE_UINT16((byte *) (base_method + offset)));
- }
-
- bool isClass(SciVersion version) {
- return (getInfoSelector(version).offset & SCRIPT_INFO_CLASS);
- }
-};
-
-struct CodeBlock {
- reg_t pos;
- int size;
-};
-
-class Script : public SegmentObj {
-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 */
-
- byte *_synonyms; /**< Synonyms block or 0 if not present*/
- int _numSynonyms; /**< Number of entries in the synonyms block */
-
-protected:
- int _lockers; /**< Number of classes and objects that require this script */
-
- IntMapper *_objIndices;
-
- SciVersion _sciVersion;
-
-public:
- /**
- * 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;
-
- int _localsOffset;
- SegmentId _localsSegment; /**< The local variable segment */
- LocalVariables *_localsBlock;
-
- Common::Array<CodeBlock> _codeBlocks;
- bool _relocated;
- bool _markedAsDeleted;
-
-public:
- Script();
- ~Script();
-
- void freeScript();
- bool init(int script_nr, ResourceManager *resMan);
-
- virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-
- Object *allocateObject(uint16 offset);
- Object *getObject(uint16 offset);
-
- /**
- * 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:
- // 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;
- }
-
- /**
- * 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);
-
-
- /**
- * 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;
-
-private:
- void setScriptSize(int script_nr, ResourceManager *resMan);
-};
-
-/** Data stack */
-struct DataStack : SegmentObj {
- int nr; /**< Number of stack entries */
- reg_t *entries;
-
-public:
- DataStack() {
- nr = 0;
- entries = NULL;
- }
- ~DataStack() {
- free(entries);
- entries = NULL;
- }
-
- virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
-
- 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>
-struct Table : public SegmentObj {
- 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;
- }
- }
-
- virtual bool isValidOffset(uint16 offset) const {
- return isValidEntry(offset);
- }
-
- bool isValidEntry(int idx) const {
- 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--;
- }
-
- 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));
- }
-};
-
-
-/* CloneTable */
-struct CloneTable : public Table<Clone> {
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-/* NodeTable */
-struct NodeTable : public Table<Node> {
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-/* ListTable */
-struct ListTable : public Table<List> {
- virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
-
- 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
-struct DynMem : public SegmentObj {
- int _size;
- Common::String _description;
- byte *_buf;
-
-public:
- DynMem() : _size(0), _buf(0) {}
- ~DynMem() {
- free(_buf);
- _buf = NULL;
- }
-
- virtual bool isValidOffset(uint16 offset) const;
- virtual byte *dereference(reg_t pointer, int *size);
- virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-};
-
-
-} // End of namespace Sci
-
-#endif // SCI_ENGINE_VM_H
Modified: scummvm/trunk/engines/sci/engine/savegame.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/savegame.cpp 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/engines/sci/engine/savegame.cpp 2009-09-17 13:22:46 UTC (rev 44155)
@@ -219,7 +219,7 @@
for (uint i = 0; i < sync_heap_size; ++i) {
SegmentObj *&mobj = _heap[i];
- // Sync the memobj type
+ // Sync the segment type
SegmentType type = (s.isSaving() && mobj) ? mobj->getType() : SEG_TYPE_INVALID;
s.syncAsUint32LE(type);
Modified: scummvm/trunk/engines/sci/engine/seg_manager.h
===================================================================
--- scummvm/trunk/engines/sci/engine/seg_manager.h 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/engines/sci/engine/seg_manager.h 2009-09-17 13:22:46 UTC (rev 44155)
@@ -23,13 +23,13 @@
*
*/
-#ifndef SCI_ENGINE_segMan_H
-#define SCI_ENGINE_segMan_H
+#ifndef SCI_ENGINE_SEGMAN_H
+#define SCI_ENGINE_SEGMAN_H
#include "common/scummsys.h"
#include "common/serializer.h"
#include "sci/engine/vm.h"
-#include "sci/engine/memobj.h"
+#include "sci/engine/segment.h"
namespace Sci {
@@ -397,4 +397,4 @@
} // End of namespace Sci
-#endif // SCI_ENGINE_segMan
+#endif // SCI_ENGINE_SEGMAN
Copied: scummvm/trunk/engines/sci/engine/segment.cpp (from rev 44154, scummvm/trunk/engines/sci/engine/memobj.cpp)
===================================================================
--- scummvm/trunk/engines/sci/engine/segment.cpp (rev 0)
+++ scummvm/trunk/engines/sci/engine/segment.cpp 2009-09-17 13:22:46 UTC (rev 44155)
@@ -0,0 +1,481 @@
+/* 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$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "sci/sci.h"
+#include "sci/engine/segment.h"
+#include "sci/engine/intmap.h"
+#include "sci/engine/seg_manager.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+
+namespace Sci {
+
+//#define GC_DEBUG // Debug garbage collection
+//#define GC_DEBUG_VERBOSE // Debug garbage verbosely
+
+
+SegmentObj *SegmentObj::createSegmentObj(SegmentType type) {
+ SegmentObj *mem = 0;
+ switch (type) {
+ case SEG_TYPE_SCRIPT:
+ mem = new Script();
+ break;
+ case SEG_TYPE_CLONES:
+ mem = new CloneTable();
+ break;
+ case SEG_TYPE_LOCALS:
+ mem = new LocalVariables();
+ break;
+ case SEG_TYPE_SYS_STRINGS:
+ mem = new SystemStrings();
+ break;
+ case SEG_TYPE_STACK:
+ mem = new DataStack();
+ break;
+ case SEG_TYPE_HUNK:
+ mem = new HunkTable();
+ break;
+ case SEG_TYPE_STRING_FRAG:
+ mem = new StringFrag();
+ break;
+ case SEG_TYPE_LISTS:
+ mem = new ListTable();
+ break;
+ case SEG_TYPE_NODES:
+ mem = new NodeTable();
+ break;
+ case SEG_TYPE_DYNMEM:
+ mem = new DynMem();
+ break;
+ default:
+ error("Unknown SegmentObj type %d", type);
+ break;
+ }
+
+ assert(mem);
+ mem->_type = type;
+ return mem;
+}
+
+Script::Script() {
+ _nr = 0;
+ _buf = NULL;
+ _bufSize = 0;
+ _scriptSize = 0;
+ _heapSize = 0;
+
+ _synonyms = NULL;
+ _heapStart = NULL;
+ _exportTable = NULL;
+
+ _objIndices = NULL;
+
+ _localsOffset = 0;
+ _localsSegment = 0;
+ _localsBlock = NULL;
+
+ _relocated = false;
+ _markedAsDeleted = 0;
+}
+
+Script::~Script() {
+ freeScript();
+}
+
+void Script::freeScript() {
+ free(_buf);
+ _buf = NULL;
+ _bufSize = 0;
+
+ _objects.clear();
+
+ delete _objIndices;
+ _objIndices = 0;
+ _codeBlocks.clear();
+}
+
+bool Script::init(int script_nr, ResourceManager *resMan) {
+ _sciVersion = resMan->sciVersion();
+
+ setScriptSize(script_nr, resMan);
+
+ _buf = (byte *)malloc(_bufSize);
+
+#ifdef DEBUG_segMan
+ printf("_buf = %p ", _buf);
+#endif
+ if (!_buf) {
+ freeScript();
+ warning("Not enough memory space for script size");
+ _bufSize = 0;
+ return false;
+ }
+
+ _localsOffset = 0;
+ _localsBlock = NULL;
+
+ _codeBlocks.clear();
+
+ _relocated = false;
+ _markedAsDeleted = false;
+
+ _objIndices = new IntMapper();
+
+ _nr = script_nr;
+
+ if (_sciVersion >= SCI_VERSION_1_1)
+ _heapStart = _buf + _scriptSize;
+ else
+ _heapStart = _buf;
+
+ return true;
+}
+
+Object *Script::allocateObject(uint16 offset) {
+ int idx = _objIndices->checkKey(offset, true);
+ if ((uint)idx == _objects.size())
+ _objects.push_back(Object());
+
+ return &_objects[idx];
+}
+
+Object *Script::getObject(uint16 offset) {
+ int idx = _objIndices->checkKey(offset, false);
+ if (idx >= 0 && (uint)idx < _objects.size())
+ return &_objects[idx];
+ else
+ return 0;
+}
+
+void Script::incrementLockers() {
+ _lockers++;
+}
+
+void Script::decrementLockers() {
+ if (_lockers > 0)
+ _lockers--;
+}
+
+int Script::getLockers() const {
+ return _lockers;
+}
+
+void Script::setLockers(int lockers) {
+ _lockers = lockers;
+}
+
+void Script::setExportTableOffset(int offset) {
+ if (offset) {
+ _exportTable = (uint16 *)(_buf + offset + 2);
+ _numExports = READ_LE_UINT16((byte *)(_exportTable - 1));
+ } else {
+ _exportTable = NULL;
+ _numExports = 0;
+ }
+}
+
+void Script::setSynonymsOffset(int offset) {
+ _synonyms = _buf + offset;
+}
+
+byte *Script::getSynonyms() const {
+ return _synonyms;
+}
+
+void Script::setSynonymsNr(int n) {
+ _numSynonyms = n;
+}
+
+int Script::getSynonymsNr() const {
+ return _numSynonyms;
+}
+
+// memory operations
+
+void Script::mcpyInOut(int dst, const void *src, size_t n) {
+ if (_buf) {
+ assert(dst + n <= _bufSize);
+ memcpy(_buf + dst, src, n);
+ }
+}
+
+int16 Script::getHeap(uint16 offset) const {
+ assert(offset + 1 < (int)_bufSize);
+ return READ_LE_UINT16(_buf + offset);
+// return (_buf[offset] | (_buf[offset+1]) << 8);
+}
+
+byte *SegmentObj::dereference(reg_t pointer, int *size) {
+ error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
+ PRINT_REG(pointer));
+ return NULL;
+}
+
+bool Script::isValidOffset(uint16 offset) const {
+ return offset < _bufSize;
+}
+
+byte *Script::dereference(reg_t pointer, int *size) {
+ if (pointer.offset > _bufSize) {
+ warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n",
+ PRINT_REG(pointer), (uint)_bufSize);
+ return NULL;
+ }
+ if (size)
+ *size = _bufSize - pointer.offset;
+ return _buf + pointer.offset;
+}
+
+bool LocalVariables::isValidOffset(uint16 offset) const {
+ return offset < _locals.size() * sizeof(reg_t);
+}
+
+byte *LocalVariables::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = _locals.size() * sizeof(reg_t);
+
+ // FIXME: The following doesn't seem to be endian safe.
+ // To fix this, we'd have to always treat the reg_t
+ // values stored here as in the little endian format.
+ byte *base = (byte *)&_locals[0];
+ return base + pointer.offset;
+}
+
+bool DataStack::isValidOffset(uint16 offset) const {
+ return offset < nr * sizeof(reg_t);
+}
+
+byte *DataStack::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = nr * sizeof(reg_t);
+
+ byte *base = (byte *)entries;
+ return base + pointer.offset;
+}
+
+bool DynMem::isValidOffset(uint16 offset) const {
+ return offset < _size;
+}
+
+byte *DynMem::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = _size;
+
+ byte *base = (byte *)_buf;
+ return base + pointer.offset;
+}
+
+bool SystemStrings::isValidOffset(uint16 offset) const {
+ return offset < SYS_STRINGS_MAX && strings[offset].name;
+}
+
+byte *SystemStrings::dereference(reg_t pointer, int *size) {
+ if (size)
+ *size = strings[pointer.offset].max_size;
+ if (pointer.offset < SYS_STRINGS_MAX && strings[pointer.offset].name)
+ return (byte *)(strings[pointer.offset].value);
+
+ // This occurs in KQ5CD when interacting with certain objects
+ warning("Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer));
+ return NULL;
+}
+
+
+//-------------------- script --------------------
+reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) {
+ addr.offset = 0;
+ return addr;
+}
+
+void Script::freeAtAddress(SegManager *segMan, reg_t addr) {
+ /*
+ debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x\n", PRINT_REG(addr));
+ if (_localsSegment)
+ debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000\n", _localsSegment);
+ */
+
+ if (_markedAsDeleted)
+ segMan->deallocateScript(_nr);
+}
+
+void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ (*note)(param, make_reg(segId, 0));
+}
+
+void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
+ if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) {
+ Object *obj = getObject(addr.offset);
+ if (obj) {
+ // Note all local variables, if we have a local variable environment
+ if (_localsSegment)
+ (*note)(param, make_reg(_localsSegment, 0));
+
+ for (uint i = 0; i < obj->_variables.size(); i++)
+ (*note)(param, obj->_variables[i]);
+ } else {
+ warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr));
+ }
+ } else {
+ /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
+ /* Happens e.g. when we're looking into strings */
+ }
+}
+
+
+//-------------------- clones --------------------
+
+void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
+ Clone *clone;
+
+// assert(addr.segment == _segId);
+
+ if (!isValidEntry(addr.offset)) {
+ error("Unexpected request for outgoing references from clone at %04x:%04x", PRINT_REG(addr));
+ }
+
+ clone = &(_table[addr.offset]);
+
+ // Emit all member variables (including references to the 'super' delegate)
+ for (uint i = 0; i < clone->_variables.size(); i++)
+ (*note)(param, clone->_variables[i]);
+
+ // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals.
+ (*note)(param, clone->pos);
+ //debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos));
+}
+
+void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) {
+#ifdef GC_DEBUG
+ Object *victim_obj;
+
+// assert(addr.segment == _segId);
+
+ victim_obj = &(_table[addr.offset]);
+
+ if (!(victim_obj->flags & OBJECT_FLAG_FREED))
+ warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr));
+#ifdef GC_DEBUG_VERBOSE
+ else
+ warning("[GC-DEBUG] Clone %04x:%04x: Freeing", PRINT_REG(addr));
+#endif
+#endif
+ /*
+ warning("[GC] Clone %04x:%04x: Freeing", PRINT_REG(addr));
+ warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos));
+ */
+ freeEntry(addr.offset);
+}
+
+
+//-------------------- locals --------------------
+reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) {
+ // Reference the owning script
+ SegmentId owner_seg = segMan->getScriptSegment(script_id);
+
+ assert(owner_seg > 0);
+
+ return make_reg(owner_seg, 0);
+}
+
+void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
+// assert(addr.segment == _segId);
+
+ for (uint i = 0; i < _locals.size(); i++)
+ (*note)(param, _locals[i]);
+}
+
+
+//-------------------- stack --------------------
+reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) {
+ addr.offset = 0;
+ return addr;
+}
+
+void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
+ fprintf(stderr, "Emitting %d stack entries\n", nr);
+ for (int i = 0; i < nr; i++)
+ (*note)(param, entries[i]);
+ fprintf(stderr, "DONE");
+}
+
+
+//-------------------- lists --------------------
+void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+}
+
+void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
+ if (!isValidEntry(addr.offset)) {
+ warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
+ return;
+ }
+
+ List *list = &(_table[addr.offset]);
+
+ note(param, list->first);
+ note(param, list->last);
+ // We could probably get away with just one of them, but
+ // let's be conservative here.
+}
+
+
+//-------------------- nodes --------------------
+void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
+ freeEntry(sub_addr.offset);
+}
+
+void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note, SciVersion version) {
+ if (!isValidEntry(addr.offset)) {
+ warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr));
+ return;
+ }
+ Node *node = &(_table[addr.offset]);
+
+ // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us
+ // to walk around from any given node
+ note(param, node->pred);
+ note(param, node->succ);
+ note(param, node->key);
+ note(param, node->value);
+}
+
+
+//-------------------- hunk --------------------
+
+//-------------------- dynamic memory --------------------
+
+reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) {
+ addr.offset = 0;
+ return addr;
+}
+
+void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) {
+ (*note)(param, make_reg(segId, 0));
+}
+
+
+} // End of namespace Sci
Property changes on: scummvm/trunk/engines/sci/engine/segment.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Copied: scummvm/trunk/engines/sci/engine/segment.h (from rev 44154, scummvm/trunk/engines/sci/engine/memobj.h)
===================================================================
--- scummvm/trunk/engines/sci/engine/segment.h (rev 0)
+++ scummvm/trunk/engines/sci/engine/segment.h 2009-09-17 13:22:46 UTC (rev 44155)
@@ -0,0 +1,644 @@
+/* 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_SEGMENT_H
+#define SCI_ENGINE_SEGMENT_H
+
+#include "common/serializer.h"
+#include "sci/engine/vm.h"
+#include "sci/engine/vm_types.h" // for reg_t
+
+//#include "common/util.h"
+
+namespace Sci {
+
+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
+};
+
+struct SegmentObj : public Common::Serializable {
+ SegmentType _type;
+
+ typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name
+
+public:
+ static SegmentObj *createSegmentObj(SegmentType type);
+
+public:
+ virtual ~SegmentObj() {}
+
+ inline SegmentType getType() const { return _type; }
+
+ /**
+ * 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;
+
+ /**
+ * Dereferences a raw memory pointer.
+ * @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
+ */
+ 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
+ */
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) { return sub_addr; }
+
+ /**
+ * Deallocates all memory associated with the specified address.
+ * @param sub_addr address (within the given segment) to deallocate
+ */
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {}
+
+ /**
+ * 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
+ */
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version) {}
+};
+
+
+// TODO: Implement the following class
+struct StringFrag : public SegmentObj {
+ virtual bool isValidOffset(uint16 offset) const { return false; }
+
+ 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;
+};
+
+struct SystemStrings : public SegmentObj {
+ 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;
+ }
+ }
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+/** This struct is used to buffer the list of send calls in send_selector() */
+struct CallsStruct {
+ reg_t addr_func;
+ reg_t varp_objp;
+ union {
+ reg_t func;
+ ObjVarRef var;
+ } address;
+ StackPtr argp;
+ int argc;
+ Selector selector;
+ StackPtr sp; /**< Stack pointer */
+ int type; /**< Same as ExecStack.type */
+};
+
+struct LocalVariables : public SegmentObj {
+ int script_id; /**< Script ID this local variable block belongs to */
+ Common::Array<reg_t> _locals;
+
+public:
+ LocalVariables() {
+ script_id = 0;
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+/** Clone has been marked as 'freed' */
+#define OBJECT_FLAG_FREED (0x1 << 0)
+
+// TODO: convert to class, perhaps?
+struct Object {
+ int flags;
+ reg_t pos; /**< Object offset within its script; for clones, this is their base */
+ 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;
+
+ uint16 getVarSelector(uint16 i, SciVersion version) {
+ if (version < SCI_VERSION_1_1)
+ return READ_LE_UINT16(base_obj + _variables.size() * 2 + i * 2);
+ else
+ return *(base_vars + i);
+ }
+
+ reg_t getSpeciesSelector(SciVersion version) {
+ return _variables[version < SCI_VERSION_1_1 ? 0 : 5];
+ }
+
+ void setSpeciesSelector(reg_t value, SciVersion version) {
+ _variables[version < SCI_VERSION_1_1 ? 0 : 5] = value;
+ }
+
+ reg_t getSuperClassSelector(SciVersion version) {
+ return _variables[version < SCI_VERSION_1_1 ? 1 : 6];
+ }
+
+ void setSuperClassSelector(reg_t value, SciVersion version) {
+ _variables[version < SCI_VERSION_1_1 ? 1 : 6] = value;
+ }
+
+ reg_t getInfoSelector(SciVersion version) {
+ return _variables[version < SCI_VERSION_1_1 ? 2 : 7];
+ }
+
+ void setInfoSelector(reg_t value, SciVersion version) {
+ _variables[version < SCI_VERSION_1_1 ? 2 : 7] = value;
+ }
+
+ reg_t getNameSelector(SciVersion version) {
+ return _variables[version < SCI_VERSION_1_1 ? 3 : 8];
+ }
+
+ void setNameSelector(reg_t value, SciVersion version) {
+ _variables[version < SCI_VERSION_1_1 ? 3 : 8] = value;
+ }
+
+ reg_t getClassScriptSelector() {
+ return _variables[4];
+ }
+
+ void setClassScriptSelector(reg_t value) {
+ _variables[4] = value;
+ }
+
+ uint16 getFuncSelector(uint16 i, SciVersion version) {
+ uint16 offset = (version < SCI_VERSION_1_1) ? i : i * 2 + 1;
+ return READ_LE_UINT16((byte *) (base_method + offset));
+ }
+
+ reg_t getFunction(uint16 i, SciVersion version) {
+ uint16 offset = (version < SCI_VERSION_1_1) ? methods_nr + 1 + i : i * 2 + 2;
+ return make_reg(pos.segment, READ_LE_UINT16((byte *) (base_method + offset)));
+ }
+
+ bool isClass(SciVersion version) {
+ return (getInfoSelector(version).offset & SCRIPT_INFO_CLASS);
+ }
+};
+
+struct CodeBlock {
+ reg_t pos;
+ int size;
+};
+
+class Script : public SegmentObj {
+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 */
+
+ byte *_synonyms; /**< Synonyms block or 0 if not present*/
+ int _numSynonyms; /**< Number of entries in the synonyms block */
+
+protected:
+ int _lockers; /**< Number of classes and objects that require this script */
+
+ IntMapper *_objIndices;
+
+ SciVersion _sciVersion;
+
+public:
+ /**
+ * 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;
+
+ int _localsOffset;
+ SegmentId _localsSegment; /**< The local variable segment */
+ LocalVariables *_localsBlock;
+
+ Common::Array<CodeBlock> _codeBlocks;
+ bool _relocated;
+ bool _markedAsDeleted;
+
+public:
+ Script();
+ ~Script();
+
+ void freeScript();
+ bool init(int script_nr, ResourceManager *resMan);
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+
+ Object *allocateObject(uint16 offset);
+ Object *getObject(uint16 offset);
+
+ /**
+ * 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:
+ // 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;
+ }
+
+ /**
+ * 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);
+
+
+ /**
+ * 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;
+
+private:
+ void setScriptSize(int script_nr, ResourceManager *resMan);
+};
+
+/** Data stack */
+struct DataStack : SegmentObj {
+ int nr; /**< Number of stack entries */
+ reg_t *entries;
+
+public:
+ DataStack() {
+ nr = 0;
+ entries = NULL;
+ }
+ ~DataStack() {
+ free(entries);
+ entries = NULL;
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
+
+ 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>
+struct Table : public SegmentObj {
+ 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;
+ }
+ }
+
+ virtual bool isValidOffset(uint16 offset) const {
+ return isValidEntry(offset);
+ }
+
+ bool isValidEntry(int idx) const {
+ 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--;
+ }
+
+ 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));
+ }
+};
+
+
+/* CloneTable */
+struct CloneTable : public Table<Clone> {
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+/* NodeTable */
+struct NodeTable : public Table<Node> {
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+/* ListTable */
+struct ListTable : public Table<List> {
+ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note, SciVersion version);
+
+ 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
+struct DynMem : public SegmentObj {
+ int _size;
+ Common::String _description;
+ byte *_buf;
+
+public:
+ DynMem() : _size(0), _buf(0) {}
+ ~DynMem() {
+ free(_buf);
+ _buf = NULL;
+ }
+
+ virtual bool isValidOffset(uint16 offset) const;
+ virtual byte *dereference(reg_t pointer, int *size);
+ virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr);
+ virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note);
+
+ virtual void saveLoadWithSerializer(Common::Serializer &ser);
+};
+
+
+} // End of namespace Sci
+
+#endif // SCI_ENGINE_SEGMENT_H
Property changes on: scummvm/trunk/engines/sci/engine/segment.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Rev Author URL Id
Added: svn:eol-style
+ native
Modified: scummvm/trunk/engines/sci/module.mk
===================================================================
--- scummvm/trunk/engines/sci/module.mk 2009-09-17 13:22:15 UTC (rev 44154)
+++ scummvm/trunk/engines/sci/module.mk 2009-09-17 13:22:46 UTC (rev 44155)
@@ -26,12 +26,12 @@
engine/ksound.o \
engine/kstring.o \
engine/message.o \
- engine/memobj.o \
engine/said.o \
engine/savegame.o \
engine/script.o \
engine/scriptdebug.o \
engine/seg_manager.o \
+ engine/segment.o \
engine/static_selectors.o \
engine/stringfrag.o \
engine/state.o \
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list