diff options
Diffstat (limited to 'object.cpp')
-rw-r--r-- | object.cpp | 490 |
1 files changed, 296 insertions, 194 deletions
diff --git a/object.cpp b/object.cpp index a661a2095f..f68e48e140 100644 --- a/object.cpp +++ b/object.cpp @@ -45,31 +45,36 @@ void Scumm::putClass(int obj, int cls, bool set) { int Scumm::getOwner(int obj) { checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getOwner"); - return _objectFlagTable[obj]&OF_OWNER_MASK; + return _objectOwnerTable[obj]; } void Scumm::putOwner(int act, int owner) { checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putOwner"); - checkRange(15, 0, owner, "Owner %d out of range in putOwner"); - _objectFlagTable[act] = (_objectFlagTable[act]&~OF_OWNER_MASK) | owner; + checkRange(0xFF, 0, owner, "Owner %d out of range in putOwner"); + _objectOwnerTable[act] = owner; } int Scumm::getState(int act) { checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in getState"); - return _objectFlagTable[act]>>4; + return _objectStateTable[act]; } void Scumm::putState(int act, int state) { checkRange(_numGlobalObjects-1, 0, act, "Object %d out of range in putState"); - checkRange(15, 0, state, "State %d out of range in putState"); - _objectFlagTable[act] = (_objectFlagTable[act]&~OF_STATE_MASK) | - (state<<OF_STATE_SHL); + checkRange(0xFF, 0, state, "State %d out of range in putState"); + _objectStateTable[act] = state; +} + +int Scumm::getObjectRoom(int obj) { + checkRange(_numGlobalObjects-1, 0, obj, "Object %d out of range in getObjectRoom"); + return _objectRoomTable[obj]; } int Scumm::getObjectIndex(int object) { int i; - if ((_objectFlagTable[object]&OF_OWNER_MASK)!=OF_OWNER_ROOM) { + /* OF_OWNER_ROOM should be 0xFF for full throttle, else 0xF */ + if (_objectOwnerTable[object] != OF_OWNER_ROOM) { for (i=0; i<_maxInventoryItems; i++) if (_inventory[i] == object) return i; @@ -89,7 +94,7 @@ int Scumm::whereIsObject(int object) { if (object >= _numGlobalObjects) return WIO_NOT_FOUND; - if ((_objectFlagTable[object]&OF_OWNER_MASK)!=OF_OWNER_ROOM) { + if (_objectOwnerTable[object] != OF_OWNER_ROOM) { for (i=0; i<_maxInventoryItems; i++) if (_inventory[i] == object) return WIO_INVENTORY; @@ -106,19 +111,22 @@ int Scumm::whereIsObject(int object) { } int Scumm::getObjectOrActorXY(int object) { - if (object <= _vars[VAR_NUM_ACTOR]) { + if (object < NUM_ACTORS) { return getActorXYPos(derefActorSafe(object, "getObjectOrActorXY")); } switch(whereIsObject(object)) { case WIO_NOT_FOUND: return -1; case WIO_INVENTORY: - return getActorXYPos(derefActorSafe(_objectFlagTable[object]&OF_OWNER_MASK,"getObjectOrActorXY(2)")); + return getActorXYPos(derefActorSafe(_objectOwnerTable[object],"getObjectOrActorXY(2)")); } getObjectXYPos(object); return 0; } +/* Return the position of an object. + Returns X, Y and direction in angles + */ void Scumm::getObjectXYPos(int object) { ObjectData *od = &_objs[getObjectIndex(object)]; int state; @@ -127,31 +135,33 @@ void Scumm::getObjectXYPos(int object) { int x,y; AdjustBoxResult abr; - if (_majorScummVersion==6) { + if (_features&GF_AFTER_V6) { state = getState(object)-1; if (state<0) state = 0; if (od->fl_object_index) { ptr = getResourceAddress(rtFlObject, od->fl_object_index); - ptr = findResource(MKID('OBIM'), ptr, 0); + ptr = findResource(MKID('OBIM'), ptr); } else { ptr = getResourceAddress(rtRoom, _roomResource); ptr += od->offs_obim_to_room; } assert(ptr); - imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0); - x = od->x_pos*8 + (int16)READ_LE_UINT16(&imhd->hotspot[state].x); - y = od->y_pos*8 + (int16)READ_LE_UINT16(&imhd->hotspot[state].y); + imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr); + x = od->x_pos + (int16)READ_LE_UINT16(&imhd->hotspot[state].x); + y = od->y_pos + (int16)READ_LE_UINT16(&imhd->hotspot[state].y); } else { x = od->walk_x; y = od->walk_y; } - abr = adjustXYToBeInBox(0, x, y); - _xPos = abr.x; - _yPos = abr.y; - _dir = od->actordir&3; +// abr = adjustXYToBeInBox(0, x, y); +// _xPos = abr.x; +// _yPos = abr.y; + _xPos = x; + _yPos = y; + _dir = oldDirToNewDir(od->actordir&3); } int Scumm::getObjActToObjActDist(int a, int b) { @@ -159,10 +169,10 @@ int Scumm::getObjActToObjActDist(int a, int b) { Actor *acta = NULL; Actor *actb = NULL; - if (a<=_vars[VAR_NUM_ACTOR]) + if (a<NUM_ACTORS) acta = derefActorSafe(a, "getObjActToObjActDist"); - if (b<=_vars[VAR_NUM_ACTOR]) + if (b<NUM_ACTORS) actb = derefActorSafe(b, "getObjActToObjActDist(2)"); if (acta && actb && acta->room==actb->room && acta->room && @@ -179,7 +189,7 @@ int Scumm::getObjActToObjActDist(int a, int b) { return 0xFF; if (acta) { - AdjustBoxResult r = adjustXYToBeInBox(acta, _xPos, _yPos); + AdjustBoxResult r = adjustXYToBeInBox(acta, _xPos, _yPos, 0); _xPos = r.x; _yPos = r.y; } @@ -192,7 +202,8 @@ int Scumm::getObjActToObjActDist(int a, int b) { } int Scumm::findObject(int x, int y) { - int i,a,b; + int i,b; + byte a; for (i=1; i<=_numObjectsInRoom; i++) { if (!_objs[i].obj_nr || getClass(_objs[i].obj_nr, 32)) @@ -202,44 +213,39 @@ int Scumm::findObject(int x, int y) { a = _objs[b].parentstate; b = _objs[b].parent; if (b==0) { - if (_objs[i].x_pos <= (x>>3) && - _objs[i].numstrips + _objs[i].x_pos > (x>>3) && - _objs[i].y_pos <= (y>>3) && - _objs[i].height + _objs[i].y_pos > (y>>3)) + if (_objs[i].x_pos <= x && + _objs[i].width + _objs[i].x_pos > x && + _objs[i].y_pos <= y && + _objs[i].height + _objs[i].y_pos > y) return _objs[i].obj_nr; break; } - } while ( (_objs[b].ownerstate&OF_STATE_MASK) == a); + } while ( _objs[b].state == a); } return 0; } void Scumm::drawRoomObjects(int arg) { - int num = _numObjectsInRoom; + int i; ObjectData *od; - int a; - - if (num==0) - return; + byte a; - do { - od = &_objs[num]; - if (!od->obj_nr || !(od->ownerstate&OF_STATE_MASK)) + for(i=1; i<=_numObjectsInRoom; i++) { + od = &_objs[i]; + if (!od->obj_nr || !od->state || od->fl_object_index) continue; - do { a = od->parentstate; if (!od->parent) { - drawObject(num, arg); + drawObject(i, arg); break; } od = &_objs[od->parent]; - } while ((od->ownerstate & OF_STATE_MASK)==a); - - } while (--num); + } while (od->state==a); + } } -const uint32 state_tags[] = { +const uint32 IMxx_tags[] = { MKID('IM00'), MKID('IM01'), MKID('IM02'), @@ -272,9 +278,9 @@ void Scumm::drawObject(int obj, int arg) { od = &_objs[obj]; - xpos = od->x_pos; + xpos = od->x_pos>>3; ypos = od->y_pos; - width = od->numstrips; + width = od->width>>3; height = od->height; if (width==0 || xpos > _screenEndStrip || xpos + width < _screenStartStrip) @@ -282,13 +288,13 @@ void Scumm::drawObject(int obj, int arg) { if (od->fl_object_index) { ptr = getResourceAddress(rtFlObject, od->fl_object_index); - ptr = findResource(MKID('OBIM'), ptr, 0); + ptr = findResource(MKID('OBIM'), ptr); } else { ptr = getResourceAddress(rtRoom, _roomResource); ptr = ptr + od->offs_obim_to_room; } - ptr = findResource(state_tags[getState(od->obj_nr)], ptr, 0); + ptr = findResource(IMxx_tags[getState(od->obj_nr)], ptr); if (!ptr) return; @@ -302,19 +308,18 @@ void Scumm::drawObject(int obj, int arg) { continue; if (tmp < _screenStartStrip || tmp > _screenEndStrip) continue; - actorDrawBits[tmp] |= 0x8000; + gfxUsageBits[tmp] |= 0x80000000; if (tmp < x) x = tmp; numstrip++; } - if (numstrip!=0) - gdi.drawBitmap(ptr, _curVirtScreen, x, ypos<<3, height<<3, x-xpos, numstrip, true); - -// _drawBmpY = ypos << 3; -// gdi._numLinesToProcess = height << 3; -// _drawBmpX = x; -// drawBmp(ptr, x - xpos, b, 1, "Object", od->obj_nr); + if (numstrip!=0) { + byte flags = Gdi::dbAllowMaskOr; + if (getClass(od->obj_nr, 22)) + flags |= Gdi::dbDrawMaskOnBoth; + gdi.drawBitmap(ptr, _curVirtScreen, x, ypos, height, x-xpos, numstrip, flags); + } } void Scumm::loadRoomObjects() { @@ -322,7 +327,7 @@ void Scumm::loadRoomObjects() { ObjectData *od; byte *ptr; uint16 obim_id; - byte *room; + byte *room,*searchptr; ImageHeader *imhd; RoomHeader *roomhdr; @@ -331,7 +336,7 @@ void Scumm::loadRoomObjects() { CHECK_HEAP room = getResourceAddress(rtRoom, _roomResource); - roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room, 0); + roomhdr = (RoomHeader*)findResource(MKID('RMHD'), room); _numObjectsInRoom = READ_LE_UINT16(&roomhdr->numObjects); @@ -342,8 +347,9 @@ void Scumm::loadRoomObjects() { error("More than %d objects in room %d", _numLocalObjects, _roomResource); od = &_objs[1]; + searchptr = room; for (i=0; i<_numObjectsInRoom; i++,od++) { - ptr = findResource(MKID('OBCD'), room, i); + ptr = findResource(MKID('OBCD'), searchptr); if (ptr==NULL) error("Room %d missing object code block(s)", _roomResource); @@ -358,10 +364,12 @@ void Scumm::loadRoomObjects() { dumpResource(buf, od->obj_nr, ptr); } while (0); #endif + searchptr = NULL; } + searchptr = room; for (i=0; i<_numObjectsInRoom; i++) { - ptr = findResource(MKID('OBIM'), room, i); + ptr = findResource(MKID('OBIM'), searchptr); if (ptr==NULL) error("Room %d missing image blocks(s)", _roomResource); @@ -372,52 +380,74 @@ void Scumm::loadRoomObjects() { if (_objs[j].obj_nr==obim_id) _objs[j].offs_obim_to_room = ptr - room; } + searchptr = NULL; } od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { - ptr = room + od->offs_obcd_to_room; - cdhd = (CodeHeader*)findResource(MKID('CDHD'), ptr,0); - od->obj_nr = READ_LE_UINT16(&cdhd->obj_id); + setupRoomObject(od, room); + } - if (_majorScummVersion == 6) { - od->numstrips = READ_LE_UINT16(&cdhd->v6.w)>>3; - od->height = READ_LE_UINT16(&cdhd->v6.h)>>3; - od->x_pos = ((int16)READ_LE_UINT16(&cdhd->v6.x))>>3; - od->y_pos = ((int16)READ_LE_UINT16(&cdhd->v6.y))>>3; - if (cdhd->v6.flags == 0x80) { - od->parentstate = 1<<4; - } else { - od->parentstate = (cdhd->v6.flags&0xF)<<OF_STATE_SHL; - } - od->parent = cdhd->v6.parent; - od->actordir = cdhd->v6.actordir; + CHECK_HEAP +} + +void Scumm::setupRoomObject(ObjectData *od, byte *room) { + byte *obcd; + CodeHeader *cdhd; + ImageHeader *imhd; + + cdhd = (CodeHeader*)findResource(MKID('CDHD'), room + od->offs_obcd_to_room); + + od->obj_nr = READ_LE_UINT16(&cdhd->obj_id); + +#if !defined(FULL_THROTTLE) + if (_features & GF_AFTER_V6) { + od->width = READ_LE_UINT16(&cdhd->v6.w); + od->height = READ_LE_UINT16(&cdhd->v6.h); + od->x_pos = ((int16)READ_LE_UINT16(&cdhd->v6.x)); + od->y_pos = ((int16)READ_LE_UINT16(&cdhd->v6.y)); + if (cdhd->v6.flags == 0x80) { + od->parentstate = 1<<4; } else { - od->numstrips = cdhd->v5.w; - od->height = cdhd->v5.h; - od->x_pos = cdhd->v5.x; - od->y_pos = cdhd->v5.y; - if (cdhd->v5.flags == 0x80) { - od->parentstate = 1<<4; - } else { - od->parentstate = (cdhd->v5.flags&0xF)<<OF_STATE_SHL; - } - od->parent = cdhd->v5.parent; - od->walk_x = READ_LE_UINT16(&cdhd->v5.walk_x); - od->walk_y = READ_LE_UINT16(&cdhd->v5.walk_y); - od->actordir = cdhd->v5.actordir; + od->parentstate = (cdhd->v6.flags&0xF)<<OF_STATE_SHL; + } + od->parent = cdhd->v6.parent; + od->actordir = cdhd->v6.actordir; + } else { + od->width = cdhd->v5.w<<3; + od->height = cdhd->v5.h<<3; + od->x_pos = cdhd->v5.x<<3; + od->y_pos = cdhd->v5.y<<3; + if (cdhd->v5.flags == 0x80) { + od->parentstate = 1<<4; + } else { + od->parentstate = (cdhd->v5.flags&0xF)<<OF_STATE_SHL; } - od->fl_object_index = 0; + od->parent = cdhd->v5.parent; + od->walk_x = READ_LE_UINT16(&cdhd->v5.walk_x); + od->walk_y = READ_LE_UINT16(&cdhd->v5.walk_y); + od->actordir = cdhd->v5.actordir; } +#else + od->parent = cdhd->parent; + od->parentstate = cdhd->parentstate; - CHECK_HEAP + imhd = (ImageHeader*)findResource(MKID('IMHD'), room + od->offs_obim_to_room); + od->x_pos = imhd->x_pos; + od->y_pos = imhd->y_pos; + od->width = imhd->width; + od->height = imhd->height; + od->actordir = imhd->actordir; + +#endif + od->fl_object_index = 0; } void Scumm::fixObjectFlags() { int i; ObjectData *od = &_objs[1]; for (i=1; i<=_numObjectsInRoom; i++,od++) { - od->ownerstate = _objectFlagTable[od->obj_nr]; + od->state = _objectStateTable[od->obj_nr]; } } @@ -463,10 +493,8 @@ void Scumm::clearOwnerOf(int obj) { if (!a[0] && a[1]) { a[0] = a[1]; a[1] = 0; - ptr = getResourceAddress(rtInventory, i+1); _baseInventoryItems[i] = _baseInventoryItems[i+1]; - _baseInventoryItems[i+1] = 0; - /* TODO: some wacky write is done here */ + _baseInventoryItems[i+1] = NULL; } } return; @@ -476,18 +504,18 @@ void Scumm::clearOwnerOf(int obj) { void Scumm::removeObjectFromRoom(int obj) { int i,cnt; - uint16 *ptr; + uint32 *ptr; for(i=1; i<=_numObjectsInRoom; i++) { - if (_objs[i].obj_nr==obj) { - if (_objs[i].numstrips != 0) { - ptr = &actorDrawBits[_objs[i].x_pos]; - cnt = _objs[i].numstrips; + if (_objs[i].obj_nr==(uint16)obj) { + if (_objs[i].width != 0) { + ptr = &gfxUsageBits[_objs[i].x_pos>>3]; + cnt = _objs[i].width>>3; do { - *ptr++ |= 0x8000; + *ptr++ |= 0x80000000; } while (--cnt); } - _BgNeedsRedraw = 1; + _BgNeedsRedraw = true; return; } } @@ -506,20 +534,20 @@ void Scumm::clearDrawObjectQueue() { byte *Scumm::getObjOrActorName(int obj) { byte *objptr; - if (obj <= _vars[VAR_NUM_ACTOR]) + if (obj < NUM_ACTORS) return getActorName(derefActorSafe(obj, "getObjOrActorName")); objptr = getObjectAddress(obj); if (objptr==NULL) return (byte*)" "; - return findResource(MKID('OBNA'), objptr, 0) + 8; + return findResource(MKID('OBNA'), objptr) + 8; } uint32 Scumm::getOBCDOffs(int object) { int i; - if ((_objectFlagTable[object]&OF_OWNER_MASK)!=OF_OWNER_ROOM) + if (_objectOwnerTable[object] != OF_OWNER_ROOM) return 0; for (i=_numObjectsInRoom; i>0; i--) { if (_objs[i].obj_nr == object) { @@ -534,7 +562,7 @@ uint32 Scumm::getOBCDOffs(int object) { byte *Scumm::getObjectAddress(int obj) { int i; - if ((_objectFlagTable[obj]&OF_OWNER_MASK)!=OF_OWNER_ROOM) { + if (_objectOwnerTable[obj] != OF_OWNER_ROOM) { for(i=0; i<_maxInventoryItems; i++) { if (_inventory[i] == obj) return getResourceAddress(rtInventory, i); @@ -553,12 +581,9 @@ byte *Scumm::getObjectAddress(int obj) { void Scumm::addObjectToInventory(uint obj, uint room) { int i, slot; - byte *ptr,*obcdptr; - uint32 size,cdoffs; - int numobj; - byte *roomptr; - CodeHeader *cdhd; - RoomHeader *roomhdr; + uint32 size; + byte *obcdptr,*ptr; + FindObjectInRoom foir; debug(1,"Adding object %d from room %d into inventory", obj, room); @@ -573,37 +598,79 @@ void Scumm::addObjectToInventory(uint obj, uint room) { createResource(rtInventory, slot, size); ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index) + 64; memcpy(getResourceAddress(rtInventory, slot), ptr, size); - CHECK_HEAP + } else { + findObjectInRoom(&foir, foCodeHeader, obj, room); + size = READ_BE_UINT32_UNALIGNED(foir.obcd+4); + slot = getInventorySlot(); + _inventory[slot] = obj; + createResource(rtInventory, slot, size); + obcdptr = getResourceAddress(rtRoom, room) - foir.roomptr + foir.obcd; + memcpy(getResourceAddress(rtInventory,slot),obcdptr,size); + } + + CHECK_HEAP +} + +void Scumm::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, uint room) { + CodeHeader *cdhd; + int i, numobj; + byte *roomptr,*obcdptr,*obimptr,*searchptr; + RoomHeader *roomhdr; + ImageHeader *imhd; + + if (findWhat&foCheckAlreadyLoaded && getObjectIndex(id) != -1) { + fo->obcd = obcdptr = getObjectAddress(id); + assert((byte*)obcdptr > (byte*)256); + fo->obim = obimptr = obcdptr + READ_BE_UINT32(&((ImageHeader*)obcdptr)->size); + fo->cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr); + fo->imhd = (ImageHeader*)findResource(MKID('IMHD'), obimptr); return; } -// ensureResourceLoaded(rtRoom, room); - roomptr = getResourceAddress(rtRoom, room); - roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0); + + fo->roomptr = roomptr = getResourceAddress(rtRoom, room); + roomhdr = (RoomHeader*)findResource(MKID('RMHD'), roomptr); numobj = READ_LE_UINT16(&roomhdr->numObjects); if (numobj==0) - error("addObjectToInventory: No object found in room %d", room); + error("findObjectInRoom: No object found in room %d", room); if (numobj > _numLocalObjects) - error("addObjectToInventory: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room); - - for (i=0; i<numobj; i++) { - obcdptr = findResource(MKID('OBCD'), roomptr, i); - if(obcdptr==NULL) - error("addObjectToInventory: Not enough code blocks in room %d", room); - cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr, 0); - if ( READ_LE_UINT16(&cdhd->obj_id) == obj) { - cdoffs = obcdptr - roomptr; - size = READ_BE_UINT32_UNALIGNED(obcdptr+4); - slot = getInventorySlot(); - _inventory[slot] = obj; - createResource(rtInventory, slot, size); - obcdptr = getResourceAddress(rtRoom, room) + cdoffs; - memcpy(getResourceAddress(rtInventory,slot),obcdptr,size); - CHECK_HEAP - return; + error("findObjectInRoom: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room); + + if (findWhat & foCodeHeader) { + searchptr = roomptr; + for (i=0;;) { + obcdptr = findResource(MKID('OBCD'), searchptr); + if(obcdptr==NULL) + error("findObjectInRoom: Not enough code blocks in room %d", room); + cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcdptr, 0); + if ( READ_LE_UINT16(&cdhd->obj_id) == (uint16)id) { + fo->cdhd = cdhd; + fo->obcd = obcdptr; + break; + } + if (++i == numobj) + error("findObjectInRoom: Object %d not found in room %d", id, room); + searchptr = NULL; } } - error("addObjectToInventory: Object %d not found in room %d", obj, room); + if (findWhat & foImageHeader) { + searchptr = roomptr; + for(i=0;;) { + obimptr = findResource(MKID('OBIM'), searchptr); + if (obimptr==NULL) + error("findObjectInRoom: Not enough image blocks in room %d", room); + imhd = (ImageHeader*)findResource(MKID('IMHD'), obimptr, 0); + if (READ_LE_UINT16(&imhd->obj_id) == (uint16)id) { + fo->obim = obimptr; + fo->imhd = imhd; + break; + } + + if (++i==numobj) + error("findObjectInRoom: Object %d image not found in room %d", id, room); + searchptr = NULL; + } + } } int Scumm::getInventorySlot() { @@ -632,7 +699,7 @@ void Scumm::setOwnerOf(int obj, int owner) { } int Scumm::getObjX(int obj) { - if (obj <= _vars[VAR_NUM_ACTOR]) { + if (obj < NUM_ACTORS) { return derefActorSafe(obj,"getObjX")->x; } else { if (whereIsObject(obj)==WIO_NOT_FOUND) @@ -643,7 +710,7 @@ int Scumm::getObjX(int obj) { } int Scumm::getObjY(int obj) { - if (obj <= _vars[VAR_NUM_ACTOR]) { + if (obj < NUM_ACTORS) { return derefActorSafe(obj,"getObjY")->y; } else { if (whereIsObject(obj)==WIO_NOT_FOUND) @@ -654,8 +721,8 @@ int Scumm::getObjY(int obj) { } int Scumm::getObjDir(int obj) { - if (obj <= _vars[VAR_NUM_ACTOR]) { - return derefActorSafe(obj,"getObjDir")->facing; + if (obj < NUM_ACTORS) { + return newDirToOldDir(derefActorSafe(obj,"getObjDir")->facing); } else { getObjectXYPos(obj); return _dir; @@ -687,12 +754,14 @@ void Scumm::setObjectState(int obj, int state, int x, int y) { int i; i = getObjectIndex(obj); - if (i==-1) + if (i==-1) { + warning("setObjectState: no such object"); return; + } if (x != -1) { - _objs[i].x_pos = x; - _objs[i].y_pos = y; + _objs[i].x_pos = x<<3; + _objs[i].y_pos = y<<3; } addObjectToDrawQue(i); @@ -717,7 +786,7 @@ int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, if (is_obj_1) { if (getObjectOrActorXY(b)==-1) return -1; - if (b < _vars[VAR_NUM_ACTOR]) + if (b < NUM_ACTORS) i = derefActorSafe(b, "unkObjProc1")->scalex; x = _xPos; y = _yPos; @@ -729,7 +798,7 @@ int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, if (is_obj_2) { if (getObjectOrActorXY(e)==-1) return -1; - if (e < _vars[VAR_NUM_ACTOR]) + if (e < NUM_ACTORS) j = derefActorSafe(e, "unkObjProc1(2)")->scalex; x2 = _xPos; y2 = _yPos; @@ -741,66 +810,42 @@ int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, return getDist(x,y,x2,y2) * 0xFF / ((i + j)>>1); } -void Scumm::setCursorImg(uint room, uint img) { +void Scumm::setCursorImg(uint img, uint room, uint imgindex) { byte *ptr; int index; - CodeHeader *cdhd; - ImageHeader *imhd; int w,h; - byte *roomptr,*obcd,*obim,*dataptr,*bomp; + byte *roomptr,*obim,*dataptr,*bomp; RoomHeader *rmhd; int i,numobj; uint32 size; + FindObjectInRoom foir; + + if (room==(uint)-1) + room = getObjectRoom(img); - if (getObjectIndex(img)!=-1) { - obim = getObjectAddress(img); - ptr = obim + READ_BE_UINT32(&((ImageHeader*)obim)->size); - cdhd = (CodeHeader*)findResource(MKID('CDHD'), obim, 0); - imhd = (ImageHeader*)findResource(MKID('IMHD'), ptr, 0); - } else { - ensureResourceLoaded(1, room); - roomptr = getResourceAddress(1, room); - rmhd = (RoomHeader*)findResource(MKID('RMHD'), roomptr, 0); - - numobj = READ_LE_UINT16(&rmhd->numObjects); - for(i=0; ;i++) { - if (i>=numobj) - error("setCursorImg: object %d code not found in room %d", img, room); - - obcd = findResource(MKID('OBCD'), roomptr, i); - if (obcd==NULL) - error("setCursorImg: not enough code blocks in room %d", room); - cdhd = (CodeHeader*)findResource(MKID('CDHD'), obcd, 0); - if (READ_LE_UINT16(&cdhd->obj_id) == img) - break; - } - - for(i=0; ;i++) { - if (i>=numobj) - error("setCursorImg: object %d image not found in room %d", img, room); - obim = findResource(MKID('OBIM'), roomptr, i); - if (obim==NULL) - error("setCursorImg: not enough image blocks in room %d", room); - imhd = (ImageHeader*)findResource(MKID('IMHD'), obim, 0); - if (READ_LE_UINT16(&imhd->obj_id) == img) - break; - } - } + findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room); setCursorHotspot2( - READ_LE_UINT16(&imhd->hotspot[0].x), - READ_LE_UINT16(&imhd->hotspot[0].y)); + READ_LE_UINT16(&foir.imhd->hotspot[0].x), + READ_LE_UINT16(&foir.imhd->hotspot[0].y)); + +#if !defined(FULL_THROTTLE) + w = READ_LE_UINT16(&foir.cdhd->v6.w)>>3; + h = READ_LE_UINT16(&foir.cdhd->v6.h)>>3; +#else + w = READ_LE_UINT16(&foir.imhd->width)>>3; + h = READ_LE_UINT16(&foir.imhd->height)>>3; +#endif - w = READ_LE_UINT16(&cdhd->v6.w)>>3; - h = READ_LE_UINT16(&cdhd->v6.h)>>3; + dataptr = findResource(IMxx_tags[imgindex],foir.obim); + if (dataptr==NULL) + error("setCursorImg: No such image"); - size = READ_BE_UINT32(&cdhd->size); + size = READ_BE_UINT32(dataptr+4); if (size > sizeof(_grabbedCursor)) error("setCursorImg: Cursor image too large"); - - dataptr = findResource(MKID('IM01'),obim, 0); - if ((bomp = findResource(MKID('BOMP'), dataptr, 0)) != NULL) + if ((bomp = findResource(MKID('BOMP'), dataptr)) != NULL) useBompCursor(bomp, w, h); else useIm01Cursor(dataptr, w, h); @@ -838,13 +883,13 @@ void Scumm::enqueueObject(int a, int b, int c, int d, int e, int f, int g, int h eo->y = c; if (d==0) { od = &_objs[getObjectIndex(a)]; - eo->width = od->numstrips<<3; + eo->width = od->width; } else { eo->width = d; } if (e==0) { od = &_objs[getObjectIndex(a)]; - eo->height = od->height<<3; + eo->height = od->height; } else { eo->height = e; } @@ -887,14 +932,14 @@ void Scumm::drawEnqueuedObject(EnqueuedObject *eo) { } else if (eo->a!=0) { od = &_objs[getObjectIndex(eo->a)]; ptr = getResourceAddress(rtFlObject, od->fl_object_index); - ptr = findResource(MKID('OBIM'), ptr, 0); + ptr = findResource(MKID('OBIM'), ptr); } else { warning("drawEnqueuedObject: invalid"); return; } - ptr = findResource(MKID('IM01'), ptr, 0); - bomp = findResource(MKID('BOMP'), ptr, 0); + ptr = findResource(MKID('IM01'), ptr); + bomp = findResource(MKID('BOMP'), ptr); width = READ_LE_UINT16(&((BompHeader*)bomp)->width); height = READ_LE_UINT16(&((BompHeader*)bomp)->height); @@ -906,9 +951,11 @@ void Scumm::drawEnqueuedObject(EnqueuedObject *eo) { if (eo->a) { dataptr = bomp + 18; - } +// debug(1, "drawEnqueuedObject(%d,%d,%d,%d,%d, %d,%d,%d,%d,%d,%d,%d)", +// eo->x, eo->y, eo->width, eo->height, eo->a, eo->b, eo->c, eo->d, eo->e, eo->j, eo->k, eo->l); + updateDirtyRect(vs->number, x, x+width,y,y+height,0); } @@ -928,3 +975,58 @@ void Scumm::removeEnqueuedObject(EnqueuedObject *eo) { restoreBG(eo->x, eo->y, eo->x + eo->width, eo->y + eo->height); } +int Scumm::findFlObjectSlot() { + int i; + for(i=1; i<_maxFLObject; i++) { + if (_baseFLObject[i] == NULL) + return i; + } + error("findFlObjectSlot: Out of FLObject slots"); +} + +void Scumm::loadFlObject(uint object, uint room) { + FindObjectInRoom foir; + int slot; + ObjectData *od; + byte *flob,*roomptr; + uint32 obcd_size, obim_size, flob_size; + + /* Don't load an already loaded object */ + if (whereIsObject(object) != WIO_NOT_FOUND) + return; + + if (room==(uint)-1) + room = getObjectRoom(object); + + /* Locate the object in the room resource */ + findObjectInRoom(&foir, foImageHeader | foCodeHeader, object, room); + + /* Add an entry for the new floating object in the local object table */ + if (++_numObjectsInRoom > _numLocalObjects) + error("loadFlObject: Local Object Table overflow"); + od = &_objs[_numObjectsInRoom]; + + /* Setup sizes */ + obcd_size = READ_BE_UINT32(foir.obcd + 4); + od->offs_obcd_to_room = 8; + od->offs_obim_to_room = obcd_size + 8; + obim_size = READ_BE_UINT32(foir.obim + 4); + flob_size = obcd_size + obim_size + 8; + + /* Allocate slot & memory for floating object */ + slot = findFlObjectSlot(); + createResource(rtFlObject, slot, flob_size); + + /* Copy object code + object image to floating object */ + roomptr = getResourceAddress(rtRoom, room); + flob = getResourceAddress(rtFlObject, slot); + ((uint32*)flob)[0] = MKID('FLOB'); + ((uint32*)flob)[1] = TO_BE_32(flob_size); + memcpy(flob + 8, roomptr - foir.roomptr + foir.obcd, obcd_size); + memcpy(flob + 8 + obcd_size, roomptr - foir.roomptr + foir.obim, obim_size); + + /* Setup local object flags */ + setupRoomObject(od, flob); + + od->fl_object_index = slot; +} |