aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sword2/layers.cpp5
-rw-r--r--sword2/resman.cpp90
2 files changed, 56 insertions, 39 deletions
diff --git a/sword2/layers.cpp b/sword2/layers.cpp
index c4cc23e085..a4eaa035f5 100644
--- a/sword2/layers.cpp
+++ b/sword2/layers.cpp
@@ -54,7 +54,6 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
int i;
assert(res);
- debug(1, "CHANGED TO LOCATION \"%s\"", fetchObjectName(res, buf));
// The resources age every time a new room is entered.
_resman->passTime();
@@ -63,6 +62,8 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
clearFxQueue();
_graphics->waitForFade();
+ debug(1, "CHANGED TO LOCATION \"%s\"", fetchObjectName(res, buf));
+
// if last screen was using a shading mask (see below)
if (_thisScreen.mask_flag) {
if (_graphics->closeLightMask() != RD_OK)
@@ -187,7 +188,7 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
_graphics->initialiseBackgroundLayer(NULL);
}
- _resman->closeResource(_thisScreen.background_layer_id);
+ _resman->closeResource(_thisScreen.background_layer_id);
return IR_CONT;
}
diff --git a/sword2/resman.cpp b/sword2/resman.cpp
index 1882fa045e..b21398a547 100644
--- a/sword2/resman.cpp
+++ b/sword2/resman.cpp
@@ -39,20 +39,6 @@ namespace Sword2 {
// resource.tab which is a table which tells us which cluster a resource
// is located in and the number within the cluster
-// If 0, resouces are expelled immediately when they are closed. At the moment
-// this causes the sound queue to run out of slots. My only theory is that it's
-// a script that gets reloaded over and over. That'd clear its local variables
-// which I guess may cause it to set up the sounds over and over.
-
-#define CACHE_CLUSTERS 1
-
-// Resources age every time a new room is entered. This constant indicates how
-// long a cached resource (i.e. one that has been closed) is allowed to live
-// before it dies of old age. This may need some tuning, but I picked three
-// because so many areas in the game seem to consist of about three rooms.
-
-#define MAX_CACHE_AGE 3
-
enum {
BOTH = 0x0, // Cluster is on both CDs
CD1 = 0x1, // Cluster is on CD1 only
@@ -471,51 +457,51 @@ byte *ResourceManager::openResource(uint32 res, bool dump) {
if (dump) {
StandardHeader *header = (StandardHeader *) _resList[res].ptr;
char buf[256];
- char tag[10];
+ const char *tag;
File out;
switch (header->fileType) {
case ANIMATION_FILE:
- strcpy(tag, "anim");
+ tag = "anim";
break;
case SCREEN_FILE:
- strcpy(tag, "layer");
+ tag = "layer";
break;
case GAME_OBJECT:
- strcpy(tag, "object");
+ tag = "object";
break;
case WALK_GRID_FILE:
- strcpy(tag, "walkgrid");
+ tag = "walkgrid";
break;
case GLOBAL_VAR_FILE:
- strcpy(tag, "globals");
+ tag = "globals";
break;
case PARALLAX_FILE_null:
- strcpy(tag, "parallax"); // Not used!
+ tag = "parallax"; // Not used!
break;
case RUN_LIST:
- strcpy(tag, "runlist");
+ tag = "runlist";
break;
case TEXT_FILE:
- strcpy(tag, "text");
+ tag = "text";
break;
case SCREEN_MANAGER:
- strcpy(tag, "screen");
+ tag = "screen";
break;
case MOUSE_FILE:
- strcpy(tag, "mouse");
+ tag = "mouse";
break;
case WAV_FILE:
- strcpy(tag, "wav");
+ tag = "wav";
break;
case ICON_FILE:
- strcpy(tag, "icon");
+ tag = "icon";
break;
case PALETTE_FILE:
- strcpy(tag, "palette");
+ tag = "palette";
break;
default:
- strcpy(tag, "unknown");
+ tag = "unknown";
break;
}
@@ -555,13 +541,15 @@ void ResourceManager::closeResource(uint32 res) {
_resList[res].refCount--;
_resList[res].refTime = _resTime;
-#if !CACHE_CLUSTERS
- // Maybe it's useful on some platforms if memory is released as
- // quickly as possible?
-
- if (_resList[res].refCount == 0)
- remove(res);
-#endif
+ // It's tempting to free the resource immediately when refCount
+ // reaches zero, but that'd be a mistake. Closing a resource does not
+ // mean "I'm not going to use this resource any more". It means that
+ // "the next time I use this resource I'm going to ask for a new
+ // pointer to it".
+ //
+ // Since the original memory manager had to deal with memory
+ // fragmentation, keeping a resource open - and thus locked down to a
+ // specific memory address - was considered a bad thing.
}
/**
@@ -633,11 +621,39 @@ uint32 ResourceManager::fetchLen(uint32 res) {
return file.readUint32LE();
}
+// When a resource is opened, regardless of whether it was read from disk or
+// from the cache, its age is zeroed. They then age every time a new room is
+// entered. This function is responsible for cleaning out the resources that
+// have grown too old to live.
+//
+// It could use a bit more tuning, I guess. I picked a max age of three for
+// most resources, because so much of the game seems to consist of areas of
+// about three rooms. I made an exception for SCREEN_FILE resources because
+// they are so large, but maybe the exception ought to be the rule...?
+
void ResourceManager::expireOldResources() {
int nuked = 0;
for (uint i = 0; i < _totalResFiles; i++) {
- if (_resList[i].ptr && _resList[i].refCount == 0 && _resTime - _resList[i].refTime >= MAX_CACHE_AGE) {
+ if (!_resList[i].ptr || _resList[i].refCount > 0)
+ continue;
+
+ StandardHeader *head = (StandardHeader *) _resList[i].ptr;
+ uint maxCacheAge;
+
+ switch (head->fileType) {
+ case SCREEN_FILE:
+ // The resource will be read from disk once as soon as
+ // the player enters the room, and thrown away when
+ // the player enters a new room.
+ maxCacheAge = 0;
+ break;
+ default:
+ maxCacheAge = 3;
+ break;
+ }
+
+ if (_resTime - _resList[i].refTime >= maxCacheAge) {
remove(i);
nuked++;
}