aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2011-05-11 17:07:31 +0200
committerMax Horn2011-05-13 11:47:09 +0200
commit26efa39d2caa0b6bb7da8414382eb5643c108261 (patch)
tree6cd58f9ec1c908d26e983a68c815c21d520bd9b6
parent45e65d7ea04b10cf7bb5282bd66b8df609700a63 (diff)
downloadscummvm-rg350-26efa39d2caa0b6bb7da8414382eb5643c108261.tar.gz
scummvm-rg350-26efa39d2caa0b6bb7da8414382eb5643c108261.tar.bz2
scummvm-rg350-26efa39d2caa0b6bb7da8414382eb5643c108261.zip
SCUMM: Document and cleanup resource type mode
-rw-r--r--engines/scumm/resource.cpp80
-rw-r--r--engines/scumm/resource.h27
-rw-r--r--engines/scumm/saveload.cpp14
-rw-r--r--engines/scumm/scumm.cpp2
4 files changed, 74 insertions, 49 deletions
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 76b6830137..7f88def0ad 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -526,28 +526,28 @@ int ScummEngine_v70he::readResTypeList(int id) {
return num;
}
-void ResourceManager::allocResTypeData(int id, uint32 tag, int num_, const char *name_, int mode_) {
- debug(9, "allocResTypeData(%s/%s,%s,%d,%d)", resTypeFromId(id), name_, tag2str(TO_BE_32(tag)), num_, mode_);
+void ResourceManager::allocResTypeData(int id, uint32 tag, int num, const char *name, ResTypeMode mode) {
+ debug(9, "allocResTypeData(%s/%s,%s,%d,%d)", resTypeFromId(id), name, tag2str(TO_BE_32(tag)), num, mode);
assert(id >= 0 && id < (int)(ARRAYSIZE(_types)));
- if (num_ >= 8000)
- error("Too many %ss (%d) in directory", name_, num_);
+ if (num >= 8000)
+ error("Too many %ss (%d) in directory", name, num);
- _types[id].mode = mode_;
- _types[id].num = num_;
- _types[id].tags = tag;
- _types[id].name = name_;
- _types[id].address = (byte **)calloc(num_, sizeof(void *));
- _types[id].flags = (byte *)calloc(num_, sizeof(byte));
- _types[id].status = (byte *)calloc(num_, sizeof(byte));
+ _types[id]._mode = mode;
+ _types[id].num = num;
+ _types[id].tag = tag;
+ _types[id].name = name;
+ _types[id].address = (byte **)calloc(num, sizeof(void *));
+ _types[id].flags = (byte *)calloc(num, sizeof(byte));
+ _types[id].status = (byte *)calloc(num, sizeof(byte));
- if (mode_) {
- _types[id].roomno = (byte *)calloc(num_, sizeof(byte));
- _types[id].roomoffs = (uint32 *)calloc(num_, sizeof(uint32));
+ if (mode) {
+ _types[id].roomno = (byte *)calloc(num, sizeof(byte));
+ _types[id].roomoffs = (uint32 *)calloc(num, sizeof(uint32));
}
if (_vm->_game.heversion >= 70) {
- _types[id].globsize = (uint32 *)calloc(num_, sizeof(uint32));
+ _types[id].globsize = (uint32 *)calloc(num, sizeof(uint32));
}
}
@@ -669,7 +669,7 @@ int ScummEngine::loadResource(int type, int idx) {
tag = _fileHandle->readUint32BE();
- if (tag != _res->_types[type].tags && _game.heversion < 70) {
+ if (tag != _res->_types[type].tag && _game.heversion < 70) {
error("%s %d not in room %d at %d+%d in file %s",
_res->_types[type].name, idx, roomNr,
_fileOffset, fileOffs, _fileHandle->getName());
@@ -734,11 +734,13 @@ byte *ScummEngine::getResourceAddress(int type, int idx) {
return NULL;
}
- if (_res->_types[type].mode && !_res->_types[type].address[idx]) {
+ // If the resource is missing, but loadable from the game data files, try to do so.
+ if (!_res->_types[type].address[idx] && _res->_types[type]._mode != kDynamicResTypeMode) {
ensureResourceLoaded(type, idx);
}
- if (!(ptr = (byte *)_res->_types[type].address[idx])) {
+ ptr = (byte *)_res->_types[type].address[idx];
+ if (!ptr) {
debugC(DEBUG_RESOURCE, "getResourceAddress(%s,%d) == NULL", resTypeFromId(type), idx);
return NULL;
}
@@ -978,7 +980,9 @@ void ResourceManager::expireResources(uint32 size) {
best_counter = 2;
for (i = rtFirst; i <= rtLast; i++)
- if (_types[i].mode) {
+ if (_types[i]._mode != kDynamicResTypeMode) {
+ // Resources of this type can be reloaded from the data files,
+ // so we can potentially unload them to free memory.
for (j = _types[i].num; --j >= 0;) {
flag = _types[i].flags[j];
if (!(flag & RF_LOCK) && flag >= best_counter && _types[i].address[j] && !_vm->isResourceInUse(i, j)) {
@@ -1275,30 +1279,30 @@ void ScummEngine::allocateArrays() {
}
_res->allocResTypeData(rtCostume, (_game.features & GF_NEW_COSTUMES) ? MKTAG('A','K','O','S') : MKTAG('C','O','S','T'),
- _numCostumes, "costume", 1);
- _res->allocResTypeData(rtRoom, MKTAG('R','O','O','M'), _numRooms, "room", 1);
- _res->allocResTypeData(rtRoomImage, MKTAG('R','M','I','M'), _numRooms, "room image", 1);
- _res->allocResTypeData(rtRoomScripts, MKTAG('R','M','S','C'), _numRooms, "room script", 1);
- _res->allocResTypeData(rtSound, MKTAG('S','O','U','N'), _numSounds, "sound", 2);
- _res->allocResTypeData(rtScript, MKTAG('S','C','R','P'), _numScripts, "script", 1);
- _res->allocResTypeData(rtCharset, MKTAG('C','H','A','R'), _numCharsets, "charset", 1);
- _res->allocResTypeData(rtObjectName, 0, _numNewNames, "new name", 0);
- _res->allocResTypeData(rtInventory, 0, _numInventory, "inventory", 0);
- _res->allocResTypeData(rtTemp, 0, 10, "temp", 0);
- _res->allocResTypeData(rtScaleTable, 0, 5, "scale table", 0);
- _res->allocResTypeData(rtActorName, 0, _numActors, "actor name", 0);
- _res->allocResTypeData(rtVerb, 0, _numVerbs, "verb", 0);
- _res->allocResTypeData(rtString, 0, _numArray, "array", 0);
- _res->allocResTypeData(rtFlObject, 0, _numFlObject, "flobject", 0);
- _res->allocResTypeData(rtMatrix, 0, 10, "boxes", 0);
- _res->allocResTypeData(rtImage, MKTAG('A','W','I','Z'), _numImages, "images", 1);
- _res->allocResTypeData(rtTalkie, MKTAG('T','L','K','E'), _numTalkies, "talkie", 1);
+ _numCostumes, "costume", kStaticResTypeMode);
+ _res->allocResTypeData(rtRoom, MKTAG('R','O','O','M'), _numRooms, "room", kStaticResTypeMode);
+ _res->allocResTypeData(rtRoomImage, MKTAG('R','M','I','M'), _numRooms, "room image", kStaticResTypeMode);
+ _res->allocResTypeData(rtRoomScripts, MKTAG('R','M','S','C'), _numRooms, "room script", kStaticResTypeMode);
+ _res->allocResTypeData(rtSound, MKTAG('S','O','U','N'), _numSounds, "sound", kSoundResTypeMode);
+ _res->allocResTypeData(rtScript, MKTAG('S','C','R','P'), _numScripts, "script", kStaticResTypeMode);
+ _res->allocResTypeData(rtCharset, MKTAG('C','H','A','R'), _numCharsets, "charset", kStaticResTypeMode);
+ _res->allocResTypeData(rtObjectName, 0, _numNewNames, "new name", kDynamicResTypeMode);
+ _res->allocResTypeData(rtInventory, 0, _numInventory, "inventory", kDynamicResTypeMode);
+ _res->allocResTypeData(rtTemp, 0, 10, "temp", kDynamicResTypeMode);
+ _res->allocResTypeData(rtScaleTable, 0, 5, "scale table", kDynamicResTypeMode);
+ _res->allocResTypeData(rtActorName, 0, _numActors, "actor name", kDynamicResTypeMode);
+ _res->allocResTypeData(rtVerb, 0, _numVerbs, "verb", kDynamicResTypeMode);
+ _res->allocResTypeData(rtString, 0, _numArray, "array", kDynamicResTypeMode);
+ _res->allocResTypeData(rtFlObject, 0, _numFlObject, "flobject", kDynamicResTypeMode);
+ _res->allocResTypeData(rtMatrix, 0, 10, "boxes", kDynamicResTypeMode);
+ _res->allocResTypeData(rtImage, MKTAG('A','W','I','Z'), _numImages, "images", kStaticResTypeMode);
+ _res->allocResTypeData(rtTalkie, MKTAG('T','L','K','E'), _numTalkies, "talkie", kStaticResTypeMode);
}
void ScummEngine_v70he::allocateArrays() {
ScummEngine::allocateArrays();
- _res->allocResTypeData(rtSpoolBuffer, 0, 9, "spool buffer", 1);
+ _res->allocResTypeData(rtSpoolBuffer, 0, 9, "spool buffer", kStaticResTypeMode);
_heV7RoomIntOffsets = (uint32 *)calloc(_numRooms, sizeof(uint32));
}
diff --git a/engines/scumm/resource.h b/engines/scumm/resource.h
index b3cb424d4f..8540ef3138 100644
--- a/engines/scumm/resource.h
+++ b/engines/scumm/resource.h
@@ -50,6 +50,24 @@ enum {
class ScummEngine;
/**
+ * The mode of a resource type indicates whether the resource can be restored
+ * from the game data files or not.
+ * This affects for example whether the resource is stored in savestates.
+ *
+ * Note that we treat sound resources somewhat differently: On the one hand,
+ * these behave mostly like a kStaticResTypeMode res type. However, when we
+ * create a savestate, we do save *some* information about them: Namely, which
+ * sound resources are loaded in memory at the time the save is made. And when
+ * loading, we invoke ensureResourceLoaded() for each sound resource that was
+ * marked in this way.
+ */
+enum ResTypeMode {
+ kDynamicResTypeMode = 0, ///!< Resource is generated during runtime and may change
+ kStaticResTypeMode = 1, ///!< Resource comes from data files, does not change
+ kSoundResTypeMode = 2 ///!< Resource comes from data files, but may change
+};
+
+/**
* The 'resource manager' class. Currently doesn't really deserve to be called
* a 'class', at least until somebody gets around to OOfying this more.
*/
@@ -60,12 +78,15 @@ protected:
ScummEngine *_vm;
public:
+ /**
+ * This struct represents a resource type and all resource of that type.
+ */
class ResTypeData {
friend class ResourceManager;
public:
- byte mode;
+ ResTypeMode _mode;
uint16 num;
- uint32 tags;
+ uint32 tag;
const char *name;
byte **address;
protected:
@@ -89,7 +110,7 @@ public:
void setHeapThreshold(int min, int max);
- void allocResTypeData(int id, uint32 tag, int num, const char *name, int mode);
+ void allocResTypeData(int id, uint32 tag, int num, const char *name, ResTypeMode mode);
void freeResources();
byte *createResource(int type, int index, uint32 size);
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 424e0005f4..40dc70af4b 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -1243,7 +1243,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
// number of script resources, savegames won't break.
if (s->isSaving()) {
for (type = rtFirst; type <= rtLast; type++) {
- if (_res->_types[type].mode != 1 && type != rtTemp && type != rtBuffer) {
+ if (_res->_types[type]._mode != kStaticResTypeMode && type != rtTemp && type != rtBuffer) {
s->saveUint16(type); // Save the res type...
for (idx = 0; idx < _res->_types[type].num; idx++) {
// Only save resources which actually exist...
@@ -1269,7 +1269,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
// with index 0, and breaks whenever we change the limit on a given
// resource type.
for (type = rtFirst; type <= rtLast; type++)
- if (_res->_types[type].mode != 1 && type != rtTemp && type != rtBuffer) {
+ if (_res->_types[type]._mode != kStaticResTypeMode && type != rtTemp && type != rtBuffer) {
// For V1-V5 games, there used to be no object name resources.
// At some point this changed. But since old savegames rely on
// unchanged resource counts, we have to hard code the following check
@@ -1637,7 +1637,7 @@ void ScummEngine::saveLoadResource(Serializer *ser, int type, int idx) {
byte *ptr;
uint32 size;
- if (!_res->_types[type].mode) {
+ if (_res->_types[type]._mode == kDynamicResTypeMode) {
if (ser->isSaving()) {
ptr = _res->_types[type].address[idx];
if (ptr == NULL) {
@@ -1676,7 +1676,7 @@ void ScummEngine::saveLoadResource(Serializer *ser, int type, int idx) {
}
}
}
- } else if (_res->_types[type].mode == 2 && ser->getVersion() >= VER(23)) {
+ } else if (_res->_types[type]._mode == kSoundResTypeMode && ser->getVersion() >= VER(23)) {
// Save/load only a list of resource numbers that need to be reloaded.
if (ser->isSaving()) {
ser->saveUint16(_res->_types[type].address[idx] ? 1 : 0);
@@ -1690,7 +1690,7 @@ void ScummEngine::saveLoadResource(Serializer *ser, int type, int idx) {
void ScummEngine::saveResource(Serializer *ser, int type, int idx) {
assert(_res->_types[type].address[idx]);
- if (_res->_types[type].mode == 0) {
+ if (_res->_types[type]._mode == kDynamicResTypeMode) {
byte *ptr = _res->_types[type].address[idx];
uint32 size = ((MemBlkHeader *)ptr)->size;
@@ -1713,7 +1713,7 @@ void ScummEngine::loadResource(Serializer *ser, int type, int idx) {
assert(size);
_res->createResource(type, idx, size);
ser->loadBytes(getResourceAddress(type, idx), size);
- } else if (_res->_types[type].mode == 0) {
+ } else if (_res->_types[type]._mode == kDynamicResTypeMode) {
uint32 size = ser->loadUint32();
assert(size);
_res->createResource(type, idx, size);
@@ -1725,7 +1725,7 @@ void ScummEngine::loadResource(Serializer *ser, int type, int idx) {
if (type == rtObjectName) {
_newNames[idx] = ser->loadUint16();
}
- } else if (_res->_types[type].mode == 2) {
+ } else if (_res->_types[type]._mode == kSoundResTypeMode) {
// HE Games use sound resource 1 for speech
if (_game.heversion >= 60 && idx == 1)
return;
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index d5c2b2eeb9..e89100688a 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1233,7 +1233,7 @@ void ScummEngine::setupScumm() {
requestLoad(ConfMan.getInt("save_slot"));
}
- _res->allocResTypeData(rtBuffer, 0, 10, "buffer", 0);
+ _res->allocResTypeData(rtBuffer, 0, 10, "buffer", kDynamicResTypeMode);
setupScummVars();