added ResourceIterator, replacing two of the old findResource/findResourceSmall function - contraty to those, this approach is thread safe

svn-id: r8650
This commit is contained in:
Max Horn 2003-06-26 00:47:39 +00:00
parent 7f3118f8d8
commit 3c296b36b7
4 changed files with 85 additions and 102 deletions

View File

@ -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);
}

View File

@ -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;
};
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;
}
}
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);
}
return result;
}
/* 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;
}
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;
}
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;
}
const byte *findResource(uint32 tag, const byte *searchin, int idx) {
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) {

View File

@ -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

View File

@ -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;
}
}