scummvm/engines/lure/res.cpp
2006-02-11 22:45:04 +00:00

400 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/screen.h"
namespace Lure {
static Resources *int_resources = NULL;
Resources &Resources::getReference() {
return *int_resources;
}
Resources::Resources() {
int_resources = this;
reloadData();
}
Resources::~Resources() {
// Delete any unremoved active hotspots
freeData();
}
void Resources::freeData() {
_activeHotspots.clear();
_roomData.clear();
_hotspotData.clear();
_hotspotOverrides.clear();
_animData.clear();
_exitJoins.clear();
_delayList.clear();
delete _paletteSubset;
delete _scriptData;
delete _script2Data;
delete _hotspotScriptData;
delete _messagesData;
}
struct AnimRecordTemp {
uint16 *offset;
MovementDataList *list;
};
void Resources::reloadData() {
Disk &d = Disk::getReference();
MemoryBlock *mb;
uint16 *offset, offsetVal;
int ctr;
// Get the palette subset data
_paletteSubset = new Palette(ALT_PALETTE_RESOURCE_ID);
// Load room data
mb = d.getEntry(ROOM_DATA_RESOURCE_ID);
offset = (uint16 *) mb->data();
for (ctr = 0; READ_LE_UINT16(offset) != 0xffff; ++ctr, ++offset) {
offsetVal = READ_LE_UINT16(offset);
if (offsetVal != 0) {
// Get room resource
RoomResource *rec = (RoomResource *) (mb->data() + offsetVal);
RoomData *newEntry = new RoomData(rec);
_roomData.push_back(newEntry);
if (rec->numExits > 0) {
RoomExitResource *exitRes = (RoomExitResource *)
(mb->data() + offsetVal + sizeof(RoomResource));
for (uint16 exitCtr = 0; exitCtr < rec->numExits; ++exitCtr, ++exitRes) {
RoomExitData *exit = new RoomExitData(exitRes);
newEntry->exits.push_back(exit);
}
}
}
}
delete mb;
// Load room exits
mb = d.getEntry(ROOM_EXITS_RESOURCE_ID);
ctr = 0;
for (;;) {
offsetVal = READ_LE_UINT16(mb->data() + (ctr * 2));
if (offsetVal == 0xffff) break;
if (offsetVal != 0) {
RoomData *room = getRoom(ctr);
if (room) {
RoomExitHotspotRecord *re = (RoomExitHotspotRecord *)
(mb->data() + offsetVal);
while (READ_LE_UINT16(&re->hotspotId) != 0xffff) {
RoomExitHotspotData *newEntry = new RoomExitHotspotData(re);
room->exitHotspots.push_back(newEntry);
++re;
}
}
}
++ctr;
}
delete mb;
// Load room joins
mb = d.getEntry(ROOM_EXIT_JOINS_RESOURCE_ID);
RoomExitJoinRecord *joinRec = (RoomExitJoinRecord *) mb->data();
while (READ_LE_UINT16(&joinRec->hotspot1Id) != 0xffff) {
RoomExitJoinData *newEntry = new RoomExitJoinData(joinRec);
_exitJoins.push_back(newEntry);
++joinRec;
}
delete mb;
// Load the hotspot list
mb = d.getEntry(HOTSPOT_DATA_RESOURCE_ID);
HotspotResource *hsRec = (HotspotResource *) mb->data();
while (READ_LE_UINT16(&hsRec->hotspotId) != 0xffff) {
HotspotData *newEntry = new HotspotData(hsRec);
_hotspotData.push_back(newEntry);
++hsRec;
}
delete mb;
// Load the hotspot overrides
mb = d.getEntry(HOTSPOT_OVERRIDE_DATA_RESOURCE_ID);
HotspotOverrideResource *hsoRec = (HotspotOverrideResource *) mb->data();
while (READ_LE_UINT16(&hsoRec->hotspotId) != 0xffff) {
HotspotOverrideData *newEntry = new HotspotOverrideData(hsoRec);
_hotspotOverrides.push_back(newEntry);
++hsoRec;
}
delete mb;
// Load the animation list
mb = d.getEntry(ANIM_DATA_RESOURCE_ID);
HotspotAnimResource *animRec = (HotspotAnimResource *) mb->data();
while (READ_LE_UINT16(&animRec->animRecordId) != 0xffff) {
HotspotAnimData *newEntry = new HotspotAnimData(animRec);
_animData.push_back(newEntry);
// Handle any direction frames
AnimRecordTemp dirEntries[4] = {
{&animRec->leftOffset, &newEntry->leftFrames},
{&animRec->rightOffset, &newEntry->rightFrames},
{&animRec->upOffset, &newEntry->upFrames},
{&animRec->downOffset, &newEntry->downFrames}};
for (int dirCtr = 0; dirCtr < 4; ++dirCtr) {
offsetVal = READ_LE_UINT16(dirEntries[dirCtr].offset);
if (offsetVal != 0) {
MovementResource *moveRec = (MovementResource *)
(mb->data() + offsetVal);
while (READ_LE_UINT16(&moveRec->frameNumber) != 0xffff) {
MovementData *newMove = new MovementData(moveRec);
dirEntries[dirCtr].list->push_back(newMove);
++moveRec;
}
}
}
++animRec;
}
delete mb;
// Hotspot scripts
mb = d.getEntry(HOTSPOT_SCRIPT_LIST_RESOURCE_ID);
uint16 numEntries = mb->size() / 2;
uint16 *srcVal = (uint16 *) mb->data();
uint16 *destVal = _hotspotScriptData = (uint16 *)
Memory::alloc(numEntries * sizeof(uint16));
for (ctr = 0; ctr < numEntries; ++ctr, ++srcVal, ++destVal) {
*destVal = READ_LE_UINT16(srcVal);
}
delete mb;
// Handle the hotspot action lists
mb = d.getEntry(ACTION_LIST_RESOURCE_ID);
uint16 *v = (uint16 *) mb->data();
uint16 recordId;
while ((recordId = READ_LE_UINT16(v)) != 0xffff) {
++v;
offsetVal = READ_LE_UINT16(v);
++v;
HotspotActionList *list = new HotspotActionList(
recordId, mb->data() + offsetVal);
_actionsList.push_back(list);
}
delete mb;
_delayList.clear();
// Load miscellaneous data
_scriptData = d.getEntry(SCRIPT_DATA_RESOURCE_ID);
_script2Data = d.getEntry(SCRIPT2_DATA_RESOURCE_ID);
_messagesData = d.getEntry(MESSAGES_LIST_RESOURCE_ID);
}
RoomExitJoinData *Resources::getExitJoin(uint16 hotspotId) {
RoomExitJoinList::iterator i;
for (i = _exitJoins.begin(); i != _exitJoins.end(); ++i) {
RoomExitJoinData *rec = *i;
if ((rec->hotspot1Id == hotspotId) || (rec->hotspot2Id == hotspotId))
return rec;
}
return NULL;
}
uint16 Resources::getHotspotScript(uint16 index) {
return _hotspotScriptData[index];
}
RoomData *Resources::getRoom(uint16 roomNumber) {
RoomDataList::iterator i;
for (i = _roomData.begin(); i != _roomData.end(); ++i) {
RoomData *rec = *i;
if (rec->roomNumber == roomNumber) return rec;
++rec;
}
return NULL;
}
void Resources::insertPaletteSubset(Palette &p) {
p.palette()->copyFrom(_paletteSubset->palette(), 0, 129*4, 60*4);
p.palette()->copyFrom(_paletteSubset->palette(), 60*4, 220*4, 8*4);
}
HotspotData *Resources::getHotspot(uint16 hotspotId) {
HotspotDataList::iterator i;
for (i = _hotspotData.begin(); i != _hotspotData.end(); ++i) {
HotspotData *rec = *i;
if (rec->hotspotId == hotspotId) return rec;
}
return NULL;
}
Hotspot *Resources::getActiveHotspot(uint16 hotspotId) {
HotspotList::iterator i;
for (i = _activeHotspots.begin(); i != _activeHotspots.end(); ++i) {
Hotspot *rec = *i;
if (rec->hotspotId() == hotspotId) return rec;
}
return NULL;
}
HotspotOverrideData *Resources::getHotspotOverride(uint16 hotspotId) {
HotspotOverrideList::iterator i;
for (i = _hotspotOverrides.begin(); i != _hotspotOverrides.end(); ++i) {
HotspotOverrideData *rec = *i;
if (rec->hotspotId == hotspotId) return rec;
}
return NULL;
}
HotspotAnimData *Resources::getAnimation(uint16 animRecordId) {
HotspotAnimList::iterator i;
for (i = _animData.begin(); i != _animData.end(); ++i) {
HotspotAnimData *rec = *i;
if (rec->animRecordId == animRecordId) return rec;
}
return NULL;
}
uint16 Resources::getHotspotAction(uint16 actionsOffset, Action action) {
HotspotActionList *list = _actionsList.getActions(actionsOffset);
if (!list) return 0;
return list->getActionOffset(action);
}
HotspotActionList *Resources::getHotspotActions(uint16 actionsOffset) {
return _actionsList.getActions(actionsOffset);
}
void Resources::activateHotspot(uint16 hotspotId) {
HotspotData *res = getHotspot(hotspotId);
if (!res) return;
res->roomNumber &= 0x7fff; // clear any suppression bit in room #
// Make sure that the hotspot isn't already active
HotspotList::iterator i = _activeHotspots.begin();
bool found = false;
for (; i != _activeHotspots.end(); ++i) {
Hotspot &h = *i.operator*();
if (h.hotspotId() == res->hotspotId) {
found = true;
break;
}
}
if (found) return;
// Check the script load flag
if (res->scriptLoadFlag) {
// Execute a script rather than doing a standard load
Script::execute(res->loadOffset);
} else {
// Standard load
bool loadFlag = true;
switch (res->loadOffset) {
case 0x3afe:
// Copy protection check - since the game is freeware now,
// don't bother with it
loadFlag = false;
break;
case 0x41BD:
// Empty handler used to prevent loading hotspots that
// are yet to be active (such as the straw fire)
loadFlag = false;
break;
case 0x7172:
case 0x7167:
// Standard animation load
break;
case 0x88ac:
// Torch in room #1
loadFlag = _fieldList.getField(TORCH_HIDE) == 0;
break;
default:
// All others simply activate the hotspot
warning("Hotspot %d uses unknown load offset proc %d",
res->hotspotId, res->loadOffset);
}
if (loadFlag) {
Hotspot *hotspot = addHotspot(hotspotId);
// if (res->loadOffset == 0x7167) hotspot->setPersistant(true);
// DEBUG - for now only keep certain hotspots active
hotspot->setPersistant((res->hotspotId >= 0x3e8) && (res->hotspotId <= 0x3ea));
}
}
}
Hotspot *Resources::addHotspot(uint16 hotspotId) {
Hotspot *hotspot = new Hotspot(getHotspot(hotspotId));
_activeHotspots.push_back(hotspot);
return hotspot;
}
void Resources::deactivateHotspot(uint16 hotspotId) {
HotspotList::iterator i = _activeHotspots.begin();
while (i != _activeHotspots.end()) {
Hotspot *h = *i;
if (h->hotspotId() == hotspotId)
i = _activeHotspots.erase(i);
else
i++;
}
}
uint16 Resources::numInventoryItems() {
uint16 numItems = 0;
HotspotDataList &list = _hotspotData;
HotspotDataList::iterator i;
for (i = list.begin(); i != list.end(); ++i) {
HotspotData *rec = *i;
if (rec->roomNumber == PLAYER_ID) ++numItems;
}
return numItems;
}
} // end of namespace Lure