aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorColin Snover2016-07-20 10:40:02 -0500
committerColin Snover2016-08-01 10:37:14 -0500
commit4a637d65c36d7dad3a4d4ec75c243e12bb3b5449 (patch)
tree6432032555fae63886c62cbf578321435e48a4e2 /engines/sci/engine
parent3645ec0d0d9b88bd0a18e52d83060a8115030a65 (diff)
downloadscummvm-rg350-4a637d65c36d7dad3a4d4ec75c243e12bb3b5449.tar.gz
scummvm-rg350-4a637d65c36d7dad3a4d4ec75c243e12bb3b5449.tar.bz2
scummvm-rg350-4a637d65c36d7dad3a4d4ec75c243e12bb3b5449.zip
SCI32: Enable optional explicit memory management of hunk entries
Bitmaps in ScrollWindow and Robot code are managed by the kernel and not by game scripts, although they must be able to be referenced through a reg_t. To prevent incorrect GC of bitmaps that are in use but not referenced by any game script, explicit memory management of hunk entries can be enabled.
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/gc.cpp29
-rw-r--r--engines/sci/engine/kgraphics32.cpp8
-rw-r--r--engines/sci/engine/kscripts.cpp2
-rw-r--r--engines/sci/engine/seg_manager.cpp3
-rw-r--r--engines/sci/engine/seg_manager.h4
-rw-r--r--engines/sci/engine/segment.h1
6 files changed, 29 insertions, 18 deletions
diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp
index b229490570..e0467e9461 100644
--- a/engines/sci/engine/gc.cpp
+++ b/engines/sci/engine/gc.cpp
@@ -143,23 +143,30 @@ AddrSet *findAllActiveReferences(EngineState *s) {
const Common::Array<SegmentObj *> &heap = s->_segMan->getSegments();
uint heapSize = heap.size();
- // Init: Explicitly loaded scripts
for (uint i = 1; i < heapSize; i++) {
- if (heap[i] && heap[i]->getType() == SEG_TYPE_SCRIPT) {
- Script *script = (Script *)heap[i];
+ if (heap[i]) {
+ // Init: Explicitly loaded scripts
+ if (heap[i]->getType() == SEG_TYPE_SCRIPT) {
+ Script *script = (Script *)heap[i];
- if (script->getLockers()) { // Explicitly loaded?
- wm.pushArray(script->listObjectReferences());
+ if (script->getLockers()) { // Explicitly loaded?
+ wm.pushArray(script->listObjectReferences());
+ }
+ }
+
+ // Init: Explicitly opted-out hunks
+ else if (heap[i]->getType() == SEG_TYPE_HUNK) {
+ HunkTable *ht = static_cast<HunkTable *>(heap[i]);
+
+ for (uint j = 0; j < ht->_table.size(); j++) {
+ if (!ht->_table[j].data.gc) {
+ wm.push(make_reg(i, j));
+ }
+ }
}
}
}
-#ifdef ENABLE_SCI32
- // Init: ScrollWindows
- if (g_sci->_gfxControls32)
- wm.pushArray(g_sci->_gfxControls32->listObjectReferences());
-#endif
-
debugC(kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set");
processWorkList(s->_segMan, wm, heap);
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 9cfe53255b..b8682b3f47 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -195,14 +195,14 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
if (subop == 0) {
TextAlign alignment = (TextAlign)readSelectorValue(segMan, object, SELECTOR(mode));
- return g_sci->_gfxText32->createFontBitmap(width, height, rect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, true);
+ return g_sci->_gfxText32->createFontBitmap(width, height, rect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, true, true);
} else {
CelInfo32 celInfo;
celInfo.type = kCelTypeView;
celInfo.resourceId = readSelectorValue(segMan, object, SELECTOR(view));
celInfo.loopNo = readSelectorValue(segMan, object, SELECTOR(loop));
celInfo.celNo = readSelectorValue(segMan, object, SELECTOR(cel));
- return g_sci->_gfxText32->createFontBitmap(celInfo, rect, text, foreColor, backColor, fontId, skipColor, borderColor, dimmed);
+ return g_sci->_gfxText32->createFontBitmap(celInfo, rect, text, foreColor, backColor, fontId, skipColor, borderColor, dimmed, true);
}
}
@@ -534,7 +534,7 @@ reg_t kBitmapCreate(EngineState *s, int argc, reg_t *argv) {
int16 scaledHeight = argc > 5 ? argv[5].toSint16() : g_sci->_gfxText32->_scaledHeight;
bool useRemap = argc > 6 ? argv[6].toSint16() : false;
- BitmapResource bitmap(s->_segMan, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap);
+ BitmapResource bitmap(s->_segMan, width, height, skipColor, 0, 0, scaledWidth, scaledHeight, 0, useRemap, true);
memset(bitmap.getPixels(), backColor, width * height);
return bitmap.getObject();
}
@@ -604,7 +604,7 @@ reg_t kBitmapDrawText(EngineState *s, int argc, reg_t *argv) {
// Then clips. But this seems stupid.
textRect.clip(Common::Rect(bitmap.getWidth(), bitmap.getHeight()));
- reg_t textBitmapObject = g_sci->_gfxText32->createFontBitmap(textRect.width(), textRect.height(), Common::Rect(textRect.width(), textRect.height()), text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, false);
+ reg_t textBitmapObject = g_sci->_gfxText32->createFontBitmap(textRect.width(), textRect.height(), Common::Rect(textRect.width(), textRect.height()), text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, false, false);
CelObjMem textCel(textBitmapObject);
textCel.draw(bitmap.getBuffer(), textRect, Common::Point(textRect.left, textRect.top), false);
s->_segMan->freeHunkEntry(textBitmapObject);
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 6fd130bceb..42e7a2028f 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -40,7 +40,7 @@ reg_t kLoad(EngineState *s, int argc, reg_t *argv) {
// Request to dynamically allocate hunk memory for later use
if (restype == kResourceTypeMemory)
- return s->_segMan->allocateHunkEntry("kLoad()", resnr);
+ return s->_segMan->allocateHunkEntry("kLoad()", resnr, true);
return make_reg(0, ((restype << 11) | resnr)); // Return the resource identifier as handle
}
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 95e3cd15f9..e6692060b6 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -393,7 +393,7 @@ void SegManager::freeHunkEntry(reg_t addr) {
ht->freeEntryContents(addr.getOffset());
}
-reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
+reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size, bool gc) {
HunkTable *table;
int offset;
@@ -412,6 +412,7 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) {
h->mem = malloc(size);
h->size = size;
h->type = hunk_type;
+ h->gc = gc;
return addr;
}
diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h
index 9da7e58770..ba2ba33a6a 100644
--- a/engines/sci/engine/seg_manager.h
+++ b/engines/sci/engine/seg_manager.h
@@ -225,9 +225,11 @@ public:
* @param[in] size Number of bytes to allocate for the hunk entry
* @param[in] hunk_type A descriptive string for the hunk entry, for
* debugging purposes
+ * @param[in] gc Whether to make the hunk eligible for garbage
+ * collection
* @return The offset of the freshly allocated hunk entry
*/
- reg_t allocateHunkEntry(const char *hunk_type, int size);
+ reg_t allocateHunkEntry(const char *hunk_type, int size, bool gc);
/**
* Deallocates a hunk entry
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 50c77d0538..6c94c24ff9 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -205,6 +205,7 @@ struct Hunk {
void *mem;
uint32 size;
const char *type;
+ bool gc;
};
template<typename T>