mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 01:08:25 +00:00
5d8d871df3
svn-id: r20763
379 lines
10 KiB
C++
379 lines
10 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2005-2006 The ScummVM project
|
|
*
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "lure/res.h"
|
|
#include "lure/disk.h"
|
|
#include "lure/scripts.h"
|
|
#include "lure/system.h"
|
|
|
|
namespace Lure {
|
|
|
|
const char *actionList[] = {NULL, "Get", NULL, "Push", "Pull", "Operate", "Open",
|
|
"Close", "Lock", "Unlock", "Use", "Give", "Talk to", "Tell", "Buy",
|
|
"Look", "Look at", "Look through", "Ask", NULL, "Drink", "Status",
|
|
"Go to", "Return", "Bribe", "Examine"};
|
|
|
|
// Room data holding class
|
|
|
|
RoomData::RoomData(RoomResource *rec) {
|
|
roomNumber = READ_LE_UINT16(&rec->roomNumber);
|
|
descId = READ_LE_UINT16(&rec->descId);
|
|
sequenceOffset = READ_LE_UINT16(&rec->sequenceOffset);
|
|
numLayers = READ_LE_UINT16(&rec->numLayers);
|
|
|
|
for (int ctr = 0; ctr < 4; ++ctr)
|
|
layers[ctr] = READ_LE_UINT16(&rec->layers[ctr]);
|
|
|
|
clippingXStart = READ_LE_UINT16(&rec->clippingXStart);
|
|
clippingXEnd = READ_LE_UINT16(&rec->clippingXEnd);
|
|
}
|
|
|
|
// Room exit hotspot area holding class
|
|
|
|
RoomExitHotspotData::RoomExitHotspotData(RoomExitHotspotResource *rec) {
|
|
hotspotId = READ_LE_UINT16(&rec->hotspotId);
|
|
xs = READ_LE_INT16(&rec->xs);
|
|
ys = READ_LE_INT16(&rec->ys);
|
|
xe = READ_LE_INT16(&rec->xe);
|
|
ye = READ_LE_INT16(&rec->ye);
|
|
cursorNum = rec->cursorNum;
|
|
destRoomNumber = READ_LE_UINT16(&rec->destRoomNumber);
|
|
}
|
|
|
|
// Room exit class
|
|
|
|
RoomExitData::RoomExitData(RoomExitResource *rec) {
|
|
xs = rec->xs;
|
|
ys = rec->ys;
|
|
xe = rec->xe;
|
|
ye = rec->ye;
|
|
sequenceOffset = rec->sequenceOffset;
|
|
roomNumber = rec->newRoom;
|
|
x = rec->newRoomX;
|
|
y = rec->newRoomY;
|
|
|
|
switch (rec->direction) {
|
|
case 0x80:
|
|
direction = UP;
|
|
break;
|
|
case 0x40:
|
|
direction = DOWN;
|
|
break;
|
|
case 0x20:
|
|
direction = LEFT;
|
|
break;
|
|
case 0x10:
|
|
direction = RIGHT;
|
|
break;
|
|
default:
|
|
direction = NO_DIRECTION;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool RoomExitData::insideRect(int16 xp, int16 yp) {
|
|
return ((xp >= xs) && (xp <= xe) && (yp >= ys) && (yp <= ye));
|
|
}
|
|
|
|
RoomExitData *RoomExitList::checkExits(int16 xp, int16 yp) {
|
|
iterator i;
|
|
for (i = begin(); i != end(); i++) {
|
|
RoomExitData *rec = *i;
|
|
if (rec->insideRect(xp, yp)) return rec;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Room exit joins class
|
|
|
|
RoomExitJoinData::RoomExitJoinData(RoomExitJoinResource *rec) {
|
|
hotspot1Id = READ_LE_UINT16(&rec->hotspot1Id);
|
|
h1CurrentFrame = rec->h1CurrentFrame;
|
|
h1DestFrame = rec->h1DestFrame;
|
|
h1Unknown = READ_LE_UINT16(&rec->h1Unknown);
|
|
hotspot2Id = READ_LE_UINT16(&rec->hotspot2Id);
|
|
h2CurrentFrame = rec->h2CurrentFrame;
|
|
h2DestFrame = rec->h2DestFrame;
|
|
h2Unknown = READ_LE_UINT16(&rec->h2Unknown);
|
|
blocked = rec->blocked;
|
|
unknown = rec->unknown;
|
|
}
|
|
|
|
// Hotspot action record
|
|
|
|
HotspotActionData::HotspotActionData(HotspotActionResource *rec) {
|
|
action = (Action) rec->action;
|
|
sequenceOffset = READ_LE_UINT16(&rec->sequenceOffset);
|
|
}
|
|
|
|
uint16 HotspotActionList::getActionOffset(Action action) {
|
|
iterator i;
|
|
for (i = begin(); i != end(); ++i) {
|
|
HotspotActionData *rec = *i;
|
|
if (rec->action == action) return rec->sequenceOffset;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Hotspot data
|
|
|
|
HotspotData::HotspotData(HotspotResource *rec) {
|
|
hotspotId = READ_LE_UINT16(&rec->hotspotId);
|
|
nameId = READ_LE_UINT16(&rec->nameId);
|
|
descId = READ_LE_UINT16(&rec->descId);
|
|
descId2 = READ_LE_UINT16(&rec->descId2);
|
|
actions = READ_LE_UINT32(&rec->actions);
|
|
actionsOffset = READ_LE_UINT16(&rec->actionsOffset);
|
|
flags = (byte) (actions >> 24) & 0xf0;
|
|
actions &= 0xfffffff;
|
|
|
|
roomNumber = READ_LE_UINT16(&rec->roomNumber);
|
|
layer = rec->layer;
|
|
scriptLoadFlag = rec->scriptLoadFlag;
|
|
loadOffset = READ_LE_UINT16(&rec->loadOffset);
|
|
startX = READ_LE_INT16(&rec->startX);
|
|
startY = READ_LE_INT16(&rec->startY);
|
|
width = READ_LE_UINT16(&rec->width);
|
|
height = READ_LE_UINT16(&rec->height);
|
|
widthCopy = READ_LE_UINT16(&rec->widthCopy);
|
|
heightCopy = READ_LE_UINT16(&rec->heightCopy);
|
|
talkX = rec->talkX;
|
|
talkY = rec->talkY;
|
|
colourOffset = READ_LE_UINT16(&rec->colourOffset);
|
|
animRecordId = READ_LE_UINT16(&rec->animRecordId);
|
|
sequenceOffset = READ_LE_UINT16(&rec->sequenceOffset);
|
|
tickProcOffset = READ_LE_UINT16(&rec->tickProcOffset);
|
|
tickTimeout = READ_LE_UINT16(&rec->tickTimeout);
|
|
}
|
|
|
|
// Hotspot override data
|
|
|
|
HotspotOverrideData::HotspotOverrideData(HotspotOverrideResource *rec) {
|
|
hotspotId = READ_LE_UINT16(&rec->hotspotId);
|
|
xs = READ_LE_INT16(&rec->xs);
|
|
ys = READ_LE_INT16(&rec->ys);
|
|
xe = READ_LE_INT16(&rec->xe);
|
|
ye = READ_LE_INT16(&rec->ye);
|
|
}
|
|
|
|
// Hotspot animation movement frame
|
|
|
|
MovementData::MovementData(MovementResource *rec) {
|
|
frameNumber = READ_LE_UINT16(&rec->frameNumber);
|
|
xChange = READ_LE_INT16(&rec->xChange);
|
|
yChange = READ_LE_INT16(&rec->yChange);
|
|
}
|
|
|
|
// List of movement frames
|
|
|
|
bool MovementDataList::getFrame(uint16 currentFrame, int16 &xChange,
|
|
int16 &yChange, uint16 &nextFrame) {
|
|
if (isEmpty()) return false;
|
|
bool foundFlag = false;
|
|
iterator i;
|
|
|
|
for (i = begin(); i != end(); ++i) {
|
|
MovementData *rec = *i;
|
|
if (foundFlag || (i == begin())) {
|
|
xChange = rec->xChange;
|
|
yChange = rec->yChange;
|
|
nextFrame = rec->frameNumber;
|
|
if (foundFlag) return true;
|
|
}
|
|
if (rec->frameNumber == currentFrame) foundFlag = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Hotspot animation data
|
|
|
|
HotspotAnimData::HotspotAnimData(HotspotAnimResource *rec) {
|
|
animRecordId = READ_LE_UINT16(&rec->animRecordId);
|
|
animId = READ_LE_UINT16(&rec->animId);
|
|
flags = READ_LE_UINT16(&rec->flags);
|
|
|
|
upFrame = rec->upFrame;
|
|
downFrame = rec->downFrame;
|
|
leftFrame = rec->leftFrame;
|
|
rightFrame = rec->rightFrame;
|
|
}
|
|
|
|
// Hotspot action lists
|
|
|
|
HotspotActionList::HotspotActionList(uint16 id, byte *data) {
|
|
recordId = id;
|
|
uint16 numItems = READ_LE_UINT16(data);
|
|
data += 2;
|
|
|
|
HotspotActionResource *actionRec = (HotspotActionResource *) data;
|
|
|
|
for (int actionCtr = 0; actionCtr < numItems; ++actionCtr, ++actionRec) {
|
|
HotspotActionData *actionEntry = new HotspotActionData(actionRec);
|
|
push_back(actionEntry);
|
|
}
|
|
}
|
|
|
|
HotspotActionList *HotspotActionSet::getActions(uint16 recordId) {
|
|
HotspotActionSet::iterator i;
|
|
for (i = begin(); i != end(); ++i) {
|
|
HotspotActionList *list = *i;
|
|
if (list->recordId == recordId) return list;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// The following class holds the set of offsets for a character's talk set
|
|
|
|
TalkHeaderData::TalkHeaderData(uint16 charId, uint16 *entries) {
|
|
uint16 *src, *dest;
|
|
characterId = charId;
|
|
|
|
// Get number of entries
|
|
_numEntries = 0;
|
|
src = entries;
|
|
while (READ_LE_UINT16(src) != 0xffff) { ++src; ++_numEntries; }
|
|
|
|
// Duplicate the list
|
|
_data = (uint16 *) Memory::alloc(_numEntries * sizeof(uint16));
|
|
src = entries; dest = _data;
|
|
|
|
for (int ctr = 0; ctr < _numEntries; ++ctr, ++src, ++dest)
|
|
*dest = READ_LE_UINT16(src);
|
|
}
|
|
|
|
TalkHeaderData::~TalkHeaderData() {
|
|
free(_data);
|
|
}
|
|
|
|
uint16 TalkHeaderData::getEntry(int index) {
|
|
if (index >= _numEntries)
|
|
error("Invalid talk index %d specified for hotspot %xh",
|
|
_numEntries, characterId);
|
|
return _data[index];
|
|
}
|
|
|
|
// The following class holds a single talking entry
|
|
|
|
TalkEntryData::TalkEntryData(TalkDataResource *rec) {
|
|
preSequenceId = FROM_LE_16(rec->preSequenceId);
|
|
descId = FROM_LE_16(rec->descId);
|
|
postSequenceId = FROM_LE_16(rec->postSequenceId);
|
|
}
|
|
|
|
// The following class acts as a container for all the talk entries and
|
|
// responses for a single record Id
|
|
|
|
TalkData::TalkData(uint16 id) {
|
|
recordId = id;
|
|
}
|
|
|
|
TalkData::~TalkData() {
|
|
entries.clear();
|
|
responses.clear();
|
|
}
|
|
|
|
TalkEntryData *TalkData::getResponse(int index) {
|
|
TalkEntryList::iterator i = responses.begin();
|
|
int v = index;
|
|
while (v-- > 0) {
|
|
if (i == responses.end())
|
|
error("Invalid talk response index %d specified", index);
|
|
++i;
|
|
}
|
|
|
|
return *i;
|
|
}
|
|
|
|
// The following classes hold any sequence offsets that are being delayed
|
|
|
|
SequenceDelayData::SequenceDelayData(uint16 delay, uint16 seqOffset) {
|
|
OSystem &system = System::getReference();
|
|
|
|
_timeoutCtr = system.getMillis() + delay;
|
|
_sequenceOffset = seqOffset;
|
|
}
|
|
|
|
void SequenceDelayList::addSequence(uint16 delay, uint16 seqOffset) {
|
|
SequenceDelayData *entry = new SequenceDelayData(delay, seqOffset);
|
|
push_back(entry);
|
|
}
|
|
|
|
void SequenceDelayList::tick() {
|
|
uint32 currTime = System::getReference().getMillis();
|
|
SequenceDelayList::iterator i;
|
|
|
|
for (i = begin(); i != end(); i++) {
|
|
SequenceDelayData *entry = *i;
|
|
if (entry->_timeoutCtr >= currTime) {
|
|
uint16 seqOffset = entry->_sequenceOffset;
|
|
erase(i);
|
|
Script::execute(seqOffset);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Field list and miscellaneous variables
|
|
|
|
ValueTableData::ValueTableData() {
|
|
_numGroats = 0;
|
|
|
|
for (uint16 index = 0; index < NUM_VALUE_FIELDS; ++index)
|
|
_fieldList[index] = 0;
|
|
}
|
|
|
|
bool ValueTableData::isKnownField(uint16 fieldIndex) {
|
|
return ((fieldIndex <= 10) && (fieldIndex != 6)) ||
|
|
(fieldIndex == 15) || ((fieldIndex >= 18) && (fieldIndex <= 20));
|
|
}
|
|
|
|
uint16 ValueTableData::getField(uint16 fieldIndex) {
|
|
if (fieldIndex > NUM_VALUE_FIELDS)
|
|
error("Invalid field index specified %d", fieldIndex);
|
|
if (!isKnownField(fieldIndex))
|
|
warning("Unknown field index %d in GET_FIELD opcode", fieldIndex);
|
|
return _fieldList[fieldIndex];
|
|
}
|
|
|
|
uint16 ValueTableData::getField(FieldName fieldName) {
|
|
return getField((uint16) fieldName);
|
|
}
|
|
|
|
void ValueTableData::setField(uint16 fieldIndex, uint16 value) {
|
|
if (fieldIndex > NUM_VALUE_FIELDS)
|
|
error("Invalid field index specified %d", fieldIndex);
|
|
_fieldList[fieldIndex] = value;
|
|
if (!isKnownField(fieldIndex))
|
|
warning("Unknown field index %d in SET_FIELD opcode", fieldIndex);
|
|
}
|
|
|
|
void ValueTableData::setField(FieldName fieldName, uint16 value) {
|
|
setField((uint16) fieldName, value);
|
|
}
|
|
|
|
} // end of namespace Lure
|