From 84dfa6d3b83e080f099ad606dc7fbeb40ebe4b97 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 16 Jun 2019 21:39:47 -0700 Subject: GLK: ALAN2: Remove previously added code fragments --- engines/glk/alan2/acode.h | 289 ------------ engines/glk/alan2/alan2.cpp | 39 +- engines/glk/alan2/alan2.h | 66 +-- engines/glk/alan2/decode.cpp | 120 ----- engines/glk/alan2/decode.h | 80 ---- engines/glk/alan2/execute.cpp | 944 ------------------------------------- engines/glk/alan2/execute.h | 171 ------- engines/glk/alan2/interpreter.cpp | 778 ------------------------------ engines/glk/alan2/interpreter.h | 59 --- engines/glk/alan2/parse.cpp | 969 -------------------------------------- engines/glk/alan2/parse.h | 185 -------- engines/glk/alan2/rules.cpp | 88 ---- engines/glk/alan2/rules.h | 51 -- engines/glk/alan2/saveload.cpp | 218 --------- engines/glk/alan2/saveload.h | 55 --- engines/glk/module.mk | 6 - 16 files changed, 3 insertions(+), 4115 deletions(-) delete mode 100644 engines/glk/alan2/acode.h delete mode 100644 engines/glk/alan2/decode.cpp delete mode 100644 engines/glk/alan2/decode.h delete mode 100644 engines/glk/alan2/execute.cpp delete mode 100644 engines/glk/alan2/execute.h delete mode 100644 engines/glk/alan2/interpreter.cpp delete mode 100644 engines/glk/alan2/interpreter.h delete mode 100644 engines/glk/alan2/parse.cpp delete mode 100644 engines/glk/alan2/parse.h delete mode 100644 engines/glk/alan2/rules.cpp delete mode 100644 engines/glk/alan2/rules.h delete mode 100644 engines/glk/alan2/saveload.cpp delete mode 100644 engines/glk/alan2/saveload.h diff --git a/engines/glk/alan2/acode.h b/engines/glk/alan2/acode.h deleted file mode 100644 index 5b5a5be990..0000000000 --- a/engines/glk/alan2/acode.h +++ /dev/null @@ -1,289 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_ACODE -#define GLK_ALAN2_ACODE - -#include "common/scummsys.h" - -namespace Glk { -namespace Alan2 { - -typedef size_t Aptr; // Type for an ACODE memory address -typedef uint32 Aword; // Type for an ACODE word -typedef uint32 Aaddr; // Type for an ACODE address -typedef uint32 Abool; // Type for an ACODE Boolean value -typedef int32 Aint; // Type for an ACODE Integer value -typedef int CodeValue; // Definition for the packing process - -// Constants for the Acode file, words/block & bytes/block -#define BLOCKLEN 256L -#define BLOCKSIZE (BLOCKLEN*sizeof(Aword)) - - -// Definitions for the packing process -#define VALUEBITS 16 - -#define EOFChar 256 -#define TOPVALUE (((CodeValue)1<>28) -#define I_OP(x) ((x&0x8000000)?(x)|0x0f0000000:(x)&0x0fffffff) - - -struct AcdHdr { -// Important info - char vers[4]; // 01 - Version of compiler - Aword size; // 02 - Size of ACD-file in Awords -// Options - Abool pack; // 03 - Is the text packed ? - Aword paglen; // 04 - Length of a page - Aword pagwidth; // 05 - and width - Aword debug; // 06 - Option debug -// Data structures - Aaddr dict; // 07 - Dictionary - Aaddr oatrs; // 08 - Object default attributes - Aaddr latrs; // 09 - Location default attributes - Aaddr aatrs; // 0a - Actor default attributes - Aaddr acts; // 0b - Actor table - Aaddr objs; // 0c - Object table - Aaddr locs; // 0d - Location table - Aaddr stxs; // 0e - Syntax table - Aaddr vrbs; // 0f - Verb table - Aaddr evts; // 10 - Event table - Aaddr cnts; // 11 - Container table - Aaddr ruls; // 12 - Rule table - Aaddr init; // 13 - String init table - Aaddr start; // 14 - Start code - Aword msgs; // 15 - Messages table -// Miscellaneous - Aword objmin, objmax; // 16 - Interval for object codes - Aword actmin, actmax; // 18 - Interval for actor codes - Aword cntmin, cntmax; // 1a - Interval for container codes - Aword locmin, locmax; // 1c - Interval for location codes - Aword dirmin, dirmax; // 1e - Interval for direction codes - Aword evtmin, evtmax; // 20 - Interval for event codes - Aword rulmin, rulmax; // 22 - Interval for rule codes - Aword maxscore; // 24 - Maximum score - Aaddr scores; // 25 - Score table - Aaddr freq; // 26 - Address to Char freq's for coding - Aword acdcrc; // 27 - Checksum for acd code (excl. hdr) - Aword txtcrc; // 28 - Checksum for text data file -}; - -// Error message numbers -enum MsgKind { - M_HUH, // Obsolete - M_WHAT, - M_WHAT_ALL, - M_WHAT_IT, - M_WHAT_THEM, - M_MULTIPLE, - M_WANT, - M_NOUN, - M_AFTER_BUT, - M_BUT_ALL, - M_NOT_MUCH, - M_WHICH_ONE, - M_NO_SUCH, - M_NO_WAY, - M_CANT0, - M_CANT, - M_NOTHING, // Obsolete - M_SEEOBJ1, - M_SEEOBJ2, - M_SEEOBJ3, - M_SEEOBJ4, - M_SEEACT, - M_CONTAINS1, - M_CONTAINS2, - M_CONTAINS3, - M_CONTAINS4, - M_CONTAINS5, - M_EMPTY1, - M_EMPTY2, - M_SCORE1, - M_SCORE2, - M_UNKNOWN_WORD, - M_MORE, - M_AGAIN, - M_SAVEWHERE, - M_SAVEOVERWRITE, - M_SAVEFAILED, - M_SAVEMISSING, - M_SAVEVERS, - M_SAVENAME, - M_RESTOREFROM, - M_REALLY, // CHANGED: v2.7 from M_RESTART - M_QUITACTION, // INTRODUCED: v2.7, so M_ARTICLE moved - M_ARTICLE, // INTRODUCED: v2.6 but replaced the M_NOMSG - MSGMAX -}; - -#define M_ARTICLE26 M_QUITACTION -#define M_MSGMAX26 M_ARTICLE - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/alan2/alan2.cpp b/engines/glk/alan2/alan2.cpp index 492d425d98..1889c696cd 100644 --- a/engines/glk/alan2/alan2.cpp +++ b/engines/glk/alan2/alan2.cpp @@ -21,10 +21,6 @@ */ #include "glk/alan2/alan2.h" -#include "glk/alan2/decode.h" -#include "glk/alan2/execute.h" -#include "glk/alan2/interpreter.h" -#include "glk/alan2/saveload.h" #include "common/config-manager.h" #include "common/translation.h" #include "common/error.h" @@ -36,25 +32,16 @@ namespace Glk { namespace Alan2 { -Alan2 *_vm = nullptr; +Alan2 *g_vm = nullptr; Alan2::Alan2(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc), vm_exited_cleanly(false) { - _vm = this; - looking = false; - dscrstkp = 0; + g_vm = this; } void Alan2::runGame() { Common::String gameFileName = _gameFile.getName(); - // TODO: Initialize these properly - int tmp = 0; - _decode = new Decode(nullptr, nullptr); - _execute = new Execute(); - _saveLoad = new SaveLoad(gameFileName, nullptr, nullptr, nullptr, nullptr, &tmp); - _interpreter = new Interpreter(_execute, _saveLoad, _stack); - if (!is_gamefile_valid()) return; @@ -85,27 +72,5 @@ bool Alan2::is_gamefile_valid() { return true; } -void Alan2::output(const Common::String str) { - // TODO -} - -void Alan2::printMessage(MsgKind msg) { - // TODO -} - -void Alan2::printError(MsgKind msg) { - // TODO -} - -void Alan2::paragraph() { - if (col != 1) - newLine(); - newLine(); -} - -void Alan2::newLine() { - // TODO -} - } // End of namespace Alan2 } // End of namespace Glk diff --git a/engines/glk/alan2/alan2.h b/engines/glk/alan2/alan2.h index a8e500a0dd..3b5c778d95 100644 --- a/engines/glk/alan2/alan2.h +++ b/engines/glk/alan2/alan2.h @@ -26,20 +26,10 @@ #include "common/scummsys.h" #include "common/stack.h" #include "glk/glk_api.h" -#include "glk/alan2/acode.h" -#include "glk/alan2/types.h" namespace Glk { namespace Alan2 { -typedef Common::FixedStack Alan2Stack; -class Decode; -class Execute; -class Interpreter; -class SaveLoad; - -#define N_EVTS 100 - /** * Alan2 game interpreter */ @@ -78,63 +68,9 @@ public: */ virtual Common::Error writeGameData(Common::WriteStream *ws) override; - /** - * Output a string to the screen - */ - void output(const Common::String str); - - /** - * Print a message from the message table - */ - void printMessage(MsgKind msg); - - /** - * Print an error from the message table, force new player input and abort - */ - void printError(MsgKind msg); - - /** - * Make a new paragraph, i.e one empty line (one or two newlines) - */ - void paragraph(); - - /** - * Print the the status line on the top of the screen - */ - void statusLine(); - - /** - * Make a newline, but check for screen full - */ - void newLine(); - - // Engine variables - Alan2Stack *_stack; - int pc; - ParamElem *params; - Aword *memory; // The Amachine memory - int memTop; // Top of memory - CurVars cur; // Amachine variables - int col; - bool fail; - int scores[100]; // FIXME: type + size - AcdHdr *header; - bool _needSpace; // originally "needsp" - - EvtElem *evts; // Event table pointer - bool looking; // LOOKING? flag - int dscrstkp; // Describe-stack pointer - Common::File *_txtFile; - bool _anyOutput; - winid_t _bottomWindow; - - Decode *_decode; - Execute *_execute; - Interpreter *_interpreter; - SaveLoad *_saveLoad; }; -extern Alan2 *_vm; +extern Alan2 *g_vm; } // End of namespace Alan2 } // End of namespace Glk diff --git a/engines/glk/alan2/decode.cpp b/engines/glk/alan2/decode.cpp deleted file mode 100644 index 58e814f97f..0000000000 --- a/engines/glk/alan2/decode.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "glk/alan2/decode.h" - -namespace Glk { -namespace Alan2 { - -int Decode::inputBit() { - int bit; - - if (!_bitsToGo) { // More bits available ? - _decodeBuffer = _txtFile->readByte(); // No, so get more - if (_txtFile->eos()) { - _garbageBits++; - - if (_garbageBits > VALUEBITS - 2) - error("Error in encoded data file."); - } else - _bitsToGo = 8; // Another Char, 8 new bits - } - - bit = _decodeBuffer & 1; // Get next bit - _decodeBuffer = _decodeBuffer >> 1; // and remove it - _bitsToGo--; - - return bit; -} - -void Decode::startDecoding() { - _bitsToGo = 0; - _garbageBits = 0; - - _value = 0; - for (int i = 0; i < VALUEBITS; i++) - _value = 2 * _value + inputBit(); - - _low = 0; - _high = TOPVALUE; -} - -int Decode::decodeChar() { - const long range = (long)(_high - _low) + 1; - const uint f = (((long)(_value - _low) + 1) * _freq[0] - 1) / range; - int symbol; - - // Find the symbol - for (symbol = 1; _freq[symbol] > f; symbol++); - - _high = _low + range * _freq[symbol - 1] / _freq[0] - 1; - _low = _low + range * _freq[symbol] / _freq[0]; - - for (;;) { - if (_high < HALF) { - // Do nothing - } else if (_low >= HALF) { - _value = _value - HALF; - _low = _low - HALF; - _high = _high - HALF; - } else if (_low >= ONEQUARTER && _high < THREEQUARTER) { - _value = _value - ONEQUARTER; - _low = _low - ONEQUARTER; - _high = _high - ONEQUARTER; - } else - break; - - // Scale up the range - _low = 2 * _low; - _high = 2 * _high + 1; - _value = 2 * _value + inputBit(); - } - - return symbol - 1; -} - -DecodeInfo *Decode::pushDecode() { - DecodeInfo *info = new DecodeInfo(); - - info->fpos = _txtFile->pos(); - info->buffer = _decodeBuffer; - info->bits = _bitsToGo; - info->value = _value; - info->high = _high; - info->low = _low; - - return info; -} - -void Decode::popDecode (DecodeInfo *info) { - _txtFile->seek(info->fpos, SEEK_CUR); - _decodeBuffer = info->buffer; - _bitsToGo = info->bits; - _value = info->value; - _high = info->high; - _low = info->low; - - delete info; -} - -} // End of namespace Alan2 -} // End of namespace Glk diff --git a/engines/glk/alan2/decode.h b/engines/glk/alan2/decode.h deleted file mode 100644 index 75a35dc945..0000000000 --- a/engines/glk/alan2/decode.h +++ /dev/null @@ -1,80 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_DECODE -#define GLK_ALAN2_DECODE - -#include "glk/alan2/alan2.h" -#include "glk/alan2/acode.h" -#include "common/file.h" - -namespace Glk { -namespace Alan2 { - -// Structure for saved decode info -struct DecodeInfo { - long fpos; - int buffer; - int bits; - CodeValue value; - CodeValue high; - CodeValue low; -}; - -class Decode { -public: - Decode(Common::File *txtFile, Aword *freq): _txtFile(txtFile), _freq(freq) {} - void startDecoding(); - int decodeChar(); - - /** - * Save so much about the decoding process, so it is possible to restore - * and continue later. - */ - DecodeInfo *pushDecode(); - - /** - * Restore enough info about the decoding process, so it is possible to - * continue after having decoded something else. - */ - void popDecode(DecodeInfo *info); - - int inputBit(); - -private: - // Bit output - int _decodeBuffer; // Bits to be input - int _bitsToGo; // Bits still in buffer - int _garbageBits; // Bits past EOF - - Aword *_freq; - Common::File *_txtFile; - - // Current state of decoding - CodeValue _value; // Currently seen code value - CodeValue _low, _high; // Current code region -}; - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/alan2/execute.cpp b/engines/glk/alan2/execute.cpp deleted file mode 100644 index 4fc0acb33b..0000000000 --- a/engines/glk/alan2/execute.cpp +++ /dev/null @@ -1,944 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "common/stack.h" -#include "glk/alan2/alan2.h" -#include "glk/alan2/decode.h" -#include "glk/alan2/execute.h" -#include "glk/alan2/interpreter.h" -#include "glk/alan2/saveload.h" -#include "glk/alan2/types.h" -#include "glk/alan2/util.h" -#include "common/debug.h" -#include "common/file.h" - -namespace Glk { -namespace Alan2 { - -#define WIDTH 80 - -// Is there an exit from one location to another ? -bool Execute::exitto(int to, int from) { - if (_locs[from - LOCMIN].exts == 0) - return false; // No exits - - for (ExtElem *ext = (ExtElem *)addrTo(_locs[from - LOCMIN].exts); !endOfTable(ext); ext++) - if ((int)ext->next == to) - return true; - - return false; -} - -int Execute::count(int cnt) { - int j = 0; - - for (uint i = OBJMIN; i <= OBJMAX; i++) - if (in(i, cnt)) - j++; // Then it's in this container also - - return j; -} - -int Execute::sumAttributes(Aword atr, Aword cnt) { - int sum = 0; - - for (uint i = OBJMIN; i <= OBJMAX; i++) { - if (_objs[i - OBJMIN].loc == cnt) { // Then it's in this container - if (_objs[i - OBJMIN].cont != 0) // This is also a container! - sum = sum + sumAttributes(atr, i); - sum = sum + attribute(i, atr); - } - } - - return sum; -} - -bool Execute::checkContainerLimit(Aword cnt, Aword obj) { - LimElem *lim; - Aword props; - - _vm->fail = true; - if (!isCnt(cnt)) - error("Checking limits for a non-container."); - - // Find the container properties - if (isObj(cnt)) - props = _objs[cnt - OBJMIN].cont; - else if (isAct(cnt)) - props = _acts[cnt - ACTMIN].cont; - else - props = cnt; - - - if (_cnts[props - CNTMIN].lims != 0) { /* Any limits at all? */ - for (lim = (LimElem *)addrTo(_cnts[props - CNTMIN].lims); !endOfTable(lim); lim++) { - if (lim->atr == 0) { - if (count(cnt) >= (int)lim->val) { - _vm->_interpreter->interpret(lim->stms); - return true; // Limit check failed - } - } else { - if (sumAttributes(lim->atr, cnt) + attribute(obj, lim->atr) > lim->val) { - _vm->_interpreter->interpret(lim->stms); - return true; - } - } - } - } - - _vm->fail = false; - - return false; -} - -void Execute::print(Aword fpos, Aword len) { - char str[2 * WIDTH]; // String buffer - int outlen = 0; // Current output length - int ch = 0; - int i; - long savfp = 0; // Temporary saved text file position - bool printFlag = false; // Printing already? - bool savedPrintFlag = printFlag; - DecodeInfo *info = nullptr; // Saved decoding info - - - if (len == 0) - return; - - if (isHere(HERO)) { // Check if the player will see it - if (printFlag) { // Already printing? - // Save current text file position and/or decoding info - if (_vm->header->pack) - info = _vm->_decode->pushDecode(); - else - savfp = _vm->_txtFile->pos(); - } - - printFlag = true; // We're printing now! - _vm->_txtFile->seek(fpos, SEEK_CUR); // Position to start of text - if (_vm->header->pack) - _vm->_decode->startDecoding(); - - for (outlen = 0; outlen != (int)len; outlen = outlen + strlen(str)) { - // Fill the buffer from the beginning - for (i = 0; i <= WIDTH || (i > WIDTH && ch != ' '); i++) { - if (outlen + i == (int)len) // No more characters? - break; - if (_vm->header->pack) - ch = _vm->_decode->decodeChar(); - else - ch = _vm->_txtFile->readSByte(); - if (ch == EOFChar) // Or end of text? - break; - str[i] = ch; - } - - str[i] = '\0'; - - // TODO - /* -#if ISO == 0 - fromIso(str, str); -#endif - */ - _vm->output(str); - } - - // And restore - printFlag = savedPrintFlag; - if (printFlag) { - if (_vm->header->pack) - _vm->_decode->popDecode(info); - else - _vm->_txtFile->seek(savfp, SEEK_CUR); - } - } -} - -void Execute::sys(Aword fpos, Aword len) { - char *command; - - getstr(fpos, len); // Returns address to string on stack - command = (char *)_vm->_stack->pop(); - - warning("Request to execute system command %s", command); - free(command); -} - -void Execute::getstr(Aword fpos, Aword len) { - char *buf = new char[len + 1]; - - _vm->_stack->push((Aptr) buf); // Push the address to the string - _vm->_txtFile->seek(fpos, SEEK_CUR); // Position to start of text - if (_vm->header->pack) - _vm->_decode->startDecoding(); - while (len--) { - if (_vm->header->pack) - *(buf++) = _vm->_decode->decodeChar(); - else - *(buf++) = _vm->_txtFile->readSByte(); - } - *buf = '\0'; -} - -void Execute::score(Aword sc) { - char buf[80]; - - if (sc == 0) { - _vm->printMessage(M_SCORE1); - sprintf(buf, "%d", _vm->cur.score); - _vm->output(buf); - _vm->printMessage(M_SCORE2); - sprintf(buf, "%ld.", (unsigned long)_vm->header->maxscore); - _vm->output(buf); - } else { - _vm->cur.score += _vm->scores[sc - 1]; - _vm->scores[sc - 1] = 0; - } -} - -void Execute::visits(Aword v) { - _vm->cur.visits = v; -} - -bool Execute::confirm(MsgKind msgno) { - char buf[80]; - - // This is a bit of a hack since we really want to compare the input, - // it could be affirmative, but for now any input is NOT! - _vm->printMessage(msgno); - - // TODO -#if 0 - //_vm->glk_request_line_event(_bottomWindow, buf, 80 - 1, 0); - -#ifdef USE_READLINE - if (!readline(buf)) return true; -#else - if (gets(buf) == nullptr) return true; -#endif - -#endif - _vm->col = 1; - - return (buf[0] == '\0'); -} - - -void Execute::quit() { - char buf[80]; -// char choices[10]; - - _vm->paragraph(); - - while (true) { - _vm->col = 1; - _vm->statusLine(); - _vm->printMessage(M_QUITACTION); - - // TODO -#if 0 -#ifdef USE_READLINE - if (!readline(buf)) terminate(0); -#else - if (gets(buf) == nullptr) terminate(0); -#endif -#endif - - if (strcmp(buf, "restart") == 0) { - //longjmp(restart_label, true); // TODO - } else if (strcmp(buf, "restore") == 0) { - _vm->_saveLoad->restore(); - return; - } else if (strcmp(buf, "quit") == 0) { - _vm->quitGame(); - } - } - error("Fallthrough in QUIT"); -} - -void Execute::restart() { - _vm->paragraph(); - if (confirm(M_REALLY)) { - //longjmp(restart_label, true); // TODO - } else - return; - - error("Fallthrough in RESTART"); -} - -void Execute::eventchk() { - while (etop != 0 && eventq[etop - 1].time == _vm->cur.tick) { - etop--; - if (isLoc(eventq[etop].where)) - _vm->cur.loc = eventq[etop].where; - else - _vm->cur.loc = where(eventq[etop].where); - - // TODO -#if 0 - if (trcflg) { - debug("\ncur.loc); - debug("):>\n"); - } -#endif - _vm->_interpreter->interpret(_vm->evts[eventq[etop].event - EVTMIN].code); - } -} - -void Execute::cancl(Aword evt) { - int i; - - for (i = etop - 1; i >= 0; i--) { - if (eventq[i].event == (int)evt) { - while (i < etop - 1) { - eventq[i].event = eventq[i + 1].event; - eventq[i].time = eventq[i + 1].time; - eventq[i].where = eventq[i + 1].where; - i++; - } - - etop--; - return; - } - } -} - -void Execute::schedule(Aword evt, Aword whr, Aword aft) { - int i; - int time; - - cancl(evt); - // Check for overflow - if (etop == N_EVTS) - error("Out of event space."); - - time = _vm->cur.tick+aft; - - // Bubble this event down - for (i = etop; i >= 1 && eventq[i-1].time <= time; i--) { - eventq[i].event = eventq[i-1].event; - eventq[i].time = eventq[i-1].time; - eventq[i].where = eventq[i-1].where; - } - - eventq[i].time = time; - eventq[i].where = whr; - eventq[i].event = evt; - etop++; -} - -Aptr Execute::getAttribute(Aaddr atradr, Aaddr atr) { - AtrElem *at = (AtrElem *)addrTo(atradr); - return at[atr - 1].val; -} - -void Execute::setAttribute(Aaddr atradr, Aword atr, Aword val) { - AtrElem *at = (AtrElem *)addrTo(atradr); - at[atr - 1].val = val; -} - -void Execute::make(Aword id, Aword atr, Aword val) { - if (isObj(id)) - setAttribute(_objs[id - OBJMIN].atrs, atr, val); - else if (isLoc(id)) - setAttribute(_locs[id - LOCMIN].atrs, atr, val); - else if (isAct(id)) - setAttribute(_acts[id - ACTMIN].atrs, atr, val); - else - error("Can't MAKE item (%ld).", (unsigned long)id); -} - -void Execute::set(Aword id, Aword atr, Aword val) { - if (isObj(id)) - setAttribute(_objs[id - OBJMIN].atrs, atr, val); - else if (isLoc(id)) { - setAttribute(_locs[id - LOCMIN].atrs, atr, val); - _locs[id - LOCMIN].describe = 0; - } else if (isAct(id)) - setAttribute(_acts[id - ACTMIN].atrs, atr, val); - else - error("Can't SET item (%ld).", (unsigned long)id); -} - -void Execute::setstr(Aword id, Aword atr, Aword str) { - free((char *)attribute(id, atr)); - set(id, atr, str); -} - -void Execute::incAttribute(Aaddr atradr, Aword atr, Aword step) { - AtrElem *at = (AtrElem *) addrTo(atradr); - at[atr - 1].val += step; -} - -void Execute::incLocation(Aword loc, Aword atr, Aword step) { - incAttribute(_locs[loc - LOCMIN].atrs, atr, step); - _locs[loc - LOCMIN].describe = 0; -} - -void Execute::incObject(Aword obj, Aword atr, Aword step) { - incAttribute(_objs[obj - OBJMIN].atrs, atr, step); -} - -void Execute::incract(Aword act, Aword atr, Aword step) { - incAttribute(_acts[act - ACTMIN].atrs, atr, step); -} - -void Execute::incr(Aword id, Aword atr, Aword step) { - if (isObj(id)) - incObject(id, atr, step); - else if (isLoc(id)) - incLocation(id, atr, step); - else if (isAct(id)) - incract(id, atr, step); - else - error("Can't INCR item (%ld).", (unsigned long)id); -} - -void Execute::decr(Aword id, Aword atr, Aword step) { - if (isObj(id)) - incObject(id, atr, -(int)step); - else if (isLoc(id)) - incLocation(id, atr, -(int)step); - else if (isAct(id)) - incract(id, atr, -(int)step); - else - error("Can't DECR item (%ld).", (unsigned long)id); -} - -Aptr Execute::attribute(Aword id, Aword atr) { - if (isObj(id)) - return getAttribute(_objs[id - OBJMIN].atrs, atr); - else if (isLoc(id)) - return getAttribute(_locs[id - LOCMIN].atrs, atr); - else if (isAct(id)) - return getAttribute(_acts[id - ACTMIN].atrs, atr); - else if (isLit(id)) { - if (atr == 1) - return litValues[id - LITMIN].value; - else - error("Unknown attribute for literal (%ld).", (unsigned long)atr); - } else - error("Can't ATTRIBUTE item (%ld).", (unsigned long) id); -} - -Aptr Execute::strattr(Aword id, Aword atr) { - Common::String result = (char *)attribute(id, atr); - return (Aptr)result.c_str(); -} - -Aword Execute::objloc(Aword obj) { - if (isCnt(_objs[obj - OBJMIN].loc)) { // In something ? - if (isObj(_objs[obj - OBJMIN].loc) || isAct(_objs[obj - OBJMIN].loc)) - return(where(_objs[obj - OBJMIN].loc)); - else // Containers not anywhere is where the hero is! - return(where(HERO)); - } else { - return(_objs[obj - OBJMIN].loc); - } -} - -Aword Execute::actloc(Aword act) { - return(_acts[act - ACTMIN].loc); -} - -Aword Execute::where(Aword id) { - if (isObj(id)) - return objloc(id); - else if (isAct(id)) - return actloc(id); - else - error("Can't WHERE item (%ld).", (unsigned long) id); -} - -Aint Execute::agrmax(Aword atr, Aword whr) { - Aword i; - uint max = 0; - - for (i = OBJMIN; i <= OBJMAX; i++) { - if (isLoc(whr)) { - if (where(i) == whr && attribute(i, atr) > max) - max = attribute(i, atr); - } else if (_objs[i - OBJMIN].loc == whr && attribute(i, atr) > max) - max = attribute(i, atr); - } - - return(max); -} - -Aint Execute::agrsum(Aword atr, Aword whr) { - Aword i; - uint sum = 0; - - for (i = OBJMIN; i <= OBJMAX; i++) { - if (isLoc(whr)) { - if (where(i) == whr) - sum += attribute(i, atr); - } else if (_objs[i-OBJMIN].loc == whr) - sum += attribute(i, atr); - } - - return(sum); -} - -Aint Execute::agrcount(Aword whr) { - Aword i; - Aword countVal = 0; - - for (i = OBJMIN; i <= OBJMAX; i++) { - if (isLoc(whr)) { - if (where(i) == whr) - countVal++; - } else if (_objs[i-OBJMIN].loc == whr) - countVal++; - } - - return(countVal); -} - -void Execute::locobj(Aword obj, Aword whr) { - if (isCnt(whr)) { // Into a container - if (whr == obj) - error("Locating something inside itself."); - if (checkContainerLimit(whr, obj)) - return; - else - _objs[obj-OBJMIN].loc = whr; - } else { - _objs[obj-OBJMIN].loc = whr; - // Make sure the location is described since it's changed - _locs[whr-LOCMIN].describe = 0; - } -} - -void Execute::locact(Aword act, Aword whr) { - Aword prevact = _vm->cur.act; - Aword prevloc = _vm->cur.loc; - - _vm->cur.loc = whr; - _acts[act - ACTMIN].loc = whr; - - if (act == HERO) { - if (_locs[_acts[act - ACTMIN].loc-LOCMIN].describe % (_vm->cur.visits+1) == 0) - look(); - else { - if (_vm->_anyOutput) - _vm->paragraph(); - - say(where(HERO)); - _vm->printMessage(M_AGAIN); - _vm->newLine(); - dscrobjs(); - dscracts(); - } - - _locs[where(HERO)-LOCMIN].describe++; - _locs[where(HERO)-LOCMIN].describe %= (_vm->cur.visits+1); - } else - _locs[whr-LOCMIN].describe = 0; - - if (_locs[_vm->cur.loc-LOCMIN].does != 0) { - _vm->cur.act = act; - _vm->_interpreter->interpret(_locs[_vm->cur.loc-LOCMIN].does); - _vm->cur.act = prevact; - } - - if (_vm->cur.act != (int)act) - _vm->cur.loc = prevloc; -} - - -void Execute::locate(Aword id, Aword whr) { - if (isObj(id)) - locobj(id, whr); - else if (isAct(id)) - locact(id, whr); - else - error("Can't LOCATE item (%ld).", (unsigned long)id); -} - -Abool Execute::objhere(Aword obj) { - if (isCnt(_objs[obj - OBJMIN].loc)) { // In something? - if (isObj(_objs[obj - OBJMIN].loc) || isAct(_objs[obj - OBJMIN].loc)) - return(isHere(_objs[obj - OBJMIN].loc)); - else // If the container wasn't anywhere, assume where HERO is! - return((int)where(HERO) == _vm->cur.loc); - } else - return((int)_objs[obj - OBJMIN].loc == _vm->cur.loc); -} - -Aword Execute::acthere(Aword act) { - return (int)_acts[act - ACTMIN].loc == _vm->cur.loc; -} - -Abool Execute::isHere(Aword id) { - if (isObj(id)) - return objhere(id); - else if (isAct(id)) - return acthere(id); - else - error("Can't HERE item (%ld).", (unsigned long)id); -} - -Aword Execute::objnear(Aword obj) { - if (isCnt(_objs[obj-OBJMIN].loc)) { // In something? - if (isObj(_objs[obj-OBJMIN].loc) || isAct(_objs[obj-OBJMIN].loc)) - return(isNear(_objs[obj-OBJMIN].loc)); - else // If the container wasn't anywhere, assume here, so not nearby! - return(false); - } else { - return(exitto(where(obj), _vm->cur.loc)); - } -} - -Aword Execute::actnear(Aword act) { - return(exitto(where(act), _vm->cur.loc)); -} - - -Abool Execute::isNear(Aword id) { - if (isObj(id)) - return objnear(id); - else if (isAct(id)) - return actnear(id); - else - error("Can't NEAR item (%ld).", (unsigned long) id); -} - -Abool Execute::in(Aword obj, Aword cnt) { - if (!isObj(obj)) - return(false); - if (!isCnt(cnt)) - error("IN in a non-container."); - - return(_objs[obj - OBJMIN].loc == cnt); -} - -void Execute::sayarticle(Aword id) { - if (!isObj(id)) - error("Trying to say article of something *not* an object."); - if (_objs[id - OBJMIN].art != 0) - _vm->_interpreter->interpret(_objs[id - OBJMIN].art); - else - _vm->printMessage(M_ARTICLE); -} - -void Execute::say(Aword id) { - if (isHere(HERO)) { - if (isObj(id)) - _vm->_interpreter->interpret(_objs[id - OBJMIN].dscr2); - else if (isLoc(id)) - _vm->_interpreter->interpret(_locs[id - LOCMIN].nams); - else if (isAct(id)) - _vm->_interpreter->interpret(_acts[id - ACTMIN].nam); - else if (isLit(id)) { - if (isNum(id)) - _vm->output(Common::String::format("%ld", litValues[id - LITMIN].value)); - else - _vm->output((char *)litValues[id - LITMIN].value); - } else - error("Can't SAY item (%ld).", (unsigned long)id); - } -} - -void Execute::dscrloc(Aword loc) { - if (_locs[loc - LOCMIN].dscr != 0) - _vm->_interpreter->interpret(_locs[loc - LOCMIN].dscr); -} - -void Execute::dscrobj(Aword obj) { - _objs[obj - OBJMIN].describe = false; - if (_objs[obj - OBJMIN].dscr1 != 0) - _vm->_interpreter->interpret(_objs[obj - OBJMIN].dscr1); - else { - _vm->printMessage(M_SEEOBJ1); - sayarticle(obj); - say(obj); - _vm->printMessage(M_SEEOBJ4); - if (_objs[obj - OBJMIN].cont != 0) - list(obj); - } -} - - -void Execute::dscract(Aword act) { - ScrElem *scr = nullptr; - - if (_acts[act - ACTMIN].script != 0) { - for (scr = (ScrElem *) addrTo(_acts[act - ACTMIN].scradr); !endOfTable(scr); scr++) - if (scr->code == _acts[act - ACTMIN].script) - break; - if (endOfTable(scr)) - scr = nullptr; - } - - if (scr != nullptr && scr->dscr != 0) - _vm->_interpreter->interpret(scr->dscr); - else if (_acts[act - ACTMIN].dscr != 0) - _vm->_interpreter->interpret(_acts[act - ACTMIN].dscr); - else { - _vm->_interpreter->interpret(_acts[act - ACTMIN].nam); - _vm->printMessage(M_SEEACT); - } - - _acts[act - ACTMIN].describe = false; -} - -void Execute::describe(Aword id) { - for (uint i = 0; i < _describeStack.size(); i++) { - _describeStack.push(id); - - if (isObj(id)) - dscrobj(id); - else if (isLoc(id)) - dscrloc(id); - else if (isAct(id)) - dscract(id); - else - error("Can't DESCRIBE item (%ld).", (unsigned long)id); - } - - _describeStack.pop(); -} - -void Execute::use(Aword act, Aword scr) { - if (!isAct(act)) - error("Item is not an Actor (%ld).", (unsigned long) act); - - _acts[act - ACTMIN].script = scr; - _acts[act - ACTMIN].step = 0; -} - -void Execute::list(Aword cnt) { - uint i; - Aword props; - Aword prevobj = 0; - bool found = false; - bool multiple = false; - - // Find container properties - if (isObj(cnt)) - props = _objs[cnt-OBJMIN].cont; - else if (isAct(cnt)) - props = _acts[cnt-ACTMIN].cont; - else - props = cnt; - - for (i = OBJMIN; i <= OBJMAX; i++) { - if (in(i, cnt)) { // Yes, it's in this container - if (!found) { - found = true; - if (_cnts[props-CNTMIN].header != 0) - _vm->_interpreter->interpret(_cnts[props-CNTMIN].header); - else { - _vm->printMessage(M_CONTAINS1); - if (_cnts[props-CNTMIN].nam != 0) // It has it's own name - _vm->_interpreter->interpret(_cnts[props-CNTMIN].nam); - else - say(_cnts[props-CNTMIN].parent); // It is actually an object or actor - - _vm->printMessage(M_CONTAINS2); - } - } else { - if (multiple) { - _vm->_needSpace = false; - _vm->printMessage(M_CONTAINS3); - } - - multiple = true; - sayarticle(prevobj); - say(prevobj); - } - - prevobj = i; - } - } - - if (found) { - if (multiple) - _vm->printMessage(M_CONTAINS4); - - sayarticle(prevobj); - say(prevobj); - _vm->printMessage(M_CONTAINS5); - } else { - if (_cnts[props-CNTMIN].empty != 0) - _vm->_interpreter->interpret(_cnts[props-CNTMIN].empty); - else { - _vm->printMessage(M_EMPTY1); - - if (_cnts[props-CNTMIN].nam != 0) // It has it's own name - _vm->_interpreter->interpret(_cnts[props-CNTMIN].nam); - else - say(_cnts[props-CNTMIN].parent); // It is actually an actor or object - - _vm->printMessage(M_EMPTY2); - } - } - - _vm->_needSpace = true; -} - -void Execute::empty(Aword cnt, Aword whr) { - for (uint i = OBJMIN; i <= OBJMAX; i++) - if (in(i, cnt)) - locate(i, whr); -} - -void Execute::dscrobjs() { - uint i; - int prevobj = 0; - bool found = false; - bool multiple = false; - - // First describe everything here with its own description - for (i = OBJMIN; i <= OBJMAX; i++) { - if ((int)_objs[i - OBJMIN].loc == _vm->cur.loc && _objs[i - OBJMIN].describe && _objs[i - OBJMIN].dscr1) - describe(i); - } - - // Then list everything else here - for (i = OBJMIN; i <= OBJMAX; i++) { - if ((int)_objs[i - OBJMIN].loc == _vm->cur.loc && _objs[i - OBJMIN].describe) { - if (!found) { - _vm->printMessage(M_SEEOBJ1); - sayarticle(i); - say(i); - found = true; - } else { - if (multiple) { - _vm->_needSpace = false; - _vm->printMessage(M_SEEOBJ2); - sayarticle(prevobj); - say(prevobj); - } - - multiple = true; - } - - prevobj = i; - } - } - - if (found) { - if (multiple) { - _vm->printMessage(M_SEEOBJ3); - sayarticle(prevobj); - say(prevobj); - } - - _vm->printMessage(M_SEEOBJ4); - } - - // Set describe flag for all objects - for (i = OBJMIN; i <= OBJMAX; i++) - _objs[i-OBJMIN].describe = true; -} - - -void Execute::dscracts() { - for (uint i = HERO+1; i <= ACTMAX; i++) - if ((int)_acts[i-ACTMIN].loc == _vm->cur.loc && - _acts[i-ACTMIN].describe) - describe(i); - - // Set describe flag for all actors - for (uint i = HERO; i <= ACTMAX; i++) - _acts[i-ACTMIN].describe = true; -} - -void Execute::look() { - uint i; - _vm->looking = true; - - // Set describe flag for all objects and actors - for (i = OBJMIN; i <= OBJMAX; i++) - _objs[i-OBJMIN].describe = true; - for (i = ACTMIN; i <= ACTMAX; i++) - _acts[i-ACTMIN].describe = true; - - if (_vm->_anyOutput) - _vm->paragraph(); - - //glk_set_style(style_Subheader); // TODO - _vm->_needSpace = false; - say(_vm->cur.loc); - - _vm->_needSpace = false; - _vm->output("."); - - //glk_set_style(style_Normal); // TODO - _vm->newLine(); - _vm->_needSpace = false; - describe(_vm->cur.loc); - dscrobjs(); - dscracts(); - _vm->looking = false; -} - -Aword Execute::rnd(Aword from, Aword to) { - if (to == from) - return to; - else if (to > from) - return to; // TODO - //return (rand()/10)%(to-from+1)+from; - else - return to; // TODO - //return (rand()/10)%(from-to+1)+to; -} - -// Between -Abool Execute::btw(Aint val, Aint low, Aint high) { - if (high > low) - return low <= val && val <= high; - else - return high <= val && val <= low; -} - -// TODO: Replace this with Common::String functionality -Aword Execute::contains(Aptr string, Aptr substring) { - Common::String str = (char *)string; - char *substr = (char *)substring; - bool result = str.contains(substr); - - free((char *)string); - free((char *)substring); - - return result; -} - -// TODO: Replace this with Common::String functionality -// Compare two strings approximately, ignore case -Abool Execute::streq(char *a, char *b) { - Common::String str1 = a; - Common::String str2 = b; - bool result = str1.equalsIgnoreCase(str2); - - free(a); - free(b); - - return result; -} - -} // End of namespace Alan2 -} // End of namespace Glk diff --git a/engines/glk/alan2/execute.h b/engines/glk/alan2/execute.h deleted file mode 100644 index 9f04ca5ae5..0000000000 --- a/engines/glk/alan2/execute.h +++ /dev/null @@ -1,171 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_EXECUTE -#define GLK_ALAN2_EXECUTE - -#include "glk/alan2/acode.h" -#include "glk/alan2/rules.h" -#include "common/list.h" - -namespace Glk { -namespace Alan2 { - -class Execute { -public: - Execute() {} - - void sys(Aword fpos, Aword len); - bool confirm(MsgKind msgno); - Aptr attribute(Aword item, Aword atr); - void say(Aword item); - void saynum(Aword num); - void saystr(char *str); - Aptr strattr(Aword id, Aword atr); - void setstr(Aword id, Aword atr, Aword str); - void getstr(Aword fpos, Aword len); - void print(Aword fpos, Aword len); - void look(); - void make(Aword id, Aword atr, Aword val); - void set(Aword id, Aword atr, Aword val); - void incr(Aword id, Aword atr, Aword step); - void decr(Aword id, Aword atr, Aword step); - void use(Aword act, Aword scr); - void describe(Aword id); - void list(Aword cnt); - void locate(Aword id, Aword whr); - void empty(Aword cnt, Aword whr); - void score(Aword sc); - void visits(Aword v); - - /** - * Check if any events are pending. If so execute them. - */ - void eventchk(); - void schedule(Aword evt, Aword whr, Aword aft); - void cancl(Aword evt); - - void quit(); - void restart(); - void sayint(Aword val); - Aword rnd(Aword from, Aword to); - Abool btw(Aint val, Aint from, Aint to); - Aword contains(Aptr string, Aptr substring); - Abool streq(char a[], char b[]); - Abool in(Aword obj, Aword cnt); - Aword where(Aword item); - Aint agrmax(Aword atr, Aword whr); - Aint agrsum(Aword atr, Aword whr); - Aint agrcount(Aword whr); - Abool isHere(Aword item); - Abool isNear(Aword item); - -private: - bool exitto(int to, int from); - - /** - * Count the number of items in a container. - * - * @param cnt The container to count - */ - int count(int cnt); - - /** - * Sum the values of one attribute in a container. Recursively. - * - * @param atr The attribute to sum over - * @param cnt the container to sum - */ - int sumAttributes(Aword atr, Aword cnt); - - /** - * Checks if a limit for a container is exceeded. - * - * @param cnt Container code - * @param obj The object to add - */ - bool checkContainerLimit(Aword cnt, Aword obj); - - /** - * Get an attribute value from an attribute list - * - * @param atradr ACODE address to attribute table - * @param atr The attribute to read - */ - Aptr getAttribute(Aaddr atradr, Aaddr atr); - - /** - * Set a particular attribute to a value. - * - * @param atradr ACODE address to attribute table - * @param atr Attribute code - * @param val New value - */ - void setAttribute(Aaddr atradr, Aword atr, Aword val); - - /** - * Increment a particular attribute by a value. - * - * @param atradr ACODE address to attribute table - * @param atr Attribute code - * @param step Step to increment by - */ - void incAttribute(Aaddr atradr, Aword atr, Aword step); - void incLocation(Aword loc, Aword atr, Aword step); - void incObject(Aword obj, Aword atr, Aword step); - void incract(Aword act, Aword atr, Aword step); - Aword objloc(Aword obj); - Aword actloc(Aword act); - void locobj(Aword obj, Aword whr); - void locact(Aword act, Aword whr); - Abool objhere(Aword obj); - Aword acthere(Aword act); - Aword objnear(Aword obj); - Aword actnear(Aword act); - void sayarticle(Aword id); - void dscrloc(Aword loc); - void dscrobj(Aword obj); - void dscract(Aword act); - - /** - * Description of current location - */ - void dscrobjs(); - - void dscracts(); - - // The event queue - EvtqElem *eventq; // Event queue - int etop; // Event queue top pointer - - // Amachine data structures - ActElem *_acts; // Actor table pointer - LocElem *_locs; // Location table pointer - ObjElem *_objs; // Object table pointer - CntElem *_cnts; // Container table pointer - Common::Stack _describeStack; -}; - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/alan2/interpreter.cpp b/engines/glk/alan2/interpreter.cpp deleted file mode 100644 index b8906d2c6e..0000000000 --- a/engines/glk/alan2/interpreter.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "glk/alan2/acode.h" -#include "glk/alan2/alan2.h" -#include "glk/alan2/execute.h" -#include "glk/alan2/interpreter.h" -#include "glk/alan2/saveload.h" -#include "glk/alan2/types.h" -#include "common/debug.h" - -namespace Glk { -namespace Alan2 { - -// TODO: Refactor these into debug flags -const bool trcflg = false; -const bool stpflg = false; - -void Interpreter::if_(Aword v) { - int lev = 1; - Aword i; - - if (!v) { - // Skip to next ELSE or ENDIF on same level - while (true) { - i = _vm->memory[_vm->pc++]; - if (I_CLASS(i) == (Aword)C_STMOP) { - switch (I_OP(i)) { - case I_ELSE: - if (lev == 1) - return; - break; - case I_IF: - lev++; - break; - case I_ENDIF: - lev--; - if (lev == 0) - return; - break; - default: - break; - } - } - } - } -} - -void Interpreter::else_() { - int lev = 1; - Aword i; - - while (true) { - // Skip to ENDIF on the same level - i = _vm->memory[_vm->pc++]; - if (I_CLASS(i) == (Aword)C_STMOP) { - switch (I_OP(i)) { - case I_ENDIF: - lev--; - if (lev == 0) - return; - break; - case I_IF: - lev++; - break; - default: - break; - } - } - } -} - -void Interpreter::depstart() { - // A DEPSTART was executed, so skip across the redundant DEPCASE to - // start at the first expression - _vm->pc++; -} - -void Interpreter::swap() { - Aptr v1 = _stack->pop(); - Aptr v2 = _stack->pop(); - - _stack->push(v1); - _stack->push(v2); -} - -void Interpreter::depexec(Aword v) { - int lev = 1; - Aword i; - - if (!v) { - // The expression was not true, skip to next CASE on the same - // level which could be a DEPCASE or DEPELSE - while (true) { - i = _vm->memory[_vm->pc++]; - if (I_CLASS(i) == (Aword)C_STMOP) { - switch (I_OP(i)) { - case I_DEPSTART: - lev++; - break; - case I_DEPEND: - if (lev == 1) - return; - lev--; - break; - case I_DEPCASE: - case I_DEPELSE: - if (lev == 1) - return; - break; - default: - break; - } - } - } - } -} - -void Interpreter::depcase() { - int lev = 1; - Aword i; - - // Skip to end of DEPENDING block (next DEPEND on same level) because - // we have just executed a DEPCASE/DEPELSE statement as a result of a DEPCASE - // catching - - while (true) { - i = _vm->memory[_vm->pc++]; - if (I_CLASS(i) == (Aword)C_STMOP) { - switch (I_OP(i)) { - case I_DEPSTART: - lev++; - break; - case I_DEPEND: - lev--; - if (lev == 0) return; - break; - default: - break; - } - } - } -} - -void Interpreter::curVar(Aword i) { - switch (I_OP(i)) { - case V_PARAM: - if (stpflg) - debug("PARAM \t%5ld\t\t(%d)", _stack->top(), _vm->params[_stack->top() - 1].code); - _stack->push(_vm->params[_stack->pop() - 1].code); - break; - case V_CURLOC: - if (stpflg) - debug("CURLOC \t\t\t(%d)", _vm->cur.loc); - _stack->push(_vm->cur.loc); - break; - case V_CURACT: - if (stpflg) - debug("CURACT \t\t\t(%d)", _vm->cur.act); - _stack->push(_vm->cur.act); - break; - case V_CURVRB: - if (stpflg) - debug("CURVRB \t\t\t(%d)", _vm->cur.vrb); - _stack->push(_vm->cur.vrb); - break; - case V_SCORE: - if (stpflg) - debug("CURSCORE \t\t\t(%d)", _vm->cur.score); - _stack->push(_vm->cur.score); - break; - default: - error("Unknown CURVAR instruction."); - } -} - -void Interpreter::adaptOldOpcodes(Aword i) { - switch (I_OP(i)) { - case I_AND: - case I_OR: - case I_NE: - case I_EQ: - case I_STREQ: - case I_STREXACT: - case I_LE: - case I_GE: - case I_LT: - case I_GT: - case I_PLUS: - case I_MINUS: - case I_MULT: - case I_DIV: - if (_vm->header->vers[0] == 2 && _vm->header->vers[1] == 7) // Check for 2.7 version - swap(); - } -} - -void Interpreter::stMop(Aword i, Aaddr oldpc) { - Aptr arg1, arg2, arg3, lh, rh; - - adaptOldOpcodes(i); - - switch (I_OP(i)) { - case I_PRINT: - arg1 = _stack->pop(); // fpos - arg2 = _stack->pop(); // len - if (stpflg) { - debug("PRINT \t%5ld, %5ld\t\"", arg1, arg2); - _vm->col = 34; // To format it better! - } - _execute->print(arg1, arg2); - if (stpflg) - debug("\""); - break; - case I_SYSTEM: - arg1 = _stack->pop(); // fpos - arg2 = _stack->pop(); // len - if (stpflg) { - debug("SYSTEM \t%5ld, %5ld\t\"", arg1, arg2); - _vm->col = 34; // To format it better! - } - _execute->sys(arg1, arg2); - break; - case I_GETSTR: - arg1 = _stack->pop(); // fpos - arg2 = _stack->pop(); // len - if (stpflg) - debug("GETSTR\t%5ld, %5ld", arg1, arg2); - _execute->getstr(arg1, arg2); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_QUIT: - if (stpflg) - debug("QUIT"); - _execute->quit(); - break; - case I_LOOK: - if (stpflg) - debug("LOOK"); - _execute->look(); - break; - case I_SAVE: - if (stpflg) - debug("SAVE"); - _saveLoad->save(); - break; - case I_RESTORE: - if (stpflg) - debug("RESTORE"); - _saveLoad->restore(); - break; - case I_RESTART: - if (stpflg) - debug("RESTART"); - _execute->restart(); - break; - case I_LIST: - arg1 = _stack->pop(); // cnt - if (stpflg) - debug("LIST \t%5ld", arg1); - _execute->list(arg1); - break; - case I_EMPTY: - arg1 = _stack->pop(); // cnt - arg2 = _stack->pop(); // whr - if (stpflg) - debug("EMPTY \t%5ld, %5ld", arg1, arg2); - _execute->empty(arg1, arg2); - break; - case I_SCORE: - arg1 = _stack->pop(); // score - if (stpflg) - debug("SCORE \t%5ld\t\t(%d)", arg1, _vm->scores[arg1 - 1]); - _execute->score(arg1); - break; - case I_VISITS: - arg1 = _stack->pop(); // visits - if (stpflg) - debug("VISITS \t%5ld", arg1); - _execute->visits(arg1); - break; - case I_SCHEDULE: - arg1 = _stack->pop(); // evt - arg2 = _stack->pop(); // whr - arg3 = _stack->pop(); // aft - if (stpflg) - debug("SCHEDULE \t%5ld, %5ld, %5ld", arg1, arg2, arg3); - _execute->schedule(arg1, arg2, arg3); - break; - case I_CANCEL: - arg1 = _stack->pop(); // evt - if (stpflg) - debug("CANCEL \t%5ld", arg1); - _execute->cancl(arg1); - break; - case I_MAKE: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - arg3 = _stack->pop(); // val - if (stpflg) { - debug("MAKE \t%5ld, %5ld, ", arg1, arg2); - if (arg3) - debug("TRUE"); - else - debug("FALSE"); - } - _execute->make(arg1, arg2, arg3); - break; - case I_SET: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - arg3 = _stack->pop(); // val - if (stpflg) - debug("SET \t%5ld, %5ld, %5ld", arg1, arg2, arg3); - _execute->set(arg1, arg2, arg3); - break; - case I_STRSET: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - arg3 = _stack->pop(); // str - if (stpflg) - debug("STRSET\t%5ld, %5ld, %5ld", arg1, arg2, arg3); - _execute->setstr(arg1, arg2, arg3); - break; - case I_INCR: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - arg3 = _stack->pop(); // step - if (stpflg) - debug("INCR\t%5ld, %5ld, %5ld", arg1, arg2, arg3); - _execute->incr(arg1, arg2, arg3); - break; - case I_DECR: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - arg3 = _stack->pop(); // step - if (stpflg) - debug("DECR\t%5ld, %5ld, %5ld", arg1, arg2, arg3); - _execute->decr(arg1, arg2, arg3); - break; - case I_ATTRIBUTE: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - if (stpflg) - debug("ATTRIBUTE %5ld, %5ld", arg1, arg2); - _stack->push(_execute->attribute(arg1, arg2)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_STRATTR: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // atr - if (stpflg) - debug("STRATTR \t%5ld, %5ld", arg1, arg2); - _stack->push(_execute->strattr(arg1, arg2)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_LOCATE: - arg1 = _stack->pop(); // id - arg2 = _stack->pop(); // whr - if (stpflg) - debug("LOCATE \t%5ld, %5ld", arg1, arg2); - _execute->locate(arg1, arg2); - break; - case I_WHERE: - arg1 = _stack->pop(); // id - if (stpflg) - debug("WHERE \t%5ld", arg1); - _stack->push(_execute->where(arg1)); - if (stpflg) - debug("\t\t(%ld)", _stack->top()); - break; - case I_HERE: - arg1 = _stack->pop(); // id - if (stpflg) - debug("HERE \t%5ld", arg1); - _stack->push(_execute->isHere(arg1)); - if (stpflg) { - if (_stack->top()) - debug("\t(TRUE)"); - else - debug("\t(FALSE)"); - } - break; - case I_NEAR: - arg1 = _stack->pop(); // id - if (stpflg) - debug("NEAR \t%5ld", arg1); - _stack->push(_execute->isNear(arg1)); - if (stpflg) { - if (_stack->top()) - debug("\t(TRUE)"); - else - debug("\t(FALSE)"); - } - break; - case I_USE: - arg1 = _stack->pop(); // act - arg2 = _stack->pop(); // scr - if (stpflg) - debug("USE \t%5ld, %5ld", arg1, arg2); - _execute->use(arg1, arg2); - break; - case I_IN: - arg1 = _stack->pop(); // obj - arg2 = _stack->pop(); // cnt - if (stpflg) - debug("IN \t%5ld, %5ld ", arg1, arg2); - _stack->push(_execute->in(arg1, arg2)); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_DESCRIBE: - arg1 = _stack->pop(); // id - if (stpflg) { - debug("DESCRIBE \t%5ld\t", arg1); - _vm->col = 34; // To format it better! - } - _execute->describe(arg1); - break; - case I_SAY: - arg1 = _stack->pop(); // id - if (stpflg) - debug("SAY \t%5ld\t\t\"", arg1); - _execute->say(arg1); - if (stpflg) - debug("\""); - break; - case I_SAYINT: - arg1 = _stack->pop(); // val - if (stpflg) - debug("SAYINT\t%5ld\t\t\"", arg1); - _execute->sayint(arg1); - if (stpflg) - debug("\""); - break; - case I_SAYSTR: - arg1 = _stack->pop(); // adr - if (stpflg) - debug("SAYSTR\t%5ld\t\t\"", arg1); - _execute->saystr((char *)arg1); - if (stpflg) - debug("\""); - break; - case I_IF: - arg1 = _stack->pop(); // v - if (stpflg) { - debug("IF \t"); - if (arg1) debug(" TRUE"); else debug("FALSE"); - } - if_(arg1); - break; - case I_ELSE: - if (stpflg) - debug("ELSE"); - else_(); - break; - case I_ENDIF: - if (stpflg) - debug("ENDIF"); - break; - case I_AND: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) { - debug("AND \t"); - if (lh) debug("TRUE, "); else debug("FALSE, "); - if (rh) debug("TRUE"); else debug("FALSE"); - } - _stack->push(lh && rh); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_OR: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) { - debug("OR \t"); - if (lh) debug("TRUE, "); else debug("FALSE, "); - if (rh) debug("TRUE"); else debug("FALSE"); - } - _stack->push(lh || rh); - if (stpflg) { - if (_stack->top()) - debug("\t(TRUE)"); - else - debug("\t(FALSE)"); - } - break; - case I_NE: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("NE \t%5ld, %5ld", lh, rh); - _stack->push(lh != rh); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_EQ: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("EQ \t%5ld, %5ld", lh, rh); - _stack->push(lh == rh); - if (stpflg) { - if (_stack->top()) - debug("\t(TRUE)"); - else - debug("\t(FALSE)"); - } - break; - case I_STREQ: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("STREQ \t%5ld, %5ld", lh, rh); - _stack->push(_execute->streq((char *)lh, (char *)rh)); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_STREXACT: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("STREXACT \t%5ld, %5ld", lh, rh); - _stack->push(strcmp((char *)lh, (char *)rh) == 0); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - free((void *)lh); - free((void *)rh); - break; - case I_LE: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("LE \t%5ld, %5ld", lh, rh); - _stack->push(lh <= rh); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_GE: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("GE \t%5ld, %5ld", lh, rh); - _stack->push(lh >= rh); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_LT: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("LT \t%5ld, %5ld", lh, rh); - _stack->push((signed int)lh < (signed int)rh); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_GT: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("GT \t%5ld, %5ld", lh, rh); - _stack->push(lh > rh); - if (stpflg) { - if (_stack->top()) debug("\t(TRUE)"); else debug("\t(FALSE)"); - } - break; - case I_PLUS: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("PLUS \t%5ld, %5ld", lh, rh); - _stack->push(lh + rh); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_MINUS: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("MINUS \t%5ld, %5ld", lh, rh); - _stack->push(lh - rh); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_MULT: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("MULT \t%5ld, %5ld", lh, rh); - _stack->push(lh * rh); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_DIV: - rh = _stack->pop(); - lh = _stack->pop(); - if (stpflg) - debug("DIV \t%5ld, %5ld", lh, rh); - _stack->push(lh / rh); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_NOT: - arg1 = _stack->pop(); // val - if (stpflg) { - debug("NOT \t"); - if (arg1) debug("TRUE"); else debug("FALSE"); - } - _stack->push(!arg1); - if (stpflg) { - if (_stack->top()) debug("\t\t(TRUE)"); else debug("\t\t(FALSE)"); - } - break; - case I_MAX: - arg1 = _stack->pop(); // atr - arg2 = _stack->pop(); // whr - if (stpflg) - debug("MAX \t%5ld, %5ld", arg1, arg2); - _stack->push(_execute->agrmax(arg1, arg2)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_SUM: - arg1 = _stack->pop(); // atr - arg2 = _stack->pop(); // whr - if (stpflg) - debug("SUM \t%5ld, %5ld", arg1, arg2); - _stack->push(_execute->agrsum(arg1, arg2)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_COUNT: - arg1 = _stack->pop(); // whr - if (stpflg) - debug("COUNT \t%5ld", arg1); - _stack->push(_execute->agrcount(arg1)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_RND: - arg1 = _stack->pop(); // from - arg2 = _stack->pop(); // to - if (stpflg) - debug("RANDOM \t%5ld, %5ld", arg1, arg2); - _stack->push(_execute->rnd(arg1, arg2)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_BTW: - arg1 = _stack->pop(); // high - arg2 = _stack->pop(); // low - arg3 = _stack->pop(); // val - if (stpflg) - debug("BETWEEN \t%5ld, %5ld, %5ld", arg1, arg2, arg3); - _stack->push(_execute->btw(arg1, arg2, arg3)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_CONTAINS: - arg1 = _stack->pop(); // substring - arg2 = _stack->pop(); // string - if (stpflg) - debug("CONTAINS \t%5ld, %5ld", arg2, arg1); - _stack->push(_execute->contains(arg2, arg1)); - if (stpflg) - debug("\t(%ld)", _stack->top()); - break; - case I_DEPSTART: - if (stpflg) - debug("DEPSTART"); - depstart(); - break; - case I_DEPCASE: - if (stpflg) - debug("DEPCASE"); - depcase(); - break; - case I_DEPEXEC: - arg1 = _stack->pop(); // v - if (stpflg) { - debug("DEPEXEC \t"); - if (arg1) debug(" TRUE"); else debug("FALSE"); - } - depexec(arg1); - break; - case I_DEPELSE: - if (stpflg) - debug("DEPELSE"); - depcase(); - break; - case I_DEPEND: - if (stpflg) - debug("DEPEND"); - break; - case I_RETURN: - if (stpflg) - debug("RETURN\n--------------------------------------------------\n"); - _vm->pc = oldpc; - return; - default: - error("Unknown STMOP instruction."); - } - - if (_vm->fail) { - _vm->pc = oldpc; - return; // TODO: Return true/false, and stop execution if necessary - } -} - -void Interpreter::interpret(Aaddr adr) { - Aaddr oldpc = _vm->pc; - Aword i; - - if (stpflg) - debug("\n++++++++++++++++++++++++++++++++++++++++++++++++++"); - - _vm->pc = adr; - - while(true) { - if (stpflg) - debug("\n%4x: ", _vm->pc); - - if (_vm->pc > _vm->memTop) - error("Interpreting outside program."); - - i = _vm->memory[_vm->pc++]; - - switch (I_CLASS(i)) { - case C_CONST: - if (stpflg) - debug("PUSH \t%5d", I_OP(i)); - _stack->push(I_OP(i)); - break; - case C_CURVAR: - curVar(i); - break; - case C_STMOP: - stMop(i, oldpc); - break; - default: - error("Unknown instruction class."); - } - } -} - -} // End of namespace Alan2 -} // End of namespace Glk diff --git a/engines/glk/alan2/interpreter.h b/engines/glk/alan2/interpreter.h deleted file mode 100644 index cbc9bcbb15..0000000000 --- a/engines/glk/alan2/interpreter.h +++ /dev/null @@ -1,59 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_INTERPRETER -#define GLK_ALAN2_INTERPRETER - -#include "glk/alan2/acode.h" -#include "glk/alan2/alan2.h" - -namespace Glk { -namespace Alan2 { - -class Execute; -class SaveLoad; - -class Interpreter { -public: - Interpreter(Execute *execute, SaveLoad *saveLoad, Alan2Stack *stack) : _execute(execute), _saveLoad(saveLoad), _stack(stack) {} - void interpret(Aaddr adr); - -private: - void if_(Aword v); - void else_(); - void depstart(); - void swap(); - void depexec(Aword v); - void depcase(); - void curVar(Aword i); - void stMop(Aword i, Aaddr oldpc); - void adaptOldOpcodes(Aword i); - - Execute *_execute; - SaveLoad *_saveLoad; - Alan2Stack *_stack; -}; - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/alan2/parse.cpp b/engines/glk/alan2/parse.cpp deleted file mode 100644 index 8e6427d09c..0000000000 --- a/engines/glk/alan2/parse.cpp +++ /dev/null @@ -1,969 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "common/stack.h" -#include "glk/alan2/alan2.h" -#include "glk/alan2/execute.h" -#include "glk/alan2/interpreter.h" -#include "glk/alan2/parse.h" -#include "glk/alan2/types.h" -#include "glk/alan2/util.h" -#include "common/debug.h" -#include "common/file.h" -#include "decode.h" - -namespace Glk { -namespace Alan2 { - -uint32 litCount = 0; - -// All procedures for getting a command and turning it into a list of -// dictionary entries are placed here. - -Parser::Parser() { - wrds[0] = EOF; - plural = false; - - // TODO -} - -void Parser::unknown(char *inputStr) { - Common::String str = Common::String::format("'%s'?", inputStr); - - // TODO -#if 0 -#if ISO == 0 - fromIso(str, str); -#endif -#endif - - _vm->output(str); - eol = true; - _vm->printError(M_UNKNOWN_WORD); -} - -int Parser::lookup(char *wrd) { - for (int i = 0; !endOfTable(&dict[i]); i++) { - if (strcmp(wrd, (char *)addrTo(dict[i].wrd)) == 0) - return i; - } - - unknown(wrd); - return EOF; -} - -char *Parser::gettoken(char *tokenBuffer) { - static char *marker; - static char oldch; - - if (tokenBuffer == nullptr) - *marker = oldch; - else - marker = tokenBuffer; - - while (*marker != '\0' && Common::isSpace(*marker) && *marker != '\n') marker++; - tokenBuffer = marker; - - if (Common::isAlpha(*marker)) - while (*marker && (Common::isAlpha(*marker) || Common::isDigit(*marker) || *marker == '\'')) marker++; - else if (Common::isDigit(*marker)) - while (Common::isDigit(*marker)) marker++; - else if (*marker == '\"') { - marker++; - while (*marker != '\"') marker++; - marker++; - } else if (*marker == '\0' || *marker == '\n') - return nullptr; - else - marker++; - - oldch = *marker; - *marker = '\0'; - - return tokenBuffer; -} - -void Parser::agetline() { - // static char buf[LISTLEN + 1]; // The input buffer - // static char isobuf[LISTLEN + 1]; // The input buffer in ISO - - _vm->paragraph(); - - // TODO -#if 0 - - do { -#if defined(HAVE_ANSI) || defined(GLK) - statusline(); -#endif - debug("> "); - -#if 0 - if (logflg) - fprintf(logfil, "> "); -#endif - -#ifdef USE_READLINE - if (!readline(buf)) { - newline(); - quit(); - } -#else - if (fgets(buf, LISTLEN, stdin) == nullptr) { - newline(); - quit(); - } -#endif - - getPageSize(); - anyOutput = FALSE; - - if (logflg) - fprintf(logfil, "%s\n", buf); - -#if ISO == 0 - toIso(isobuf, buf, NATIVECHARSET); -#else - strcpy(isobuf, buf); -#endif - - token = gettoken(isobuf); - - if (token != nullptr && strcmp("debug", token) == 0 && _vm->header->debug) { - dbgflg = true; - debug(); - token = nullptr; - } - } while (token == nullptr); - - eol = false; - lin = 1; - -#endif -} - -void Parser::scan() { - uint i; - // int w; - - agetline(); - wrds[0] = 0; - - for (i = 0; i < litCount; i++) - if (litValues[i].type == TYPSTR && litValues[i].value != 0) - free((char *) litValues[i].value); - - litCount = 0; - - do { - if (Common::isAlpha(token[0])) { - Common::String tmp = token; - tmp.toLowercase(); - strcpy(token, tmp.c_str()); - - // w = lookup(token); - - // TODO - //if (!isNoise(w)) - // wrds[i++] = w; - } else if (Common::isDigit(token[0])) { - if (litCount > MAXPARAMS) - error("Too many parameters."); - - wrds[i++] = dictsize + litCount; // Word outside dictionary = literal - litValues[litCount].type = TYPNUM; - litValues[litCount++].value = atoi(token); - } else if (token[0] == '\"') { - if (litCount > MAXPARAMS) - error("Too many parameters."); - - wrds[i++] = dictsize + litCount; // Word outside dictionary = literal - litValues[litCount].type = TYPSTR; - - // Remove the string quotes while copying - Common::String tmp = token; - tmp.deleteChar(0); - tmp.deleteLastChar(); - char *str = scumm_strdup(tmp.c_str()); - - litValues[litCount++].value = (Aptr) str; - } else if (token[0] == ',') { - //wrds[i++] = conjWord; // TODO - } else - unknown(token); - - wrds[i] = EOF; - eol = (token = gettoken(nullptr)) == nullptr; - } while (!eol); -} - -void Parser::nonverb() { - if (isDir(wrds[wrdidx])) { - wrdidx++; - if (wrds[wrdidx] != EOF && !isConj(wrds[wrdidx])) - _vm->printError(M_WHAT); -// TODO -#if 0 - else - go(dict[wrds[wrdidx-1]].code); -#endif - - if (wrds[wrdidx] != EOF) - wrdidx++; - } else - _vm->printError(M_WHAT); -} - -Aword Parser::where(Aword id) { - if (isObj(id)) - return objloc(id); - else if (isAct(id)) - return acts[id - ACTMIN].loc; - else - error("Can't WHERE item (%ld).", (unsigned long)id); -} - -Aword Parser::objloc(Aword obj) { - if (isCnt(objs[obj - OBJMIN].loc)) // In something ? - if (isObj(objs[obj - OBJMIN].loc) || isAct(objs[obj - OBJMIN].loc)) - return where(objs[obj - OBJMIN].loc); - else // Containers not anywhere is where the hero is! - return where(HERO); - else - return(objs[obj - OBJMIN].loc); -} - -Abool Parser::objhere(Aword obj) { - if (isCnt(objs[obj - OBJMIN].loc)) { // In something? - if (isObj(objs[obj - OBJMIN].loc) || isAct(objs[obj - OBJMIN].loc)) - return isHere(objs[obj - OBJMIN].loc); - else // If the container wasn't anywhere, assume where HERO is! - return (int)where(HERO) == _vm->cur.loc; - } else - return((int)objs[obj - OBJMIN].loc == _vm->cur.loc); -} - - -Abool Parser::isHere(Aword id) { - if (isObj(id)) - return objhere(id); - else if (isAct(id)) - return (int)acts[id - ACTMIN].loc == _vm->cur.loc; - else - error("Can't HERE item (%ld).", (unsigned long)id); -} - -// ---------------------------------------------------------------------------- - -void Parser::buildall(ParamElem list[]) { - uint o, i = 0; - bool found = false; - - for (o = OBJMIN; o <= OBJMAX; o++) { - if (isHere(o)) { - found = true; - list[i].code = o; - list[i++].firstWord = (Aword)EOF; - } - } - - if (!found) - _vm->printError(M_WHAT_ALL); - else - list[i].code = (Aword)EOF; -} - -void Parser::listCopy(ParamElem a[], ParamElem b[]) { - int i; - - for (i = 0; b[i].code != (Aword)EOF; i++) - a[i] = b[i]; - - a[i].code = (Aword)EOF; -} - -bool Parser::listContains(ParamElem l[], Aword e) { - int i; - - for (i = 0; l[i].code != (Aword)EOF && l[i].code != e; i++); - - return (l[i].code == e); -} - -void Parser::listIntersection(ParamElem a[], ParamElem b[]) { - int i, last = 0; - - for (i = 0; a[i].code != (Aword)EOF; i++) - if (listContains(b, a[i].code)) - a[last++] = a[i]; - - a[last].code = (Aword)EOF; -} - -void Parser::listCopyFromDictionary(ParamElem p[], Aword r[]) { - int i; - - for (i = 0; r[i] != (Aword)EOF; i++) { - p[i].code = r[i]; - p[i].firstWord = (Aword)EOF; - } - - p[i].code = (Aword)EOF; -} - -int Parser::listLength(ParamElem a[]) { - int i = 0; - - while (a[i].code != (Aword)EOF) - i++; - - return (i); -} - -void Parser::listCompact(ParamElem a[]) { - int i, j; - - for (i = 0, j = 0; a[j].code != (Aword)EOF; j++) - if (a[j].code != 0) - a[i++] = a[j]; - - a[i].code = (Aword)EOF; -} - -void Parser::listMerge(ParamElem a[], ParamElem b[]) { - int i, last; - - for (last = 0; a[last].code != (Aword)EOF; last++); // Find end of list - - for (i = 0; b[i].code != (Aword)EOF; i++) { - if (!listContains(a, b[i].code)) { - a[last++] = b[i]; - a[last].code = (Aword)EOF; - } - } -} - -void Parser::listSubtract(ParamElem a[], ParamElem b[]) { - for (int i = 0; a[i].code != (Aword)EOF; i++) - if (listContains(b, a[i].code)) - a[i].code = 0; // Mark empty - - listCompact(a); -} - -void Parser::unambig(ParamElem plst[]) { - int i; - bool found = false; // Adjective or noun found? - static ParamElem *refs; // Entities referenced by word - static ParamElem *savlst; // Saved list for backup at EOF - int firstWord, lastWord; // The words the player used - - if (refs == nullptr) - refs = new ParamElem[MAXENTITY + 1]; - - if (savlst == nullptr) - savlst = new ParamElem[MAXENTITY + 1]; - - if (isLiteral(wrds[wrdidx])) { - // Transform the word into a reference to the literal value - plst[0].code = wrds[wrdidx++] - dictsize + LITMIN; - plst[0].firstWord = (Aword)EOF; // No words used! - plst[1].code = (Aword)EOF; - return; - } - - plst[0].code = (Aword)EOF; // Make empty - - if (isIt(wrds[wrdidx])) { - wrdidx++; - - // Use last object in previous command! - for (i = listLength(pparams)-1; i >= 0 && (pparams[i].code == 0 || pparams[i].code >= LITMIN); i--); - - if (i < 0) - _vm->printError(M_WHAT_IT); - - if (!isHere(pparams[i].code)) { - params[0].code = pparams[i].code; - params[0].firstWord = (Aword)EOF; - params[1].code = (Aword)EOF; - _vm->printError(M_NO_SUCH); - } - - plst[0] = pparams[i]; - plst[0].firstWord = (Aword)EOF; // No words used! - plst[1].code = (Aword)EOF; - return; - } - - firstWord = wrdidx; - - while (wrds[wrdidx] != EOF && isAdj(wrds[wrdidx])) { - // If this word can be a noun and there is no noun following break loop - if (isNoun(wrds[wrdidx]) && (wrds[wrdidx+1] == EOF || !isNoun(wrds[wrdidx+1]))) - break; - - listCopyFromDictionary(refs, (Aword *)addrTo(dict[wrds[wrdidx]].adjrefs)); - listCopy(savlst, plst); // To save it for backtracking - - if (found) - listIntersection(plst, refs); - else { - listCopy(plst, refs); - found = true; - } - - wrdidx++; - } - - if (wrds[wrdidx] != EOF) { - if (isNoun(wrds[wrdidx])) { - listCopyFromDictionary(refs, (Aword *)addrTo(dict[wrds[wrdidx]].nounrefs)); - if (found) - listIntersection(plst, refs); - else { - listCopy(plst, refs); - found = true; - } - - wrdidx++; - } else - _vm->printError(M_NOUN); - } else if (found) { - if (isNoun(wrds[wrdidx-1])) { - // Perhaps the last word was also a noun? - listCopy(plst, savlst); // Restore to before last adjective - listCopyFromDictionary(refs, (Aword *)addrTo(dict[wrds[wrdidx-1]].nounrefs)); - - if (plst[0].code == (Aword)EOF) - listCopy(plst, refs); - else - listIntersection(plst, refs); - } else - _vm->printError(M_NOUN); - } - - lastWord = wrdidx - 1; - - // Allow remote objects, but resolve ambiguities by presence - if (listLength(plst) > 1) { - for (i=0; plst[i].code != (Aword)EOF; i++) - if (!isHere(plst[i].code)) - plst[i].code = 0; - - listCompact(plst); - } - - if (listLength(plst) > 1 || (found && listLength(plst) == 0)) { - params[0].code = 0; /* Just make it anything != EOF */ - params[0].firstWord = firstWord; /* Remember words for errors below */ - params[0].lastWord = lastWord; - params[1].code = (Aword)EOF; /* But be sure to terminate */ - - if (listLength(plst) > 1) - _vm->printError(M_WHICH_ONE); - else if (found && listLength(plst) == 0) - _vm->printError(M_NO_SUCH); - } else { - plst[0].firstWord = firstWord; - plst[0].lastWord = lastWord; - } -} - -void Parser::simple(ParamElem olst[]) { - static ParamElem *tlst = nullptr; - int savidx = wrdidx; - bool savplur = false; - int i; - - if (tlst == nullptr) - tlst = new ParamElem[MAXENTITY + 1]; - - tlst[0].code = (Aword)EOF; - - for (;;) { - if (isThem(wrds[wrdidx])) { - plural = true; - - for (i = 0; pmlst[i].code != (Aword)EOF; i++) - if (!isHere(pmlst[i].code)) - pmlst[i].code = 0; - - listCompact(pmlst); - - if (listLength(pmlst) == 0) - _vm->printError(M_WHAT_THEM); - - listCopy(olst, pmlst); - olst[0].firstWord = (Aword)EOF; // No words used - wrdidx++; - } else { - unambig(olst); // Look for unambigous noun phrase - - if (listLength(olst) == 0) { // Failed! - listCopy(olst, tlst); - wrdidx = savidx; - plural = savplur; - return; - } - } - - listMerge(tlst, olst); - - if (wrds[wrdidx] != EOF - && (isConj(wrds[wrdidx]) - && (isAdj(wrds[wrdidx+1]) || isNoun(wrds[wrdidx+1])))) { - // More parameters in a conjunction separated list ? - savplur = plural; - savidx = wrdidx; - wrdidx++; - plural = true; - } else { - listCopy(olst, tlst); - return; - } - } -} - -void Parser::complex(ParamElem olst[]) { - // Above this procedure we can use the is* tests, but not below since - // they work on words.Below all is converted to indices into the - // entity tables.Particularly this goes for literals... - - static ParamElem *alst = nullptr; - - if (alst == nullptr) - alst = new ParamElem[MAXENTITY + 1]; - - if (isAll(wrds[wrdidx])) { - plural = true; - buildall(alst); // Build list of all objects - wrdidx++; - if (wrds[wrdidx] != EOF && isBut(wrds[wrdidx])) { - wrdidx++; - simple(olst); - - if (listLength(olst) == 0) - _vm->printError(M_AFTER_BUT); - - listSubtract(alst, olst); - if (listLength(alst) == 0) - _vm->printError(M_NOT_MUCH); - } - - listCopy(olst, alst); - allLength = listLength(olst); - } else - simple(olst); // Look for simple noun group -} - -bool Parser::claCheck(ClaElem *cla) { - bool ok = false; - - if ((cla->classes & (Aword)CLA_OBJ) != 0) - ok = ok || isObj(params[cla->code - 1].code); - if ((cla->classes & (Aword)CLA_CNT) != 0) - ok = ok || isCnt(params[cla->code - 1].code); - if ((cla->classes & (Aword)CLA_ACT) != 0) - ok = ok || isAct(params[cla->code - 1].code); - if ((cla->classes & (Aword)CLA_NUM) != 0) - ok = ok || isNum(params[cla->code - 1].code); - if ((cla->classes & (Aword)CLA_STR) != 0) - ok = ok || isStr(params[cla->code - 1].code); - if ((cla->classes & (Aword)CLA_COBJ) != 0) - ok = ok || (isCnt(params[cla->code - 1].code) && isObj(params[cla->code - 1].code)); - if ((cla->classes & (Aword)CLA_CACT) != 0) - ok = ok || (isCnt(params[cla->code - 1].code) && isAct(params[cla->code - 1].code)); - - return ok; -} - -void Parser::resolve(ParamElem plst[]) { - if (allLength > 0) - return; // ALL has already done this - - // Resolve ambiguities by presence - for (int i = 0; plst[i].code != (Aword)EOF; i++) { - if (plst[i].code < LITMIN) { // Literals are always 'here' - if (!isHere(plst[i].code)) { - params[0] = plst[i]; // Copy error param as first one for message - params[1].code = (Aword)EOF; // But be sure to terminate - _vm->printError(M_NO_SUCH); - } - } - } -} - -bool Parser::endOfTable(StxElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -bool Parser::endOfTable(ElmElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -bool Parser::endOfTable(ClaElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -bool Parser::endOfTable(VrbElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -bool Parser::endOfTable(AltElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -bool Parser::endOfTable(ChkElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -bool Parser::endOfTable(WrdElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -AltElem *Parser::findalt(Aword vrbsadr, Aword param) { - VrbElem *vrb; - AltElem *alt; - - if (vrbsadr == 0) - return nullptr; - - for (vrb = (VrbElem *)addrTo(vrbsadr); !endOfTable(vrb); vrb++) { - if ((int)vrb->code == _vm->cur.vrb) { - for (alt = (AltElem *)addrTo(vrb->alts); !endOfTable(alt); alt++) - if (alt->param == param || alt->param == 0) - return alt; - return nullptr; - } - } - - return nullptr; -} - -bool Parser::trycheck(Aaddr adr, bool act) { - ChkElem *chk = (ChkElem *)addrTo(adr); - - if (chk->exp == 0) { - _vm->_interpreter->interpret(chk->stms); - return false; - } else { - while (!endOfTable(chk)) { - _vm->_interpreter->interpret(chk->exp); - if (!(Abool)_vm->_stack->pop()) { - if (act) - _vm->_interpreter->interpret(chk->stms); - return false; - } - chk++; - } - return true; - } -} - -bool Parser::possible() { - AltElem *alt[MAXPARAMS + 2]; // List of alt-pointers, one for each param - int i; // Parameter index - - _vm->fail = false; - alt[0] = findalt(_vm->header->vrbs, 0); - - // Perform global checks - if (alt[0] != 0 && alt[0]->checks != 0) { - if (!trycheck(alt[0]->checks, false)) - return false; - if (_vm->fail) - return false; - } - - // Now CHECKs in this location - alt[1] = findalt(locs[_vm->cur.loc - LOCMIN].vrbs, 0); - if (alt[1] != 0 && alt[1]->checks != 0) - if (!trycheck(alt[1]->checks, false)) - return false; - - for (i = 0; params[i].code != (Aword)EOF; i++) { - alt[i + 2] = findalt(objs[params[i].code - OBJMIN].vrbs, i + 1); - // CHECKs in a possible parameter - if (alt[i + 2] != 0 && alt[i + 2]->checks != 0) - if (!trycheck(alt[i + 2]->checks, false)) - return false; - } - - for (i = 0; i < 2 || params[i - 2].code != (Aword)EOF; i++) - if (alt[i] != 0 && alt[i]->action != 0) - break; - if (i >= 2 && params[i - 2].code == (Aword)EOF) - // Didn't find any code for this verb/object combination - return false; - else - return true; -} - -void Parser::tryMatch(ParamElem mlstArr[]) { - ElmElem *elms; // Pointer to element list - StxElem *stx; // Pointer to syntax list - ClaElem *cla; // Pointer to class definitions - bool anyPlural = false; // Any parameter that was plural? - int i, p; - static ParamElem *tlst = nullptr; // List of params found by complex() - static bool *checked = nullptr; // Corresponding parameter checked? - - if (tlst == nullptr) { - tlst = new ParamElem[MAXENTITY + 1]; - checked = new bool[MAXENTITY + 1]; - } - - for (stx = stxs; !endOfTable(stx); stx++) - if ((int)stx->code == vrbcode) - break; - - if (endOfTable(stx)) - _vm->printError(M_WHAT); - - elms = (ElmElem *) addrTo(stx->elms); - - while (true) { - // End of input? - if (wrds[wrdidx] == EOF || isConj(wrds[wrdidx])) { - while (!endOfTable(elms) && elms->code != (Aword)EOS) - elms++; - - if (endOfTable(elms)) - _vm->printError(M_WHAT); - else - break; - } else { - // A preposition? - if (isPrep(wrds[wrdidx])) { - while (!endOfTable(elms) && elms->code != dict[wrds[wrdidx]].code) - elms++; - - if (endOfTable(elms)) - _vm->printError(M_WHAT); - else - wrdidx++; - } else { - // Must be a parameter! - while (!endOfTable(elms) && elms->code != 0) - elms++; - - if (endOfTable(elms)) - _vm->printError(M_WHAT); - - // Get it! - plural = false; - complex(tlst); - - if (listLength(tlst) == 0) // No object!? - _vm->printError(M_WHAT); - - if ((elms->flags & OMNIBIT) == 0) // Omnipotent parameter? - resolve(tlst); // If its not an omnipotent parameter, resolve by presence - - if (plural) { - if ((elms->flags & MULTIPLEBIT) == 0) // Allowed multiple? - _vm->printError(M_MULTIPLE); - else { - // Mark this as the multiple position in which to insert - // actual parameter values later - params[paramidx++].code = 0; - listCopy(mlstArr, tlst); - anyPlural = true; - } - } else - params[paramidx++] = tlst[0]; - - params[paramidx].code = (Aword)EOF; - } - - elms = (ElmElem *) addrTo(elms->next); - } - } - - // Now perform class checks - if (elms->next == 0) // No verb code, verb not declared! - _vm->printError(M_CANT0); - - for (p = 0; params[p].code != (Aword)EOF; p++) /* Mark all parameters unchecked */ - checked[p] = false; - - for (cla = (ClaElem *) addrTo(elms->next); !endOfTable(cla); cla++) { - if (params[cla->code - 1].code == 0) { - // This was a multiple parameter, so check all and remove failing - for (i = 0; mlstArr[i].code != (Aword)EOF; i++) { - params[cla->code-1] = mlstArr[i]; - if (!claCheck(cla)) { - // Multiple could be both an explicit list of params and an ALL - if (allLength == 0) { - char marker[80]; - // It wasn't ALL, we need to say something about it, so - // prepare a printout with $1/2/3 - sprintf(marker, "($%ld)", (unsigned long) cla->code); - _vm->output(marker); - _vm->_interpreter->interpret(cla->stms); - _vm->paragraph(); - } - - mlstArr[i].code = 0; // In any case remove it from the list - } - } - - params[cla->code - 1].code = 0; - } else { - if (!claCheck(cla)) { - _vm->_interpreter->interpret(cla->stms); - _vm->printError(MSGMAX); // Return to player without saying anything - } - } - - checked[cla->code - 1] = true; // Remember that it's already checked - } - - // Now check the rest of the parameters, must be objects - for (p = 0; params[p].code != (Aword)EOF; p++) { - if (!checked[p]) { - if (params[p].code == 0) { - // This was a multiple parameter, check all and remove failing - for (i = 0; mlstArr[i].code != (Aword)EOF; i++) { - if (mlstArr[i].code != 0 && !isObj(mlstArr[i].code)) // Skip any empty slots - mlstArr[i].code = 0; - } - } else if (!isObj(params[p].code)) - _vm->printError(M_CANT0); - } - } - - // Set verb code - _vm->cur.vrb = ((Aword *) cla)[1]; // Take first word after end of table! - - // Finally, if ALL was used, try to find out what was applicable - if (allLength > 0) { - for (p = 0; params[p].code != 0; p++); // Find multiple marker - - for (i = 0; i < allLength; i++) { - if (mlstArr[i].code != 0) { // Already empty? - params[p] = mlstArr[i]; - - if (!possible()) - mlstArr[i].code = 0; // Remove this from list - } - } - - params[p].code = 0; // Restore multiple marker - listCompact(mlstArr); - - if (listLength(mlstArr) == 0) { - params[0].code = (Aword)EOF; - _vm->printError(M_WHAT_ALL); - } - } else if (anyPlural) { - listCompact(mlstArr); - - // If there where multiple parameters but non left, exit without a - // word, assuming we have already said enough - if (listLength(mlstArr) == 0) - _vm->printError(MSGMAX); - } - - plural = anyPlural; // Remember that we found plural objects -} - -void Parser::match(ParamElem *mlstArr) { - tryMatch(mlstArr); // try to understand what the user said - - if (wrds[wrdidx] != EOF && !isConj(wrds[wrdidx])) - _vm->printError(M_WHAT); - if (wrds[wrdidx] != EOF) // More on this line? - wrdidx++; // If so skip the AND -} - -void Parser::action(ParamElem plst[]) { - int i, mpos; - char marker[10]; - - if (plural) { - // The code == 0 means this is a multiple position. We must loop - // over this position (and replace it by each present in the plst) - for (mpos = 0; params[mpos].code != 0; mpos++); // Find multiple position - - sprintf(marker, "($%d)", mpos + 1); // Prepare a printout with $1/2/3 - - for (i = 0; plst[i].code != (Aword)EOF; i++) { - params[mpos] = plst[i]; - _vm->output(marker); - //do_it(); // TODO - - if (plst[i + 1].code != (Aword)EOF) - _vm->paragraph(); - } - - params[mpos].code = 0; - } //else // TODO - //do_it(); -} - -void Parser::parse() { - if (mlst == nullptr) { // Allocate large enough paramlists - mlst = new ParamElem[MAXENTITY + 1]; - mlst[0].code = (Aword)EOF; - pmlst = new ParamElem[MAXENTITY + 1]; - params = new ParamElem[MAXENTITY + 1]; - params[0].code = (Aword)EOF; - pparams = new ParamElem[MAXENTITY + 1]; - } - - if (wrds[wrdidx] == EOF) { - wrdidx = 0; - scan(); - } else if (false/*anyOutput*/) // TODO - _vm->paragraph(); - - allLength = 0; - paramidx = 0; - listCopy(pparams, params); - params[0].code = (Aword)EOF; - listCopy(pmlst, mlst); - mlst[0].code = (Aword)EOF; - - if (isVerb(wrds[wrdidx])) { - vrbwrd = wrds[wrdidx]; - vrbcode = dict[vrbwrd].code; - wrdidx++; - match(mlst); - action(mlst); // mlst contains possible multiple params - } else { - params[0].code = (Aword)EOF; - pmlst[0].code = (Aword)EOF; - nonverb(); - } -} - -} // End of namespace Alan2 -} // End of namespace Glk diff --git a/engines/glk/alan2/parse.h b/engines/glk/alan2/parse.h deleted file mode 100644 index c5b223baa0..0000000000 --- a/engines/glk/alan2/parse.h +++ /dev/null @@ -1,185 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_PARSE -#define GLK_ALAN2_PARSE - -namespace Glk { -namespace Alan2 { - -#define LISTLEN 100 - -class Parser { -public: - Parser(); - - /** - * Parse a new player command - */ - void parse(); - -private: - void unknown(char *inputStr); - int lookup(char *wrd); - char *gettoken(char *tokenBuffer); - void agetline(); - void scan(); - - /** - * Search for a non-verb command - */ - void nonverb(); - - Abool objhere(Aword obj); - Aword objloc(Aword obj); - Abool isHere(Aword id); - Aword where(Aword id); - - /** - * Build a list of objects matching 'all' - */ - void buildall(ParamElem list[]); - - void listCopy(ParamElem a[], ParamElem b[]); - bool listContains(ParamElem l[], Aword e); - void listIntersection(ParamElem a[], ParamElem b[]); - - /** - * Copy the refs (in dictionary) to a paramList - */ - void listCopyFromDictionary(ParamElem p[], Aword r[]); - - int listLength(ParamElem a[]); - - /** - * Compact a list, i.e remove any nullptr elements - */ - void listCompact(ParamElem a[]); - - /** - * Merge the paramElems of one list into the first - */ - void listMerge(ParamElem a[], ParamElem b[]); - - /** - * Subtract two lists - */ - void listSubtract(ParamElem a[], ParamElem b[]); - - /** - * Match an unambigous object reference - */ - void unambig(ParamElem plst[]); - - /** - * Match a simple verb command - */ - void simple(ParamElem olst[]); - - /** - * Match a complex verb command - */ - void complex(ParamElem olst[]); - - bool claCheck(ClaElem *cla); - - /** - * In case the syntax did not indicate omnipotent powers (allowed - * access to remote object), we need to remove non - present parameters - */ - void resolve(ParamElem plst[]); - - bool endOfTable(StxElem *addr); - bool endOfTable(ElmElem *addr); - bool endOfTable(ClaElem *addr); - bool endOfTable(VrbElem *addr); - bool endOfTable(AltElem *addr); - bool endOfTable(ChkElem *addr); - bool endOfTable(WrdElem *addr); - - /** - * Find the verb alternative wanted in a verb list and return - * the address to it. - * - * @param vrbsadr Address to start of list - * @param param Which parameter to match - */ - AltElem *findalt(Aword vrbsadr, Aword param); - - /** - * Tries a check, returns TRUE if it passed, FALSE otherwise - * - * @param adr ACODE address to check table - * @param act Act if it fails? - */ - bool trycheck(Aaddr adr, bool act); - - /** - * Check if current action is possible according to the CHECKs. - */ - bool possible(); - - void tryMatch(ParamElem mlstArr[]); - void match(ParamElem *mlstArr); - - /** - * Execute all activities commanded. Handles possible multiple actions - * such as THEM or lists of objects. - */ - void action(ParamElem plst[]); - - // TODO: Initialize / move these - int wrds[LISTLEN / 2]; // List of parsed words - int wrdidx; // and an index into it - - bool plural; - - // Syntax Parameters - int paramidx; // Index in params - ParamElem *params; // List of params - static ParamElem *pparams; // Previous parameter list - static ParamElem *mlst; // Multiple objects list - static ParamElem *pmlst; // Previous multiple list - - StxElem *stxs; // Syntax table pointer - LocElem *locs; // Location table pointer - - // Literals - LitElem litValues[MAXPARAMS + 1]; - - // What did the user say? - int vrbwrd; // The word he used - int vrbcode; // The code for that verb - - bool eol; // Looking at End of line? Yes, initially - char *token; - - WrdElem *dict; // Dictionary pointer - int dictsize; - - int allLength; // No. of objects matching 'all' -}; - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/alan2/rules.cpp b/engines/glk/alan2/rules.cpp deleted file mode 100644 index 973bd2389c..0000000000 --- a/engines/glk/alan2/rules.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "glk/alan2/acode.h" -#include "glk/alan2/interpreter.h" -#include "glk/alan2/rules.h" -#include "glk/alan2/types.h" -#include "common/debug.h" - -namespace Glk { -namespace Alan2 { - -// TODO: Refactor these into debug flags -const bool trcflg = false; -const bool stpflg = false; - -void Rules::parseRules() { - bool change = true; - int i; - - for (i = 1; !endOfTable(&_ruls[i - 1]); i++) - _ruls[i - 1].run = false; - - while (change) { - change = false; - for (i = 1; !endOfTable(&_ruls[i - 1]); i++) { - if (!_ruls[i - 1].run) { - if (trcflg) { - debug("\n\n"); - } - - _interpreter->interpret(_ruls[i - 1].exp); - - if (_stack->pop()) { - change = true; - _ruls[i - 1].run = true; - - if (trcflg) { - if (!stpflg) { - debug(", Executing:>\n"); - } else { - debug("\nRULE %d (at ", i); - //debugsay(cur.loc); // TODO - debug("), Executing:>\n"); - } - } - - _interpreter->interpret(_ruls[i - 1].stms); - - } else if (trcflg && !stpflg) { - debug(":>\n"); - } - } - } - } -} - -bool Rules::endOfTable(RulElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -} // End of namespace Alan2 -} // End of namespace Glk diff --git a/engines/glk/alan2/rules.h b/engines/glk/alan2/rules.h deleted file mode 100644 index 194c7d0733..0000000000 --- a/engines/glk/alan2/rules.h +++ /dev/null @@ -1,51 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_RULES -#define GLK_ALAN2_RULES - -#include "common/stack.h" -#include "glk/alan2/alan2.h" -#include "glk/alan2/types.h" - -namespace Glk { -namespace Alan2 { - -class Interpreter; - -class Rules { -public: - Rules(RulElem *rules, Alan2Stack *stack, Interpreter *interpreter) : _ruls(rules), _stack(stack), _interpreter(interpreter) {} - void parseRules(); - -private: - bool endOfTable(RulElem *addr); - - RulElem *_ruls; - Alan2Stack *_stack; - Interpreter *_interpreter; -}; - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/alan2/saveload.cpp b/engines/glk/alan2/saveload.cpp deleted file mode 100644 index 838c2588a1..0000000000 --- a/engines/glk/alan2/saveload.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#include "common/savefile.h" -#include "glk/alan2/acode.h" -#include "glk/alan2/alan2.h" -#include "glk/alan2/saveload.h" -#include "glk/alan2/types.h" - -namespace Glk { -namespace Alan2 { - -void SaveLoad::save() { - uint i; - Common::SaveFileManager *saveFileMan = _vm->getSaveFileManager(); - Common::OutSaveFile *saveFile = nullptr; - Common::String str; - AtrElem *atr; - - // TODO -#if 0 - frefid_t fref = glk_fileref_create_by_prompt(fileusage_SavedGame, filemode_Write, 0); - if (fref == nullptr) - _vm->printError(M_SAVEFAILED); - - strcpy(str, garglk_fileref_get_name(fref)); - glk_fileref_destroy(fref); -#endif - - if (str.empty()) - str = _prevSaveName; - - _vm->col = 1; - - // TODO -#if 0 - if ((savfil = fopen(str, READ_MODE)) != nullptr) - // It already existed - if (!confirm(M_SAVEOVERWRITE)) - _vm->printError(MSGMAX); // Return to player without saying anything - - if ((savfil = fopen(str, WRITE_MODE)) == nullptr) - _vm->printError(M_SAVEFAILED); -#endif - - saveFile = saveFileMan->openForSaving(str); - - _prevSaveName = str; - - // Save version of interpreter and name of game - saveFile->write(_vm->header->vers, sizeof(Aword)); - saveFile->writeString(_gameName); - saveFile->writeByte('\0'); - // Save current values - saveFile->write(&_vm->cur, sizeof(_vm->cur)); - - // Save actors - for (i = ACTMIN; i <= ACTMAX; i++) { - saveFile->writeUint32LE(_actors[i - ACTMIN].loc); - saveFile->writeUint32LE(_actors[i - ACTMIN].script); - saveFile->writeUint32LE(_actors[i - ACTMIN].step); - saveFile->writeUint32LE(_actors[i - ACTMIN].count); - if (_actors[i - ACTMIN].atrs) - for (atr = (AtrElem *)addrTo(_actors[i - ACTMIN].atrs); !endOfTable(atr); atr++) - saveFile->writeUint32LE(atr->val); - } - - // Save locations - for (i = LOCMIN; i <= LOCMAX; i++) { - saveFile->writeUint32LE(_locations[i - LOCMIN].describe); - if (_locations[i - LOCMIN].atrs) - for (atr = (AtrElem *)addrTo(_locations[i - LOCMIN].atrs); !endOfTable(atr); atr++) - saveFile->writeUint32LE(atr->val); - } - - // Save objects - for (i = OBJMIN; i <= OBJMAX; i++) { - saveFile->writeUint32LE(_objects[i - OBJMIN].loc); - if (_objects[i - OBJMIN].atrs) - for (atr = (AtrElem *)addrTo(_objects[i - OBJMIN].atrs); !endOfTable(atr); atr++) - saveFile->writeUint32LE(atr->val); - } - - // Save the event queue - _events[*_eventTop].time = 0; // Mark the top - for (i = 0; i < (uint)*_eventTop + 1; i++) - saveFile->write(&_events[i], sizeof(_events[0])); - - // Save scores - for (i = 0; _vm->scores[i] != EOF; i++) - saveFile->writeUint32LE(_vm->scores[i]); - - delete saveFile; -} - -void SaveLoad::restore() { - uint i; - Common::SaveFileManager *saveFileMan = _vm->getSaveFileManager(); - Common::InSaveFile *saveFile = nullptr; - Common::String str; - AtrElem *atr; - char savedVersion[4]; - char savedName[256]; - - // TODO -#if 0 - frefid_t fref = glk_fileref_create_by_prompt(fileusage_SavedGame, filemode_Read, 0); - if (fref == nullptr) - _vm->printError(M_SAVEFAILED); - - strcpy(str, garglk_fileref_get_name(fref)); - glk_fileref_destroy(fref); -#endif - - _vm->col = 1; - - if (str.empty()) - str = _prevSaveName; // Use the name temporarily - - if ((saveFile = saveFileMan->openForLoading(str)) == nullptr) { - _vm->printError(M_SAVEMISSING); - return; - } - - _prevSaveName = str; // Save it for future use - - saveFile->read(savedVersion, sizeof(Aword)); - - // 4f - save file version check doesn't seem to work on PC's! - if (strncmp(savedVersion, _vm->header->vers, 4)) { - delete saveFile; - _vm->printError(M_SAVEVERS); - return; - } - - i = 0; - - while ((savedName[i++] = saveFile->readByte()) != '\0'); - - if (savedName != _gameName) { - delete saveFile; - _vm->printError(M_SAVENAME); - return; - } - - // Restore current values - saveFile->read(&_vm->cur, sizeof(_vm->cur)); - - // Restore actors - for (i = ACTMIN; i <= ACTMAX; i++) { - _actors[i - ACTMIN].loc = saveFile->readUint32LE(); - _actors[i - ACTMIN].script = saveFile->readUint32LE(); - _actors[i - ACTMIN].step = saveFile->readUint32LE(); - _actors[i - ACTMIN].count = saveFile->readUint32LE(); - - if (_actors[i - ACTMIN].atrs) - for (atr = (AtrElem *)addrTo(_actors[i - ACTMIN].atrs); !endOfTable(atr); atr++) - atr->val = saveFile->readUint32LE(); - } - - // Restore locations - for (i = LOCMIN; i <= LOCMAX; i++) { - _locations[i - LOCMIN].describe = saveFile->readUint32LE(); - if (_locations[i - LOCMIN].atrs) - for (atr = (AtrElem *)addrTo(_locations[i - LOCMIN].atrs); !endOfTable(atr); atr++) - atr->val = saveFile->readUint32LE(); - } - - // Restore objects - for (i = OBJMIN; i <= OBJMAX; i++) { - _objects[i - OBJMIN].loc = saveFile->readUint32LE(); - if (_objects[i - OBJMIN].atrs) - for (atr = (AtrElem *)addrTo(_objects[i - OBJMIN].atrs); !endOfTable(atr); atr++) - atr->val = saveFile->readUint32LE(); - } - - // Restore the event queue - *_eventTop = 0; - do { - saveFile->read(&_events[*_eventTop], sizeof(_events[0])); - (*_eventTop)++; - } while (_events[*_eventTop - 1].time != 0); - - (*_eventTop)--; - - // Restore scores - for (i = 0; _vm->scores[i] != EOF; i++) - _vm->scores[i] = saveFile->readUint32LE(); - - delete saveFile; -} - -bool SaveLoad::endOfTable(AtrElem *addr) { - Aword *x = (Aword *)addr; - return *x == (Aword)EOF; -} - -} // End of namespace Alan2 -} // End of namespace Glk diff --git a/engines/glk/alan2/saveload.h b/engines/glk/alan2/saveload.h deleted file mode 100644 index 32a02bb5c4..0000000000 --- a/engines/glk/alan2/saveload.h +++ /dev/null @@ -1,55 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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. - * - */ - -#ifndef GLK_ALAN2_SAVELOAD -#define GLK_ALAN2_SAVELOAD - -#include "common/scummsys.h" -#include "glk/alan2/types.h" - -namespace Glk { -namespace Alan2 { - -class SaveLoad { -public: - SaveLoad(Common::String &gameName, ActElem *actors, LocElem *locations, ObjElem *objects, EvtqElem *events, int *eventTop) : - _gameName(gameName), _actors(actors), _locations(locations), _objects(objects), _events(events), _eventTop(eventTop) {} - void save(); - void restore(); -private: - bool endOfTable(AtrElem *addr); - - Common::String _prevSaveName; - - // Save state related variables - Common::String _gameName; - ActElem *_actors; - LocElem *_locations; - ObjElem *_objects; - EvtqElem *_events; - int *_eventTop; -}; - -} // End of namespace Alan2 -} // End of namespace Glk - -#endif diff --git a/engines/glk/module.mk b/engines/glk/module.mk index 19dc6c9d97..bfda72d34a 100644 --- a/engines/glk/module.mk +++ b/engines/glk/module.mk @@ -32,13 +32,7 @@ MODULE_OBJS := \ advsys/glk_interface.o \ advsys/vm.o \ alan2/alan2.o \ - alan2/decode.o \ alan2/detection.o \ - alan2/execute.o \ - alan2/interpreter.o \ - alan2/parse.o \ - alan2/rules.o \ - alan2/saveload.o \ frotz/bitmap_font.o \ frotz/config.o \ frotz/detection.o \ -- cgit v1.2.3