mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-24 05:01:43 +00:00
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:
parent
7f3118f8d8
commit
3c296b36b7
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user