aboutsummaryrefslogtreecommitdiff
path: root/scumm
diff options
context:
space:
mode:
authorMax Horn2003-06-26 00:47:39 +0000
committerMax Horn2003-06-26 00:47:39 +0000
commit3c296b36b7a2cbf9bd049e65810f1d5c43fe6573 (patch)
tree7ff5ab22bd2e6476d14156040505738dbc80f309 /scumm
parent7f3118f8d864f6d0beec385cb5776979581d6e2a (diff)
downloadscummvm-rg350-3c296b36b7a2cbf9bd049e65810f1d5c43fe6573.tar.gz
scummvm-rg350-3c296b36b7a2cbf9bd049e65810f1d5c43fe6573.tar.bz2
scummvm-rg350-3c296b36b7a2cbf9bd049e65810f1d5c43fe6573.zip
added ResourceIterator, replacing two of the old findResource/findResourceSmall function - contraty to those, this approach is thread safe
svn-id: r8650
Diffstat (limited to 'scumm')
-rw-r--r--scumm/object.cpp41
-rw-r--r--scumm/resource.cpp114
-rw-r--r--scumm/resource.h13
-rw-r--r--scumm/scummvm.cpp9
4 files changed, 80 insertions, 97 deletions
diff --git a/scumm/object.cpp b/scumm/object.cpp
index 4ae64274b0..2c285b12e7 100644
--- a/scumm/object.cpp
+++ b/scumm/object.cpp
@@ -533,10 +533,11 @@ void Scumm::loadRoomObjects() {
assert(searchptr);
// Load in new room objects
+ ResourceIterator obcds(searchptr, false);
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
- ptr = findResource(MKID('OBCD'), searchptr);
+ ptr = obcds.findNext(MKID('OBCD'));
if (ptr == NULL)
error("Room %d missing object code block(s)", _roomResource);
@@ -553,16 +554,16 @@ void Scumm::loadRoomObjects() {
if (_dumpScripts) {
char buf[32];
sprintf(buf, "roomobj-%d-", _roomResource);
- ptr = findResource(MKID('VERB'), ptr, 0);
+ ptr = findResource(MKID('VERB'), ptr);
dumpResource(buf, od->obj_nr, ptr);
}
- searchptr = NULL;
}
searchptr = room;
+ ResourceIterator obims(room, false);
for (i = 0; i < _numObjectsInRoom; i++) {
- ptr = findResource(MKID('OBIM'), searchptr);
+ ptr = obims.findNext(MKID('OBIM'));
if (ptr == NULL)
error("Room %d missing image blocks(s)", _roomResource);
@@ -580,7 +581,6 @@ void Scumm::loadRoomObjects() {
if (_objs[j].obj_nr == obim_id)
_objs[j].OBIMoffset = ptr - room;
}
- searchptr = NULL;
}
for (i = 1; i < _numLocalObjects; i++) {
@@ -636,7 +636,7 @@ void Scumm::loadRoomObjectsSmall() {
ObjectData *od;
const byte *ptr;
uint16 obim_id;
- const byte *room, *searchptr;
+ const byte *room;
const RoomHeader *roomhdr;
CHECK_HEAP
@@ -651,11 +651,11 @@ void Scumm::loadRoomObjectsSmall() {
if (_numObjectsInRoom > _numLocalObjects)
error("More than %d objects in room %d", _numLocalObjects, _roomResource);
- searchptr = room;
+ ResourceIterator obcds(room, true);
for (i = 0; i < _numObjectsInRoom; i++) {
od = &_objs[findLocalObjectSlot()];
- ptr = findResourceSmall(MKID('OBCD'), searchptr);
+ ptr = obcds.findNext(MKID('OBCD'));
if (ptr == NULL)
error("Room %d missing object code block(s)", _roomResource);
@@ -666,13 +666,11 @@ void Scumm::loadRoomObjectsSmall() {
sprintf(buf, "roomobj-%d-", _roomResource);
dumpResource(buf, od->obj_nr, ptr);
}
-
- searchptr = NULL;
}
- searchptr = room;
+ ResourceIterator obims(room, true);
for (i = 0; i < _numObjectsInRoom; i++) {
- ptr = findResourceSmall(MKID('OBIM'), searchptr);
+ ptr = obims.findNext(MKID('OBIM'));
if (ptr == NULL)
error("Room %d missing image blocks(s)", _roomResource);
@@ -682,7 +680,6 @@ void Scumm::loadRoomObjectsSmall() {
if (_objs[j].obj_nr == obim_id)
_objs[j].OBIMoffset = ptr - room;
}
- searchptr = NULL;
}
for (i = 1; i < _numLocalObjects; i++) {
@@ -1090,11 +1087,9 @@ void Scumm::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, uint
else
searchptr = roomptr;
assert(searchptr);
+ ResourceIterator obcds(searchptr, _features & GF_SMALL_HEADER);
for (i = 0;;) {
- if (_features & GF_SMALL_HEADER)
- obcdptr = findResourceSmall(MKID('OBCD'), searchptr);
- else
- obcdptr = findResource(MKID('OBCD'), searchptr);
+ obcdptr = obcds.findNext(MKID('OBCD'));
if (obcdptr == NULL)
error("findObjectInRoom: Not enough code blocks in room %d", room);
cdhd = (const CodeHeader *)findResourceData(MKID('CDHD'), obcdptr);
@@ -1115,19 +1110,14 @@ void Scumm::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, uint
}
if (++i == numobj)
error("findObjectInRoom: Object %d not found in room %d", id, room);
- searchptr = NULL;
}
}
roomptr = fo->roomptr;
if (findWhat & foImageHeader) {
- searchptr = roomptr;
- assert(searchptr);
+ ResourceIterator obims(roomptr, _features & GF_SMALL_HEADER);
for (i = 0;;) {
- if (_features & GF_SMALL_HEADER)
- obimptr = findResourceSmall(MKID('OBIM'), searchptr);
- else
- obimptr = findResource(MKID('OBIM'), searchptr);
+ obimptr = obims.findNext(MKID('OBIM'));
if (obimptr == NULL)
error("findObjectInRoom: Not enough image blocks in room %d", room);
imhd = (const ImageHeader *)findResourceData(MKID('IMHD'), obimptr);
@@ -1149,7 +1139,6 @@ void Scumm::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, uint
}
if (++i == numobj)
error("findObjectInRoom: Object %d image not found in room %d", id, room);
- searchptr = NULL;
}
}
}
@@ -1640,7 +1629,7 @@ void Scumm::loadFlObject(uint object, uint room) {
char buf[32];
const byte *ptr = foir.obcd;
sprintf(buf, "roomobj-%d-", room);
- ptr = findResource(MKID('VERB'), ptr, 0);
+ ptr = findResource(MKID('VERB'), ptr);
dumpResource(buf, object, ptr);
}
diff --git a/scumm/resource.cpp b/scumm/resource.cpp
index 8cd61c5166..3e3ed7b522 100644
--- a/scumm/resource.cpp
+++ b/scumm/resource.cpp
@@ -1349,9 +1349,9 @@ const byte *Scumm::findResourceData(uint32 tag, const byte *ptr) {
if (_features & GF_OLD_BUNDLE)
error("findResourceData must not be used in GF_OLD_BUNDLE games");
else if (_features & GF_SMALL_HEADER)
- ptr = findResourceSmall(tag, ptr, 0);
+ ptr = findResourceSmall(tag, ptr);
else
- ptr = findResource(tag, ptr, 0);
+ ptr = findResource(tag, ptr);
if (ptr == NULL)
return NULL;
@@ -1370,72 +1370,58 @@ int Scumm::getResourceDataSize(const byte *ptr) const {
return READ_BE_UINT32(ptr - 4) - 8;
}
-struct FindResourceState {
- uint32 size, pos;
- const byte *ptr;
-};
-
-/* just O(N) complexity when iterating with this function */
-const byte *findResource(uint32 tag, const byte *searchin) {
- uint32 size;
- static FindResourceState frs;
- FindResourceState *f = &frs; /* easier to make it thread safe like this */
-
- if (searchin) {
- f->size = READ_BE_UINT32(searchin + 4);
- f->pos = 8;
- f->ptr = searchin + 8;
- goto StartScan;
+ResourceIterator::ResourceIterator(const byte *searchin, bool smallHeader)
+ : _ptr(searchin), _smallHeader(smallHeader) {
+ assert(searchin);
+ if (_smallHeader) {
+ _size = READ_LE_UINT32(searchin);
+ _pos = 6;
+ _ptr = searchin + 6;
+ } else {
+ _size = READ_BE_UINT32(searchin + 4);
+ _pos = 8;
+ _ptr = searchin + 8;
}
-
- do {
- size = READ_BE_UINT32(f->ptr + 4);
- if ((int32)size <= 0)
- return NULL;
-
- f->pos += size;
- f->ptr += size;
-
- StartScan:
- if (f->pos >= f->size)
- return NULL;
- } while (READ_UINT32(f->ptr) != tag);
-
- return f->ptr;
+
}
-const byte *findResourceSmall(uint32 tag, const byte *searchin) {
- uint32 size;
- static FindResourceState frs;
- FindResourceState *f = &frs; /* easier to make it thread safe like this */
- uint16 smallTag;
-
- smallTag = newTag2Old(tag);
-
- if (searchin) {
- f->size = READ_LE_UINT32(searchin);
- f->pos = 6;
- f->ptr = searchin + 6;
- goto StartScan;
+const byte *ResourceIterator::findNext(uint32 tag) {
+ uint32 size = 0;
+ const byte *result = 0;
+
+ if (_smallHeader) {
+ uint16 smallTag = newTag2Old(tag);
+ do {
+ if (_pos >= _size)
+ return 0;
+
+ result = _ptr;
+ size = READ_LE_UINT32(result);
+ if ((int32)size <= 0)
+ return 0; // Avoid endless loop
+
+ _pos += size;
+ _ptr += size;
+ } while (READ_LE_UINT16(result + 4) != smallTag);
+ } else {
+ do {
+ if (_pos >= _size)
+ return 0;
+
+ result = _ptr;
+ size = READ_BE_UINT32(result + 4);
+ if ((int32)size <= 0)
+ return 0; // Avoid endless loop
+
+ _pos += size;
+ _ptr += size;
+ } while (READ_UINT32(result) != tag);
}
- do {
- size = READ_LE_UINT32(f->ptr);
- if ((int32)size <= 0)
- return NULL;
-
- f->pos += size;
- f->ptr += size;
-
- StartScan:
- if (f->pos >= f->size)
- return NULL;
- } while (READ_LE_UINT16(f->ptr + 4) != smallTag);
-
- return f->ptr;
+ return result;
}
-const byte *findResource(uint32 tag, const byte *searchin, int idx) {
+const byte *findResource(uint32 tag, const byte *searchin) {
uint32 curpos, totalsize, size;
assert(searchin);
@@ -1446,7 +1432,7 @@ const byte *findResource(uint32 tag, const byte *searchin, int idx) {
searchin += 4;
while (curpos < totalsize) {
- if (READ_UINT32(searchin) == tag && !idx--)
+ if (READ_UINT32(searchin) == tag)
return searchin;
size = READ_BE_UINT32(searchin + 4);
@@ -1463,7 +1449,7 @@ const byte *findResource(uint32 tag, const byte *searchin, int idx) {
return NULL;
}
-const byte *findResourceSmall(uint32 tag, const byte *searchin, int idx) {
+const byte *findResourceSmall(uint32 tag, const byte *searchin) {
uint32 curpos, totalsize, size;
uint16 smallTag;
@@ -1478,7 +1464,7 @@ const byte *findResourceSmall(uint32 tag, const byte *searchin, int idx) {
while (curpos < totalsize) {
size = READ_LE_UINT32(searchin);
- if (READ_LE_UINT16(searchin + 4) == smallTag && !idx--)
+ if (READ_LE_UINT16(searchin + 4) == smallTag)
return searchin;
if ((int32)size <= 0) {
diff --git a/scumm/resource.h b/scumm/resource.h
index a3be6a74a3..d89c5266cf 100644
--- a/scumm/resource.h
+++ b/scumm/resource.h
@@ -50,9 +50,18 @@ enum {
};
-const byte *findResource(uint32 tag, const byte *searchin, int index);
-const byte *findResourceSmall(uint32 tag, const byte *searchin, int index);
const byte *findResource(uint32 tag, const byte *searchin);
const byte *findResourceSmall(uint32 tag, const byte *searchin);
+class ResourceIterator {
+ uint32 _size;
+ uint32 _pos;
+ const byte *_ptr;
+ bool _smallHeader;
+public:
+ ResourceIterator(const byte *searchin, bool smallHeader);
+ const byte *findNext(uint32 tag);
+};
+
+
#endif
diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp
index d25cb0f24f..d5d1a9746f 100644
--- a/scumm/scummvm.cpp
+++ b/scumm/scummvm.cpp
@@ -1662,7 +1662,8 @@ void Scumm::initRoomSubBlocks() {
}
}
} else if (_features & GF_SMALL_HEADER) {
- while ((ptr = findResourceSmall(MKID('LSCR'), searchptr)) != NULL) {
+ ResourceIterator localScriptIterator(searchptr, true);
+ while ((ptr = localScriptIterator.findNext(MKID('LSCR'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
id = ptr[0];
@@ -1674,10 +1675,10 @@ void Scumm::initRoomSubBlocks() {
}
_localScriptList[id - _numGlobalScripts] = ptr + 1 - roomptr;
- searchptr = NULL;
}
} else {
- while ((ptr = findResource(MKID('LSCR'), searchptr)) != NULL) {
+ ResourceIterator localScriptIterator(searchptr, false);
+ while ((ptr = localScriptIterator.findNext(MKID('LSCR'))) != NULL) {
int id = 0;
ptr += _resourceHeaderSize; /* skip tag & size */
@@ -1700,8 +1701,6 @@ void Scumm::initRoomSubBlocks() {
sprintf(buf, "room-%d-", _roomResource);
dumpResource(buf, id, ptr - _resourceHeaderSize);
}
-
- searchptr = NULL;
}
}