aboutsummaryrefslogtreecommitdiff
path: root/lure/scripts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lure/scripts.cpp')
-rw-r--r--lure/scripts.cpp576
1 files changed, 0 insertions, 576 deletions
diff --git a/lure/scripts.cpp b/lure/scripts.cpp
deleted file mode 100644
index 073753a93f..0000000000
--- a/lure/scripts.cpp
+++ /dev/null
@@ -1,576 +0,0 @@
-/* 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/scripts.h"
-#include "lure/res.h"
-#include "lure/game.h"
-#include "common/stack.h"
-
-namespace Lure {
-
-/*------------------------------------------------------------------------*/
-/*- Script Method List -*/
-/*- -*/
-/*------------------------------------------------------------------------*/
-
-// activateHotspot
-// Activates a hotspot entry for active use
-
-void Script::activateHotspot(uint16 hotspotId, uint16 v2, uint16 v3) {
- Resources::getReference().activateHotspot(hotspotId);
-}
-
-// setHotspotScript
-// Sets a hotspot's animation script offset from a master table of offsets
-
-void Script::setHotspotScript(uint16 hotspotId, uint16 scriptIndex, uint16 v3) {
- Resources &r = Resources::getReference();
- uint16 offset = r.getHotspotScript(scriptIndex);
- HotspotData *rsc = r.getHotspot(hotspotId);
- rsc->sequenceOffset = offset;
-}
-
-// Clears the sequence delay list
-
-void Script::clearSequenceDelayList(uint16 v1, uint16 scriptIndex, uint16 v3) {
- Resources::getReference().delayList().clear();
-}
-
-// deactivates the specified hotspot from active animation
-
-void Script::deactivateHotspot(uint16 hotspotId, uint16 v2, uint16 v3) {
- Resources &rsc = Resources::getReference();
- if (hotspotId < START_NONVISUAL_HOTSPOT_ID)
- rsc.deactivateHotspot(hotspotId);
- HotspotData *hs = rsc.getHotspot(hotspotId);
- hs->flags |= 0x20;
- if (hotspotId < START_NONVISUAL_HOTSPOT_ID)
- hs->layer = 0xff;
-}
-
-// Sets the offset for the table of action sequence offsets for the given
-// hotspot
-
-void Script::setActionsOffset(uint16 hotspotId, uint16 offset, uint16 v3) {
- Resources &res = Resources::getReference();
- HotspotData *hotspot = res.getHotspot(hotspotId);
-
- if (!res.getHotspotActions(offset))
- warning("Hotspot %d set to invalid actions offset %d",
- hotspotId, offset);
-
- hotspot->actionsOffset = offset;
-}
-
-// Add a sequence to be executed after a specified delay
-
-void Script::addDelayedSequence(uint16 seqOffset, uint16 delay, uint16 v3) {
- SequenceDelayList &list = Resources::getReference().delayList();
- list.addSequence(delay, seqOffset);
-}
-
-// Checks whether the given character is in the specified room, and stores
-// the result in the general value field
-
-void Script::characterInRoom(uint16 characterId, uint16 roomNumber, uint16 v3) {
- Resources &res = Resources::getReference();
- uint16 result = 0;
- if (characterId >= PLAYER_ID) {
- HotspotData *hotspot = res.getHotspot(characterId);
- if (hotspot->roomNumber == roomNumber)
- result = 1;
- }
-
- res.fieldList().setField(GENERAL, result);
-}
-
-// Changes the given hotspot's name to a new name
-
-void Script::setHotspotName(uint16 hotspotId, uint16 nameId, uint16 v3) {
- HotspotData *hotspot = Resources::getReference().getHotspot(hotspotId);
- hotspot->nameId = nameId;
-}
-
-// Displays the given string resource Id in a dialog
-
-void Script::displayDialog(uint16 stringId, uint16 v2, uint16 v3) {
- Dialog::show(stringId);
-}
-
-// Flags for remotely viewing a room
-
-void Script::remoteRoomViewSetup(uint16 v1, uint16 v2, uint16 v3) {
- Hotspot *player = Resources::getReference().getActiveHotspot(PLAYER_ID);
- player->setTickProc(0); // disable player actions
- Game::getReference().setRemoteView();
-}
-
-// Gets the current blocked state for the given door and stores it in the
-// general value field
-
-void Script::getDoorBlocked(uint16 hotspotId, uint16 v2, uint16 v3) {
- Resources &res = Resources::getReference();
- RoomExitJoinData *joinRec = res.getExitJoin(hotspotId);
- res.fieldList().setField(GENERAL, joinRec->blocked);
-}
-
-// Decrements the number of inventory itemst he player has
-
-void Script::decrInventoryItems(uint16 v1, uint16 v2, uint16 v3) {
- // module currently doesn't use a static counter for the number of
- // inventory items, so don't do anything
-}
-
-// Sets the current frame number for the given hotspot
-
-void Script::setFrameNumber(uint16 hotspotId, uint16 frameNumber, uint16 v3) {
- Hotspot *hotspot = Resources::getReference().getActiveHotspot(hotspotId);
- hotspot->setFrameNumber(frameNumber);
-}
-
-// Disables the given hotspot from being highlighted by the cursor
-
-void Script::disableHotspot(uint16 hotspotId, uint16 v2, uint16 v3) {
- HotspotData *hotspot = Resources::getReference().getHotspot(hotspotId);
- hotspot->flags |= 0x20;
-}
-
-// Increase the player's number by the specified amount
-
-void Script::increaseNumGroats(uint16 v1, uint16 numGroats, uint16 v3) {
- ValueTableData &fields = Resources::getReference().fieldList();
- fields.numGroats() += numGroats;
-}
-
-// Enables the flags for the given hotspot for it to be actively highlighted
-
-void Script::enableHotspot(uint16 hotspotId, uint16 v2, uint16 v3) {
- HotspotData *hotspot = Resources::getReference().getHotspot(hotspotId);
- // Clear flag 0x20 and add flag 0x80
- hotspot->flags = (hotspot->flags & 0xdf) | 0x80;
-}
-
-// Marks the door in room 14 for closing
-
-void Script::room14DoorClose(uint16 v1, uint16 v2, uint16 v3) {
- RoomExitJoinData *joinRec = Resources::getReference().getExitJoin(0x2719);
- joinRec->blocked = 1;
-}
-
-// Sets the sequence result to 1 if the given secondary description for a
-// hotspot is empty (for inventory items, this gives the description before
-// the item is initially picked up)
-
-void Script::checkDroppedDesc(uint16 hotspotId, uint16 v2, uint16 v3) {
- Resources &res = Resources::getReference();
- HotspotData *hotspot = res.getHotspot(hotspotId);
- uint16 seqResult = (hotspot->descId2 == 0) ? 1 : 0;
- res.fieldList().setField(SEQUENCE_RESULT, seqResult);
-}
-
-// Marks the given door hotspot for closing
-
-void Script::doorClose(uint16 hotspotId, uint16 v2, uint16 v3) {
- RoomExitJoinData *joinRec = Resources::getReference().getExitJoin(hotspotId);
- if (!joinRec) error("Tried to close a non-door");
- joinRec->blocked = 1;
-}
-
-// Marks the given door hotspot for opening
-
-void Script::doorOpen(uint16 hotspotId, uint16 v2, uint16 v3) {
- RoomExitJoinData *joinRec = Resources::getReference().getExitJoin(hotspotId);
- if (!joinRec) error("Tried to close a non-door");
- joinRec->blocked = 0;
-}
-
-// Lookup the given message Id for the specified character and display in a dialog
-
-void Script::displayMessage(uint16 messageId, uint16 characterId, uint16 unknownVal) {
- Dialog::showMessage(messageId, characterId);
-}
-
-// Assign the given hotspot item to the player's inventory
-
-void Script::givePlayerItem(uint16 hotspotId, uint16 v2, uint16 v3) {
- HotspotData *hotspot = Resources::getReference().getHotspot(hotspotId);
- hotspot->roomNumber = PLAYER_ID;
- hotspot->flags |= 0x80;
-}
-
-// Decrease the number of graots the player has
-
-void Script::decreaseNumGroats(uint16 characterId, uint16 numGroats, uint16 v3) {
- ValueTableData &fields = Resources::getReference().fieldList();
- fields.numGroats() -= numGroats;
-}
-
-// Sets the tick handler for the village Skorl to an alternate handler
-
-void Script::setVillageSkorlTickProc(uint16 v1, uint16 v2, uint16 v3) {
- HotspotData *hotspot = Resources::getReference().getHotspot(0x3F1);
- hotspot->tickProcOffset = 0x7efa;
-}
-
-// Stores the current number of groats in the general field
-
-void Script::getNumGroats(uint16 v1, uint16 v2, uint16 v3) {
- ValueTableData fields = Resources::getReference().fieldList();
- fields.setField(GENERAL, fields.numGroats());
-}
-
-// Loads the specified animation, completely bypassing the standard process
-// of checking for a load proc/sequence
-
-void Script::animationLoad(uint16 hotspotId, uint16 v2, uint16 v3) {
- Resources::getReference().addHotspot(hotspotId);
-}
-
-// Adds the passed actions to the available actions for the given hotspot
-
-void Script::addActions(uint16 hotspotId, uint16 actions, uint16 v3) {
- HotspotData *hotspot = Resources::getReference().getHotspot(hotspotId);
- hotspot->actions |= actions;
-}
-
-// Checks the status of the cell door, and starts music depending on it's state
-
-void Script::checkCellDoor(uint16 v1, uint16 v2, uint16 v3) {
- // In the original game, this method checks to see if the cell door
- // is currently open, if it is, starts a music sequence. I'll
- // implement this method properly when I get around to implementing
- // the in-game music
-}
-
-typedef void(*SequenceMethodPtr)(uint16, uint16, uint16);
-
-struct SequenceMethodRecord {
- uint8 methodIndex;
- SequenceMethodPtr proc;
-};
-
-SequenceMethodRecord scriptMethods[] = {
- {0, Script::activateHotspot},
- {1, Script::setHotspotScript},
- {4, Script::clearSequenceDelayList},
- {6, Script::deactivateHotspot},
- {8, Script::addDelayedSequence},
- {10, Script::characterInRoom},
- {11, Script::setActionsOffset},
- {12, Script::setHotspotName},
- {16, Script::displayDialog},
- {18, Script::remoteRoomViewSetup},
- {20, Script::checkCellDoor},
- {22, Script::getDoorBlocked},
- {28, Script::decrInventoryItems},
- {30, Script::setFrameNumber},
- {32, Script::disableHotspot},
- {34, Script::increaseNumGroats},
- {35, Script::enableHotspot},
- {39, Script::room14DoorClose},
- {40, Script::checkDroppedDesc},
- {42, Script::doorClose},
- {44, Script::doorOpen},
- {47, Script::displayMessage},
- {50, Script::givePlayerItem},
- {51, Script::decreaseNumGroats},
- {54, Script::setVillageSkorlTickProc},
- {57, Script::getNumGroats},
- {62, Script::animationLoad},
- {63, Script::addActions},
- {65, Script::checkCellDoor},
- {0xff, NULL}};
-
-/*------------------------------------------------------------------------*/
-/*- Script Execution -*/
-/*- -*/
-/*------------------------------------------------------------------------*/
-
-uint16 Script::execute(uint16 startOffset) {
- Resources &r = Resources::getReference();
- ValueTableData &fields = r.fieldList();
- MemoryBlock *scriptData = r.scriptData();
- byte *scripts = scriptData->data();
- Common::Stack<uint16> stack;
- Common::Stack<uint16> methodStack;
- byte opcode;
- uint16 param, v1, v2;
- uint16 param1, param2, param3;
- uint16 fieldNum;
- uint32 tempVal;
- SequenceMethodPtr ptr;
- SequenceMethodRecord *rec;
-
- uint16 offset = startOffset;
- bool breakFlag = false;
- param = 0;
- fields.setField(SEQUENCE_RESULT, 0);
-
- while (!breakFlag) {
- if (offset >= scriptData->size())
- error("Script failure in script %d - invalid offset %d", startOffset, offset);
-
- opcode = scripts[offset++];
- if ((opcode & 1) != 0) {
- // Flag to read next two bytes as active parameter
- if (offset >= scriptData->size()-2)
- error("Script failure in script %d - invalid offset %d", startOffset, offset);
-
- param = READ_LE_UINT16(scripts + offset);
- offset += 2;
- }
- opcode >>= 1; // Discard param bit from opcode byte
-
- switch (opcode) {
- case S_OPCODE_ABORT:
- case S_OPCODE_ABORT2:
- case S_OPCODE_ABORT3:
- methodStack.clear();
- break;
-
- case S_OPCODE_ADD:
- stack.push(stack.pop() + stack.pop());
- break;
-
- case S_OPCODE_SUBTRACT:
- v1 = stack.pop();
- v2 = stack.pop();
- stack.push(v2 - v1);
- break;
-
- case S_OPCODE_MULTIPLY:
- tempVal = stack.pop() * stack.pop();
- stack.push(tempVal & 0xffff);
- param = (uint16) (tempVal >> 16);
- break;
-
- case S_OPCODE_DIVIDE:
- v1 = stack.pop();
- v2 = stack.pop();
- stack.push(v2 / v1);
- param = v2 % v1; // remainder
- break;
-
- case S_OPCODE_NOT_EQUALS:
- stack.push((stack.pop() != stack.pop()) ? 0 : 1);
- break;
-
- case S_OPCODE_EQUALS:
- stack.push((stack.pop() == stack.pop()) ? 0 : 1);
- break;
-
- case S_OPCODE_GT:
- stack.push((stack.pop() > stack.pop()) ? 1 : 0);
- break;
-
- case S_OPCODE_LT:
- stack.push((stack.pop() < stack.pop()) ? 1 : 0);
- break;
-
- case S_OPCODE_LT2:
- stack.push((stack.pop() < stack.pop()) ? 1 : 0);
- break;
-
- case S_OPCODE_GT2:
- stack.push((stack.pop() > stack.pop()) ? 1 : 0);
- break;
-
- case S_OPCODE_AND:
- stack.push(stack.pop() & stack.pop());
- break;
-
- case S_OPCODE_OR:
- stack.push(stack.pop() | stack.pop());
- break;
-
- case S_OPCODE_LOGICAL_AND:
- stack.push(((stack.pop() != 0) && (stack.pop() != 0)) ? 1 : 0);
- break;
-
- case S_OPCODE_LOGICAL_OR:
- stack.push(((stack.pop() != 0) || (stack.pop() != 0)) ? 1 : 0);
- break;
-
- case S_OPCODE_GET_FIELD:
- // Opcode not yet fully implemented
- fieldNum = param >> 1;
- v1 = fields.getField(fieldNum);
- stack.push(v1);
- break;
-
- case S_OPCODE_SET_FIELD:
- // Opcode not yet fully implemented
- fieldNum = param >> 1;
- v1 = stack.pop();
- fields.setField(fieldNum, v1);
- break;
-
- case S_OPCODE_PUSH:
- stack.push(param);
- break;
-
- case S_OPCODE_SUBROUTINE:
- methodStack.push(offset);
- offset = param;
- break;
-
- case S_OPCODE_EXEC:
- param1 = 0; param2 = 0; param3 = 0;
- if (!stack.empty()) param1 = stack.pop();
- if (!stack.empty()) param2 = stack.pop();
- if (!stack.empty()) param3 = stack.pop();
-
- rec = &scriptMethods[0];
- while ((rec->methodIndex != 0xff) && (rec->methodIndex != param))
- ++rec;
-
- if (rec->methodIndex == 0xff)
- warning("Undefined script method %d", param);
- else {
- ptr = rec->proc;
- ptr(param1, param2, param3);
- }
- break;
-
- case S_OPCODE_COND_JUMP:
- v1 = stack.pop();
- if (v1 == 0) offset += (int16) param;
- break;
-
- case S_OPCODE_JUMP:
- offset += (int16) param;
- break;
-
- case S_OPCODE_RANDOM:
- param = r.random() >> 8; // make number between 0 to 255
- break;
-
- case S_OPCODE_END:
- // Signal to end the execution
- if (!methodStack.empty())
- offset = methodStack.pop();
- else
- breakFlag = true;
- break;
-
- default:
- error("Unknown script opcode %d", opcode);
- break;
- }
- }
-
- return fields.getField(SEQUENCE_RESULT);
-}
-
-/*------------------------------------------------------------------------*/
-/*- Hotspot Script Handler -*/
-/*- -*/
-/*------------------------------------------------------------------------*/
-
-int16 HotspotScript::nextVal(MemoryBlock *data, uint16 &offset) {
- if (offset >= data->size() - 1)
- error("Script failure - invalid offset");
- int16 value = READ_LE_UINT16(data->data() + offset);
- offset += 2;
- return value;
-}
-
-bool HotspotScript::execute(Hotspot *h)
-{
- Resources &r = Resources::getReference();
- MemoryBlock *scriptData = r.hotspotScriptData();
- uint16 offset = h->script();
- int16 opcode = 0;
- int16 param1, param2;
- bool breakFlag = false;
-
- while (!breakFlag) {
- opcode = nextVal(scriptData, offset);
- switch (opcode) {
- case S2_OPCODE_TIMEOUT:
- param1 = nextVal(scriptData, offset);
- h->setTickCtr(param1);
- h->setScript(offset);
- breakFlag = true;
- break;
-
- case S2_OPCODE_POSITION:
- param1 = nextVal(scriptData, offset);
- param2 = nextVal(scriptData, offset);
- h->setPosition(param1 - 0x80, param2 - 0x80);
- break;
-
- case S2_OPCODE_CHANGE_POS:
- param1 = nextVal(scriptData, offset);
- param2 = nextVal(scriptData, offset);
- h->setPosition(h->x() + param1, h->y() + param2);
- break;
-
- case S2_OPCODE_UNLOAD:
- breakFlag = true;
- break;
-
- case S2_OPCODE_DIMENSIONS:
- param1 = nextVal(scriptData, offset) << 4;
- param2 = nextVal(scriptData, offset);
- h->setSize((uint16) param1, (uint16) param2);
- break;
-
- case S2_OPCODE_JUMP:
- offset = (uint16) nextVal(scriptData, offset);
- break;
-
- case S2_OPCODE_ANIMATION:
- param1 = nextVal(scriptData, offset);
- h->setAnimation(param1);
- break;
-
- case S2_OPCODE_UNKNOWN_247:
- param1 = nextVal(scriptData, offset);
- param2 = nextVal(scriptData, offset);
-// warning("UNKNOWN_247 stub called");
- break;
-
- case S2_OPCODE_UNKNOWN_258:
- param1 = nextVal(scriptData, offset);
-// warning("UNKNOWN_258 stub called");
- break;
-
- case S2_OPCODE_ACTIONS:
- param1 = nextVal(scriptData, offset) << 4;
- param2 = nextVal(scriptData, offset);
- h->setActions((uint32) param1 | ((uint32) param2 << 16));
- break;
-
- default:
- // Set the animation frame number
- h->setFrameNumber(opcode);
- h->setScript(offset);
- breakFlag = true;
- break;
- }
- }
-
- return (opcode == S2_OPCODE_UNLOAD);
-}
-
-} // end of namespace Lure