2001-10-09 14:30:12 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2001 Ludvig Strigeus
|
2002-03-20 17:51:07 +00:00
|
|
|
* Copyright (C) 2001/2002 The ScummVM project
|
2001-10-09 14:30:12 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
2001-11-06 20:00:47 +00:00
|
|
|
* $Header$
|
2001-10-09 14:30:12 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "scumm.h"
|
2002-05-14 23:32:34 +00:00
|
|
|
#include "actor.h"
|
2002-07-16 21:03:14 +00:00
|
|
|
#include "object.h"
|
|
|
|
#include "resource.h"
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
bool Scumm::getClass(int obj, int cls)
|
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in getClass");
|
2002-04-03 16:20:17 +00:00
|
|
|
cls &= 0x7F;
|
2002-04-11 17:19:16 +00:00
|
|
|
checkRange(32, 1, cls, "Class %d out of range in getClass");
|
2002-04-03 16:20:17 +00:00
|
|
|
|
2002-04-04 04:38:18 +00:00
|
|
|
if (_features & GF_SMALL_HEADER) {
|
2002-05-11 17:49:42 +00:00
|
|
|
if (cls == 31) // CLASS_PLAYERONLY
|
|
|
|
cls = 23;
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (cls == 32) // CLASS_TOUCHABLE
|
|
|
|
cls = 24;
|
2002-04-03 15:45:32 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
return (_classData[obj] & (1 << (cls - 1))) != 0;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::putClass(int obj, int cls, bool set)
|
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in putClass");
|
2001-10-09 14:30:12 +00:00
|
|
|
cls &= 0x7F;
|
2002-07-15 22:56:24 +00:00
|
|
|
checkRange(32, 1, cls, "Class %d out of range in putClass");
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-20 04:09:02 +00:00
|
|
|
|
2002-04-04 04:38:18 +00:00
|
|
|
if (_features & GF_SMALL_HEADER) {
|
2002-05-11 17:49:42 +00:00
|
|
|
if (cls == 31) // CLASS_PLAYERONLY
|
|
|
|
cls = 23;
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (cls == 32) // CLASS_TOUCHABLE
|
|
|
|
cls = 24;
|
2002-11-10 18:11:39 +00:00
|
|
|
|
2002-12-13 01:33:23 +00:00
|
|
|
// FIXME: It isn't enough for the Indy3 intro to make the
|
|
|
|
// little trains ignore boxes (class 22), they have to always
|
|
|
|
// clip (class 21) as well. Is this yet another walkbox 0
|
|
|
|
// error?
|
|
|
|
if (_gameId == GID_INDY3_256 && cls == 22 && _currentRoom == 76)
|
|
|
|
putClass(obj, 21, set);
|
2002-04-03 16:20:17 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-04-11 15:22:02 +00:00
|
|
|
if (set)
|
2002-04-11 17:19:16 +00:00
|
|
|
_classData[obj] |= (1 << (cls - 1));
|
2002-04-11 15:22:02 +00:00
|
|
|
else
|
2002-04-11 17:19:16 +00:00
|
|
|
_classData[obj] &= ~(1 << (cls - 1));
|
2002-07-26 16:13:04 +00:00
|
|
|
|
|
|
|
if (1 <= obj && obj < NUM_ACTORS) {
|
|
|
|
_actors[obj].classChanged(cls, set);
|
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getOwner(int obj)
|
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in getOwner");
|
2001-11-26 19:57:57 +00:00
|
|
|
return _objectOwnerTable[obj];
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-07-02 21:29:24 +00:00
|
|
|
void Scumm::putOwner(int obj, int owner)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in putOwner");
|
2001-11-26 19:57:57 +00:00
|
|
|
checkRange(0xFF, 0, owner, "Owner %d out of range in putOwner");
|
2002-07-02 21:29:24 +00:00
|
|
|
_objectOwnerTable[obj] = owner;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-07-02 21:29:24 +00:00
|
|
|
int Scumm::getState(int obj)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in getState");
|
2002-07-02 21:29:24 +00:00
|
|
|
return _objectStateTable[obj];
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-07-02 21:29:24 +00:00
|
|
|
void Scumm::putState(int obj, int state)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in putState");
|
2001-11-26 19:57:57 +00:00
|
|
|
checkRange(0xFF, 0, state, "State %d out of range in putState");
|
2002-07-02 21:29:24 +00:00
|
|
|
_objectStateTable[obj] = state;
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjectRoom(int obj)
|
|
|
|
{
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 0, obj, "Object %d out of range in getObjectRoom");
|
2001-11-26 19:57:57 +00:00
|
|
|
return _objectRoomTable[obj];
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjectIndex(int object)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
if (object < 1)
|
|
|
|
return -1;
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
/* OF_OWNER_ROOM should be 0xFF for full throttle, else 0xF */
|
|
|
|
if (_objectOwnerTable[object] != OF_OWNER_ROOM) {
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _maxInventoryItems; i++)
|
2001-10-09 14:30:12 +00:00
|
|
|
if (_inventory[i] == object)
|
|
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
} else {
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = (_numLocalObjects-1); i > 0; i--) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[i].obj_nr == object)
|
2001-10-09 14:30:12 +00:00
|
|
|
return i;
|
|
|
|
}
|
2003-01-11 18:52:19 +00:00
|
|
|
|
|
|
|
// FIXME: Major HACK. This is probably the worst biggest
|
|
|
|
// hack in the whole engine. It's that bad.
|
|
|
|
// (Workaround flobject 188/189 not loaded bug)
|
2003-01-12 10:20:09 +00:00
|
|
|
/*if (_gameId == GID_CMI && ((object == 188 || object == 189))) {
|
2003-01-11 18:53:15 +00:00
|
|
|
warning("FIXME MAJOR: Hacking load of FlObject %d\n", object);
|
2003-01-11 18:52:19 +00:00
|
|
|
loadFlObject(object, 3);
|
|
|
|
return getObjectIndex(object);
|
2003-01-12 10:20:09 +00:00
|
|
|
}*/
|
2001-10-09 14:30:12 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::whereIsObject(int object)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
|
|
|
|
2001-11-07 18:10:52 +00:00
|
|
|
if (object >= _numGlobalObjects)
|
2001-11-12 20:50:36 +00:00
|
|
|
return WIO_NOT_FOUND;
|
2001-11-06 21:29:23 +00:00
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
if (object < 1)
|
|
|
|
return WIO_NOT_FOUND;
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
if (_objectOwnerTable[object] != OF_OWNER_ROOM) {
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _maxInventoryItems; i++)
|
2001-10-09 14:30:12 +00:00
|
|
|
if (_inventory[i] == object)
|
2001-11-12 20:50:36 +00:00
|
|
|
return WIO_INVENTORY;
|
|
|
|
return WIO_NOT_FOUND;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = (_numLocalObjects-1); i > 0; i--)
|
2001-10-16 10:01:48 +00:00
|
|
|
if (_objs[i].obj_nr == object) {
|
|
|
|
if (_objs[i].fl_object_index)
|
2001-11-12 20:50:36 +00:00
|
|
|
return WIO_FLOBJECT;
|
|
|
|
return WIO_ROOM;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2003-01-11 18:52:19 +00:00
|
|
|
|
2001-11-12 20:50:36 +00:00
|
|
|
return WIO_NOT_FOUND;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-07-16 18:51:27 +00:00
|
|
|
int Scumm::getObjectOrActorXY(int object, int &x, int &y)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-07-30 11:43:30 +00:00
|
|
|
if (object < NUM_ACTORS) {
|
|
|
|
Actor *act = derefActorSafe(object, "getObjectOrActorXY");
|
|
|
|
if (!act)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return act->getActorXYPos(x, y);
|
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
switch (whereIsObject(object)) {
|
2001-11-12 20:50:36 +00:00
|
|
|
case WIO_NOT_FOUND:
|
2001-10-09 14:30:12 +00:00
|
|
|
return -1;
|
2002-04-11 17:19:16 +00:00
|
|
|
case WIO_INVENTORY:
|
2002-04-07 04:29:15 +00:00
|
|
|
if (_objectOwnerTable[object] < NUM_ACTORS)
|
2002-07-16 18:51:27 +00:00
|
|
|
return derefActorSafe(_objectOwnerTable[object], "getObjectOrActorXY(2)")->getActorXYPos(x, y);
|
2002-04-07 04:29:15 +00:00
|
|
|
else
|
|
|
|
return 0xFF;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2002-07-16 18:51:27 +00:00
|
|
|
getObjectXYPos(object, x, y);
|
2001-10-09 14:30:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
/* Return the position of an object.
|
|
|
|
Returns X, Y and direction in angles
|
|
|
|
*/
|
2002-07-16 18:51:27 +00:00
|
|
|
void Scumm::getObjectXYPos(int object, int &x, int &y, int &dir)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2001-10-16 10:01:48 +00:00
|
|
|
ObjectData *od = &_objs[getObjectIndex(object)];
|
|
|
|
int state;
|
|
|
|
byte *ptr;
|
|
|
|
ImageHeader *imhd;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
if (!(_features & GF_SMALL_HEADER)) {
|
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
ptr = getResourceAddress(rtRoom, _roomResource);
|
2002-12-26 20:37:49 +00:00
|
|
|
ptr += od->OBIMoffset;
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
assert(ptr);
|
|
|
|
imhd = (ImageHeader *)findResourceData(MKID('IMHD'), ptr);
|
2002-12-24 04:02:21 +00:00
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
x = od->x_pos + (int32)READ_LE_UINT32(&imhd->v8.hotspot[state].x);
|
|
|
|
y = od->y_pos + (int32)READ_LE_UINT32(&imhd->v8.hotspot[state].y);
|
|
|
|
} else if (_features & GF_AFTER_V7) {
|
2002-07-07 20:25:23 +00:00
|
|
|
x = od->x_pos + (int16)READ_LE_UINT16(&imhd->v7.hotspot[state].x);
|
|
|
|
y = od->y_pos + (int16)READ_LE_UINT16(&imhd->v7.hotspot[state].y);
|
2002-03-05 21:03:32 +00:00
|
|
|
} else {
|
2002-07-07 20:25:23 +00:00
|
|
|
x = od->x_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].x);
|
|
|
|
y = od->y_pos + (int16)READ_LE_UINT16(&imhd->old.hotspot[state].y);
|
2002-03-05 21:03:32 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
} else {
|
|
|
|
x = od->walk_x;
|
2002-03-23 20:34:47 +00:00
|
|
|
y = od->walk_y;
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
2002-07-16 18:51:27 +00:00
|
|
|
dir = oldDirToNewDir(od->actordir & 3);
|
2002-04-11 17:19:16 +00:00
|
|
|
} else {
|
|
|
|
x = od->walk_x;
|
2002-03-23 20:34:47 +00:00
|
|
|
y = od->walk_y;
|
2002-07-16 18:51:27 +00:00
|
|
|
dir = oldDirToNewDir(od->actordir & 3);
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjActToObjActDist(int a, int b)
|
|
|
|
{
|
2002-07-16 18:51:27 +00:00
|
|
|
int x, y, x2, y2;
|
2001-10-09 14:30:12 +00:00
|
|
|
Actor *acta = NULL;
|
|
|
|
Actor *actb = NULL;
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (a < NUM_ACTORS)
|
2001-10-09 14:30:12 +00:00
|
|
|
acta = derefActorSafe(a, "getObjActToObjActDist");
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (b < NUM_ACTORS)
|
2001-10-09 14:30:12 +00:00
|
|
|
actb = derefActorSafe(b, "getObjActToObjActDist(2)");
|
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
if (acta && actb && acta->getRoom() == actb->getRoom() && acta->getRoom() && !acta->isInCurrentRoom())
|
2002-04-11 17:19:16 +00:00
|
|
|
return 0;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-07-16 18:51:27 +00:00
|
|
|
if (getObjectOrActorXY(a, x, y) == -1)
|
2001-10-09 14:30:12 +00:00
|
|
|
return 0xFF;
|
|
|
|
|
2002-07-16 18:51:27 +00:00
|
|
|
if (getObjectOrActorXY(b, x2, y2) == -1)
|
2001-10-09 14:30:12 +00:00
|
|
|
return 0xFF;
|
|
|
|
|
|
|
|
if (acta) {
|
2002-07-16 18:51:27 +00:00
|
|
|
AdjustBoxResult r = acta->adjustXYToBeInBox(x2, y2, -1);
|
|
|
|
x2 = r.x;
|
|
|
|
y2 = r.y;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-07-16 18:51:27 +00:00
|
|
|
y = abs(y - y2);
|
|
|
|
x = abs(x - x2);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (y > x)
|
|
|
|
x = y;
|
2001-10-09 14:30:12 +00:00
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::findObject(int x, int y)
|
|
|
|
{
|
|
|
|
int i, b;
|
2001-11-26 19:57:57 +00:00
|
|
|
byte a;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++) {
|
2003-01-12 07:30:17 +00:00
|
|
|
if ((_objs[i].obj_nr < 1) || getClass(_objs[i].obj_nr, 32))
|
2001-10-09 14:30:12 +00:00
|
|
|
continue;
|
|
|
|
b = i;
|
|
|
|
do {
|
2001-10-16 10:01:48 +00:00
|
|
|
a = _objs[b].parentstate;
|
|
|
|
b = _objs[b].parent;
|
2002-04-11 17:19:16 +00:00
|
|
|
if (b == 0) {
|
2002-12-28 00:45:44 +00:00
|
|
|
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)
|
2002-04-11 17:19:16 +00:00
|
|
|
return _objs[i].obj_nr;
|
2001-10-09 14:30:12 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
} while (_objs[b].state == a);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::drawRoomObject(int i, int arg)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
ObjectData *od;
|
2001-11-26 19:57:57 +00:00
|
|
|
byte a;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2001-12-04 21:44:41 +00:00
|
|
|
od = &_objs[i];
|
2003-01-12 07:30:17 +00:00
|
|
|
if ((i < 1) || (od->obj_nr < 1) || !od->state)
|
2001-12-04 21:44:41 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
do {
|
|
|
|
a = od->parentstate;
|
|
|
|
if (!od->parent) {
|
|
|
|
drawObject(i, arg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
od = &_objs[od->parent];
|
2002-04-11 17:19:16 +00:00
|
|
|
} while (od->state == a);
|
2001-12-04 21:44:41 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::drawRoomObjects(int arg)
|
|
|
|
{
|
2001-12-04 21:44:41 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (_features & GF_DRAWOBJ_OTHER_ORDER) {
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++)
|
2003-01-12 07:30:17 +00:00
|
|
|
if (_objs[i].obj_nr > 0)
|
|
|
|
drawRoomObject(i, arg);
|
2001-12-04 21:44:41 +00:00
|
|
|
} else {
|
2003-01-12 08:37:59 +00:00
|
|
|
for (i = (_numLocalObjects-1); i > 0; i--)
|
2003-01-12 07:30:17 +00:00
|
|
|
if (_objs[i].obj_nr > 0)
|
|
|
|
drawRoomObject(i, arg);
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
const uint32 IMxx_tags[] = {
|
2001-10-09 14:30:12 +00:00
|
|
|
MKID('IM00'),
|
|
|
|
MKID('IM01'),
|
|
|
|
MKID('IM02'),
|
|
|
|
MKID('IM03'),
|
|
|
|
MKID('IM04'),
|
|
|
|
MKID('IM05'),
|
|
|
|
MKID('IM06'),
|
|
|
|
MKID('IM07'),
|
|
|
|
MKID('IM08'),
|
|
|
|
MKID('IM09'),
|
|
|
|
MKID('IM0A'),
|
|
|
|
MKID('IM0B'),
|
|
|
|
MKID('IM0C'),
|
|
|
|
MKID('IM0D'),
|
|
|
|
MKID('IM0E'),
|
|
|
|
MKID('IM0F')
|
|
|
|
};
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::drawObject(int obj, int arg)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
ObjectData *od;
|
|
|
|
int xpos, ypos, height, width;
|
|
|
|
byte *ptr;
|
2002-04-11 17:19:16 +00:00
|
|
|
int x, a, numstrip;
|
2001-10-26 17:34:50 +00:00
|
|
|
int tmp;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
|
|
|
if (_BgNeedsRedraw)
|
|
|
|
arg = 0;
|
|
|
|
|
2001-10-16 10:01:48 +00:00
|
|
|
od = &_objs[obj];
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
if (od->obj_nr == 0)
|
|
|
|
return;
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
xpos = od->x_pos >> 3;
|
2001-10-09 14:30:12 +00:00
|
|
|
ypos = od->y_pos;
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
width = od->width >> 3;
|
|
|
|
height = od->height &= 0xF8; // Ender
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
if (width == 0 || xpos > _screenEndStrip || xpos + width < _screenStartStrip)
|
2001-10-09 14:30:12 +00:00
|
|
|
return;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2001-10-09 14:30:12 +00:00
|
|
|
if (od->fl_object_index) {
|
2001-11-05 19:21:49 +00:00
|
|
|
ptr = getResourceAddress(rtFlObject, od->fl_object_index);
|
2002-04-11 17:19:16 +00:00
|
|
|
ptr = findResource(MKID('OBIM'), ptr);
|
2001-10-09 14:30:12 +00:00
|
|
|
} else {
|
2001-11-05 19:21:49 +00:00
|
|
|
ptr = getResourceAddress(rtRoom, _roomResource);
|
2002-12-26 20:37:49 +00:00
|
|
|
ptr = ptr + od->OBIMoffset;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_features & GF_SMALL_HEADER)
|
|
|
|
ptr += 8;
|
2002-12-31 03:26:02 +00:00
|
|
|
else if (_features & GF_AFTER_V8) {
|
|
|
|
ptr = findResource(MKID('IMAG'), ptr);
|
|
|
|
if (!ptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ptr = findResource(MKID('WRAP'), ptr);
|
|
|
|
assert(ptr);
|
|
|
|
ptr = findResource(MKID('OFFS'), ptr);
|
|
|
|
assert(ptr);
|
|
|
|
// Get the address of the specified SMAP (corresponding to IMxx)
|
|
|
|
ptr += READ_LE_UINT32(ptr + 4 + 4*getState(od->obj_nr));
|
|
|
|
} else
|
2002-04-11 17:19:16 +00:00
|
|
|
ptr = findResource(IMxx_tags[getState(od->obj_nr)], ptr);
|
2001-10-09 14:30:12 +00:00
|
|
|
if (!ptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
x = 0xFFFF;
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
for (a = numstrip = 0; a < width; a++) {
|
2001-10-26 17:34:50 +00:00
|
|
|
tmp = xpos + a;
|
2002-04-11 17:19:16 +00:00
|
|
|
if (arg == 1 && _screenStartStrip != tmp)
|
2001-10-09 14:30:12 +00:00
|
|
|
continue;
|
2002-04-11 17:19:16 +00:00
|
|
|
if (arg == 2 && _screenEndStrip != tmp)
|
2001-10-09 14:30:12 +00:00
|
|
|
continue;
|
2001-10-26 17:34:50 +00:00
|
|
|
if (tmp < _screenStartStrip || tmp > _screenEndStrip)
|
2001-10-09 14:30:12 +00:00
|
|
|
continue;
|
2001-11-26 19:57:57 +00:00
|
|
|
gfxUsageBits[tmp] |= 0x80000000;
|
2001-10-26 17:34:50 +00:00
|
|
|
if (tmp < x)
|
|
|
|
x = tmp;
|
|
|
|
numstrip++;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (numstrip != 0) {
|
2001-11-26 19:57:57 +00:00
|
|
|
byte flags = Gdi::dbAllowMaskOr;
|
2002-09-24 15:23:57 +00:00
|
|
|
// Sam & Max needs this to fix object-layering problems with
|
|
|
|
// the inventory and conversation icons.
|
|
|
|
if ((_features & GF_AFTER_V7 || _gameId == GID_SAMNMAX) && getClass(od->obj_nr, 22))
|
2002-09-29 15:20:02 +00:00
|
|
|
flags |= Gdi::dbDrawMaskOnAll;
|
2002-12-21 01:11:42 +00:00
|
|
|
gdi.drawBitmap(ptr, &virtscr[0], x, ypos, height, x - xpos, numstrip, flags);
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::loadRoomObjects()
|
|
|
|
{
|
|
|
|
int i, j;
|
2001-10-09 14:30:12 +00:00
|
|
|
ObjectData *od;
|
|
|
|
byte *ptr;
|
|
|
|
uint16 obim_id;
|
2002-12-24 12:49:25 +00:00
|
|
|
byte *room, *searchptr, *rootptr;
|
2001-10-09 14:30:12 +00:00
|
|
|
ImageHeader *imhd;
|
|
|
|
RoomHeader *roomhdr;
|
2002-04-11 17:19:16 +00:00
|
|
|
CodeHeader *cdhd;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-24 15:27:27 +00:00
|
|
|
CHECK_HEAP
|
|
|
|
room = getResourceAddress(rtRoom, _roomResource);
|
2002-04-11 17:19:16 +00:00
|
|
|
roomhdr = (RoomHeader *)findResourceData(MKID('RMHD'), room);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-24 04:02:21 +00:00
|
|
|
if (_features & GF_AFTER_V8)
|
2002-12-25 07:48:37 +00:00
|
|
|
_numObjectsInRoom = (byte)READ_LE_UINT32(&(roomhdr->v8.numObjects));
|
2002-12-24 04:02:21 +00:00
|
|
|
else if (_features & GF_AFTER_V7)
|
2002-03-05 20:13:47 +00:00
|
|
|
_numObjectsInRoom = READ_LE_UINT16(&(roomhdr->v7.numObjects));
|
|
|
|
else
|
|
|
|
_numObjectsInRoom = READ_LE_UINT16(&(roomhdr->old.numObjects));
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2003-01-12 08:37:59 +00:00
|
|
|
// Clear out old room objects (FIXME: Locking/FlObjects stuff?)
|
|
|
|
for (i = 0; i < _numLocalObjects; i++) {
|
2003-01-12 10:20:09 +00:00
|
|
|
if (_objs[i].obj_nr < 1) // Optimise codepath
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Nuke all non-flObjects (flObjects are nuked in script.cpp)
|
|
|
|
if (!_objs[i].fl_object_index) {
|
|
|
|
_objs[i].obj_nr = 0;
|
|
|
|
_objs[i].fl_object_index = 0;
|
|
|
|
} else {
|
|
|
|
// Nuke all unlocked flObjects
|
|
|
|
if (!(res.flags[rtFlObject][_objs[i].fl_object_index] & RF_LOCK)) {
|
|
|
|
nukeResource(rtFlObject, _objs[i].fl_object_index);
|
|
|
|
_objs[i].obj_nr = 0;
|
|
|
|
_objs[i].fl_object_index = 0;
|
|
|
|
}
|
|
|
|
}
|
2003-01-12 08:37:59 +00:00
|
|
|
}
|
|
|
|
|
2001-10-09 14:30:12 +00:00
|
|
|
if (_numObjectsInRoom == 0)
|
|
|
|
return;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2001-10-16 10:01:48 +00:00
|
|
|
if (_numObjectsInRoom > _numLocalObjects)
|
|
|
|
error("More than %d objects in room %d", _numLocalObjects, _roomResource);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-24 12:27:35 +00:00
|
|
|
if (_features & GF_AFTER_V8)
|
2002-12-24 12:49:25 +00:00
|
|
|
searchptr = rootptr = getResourceAddress(rtRoomScripts, _roomResource);
|
2002-12-24 12:09:11 +00:00
|
|
|
else
|
2002-12-24 12:49:25 +00:00
|
|
|
searchptr = rootptr = room;
|
2002-12-27 14:36:28 +00:00
|
|
|
assert(searchptr);
|
2002-12-24 12:09:11 +00:00
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
|
|
|
|
// Load in new room objects
|
|
|
|
for (i = 0; i < _numObjectsInRoom; i++) {
|
|
|
|
od = &_objs[findLocalObjectSlot()];
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
ptr = findResource(MKID('OBCD'), searchptr);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (ptr == NULL)
|
2001-10-09 14:30:12 +00:00
|
|
|
error("Room %d missing object code block(s)", _roomResource);
|
|
|
|
|
2002-12-26 20:37:49 +00:00
|
|
|
od->OBCDoffset = ptr - rootptr;
|
2002-04-11 17:19:16 +00:00
|
|
|
cdhd = (CodeHeader *)findResourceData(MKID('CDHD'), ptr);
|
2002-03-05 20:43:26 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_features & GF_AFTER_V7)
|
2002-03-05 20:43:26 +00:00
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v7.obj_id));
|
2002-04-11 17:19:16 +00:00
|
|
|
else if (_features & GF_AFTER_V6)
|
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v6.obj_id));
|
2002-03-05 20:43:26 +00:00
|
|
|
else
|
2002-04-11 17:19:16 +00:00
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v5.obj_id));
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-31 02:09:57 +00:00
|
|
|
if (_dumpScripts) {
|
2001-10-09 14:30:12 +00:00
|
|
|
char buf[32];
|
2002-04-11 17:19:16 +00:00
|
|
|
sprintf(buf, "roomobj-%d-", _roomResource);
|
2002-12-27 14:36:28 +00:00
|
|
|
if (_features & GF_AFTER_V8)
|
|
|
|
// TODO - maybe V8 is not the only that needs this?
|
|
|
|
ptr = findResource(MKID('VERB'), ptr, 0);
|
2001-10-09 14:30:12 +00:00
|
|
|
dumpResource(buf, od->obj_nr, ptr);
|
2002-12-31 02:09:57 +00:00
|
|
|
}
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
searchptr = NULL;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
searchptr = room;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _numObjectsInRoom; i++) {
|
2001-11-26 19:57:57 +00:00
|
|
|
ptr = findResource(MKID('OBIM'), searchptr);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (ptr == NULL)
|
2001-10-09 14:30:12 +00:00
|
|
|
error("Room %d missing image blocks(s)", _roomResource);
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
imhd = (ImageHeader *)findResourceData(MKID('IMHD'), ptr);
|
2002-12-24 04:02:21 +00:00
|
|
|
if (_features & GF_AFTER_V8)
|
2002-12-24 16:10:31 +00:00
|
|
|
// In V8, IMHD has no obj_id, but rather a name string. We map the name
|
|
|
|
// back to an object id using a table derived from the DOBJ resource.
|
|
|
|
obim_id = _objectIDMap[imhd->v8.name];
|
2002-12-24 04:02:21 +00:00
|
|
|
else if (_features & GF_AFTER_V7)
|
2002-03-05 21:03:32 +00:00
|
|
|
obim_id = READ_LE_UINT16(&imhd->v7.obj_id);
|
|
|
|
else
|
|
|
|
obim_id = READ_LE_UINT16(&imhd->old.obj_id);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (j = 1; j < _numLocalObjects; j++) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[j].obj_nr == obim_id)
|
2002-12-26 20:37:49 +00:00
|
|
|
_objs[j].OBIMoffset = ptr - room;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
searchptr = NULL;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
// ENDERFIXME: Switch this one over to numLocals also
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++) {
|
2003-01-12 10:20:09 +00:00
|
|
|
if (_objs[i].obj_nr && !_objs[i].fl_object_index)
|
2003-01-12 07:30:17 +00:00
|
|
|
setupRoomObject(&_objs[i], room);
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
2001-10-16 10:01:48 +00:00
|
|
|
|
2002-12-24 15:27:27 +00:00
|
|
|
CHECK_HEAP
|
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::loadRoomObjectsSmall()
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
ObjectData *od;
|
|
|
|
byte *ptr;
|
|
|
|
uint16 obim_id;
|
|
|
|
byte *room, *searchptr;
|
|
|
|
RoomHeader *roomhdr;
|
|
|
|
|
2002-12-26 21:50:13 +00:00
|
|
|
CHECK_HEAP
|
|
|
|
room = getResourceAddress(rtRoom, _roomResource);
|
2002-04-11 17:19:16 +00:00
|
|
|
roomhdr = (RoomHeader *)findResourceData(MKID('RMHD'), room);
|
|
|
|
|
|
|
|
_numObjectsInRoom = READ_LE_UINT16(&(roomhdr->old.numObjects));
|
|
|
|
|
|
|
|
if (_numObjectsInRoom == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (_numObjectsInRoom > _numLocalObjects)
|
|
|
|
error("More than %d objects in room %d", _numLocalObjects, _roomResource);
|
|
|
|
|
|
|
|
searchptr = room;
|
2003-01-12 07:30:17 +00:00
|
|
|
for (i = 0; i < _numObjectsInRoom; i++) {
|
|
|
|
od = &_objs[findLocalObjectSlot()];
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
ptr = findResourceSmall(MKID('OBCD'), searchptr);
|
|
|
|
if (ptr == NULL)
|
|
|
|
error("Room %d missing object code block(s)", _roomResource);
|
|
|
|
|
2002-12-26 20:37:49 +00:00
|
|
|
od->OBCDoffset = ptr - room;
|
2002-04-11 17:19:16 +00:00
|
|
|
od->obj_nr = READ_LE_UINT16(ptr + 6);
|
2002-02-12 18:20:37 +00:00
|
|
|
|
2002-12-31 02:09:57 +00:00
|
|
|
if (_dumpScripts) {
|
2002-04-11 17:19:16 +00:00
|
|
|
char buf[32];
|
|
|
|
sprintf(buf, "roomobj-%d-", _roomResource);
|
|
|
|
dumpResource(buf, od->obj_nr, ptr);
|
2002-12-31 02:09:57 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
searchptr = NULL;
|
|
|
|
}
|
2002-02-12 18:20:37 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
searchptr = room;
|
|
|
|
for (i = 0; i < _numObjectsInRoom; i++) {
|
|
|
|
ptr = findResourceSmall(MKID('OBIM'), searchptr);
|
|
|
|
if (ptr == NULL)
|
|
|
|
error("Room %d missing image blocks(s)", _roomResource);
|
|
|
|
|
|
|
|
obim_id = READ_LE_UINT16(ptr + 6);
|
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (j = 1; j < _numLocalObjects; j++) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[j].obj_nr == obim_id)
|
2002-12-26 20:37:49 +00:00
|
|
|
_objs[j].OBIMoffset = ptr - room;
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
searchptr = NULL;
|
|
|
|
}
|
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
// ENDERFIXME: Switch to numLocals
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++) {
|
2003-01-12 10:20:09 +00:00
|
|
|
if (_objs[i].obj_nr && !_objs[i].fl_object_index)
|
2003-01-12 07:30:17 +00:00
|
|
|
setupRoomObject(&_objs[i], room);
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
|
2002-12-24 15:27:27 +00:00
|
|
|
CHECK_HEAP
|
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
void Scumm::setupRoomObject(ObjectData *od, byte *room, byte *searchptr)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-12-24 12:27:35 +00:00
|
|
|
CodeHeader *cdhd = NULL;
|
|
|
|
ImageHeader *imhd = NULL;
|
2002-12-27 14:36:28 +00:00
|
|
|
|
|
|
|
assert(room);
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
if (_features & GF_SMALL_HEADER) {
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-12-26 20:37:49 +00:00
|
|
|
byte *ptr = room + od->OBCDoffset;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
od->obj_nr = READ_LE_UINT16(ptr + 6); // ok
|
|
|
|
|
|
|
|
od->width = *(ptr + 11) << 3; // ok
|
|
|
|
od->x_pos = *(ptr + 9) << 3; // ok
|
|
|
|
|
|
|
|
if (*(ptr + 10) & 0x80) {
|
|
|
|
od->parentstate = 1; // it's 0x10 in the original code
|
2002-02-13 20:16:01 +00:00
|
|
|
} else {
|
2002-02-12 21:28:07 +00:00
|
|
|
od->parentstate = 0;
|
2002-02-13 20:16:01 +00:00
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
od->y_pos = ((*(ptr + 10)) & 0x7F) << 3;
|
|
|
|
|
|
|
|
od->parent = *(ptr + 12);
|
|
|
|
od->walk_x = READ_LE_UINT16(ptr + 13);
|
|
|
|
|
|
|
|
od->walk_y = READ_LE_UINT16(ptr + 15);
|
|
|
|
|
|
|
|
od->actordir = (*(ptr + 17)) & 7;
|
|
|
|
od->height = *(ptr + 17); // ok
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
if (searchptr == NULL) {
|
|
|
|
if (_features & GF_AFTER_V8)
|
|
|
|
searchptr = getResourceAddress(rtRoomScripts, _roomResource);
|
|
|
|
else
|
|
|
|
searchptr = room;
|
|
|
|
}
|
|
|
|
|
2002-12-26 20:37:49 +00:00
|
|
|
cdhd = (CodeHeader *)findResourceData(MKID('CDHD'), searchptr + od->OBCDoffset);
|
2002-12-24 12:27:35 +00:00
|
|
|
if (cdhd == NULL)
|
|
|
|
error("Room %d missing CDHD blocks(s)", _roomResource);
|
2002-12-24 04:02:21 +00:00
|
|
|
|
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v7.obj_id));
|
|
|
|
|
|
|
|
od->parent = cdhd->v7.parent;
|
|
|
|
od->parentstate = cdhd->v7.parentstate;
|
|
|
|
|
2002-12-26 20:37:49 +00:00
|
|
|
imhd = (ImageHeader *)findResourceData(MKID('IMHD'), room + od->OBIMoffset);
|
2002-12-25 07:48:37 +00:00
|
|
|
od->x_pos = (int)READ_LE_UINT32(&imhd->v8.x_pos);
|
|
|
|
od->y_pos = (int)READ_LE_UINT32(&imhd->v8.y_pos);
|
|
|
|
od->width = (uint)READ_LE_UINT32(&imhd->v8.width);
|
|
|
|
od->height = (uint)READ_LE_UINT32(&imhd->v8.height);
|
|
|
|
od->actordir = (byte)READ_LE_UINT32(&imhd->v8.actordir);
|
2002-12-24 04:02:21 +00:00
|
|
|
|
|
|
|
} else if (_features & GF_AFTER_V7) {
|
2002-03-05 20:43:26 +00:00
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v7.obj_id));
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-03-05 23:05:55 +00:00
|
|
|
od->parent = cdhd->v7.parent;
|
|
|
|
od->parentstate = cdhd->v7.parentstate;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-26 20:37:49 +00:00
|
|
|
imhd = (ImageHeader *)findResourceData(MKID('IMHD'), room + od->OBIMoffset);
|
2002-03-16 18:58:51 +00:00
|
|
|
od->x_pos = READ_LE_UINT16(&imhd->v7.x_pos);
|
|
|
|
od->y_pos = READ_LE_UINT16(&imhd->v7.y_pos);
|
2002-04-11 17:19:16 +00:00
|
|
|
od->width = READ_LE_UINT16(&imhd->v7.width);
|
2002-03-16 18:58:51 +00:00
|
|
|
od->height = READ_LE_UINT16(&imhd->v7.height);
|
|
|
|
od->actordir = READ_LE_UINT16(&imhd->v7.actordir);
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-12-24 04:02:21 +00:00
|
|
|
} else if (_features & GF_AFTER_V6) {
|
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v6.obj_id));
|
|
|
|
|
|
|
|
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;
|
|
|
|
} else {
|
|
|
|
od->parentstate = (cdhd->v6.flags & 0xF);
|
|
|
|
}
|
|
|
|
od->parent = cdhd->v6.parent;
|
|
|
|
od->actordir = cdhd->v6.actordir;
|
|
|
|
} else {
|
|
|
|
od->obj_nr = READ_LE_UINT16(&(cdhd->v5.obj_id));
|
|
|
|
|
|
|
|
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;
|
|
|
|
} else {
|
|
|
|
od->parentstate = (cdhd->v5.flags & 0xF);
|
|
|
|
}
|
|
|
|
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;
|
2002-03-05 23:05:55 +00:00
|
|
|
}
|
2002-12-24 04:02:21 +00:00
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
od->fl_object_index = 0;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::fixObjectFlags()
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
2001-10-16 10:01:48 +00:00
|
|
|
ObjectData *od = &_objs[1];
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++, od++) {
|
2003-01-12 07:30:17 +00:00
|
|
|
if (od->obj_nr > 0)
|
|
|
|
od->state = _objectStateTable[od->obj_nr];
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::processDrawQue()
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i, j;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _drawObjectQueNr; i++) {
|
2001-10-09 14:30:12 +00:00
|
|
|
j = _drawObjectQue[i];
|
|
|
|
if (j)
|
2002-04-11 17:19:16 +00:00
|
|
|
drawObject(j, 0);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
_drawObjectQueNr = 0;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::clearOwnerOf(int obj)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
uint16 *a;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
|
|
|
stopObjectScript(obj);
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
if (getOwner(obj) == OF_OWNER_ROOM) {
|
2001-10-09 14:30:12 +00:00
|
|
|
i = 0;
|
|
|
|
do {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[i].obj_nr == obj) {
|
2001-10-16 10:01:48 +00:00
|
|
|
if (!_objs[i].fl_object_index)
|
2001-10-09 14:30:12 +00:00
|
|
|
return;
|
2001-11-05 19:21:49 +00:00
|
|
|
nukeResource(rtFlObject, _objs[i].fl_object_index);
|
2001-10-16 10:01:48 +00:00
|
|
|
_objs[i].obj_nr = 0;
|
|
|
|
_objs[i].fl_object_index = 0;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2003-01-12 08:32:44 +00:00
|
|
|
} while (++i < _numLocalObjects);
|
2001-10-09 14:30:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 1; i < _maxInventoryItems; i++) {
|
2001-10-09 14:30:12 +00:00
|
|
|
if (_inventory[i] == obj) {
|
|
|
|
j = whereIsObject(obj);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (j == WIO_INVENTORY) {
|
2001-11-05 19:21:49 +00:00
|
|
|
nukeResource(rtInventory, i);
|
2001-10-09 14:30:12 +00:00
|
|
|
_inventory[i] = 0;
|
|
|
|
}
|
2001-10-26 17:34:50 +00:00
|
|
|
a = &_inventory[1];
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 1; i < _maxInventoryItems - 1; i++, a++) {
|
2001-10-26 17:34:50 +00:00
|
|
|
if (!a[0] && a[1]) {
|
|
|
|
a[0] = a[1];
|
|
|
|
a[1] = 0;
|
2002-04-11 17:19:16 +00:00
|
|
|
_baseInventoryItems[i] = _baseInventoryItems[i + 1];
|
|
|
|
_baseInventoryItems[i + 1] = NULL;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::removeObjectFromRoom(int obj)
|
|
|
|
{
|
|
|
|
int i, cnt;
|
2001-11-26 19:57:57 +00:00
|
|
|
uint32 *ptr;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[i].obj_nr == (uint16)obj) {
|
2001-11-26 19:57:57 +00:00
|
|
|
if (_objs[i].width != 0) {
|
2002-04-11 17:19:16 +00:00
|
|
|
ptr = &gfxUsageBits[_objs[i].x_pos >> 3];
|
|
|
|
cnt = _objs[i].width >> 3;
|
2001-10-09 14:30:12 +00:00
|
|
|
do {
|
2001-11-26 19:57:57 +00:00
|
|
|
*ptr++ |= 0x80000000;
|
2001-10-09 14:30:12 +00:00
|
|
|
} while (--cnt);
|
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
_BgNeedsRedraw = true;
|
2001-10-09 14:30:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::addObjectToDrawQue(int object)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
_drawObjectQue[_drawObjectQueNr++] = object;
|
2002-07-07 20:25:23 +00:00
|
|
|
if ((unsigned int)_drawObjectQueNr > sizeof(_drawObjectQue) / sizeof(_drawObjectQue[0]))
|
2001-10-09 14:30:12 +00:00
|
|
|
error("Draw Object Que overflow");
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::clearDrawObjectQueue()
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
_drawObjectQueNr = 0;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
byte *Scumm::getObjOrActorName(int obj)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
byte *objptr;
|
2002-06-25 02:04:43 +00:00
|
|
|
int i;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
if (obj < NUM_ACTORS)
|
2002-05-14 19:11:20 +00:00
|
|
|
return derefActorSafe(obj, "getObjOrActorName")->getActorName();
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_features & GF_SMALL_HEADER) {
|
|
|
|
byte offset = 0;
|
2002-02-12 21:28:07 +00:00
|
|
|
|
|
|
|
objptr = getOBCDFromObject(obj);
|
2002-03-16 05:33:25 +00:00
|
|
|
if (objptr)
|
2002-07-03 23:35:50 +00:00
|
|
|
offset = READ_LE_UINT16(objptr + 18);
|
2002-04-11 17:19:16 +00:00
|
|
|
return (objptr + offset);
|
|
|
|
}
|
2002-02-12 21:28:07 +00:00
|
|
|
|
2002-06-25 02:04:43 +00:00
|
|
|
if (_features & GF_AFTER_V6) {
|
|
|
|
for (i = 1; i < 50; i++) {
|
|
|
|
if (_newNames[i] == obj) {
|
|
|
|
debug(5, "Found new name for object %d at _newNames[i]", obj, i);
|
|
|
|
return getResourceAddress(rtObjectName, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-27 17:51:58 +00:00
|
|
|
objptr = getOBCDFromObject(obj);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (objptr == NULL)
|
|
|
|
return (byte *)" ";
|
|
|
|
|
2001-12-27 17:51:58 +00:00
|
|
|
return findResourceData(MKID('OBNA'), objptr);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
uint32 Scumm::getOBCDOffs(int object)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
if (_objectOwnerTable[object] != OF_OWNER_ROOM)
|
2001-10-09 14:30:12 +00:00
|
|
|
return 0;
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = (_numLocalObjects-1); i > 0; i--) {
|
2001-10-16 10:01:48 +00:00
|
|
|
if (_objs[i].obj_nr == object) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[i].fl_object_index != 0)
|
2001-10-09 14:30:12 +00:00
|
|
|
return 8;
|
2002-12-26 20:37:49 +00:00
|
|
|
return _objs[i].OBCDoffset;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
byte *Scumm::getOBCDFromObject(int obj)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
if (_objectOwnerTable[obj] != OF_OWNER_ROOM) {
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _maxInventoryItems; i++) {
|
2001-10-09 14:30:12 +00:00
|
|
|
if (_inventory[i] == obj)
|
2001-11-05 19:21:49 +00:00
|
|
|
return getResourceAddress(rtInventory, i);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
} else {
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = (_numLocalObjects-1); i > 0; --i) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_objs[i].obj_nr == obj) {
|
2001-10-16 10:01:48 +00:00
|
|
|
if (_objs[i].fl_object_index)
|
2002-04-11 17:19:16 +00:00
|
|
|
return getResourceAddress(rtFlObject, _objs[i].fl_object_index) + 8;
|
2002-12-26 20:37:49 +00:00
|
|
|
if (_features & GF_AFTER_V8)
|
|
|
|
return getResourceAddress(rtRoomScripts, _roomResource) + _objs[i].OBCDoffset;
|
|
|
|
else
|
|
|
|
return getResourceAddress(rtRoom, _roomResource) + _objs[i].OBCDoffset;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::addObjectToInventory(uint obj, uint room)
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i, slot;
|
2001-11-26 19:57:57 +00:00
|
|
|
uint32 size;
|
2002-12-27 19:48:30 +00:00
|
|
|
byte *ptr, *dst;
|
2001-11-26 19:57:57 +00:00
|
|
|
FindObjectInRoom foir;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
debug(1, "Adding object %d from room %d into inventory", obj, room);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-26 21:50:13 +00:00
|
|
|
CHECK_HEAP
|
|
|
|
if (whereIsObject(obj) == WIO_FLOBJECT) {
|
2001-10-09 14:30:12 +00:00
|
|
|
i = getObjectIndex(obj);
|
2001-12-27 17:51:58 +00:00
|
|
|
ptr = getResourceAddress(rtFlObject, _objs[i].fl_object_index) + 8;
|
2002-04-11 17:19:16 +00:00
|
|
|
size = READ_BE_UINT32_UNALIGNED(ptr + 4);
|
2001-11-26 19:57:57 +00:00
|
|
|
} else {
|
|
|
|
findObjectInRoom(&foir, foCodeHeader, obj, room);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (_features & GF_SMALL_HEADER)
|
|
|
|
size = READ_LE_UINT32(foir.obcd);
|
|
|
|
else
|
|
|
|
size = READ_BE_UINT32_UNALIGNED(foir.obcd + 4);
|
2002-12-27 19:48:30 +00:00
|
|
|
ptr = foir.obcd;
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
|
|
|
|
2002-12-27 19:48:30 +00:00
|
|
|
slot = getInventorySlot();
|
|
|
|
_inventory[slot] = obj;
|
|
|
|
createResource(rtInventory, slot, size);
|
|
|
|
|
|
|
|
dst = getResourceAddress(rtInventory, slot);
|
|
|
|
assert(dst);
|
|
|
|
memcpy(dst, ptr, size);
|
|
|
|
|
2002-12-24 04:02:21 +00:00
|
|
|
CHECK_HEAP
|
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
void Scumm::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id, uint room)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2001-11-26 19:57:57 +00:00
|
|
|
CodeHeader *cdhd;
|
|
|
|
int i, numobj;
|
2002-04-11 17:19:16 +00:00
|
|
|
byte *roomptr, *obcdptr, *obimptr, *searchptr;
|
2001-11-26 19:57:57 +00:00
|
|
|
RoomHeader *roomhdr;
|
|
|
|
ImageHeader *imhd;
|
2002-03-05 20:43:26 +00:00
|
|
|
int id2;
|
2002-03-05 21:03:32 +00:00
|
|
|
int id3;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
if (findWhat & foCheckAlreadyLoaded && getObjectIndex(id) != -1) {
|
2001-12-27 17:51:58 +00:00
|
|
|
fo->obcd = obcdptr = getOBCDFromObject(id);
|
2002-04-11 17:19:16 +00:00
|
|
|
assert((byte *)obcdptr > (byte *)256);
|
2002-07-16 21:03:14 +00:00
|
|
|
fo->obim = obimptr = obcdptr + RES_SIZE(obcdptr);
|
2002-04-11 17:19:16 +00:00
|
|
|
fo->cdhd = (CodeHeader *)findResourceData(MKID('CDHD'), obcdptr);
|
|
|
|
fo->imhd = (ImageHeader *)findResourceData(MKID('IMHD'), obimptr);
|
2001-10-09 14:30:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
|
|
|
|
fo->roomptr = roomptr = getResourceAddress(rtRoom, room);
|
2002-04-19 16:26:44 +00:00
|
|
|
if (!roomptr)
|
|
|
|
error("findObjectInRoom: failed getting roomptr to %d", room);
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
roomhdr = (RoomHeader *)findResourceData(MKID('RMHD'), roomptr);
|
|
|
|
|
2002-12-24 04:02:21 +00:00
|
|
|
if (_features & GF_AFTER_V8)
|
|
|
|
numobj = READ_LE_UINT32(&(roomhdr->v8.numObjects));
|
|
|
|
else if (_features & GF_AFTER_V7)
|
2002-03-05 20:13:47 +00:00
|
|
|
numobj = READ_LE_UINT16(&(roomhdr->v7.numObjects));
|
|
|
|
else
|
|
|
|
numobj = READ_LE_UINT16(&(roomhdr->old.numObjects));
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
if (numobj == 0)
|
2001-11-26 19:57:57 +00:00
|
|
|
error("findObjectInRoom: No object found in room %d", room);
|
2001-11-06 21:41:56 +00:00
|
|
|
if (numobj > _numLocalObjects)
|
2002-07-07 20:25:23 +00:00
|
|
|
error("findObjectInRoom: More (%d) than %d objects in room %d", numobj, _numLocalObjects, room);
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-12-25 12:14:42 +00:00
|
|
|
if (_features & GF_AFTER_V8) {
|
2002-12-25 03:48:27 +00:00
|
|
|
roomptr = getResourceAddress(rtRoomScripts, room);
|
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
if (findWhat & foCodeHeader) {
|
|
|
|
searchptr = roomptr;
|
2002-12-27 14:36:28 +00:00
|
|
|
assert(searchptr);
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0;;) {
|
|
|
|
if (_features & GF_SMALL_HEADER)
|
|
|
|
obcdptr = findResourceSmall(MKID('OBCD'), searchptr);
|
|
|
|
else
|
|
|
|
obcdptr = findResource(MKID('OBCD'), searchptr);
|
|
|
|
if (obcdptr == NULL)
|
2001-11-26 19:57:57 +00:00
|
|
|
error("findObjectInRoom: Not enough code blocks in room %d", room);
|
2002-12-25 11:59:55 +00:00
|
|
|
cdhd = (CodeHeader *)findResourceData(MKID('CDHD'), obcdptr);
|
|
|
|
|
|
|
|
if (_features & GF_SMALL_HEADER)
|
|
|
|
id2 = READ_LE_UINT16(obcdptr + 6);
|
|
|
|
else if (_features & GF_AFTER_V7)
|
|
|
|
id2 = READ_LE_UINT16(&(cdhd->v7.obj_id));
|
|
|
|
else if (_features & GF_AFTER_V6)
|
|
|
|
id2 = READ_LE_UINT16(&(cdhd->v6.obj_id));
|
|
|
|
else
|
|
|
|
id2 = READ_LE_UINT16(&(cdhd->v5.obj_id));
|
|
|
|
|
|
|
|
if (id2 == (uint16)id) {
|
|
|
|
fo->cdhd = cdhd;
|
|
|
|
fo->obcd = obcdptr;
|
|
|
|
break;
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
2001-11-26 19:57:57 +00:00
|
|
|
if (++i == numobj)
|
|
|
|
error("findObjectInRoom: Object %d not found in room %d", id, room);
|
|
|
|
searchptr = NULL;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-12-25 03:48:27 +00:00
|
|
|
roomptr = fo->roomptr;
|
2001-11-26 19:57:57 +00:00
|
|
|
if (findWhat & foImageHeader) {
|
|
|
|
searchptr = roomptr;
|
2002-12-27 14:36:28 +00:00
|
|
|
assert(searchptr);
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0;;) {
|
|
|
|
if (_features & GF_SMALL_HEADER)
|
|
|
|
obimptr = findResourceSmall(MKID('OBIM'), searchptr);
|
|
|
|
else
|
|
|
|
obimptr = findResource(MKID('OBIM'), searchptr);
|
|
|
|
if (obimptr == NULL)
|
2001-11-26 19:57:57 +00:00
|
|
|
error("findObjectInRoom: Not enough image blocks in room %d", room);
|
2002-04-11 17:19:16 +00:00
|
|
|
imhd = (ImageHeader *)findResourceData(MKID('IMHD'), obimptr);
|
2002-12-25 11:59:55 +00:00
|
|
|
if (_features & GF_SMALL_HEADER)
|
|
|
|
id3 = READ_LE_UINT16(obimptr + 6);
|
|
|
|
else if (_features & GF_AFTER_V8)
|
|
|
|
// In V8, IMHD has no obj_id, but rather a name string. We map the name
|
|
|
|
// back to an object id using a table derived from the DOBJ resource.
|
|
|
|
id3 = _objectIDMap[imhd->v8.name];
|
|
|
|
else if (_features & GF_AFTER_V7)
|
|
|
|
id3 = READ_LE_UINT16(&imhd->v7.obj_id);
|
|
|
|
else
|
|
|
|
id3 = READ_LE_UINT16(&imhd->old.obj_id);
|
|
|
|
|
|
|
|
if (id3 == (uint16)id) {
|
|
|
|
fo->obim = obimptr;
|
|
|
|
fo->imhd = imhd;
|
|
|
|
break;
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
if (++i == numobj)
|
2002-07-07 20:25:23 +00:00
|
|
|
error("findObjectInRoom: Object %d image not found in room %d", id, room);
|
2001-11-26 19:57:57 +00:00
|
|
|
searchptr = NULL;
|
|
|
|
}
|
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getInventorySlot()
|
|
|
|
{
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 1; i <= _maxInventoryItems; i++) {
|
|
|
|
if (_inventory[i] == 0)
|
2001-10-09 14:30:12 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
error("Inventory full, %d max items", _maxInventoryItems);
|
2002-05-05 18:10:29 +00:00
|
|
|
return -1;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::SamInventoryHack(int obj)
|
|
|
|
{ // FIXME: Sam and Max hack
|
2002-03-05 09:24:42 +00:00
|
|
|
int base = 6;
|
|
|
|
|
|
|
|
while (base < 80) {
|
|
|
|
int value = readArray(178, 0, base);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (value == obj)
|
|
|
|
return;
|
2002-03-05 09:24:42 +00:00
|
|
|
if (value == 0) {
|
2002-04-11 17:19:16 +00:00
|
|
|
_vars[179]++;
|
|
|
|
writeArray(178, 0, base, obj);
|
|
|
|
return;
|
2002-03-05 09:24:42 +00:00
|
|
|
}
|
|
|
|
base++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::setOwnerOf(int obj, int owner)
|
|
|
|
{
|
2001-10-16 10:01:48 +00:00
|
|
|
ScriptSlot *ss;
|
2002-04-11 17:19:16 +00:00
|
|
|
if (owner == 0) {
|
2001-10-16 10:01:48 +00:00
|
|
|
clearOwnerOf(obj);
|
|
|
|
ss = &vm.slot[_currentScript];
|
2002-04-11 17:19:16 +00:00
|
|
|
if (ss->where == WIO_INVENTORY && _inventory[ss->number] == obj) {
|
2001-10-16 10:01:48 +00:00
|
|
|
putOwner(obj, 0);
|
|
|
|
runHook(0);
|
|
|
|
stopObjectCode();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2002-03-05 09:24:42 +00:00
|
|
|
if ((owner == 2) && (_gameId == GID_SAMNMAX))
|
|
|
|
SamInventoryHack(obj);
|
|
|
|
|
2001-10-16 10:01:48 +00:00
|
|
|
putOwner(obj, owner);
|
|
|
|
runHook(0);
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjX(int obj)
|
|
|
|
{
|
2001-11-26 19:57:57 +00:00
|
|
|
if (obj < NUM_ACTORS) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (obj < 1)
|
|
|
|
return 0; /* fix for indy4's map */
|
|
|
|
return derefActorSafe(obj, "getObjX")->x;
|
2001-10-16 10:01:48 +00:00
|
|
|
} else {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (whereIsObject(obj) == WIO_NOT_FOUND)
|
2001-10-16 10:01:48 +00:00
|
|
|
return -1;
|
2002-07-16 18:51:27 +00:00
|
|
|
int x, y;
|
|
|
|
getObjectOrActorXY(obj, x, y);
|
|
|
|
return x;
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjY(int obj)
|
|
|
|
{
|
2001-11-26 19:57:57 +00:00
|
|
|
if (obj < NUM_ACTORS) {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (obj < 1)
|
|
|
|
return 0; /* fix for indy4's map */
|
|
|
|
return derefActorSafe(obj, "getObjY")->y;
|
2001-10-16 10:01:48 +00:00
|
|
|
} else {
|
2002-04-11 17:19:16 +00:00
|
|
|
if (whereIsObject(obj) == WIO_NOT_FOUND)
|
2001-10-16 10:01:48 +00:00
|
|
|
return -1;
|
2002-07-16 18:51:27 +00:00
|
|
|
int x, y;
|
|
|
|
getObjectOrActorXY(obj, x, y);
|
|
|
|
return y;
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjOldDir(int obj)
|
|
|
|
{
|
2001-11-26 19:57:57 +00:00
|
|
|
if (obj < NUM_ACTORS) {
|
2002-04-11 17:19:16 +00:00
|
|
|
return newDirToOldDir(derefActorSafe(obj, "getObjOldDir")->facing);
|
2001-10-16 10:01:48 +00:00
|
|
|
} else {
|
2002-07-16 18:51:27 +00:00
|
|
|
int x, y, dir;
|
|
|
|
getObjectXYPos(obj, x, y, dir);
|
|
|
|
return dir;
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getObjNewDir(int obj)
|
|
|
|
{
|
2001-12-27 17:51:58 +00:00
|
|
|
if (obj < NUM_ACTORS) {
|
2002-04-11 17:19:16 +00:00
|
|
|
return derefActorSafe(obj, "getObjNewDir")->facing;
|
2001-12-27 17:51:58 +00:00
|
|
|
} else {
|
2002-07-16 18:51:27 +00:00
|
|
|
int x, y, dir;
|
|
|
|
getObjectXYPos(obj, x, y, dir);
|
|
|
|
return oldDirToNewDir(dir);
|
2001-12-27 17:51:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::findInventory(int owner, int idx)
|
|
|
|
{
|
2001-10-16 10:01:48 +00:00
|
|
|
int count = 1, i, obj;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i != _maxInventoryItems; i++) {
|
2001-10-16 10:01:48 +00:00
|
|
|
obj = _inventory[i];
|
2002-04-11 17:19:16 +00:00
|
|
|
if (obj && getOwner(obj) == owner && count++ == idx)
|
2001-10-16 10:01:48 +00:00
|
|
|
return obj;
|
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
return 0;
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::getInventoryCount(int owner)
|
|
|
|
{
|
|
|
|
int i, obj;
|
2001-10-16 10:01:48 +00:00
|
|
|
int count = 0;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i != _maxInventoryItems; i++) {
|
2001-10-16 10:01:48 +00:00
|
|
|
obj = _inventory[i];
|
|
|
|
if (obj && getOwner(obj) == owner)
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::setObjectState(int obj, int state, int x, int y)
|
|
|
|
{
|
2001-10-16 10:01:48 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
i = getObjectIndex(obj);
|
2002-04-11 17:19:16 +00:00
|
|
|
if (i == -1) {
|
2001-11-26 19:57:57 +00:00
|
|
|
warning("setObjectState: no such object");
|
2001-10-16 10:01:48 +00:00
|
|
|
return;
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
2001-10-16 10:01:48 +00:00
|
|
|
|
|
|
|
if (x != -1) {
|
2002-04-11 17:19:16 +00:00
|
|
|
_objs[i].x_pos = x << 3;
|
|
|
|
_objs[i].y_pos = y << 3;
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
addObjectToDrawQue(i);
|
|
|
|
putState(obj, state);
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
static int getDist(int x, int y, int x2, int y2)
|
|
|
|
{
|
|
|
|
int a = abs(y - y2);
|
|
|
|
int b = abs(x - x2);
|
|
|
|
if (a > b)
|
2001-10-16 10:01:48 +00:00
|
|
|
return a;
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
int Scumm::getDistanceBetween(bool is_obj_1, int b, int c, bool is_obj_2, int e, int f)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int x, y;
|
|
|
|
int x2, y2;
|
|
|
|
|
2001-10-16 10:01:48 +00:00
|
|
|
j = i = 0xFF;
|
|
|
|
|
|
|
|
if (is_obj_1) {
|
2002-07-16 18:51:27 +00:00
|
|
|
if (getObjectOrActorXY(b, x, y) == -1)
|
2001-10-16 10:01:48 +00:00
|
|
|
return -1;
|
2001-11-26 19:57:57 +00:00
|
|
|
if (b < NUM_ACTORS)
|
2001-10-16 10:01:48 +00:00
|
|
|
i = derefActorSafe(b, "unkObjProc1")->scalex;
|
|
|
|
} else {
|
|
|
|
x = b;
|
|
|
|
y = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_obj_2) {
|
2002-07-16 18:51:27 +00:00
|
|
|
if (getObjectOrActorXY(e, x2, y2) == -1)
|
2001-10-16 10:01:48 +00:00
|
|
|
return -1;
|
2001-11-26 19:57:57 +00:00
|
|
|
if (e < NUM_ACTORS)
|
2001-10-16 10:01:48 +00:00
|
|
|
j = derefActorSafe(e, "unkObjProc1(2)")->scalex;
|
|
|
|
} else {
|
|
|
|
x2 = e;
|
|
|
|
y2 = f;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
return getDist(x, y, x2, y2) * 0xFF / ((i + j) >> 1);
|
2001-10-16 10:01:48 +00:00
|
|
|
}
|
2001-11-06 20:00:47 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::setCursorImg(uint img, uint room, uint imgindex)
|
|
|
|
{
|
|
|
|
int w, h;
|
|
|
|
byte *dataptr, *bomp;
|
2001-11-06 20:00:47 +00:00
|
|
|
uint32 size;
|
2001-11-26 19:57:57 +00:00
|
|
|
FindObjectInRoom foir;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
if (room == (uint) - 1)
|
2001-11-26 19:57:57 +00:00
|
|
|
room = getObjectRoom(img);
|
2001-11-06 20:00:47 +00:00
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
findObjectInRoom(&foir, foCodeHeader | foImageHeader | foCheckAlreadyLoaded, img, room);
|
2001-11-06 20:00:47 +00:00
|
|
|
|
2002-12-24 04:02:21 +00:00
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
setCursorHotspot2(READ_LE_UINT32(&foir.imhd->v8.hotspot[0].x),
|
|
|
|
READ_LE_UINT32(&foir.imhd->v8.hotspot[0].y));
|
|
|
|
w = READ_LE_UINT32(&foir.imhd->v8.width) >> 3;
|
|
|
|
h = READ_LE_UINT32(&foir.imhd->v8.height) >> 3;
|
|
|
|
} else if (_features & GF_AFTER_V7) {
|
2002-04-11 17:19:16 +00:00
|
|
|
setCursorHotspot2(READ_LE_UINT16(&foir.imhd->v7.hotspot[0].x),
|
2002-12-24 04:02:21 +00:00
|
|
|
READ_LE_UINT16(&foir.imhd->v7.hotspot[0].y));
|
|
|
|
w = READ_LE_UINT16(&foir.imhd->v7.width) >> 3;
|
|
|
|
h = READ_LE_UINT16(&foir.imhd->v7.height) >> 3;
|
|
|
|
} else {
|
2002-04-11 17:19:16 +00:00
|
|
|
setCursorHotspot2(READ_LE_UINT16(&foir.imhd->old.hotspot[0].x),
|
2002-12-24 04:02:21 +00:00
|
|
|
READ_LE_UINT16(&foir.imhd->old.hotspot[0].y));
|
2002-04-11 17:19:16 +00:00
|
|
|
w = READ_LE_UINT16(&foir.cdhd->v6.w) >> 3;
|
|
|
|
h = READ_LE_UINT16(&foir.cdhd->v6.h) >> 3;
|
2002-03-05 23:41:41 +00:00
|
|
|
}
|
2001-11-06 20:00:47 +00:00
|
|
|
|
2002-12-25 03:48:27 +00:00
|
|
|
// TODO - for V8 don't use IMxx_tags. Rather, we do something similiar to the V8
|
|
|
|
// code in drawBlastObject. It would be *much* nicer if we could aggregate this
|
|
|
|
// common code into some helper functions, instead of having long convuluted
|
|
|
|
// cases scattered all over the place.
|
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
dataptr = findResource(MKID('IMAG'), foir.obim);
|
|
|
|
assert(dataptr);
|
|
|
|
dataptr = findResource(MKID('WRAP'), dataptr);
|
|
|
|
assert(dataptr);
|
|
|
|
dataptr = findResource(MKID('OFFS'), dataptr);
|
|
|
|
assert(dataptr);
|
|
|
|
dataptr += READ_LE_UINT32(dataptr + 4 + 4*imgindex);
|
|
|
|
// TODO - distinguish between SMAP and BOMP here?
|
2001-11-06 20:00:47 +00:00
|
|
|
|
2002-12-25 03:48:27 +00:00
|
|
|
// HACK - adjust dataptr here until bomp code gets adjusted for V8
|
2002-12-25 12:41:41 +00:00
|
|
|
bomp = dataptr;
|
2002-12-25 03:48:27 +00:00
|
|
|
} else {
|
|
|
|
dataptr = findResource(IMxx_tags[imgindex], foir.obim);
|
|
|
|
if (dataptr == NULL)
|
|
|
|
error("setCursorImg: No such image");
|
|
|
|
|
|
|
|
size = READ_BE_UINT32_UNALIGNED(dataptr + 4);
|
|
|
|
if (size > sizeof(_grabbedCursor))
|
|
|
|
error("setCursorImg: Cursor image too large");
|
|
|
|
|
|
|
|
bomp = findResource(MKID('BOMP'), dataptr);
|
|
|
|
}
|
2001-11-06 20:00:47 +00:00
|
|
|
|
2002-12-25 03:48:27 +00:00
|
|
|
if (bomp != NULL)
|
2001-11-06 20:00:47 +00:00
|
|
|
useBompCursor(bomp, w, h);
|
|
|
|
else
|
|
|
|
useIm01Cursor(dataptr, w, h);
|
|
|
|
|
|
|
|
}
|
2001-11-11 16:54:45 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::nukeFlObjects(int min, int max)
|
|
|
|
{
|
2001-11-11 16:54:45 +00:00
|
|
|
ObjectData *od;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
warning("nukeFlObjects(%d,%d)", min, max);
|
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = (_numLocalObjects-1), od = _objs; --i >= 0; od++)
|
2002-04-11 17:19:16 +00:00
|
|
|
if (od->fl_object_index && od->obj_nr >= min && od->obj_nr <= max) {
|
2001-11-11 16:54:45 +00:00
|
|
|
nukeResource(rtFlObject, od->fl_object_index);
|
|
|
|
od->obj_nr = 0;
|
|
|
|
od->fl_object_index = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
void Scumm::enqueueObject(int objectNumber, int objectX, int objectY, int objectWidth,
|
2002-11-06 15:29:49 +00:00
|
|
|
int objectHeight, int scaleX, int scaleY, int image, int mode)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-04-21 21:20:32 +00:00
|
|
|
BlastObject *eo;
|
2001-11-11 16:54:45 +00:00
|
|
|
ObjectData *od;
|
|
|
|
|
2002-10-23 03:28:06 +00:00
|
|
|
if (_enqueuePos == sizeof(_enqueuedObjects) / sizeof(_enqueuedObjects[0])) {
|
|
|
|
warning("enqueueObject: overflow");
|
|
|
|
return;
|
|
|
|
}
|
2001-11-11 16:54:45 +00:00
|
|
|
|
|
|
|
eo = &_enqueuedObjects[_enqueuePos++];
|
2002-04-22 13:55:28 +00:00
|
|
|
eo->number = objectNumber;
|
2002-05-20 16:02:29 +00:00
|
|
|
eo->posX = objectX + (camera._cur.x & 7);
|
2002-09-01 15:01:40 +00:00
|
|
|
eo->posY = objectY + (camera._cur.y - (_realHeight / 2));
|
2002-04-21 21:20:32 +00:00
|
|
|
if (objectWidth == 0) {
|
|
|
|
od = &_objs[getObjectIndex(objectNumber)];
|
2001-11-26 19:57:57 +00:00
|
|
|
eo->width = od->width;
|
2001-11-11 16:54:45 +00:00
|
|
|
} else {
|
2002-04-21 21:20:32 +00:00
|
|
|
eo->width = objectWidth;
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
2002-04-21 21:20:32 +00:00
|
|
|
if (objectHeight == 0) {
|
|
|
|
od = &_objs[getObjectIndex(objectNumber)];
|
2001-11-26 19:57:57 +00:00
|
|
|
eo->height = od->height;
|
2001-11-11 16:54:45 +00:00
|
|
|
} else {
|
2002-04-21 21:20:32 +00:00
|
|
|
eo->height = objectHeight;
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
|
|
|
|
2002-11-06 15:29:49 +00:00
|
|
|
eo->scaleX = scaleX;
|
|
|
|
eo->scaleY = scaleY;
|
2002-04-22 13:55:28 +00:00
|
|
|
eo->image = image;
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2002-04-21 21:20:32 +00:00
|
|
|
eo->mode = mode;
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
|
|
|
|
2002-04-21 21:20:32 +00:00
|
|
|
void Scumm::drawBlastObjects()
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-04-21 21:20:32 +00:00
|
|
|
BlastObject *eo;
|
2001-11-11 16:54:45 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
eo = _enqueuedObjects;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _enqueuePos; i++, eo++) {
|
2002-04-21 21:20:32 +00:00
|
|
|
drawBlastObject(eo);
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
void Scumm::drawBlastObject(BlastObject *eo)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2001-11-11 16:54:45 +00:00
|
|
|
VirtScreen *vs;
|
2002-12-31 03:26:02 +00:00
|
|
|
byte *bomp, *ptr;
|
2003-01-01 11:25:04 +00:00
|
|
|
int idx, objnum;
|
2001-11-27 17:56:04 +00:00
|
|
|
BompDrawData bdd;
|
|
|
|
|
2001-11-11 16:54:45 +00:00
|
|
|
vs = &virtscr[0];
|
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
checkRange(_numGlobalObjects - 1, 30, eo->number, "Illegal Blast object %d");
|
2002-04-22 13:55:28 +00:00
|
|
|
|
2003-01-01 11:25:04 +00:00
|
|
|
objnum = getObjectIndex(eo->number);
|
|
|
|
if (objnum == -1)
|
|
|
|
error("drawBlastObject: getObjectIndex on BlastObject %d failed", eo->number);
|
2002-04-22 13:55:28 +00:00
|
|
|
|
2003-01-01 11:25:04 +00:00
|
|
|
idx = _objs[objnum].fl_object_index;
|
2002-07-07 20:25:23 +00:00
|
|
|
if (idx) {
|
2002-04-22 13:55:28 +00:00
|
|
|
ptr = getResourceAddress(rtFlObject, idx);
|
2001-11-26 19:57:57 +00:00
|
|
|
ptr = findResource(MKID('OBIM'), ptr);
|
2001-11-11 16:54:45 +00:00
|
|
|
} else {
|
2003-01-01 11:25:04 +00:00
|
|
|
idx = objnum;
|
|
|
|
ptr = getResourceAddress(rtRoom, _roomResource) + _objs[objnum].OBIMoffset;
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
2002-07-07 20:25:23 +00:00
|
|
|
if (!ptr)
|
2002-12-27 14:36:28 +00:00
|
|
|
error("BlastObject object %d (%d) image not found", eo->number, idx);
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-12-25 03:48:27 +00:00
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
// The OBIM contains an IMAG, which in turn contains a WRAP, which contains
|
|
|
|
// an OFFS chunk and multiple BOMP chunks. To find the right BOMP, we can
|
|
|
|
// either use the offsets in the OFFS chunk, or iterate over all BOMPs we find.
|
|
|
|
// Here we use the first method.
|
2002-12-31 03:26:02 +00:00
|
|
|
ptr = findResource(MKID('IMAG'), ptr);
|
|
|
|
assert(ptr);
|
|
|
|
ptr = findResource(MKID('WRAP'), ptr);
|
|
|
|
assert(ptr);
|
|
|
|
ptr = findResource(MKID('OFFS'), ptr);
|
|
|
|
assert(ptr);
|
|
|
|
// Get the address of the specified BOMP (we really should verify it's a BOMP and not a SMAP
|
|
|
|
bomp = ptr + READ_LE_UINT32(ptr + 4 + 4*eo->image) + 8;
|
2002-12-25 03:48:27 +00:00
|
|
|
} else {
|
2002-12-31 03:26:02 +00:00
|
|
|
byte *img = findResource(IMxx_tags[eo->image], ptr);
|
2002-12-25 03:48:27 +00:00
|
|
|
if (!img)
|
|
|
|
img = findResource(IMxx_tags[1], ptr); // Backward compatibility with samnmax blast objects
|
|
|
|
|
|
|
|
if (!img)
|
|
|
|
error("blast-object %d invalid image %d (1-x)", eo->number, eo->image);
|
|
|
|
|
|
|
|
bomp = findResourceData(MKID('BOMP'), img);
|
|
|
|
}
|
2002-04-22 13:55:28 +00:00
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
if (!bomp)
|
|
|
|
error("object %d is not a blast object", eo->number);
|
2001-11-11 16:54:45 +00:00
|
|
|
|
2002-12-25 04:30:24 +00:00
|
|
|
//hexdump(bomp,32);
|
2001-11-11 16:54:45 +00:00
|
|
|
|
2002-12-25 03:48:27 +00:00
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
bdd.srcwidth = READ_LE_UINT32(&((BompHeader *)bomp)->v8.width);
|
|
|
|
bdd.srcheight = READ_LE_UINT32(&((BompHeader *)bomp)->v8.height);
|
|
|
|
} else {
|
|
|
|
bdd.srcwidth = READ_LE_UINT16(&((BompHeader *)bomp)->old.width);
|
|
|
|
bdd.srcheight = READ_LE_UINT16(&((BompHeader *)bomp)->old.height);
|
|
|
|
}
|
|
|
|
|
2002-03-20 22:58:41 +00:00
|
|
|
bdd.out = vs->screenPtr + vs->xstart;
|
2002-04-22 16:18:20 +00:00
|
|
|
bdd.outwidth = vs->width;
|
2001-11-27 17:56:04 +00:00
|
|
|
bdd.outheight = vs->height;
|
2002-12-25 03:48:27 +00:00
|
|
|
if (_features & GF_AFTER_V8) {
|
|
|
|
bdd.dataptr = bomp + 8; // Why this? See also useBompCursor
|
|
|
|
} else {
|
|
|
|
bdd.dataptr = bomp + 10; // Why this? See also useBompCursor
|
|
|
|
}
|
2002-04-22 13:55:28 +00:00
|
|
|
bdd.x = eo->posX;
|
|
|
|
bdd.y = eo->posY;
|
2002-11-06 07:28:39 +00:00
|
|
|
bdd.scale_x = (byte)eo->scaleX;
|
|
|
|
bdd.scale_y = (byte)eo->scaleY;
|
|
|
|
|
|
|
|
byte bomp_scalling_x[64], bomp_scalling_y[64];
|
|
|
|
|
|
|
|
if ((bdd.scale_x != 255) || (bdd.scale_y != 255)) {
|
2002-11-06 14:02:07 +00:00
|
|
|
_bompScallingXPtr = bomp_scalling_x;
|
|
|
|
_bompScallingYPtr = bomp_scalling_y;
|
2002-11-06 07:28:39 +00:00
|
|
|
_bompScaleRight = setupBompScale(_bompScallingXPtr, bdd.srcwidth, bdd.scale_x);
|
|
|
|
_bompScaleBottom = setupBompScale(_bompScallingYPtr, bdd.srcheight, bdd.scale_y);
|
2002-11-06 15:29:49 +00:00
|
|
|
bdd.shadowMode = 0;
|
2002-11-06 14:54:21 +00:00
|
|
|
drawBomp(&bdd, 1, 3);
|
2002-11-06 07:28:39 +00:00
|
|
|
} else {
|
2002-11-06 15:29:49 +00:00
|
|
|
bdd.shadowMode = eo->mode;
|
2002-11-06 14:54:21 +00:00
|
|
|
drawBomp(&bdd, 1, 0);
|
2002-11-06 07:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_bompScallingXPtr = NULL;
|
|
|
|
_bompScallingYPtr = NULL;
|
|
|
|
_bompScaleRight = 0;
|
|
|
|
_bompScaleBottom = 0;
|
2001-11-11 16:54:45 +00:00
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
updateDirtyRect(vs->number, bdd.x, bdd.x + bdd.srcwidth, bdd.y, bdd.y + bdd.srcheight, 0);
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
|
|
|
|
2002-11-06 07:28:39 +00:00
|
|
|
byte _bompScaleTable[] = {
|
|
|
|
0, 128, 64, 192, 32, 160, 96, 224,
|
|
|
|
16, 144, 80, 208, 48, 176, 112, 240,
|
|
|
|
8, 136, 72, 200, 40, 168, 104, 232,
|
|
|
|
24, 152, 88, 216, 56, 184, 120, 248,
|
|
|
|
4, 132, 68, 196, 36, 164, 100, 228,
|
|
|
|
20, 148, 84, 212, 52, 180, 116, 244,
|
|
|
|
12, 140, 76, 204, 44, 172, 108, 236,
|
|
|
|
28, 156, 92, 220, 60, 188, 124, 252,
|
|
|
|
2, 130, 66, 194, 34, 162, 98, 226,
|
|
|
|
18, 146, 82, 210, 50, 178, 114, 242,
|
|
|
|
10, 138, 74, 202, 42, 170, 106, 234,
|
|
|
|
26, 154, 90, 218, 58, 186, 122, 250,
|
|
|
|
6, 134, 70, 198, 38, 166, 102, 230,
|
|
|
|
22, 150, 86, 214, 54, 182, 118, 246,
|
|
|
|
14, 142, 78, 206, 46, 174, 110, 238,
|
|
|
|
30, 158, 94, 222, 62, 190, 126, 254,
|
|
|
|
1, 129, 65, 193, 33, 161, 97, 225,
|
|
|
|
17, 145, 81, 209, 49, 177, 113, 241,
|
|
|
|
9, 137, 73, 201, 41, 169, 105, 233,
|
|
|
|
25, 153, 89, 217, 57, 185, 121, 249,
|
2002-11-09 07:13:30 +00:00
|
|
|
5, 133, 69, 197, 37, 165, 101, 229,
|
|
|
|
21, 149, 85, 213, 53, 181, 117, 245,
|
|
|
|
13, 141, 77, 205, 45, 173, 109, 237,
|
|
|
|
29, 157, 93, 221, 61, 189, 125, 253,
|
|
|
|
3, 131, 67, 195, 35, 163, 99, 227,
|
|
|
|
19, 147, 83, 211, 51, 179, 115, 243,
|
|
|
|
11, 139, 75, 203, 43, 171, 107, 235,
|
|
|
|
27, 155, 91, 219, 59, 187, 123, 251,
|
|
|
|
7, 135, 71, 199, 39, 167, 103, 231,
|
|
|
|
23, 151, 87, 215, 55, 183, 119, 247,
|
|
|
|
15, 143, 79, 207, 47, 175, 111, 239,
|
|
|
|
31, 159, 95, 223, 63, 191, 127, 255,
|
|
|
|
|
|
|
|
0, 128, 64, 192, 32, 160, 96, 224,
|
|
|
|
16, 144, 80, 208, 48, 176, 112, 240,
|
|
|
|
8, 136, 72, 200, 40, 168, 104, 232,
|
|
|
|
24, 152, 88, 216, 56, 184, 120, 248,
|
|
|
|
4, 132, 68, 196, 36, 164, 100, 228,
|
|
|
|
20, 148, 84, 212, 52, 180, 116, 244,
|
|
|
|
12, 140, 76, 204, 44, 172, 108, 236,
|
|
|
|
28, 156, 92, 220, 60, 188, 124, 252,
|
|
|
|
2, 130, 66, 194, 34, 162, 98, 226,
|
|
|
|
18, 146, 82, 210, 50, 178, 114, 242,
|
|
|
|
10, 138, 74, 202, 42, 170, 106, 234,
|
|
|
|
26, 154, 90, 218, 58, 186, 122, 250,
|
|
|
|
6, 134, 70, 198, 38, 166, 102, 230,
|
|
|
|
22, 150, 86, 214, 54, 182, 118, 246,
|
|
|
|
14, 142, 78, 206, 46, 174, 110, 238,
|
|
|
|
30, 158, 94, 222, 62, 190, 126, 254,
|
|
|
|
1, 129, 65, 193, 33, 161, 97, 225,
|
|
|
|
17, 145, 81, 209, 49, 177, 113, 241,
|
|
|
|
9, 137, 73, 201, 41, 169, 105, 233,
|
|
|
|
25, 153, 89, 217, 57, 185, 121, 249,
|
2002-11-06 07:28:39 +00:00
|
|
|
5, 133, 69, 197, 37, 165, 101, 229,
|
|
|
|
21, 149, 85, 213, 53, 181, 117, 245,
|
|
|
|
13, 141, 77, 205, 45, 173, 109, 237,
|
|
|
|
29, 157, 93, 221, 61, 189, 125, 253,
|
|
|
|
3, 131, 67, 195, 35, 163, 99, 227,
|
|
|
|
19, 147, 83, 211, 51, 179, 115, 243,
|
|
|
|
11, 139, 75, 203, 43, 171, 107, 235,
|
|
|
|
27, 155, 91, 219, 59, 187, 123, 251,
|
|
|
|
7, 135, 71, 199, 39, 167, 103, 231,
|
|
|
|
23, 151, 87, 215, 55, 183, 119, 247,
|
|
|
|
15, 143, 79, 207, 47, 175, 111, 239,
|
|
|
|
31, 159, 95, 223, 63, 191, 127, 255,
|
|
|
|
};
|
|
|
|
|
|
|
|
byte _bompBitsTable[] = {
|
|
|
|
8, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4,
|
|
|
|
7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
|
|
|
|
7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
|
|
|
|
6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
|
|
|
|
7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
|
|
|
|
6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
|
|
|
|
6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
|
|
|
|
5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
|
|
|
|
7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
|
|
|
|
6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
|
|
|
|
6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
|
|
|
|
5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
|
|
|
|
6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2,
|
|
|
|
5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
|
|
|
|
5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1,
|
|
|
|
4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
int32 Scumm::setupBompScale(byte * scalling, int32 size, byte scale) {
|
|
|
|
uint32 tmp;
|
|
|
|
int32 count = (size + 7) >> 3;
|
|
|
|
byte * tmp_ptr = _bompScaleTable + (256 - (size >> 1));
|
|
|
|
byte * tmp_scalling = scalling;
|
|
|
|
byte a = 0;
|
|
|
|
|
|
|
|
while((count--) != 0) {
|
|
|
|
tmp = *(tmp_ptr + 3);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp = *(tmp_ptr + 2);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp = *(tmp_ptr + 1);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp = *(tmp_ptr + 0);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp_ptr += 4;
|
|
|
|
|
|
|
|
tmp = *(tmp_ptr + 3);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp = *(tmp_ptr + 2);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp = *(tmp_ptr + 1);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp = *(tmp_ptr + 0);
|
|
|
|
a <<= 1;
|
|
|
|
if (scale < tmp) {
|
|
|
|
a |= 1;
|
|
|
|
}
|
|
|
|
tmp_ptr += 4;
|
|
|
|
|
|
|
|
*(tmp_scalling++) = a;
|
|
|
|
}
|
|
|
|
if ((size & 7) != 0) {
|
|
|
|
*(tmp_scalling - 1) |= revBitMask[size & 7];
|
|
|
|
}
|
|
|
|
|
|
|
|
count = (size + 7) >> 3;
|
|
|
|
byte ret_value = 0;
|
|
|
|
while((count--) != 0) {
|
|
|
|
ret_value += *(*(scalling++) + _bompBitsTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret_value;
|
|
|
|
}
|
|
|
|
|
2002-04-21 21:20:32 +00:00
|
|
|
void Scumm::removeBlastObjects()
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-04-21 21:20:32 +00:00
|
|
|
BlastObject *eo;
|
2001-11-11 16:54:45 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
eo = _enqueuedObjects;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < _enqueuePos; i++, eo++) {
|
2002-04-21 21:20:32 +00:00
|
|
|
removeBlastObject(eo);
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
clearEnqueue();
|
|
|
|
}
|
|
|
|
|
2002-07-07 20:25:23 +00:00
|
|
|
void Scumm::removeBlastObject(BlastObject *eo)
|
2002-04-11 17:19:16 +00:00
|
|
|
{
|
2002-10-11 11:50:06 +00:00
|
|
|
VirtScreen *vs = &virtscr[0];
|
|
|
|
|
|
|
|
int top, bottom, left, right;
|
|
|
|
int left_strip, right_strip;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
top = eo->posY;
|
|
|
|
bottom = eo->posY + eo->height;
|
|
|
|
left = eo->posX;
|
|
|
|
right = eo->posX + eo->width;
|
|
|
|
|
|
|
|
if (bottom < 0 || right < 0 || top > vs->height || left > vs->width)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (top < 0)
|
|
|
|
top = 0;
|
|
|
|
if (bottom > vs->height)
|
|
|
|
bottom = vs->height;
|
|
|
|
if (left < 0)
|
|
|
|
left = 0;
|
|
|
|
if (right > vs->width)
|
|
|
|
right = vs->width;
|
|
|
|
|
|
|
|
left_strip = left >> 3;
|
|
|
|
right_strip = (right >> 3) + 1;
|
|
|
|
|
|
|
|
if (left_strip < 0)
|
|
|
|
left_strip = 0;
|
2002-11-06 17:55:44 +00:00
|
|
|
if (_features & GF_AFTER_V7) {
|
|
|
|
if (right_strip > 409)
|
|
|
|
right_strip = 409;
|
|
|
|
} else {
|
|
|
|
if (right_strip >= 200)
|
|
|
|
right_strip = 200;
|
|
|
|
}
|
2002-10-11 11:50:06 +00:00
|
|
|
for (i = left_strip; i <= right_strip; i++)
|
|
|
|
gdi.resetBackground(top, bottom, i);
|
|
|
|
|
|
|
|
updateDirtyRect(0, left, right, top, bottom, 0x40000000);
|
2001-11-11 16:54:45 +00:00
|
|
|
}
|
|
|
|
|
2003-01-12 07:30:17 +00:00
|
|
|
int Scumm::findLocalObjectSlot()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2003-01-12 08:32:44 +00:00
|
|
|
for (i = 1; i < _numLocalObjects; i++) {
|
2003-01-12 08:37:59 +00:00
|
|
|
if (!_objs[i].obj_nr)
|
2003-01-12 07:30:17 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
int Scumm::findFlObjectSlot()
|
|
|
|
{
|
2001-11-26 19:57:57 +00:00
|
|
|
int i;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 1; i < _maxFLObject; i++) {
|
2001-11-26 19:57:57 +00:00
|
|
|
if (_baseFLObject[i] == NULL)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
error("findFlObjectSlot: Out of FLObject slots");
|
2002-05-05 18:10:29 +00:00
|
|
|
return -1;
|
2001-11-26 19:57:57 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
void Scumm::loadFlObject(uint object, uint room)
|
|
|
|
{
|
2001-11-26 19:57:57 +00:00
|
|
|
FindObjectInRoom foir;
|
2003-01-12 07:30:17 +00:00
|
|
|
int slot, objslot;
|
2001-11-26 19:57:57 +00:00
|
|
|
ObjectData *od;
|
2002-04-11 17:19:16 +00:00
|
|
|
byte *flob, *roomptr;
|
2001-11-26 19:57:57 +00:00
|
|
|
uint32 obcd_size, obim_size, flob_size;
|
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
// Don't load an already loaded object
|
2001-11-26 19:57:57 +00:00
|
|
|
if (whereIsObject(object) != WIO_NOT_FOUND)
|
|
|
|
return;
|
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
// Locate the object in the room resource
|
2001-11-26 19:57:57 +00:00
|
|
|
findObjectInRoom(&foir, foImageHeader | foCodeHeader, object, room);
|
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
// Add an entry for the new floating object in the local object table
|
2003-01-12 07:30:17 +00:00
|
|
|
if (!(objslot = findLocalObjectSlot()))
|
2001-11-26 19:57:57 +00:00
|
|
|
error("loadFlObject: Local Object Table overflow");
|
2003-01-12 07:30:17 +00:00
|
|
|
|
|
|
|
od = &_objs[objslot];
|
2001-11-26 19:57:57 +00:00
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
// Setup sizes
|
2001-12-03 11:49:06 +00:00
|
|
|
obcd_size = READ_BE_UINT32_UNALIGNED(foir.obcd + 4);
|
2002-12-26 20:37:49 +00:00
|
|
|
od->OBCDoffset = 8;
|
|
|
|
od->OBIMoffset = obcd_size + 8;
|
2001-12-03 11:49:06 +00:00
|
|
|
obim_size = READ_BE_UINT32_UNALIGNED(foir.obim + 4);
|
2001-11-26 19:57:57 +00:00
|
|
|
flob_size = obcd_size + obim_size + 8;
|
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
// Get room pointer
|
|
|
|
roomptr = getResourceAddress(rtRoom, room);
|
|
|
|
assert(roomptr);
|
|
|
|
|
|
|
|
// Allocate slot & memory for floating object
|
2001-11-26 19:57:57 +00:00
|
|
|
slot = findFlObjectSlot();
|
|
|
|
createResource(rtFlObject, slot, flob_size);
|
|
|
|
flob = getResourceAddress(rtFlObject, slot);
|
2002-12-27 14:36:28 +00:00
|
|
|
assert(flob);
|
|
|
|
|
|
|
|
// Copy object code + object image to floating object
|
2002-04-11 17:19:16 +00:00
|
|
|
((uint32 *)flob)[0] = MKID('FLOB');
|
|
|
|
((uint32 *)flob)[1] = TO_BE_32(flob_size);
|
2002-12-27 14:36:28 +00:00
|
|
|
|
2001-11-26 19:57:57 +00:00
|
|
|
memcpy(flob + 8, roomptr - foir.roomptr + foir.obcd, obcd_size);
|
|
|
|
memcpy(flob + 8 + obcd_size, roomptr - foir.roomptr + foir.obim, obim_size);
|
|
|
|
|
2002-12-27 14:36:28 +00:00
|
|
|
// Setup local object flags
|
|
|
|
setupRoomObject(od, flob, flob);
|
2001-11-26 19:57:57 +00:00
|
|
|
|
|
|
|
od->fl_object_index = slot;
|
|
|
|
}
|