mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
26ee630756
svn-id: r20582
400 lines
10 KiB
C++
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
|