aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/seg_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/seg_manager.cpp')
-rw-r--r--engines/sci/engine/seg_manager.cpp120
1 files changed, 69 insertions, 51 deletions
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 58c2b8d3e3..95e3cd15f9 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -144,11 +144,21 @@ Script *SegManager::allocateScript(int script_nr, SegmentId *segid) {
return (Script *)mem;
}
+SegmentId SegManager::getActualSegment(SegmentId seg) const {
+ if (getSciVersion() <= SCI_VERSION_2_1_LATE) {
+ return seg;
+ } else {
+ // Return the lower 14 bits of the segment
+ return (seg & 0x3FFF);
+ }
+}
+
void SegManager::deallocate(SegmentId seg) {
- if (seg < 1 || (uint)seg >= _heap.size())
+ SegmentId actualSegment = getActualSegment(seg);
+ if (actualSegment < 1 || (uint)actualSegment >= _heap.size())
error("Attempt to deallocate an invalid segment ID");
- SegmentObj *mobj = _heap[seg];
+ SegmentObj *mobj = _heap[actualSegment];
if (!mobj)
error("Attempt to deallocate an already freed segment");
@@ -169,7 +179,7 @@ void SegManager::deallocate(SegmentId seg) {
}
delete mobj;
- _heap[seg] = NULL;
+ _heap[actualSegment] = NULL;
}
bool SegManager::isHeapObject(reg_t pos) const {
@@ -185,22 +195,24 @@ void SegManager::deallocateScript(int script_nr) {
}
Script *SegManager::getScript(const SegmentId seg) {
- if (seg < 1 || (uint)seg >= _heap.size()) {
- error("SegManager::getScript(): seg id %x out of bounds", seg);
+ SegmentId actualSegment = getActualSegment(seg);
+ if (actualSegment < 1 || (uint)actualSegment >= _heap.size()) {
+ error("SegManager::getScript(): seg id %x out of bounds", actualSegment);
}
- if (!_heap[seg]) {
- error("SegManager::getScript(): seg id %x is not in memory", seg);
+ if (!_heap[actualSegment]) {
+ error("SegManager::getScript(): seg id %x is not in memory", actualSegment);
}
- if (_heap[seg]->getType() != SEG_TYPE_SCRIPT) {
- error("SegManager::getScript(): seg id %x refers to type %d != SEG_TYPE_SCRIPT", seg, _heap[seg]->getType());
+ if (_heap[actualSegment]->getType() != SEG_TYPE_SCRIPT) {
+ error("SegManager::getScript(): seg id %x refers to type %d != SEG_TYPE_SCRIPT", actualSegment, _heap[actualSegment]->getType());
}
- return (Script *)_heap[seg];
+ return (Script *)_heap[actualSegment];
}
Script *SegManager::getScriptIfLoaded(const SegmentId seg) const {
- if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg] || _heap[seg]->getType() != SEG_TYPE_SCRIPT)
+ SegmentId actualSegment = getActualSegment(seg);
+ if (actualSegment < 1 || (uint)actualSegment >= _heap.size() || !_heap[actualSegment] || _heap[actualSegment]->getType() != SEG_TYPE_SCRIPT)
return 0;
- return (Script *)_heap[seg];
+ return (Script *)_heap[actualSegment];
}
SegmentId SegManager::findSegmentByType(int type) const {
@@ -211,19 +223,22 @@ SegmentId SegManager::findSegmentByType(int type) const {
}
SegmentObj *SegManager::getSegmentObj(SegmentId seg) const {
- if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg])
+ SegmentId actualSegment = getActualSegment(seg);
+ if (actualSegment < 1 || (uint)actualSegment >= _heap.size() || !_heap[actualSegment])
return 0;
- return _heap[seg];
+ return _heap[actualSegment];
}
SegmentType SegManager::getSegmentType(SegmentId seg) const {
- if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg])
+ SegmentId actualSegment = getActualSegment(seg);
+ if (actualSegment < 1 || (uint)actualSegment >= _heap.size() || !_heap[actualSegment])
return SEG_TYPE_INVALID;
- return _heap[seg]->getType();
+ return _heap[actualSegment]->getType();
}
SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) const {
- return getSegmentType(seg) == type ? _heap[seg] : NULL;
+ SegmentId actualSegment = getActualSegment(seg);
+ return getSegmentType(actualSegment) == type ? _heap[actualSegment] : NULL;
}
Object *SegManager::getObject(reg_t pos) const {
@@ -232,9 +247,9 @@ Object *SegManager::getObject(reg_t pos) const {
if (mobj != NULL) {
if (mobj->getType() == SEG_TYPE_CLONES) {
- CloneTable *ct = (CloneTable *)mobj;
- if (ct->isValidEntry(pos.getOffset()))
- obj = &(ct->_table[pos.getOffset()]);
+ CloneTable &ct = *(CloneTable *)mobj;
+ if (ct.isValidEntry(pos.getOffset()))
+ obj = &(ct[pos.getOffset()]);
else
warning("getObject(): Trying to get an invalid object");
} else if (mobj->getType() == SEG_TYPE_SCRIPT) {
@@ -298,7 +313,7 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) {
} else if (mobj->getType() == SEG_TYPE_CLONES) {
// It's clone table, scan all objects in it
const CloneTable *ct = (const CloneTable *)mobj;
- for (uint idx = 0; idx < ct->_table.size(); ++idx) {
+ for (uint idx = 0; idx < ct->size(); ++idx) {
if (!ct->isValidEntry(idx))
continue;
@@ -389,7 +404,7 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
offset = table->allocEntry();
reg_t addr = make_reg(_hunksSegId, offset);
- Hunk *h = &(table->_table[offset]);
+ Hunk *h = &table->at(offset);
if (!h)
return NULL_REG;
@@ -409,7 +424,7 @@ byte *SegManager::getHunkPointer(reg_t addr) {
return NULL;
}
- return (byte *)ht->_table[addr.getOffset()].mem;
+ return (byte *)ht->at(addr.getOffset()).mem;
}
Clone *SegManager::allocateClone(reg_t *addr) {
@@ -424,7 +439,7 @@ Clone *SegManager::allocateClone(reg_t *addr) {
offset = table->allocEntry();
*addr = make_reg(_clonesSegId, offset);
- return &(table->_table[offset]);
+ return &table->at(offset);
}
List *SegManager::allocateList(reg_t *addr) {
@@ -438,7 +453,7 @@ List *SegManager::allocateList(reg_t *addr) {
offset = table->allocEntry();
*addr = make_reg(_listsSegId, offset);
- return &(table->_table[offset]);
+ return &table->at(offset);
}
Node *SegManager::allocateNode(reg_t *addr) {
@@ -452,7 +467,7 @@ Node *SegManager::allocateNode(reg_t *addr) {
offset = table->allocEntry();
*addr = make_reg(_nodesSegId, offset);
- return &(table->_table[offset]);
+ return &table->at(offset);
}
reg_t SegManager::newNode(reg_t value, reg_t key) {
@@ -471,14 +486,14 @@ List *SegManager::lookupList(reg_t addr) {
return NULL;
}
- ListTable *lt = (ListTable *)_heap[addr.getSegment()];
+ ListTable &lt = *(ListTable *)_heap[addr.getSegment()];
- if (!lt->isValidEntry(addr.getOffset())) {
+ if (!lt.isValidEntry(addr.getOffset())) {
error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr));
return NULL;
}
- return &(lt->_table[addr.getOffset()]);
+ return &(lt[addr.getOffset()]);
}
Node *SegManager::lookupNode(reg_t addr, bool stopOnDiscarded) {
@@ -492,9 +507,9 @@ Node *SegManager::lookupNode(reg_t addr, bool stopOnDiscarded) {
return NULL;
}
- NodeTable *nt = (NodeTable *)_heap[addr.getSegment()];
+ NodeTable &nt = *(NodeTable *)_heap[addr.getSegment()];
- if (!nt->isValidEntry(addr.getOffset())) {
+ if (!nt.isValidEntry(addr.getOffset())) {
if (!stopOnDiscarded)
return NULL;
@@ -502,7 +517,7 @@ Node *SegManager::lookupNode(reg_t addr, bool stopOnDiscarded) {
return NULL;
}
- return &(nt->_table[addr.getOffset()]);
+ return &(nt[addr.getOffset()]);
}
SegmentRef SegManager::dereference(reg_t pointer) {
@@ -822,10 +837,13 @@ byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) {
d._size = size;
- if (size == 0)
+ // Original SCI only zeroed out heap memory on initialize
+ // They didn't do it again for every allocation
+ if (size) {
+ d._buf = (byte *)calloc(size, 1);
+ } else {
d._buf = NULL;
- else
- d._buf = (byte *)malloc(size);
+ }
d._description = descr;
@@ -855,32 +873,32 @@ SciArray<reg_t> *SegManager::allocateArray(reg_t *addr) {
offset = table->allocEntry();
*addr = make_reg(_arraysSegId, offset);
- return &(table->_table[offset]);
+ return &table->at(offset);
}
SciArray<reg_t> *SegManager::lookupArray(reg_t addr) {
if (_heap[addr.getSegment()]->getType() != SEG_TYPE_ARRAY)
error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr));
- ArrayTable *arrayTable = (ArrayTable *)_heap[addr.getSegment()];
+ ArrayTable &arrayTable = *(ArrayTable *)_heap[addr.getSegment()];
- if (!arrayTable->isValidEntry(addr.getOffset()))
+ if (!arrayTable.isValidEntry(addr.getOffset()))
error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr));
- return &(arrayTable->_table[addr.getOffset()]);
+ return &(arrayTable[addr.getOffset()]);
}
void SegManager::freeArray(reg_t addr) {
if (_heap[addr.getSegment()]->getType() != SEG_TYPE_ARRAY)
error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr));
- ArrayTable *arrayTable = (ArrayTable *)_heap[addr.getSegment()];
+ ArrayTable &arrayTable = *(ArrayTable *)_heap[addr.getSegment()];
- if (!arrayTable->isValidEntry(addr.getOffset()))
+ if (!arrayTable.isValidEntry(addr.getOffset()))
error("Attempt to use non-array %04x:%04x as array", PRINT_REG(addr));
- arrayTable->_table[addr.getOffset()].destroy();
- arrayTable->freeEntry(addr.getOffset());
+ arrayTable[addr.getOffset()].destroy();
+ arrayTable.freeEntry(addr.getOffset());
}
SciString *SegManager::allocateString(reg_t *addr) {
@@ -895,32 +913,32 @@ SciString *SegManager::allocateString(reg_t *addr) {
offset = table->allocEntry();
*addr = make_reg(_stringSegId, offset);
- return &(table->_table[offset]);
+ return &table->at(offset);
}
SciString *SegManager::lookupString(reg_t addr) {
if (_heap[addr.getSegment()]->getType() != SEG_TYPE_STRING)
error("lookupString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr));
- StringTable *stringTable = (StringTable *)_heap[addr.getSegment()];
+ StringTable &stringTable = *(StringTable *)_heap[addr.getSegment()];
- if (!stringTable->isValidEntry(addr.getOffset()))
+ if (!stringTable.isValidEntry(addr.getOffset()))
error("lookupString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr));
- return &(stringTable->_table[addr.getOffset()]);
+ return &(stringTable[addr.getOffset()]);
}
void SegManager::freeString(reg_t addr) {
if (_heap[addr.getSegment()]->getType() != SEG_TYPE_STRING)
error("freeString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr));
- StringTable *stringTable = (StringTable *)_heap[addr.getSegment()];
+ StringTable &stringTable = *(StringTable *)_heap[addr.getSegment()];
- if (!stringTable->isValidEntry(addr.getOffset()))
+ if (!stringTable.isValidEntry(addr.getOffset()))
error("freeString: Attempt to use non-string %04x:%04x as string", PRINT_REG(addr));
- stringTable->_table[addr.getOffset()].destroy();
- stringTable->freeEntry(addr.getOffset());
+ stringTable[addr.getOffset()].destroy();
+ stringTable.freeEntry(addr.getOffset());
}
#endif