Initial commit
This commit is contained in:
297
engines/glk/alan2/acode.h
Normal file
297
engines/glk/alan2/acode.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_ACODE
|
||||
#define GLK_ALAN2_ACODE
|
||||
|
||||
#include "common/stream.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<<VALUEBITS) - 1) /* Highest value possible */
|
||||
|
||||
/* Half and quarter points in the code value range */
|
||||
#define ONEQUARTER (TOPVALUE/4+1) /* Point after first quarter */
|
||||
#define HALF (2*ONEQUARTER) /* Point after first half */
|
||||
#define THREEQUARTER (3*ONEQUARTER) /* Point after third quarter */
|
||||
|
||||
|
||||
/* AMACHINE Word Classes */
|
||||
typedef int WrdKind;
|
||||
#define WRD_SYN 0 /* 1 - Synonym */
|
||||
#define WRD_ADJ 1 /* 2 - Adjective */
|
||||
#define WRD_ALL 2 /* 4 - All */
|
||||
#define WRD_BUT 3 /* 8 - But */
|
||||
#define WRD_CONJ 4 /* 16 - Conjunction */
|
||||
#define WRD_PREP 5 /* 32 - Preposition */
|
||||
#define WRD_DIR 6 /* 64 - Direction */
|
||||
#define WRD_IT 7 /* 128 - It */
|
||||
#define WRD_NOISE 8 /* 256 - Noise word */
|
||||
#define WRD_NOUN 9 /* 512 - Noun */
|
||||
#define WRD_ACT 10 /* 1024 - Actor */
|
||||
#define WRD_THEM 11 /* 2048 - Them */
|
||||
#define WRD_VRB 12 /* 4096 - Verb */
|
||||
#define WRD_CLASSES 13
|
||||
|
||||
|
||||
|
||||
/* Syntax element classifications */
|
||||
// End of data
|
||||
#define EOD ((uint32)-1)
|
||||
// End of syntax
|
||||
#define EOS ((uint32)-2)
|
||||
|
||||
/* Syntax element flag bits */
|
||||
#define MULTIPLEBIT 0x1
|
||||
#define OMNIBIT 0x2
|
||||
|
||||
|
||||
/* Parameter Classes */
|
||||
enum ClaKind { /* NOTE! These must have the same order as */
|
||||
CLA_OBJ = 1, /* the name classes in NAM.H */
|
||||
CLA_CNT = (int)CLA_OBJ << 1,
|
||||
CLA_ACT = (int)CLA_CNT << 1,
|
||||
CLA_NUM = (int)CLA_ACT << 1,
|
||||
CLA_STR = (int)CLA_NUM << 1,
|
||||
CLA_COBJ = (int)CLA_STR << 1,
|
||||
CLA_CACT = (int)CLA_COBJ << 1
|
||||
};
|
||||
|
||||
|
||||
/* Verb Qualifiers */
|
||||
enum QualClass {
|
||||
Q_DEFAULT,
|
||||
Q_AFTER,
|
||||
Q_BEFORE,
|
||||
Q_ONLY
|
||||
};
|
||||
|
||||
|
||||
/* The AMACHINE Operations */
|
||||
enum OpClass {
|
||||
C_CONST,
|
||||
C_STMOP,
|
||||
C_CURVAR
|
||||
};
|
||||
|
||||
enum InstClass {
|
||||
I_PRINT, /* Print a string from the text file */
|
||||
I_QUIT,
|
||||
I_LOOK,
|
||||
I_SAVE,
|
||||
I_RESTORE,
|
||||
I_LIST, /* List contents of a container */
|
||||
I_EMPTY,
|
||||
I_SCORE,
|
||||
I_VISITS,
|
||||
I_SCHEDULE,
|
||||
I_CANCEL,
|
||||
I_LOCATE,
|
||||
I_MAKE,
|
||||
I_SET, /* Set a numeric attribute to the */
|
||||
/* value on top of stack */
|
||||
I_STRSET, /* Set a string valued attribute to a */
|
||||
/* copy of the string on top of stack, */
|
||||
/* deallocate current contents first */
|
||||
I_GETSTR, /* Get a string contents from text */
|
||||
/* file, create a copy and push it */
|
||||
/* on top of stack */
|
||||
I_INCR, /* Increment an attribute */
|
||||
I_DECR, /* Decrement a numeric attribute */
|
||||
I_USE,
|
||||
I_IN,
|
||||
I_DESCRIBE,
|
||||
I_SAY,
|
||||
I_SAYINT,
|
||||
I_SAYSTR,
|
||||
I_IF,
|
||||
I_ELSE,
|
||||
I_ENDIF,
|
||||
I_ATTRIBUTE,
|
||||
I_STRATTR, /* Push a copy of a string attribute */
|
||||
I_HERE,
|
||||
I_NEAR,
|
||||
I_WHERE,
|
||||
I_AND,
|
||||
I_OR,
|
||||
I_NE,
|
||||
I_EQ,
|
||||
I_STREQ, /* String compare */
|
||||
I_STREXACT,
|
||||
I_LE,
|
||||
I_GE,
|
||||
I_LT,
|
||||
I_GT,
|
||||
I_PLUS,
|
||||
I_MINUS,
|
||||
I_MULT,
|
||||
I_DIV,
|
||||
I_NOT,
|
||||
I_UMINUS,
|
||||
I_RND,
|
||||
I_SUM, /* SUM-aggregate */
|
||||
I_MAX, /* MAX-aggregate */
|
||||
I_COUNT, /* COUNT-aggregate */
|
||||
I_RETURN,
|
||||
I_SYSTEM,
|
||||
I_RESTART, /* INTRODUCED: v2.7 */
|
||||
I_BTW, /* INTRODUCED: v2.8 */
|
||||
I_CONTAINS, /* -""- */
|
||||
I_DEPSTART, /* -""- */
|
||||
I_DEPCASE, /* -""- */
|
||||
I_DEPEXEC, /* -""- */
|
||||
I_DEPELSE, /* -""- */
|
||||
I_DEPEND /* -""- */
|
||||
};
|
||||
|
||||
|
||||
enum VarClass {
|
||||
V_PARAM,
|
||||
V_CURLOC,
|
||||
V_CURACT,
|
||||
V_CURVRB,
|
||||
V_SCORE
|
||||
};
|
||||
|
||||
|
||||
#define I_CLASS(x) ((x)>>28)
|
||||
#define I_OP(x) ((x&0x8000000)?(x)|0x0f0000000:(x)&0x0fffffff)
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
/**
|
||||
* Game header
|
||||
*/
|
||||
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 - Unused - Length of a page */
|
||||
Aword pagwidth; /* 05 - Unused - 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 */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
/* 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
|
||||
197
engines/glk/alan2/alan2.cpp
Normal file
197
engines/glk/alan2/alan2.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/alan2.h"
|
||||
#include "glk/alan2/exe.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "common/system.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/translation.h"
|
||||
#include "common/error.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
#include "glk/glk.h"
|
||||
#include "glk/streams.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
Alan2 *g_vm = nullptr;
|
||||
|
||||
Alan2::Alan2(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
|
||||
vm_exited_cleanly(false), _restartFlag(false), _saveSlot(-1), _pendingLook(false) {
|
||||
g_vm = this;
|
||||
txtfil = nullptr;
|
||||
logfil = nullptr;
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
void Alan2::runGame() {
|
||||
if (initialize())
|
||||
Glk::Alan2::run();
|
||||
|
||||
deinitialize();
|
||||
}
|
||||
|
||||
bool Alan2::initialize() {
|
||||
// Set up adventure name
|
||||
_advName = getFilename();
|
||||
if (_advName.size() > 4 && _advName[_advName.size() - 4] == '.')
|
||||
_advName = Common::String(_advName.c_str(), _advName.size() - 4);
|
||||
|
||||
// first, open a window for error output
|
||||
glkMainWin = g_vm->glk_window_open(nullptr, 0, 0, wintype_TextBuffer, 0);
|
||||
if (glkMainWin == nullptr)
|
||||
::error("FATAL ERROR: Cannot open initial window");
|
||||
|
||||
g_vm->glk_stylehint_set(wintype_TextGrid, style_User1, stylehint_ReverseColor, 1);
|
||||
glkStatusWin = g_vm->glk_window_open(glkMainWin, winmethod_Above |
|
||||
winmethod_Fixed, 1, wintype_TextGrid, 0);
|
||||
g_vm->glk_set_window(glkMainWin);
|
||||
|
||||
// Set up the code file to point to the already opened game file
|
||||
codfil = &_gameFile;
|
||||
|
||||
if (_gameFile.size() < 8) {
|
||||
GUIErrorMessage(_("This is too short to be a valid Alan2 file."));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 version = _gameFile.readUint32BE();
|
||||
if (version != MKTAG(2, 8, 1, 0) && version != MKTAG(2, 6, 0, 0)) {
|
||||
GUIErrorMessage(_("This is not a valid Alan2 file."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open up the text file
|
||||
txtfil = new Common::File();
|
||||
if (!txtfil->open(Common::Path(Common::String::format("%s.dat", _advName.c_str())))) {
|
||||
GUIErrorMessage("Could not open adventure text data file");
|
||||
delete txtfil;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for a save being loaded directly from the launcher
|
||||
_saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Alan2::deinitialize() {
|
||||
free(memory);
|
||||
|
||||
delete txtfil;
|
||||
delete logfil;
|
||||
}
|
||||
|
||||
Common::Error Alan2::readSaveData(Common::SeekableReadStream *rs) {
|
||||
Common::Serializer s(rs, nullptr);
|
||||
synchronizeSave(s);
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::Error Alan2::writeGameData(Common::WriteStream *ws) {
|
||||
Common::Serializer s(nullptr, ws);
|
||||
synchronizeSave(s);
|
||||
|
||||
ws->flush();
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
// This works around gcc errors for passing packed structure fields
|
||||
void syncVal(Common::Serializer &s, void *fld) {
|
||||
uint32 v = READ_UINT32(fld);
|
||||
s.syncAsUint32LE(v);
|
||||
if (s.isLoading())
|
||||
WRITE_UINT32(fld, v);
|
||||
}
|
||||
|
||||
static void syncActors(Common::Serializer &s) {
|
||||
for (uint i = ACTMIN; i <= ACTMAX; ++i) {
|
||||
syncVal(s, &acts[i - ACTMIN].loc);
|
||||
syncVal(s, &acts[i - ACTMIN].script);
|
||||
syncVal(s, &acts[i - ACTMIN].step);
|
||||
syncVal(s, &acts[i - ACTMIN].count);
|
||||
|
||||
if (acts[i - ACTMIN].atrs) {
|
||||
for (AtrElem *atr = (AtrElem *)addrTo(acts[i - ACTMIN].atrs); !endOfTable(atr); ++atr)
|
||||
syncVal(s, &atr->val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void syncLocations(Common::Serializer &s) {
|
||||
for (uint i = LOCMIN; i <= LOCMAX; ++i) {
|
||||
syncVal(s, &locs[i - LOCMIN].describe);
|
||||
if (locs[i - LOCMIN].atrs)
|
||||
for (AtrElem *atr = (AtrElem *)addrTo(locs[i - LOCMIN].atrs); !endOfTable(atr); atr++)
|
||||
syncVal(s, &atr->val);
|
||||
}
|
||||
}
|
||||
|
||||
static void syncObjects(Common::Serializer &s) {
|
||||
for (uint i = OBJMIN; i <= OBJMAX; ++i) {
|
||||
syncVal(s, &objs[i - OBJMIN].loc);
|
||||
if (objs[i - OBJMIN].atrs)
|
||||
for (AtrElem *atr = (AtrElem *)addrTo(objs[i - OBJMIN].atrs); !endOfTable(atr); atr++)
|
||||
syncVal(s, &atr->val);
|
||||
}
|
||||
}
|
||||
|
||||
static void syncEventQueue(Common::Serializer &s) {
|
||||
int i;
|
||||
EvtqElem *arr = eventq;
|
||||
|
||||
if (s.isLoading()) {
|
||||
i = 0;
|
||||
do {
|
||||
arr[i].synchronize(s);
|
||||
i++;
|
||||
} while (arr[i - 1].time != 0);
|
||||
etop = i - 1;
|
||||
} else {
|
||||
// Mark the top
|
||||
arr[etop].time = 0;
|
||||
|
||||
for (i = 0; i <= etop; ++i)
|
||||
arr[i].synchronize(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void syncScores(Common::Serializer &s) {
|
||||
for (int i = 0; scores[i] != EOD; i++)
|
||||
syncVal(s, &scores[i]);
|
||||
}
|
||||
|
||||
void Alan2::synchronizeSave(Common::Serializer &s) {
|
||||
// Sync various savegame data
|
||||
cur.synchronize(s);
|
||||
syncActors(s);
|
||||
syncLocations(s);
|
||||
syncObjects(s);
|
||||
syncEventQueue(s);
|
||||
syncScores(s);
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
107
engines/glk/alan2/alan2.h
Normal file
107
engines/glk/alan2/alan2.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Based on Alan2 interpreter version 2.8(6) */
|
||||
|
||||
#ifndef GLK_ALAN2
|
||||
#define GLK_ALAN2
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/stack.h"
|
||||
#include "glk/glk_api.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/**
|
||||
* Alan2 game interpreter
|
||||
*/
|
||||
class Alan2 : public GlkAPI {
|
||||
private:
|
||||
bool _restartFlag;
|
||||
public:
|
||||
bool vm_exited_cleanly;
|
||||
Common::String _advName;
|
||||
int _saveSlot;
|
||||
bool _pendingLook;
|
||||
private:
|
||||
/**
|
||||
* Initialization
|
||||
*/
|
||||
bool initialize();
|
||||
|
||||
/**
|
||||
* Deinitialization
|
||||
*/
|
||||
void deinitialize();
|
||||
|
||||
/**
|
||||
* Synchronize data to or from a save file
|
||||
*/
|
||||
void synchronizeSave(Common::Serializer &s);
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Alan2(OSystem *syst, const GlkGameDescription &gameDesc);
|
||||
|
||||
/**
|
||||
* Run the game
|
||||
*/
|
||||
void runGame() override;
|
||||
|
||||
/**
|
||||
* Flag for the game to restart
|
||||
*/
|
||||
void setRestart(bool flag) { _restartFlag = flag; }
|
||||
|
||||
/**
|
||||
* Returns whether the game should restart
|
||||
*/
|
||||
bool shouldRestart() const { return _restartFlag; }
|
||||
|
||||
/**
|
||||
* Returns the running interpreter type
|
||||
*/
|
||||
InterpreterType getInterpreterType() const override {
|
||||
return INTERPRETER_ALAN2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a savegame from the passed Quetzal file chunk stream
|
||||
*/
|
||||
Common::Error readSaveData(Common::SeekableReadStream *rs) override;
|
||||
|
||||
/**
|
||||
* Save the game. The passed write stream represents access to the UMem chunk
|
||||
* in the Quetzal save file that will be created
|
||||
*/
|
||||
Common::Error writeGameData(Common::WriteStream *ws) override;
|
||||
|
||||
};
|
||||
|
||||
extern Alan2 *g_vm;
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
41
engines/glk/alan2/alan_version.cpp
Normal file
41
engines/glk/alan2/alan_version.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/alan_version.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
Product alan = {
|
||||
"Alan",
|
||||
"Adventure Language System",
|
||||
"Alan 2.8(6)",
|
||||
"Alan 2.8(6) -- Adventure Language System (2001-07-13 14:35)",
|
||||
"2001-07-13",
|
||||
"14:35:07",
|
||||
"Thomas Nilsson",
|
||||
"",
|
||||
"cygwin",
|
||||
{"2.8(6)", 2, 8, 6, 995034907, ""}
|
||||
};
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
35
engines/glk/alan2/alan_version.h
Normal file
35
engines/glk/alan2/alan_version.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_ALAN_VERSION
|
||||
#define GLK_ALAN2_ALAN_VERSION
|
||||
|
||||
#include "glk/alan2/version.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern Product alan;
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
57
engines/glk/alan2/args.cpp
Normal file
57
engines/glk/alan2/args.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/alan2.h"
|
||||
#include "glk/alan2/args.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/sysdep.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
static void switches(unsigned argc, char *argv[]) {
|
||||
}
|
||||
|
||||
void args(int argc, char *argv[]) {
|
||||
char *prgnam;
|
||||
|
||||
if ((prgnam = strrchr(argv[0], '\\')) == nullptr
|
||||
&& (prgnam = strrchr(argv[0], '/')) == nullptr
|
||||
&& (prgnam = strrchr(argv[0], ':')) == nullptr)
|
||||
prgnam = argv[0];
|
||||
else
|
||||
prgnam++;
|
||||
if (strlen(prgnam) > 4
|
||||
&& (strcmp(&prgnam[strlen(prgnam) - 4], ".EXE") == 0
|
||||
|| strcmp(&prgnam[strlen(prgnam) - 4], ".exe") == 0))
|
||||
prgnam[strlen(prgnam) - 4] = '\0';
|
||||
/* Now look at the switches and arguments */
|
||||
switches(argc, argv);
|
||||
if (advnam[0] == '\0')
|
||||
/* No game given, try program name */
|
||||
if (scumm_stricmp(prgnam, PROGNAME) != 0
|
||||
&& strstr(prgnam, PROGNAME) == nullptr)
|
||||
advnam = scumm_strdup(argv[0]);
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
43
engines/glk/alan2/args.h
Normal file
43
engines/glk/alan2/args.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_ARGS
|
||||
#define GLK_ALAN2_ARGS
|
||||
|
||||
/* Handles the various startup methods on all machines.
|
||||
*
|
||||
* Main function args() will set up global variable advnam and the flags,
|
||||
* the terminal will also be set up and connected.
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
#define PROGNAME "alan2"
|
||||
|
||||
extern void args(int argc, char *argv[]);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
396
engines/glk/alan2/debug.cpp
Normal file
396
engines/glk/alan2/debug.cpp
Normal file
@@ -0,0 +1,396 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/alan2/alan_version.h"
|
||||
#include "glk/alan2/debug.h"
|
||||
#include "glk/alan2/exe.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "glk/alan2/inter.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/parse.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
static void showatrs(Aword atradr) {
|
||||
AtrElem *at;
|
||||
int i;
|
||||
char str[80];
|
||||
|
||||
if (atradr == 0) return;
|
||||
|
||||
i = 1;
|
||||
for (at = (AtrElem *) addrTo(atradr); !endOfTable(at); at++) {
|
||||
Common::sprintf_s(str, "$i%3ld: %ld (%s)", (long) i, (unsigned long) at->val, (char *) addrTo(at->stradr));
|
||||
output(str);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void showobjs() {
|
||||
char str[80];
|
||||
uint obj;
|
||||
|
||||
output("OBJECTS:");
|
||||
for (obj = OBJMIN; obj <= OBJMAX; obj++) {
|
||||
Common::sprintf_s(str, "$i%3ld: ", (long) obj);
|
||||
output(str);
|
||||
say(obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void showobj(int obj) {
|
||||
char str[80];
|
||||
#define OBJ (obj-OBJMIN)
|
||||
|
||||
|
||||
if (!isObj(obj)) {
|
||||
Common::sprintf_s(str, "Object number out of range. Between %ld and %ld, please.", (unsigned long) OBJMIN, (unsigned long) OBJMAX);
|
||||
output(str);
|
||||
return;
|
||||
}
|
||||
|
||||
Common::sprintf_s(str, "OBJECT %d :", obj);
|
||||
output(str);
|
||||
say(obj);
|
||||
|
||||
Common::sprintf_s(str, "$iLocation = %ld", (unsigned long) where(obj));
|
||||
output(str);
|
||||
if (isLoc(objs[OBJ].loc))
|
||||
say(objs[OBJ].loc);
|
||||
else if (isCnt(objs[OBJ].loc)) {
|
||||
if (isObj(objs[OBJ].loc)) {
|
||||
output("in");
|
||||
say(objs[OBJ].loc);
|
||||
} else if (isAct(objs[OBJ].loc)) {
|
||||
output("carried by");
|
||||
say(objs[OBJ].loc);
|
||||
} else
|
||||
interpret(cnts[objs[OBJ].loc - CNTMIN].nam);
|
||||
} else if (objs[OBJ].loc == 0)
|
||||
output("nowhere");
|
||||
else
|
||||
output("Illegal location!");
|
||||
|
||||
|
||||
output("$iAttributes =");
|
||||
showatrs(objs[OBJ].atrs);
|
||||
|
||||
#undef OBJ
|
||||
}
|
||||
|
||||
static void showcnts() {
|
||||
char str[80];
|
||||
uint cnt;
|
||||
#define CNT (cnt-CNTMIN)
|
||||
|
||||
output("CONTAINERS:");
|
||||
for (cnt = CNTMIN; cnt <= CNTMAX; cnt++) {
|
||||
Common::sprintf_s(str, "$i%3ld: ", (long) cnt);
|
||||
output(str);
|
||||
if (cnts[CNT].nam != 0)
|
||||
interpret(cnts[CNT].nam);
|
||||
if (cnts[CNT].parent != 0)
|
||||
say(cnts[CNT].parent);
|
||||
}
|
||||
|
||||
#undef CNT
|
||||
}
|
||||
|
||||
static void showcnt(int cnt) {
|
||||
char str[80];
|
||||
uint i;
|
||||
Abool found = FALSE;
|
||||
#define CNT (int)(cnt - CNTMIN)
|
||||
|
||||
if (cnt < (int)CNTMIN || cnt >(int)CNTMAX) {
|
||||
Common::sprintf_s(str, "Container number out of range. Between %ld and %ld, please.", (unsigned long) CNTMIN, (unsigned long) CNTMAX);
|
||||
output(str);
|
||||
return;
|
||||
}
|
||||
|
||||
Common::sprintf_s(str, "CONTAINER %d :", cnt);
|
||||
output(str);
|
||||
if (cnts[CNT].nam != 0)
|
||||
interpret(cnts[CNT].nam);
|
||||
if (cnts[CNT].parent != 0) {
|
||||
cnt = cnts[CNT].parent;
|
||||
say(cnt);
|
||||
Common::sprintf_s(str, "$iLocation = %ld", (unsigned long) where(cnt));
|
||||
output(str);
|
||||
}
|
||||
output("$iContains ");
|
||||
for (i = OBJMIN; i <= OBJMAX; i++) {
|
||||
if (in(i, cnt)) { /* Yes, it's in this container */
|
||||
if (!found) {
|
||||
output("$n");
|
||||
found = TRUE;
|
||||
}
|
||||
Common::sprintf_s(str, "$t$t%d: ", i);
|
||||
output(str);
|
||||
say(i);
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
output("nothing");
|
||||
|
||||
#undef CNT
|
||||
}
|
||||
|
||||
static void showlocs() {
|
||||
char str[80];
|
||||
uint loc;
|
||||
|
||||
output("LOCATIONS:");
|
||||
for (loc = LOCMIN; loc <= LOCMAX; loc++) {
|
||||
Common::sprintf_s(str, "$i%3ld: ", (long) loc);
|
||||
output(str);
|
||||
say(loc);
|
||||
}
|
||||
}
|
||||
|
||||
static void showloc(int loc) {
|
||||
char str[80];
|
||||
|
||||
|
||||
if (!isLoc(loc)) {
|
||||
Common::sprintf_s(str, "Location number out of range. Between %ld and %ld, please.", (unsigned long) LOCMIN, (unsigned long) LOCMAX);
|
||||
output(str);
|
||||
return;
|
||||
}
|
||||
|
||||
Common::sprintf_s(str, "LOCATION %d :", loc);
|
||||
output(str);
|
||||
say(loc);
|
||||
|
||||
output("$iAttributes =");
|
||||
showatrs(locs[loc - LOCMIN].atrs);
|
||||
}
|
||||
|
||||
static void showacts() {
|
||||
char str[80];
|
||||
uint act;
|
||||
|
||||
output("ACTORS:");
|
||||
for (act = ACTMIN; act <= ACTMAX; act++) {
|
||||
Common::sprintf_s(str, "$i%3ld:", (long) act);
|
||||
output(str);
|
||||
say(act);
|
||||
}
|
||||
}
|
||||
|
||||
static void showact(int act) {
|
||||
char str[80];
|
||||
Boolean oldstp;
|
||||
|
||||
if (!isAct(act)) {
|
||||
Common::sprintf_s(str, "Actor number out of range. Between %ld and %ld, please.", (unsigned long) ACTMIN, (unsigned long) ACTMAX);
|
||||
output(str);
|
||||
return;
|
||||
}
|
||||
|
||||
Common::sprintf_s(str, "ACTOR %d :", act);
|
||||
output(str);
|
||||
oldstp = stpflg;
|
||||
stpflg = FALSE; /* Make sure not to trace this! */
|
||||
say(act);
|
||||
stpflg = oldstp;
|
||||
|
||||
Common::sprintf_s(str, "$iLocation = %ld", (unsigned long) acts[act - ACTMIN].loc);
|
||||
output(str);
|
||||
if (isLoc(acts[act - ACTMIN].loc))
|
||||
say(acts[act - ACTMIN].loc);
|
||||
else if (acts[act - ACTMIN].loc == 0)
|
||||
output("nowhere");
|
||||
else
|
||||
output("Illegal location!");
|
||||
|
||||
Common::sprintf_s(str, "$iScript = %ld", (unsigned long) acts[act - ACTMIN].script);
|
||||
output(str);
|
||||
|
||||
Common::sprintf_s(str, "$iStep = %ld", (unsigned long) acts[act - ACTMIN].step);
|
||||
output(str);
|
||||
|
||||
output("$iAttributes =");
|
||||
showatrs(acts[act - ACTMIN].atrs);
|
||||
}
|
||||
|
||||
static void showevts() {
|
||||
int i;
|
||||
char str[80];
|
||||
Boolean scheduled;
|
||||
|
||||
output("EVENTS:");
|
||||
for (uint evt = EVTMIN; evt <= EVTMAX; evt++) {
|
||||
Common::sprintf_s(str, "$i%d (%s):", evt, (char *)addrTo(evts[evt - EVTMIN].stradr));
|
||||
output(str);
|
||||
scheduled = FALSE;
|
||||
for (i = 0; i < etop; i++)
|
||||
if ((scheduled = (eventq[i].event == (int)evt)))
|
||||
break;
|
||||
if (scheduled) {
|
||||
Common::sprintf_s(str, "Scheduled for +%d, at ", eventq[i].time - cur.tick);
|
||||
output(str);
|
||||
say(eventq[i].where);
|
||||
} else
|
||||
output("Not scheduled.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Boolean trc, stp;
|
||||
static int loc;
|
||||
|
||||
void saveInfo() {
|
||||
/* Save some important things */
|
||||
trc = trcflg;
|
||||
trcflg = FALSE;
|
||||
stp = stpflg;
|
||||
stpflg = FALSE;
|
||||
loc = cur.loc;
|
||||
cur.loc = where(HERO);
|
||||
}
|
||||
|
||||
void restoreInfo() {
|
||||
/* Restore! */
|
||||
trcflg = trc;
|
||||
stpflg = stp;
|
||||
cur.loc = loc;
|
||||
}
|
||||
|
||||
void debug() {
|
||||
char buf[256];
|
||||
char c;
|
||||
int i;
|
||||
|
||||
saveInfo();
|
||||
while (TRUE) {
|
||||
if (anyOutput)
|
||||
para();
|
||||
do {
|
||||
output("ABUG> ");
|
||||
(void)readline(buf, sizeof(buf));
|
||||
|
||||
lin = 1;
|
||||
c = buf[0];
|
||||
i = 0;
|
||||
(void)sscanf(&buf[1], "%d", &i);
|
||||
} while (/*buf &&*/ c == '\0');
|
||||
|
||||
switch (toUpper(c)) {
|
||||
case 'H':
|
||||
case '?':
|
||||
output(alan.longHeader);
|
||||
output("$nABUG Commands:\
|
||||
$iO [n] -- show object[s]\
|
||||
$iA [n] -- show actor[s]\
|
||||
$iL [n] -- show location[s]\
|
||||
$iC [n] -- show container[s]\
|
||||
$iE -- show events\
|
||||
$iG -- go on\
|
||||
$iT -- toggle trace mode\
|
||||
$iS -- toggle step mode\
|
||||
$iX -- exit debug mode\
|
||||
$iQ -- quit game");
|
||||
break;
|
||||
case 'Q': {
|
||||
Context ctx;
|
||||
terminate(ctx, 0);
|
||||
break;
|
||||
}
|
||||
case 'X':
|
||||
dbgflg = FALSE;
|
||||
restoreInfo();
|
||||
return;
|
||||
case 'G':
|
||||
restoreInfo();
|
||||
return;
|
||||
case 'O':
|
||||
if (i == 0)
|
||||
showobjs();
|
||||
else
|
||||
showobj(i);
|
||||
break;
|
||||
case 'C':
|
||||
if (i == 0)
|
||||
showcnts();
|
||||
else
|
||||
showcnt(i);
|
||||
break;
|
||||
case 'A':
|
||||
if (i == 0)
|
||||
showacts();
|
||||
else
|
||||
showact(i);
|
||||
break;
|
||||
case 'L':
|
||||
if (i == 0)
|
||||
showlocs();
|
||||
else
|
||||
showloc(i);
|
||||
break;
|
||||
case 'E':
|
||||
showevts();
|
||||
break;
|
||||
case 'S':
|
||||
if ((stp = !stp))
|
||||
printf("Step on.");
|
||||
else
|
||||
printf("Step off.");
|
||||
break;
|
||||
case 'T':
|
||||
if ((trc = !trc))
|
||||
printf("Trace on.");
|
||||
else
|
||||
printf("Trace off.");
|
||||
break;
|
||||
default:
|
||||
output("Unknown ABUG command. ? for help.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
debugsay()
|
||||
|
||||
Say somethin, but make sure we don't disturb anything and that it is
|
||||
shown to the player.
|
||||
|
||||
*/
|
||||
void debugsay(int item) {
|
||||
saveInfo();
|
||||
needsp = FALSE;
|
||||
col = 1;
|
||||
if (item == 0)
|
||||
printf("$null$");
|
||||
else
|
||||
say(item);
|
||||
needsp = FALSE;
|
||||
col = 1;
|
||||
restoreInfo();
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
38
engines/glk/alan2/debug.h
Normal file
38
engines/glk/alan2/debug.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/* TYPES */
|
||||
|
||||
#ifndef GLK_ALAN2_DEBUG
|
||||
#define GLK_ALAN2_DEBUG
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern void saveInfo();
|
||||
extern void restoreInfo();
|
||||
extern void debug();
|
||||
extern void debugsay(int item);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
163
engines/glk/alan2/decode.cpp
Normal file
163
engines/glk/alan2/decode.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/decode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* Bit output */
|
||||
static int decodeBuffer; /* Bits to be input */
|
||||
static int bitsToGo; /* Bits still in buffer */
|
||||
static int garbageBits; /* Bits past EOD */
|
||||
|
||||
static int inputBit() {
|
||||
int bit;
|
||||
|
||||
if (!bitsToGo) { /* More bits available ? */
|
||||
decodeBuffer = txtfil->readByte(); /* No, so get more */
|
||||
if ((uint)decodeBuffer == EOD) {
|
||||
garbageBits++;
|
||||
if (garbageBits > VALUEBITS - 2)
|
||||
syserr("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;
|
||||
}
|
||||
|
||||
|
||||
/* Current state of decoding */
|
||||
|
||||
static CodeValue value; /* Currently seen code value */
|
||||
static CodeValue low, high; /* Current code region */
|
||||
|
||||
|
||||
void startDecoding() {
|
||||
int i;
|
||||
|
||||
bitsToGo = 0;
|
||||
garbageBits = 0;
|
||||
|
||||
value = 0;
|
||||
for (i = 0; i < VALUEBITS; i++)
|
||||
value = 2 * value + inputBit();
|
||||
low = 0;
|
||||
high = TOPVALUE;
|
||||
}
|
||||
|
||||
int decodeChar() {
|
||||
long range;
|
||||
int f;
|
||||
int symbol;
|
||||
|
||||
range = (long)(high - low) + 1;
|
||||
f = (((long)(value - low) + 1) * freq[0] - 1) / range;
|
||||
|
||||
/* Find the symbol */
|
||||
for (symbol = 1; (int)freq[symbol] > f; symbol++);
|
||||
|
||||
high = low + range * freq[symbol - 1] / freq[0] - 1;
|
||||
low = low + range * freq[symbol] / freq[0];
|
||||
|
||||
for (;;) {
|
||||
if (high < HALF)
|
||||
;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Structure for saved decode info */
|
||||
typedef struct DecodeInfo {
|
||||
long fpos;
|
||||
int buffer;
|
||||
int bits;
|
||||
CodeValue value;
|
||||
CodeValue high;
|
||||
CodeValue low;
|
||||
} DecodeInfo;
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
pushDecode()
|
||||
|
||||
Save so much info about the decoding process so it is possible to
|
||||
restore and continue later.
|
||||
|
||||
*/
|
||||
void *pushDecode() {
|
||||
DecodeInfo *info;
|
||||
|
||||
info = (DecodeInfo *) allocate(sizeof(DecodeInfo));
|
||||
info->fpos = txtfil->pos();
|
||||
info->buffer = decodeBuffer;
|
||||
info->bits = bitsToGo;
|
||||
info->value = value;
|
||||
info->high = high;
|
||||
info->low = low;
|
||||
return (info);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
popDecode()
|
||||
|
||||
Restore enough info about the decoding process so it is possible to
|
||||
continue after having decoded something else.
|
||||
|
||||
*/
|
||||
void popDecode(void *i) {
|
||||
DecodeInfo *info = (DecodeInfo *) i;
|
||||
fseek(txtfil, info->fpos, 0);
|
||||
decodeBuffer = info->buffer;
|
||||
bitsToGo = info->bits;
|
||||
value = info->value;
|
||||
high = info->high;
|
||||
low = info->low;
|
||||
|
||||
free(info);
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
41
engines/glk/alan2/decode.h
Normal file
41
engines/glk/alan2/decode.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_DECODE
|
||||
#define GLK_ALAN2_DECODE
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
|
||||
/* Arithmetic decoding module in Arun
|
||||
*/
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern void startDecoding(void);
|
||||
extern int decodeChar(void);
|
||||
extern void *pushDecode(void);
|
||||
extern void popDecode(void *info);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
101
engines/glk/alan2/detection.cpp
Normal file
101
engines/glk/alan2/detection.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/detection.h"
|
||||
#include "glk/alan2/detection_tables.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/md5.h"
|
||||
#include "engines/game.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
void Alan2MetaEngine::getSupportedGames(PlainGameList &games) {
|
||||
for (const PlainGameDescriptor *pd = ALAN2_GAME_LIST; pd->gameId; ++pd) {
|
||||
games.push_back(*pd);
|
||||
}
|
||||
}
|
||||
|
||||
const GlkDetectionEntry* Alan2MetaEngine::getDetectionEntries() {
|
||||
return ALAN2_GAMES;
|
||||
}
|
||||
|
||||
GameDescriptor Alan2MetaEngine::findGame(const char *gameId) {
|
||||
for (const PlainGameDescriptor *pd = ALAN2_GAME_LIST; pd->gameId; ++pd) {
|
||||
if (!strcmp(gameId, pd->gameId))
|
||||
return *pd;
|
||||
}
|
||||
|
||||
return GameDescriptor::empty();
|
||||
}
|
||||
|
||||
bool Alan2MetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
|
||||
// Loop through the files of the folder
|
||||
for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||
// Check for a recognised filename
|
||||
if (file->isDirectory())
|
||||
continue;
|
||||
Common::String filename = file->getName();
|
||||
bool hasExt = filename.hasSuffixIgnoreCase(".acd");
|
||||
if (!hasExt)
|
||||
continue;
|
||||
|
||||
// Open up the file and calculate the md5
|
||||
Common::File gameFile;
|
||||
if (!gameFile.open(*file))
|
||||
continue;
|
||||
uint32 version = gameFile.readUint32BE();
|
||||
if (version != MKTAG(2, 8, 1, 0) && version != MKTAG(2, 6, 0, 0))
|
||||
continue;
|
||||
|
||||
gameFile.seek(0);
|
||||
Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
|
||||
size_t filesize = gameFile.size();
|
||||
gameFile.close();
|
||||
|
||||
// Check for known games
|
||||
const GlkDetectionEntry *p = ALAN2_GAMES;
|
||||
while (p->_gameId && (md5 != p->_md5 || filesize != p->_filesize))
|
||||
++p;
|
||||
|
||||
if (!p->_gameId) {
|
||||
const PlainGameDescriptor &desc = ALAN2_GAME_LIST[0];
|
||||
gameList.push_back(GlkDetectedGame(desc.gameId, desc.description, filename, md5, filesize));
|
||||
} else {
|
||||
PlainGameDescriptor gameDesc = findGame(p->_gameId);
|
||||
gameList.push_back(GlkDetectedGame(p->_gameId, gameDesc.description, p->_extra, filename, p->_language));
|
||||
}
|
||||
}
|
||||
|
||||
return !gameList.empty();
|
||||
}
|
||||
|
||||
void Alan2MetaEngine::detectClashes(Common::StringMap &map) {
|
||||
for (const PlainGameDescriptor *pd = ALAN2_GAME_LIST; pd->gameId; ++pd) {
|
||||
if (map.contains(pd->gameId))
|
||||
error("Duplicate game Id found - %s", pd->gameId);
|
||||
map[pd->gameId] = "";
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
67
engines/glk/alan2/detection.h
Normal file
67
engines/glk/alan2/detection.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_DETECTION
|
||||
#define GLK_ALAN2_DETECTION
|
||||
|
||||
#include "common/fs.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "engines/game.h"
|
||||
#include "glk/detection.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/**
|
||||
* Meta engine for Alan2 interpreter
|
||||
*/
|
||||
class Alan2MetaEngine {
|
||||
public:
|
||||
/**
|
||||
* Get a list of supported games
|
||||
*/
|
||||
static void getSupportedGames(PlainGameList &games);
|
||||
|
||||
/**
|
||||
* Get the detection entries
|
||||
*/
|
||||
static const GlkDetectionEntry* getDetectionEntries();
|
||||
|
||||
/**
|
||||
* Returns a game description for the given game Id, if it's supported
|
||||
*/
|
||||
static GameDescriptor findGame(const char *gameId);
|
||||
|
||||
/**
|
||||
* Detect supported games
|
||||
*/
|
||||
static bool detectGames(const Common::FSList &fslist, DetectedGames &gameList);
|
||||
|
||||
/**
|
||||
* Check for game Id clashes with other sub-engines
|
||||
*/
|
||||
static void detectClashes(Common::StringMap &map);
|
||||
};
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
106
engines/glk/alan2/detection_tables.h
Normal file
106
engines/glk/alan2/detection_tables.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/game.h"
|
||||
#include "common/gui_options.h"
|
||||
#include "common/language.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
const PlainGameDescriptor ALAN2_GAME_LIST[] = {
|
||||
{ "alan2", "Alan2 Game" },
|
||||
|
||||
// Unsupported 2.6 games
|
||||
{ "hollywoodmurders", "The Hollywood Murders" },
|
||||
|
||||
// Supported 2.8.1 games
|
||||
{ "artifiction", "Artifiction" },
|
||||
{ "bantams", "Even Bantams get the Blues" },
|
||||
{ "bugged", "Bugged" },
|
||||
{ "cc", "CC" },
|
||||
{ "chasing", "The Chasing" },
|
||||
{ "closet", "Closet" },
|
||||
{ "crystalball", "Crystal Ball" },
|
||||
{ "dinnertime", "Dinnertime" },
|
||||
{ "hebgb", "The HeBGB Horror!" },
|
||||
{ "arthursnightout", "King Arthur's Night Out" },
|
||||
{ "knotundone", "Knot To Be Undone" },
|
||||
{ "lostinnewyork", "Lost In New York" },
|
||||
{ "mazemapper", "Mazemapper" },
|
||||
{ "meanstory", "The Mean Story" },
|
||||
{ "outofthestudy", "Out Of The Study" },
|
||||
{ "plsghints", "Painless Little Stupid Games Hints" },
|
||||
{ "puddlespath", "Puddles on the Path" },
|
||||
{ "sardoria", "Sardoria" },
|
||||
{ "skipbreak", "Skipping Breakfast" },
|
||||
{ "speedif11p6", "SpeedIF 11 - part six" },
|
||||
{ "presidentadventures", "The Adventures of the President of the United States" },
|
||||
{ "thechasing", "The Chasing" },
|
||||
{ "nobread", "There Is No Bread" },
|
||||
{ "afteryou", "They're After You" },
|
||||
{ "tgttos", "To Get To The Other Side" },
|
||||
{ "zeroone", "Zero One" },
|
||||
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
const GlkDetectionEntry ALAN2_GAMES[] = {
|
||||
// Unsupported 2.6 games
|
||||
DT_ENTRY0("hollywoodmurders", "e6da6dfa85dd471a251ce485af710730", 95232),
|
||||
|
||||
// Supported 2.8.1 games
|
||||
DT_ENTRY0("artifiction", "2615ba29c6030ec50454fdded1049b44", 40960),
|
||||
DT_ENTRY0("bantams", "8c4be4f2e21f9770523ea0c4a180cb8a", 40960),
|
||||
DT_ENTRY0("bugged", "f4eed3db3771a456143744a0e36653db", 112640),
|
||||
DT_ENTRY0("cc", "47f4a5436ce07d65bb828e2938f81952", 53248),
|
||||
DT_ENTRY1("chasing", "1.0", "10ad37b6dd6d9f399578b28e644914ca", 144384),
|
||||
DT_ENTRY1("chasing", "1.1", "718ffcc9dfe85cfd8c6f50f541a3926e", 147456),
|
||||
DT_ENTRY0("closet", "5d724469e6240cde0c16c959f50ebc93", 37888),
|
||||
DT_ENTRY0("crystalball", "625e15e14081847cd26842a52839a07c", 11264),
|
||||
DT_ENTRY0("dinnertime", "1c0bad19156e8bdefe9e19d99f96f7d8", 9216),
|
||||
DT_ENTRY0("hebgb", "87f9516bc4217afb5c329cb1ae01d861", 173056),
|
||||
DT_ENTRY0("hebgb", "96f016f4657a801686d1d1da5dd6f382", 157696),
|
||||
DT_ENTRY0("knotundone", "a4249a82d7211398adc9917c773c58fa", 25600),
|
||||
DT_ENTRY0("arthursnightout", "c8c87b88a9250cec2f03af3a347d3c05", 50176),
|
||||
DT_ENTRY0("lostinnewyork", "483a8c7c84f3bb5af61150fd770806e5", 30720),
|
||||
DT_ENTRY0("mazemapper", "8e7409758c3535201aeb901923b20064", 30720),
|
||||
DT_ENTRY0("meanstory", "e4ae6873d6f2ab74fb2ec35b27752397", 13312),
|
||||
DT_ENTRY1("outofthestudy", "1.0", "089082d50b232b07fc31cf60aeefb5ae", 102400),
|
||||
DT_ENTRY1("outofthestudy", "1.3", "cc4ab3f1b406a8ce04adcfb641c3b250", 110592),
|
||||
DT_ENTRY0("plsghints", "fb9df41138691a77ea3489986fe8856c", 10240),
|
||||
DT_ENTRY0("puddlespath", "5b6bf831263f43b6e9f26517fae6294b", 104448),
|
||||
DT_ENTRY0("sardoria", "b48ba08ae33b5cb224bcb4ce0eea36bc", 150528),
|
||||
DT_ENTRY0("sardoria", "1b0e03cbdcb74d59a92920d093fc7446", 143360),
|
||||
DT_ENTRY0("skipbreak", "a0f7e71f00fd4d26eacc82637da84cb0", 44032),
|
||||
DT_ENTRY0("speedif11p6", "0c8a517bd49c3f6ed28d44e5a294de06", 32768),
|
||||
DT_ENTRY0("presidentadventures", "74caac5475f8801ac27d76a3d2e034ad", 53248),
|
||||
DT_ENTRY0("thechasing", "10ad37b6dd6d9f399578b28e644914ca", 144384),
|
||||
DT_ENTRY0("nobread", "7a85bef5bc441bbaa8a6321e063ec711", 30720),
|
||||
DT_ENTRY0("afteryou", "998ca167b0e9ffb671203b2057d06bef", 17408),
|
||||
DT_ENTRY0("tgttos", "0fed94b37b8add48938d8288ca5e7e4f", 29696),
|
||||
DT_ENTRY0("zeroone", "1e2f65611c41040f60caaf5f26e61367", 59392),
|
||||
|
||||
DT_END_MARKER
|
||||
};
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
1158
engines/glk/alan2/exe.cpp
Normal file
1158
engines/glk/alan2/exe.cpp
Normal file
File diff suppressed because it is too large
Load Diff
84
engines/glk/alan2/exe.h
Normal file
84
engines/glk/alan2/exe.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_EXE
|
||||
#define GLK_ALAN2_EXE
|
||||
|
||||
/* Header file for instruction execution unit in Alan interpreter
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* The event queue */
|
||||
extern EvtqElem eventq[]; /* Event queue */
|
||||
extern int etop; /* Event queue top pointer */
|
||||
extern Boolean looking; /* LOOKING? flag */
|
||||
extern int dscrstkp; /* Point into describe stack */
|
||||
|
||||
extern void sys(Aword fpos, Aword len);
|
||||
extern Boolean confirm(MsgKind msgno);
|
||||
extern Aptr attribute(Aword item, Aword atr);
|
||||
extern void saynum(Aword num);
|
||||
extern void saystr(char *str);
|
||||
extern Aptr strattr(Aword id, Aword atr);
|
||||
extern void setstr(Aword id, Aword atr, Aword str);
|
||||
extern void getstr(Aword fpos, Aword len);
|
||||
extern void print(Aword fpos, Aword len);
|
||||
extern void look(void);
|
||||
extern void make(Aword id, Aword atr, Aword val);
|
||||
extern void set(Aword id, Aword atr, Aword val);
|
||||
extern void incr(Aword id, Aword atr, Aword step);
|
||||
extern void decr(Aword id, Aword atr, Aword step);
|
||||
extern void use(Aword act, Aword scr);
|
||||
extern void describe(Aword id);
|
||||
extern void list(Aword cnt);
|
||||
extern void locate(Aword id, Aword whr);
|
||||
extern void empty(Aword cnt, Aword whr);
|
||||
extern void score(Aword sc);
|
||||
extern void visits(Aword v);
|
||||
extern void schedule(Aword evt, Aword whr, Aword aft);
|
||||
extern void cancl(Aword evt);
|
||||
extern void quit(CONTEXT);
|
||||
extern void restart(void);
|
||||
extern void save(void);
|
||||
extern void restore(void);
|
||||
extern void say(Aword id);
|
||||
extern void sayint(Aword val);
|
||||
extern Aword rnd(Aword from, Aword to);
|
||||
extern Abool btw(Aint val, Aint from, Aint to);
|
||||
extern Aword contains(Aptr string, Aptr substring);
|
||||
extern Abool streq(char a[], char b[]);
|
||||
extern Abool in(Aword obj, Aword cnt);
|
||||
extern Aword where(Aword item);
|
||||
extern Aint agrmax(Aword atr, Aword whr);
|
||||
extern Aint agrsum(Aword atr, Aword whr);
|
||||
extern Aint agrcount(Aword whr);
|
||||
extern Abool isHere(Aword item);
|
||||
extern Abool isNear(Aword item);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
92
engines/glk/alan2/glkio.cpp
Normal file
92
engines/glk/alan2/glkio.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/glk.h"
|
||||
#include "glk/alan2/alan2.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "glk/alan2/main.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
winid_t glkMainWin;
|
||||
winid_t glkStatusWin;
|
||||
|
||||
void glkio_printf(const char *fmt, ...) {
|
||||
// If there's a savegame being loaded from the launcher, ignore any text out
|
||||
if (g_vm->_saveSlot != -1)
|
||||
return;
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
if (glkMainWin) {
|
||||
char buf[1024]; /* FIXME: buf size should be foolproof */
|
||||
Common::vsprintf_s(buf, fmt, argp);
|
||||
g_vm->glk_put_string(buf);
|
||||
} else {
|
||||
// assume stdio is available in this case only
|
||||
Common::String str = Common::String::vformat(fmt, argp);
|
||||
warning(fmt, argp);
|
||||
}
|
||||
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
/*======================================================================
|
||||
|
||||
readline()
|
||||
|
||||
Read a line from the user, with history and editing
|
||||
|
||||
*/
|
||||
|
||||
/* 4f - length of user buffer should be used */
|
||||
Boolean readline(char usrbuf[], size_t maxlen) {
|
||||
if (g_vm->_pendingLook) {
|
||||
g_vm->_pendingLook = false;
|
||||
glkio_printf("look\n");
|
||||
Common::strcpy_s(usrbuf, maxlen, "look");
|
||||
} else {
|
||||
event_t event;
|
||||
g_vm->glk_request_line_event(glkMainWin, usrbuf, maxlen, 0);
|
||||
|
||||
/* FIXME: buffer size should be infallible: all existing calls use 256 or
|
||||
80 character buffers, except parse which uses LISTLEN (currently 100)
|
||||
*/
|
||||
do {
|
||||
g_vm->glk_select(&event);
|
||||
if (evtype_Arrange == event.type)
|
||||
statusline();
|
||||
if (g_vm->shouldQuit())
|
||||
return false;
|
||||
|
||||
} while (event.type != evtype_LineInput);
|
||||
|
||||
usrbuf[event.val1] = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
53
engines/glk/alan2/glkio.h
Normal file
53
engines/glk/alan2/glkio.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_GLKIO
|
||||
#define GLK_ALAN2_GLKIO
|
||||
|
||||
/* Header file for Glk output for Alan interpreter
|
||||
*/
|
||||
|
||||
#include "glk/windows.h"
|
||||
#include "glk/alan2/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern winid_t glkMainWin;
|
||||
extern winid_t glkStatusWin;
|
||||
|
||||
/* NB: this header must be included in any file which calls print() */
|
||||
|
||||
#undef printf
|
||||
#define printf glkio_printf
|
||||
|
||||
void glkio_printf(const char *, ...);
|
||||
|
||||
#define LINELENGTH 80
|
||||
#define HISTORYLENGTH 20
|
||||
|
||||
extern Boolean readline(char usrbuf[], size_t maxlen);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
|
||||
887
engines/glk/alan2/inter.cpp
Normal file
887
engines/glk/alan2/inter.cpp
Normal file
@@ -0,0 +1,887 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/alan2/exe.h"
|
||||
#include "glk/alan2/inter.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/parse.h"
|
||||
#include "glk/alan2/stack.h"
|
||||
#include "glk/alan2/sysdep.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* PRIVATE DATA */
|
||||
|
||||
static int pc;
|
||||
|
||||
|
||||
static void if_(Aword v) {
|
||||
int lev = 1;
|
||||
Aword i;
|
||||
|
||||
if (!v) {
|
||||
/* Skip to next ELSE or ENDIF on same level */
|
||||
while (TRUE) {
|
||||
i = memory[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void else_() {
|
||||
int lev = 1;
|
||||
Aword i;
|
||||
|
||||
while (TRUE) {
|
||||
/* Skip to ENDIF on the same level */
|
||||
i = memory[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void depstart() {
|
||||
/* A DEPSTART was executed so skip across the redundant DEPCASE to
|
||||
start at the first expression */
|
||||
pc++;
|
||||
}
|
||||
|
||||
static void swap() {
|
||||
Aptr v1 = pop();
|
||||
Aptr v2 = pop();
|
||||
|
||||
push(v1);
|
||||
push(v2);
|
||||
}
|
||||
|
||||
static void 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 = memory[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void 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 = memory[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 interpret(Aaddr adr) {
|
||||
Context ctx;
|
||||
interpret(ctx, adr);
|
||||
}
|
||||
|
||||
void interpret(CONTEXT, Aaddr adr) {
|
||||
Aaddr oldpc;
|
||||
Aword i;
|
||||
|
||||
if (stpflg) printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++");
|
||||
|
||||
oldpc = pc;
|
||||
pc = adr;
|
||||
while (TRUE) {
|
||||
if (stpflg) printf("\n%4x: ", pc);
|
||||
if (pc > (int)memTop)
|
||||
syserr("Interpreting outside program.");
|
||||
|
||||
i = memory[pc++];
|
||||
|
||||
switch (I_CLASS(i)) {
|
||||
case C_CONST:
|
||||
if (stpflg) printf("PUSH \t%5u", I_OP(i));
|
||||
push(I_OP(i));
|
||||
break;
|
||||
case C_CURVAR:
|
||||
switch (I_OP(i)) {
|
||||
case V_PARAM:
|
||||
if (stpflg) printf("PARAM \t%5lu\t\t(%u)", top(), params[top() - 1].code);
|
||||
push(params[pop() - 1].code);
|
||||
break;
|
||||
case V_CURLOC:
|
||||
if (stpflg) printf("CURLOC \t\t\t(%d)", cur.loc);
|
||||
push(cur.loc);
|
||||
break;
|
||||
case V_CURACT:
|
||||
if (stpflg) printf("CURACT \t\t\t(%d)", cur.act);
|
||||
push(cur.act);
|
||||
break;
|
||||
case V_CURVRB:
|
||||
if (stpflg) printf("CURVRB \t\t\t(%d)", cur.vrb);
|
||||
push(cur.vrb);
|
||||
break;
|
||||
case V_SCORE:
|
||||
if (stpflg) printf("CURSCORE \t\t\t(%d)", cur.score);
|
||||
push(cur.score);
|
||||
break;
|
||||
default:
|
||||
syserr("Unknown CURVAR instruction.");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case C_STMOP:
|
||||
switch (I_OP(i)) {
|
||||
case I_PRINT: {
|
||||
Aptr fpos, len;
|
||||
fpos = pop();
|
||||
len = pop();
|
||||
if (stpflg) {
|
||||
printf("PRINT \t%5ld, %5ld\t\"", fpos, len);
|
||||
col = 34; /* To format it better! */
|
||||
}
|
||||
print(fpos, len);
|
||||
if (stpflg)
|
||||
printf("\"");
|
||||
break;
|
||||
}
|
||||
case I_SYSTEM: {
|
||||
Aptr fpos, len;
|
||||
fpos = pop();
|
||||
len = pop();
|
||||
if (stpflg) {
|
||||
printf("SYSTEM \t%5ld, %5ld\t\"", fpos, len);
|
||||
col = 34; /* To format it better! */
|
||||
}
|
||||
sys(fpos, len);
|
||||
break;
|
||||
}
|
||||
case I_GETSTR: {
|
||||
Aptr fpos, len;
|
||||
fpos = pop();
|
||||
len = pop();
|
||||
if (stpflg)
|
||||
printf("GETSTR\t%5ld, %5ld", fpos, len);
|
||||
getstr(fpos, len);
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_QUIT: {
|
||||
if (stpflg)
|
||||
printf("QUIT");
|
||||
CALL0(quit)
|
||||
break;
|
||||
}
|
||||
case I_LOOK: {
|
||||
if (stpflg)
|
||||
printf("LOOK");
|
||||
look();
|
||||
break;
|
||||
}
|
||||
case I_SAVE: {
|
||||
if (stpflg)
|
||||
printf("SAVE");
|
||||
save();
|
||||
break;
|
||||
}
|
||||
case I_RESTORE: {
|
||||
if (stpflg)
|
||||
printf("RESTORE");
|
||||
restore();
|
||||
break;
|
||||
}
|
||||
case I_RESTART: {
|
||||
if (stpflg)
|
||||
printf("RESTART");
|
||||
restart();
|
||||
break;
|
||||
}
|
||||
case I_LIST: {
|
||||
Aptr cnt;
|
||||
cnt = pop();
|
||||
if (stpflg)
|
||||
printf("LIST \t%5ld", cnt);
|
||||
list(cnt);
|
||||
break;
|
||||
}
|
||||
case I_EMPTY: {
|
||||
Aptr cnt, whr;
|
||||
cnt = pop();
|
||||
whr = pop();
|
||||
if (stpflg)
|
||||
printf("EMPTY \t%5ld, %5ld", cnt, whr);
|
||||
empty(cnt, whr);
|
||||
break;
|
||||
}
|
||||
case I_SCORE: {
|
||||
Aptr sc;
|
||||
sc = pop();
|
||||
if (stpflg)
|
||||
printf("SCORE \t%5ld\t\t(%u)", sc, scores[sc - 1]);
|
||||
score(sc);
|
||||
break;
|
||||
}
|
||||
case I_VISITS: {
|
||||
Aptr v;
|
||||
v = pop();
|
||||
if (stpflg)
|
||||
printf("VISITS \t%5ld", v);
|
||||
visits(v);
|
||||
break;
|
||||
}
|
||||
case I_SCHEDULE: {
|
||||
Aptr evt, whr, aft;
|
||||
evt = pop();
|
||||
whr = pop();
|
||||
aft = pop();
|
||||
if (stpflg)
|
||||
printf("SCHEDULE \t%5ld, %5ld, %5ld", evt, whr, aft);
|
||||
schedule(evt, whr, aft);
|
||||
break;
|
||||
}
|
||||
case I_CANCEL: {
|
||||
Aptr evt;
|
||||
evt = pop();
|
||||
if (stpflg)
|
||||
printf("CANCEL \t%5ld", evt);
|
||||
cancl(evt);
|
||||
break;
|
||||
}
|
||||
case I_MAKE: {
|
||||
Aptr id, atr, val;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
val = pop();
|
||||
if (stpflg) {
|
||||
printf("MAKE \t%5ld, %5ld, ", id, atr);
|
||||
if (val) printf("TRUE");
|
||||
else printf("FALSE");
|
||||
}
|
||||
make(id, atr, val);
|
||||
break;
|
||||
}
|
||||
case I_SET: {
|
||||
Aptr id, atr, val;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
val = pop();
|
||||
if (stpflg) {
|
||||
printf("SET \t%5ld, %5ld, %5ld", id, atr, val);
|
||||
}
|
||||
set(id, atr, val);
|
||||
break;
|
||||
}
|
||||
case I_STRSET: {
|
||||
Aptr id, atr, str;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
str = pop();
|
||||
if (stpflg) {
|
||||
printf("STRSET\t%5ld, %5ld, %5ld", id, atr, str);
|
||||
}
|
||||
setstr(id, atr, str);
|
||||
break;
|
||||
}
|
||||
case I_INCR: {
|
||||
Aptr id, atr, step;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
step = pop();
|
||||
if (stpflg) {
|
||||
printf("INCR\t%5ld, %5ld, %5ld", id, atr, step);
|
||||
}
|
||||
incr(id, atr, step);
|
||||
break;
|
||||
}
|
||||
case I_DECR: {
|
||||
Aptr id, atr, step;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
step = pop();
|
||||
if (stpflg) {
|
||||
printf("DECR\t%5ld, %5ld, %5ld", id, atr, step);
|
||||
}
|
||||
decr(id, atr, step);
|
||||
break;
|
||||
}
|
||||
case I_ATTRIBUTE: {
|
||||
Aptr id, atr;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
if (stpflg)
|
||||
printf("ATTRIBUTE %5ld, %5ld", id, atr);
|
||||
push(attribute(id, atr));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_STRATTR: {
|
||||
Aptr id, atr;
|
||||
id = pop();
|
||||
atr = pop();
|
||||
if (stpflg)
|
||||
printf("STRATTR \t%5ld, %5ld", id, atr);
|
||||
push(strattr(id, atr));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_LOCATE: {
|
||||
Aptr id, whr;
|
||||
id = pop();
|
||||
whr = pop();
|
||||
if (stpflg)
|
||||
printf("LOCATE \t%5ld, %5ld", id, whr);
|
||||
locate(id, whr);
|
||||
break;
|
||||
}
|
||||
case I_WHERE: {
|
||||
Aptr id;
|
||||
id = pop();
|
||||
if (stpflg)
|
||||
printf("WHERE \t%5ld", id);
|
||||
push(where(id));
|
||||
if (stpflg)
|
||||
printf("\t\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_HERE: {
|
||||
Aptr id;
|
||||
id = pop();
|
||||
if (stpflg)
|
||||
printf("HERE \t%5ld", id);
|
||||
push(isHere(id));
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_NEAR: {
|
||||
Aptr id;
|
||||
id = pop();
|
||||
if (stpflg)
|
||||
printf("NEAR \t%5ld", id);
|
||||
push(isNear(id));
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_USE: {
|
||||
Aptr act, scr;
|
||||
act = pop();
|
||||
scr = pop();
|
||||
if (stpflg)
|
||||
printf("USE \t%5ld, %5ld", act, scr);
|
||||
use(act, scr);
|
||||
break;
|
||||
}
|
||||
case I_IN: {
|
||||
Aptr obj, cnt;
|
||||
obj = pop();
|
||||
cnt = pop();
|
||||
if (stpflg)
|
||||
printf("IN \t%5ld, %5ld ", obj, cnt);
|
||||
push(in(obj, cnt));
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_DESCRIBE: {
|
||||
Aptr id;
|
||||
id = pop();
|
||||
if (stpflg) {
|
||||
printf("DESCRIBE \t%5ld\t", id);
|
||||
col = 34; /* To format it better! */
|
||||
}
|
||||
describe(id);
|
||||
break;
|
||||
}
|
||||
case I_SAY: {
|
||||
Aptr id;
|
||||
id = pop();
|
||||
if (stpflg)
|
||||
printf("SAY \t%5ld\t\t\"", id);
|
||||
say(id);
|
||||
if (stpflg)
|
||||
printf("\"");
|
||||
break;
|
||||
}
|
||||
case I_SAYINT: {
|
||||
Aptr val;
|
||||
val = pop();
|
||||
if (stpflg)
|
||||
printf("SAYINT\t%5ld\t\t\"", val);
|
||||
sayint(val);
|
||||
if (stpflg)
|
||||
printf("\"");
|
||||
break;
|
||||
}
|
||||
case I_SAYSTR: {
|
||||
Aptr sayAdr;
|
||||
sayAdr = pop();
|
||||
if (stpflg)
|
||||
printf("SAYSTR\t%5ld\t\t\"", sayAdr);
|
||||
saystr((char *)sayAdr);
|
||||
if (stpflg)
|
||||
printf("\"");
|
||||
break;
|
||||
}
|
||||
case I_IF: {
|
||||
Aptr v;
|
||||
v = pop();
|
||||
if (stpflg) {
|
||||
printf("IF \t");
|
||||
if (v) printf(" TRUE");
|
||||
else printf("FALSE");
|
||||
}
|
||||
if_(v);
|
||||
break;
|
||||
}
|
||||
case I_ELSE: {
|
||||
if (stpflg)
|
||||
printf("ELSE");
|
||||
else_();
|
||||
break;
|
||||
}
|
||||
case I_ENDIF: {
|
||||
if (stpflg)
|
||||
printf("ENDIF");
|
||||
break;
|
||||
}
|
||||
case I_AND: {
|
||||
Aptr lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg) {
|
||||
printf("AND \t");
|
||||
if (lh) printf("TRUE, ");
|
||||
else printf("FALSE, ");
|
||||
if (rh) printf("TRUE");
|
||||
else printf("FALSE");
|
||||
}
|
||||
push(lh && rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_OR: {
|
||||
Aptr lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg) {
|
||||
printf("OR \t");
|
||||
if (lh) printf("TRUE, ");
|
||||
else printf("FALSE, ");
|
||||
if (rh) printf("TRUE");
|
||||
else printf("FALSE");
|
||||
}
|
||||
push(lh || rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_NE: {
|
||||
Aptr lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("NE \t%5ld, %5ld", lh, rh);
|
||||
push(lh != rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_EQ: {
|
||||
Aptr lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("EQ \t%5ld, %5ld", lh, rh);
|
||||
push(lh == rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_STREQ: {
|
||||
Aptr lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("STREQ \t%5ld, %5ld", lh, rh);
|
||||
push(streq((char *)lh, (char *)rh));
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_STREXACT: {
|
||||
Aptr lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("STREXACT \t%5ld, %5ld", lh, rh);
|
||||
push(strcmp((char *)lh, (char *)rh) == 0);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
free((void *)lh);
|
||||
free((void *)rh);
|
||||
break;
|
||||
}
|
||||
case I_LE: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("LE \t%5d, %5d", lh, rh);
|
||||
push(lh <= rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_GE: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("GE \t%5d, %5d", lh, rh);
|
||||
push(lh >= rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_LT: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("LT \t%5d, %5d", lh, rh);
|
||||
push((signed int)lh < (signed int)rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_GT: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("GT \t%5d, %5d", lh, rh);
|
||||
push(lh > rh);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t(TRUE)");
|
||||
else printf("\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_PLUS: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("PLUS \t%5d, %5d", lh, rh);
|
||||
push(lh + rh);
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_MINUS: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("MINUS \t%5d, %5d", lh, rh);
|
||||
push(lh - rh);
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_MULT: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("MULT \t%5d, %5d", lh, rh);
|
||||
push(lh * rh);
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_DIV: {
|
||||
Aint lh, rh;
|
||||
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
||||
swap();
|
||||
rh = pop();
|
||||
lh = pop();
|
||||
if (stpflg)
|
||||
printf("DIV \t%5d, %5d", lh, rh);
|
||||
push(lh / rh);
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_NOT: {
|
||||
Aptr val;
|
||||
val = pop();
|
||||
if (stpflg) {
|
||||
printf("NOT \t");
|
||||
if (val) printf("TRUE");
|
||||
else printf("FALSE");
|
||||
}
|
||||
push(!val);
|
||||
if (stpflg) {
|
||||
if (top()) printf("\t\t(TRUE)");
|
||||
else printf("\t\t(FALSE)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case I_MAX: {
|
||||
Aptr atr, whr;
|
||||
atr = pop();
|
||||
whr = pop();
|
||||
if (stpflg)
|
||||
printf("MAX \t%5ld, %5ld", atr, whr);
|
||||
push(agrmax(atr, whr));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_SUM: {
|
||||
Aptr atr, whr;
|
||||
atr = pop();
|
||||
whr = pop();
|
||||
if (stpflg)
|
||||
printf("SUM \t%5ld, %5ld", atr, whr);
|
||||
push(agrsum(atr, whr));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_COUNT: {
|
||||
Aptr whr;
|
||||
whr = pop();
|
||||
if (stpflg)
|
||||
printf("COUNT \t%5ld", whr);
|
||||
push(agrcount(whr));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_RND: {
|
||||
Aptr from, to;
|
||||
from = pop();
|
||||
to = pop();
|
||||
if (stpflg)
|
||||
printf("RANDOM \t%5ld, %5ld", from, to);
|
||||
push(rnd(from, to));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_BTW: {
|
||||
Aint low, high, val;
|
||||
high = pop();
|
||||
low = pop();
|
||||
val = pop();
|
||||
if (stpflg)
|
||||
printf("BETWEEN \t%5d, %5d, %5d", val, low, high);
|
||||
push(btw(val, low, high));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
case I_CONTAINS: {
|
||||
Aptr string, substring;
|
||||
substring = pop();
|
||||
string = pop();
|
||||
if (stpflg)
|
||||
printf("CONTAINS \t%5ld, %5ld", string, substring);
|
||||
push(contains(string, substring));
|
||||
if (stpflg)
|
||||
printf("\t(%ld)", top());
|
||||
break;
|
||||
}
|
||||
|
||||
case I_DEPSTART:
|
||||
if (stpflg)
|
||||
printf("DEPSTART");
|
||||
depstart();
|
||||
break;
|
||||
|
||||
case I_DEPCASE:
|
||||
if (stpflg)
|
||||
printf("DEPCASE");
|
||||
depcase();
|
||||
break;
|
||||
|
||||
case I_DEPEXEC: {
|
||||
Aptr v;
|
||||
v = pop();
|
||||
if (stpflg) {
|
||||
printf("DEPEXEC \t");
|
||||
if (v) printf(" TRUE");
|
||||
else printf("FALSE");
|
||||
}
|
||||
depexec(v);
|
||||
break;
|
||||
}
|
||||
|
||||
case I_DEPELSE:
|
||||
if (stpflg)
|
||||
printf("DEPELSE");
|
||||
depcase();
|
||||
break;
|
||||
|
||||
case I_DEPEND:
|
||||
if (stpflg)
|
||||
printf("DEPEND");
|
||||
break;
|
||||
|
||||
case I_RETURN:
|
||||
if (stpflg)
|
||||
printf("RETURN\n--------------------------------------------------\n");
|
||||
pc = oldpc;
|
||||
return;
|
||||
|
||||
default:
|
||||
syserr("Unknown STMOP instruction.");
|
||||
break;
|
||||
}
|
||||
if (fail) {
|
||||
pc = oldpc;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
syserr("Unknown instruction class.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
36
engines/glk/alan2/inter.h
Normal file
36
engines/glk/alan2/inter.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_INTER
|
||||
#define GLK_ALAN2_INTER
|
||||
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern void interpret(Aaddr adr);
|
||||
extern void interpret(CONTEXT, Aaddr adr);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
1417
engines/glk/alan2/main.cpp
Normal file
1417
engines/glk/alan2/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
127
engines/glk/alan2/main.h
Normal file
127
engines/glk/alan2/main.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_MAIN
|
||||
#define GLK_ALAN2_MAIN
|
||||
|
||||
/* Header file for main unit of ARUN Alan System interpreter */
|
||||
|
||||
#include "common/file.h"
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* DATA */
|
||||
|
||||
#define MEMORYSIZE 1000L
|
||||
|
||||
extern Aaddr memTop; // Top of memory
|
||||
|
||||
extern int conjWord; // First conjunction in dictionary
|
||||
|
||||
/* The Amachine memory */
|
||||
extern Aword *memory;
|
||||
extern AcdHdr *header;
|
||||
|
||||
/* Amachine variables */
|
||||
extern CurVars cur;
|
||||
|
||||
/* Amachine data structures */
|
||||
extern WrdElem *dict; /* Dictionary pointer */
|
||||
extern ActElem *acts; /* Actor table pointer */
|
||||
extern LocElem *locs; /* Location table pointer */
|
||||
extern VrbElem *vrbs; /* Verb table pointer */
|
||||
extern StxElem *stxs; /* Syntax table pointer */
|
||||
extern ObjElem *objs; /* Object table pointer */
|
||||
extern CntElem *cnts; /* Container table pointer */
|
||||
extern RulElem *ruls; /* Rule table pointer */
|
||||
extern EvtElem *evts; /* Event table pointer */
|
||||
extern MsgElem *msgs; /* Message table pointer */
|
||||
extern Aword *scores; /* Score table pointer */
|
||||
extern Aword *freq; /* Cumulated frequencies */
|
||||
|
||||
extern int dictsize; /* Number of entries in dictionary */
|
||||
|
||||
/* The text and message file */
|
||||
extern Common::File *txtfil;
|
||||
extern Common::WriteStream *logfil;
|
||||
extern Common::SeekableReadStream *codfil;
|
||||
|
||||
#undef ftell
|
||||
#undef fgetc
|
||||
#undef getc
|
||||
#undef fseek
|
||||
#undef fclose
|
||||
#define ftell(FP) FP->pos()
|
||||
#define fgetc(FP) (FP->pos() >= FP->size()) ? EOD : FP->readByte()
|
||||
#define getc(FP) (FP->pos() >= FP->size()) ? EOD : FP->readByte()
|
||||
#define fseek(FP, OFS, WHENCE) FP->seek(OFS, WHENCE)
|
||||
#define fclose(FP) delete FP
|
||||
|
||||
|
||||
/* File names */
|
||||
extern const char *advnam;
|
||||
|
||||
/* Screen formatting info */
|
||||
extern int col, lin;
|
||||
|
||||
extern Boolean verbose, errflg, trcflg, dbgflg, stpflg, logflg, statusflg;
|
||||
extern Boolean fail;
|
||||
extern Boolean anyOutput;
|
||||
extern Boolean needsp;
|
||||
|
||||
#define endOfTable(x) eot((const void *)x)
|
||||
|
||||
extern void *allocate(unsigned long len);
|
||||
extern void terminate(CONTEXT, int code);
|
||||
extern void usage(void);
|
||||
extern void error(CONTEXT, MsgKind msg);
|
||||
extern void syserr(const char *msg);
|
||||
extern void statusline(void);
|
||||
extern void output(const char string[]);
|
||||
extern void prmsg(MsgKind msg);
|
||||
extern void para(void);
|
||||
extern void newline(void);
|
||||
|
||||
extern Boolean checklim(Aword cnt, Aword obj);
|
||||
extern Boolean possible(void);
|
||||
extern Boolean exitto(int to, int from);
|
||||
extern void action(CONTEXT, ParamElem *plst);
|
||||
extern void go(CONTEXT, int dir);
|
||||
|
||||
extern Boolean eot(const void *adr);
|
||||
extern Boolean isObj(Aword x);
|
||||
extern Boolean isCnt(Aword x);
|
||||
extern Boolean isAct(Aword x);
|
||||
extern Boolean isLoc(Aword x);
|
||||
extern Boolean isLit(Aword x);
|
||||
extern Boolean isNum(Aword x);
|
||||
extern Boolean isStr(Aword x);
|
||||
|
||||
/* Run the game! */
|
||||
extern void run(void);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
100
engines/glk/alan2/params.cpp
Normal file
100
engines/glk/alan2/params.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/alan2/params.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
void compact(ParamElem a[]) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; a[j].code != (Aword)EOD; j++)
|
||||
if (a[j].code != 0)
|
||||
a[i++] = a[j];
|
||||
a[i].code = (Aword)EOD;
|
||||
}
|
||||
|
||||
int lstlen(ParamElem a[]) {
|
||||
int i = 0;
|
||||
|
||||
while (a[i].code != (Aword)EOD)
|
||||
i++;
|
||||
return (i);
|
||||
}
|
||||
|
||||
Boolean inlst(ParamElem l[], Aword e) {
|
||||
int i;
|
||||
|
||||
for (i = 0; l[i].code != (Aword)EOD && l[i].code != e; i++);
|
||||
return (l[i].code == e);
|
||||
}
|
||||
|
||||
void lstcpy(ParamElem a[], ParamElem b[]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; b[i].code != (Aword)EOD; i++)
|
||||
a[i] = b[i];
|
||||
a[i].code = (Aword)EOD;
|
||||
}
|
||||
|
||||
void sublst(ParamElem a[], ParamElem b[]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; a[i].code != (Aword)EOD; i++)
|
||||
if (inlst(b, a[i].code))
|
||||
a[i].code = 0; /* Mark empty */
|
||||
compact(a);
|
||||
}
|
||||
|
||||
void mrglst(ParamElem a[], ParamElem b[]) {
|
||||
int i, last;
|
||||
|
||||
for (last = 0; a[last].code != (Aword)EOD; last++); /* Find end of list */
|
||||
for (i = 0; b[i].code != (Aword)EOD; i++)
|
||||
if (!inlst(a, b[i].code)) {
|
||||
a[last++] = b[i];
|
||||
a[last].code = (Aword)EOD;
|
||||
}
|
||||
}
|
||||
|
||||
void isect(ParamElem a[], ParamElem b[]) {
|
||||
int i, last = 0;
|
||||
|
||||
for (i = 0; a[i].code != (Aword)EOD; i++)
|
||||
if (inlst(b, a[i].code))
|
||||
a[last++] = a[i];
|
||||
a[last].code = (Aword)EOD;
|
||||
}
|
||||
|
||||
void cpyrefs(ParamElem p[], Aword r[]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; r[i] != (Aword)EOD; i++) {
|
||||
p[i].code = r[i];
|
||||
p[i].firstWord = (Aword)EOD;
|
||||
}
|
||||
p[i].code = (Aword)EOD;
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
54
engines/glk/alan2/params.h
Normal file
54
engines/glk/alan2/params.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_PARAMS
|
||||
#define GLK_ALAN2_PARAMS
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
|
||||
/* Various utility functions for handling parameters:
|
||||
*
|
||||
* compact() Compact a list, i.e remove any NULL elements
|
||||
* lstlen() Count number of elements
|
||||
* inlst() Check if an element is in the list
|
||||
* sublst() Subract two lists
|
||||
* lstcpy() Copy one list onto another
|
||||
* mrglst() Merge the paramElems of one list into the first
|
||||
* isect() Take the intersection of two lists
|
||||
* cpyrefs() Copy the refs (in dictionary) to a paramList
|
||||
*/
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern void compact(ParamElem *a);
|
||||
extern int lstlen(ParamElem *a);
|
||||
extern Boolean inlst(ParamElem *l, Aword e);
|
||||
extern void lstcpy(ParamElem *a, ParamElem *b);
|
||||
extern void sublst(ParamElem *a, ParamElem *b);
|
||||
extern void mrglst(ParamElem *a, ParamElem *b);
|
||||
extern void isect(ParamElem *a, ParamElem *b);
|
||||
extern void cpyrefs(ParamElem *p, Aword *r);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
737
engines/glk/alan2/parse.cpp
Normal file
737
engines/glk/alan2/parse.cpp
Normal file
@@ -0,0 +1,737 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/alan2.h"
|
||||
#include "glk/alan2/debug.h"
|
||||
#include "glk/alan2/exe.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "glk/alan2/inter.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/params.h"
|
||||
#include "glk/alan2/parse.h"
|
||||
#include "glk/alan2/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
#define LISTLEN 100
|
||||
|
||||
|
||||
/* PUBLIC DATA */
|
||||
|
||||
Aword wrds[LISTLEN / 2] = {EOD}; // List of parsed words
|
||||
int wrdidx; // and an index into it
|
||||
|
||||
Boolean plural = FALSE;
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Literals */
|
||||
LitElem litValues[MAXPARAMS + 1];
|
||||
int litCount;
|
||||
|
||||
/* What did the user say? */
|
||||
int vrbwrd; /* The word he used */
|
||||
int vrbcode; /* The code for that verb */
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*\
|
||||
|
||||
SCAN DATA & PROCEDURES
|
||||
|
||||
All procedures for getting a command and turning it into a list of
|
||||
dictionary entries are placed here.
|
||||
|
||||
buf
|
||||
unknown()
|
||||
lookup()
|
||||
token
|
||||
agetline()
|
||||
scan()
|
||||
|
||||
\*----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* PRIVATE DATA */
|
||||
|
||||
static char buf[LISTLEN + 1]; /* The input buffer */
|
||||
static char isobuf[LISTLEN + 1]; /* The input buffer in ISO */
|
||||
|
||||
|
||||
static Boolean eol = TRUE; /* Looking at End of line? Yes, initially */
|
||||
|
||||
|
||||
static void unknown(CONTEXT, char token[]) {
|
||||
size_t ln = strlen(token) + 4;
|
||||
char *str = (char *)allocate((int)ln);
|
||||
|
||||
str[0] = '\'';
|
||||
Common::strcpy_s(&str[1], ln, token);
|
||||
Common::strcat_s(str, ln, "'?");
|
||||
output(str);
|
||||
free(str);
|
||||
eol = TRUE;
|
||||
CALL1(error, M_UNKNOWN_WORD)
|
||||
}
|
||||
|
||||
|
||||
static char *token;
|
||||
|
||||
|
||||
static int lookup(CONTEXT, char wrd[]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; !endOfTable(&dict[i]); i++) {
|
||||
if (strcmp(wrd, (char *) addrTo(dict[i].wrd)) == 0)
|
||||
return (i);
|
||||
}
|
||||
R0CALL1(unknown, wrd)
|
||||
return EOD;
|
||||
}
|
||||
|
||||
/* IN - The string to convert to a number */
|
||||
static int number(char tok[]) {
|
||||
int i;
|
||||
|
||||
(void)sscanf(tok, "%d", &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static char *gettoken(char *tokBuf) {
|
||||
static char *marker;
|
||||
static char oldch;
|
||||
|
||||
if (tokBuf == nullptr)
|
||||
*marker = oldch;
|
||||
else
|
||||
marker = tokBuf;
|
||||
while (*marker != '\0' && isSpace(*marker) && *marker != '\n') marker++;
|
||||
tokBuf = marker;
|
||||
if (isISOLetter(*marker))
|
||||
while (*marker && (isISOLetter(*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 tokBuf;
|
||||
}
|
||||
|
||||
static void agetline(CONTEXT) {
|
||||
para();
|
||||
do {
|
||||
statusline();
|
||||
|
||||
printf("> ");
|
||||
if (logflg)
|
||||
fprintf(logfil, "> ");
|
||||
|
||||
if (!readline(buf, sizeof(buf))) {
|
||||
if (g_vm->shouldQuit())
|
||||
return;
|
||||
|
||||
newline();
|
||||
CALL0(quit)
|
||||
}
|
||||
|
||||
anyOutput = FALSE;
|
||||
if (logflg)
|
||||
fprintf(logfil, "%s\n", buf);
|
||||
Common::strcpy_s(isobuf, buf);
|
||||
|
||||
token = gettoken(isobuf);
|
||||
if (token != nullptr && strcmp("debug", token) == 0 && header->debug) {
|
||||
dbgflg = TRUE;
|
||||
debug();
|
||||
token = nullptr;
|
||||
}
|
||||
} while (token == nullptr);
|
||||
eol = FALSE;
|
||||
lin = 1;
|
||||
}
|
||||
|
||||
static void scan(CONTEXT) {
|
||||
int i;
|
||||
int w;
|
||||
char *str;
|
||||
|
||||
CALL0(agetline)
|
||||
if (g_vm->shouldQuit())
|
||||
return;
|
||||
|
||||
wrds[0] = 0;
|
||||
for (i = 0; i < litCount; i++)
|
||||
if (litValues[i].type == TYPSTR && litValues[i].value != 0)
|
||||
free((char *) litValues[i].value);
|
||||
i = 0;
|
||||
litCount = 0;
|
||||
do {
|
||||
if (isISOLetter(token[0])) {
|
||||
(void) stringLower(token);
|
||||
FUNC1(lookup, w, token);
|
||||
|
||||
if (!isNoise(w))
|
||||
wrds[i++] = w;
|
||||
} else if (Common::isDigit(token[0])) {
|
||||
if (litCount > MAXPARAMS)
|
||||
syserr("Too many parameters.");
|
||||
wrds[i++] = dictsize + litCount; /* Word outside dictionary = literal */
|
||||
litValues[litCount].type = TYPNUM;
|
||||
litValues[litCount++].value = number(token);
|
||||
} else if (token[0] == '\"') {
|
||||
if (litCount > MAXPARAMS)
|
||||
syserr("Too many parameters.");
|
||||
wrds[i++] = dictsize + litCount; /* Word outside dictionary = literal */
|
||||
litValues[litCount].type = TYPSTR;
|
||||
/* Remove the string quotes while copying */
|
||||
str = scumm_strdup(&token[1]);
|
||||
str[strlen(token) - 2] = '\0';
|
||||
litValues[litCount++].value = (Aptr) str;
|
||||
} else if (token[0] == ',') {
|
||||
wrds[i++] = conjWord;
|
||||
} else {
|
||||
CALL1(unknown, token)
|
||||
}
|
||||
wrds[i] = EOD;
|
||||
eol = (token = gettoken(nullptr)) == nullptr;
|
||||
} while (!eol);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*\
|
||||
|
||||
PARSE DATA & PROCEDURES
|
||||
|
||||
All procedures and data for getting a command and parsing it
|
||||
|
||||
nonverb() - search for a non-verb command
|
||||
buildall() - build a list of objects matching 'all'
|
||||
unambig() - match an unambigous object reference
|
||||
simple() - match a simple verb command
|
||||
complex() - match a complex -"-
|
||||
tryMatch()- to match a verb command
|
||||
match() - find the verb class (not used currently) and 'tryMatch()'
|
||||
|
||||
\*---------------------------------------------------------------------- */
|
||||
|
||||
static int allLength; /* No. of objects matching 'all' */
|
||||
|
||||
|
||||
static void nonverb(CONTEXT) {
|
||||
if (isDir(wrds[wrdidx])) {
|
||||
wrdidx++;
|
||||
if (wrds[wrdidx] != EOD && !isConj(wrds[wrdidx])) {
|
||||
CALL1(error, M_WHAT)
|
||||
} else {
|
||||
CALL1(go, dict[wrds[wrdidx - 1]].code)
|
||||
}
|
||||
if (wrds[wrdidx] != EOD)
|
||||
wrdidx++;
|
||||
} else {
|
||||
CALL1(error, M_WHAT)
|
||||
}
|
||||
}
|
||||
|
||||
static void buildall(CONTEXT, ParamElem list[]) {
|
||||
int i = 0;
|
||||
Boolean found = FALSE;
|
||||
|
||||
for (uint o = OBJMIN; o <= OBJMAX; o++)
|
||||
if (isHere(o)) {
|
||||
found = TRUE;
|
||||
list[i].code = o;
|
||||
list[i++].firstWord = EOD;
|
||||
}
|
||||
if (!found) {
|
||||
CALL1(error, M_WHAT_ALL)
|
||||
} else {
|
||||
list[i].code = EOD;
|
||||
}
|
||||
}
|
||||
|
||||
static void unambig(CONTEXT, ParamElem plst[]) {
|
||||
int i;
|
||||
Boolean found = FALSE; /* Adjective or noun found ? */
|
||||
static ParamElem *refs; /* Entities referenced by word */
|
||||
static ParamElem *savlst; /* Saved list for backup at EOD */
|
||||
int firstWord, lastWord; /* The words the player used */
|
||||
|
||||
if (refs == nullptr)
|
||||
refs = (ParamElem *)allocate((MAXENTITY + 1) * sizeof(ParamElem));
|
||||
|
||||
if (savlst == nullptr)
|
||||
savlst = (ParamElem *)allocate((MAXENTITY + 1) * sizeof(ParamElem));
|
||||
|
||||
if (isLiteral(wrds[wrdidx])) {
|
||||
/* Transform the word into a reference to the literal value */
|
||||
plst[0].code = wrds[wrdidx++] - dictsize + LITMIN;
|
||||
plst[0].firstWord = EOD; /* No words used! */
|
||||
plst[1].code = EOD;
|
||||
return;
|
||||
}
|
||||
|
||||
plst[0].code = EOD; /* Make empty */
|
||||
if (isIt(wrds[wrdidx])) {
|
||||
wrdidx++;
|
||||
/* Use last object in previous command! */
|
||||
for (i = lstlen(pparams) - 1; i >= 0 && (pparams[i].code == 0 || pparams[i].code >= LITMIN); i--);
|
||||
if (i < 0) {
|
||||
CALL1(error, M_WHAT_IT)
|
||||
}
|
||||
if (!isHere(pparams[i].code)) {
|
||||
params[0].code = pparams[i].code;
|
||||
params[0].firstWord = EOD;
|
||||
params[1].code = EOD;
|
||||
CALL1(error, M_NO_SUCH)
|
||||
}
|
||||
plst[0] = pparams[i];
|
||||
plst[0].firstWord = EOD; /* No words used! */
|
||||
plst[1].code = EOD;
|
||||
return;
|
||||
}
|
||||
|
||||
firstWord = wrdidx;
|
||||
while (wrds[wrdidx] != EOD && 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] == EOD || !isNoun(wrds[wrdidx + 1])))
|
||||
break;
|
||||
cpyrefs(refs, (Aword *)addrTo(dict[wrds[wrdidx]].adjrefs));
|
||||
lstcpy(savlst, plst); /* To save it for backtracking */
|
||||
if (found)
|
||||
isect(plst, refs);
|
||||
else {
|
||||
lstcpy(plst, refs);
|
||||
found = TRUE;
|
||||
}
|
||||
wrdidx++;
|
||||
}
|
||||
if (wrds[wrdidx] != EOD) {
|
||||
if (isNoun(wrds[wrdidx])) {
|
||||
cpyrefs(refs, (Aword *)addrTo(dict[wrds[wrdidx]].nounrefs));
|
||||
if (found)
|
||||
isect(plst, refs);
|
||||
else {
|
||||
lstcpy(plst, refs);
|
||||
found = TRUE;
|
||||
}
|
||||
wrdidx++;
|
||||
} else
|
||||
CALL1(error, M_NOUN)
|
||||
} else if (found) {
|
||||
if (isNoun(wrds[wrdidx - 1])) {
|
||||
/* Perhaps the last word was also a noun? */
|
||||
lstcpy(plst, savlst); /* Restore to before last adjective */
|
||||
cpyrefs(refs, (Aword *)addrTo(dict[wrds[wrdidx - 1]].nounrefs));
|
||||
if (plst[0].code == EOD)
|
||||
lstcpy(plst, refs);
|
||||
else
|
||||
isect(plst, refs);
|
||||
} else {
|
||||
CALL1(error, M_NOUN)
|
||||
}
|
||||
}
|
||||
lastWord = wrdidx - 1;
|
||||
|
||||
/* Allow remote objects, but resolve ambiguities by presence */
|
||||
if (lstlen(plst) > 1) {
|
||||
for (i = 0; plst[i].code != EOD; i++)
|
||||
if (!isHere(plst[i].code))
|
||||
plst[i].code = 0;
|
||||
compact(plst);
|
||||
}
|
||||
|
||||
if (lstlen(plst) > 1 || (found && lstlen(plst) == 0)) {
|
||||
params[0].code = 0; /* Just make it anything != EOD */
|
||||
params[0].firstWord = firstWord; /* Remember words for errors below */
|
||||
params[0].lastWord = lastWord;
|
||||
params[1].code = EOD; /* But be sure to terminate */
|
||||
if (lstlen(plst) > 1) {
|
||||
CALL1(error, M_WHICH_ONE)
|
||||
} else if (found && lstlen(plst) == 0) {
|
||||
CALL1(error, M_NO_SUCH)
|
||||
}
|
||||
} else {
|
||||
plst[0].firstWord = firstWord;
|
||||
plst[0].lastWord = lastWord;
|
||||
}
|
||||
}
|
||||
|
||||
static void simple(CONTEXT, ParamElem olst[]) {
|
||||
static ParamElem *tlst = nullptr;
|
||||
int savidx = wrdidx;
|
||||
Boolean savplur = FALSE;
|
||||
int i;
|
||||
|
||||
if (tlst == nullptr)
|
||||
tlst = (ParamElem *) allocate(sizeof(ParamElem) * (MAXENTITY + 1));
|
||||
tlst[0].code = EOD;
|
||||
|
||||
for (;;) {
|
||||
if (isThem(wrds[wrdidx])) {
|
||||
plural = TRUE;
|
||||
for (i = 0; pmlst[i].code != EOD; i++)
|
||||
if (!isHere(pmlst[i].code))
|
||||
pmlst[i].code = 0;
|
||||
compact(pmlst);
|
||||
if (lstlen(pmlst) == 0) {
|
||||
CALL1(error, M_WHAT_THEM)
|
||||
}
|
||||
|
||||
lstcpy(olst, pmlst);
|
||||
olst[0].firstWord = EOD; /* No words used */
|
||||
wrdidx++;
|
||||
} else {
|
||||
// Look for unambigous noun phrase
|
||||
CALL1(unambig, olst)
|
||||
if (lstlen(olst) == 0) { /* Failed! */
|
||||
lstcpy(olst, tlst);
|
||||
wrdidx = savidx;
|
||||
plural = savplur;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mrglst(tlst, olst);
|
||||
if (wrds[wrdidx] != EOD
|
||||
&& (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 {
|
||||
lstcpy(olst, tlst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
complex()
|
||||
|
||||
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 void complex(CONTEXT, ParamElem olst[]) {
|
||||
static ParamElem *alst = nullptr;
|
||||
|
||||
if (alst == nullptr)
|
||||
alst = (ParamElem *) allocate((MAXENTITY + 1) * sizeof(ParamElem));
|
||||
|
||||
if (isAll(wrds[wrdidx])) {
|
||||
plural = TRUE;
|
||||
// Build list of all objects
|
||||
CALL1(buildall, alst)
|
||||
wrdidx++;
|
||||
if (wrds[wrdidx] != EOD && isBut(wrds[wrdidx])) {
|
||||
wrdidx++;
|
||||
CALL1(simple, olst)
|
||||
if (lstlen(olst) == 0)
|
||||
CALL1(error, M_AFTER_BUT)
|
||||
sublst(alst, olst);
|
||||
if (lstlen(alst) == 0)
|
||||
CALL1(error, M_NOT_MUCH)
|
||||
}
|
||||
lstcpy(olst, alst);
|
||||
allLength = lstlen(olst);
|
||||
} else {
|
||||
// Look for simple noun group
|
||||
CALL1(simple, olst)
|
||||
}
|
||||
}
|
||||
|
||||
static Boolean claCheck(ClaElem *cla /* IN - The cla elem to check */) {
|
||||
Boolean 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;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
resolve()
|
||||
|
||||
In case the syntax did not indicate omnipotent powers (allowed
|
||||
access to remote object), we need to remove non-present parameters
|
||||
|
||||
*/
|
||||
static void resolve(CONTEXT, ParamElem plst[]) {
|
||||
int i;
|
||||
|
||||
if (allLength > 0) return; /* ALL has already done this */
|
||||
|
||||
/* Resolve ambiguities by presence */
|
||||
for (i = 0; plst[i].code != EOD; 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 = EOD; /* But be sure to terminate */
|
||||
CALL1(error, M_NO_SUCH)
|
||||
}
|
||||
}
|
||||
|
||||
/* OUT - List of params allowed by multiple */
|
||||
static void tryMatch(CONTEXT, ParamElem matchLst[]) {
|
||||
ElmElem *elms; /* Pointer to element list */
|
||||
StxElem *stx; /* Pointer to syntax list */
|
||||
ClaElem *cla; /* Pointer to class definitions */
|
||||
Boolean anyPlural = FALSE; /* Any parameter that was plural? */
|
||||
int i, p;
|
||||
static ParamElem *tlst = nullptr; /* List of params found by complex() */
|
||||
static Boolean *checked = nullptr; /* Corresponding parameter checked? */
|
||||
|
||||
if (tlst == nullptr) {
|
||||
tlst = (ParamElem *) allocate((MAXENTITY + 1) * sizeof(ParamElem));
|
||||
checked = (Boolean *) allocate((MAXENTITY + 1) * sizeof(Boolean));
|
||||
}
|
||||
|
||||
for (stx = stxs; !endOfTable(stx); stx++)
|
||||
if ((int)stx->code == vrbcode)
|
||||
break;
|
||||
if (endOfTable(stx)) {
|
||||
CALL1(error, M_WHAT)
|
||||
}
|
||||
|
||||
elms = (ElmElem *) addrTo(stx->elms);
|
||||
|
||||
while (TRUE) {
|
||||
/* End of input? */
|
||||
if (wrds[wrdidx] == EOD || isConj(wrds[wrdidx])) {
|
||||
while (!endOfTable(elms) && elms->code != EOS)
|
||||
elms++;
|
||||
if (endOfTable(elms)) {
|
||||
CALL1(error, M_WHAT)
|
||||
} else
|
||||
break;
|
||||
} else {
|
||||
/* A preposition? */
|
||||
if (isPrep(wrds[wrdidx])) {
|
||||
while (!endOfTable(elms) && elms->code != dict[wrds[wrdidx]].code)
|
||||
elms++;
|
||||
if (endOfTable(elms)) {
|
||||
CALL1(error, M_WHAT)
|
||||
} else
|
||||
wrdidx++;
|
||||
} else {
|
||||
/* Must be a parameter! */
|
||||
while (!endOfTable(elms) && elms->code != 0)
|
||||
elms++;
|
||||
if (endOfTable(elms)) {
|
||||
CALL1(error, M_WHAT)
|
||||
}
|
||||
/* Get it! */
|
||||
plural = FALSE;
|
||||
CALL1(complex, tlst)
|
||||
if (lstlen(tlst) == 0) {
|
||||
/* No object!? */
|
||||
CALL1(error, M_WHAT)
|
||||
}
|
||||
/* Omnipotent parameter? */
|
||||
if ((elms->flags & OMNIBIT) == 0) {
|
||||
/* If its not an omnipotent parameter, resolve by presence */
|
||||
CALL1(resolve, tlst)
|
||||
}
|
||||
if (plural) {
|
||||
/* Allowed multiple? */
|
||||
if ((elms->flags & MULTIPLEBIT) == 0) {
|
||||
CALL1(error, M_MULTIPLE)
|
||||
} else {
|
||||
/*
|
||||
Mark this as the multiple position in which to insert
|
||||
actual parameter values later
|
||||
*/
|
||||
params[paramidx++].code = 0;
|
||||
lstcpy(matchLst, tlst);
|
||||
anyPlural = TRUE;
|
||||
}
|
||||
} else
|
||||
params[paramidx++] = tlst[0];
|
||||
params[paramidx].code = EOD;
|
||||
}
|
||||
elms = (ElmElem *) addrTo(elms->next);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now perform class checks */
|
||||
if (elms->next == 0) {
|
||||
/* No verb code, verb not declared! */
|
||||
CALL1(error, M_CANT0)
|
||||
}
|
||||
|
||||
for (p = 0; params[p].code != EOD; 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; matchLst[i].code != EOD; i++) {
|
||||
params[cla->code - 1] = matchLst[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
|
||||
*/
|
||||
Common::sprintf_s(marker, "($%ld)", (unsigned long) cla->code);
|
||||
output(marker);
|
||||
interpret(cla->stms);
|
||||
para();
|
||||
}
|
||||
matchLst[i].code = 0; /* In any case remove it from the list */
|
||||
}
|
||||
}
|
||||
params[cla->code - 1].code = 0;
|
||||
} else {
|
||||
if (!claCheck(cla)) {
|
||||
/* Return to player without saying anything */
|
||||
interpret(cla->stms);
|
||||
CALL1(error, MSGMAX)
|
||||
}
|
||||
}
|
||||
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 != EOD; p++)
|
||||
if (!checked[p]) {
|
||||
if (params[p].code == 0) {
|
||||
/* This was a multiple parameter, check all and remove failing */
|
||||
for (i = 0; matchLst[i].code != EOD; i++)
|
||||
if (matchLst[i].code != 0) /* Skip any empty slots */
|
||||
if (!isObj(matchLst[i].code))
|
||||
matchLst[i].code = 0;
|
||||
} else if (!isObj(params[p].code)) {
|
||||
CALL1(error, M_CANT0)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set verb code */
|
||||
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 (matchLst[i].code != 0) { /* Already empty? */
|
||||
params[p] = matchLst[i];
|
||||
if (!possible())
|
||||
matchLst[i].code = 0; /* Remove this from list */
|
||||
}
|
||||
}
|
||||
params[p].code = 0; /* Restore multiple marker */
|
||||
compact(matchLst);
|
||||
if (lstlen(matchLst) == 0) {
|
||||
params[0].code = EOD;
|
||||
CALL1(error, M_WHAT_ALL)
|
||||
}
|
||||
} else if (anyPlural) {
|
||||
compact(matchLst);
|
||||
if (lstlen(matchLst) == 0)
|
||||
/* If there where multiple parameters but non left, exit without a */
|
||||
/* word, assuming we have already said enough */
|
||||
CALL1(error, MSGMAX)
|
||||
}
|
||||
plural = anyPlural; /* Remember that we found plural objects */
|
||||
}
|
||||
|
||||
/* OUT - List of params allowed by multiple */
|
||||
static void match(CONTEXT, ParamElem *matchLst) {
|
||||
/* ... to understand what he said */
|
||||
CALL1(tryMatch, matchLst)
|
||||
if (wrds[wrdidx] != EOD && !isConj(wrds[wrdidx])) {
|
||||
CALL1(error, M_WHAT)
|
||||
}
|
||||
if (wrds[wrdidx] != EOD) /* More on this line? */
|
||||
wrdidx++; /* If so skip the AND */
|
||||
}
|
||||
|
||||
void parse(CONTEXT) {
|
||||
if (mlst == nullptr) { /* Allocate large enough paramlists */
|
||||
mlst = (ParamElem *) allocate(sizeof(ParamElem) * (MAXENTITY + 1));
|
||||
mlst[0].code = EOD;
|
||||
pmlst = (ParamElem *) allocate(sizeof(ParamElem) * (MAXENTITY + 1));
|
||||
params = (ParamElem *) allocate(sizeof(ParamElem) * (MAXENTITY + 1));
|
||||
params[0].code = EOD;
|
||||
pparams = (ParamElem *) allocate(sizeof(ParamElem) * (MAXENTITY + 1));
|
||||
}
|
||||
|
||||
if (wrds[wrdidx] == EOD) {
|
||||
wrdidx = 0;
|
||||
CALL0(scan)
|
||||
|
||||
if (g_vm->shouldQuit())
|
||||
return;
|
||||
} else if (anyOutput)
|
||||
para();
|
||||
|
||||
allLength = 0;
|
||||
paramidx = 0;
|
||||
lstcpy(pparams, params);
|
||||
params[0].code = EOD;
|
||||
lstcpy(pmlst, mlst);
|
||||
mlst[0].code = EOD;
|
||||
if (isVerb(wrds[wrdidx])) {
|
||||
vrbwrd = wrds[wrdidx];
|
||||
vrbcode = dict[vrbwrd].code;
|
||||
wrdidx++;
|
||||
CALL1(match, mlst)
|
||||
/* mlst contains possible multiple params */
|
||||
CALL1(action, mlst)
|
||||
} else {
|
||||
params[0].code = EOD;
|
||||
pmlst[0].code = EOD;
|
||||
CALL0(nonverb)
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
49
engines/glk/alan2/parse.h
Normal file
49
engines/glk/alan2/parse.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_PARSE
|
||||
#define GLK_ALAN2_PARSE
|
||||
|
||||
/* Parse data for ALAN interpreter module. */
|
||||
|
||||
#include "engines/glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern Aword wrds[]; // List of Parsed Word
|
||||
extern int wrdidx; // and an index into it
|
||||
|
||||
extern ParamElem *params; // List of parameters
|
||||
extern Boolean plural;
|
||||
|
||||
extern LitElem litValues[];
|
||||
extern int litCount;
|
||||
|
||||
extern int vrbwrd;
|
||||
|
||||
// Parse a new player command
|
||||
extern void parse(CONTEXT);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
384
engines/glk/alan2/reverse.cpp
Normal file
384
engines/glk/alan2/reverse.cpp
Normal file
@@ -0,0 +1,384 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/reverse.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
reversed()
|
||||
|
||||
Return the reversed bytes in the Aword
|
||||
|
||||
*/
|
||||
Aword reversed(Aword w /* IN - The ACODE word to swap bytes of */) {
|
||||
Aword s; /* The swapped ACODE word */
|
||||
char *wp, *sp;
|
||||
|
||||
wp = (char *) &w;
|
||||
sp = (char *) &s;
|
||||
|
||||
for (uint i = 0; i < sizeof(Aword); i++)
|
||||
sp[sizeof(Aword) - 1 - i] = wp[i];
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void reverse(Aword *w /* IN - The ACODE word to reverse bytes in */) {
|
||||
*w = reversed(*w);
|
||||
}
|
||||
|
||||
static void reverseTable(Aword adr, int len) {
|
||||
Aword *e = &memory[adr];
|
||||
int i;
|
||||
|
||||
if (adr != 0)
|
||||
while (!endOfTable(e)) {
|
||||
for (i = 0; i < len / (int)sizeof(Aword); i++) {
|
||||
reverse(e);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseStms(Aword adr) {
|
||||
Aword *e = &memory[adr];
|
||||
|
||||
if (adr != 0)
|
||||
while (TRUE) {
|
||||
reverse(e);
|
||||
if (*e == ((Aword)C_STMOP << 28 | (Aword)I_RETURN)) break;
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseMsgs(Aword adr) {
|
||||
MsgElem *e = (MsgElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(MsgElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseWrds(Aword adr) {
|
||||
WrdElem *e = (WrdElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(WrdElem));
|
||||
while (!endOfTable(e)) {
|
||||
if ((e->_class & (1L << WRD_SYN)) == 0) { /* Do not do this for synonyms */
|
||||
reverseTable(e->adjrefs, sizeof(Aword));
|
||||
reverseTable(e->nounrefs, sizeof(Aword));
|
||||
}
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseChks(Aword adr) {
|
||||
ChkElem *e = (ChkElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ChkElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->exp);
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseAlts(Aword adr) {
|
||||
AltElem *e = (AltElem *)&memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e) && !e->done) {
|
||||
reverseTable(adr, sizeof(AltElem));
|
||||
e->done = TRUE;
|
||||
while (!endOfTable(e)) {
|
||||
reverseChks(e->checks);
|
||||
reverseStms(e->action);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseVrbs(Aword adr) {
|
||||
VrbElem *e = (VrbElem *)&memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(VrbElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseAlts(e->alts);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseSteps(Aword adr) {
|
||||
StepElem *e = (StepElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(StepElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->exp);
|
||||
reverseStms(e->stm);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseScrs(Aword adr) {
|
||||
ScrElem *e = (ScrElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ScrElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->dscr);
|
||||
reverseSteps(e->steps);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseActs(Aword adr) {
|
||||
ActElem *e = (ActElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ActElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->nam);
|
||||
reverseTable(e->atrs, sizeof(AtrElem));
|
||||
reverseScrs(e->scradr);
|
||||
reverseVrbs(e->vrbs);
|
||||
reverseStms(e->dscr);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseObjs(Aword adr, Boolean v2_5) {
|
||||
ObjElem *e = (ObjElem *) &memory[adr];
|
||||
ObjElem25 *e25 = (ObjElem25 *) &memory[adr];
|
||||
|
||||
if (v2_5) {
|
||||
if (adr != 0 && !endOfTable(e25)) {
|
||||
reverseTable(adr, sizeof(ObjElem25));
|
||||
while (!endOfTable(e25)) {
|
||||
reverseTable(e25->atrs, sizeof(AtrElem));
|
||||
reverseVrbs(e25->vrbs);
|
||||
reverseStms(e25->dscr1);
|
||||
reverseStms(e25->dscr2);
|
||||
e25++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ObjElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseTable(e->atrs, sizeof(AtrElem));
|
||||
reverseVrbs(e->vrbs);
|
||||
reverseStms(e->art);
|
||||
reverseStms(e->dscr1);
|
||||
reverseStms(e->dscr2);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseExts(Aword adr) {
|
||||
ExtElem *e = (ExtElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ExtElem));
|
||||
while (!endOfTable(e)) {
|
||||
if (!e->done) {
|
||||
reverseChks(e->checks);
|
||||
reverseStms(e->action);
|
||||
}
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseLocs(Aword adr) {
|
||||
LocElem *e = (LocElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(LocElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->nams);
|
||||
reverseStms(e->dscr);
|
||||
reverseStms(e->does);
|
||||
reverseTable(e->atrs, sizeof(AtrElem));
|
||||
reverseExts(e->exts);
|
||||
reverseVrbs(e->vrbs);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseClas(Aword adr) {
|
||||
ClaElem *e = (ClaElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ClaElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
if (adr)
|
||||
reverse(&((Aword *)e)[1]); /* The verb code is stored after the table */
|
||||
}
|
||||
|
||||
static void reverseElms(Aword adr) {
|
||||
ElmElem *e = (ElmElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(ElmElem));
|
||||
while (!endOfTable(e)) {
|
||||
if (e->code == EOS) reverseClas(e->next);
|
||||
else reverseElms(e->next);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseStxs(Aword adr) {
|
||||
StxElem *e = (StxElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(StxElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseElms(e->elms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseEvts(Aword adr) {
|
||||
EvtElem *e = (EvtElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(EvtElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->code);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseLims(Aword adr) {
|
||||
LimElem *e = (LimElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(LimElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseCnts(Aword adr) {
|
||||
CntElem *e = (CntElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(CntElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseLims(e->lims);
|
||||
reverseStms(e->header);
|
||||
reverseStms(e->empty);
|
||||
reverseStms(e->nam);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reverseRuls(Aword adr) {
|
||||
RulElem *e = (RulElem *) &memory[adr];
|
||||
|
||||
if (adr != 0 && !endOfTable(e)) {
|
||||
reverseTable(adr, sizeof(RulElem));
|
||||
while (!endOfTable(e)) {
|
||||
reverseStms(e->exp);
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
reverseHdr()
|
||||
|
||||
Reverse the header structure.
|
||||
|
||||
*/
|
||||
void reverseHdr(AcdHdr *hdr) {
|
||||
// Reverse all words in the header except the first (version marking)
|
||||
for (uint i = 1; i < sizeof(AcdHdr) / sizeof(Aword); i++)
|
||||
reverse(&((Aword *)hdr)[i]);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
reverseACD()
|
||||
|
||||
Traverse all the data structures and reverse all integers.
|
||||
Only performed in architectures with reversed byte ordering, which
|
||||
makes the .ACD files fully compatible across architectures
|
||||
|
||||
*/
|
||||
void reverseACD(Boolean v2_5) {
|
||||
reverseHdr(header);
|
||||
reverseWrds(header->dict);
|
||||
reverseTable(header->oatrs, sizeof(AtrElem));
|
||||
reverseTable(header->latrs, sizeof(AtrElem));
|
||||
reverseTable(header->aatrs, sizeof(AtrElem));
|
||||
reverseActs(header->acts);
|
||||
reverseObjs(header->objs, v2_5);
|
||||
reverseLocs(header->locs);
|
||||
reverseStxs(header->stxs);
|
||||
reverseVrbs(header->vrbs);
|
||||
reverseEvts(header->evts);
|
||||
reverseCnts(header->cnts);
|
||||
reverseRuls(header->ruls);
|
||||
reverseTable(header->init, sizeof(IniElem));
|
||||
reverseStms(header->start);
|
||||
reverseMsgs(header->msgs);
|
||||
|
||||
reverseTable(header->scores, sizeof(Aword));
|
||||
reverseTable(header->freq, sizeof(Aword));
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
36
engines/glk/alan2/reverse.h
Normal file
36
engines/glk/alan2/reverse.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_REVERSE
|
||||
#define GLK_ALAN2_REVERSE
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
extern void reverseHdr(AcdHdr *hdr);
|
||||
extern void reverseACD(Boolean v25);
|
||||
extern void reverse(Aword *word);
|
||||
extern Aword reversed(Aword word);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
75
engines/glk/alan2/rules.cpp
Normal file
75
engines/glk/alan2/rules.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/alan2/debug.h"
|
||||
#include "glk/alan2/exe.h"
|
||||
#include "glk/alan2/inter.h"
|
||||
#include "glk/alan2/glkio.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/rules.h"
|
||||
#include "glk/alan2/stack.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
void rules() {
|
||||
Boolean 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) {
|
||||
printf("\n<RULE %d (at ", i);
|
||||
debugsay(cur.loc);
|
||||
if (!stpflg)
|
||||
printf("), Evaluating");
|
||||
else
|
||||
printf("), Evaluating:>\n");
|
||||
}
|
||||
interpret(ruls[i - 1].exp);
|
||||
if (pop()) {
|
||||
change = TRUE;
|
||||
ruls[i - 1].run = TRUE;
|
||||
if (trcflg) {
|
||||
if (!stpflg)
|
||||
printf(", Executing:>\n");
|
||||
else {
|
||||
printf("\nRULE %d (at ", i);
|
||||
debugsay(cur.loc);
|
||||
printf("), Executing:>\n");
|
||||
}
|
||||
}
|
||||
|
||||
interpret(ruls[i - 1].stms);
|
||||
} else if (trcflg && !stpflg)
|
||||
printf(":>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
37
engines/glk/alan2/rules.h
Normal file
37
engines/glk/alan2/rules.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_RULES
|
||||
#define GLK_ALAN2_RULES
|
||||
|
||||
/* Header file for rules handler in Alan interpreter */
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* TYPES */
|
||||
|
||||
extern void rules(void);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
55
engines/glk/alan2/stack.cpp
Normal file
55
engines/glk/alan2/stack.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
#include "glk/alan2/main.h"
|
||||
#include "glk/alan2/stack.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* PRIVATE DATA */
|
||||
|
||||
#define STACKSIZE 100
|
||||
|
||||
/* The AMACHINE STACK */
|
||||
static Aptr stack[STACKSIZE];
|
||||
static int stackp = 0;
|
||||
|
||||
|
||||
void push(Aptr i) {
|
||||
if (stackp == STACKSIZE)
|
||||
syserr("Out of stack space.");
|
||||
stack[stackp++] = i;
|
||||
}
|
||||
|
||||
Aptr pop() {
|
||||
if (stackp == 0)
|
||||
syserr("Stack underflow.");
|
||||
return (stack[--stackp]);
|
||||
}
|
||||
|
||||
Aptr top() {
|
||||
return (stack[stackp - 1]);
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
39
engines/glk/alan2/stack.h
Normal file
39
engines/glk/alan2/stack.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_STACK
|
||||
#define GLK_ALAN2_STACK
|
||||
|
||||
/* Header file for stack handler in Alan interpreter */
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* TYPES */
|
||||
|
||||
extern Aptr pop(void);
|
||||
extern void push(Aptr item);
|
||||
extern Aptr top(void);
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
311
engines/glk/alan2/sysdep.cpp
Normal file
311
engines/glk/alan2/sysdep.cpp
Normal file
@@ -0,0 +1,311 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/alan2.h"
|
||||
#include "glk/alan2/sysdep.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
void syserr(char str[]);
|
||||
|
||||
void fprintf(Common::WriteStream *ws, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
Common::String s = Common::String::vformat(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
ws->write(s.c_str(), s.size());
|
||||
}
|
||||
|
||||
/* Note to Glk maintainers: 'native' characters are used for output, in this
|
||||
case, Glk's Latin-1. ISO characters are Alan's internal representation,
|
||||
stored in the .DAT file, and must be converted to native before printing.
|
||||
Glk could just use the ISO routines directly, but its safer to maintain
|
||||
its own tables to guard against future changes in either Alan or Glk (ie. a
|
||||
move to Unicode).
|
||||
*/
|
||||
|
||||
static char spcChrs[] = {
|
||||
'\x0A', /* linefeed */
|
||||
'\x20', /* space */
|
||||
'\xA0', /* non-breaking space */
|
||||
'\x00'
|
||||
};
|
||||
|
||||
static char lowChrs[] = {
|
||||
'\x61', /* a */ '\x62', /* b */ '\x63', /* c */ '\x64', /* d */
|
||||
'\x65', /* e */ '\x66', /* f */ '\x67', /* g */ '\x68', /* h */
|
||||
'\x69', /* i */ '\x6A', /* j */ '\x6B', /* k */ '\x6C', /* l */
|
||||
'\x6D', /* m */ '\x6E', /* n */ '\x6F', /* o */ '\x70', /* p */
|
||||
'\x71', /* q */ '\x72', /* r */ '\x73', /* s */ '\x74', /* t */
|
||||
'\x75', /* u */ '\x76', /* v */ '\x77', /* w */ '\x78', /* x */
|
||||
'\x79', /* y */ '\x7A', /* z */ '\xDF', /* ss <small sharp s> */
|
||||
'\xE0', /* a grave */ '\xE1', /* a acute */
|
||||
'\xE2', /* a circumflex */ '\xE3', /* a tilde */
|
||||
'\xE4', /* a diaeresis */ '\xE5', /* a ring */
|
||||
'\xE6', /* ae */ '\xE7', /* c cedilla */
|
||||
'\xE8', /* e grave */ '\xE9', /* e acute */
|
||||
'\xEA', /* e circumflex */ '\xEB', /* e diaeresis */
|
||||
'\xEC', /* i grave */ '\xED', /* i acute */
|
||||
'\xEE', /* i circumflex */ '\xEF', /* i diaeresis */
|
||||
'\xF0', /* <small eth> */ '\xF1', /* n tilde */
|
||||
'\xF2', /* o grave */ '\xF3', /* o acute */
|
||||
'\xF4', /* o circumflex */ '\xF5', /* o tilde */
|
||||
'\xF6', /* o diaeresis */ '\xF8', /* o slash */
|
||||
'\xF9', /* u grave */ '\xFA', /* u acute */
|
||||
'\xFB', /* u circumflex */ '\xFC', /* u diaeresis */
|
||||
'\xFD', /* y acute */ '\xFE', /* <small thorn> */
|
||||
'\xFF', /* y diaeresis */ '\x00'
|
||||
};
|
||||
|
||||
/* FIXME: ss <small sharp s> and y diaeresis have no UC analogues
|
||||
Are they really considered LC?
|
||||
*/
|
||||
|
||||
static char uppChrs[] = {
|
||||
'\x41', /* A */ '\x42', /* B */ '\x43', /* C */ '\x44', /* D */
|
||||
'\x45', /* E */ '\x46', /* F */ '\x47', /* G */ '\x48', /* H */
|
||||
'\x49', /* I */ '\x4A', /* J */ '\x4B', /* K */ '\x4C', /* L */
|
||||
'\x4D', /* M */ '\x4E', /* N */ '\x4F', /* O */ '\x50', /* P */
|
||||
'\x51', /* Q */ '\x52', /* R */ '\x53', /* S */ '\x54', /* T */
|
||||
'\x55', /* U */ '\x56', /* V */ '\x57', /* W */ '\x58', /* X */
|
||||
'\x59', /* Y */ '\x5A', /* Z */
|
||||
'\xC0', /* A grave */ '\xC1', /* A acute */
|
||||
'\xC2', /* A circumflex */ '\xC3', /* A tilde */
|
||||
'\xC4', /* A diaeresis */ '\xC5', /* A ring */
|
||||
'\xC6', /* AE */ '\xC7', /* C cedilla */
|
||||
'\xC8', /* E grave */ '\xC9', /* E acute */
|
||||
'\xCA', /* E circumflex */ '\xCB', /* E diaeresis */
|
||||
'\xCC', /* I grave */ '\xCD', /* I acute */
|
||||
'\xCE', /* I circumflex */ '\xCF', /* I diaeresis */
|
||||
'\xD0', /* <capital eth> */ '\xD1', /* N tilde */
|
||||
'\xD2', /* O grave */ '\xD3', /* O acute */
|
||||
'\xD4', /* O circumflex */ '\xD5', /* O tilde */
|
||||
'\xD6', /* O diaeresis */ '\xD8', /* O slash */
|
||||
'\xD9', /* U grave */ '\xDA', /* U acute */
|
||||
'\xDB', /* U circumflex */ '\xDC', /* U diaeresis */
|
||||
'\xDD', /* Y acute */ '\xDE', /* <capital thorn> */
|
||||
'\x00'
|
||||
};
|
||||
|
||||
|
||||
int isSpace(int c) { /* IN - Native character to test */
|
||||
return (c != '\0' && strchr(spcChrs, c) != nullptr);
|
||||
}
|
||||
|
||||
|
||||
int isLower(int c) { /* IN - Native character to test */
|
||||
return (c != '\0' && strchr(lowChrs, c) != nullptr);
|
||||
}
|
||||
|
||||
|
||||
int isUpper(int c) { /* IN - Native character to test */
|
||||
return (c != '\0' && strchr(uppChrs, c) != nullptr);
|
||||
}
|
||||
|
||||
int isLetter(int c) { /* IN - Native character to test */
|
||||
return (c != '\0' && (isLower(c) ? !0 : isUpper(c)));
|
||||
}
|
||||
|
||||
|
||||
int toLower(int c) { /* IN - Native character to convert */
|
||||
return g_vm->glk_char_to_lower(c);
|
||||
}
|
||||
|
||||
int toUpper(int c) { /* IN - Native character to convert */
|
||||
return g_vm->glk_char_to_upper(c);
|
||||
}
|
||||
|
||||
char *strlow(char str[]) { /* INOUT - Native string to convert */
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = toLower(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
char *strupp(char str[]) { /* INOUT - Native string to convert */
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = toUpper(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
/* The following work on ISO characters */
|
||||
|
||||
int isLowerCase(int c) { /* IN - ISO character to test */
|
||||
static char lowChars[] = "abcdefghijklmnopqrstuvwxyz\340\341\342\343\344\345\346\347\351\352\353\354\355\356\357\360\361\362\363\364\365\366\370\371\372\373\374\375\376\377";
|
||||
return (c != '\0' && strchr(lowChars, c) != nullptr);
|
||||
}
|
||||
|
||||
|
||||
int isUpperCase(int c) { /* IN - ISO character to test */
|
||||
static char upperChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
|
||||
return (c != '\0' && strchr(upperChars, c) != nullptr);
|
||||
}
|
||||
|
||||
|
||||
int isISOLetter(int c) { /* IN - ISO character to test */
|
||||
return (isLowerCase(c) || isUpperCase(c));
|
||||
}
|
||||
|
||||
|
||||
char toLowerCase(int c) { /* IN - ISO character to convert */
|
||||
return (isUpperCase(c) ? c + ('a' - 'A') : c);
|
||||
}
|
||||
|
||||
|
||||
char toUpperCase(int c) { /* IN - ISO character to convert */
|
||||
return (isLowerCase(c) ? c - ('a' - 'A') : c);
|
||||
}
|
||||
|
||||
|
||||
char *stringLower(char str[]) { /* INOUT - ISO string to convert */
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = toLowerCase(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
char *stringUpper(char str[]) { /* INOUT - ISO string to convert */
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = toUpperCase(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*----------------------------------------------------------------------
|
||||
toIso
|
||||
|
||||
Converts the incoming string to ISO character set. The original is
|
||||
in the current character set which in the case of the compiler might
|
||||
be other than the native.
|
||||
|
||||
*/
|
||||
void toIso(char copy[], /* OUT - Mapped string */
|
||||
char original[], /* IN - string to convert */
|
||||
int charset) { /* IN - the current character set */
|
||||
static unsigned char macMap[256]
|
||||
= {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0A, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1, 0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
|
||||
0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3, 0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
|
||||
0xB9, 0xB0, 0xA2, 0xA3, 0xA7, 0xB7, 0xB6, 0xDF, 0xAE, 0xA9, 0xB2, 0xB4, 0xA8, 0xD7, 0xC6, 0xD8,
|
||||
0xA4, 0xB1, 0xCD, 0xCC, 0xA5, 0xB5, 0xF0, 0xCA, 0xDE, 0xFE, 0xA6, 0xAA, 0xBA, 0xD4, 0xE6, 0xF8,
|
||||
0xBF, 0xA1, 0xAC, 0xCE, 0xCF, 0xC8, 0xD0, 0xAB, 0xBB, 0xCB, 0xA0, 0xC0, 0xC3, 0xD5, 0xDD, 0xFD,
|
||||
0xAD, 0xAF, 0xDA, 0xD9, 0xB8, 0xB3, 0xF7, 0xC2, 0xFF, 0xBC, 0xBD, 0xBE, 0xC1, 0xD2, 0xD3, 0xDB,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
|
||||
};
|
||||
|
||||
static unsigned char dosMap[256]
|
||||
= {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0A, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7, 0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
|
||||
0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9, 0xFF, 0xD6, 0xDC, 0xA2, 0xA3, 0xA5, 0xDE, 0xA6,
|
||||
0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA, 0xBF, 0xC0, 0xC1, 0xBD, 0xBC, 0xCF, 0xAB, 0xBB,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
|
||||
0xA1, 0xA7, 0xAD, 0xB3, 0xB8, 0xB9, 0xC3, 0xCE, 0xD2, 0xD3, 0xDB, 0xDD, 0xE3, 0xF5, 0xF8, 0xFD,
|
||||
0xA9, 0xDF, 0xC8, 0xB6, 0xCA, 0xA4, 0xB5, 0xAE, 0xD5, 0xD0, 0xD4, 0xF0, 0xD7, 0xD8, 0xCB, 0xC2,
|
||||
0xBE, 0xB1, 0xD9, 0xDA, 0xCD, 0xCC, 0xF7, 0xA8, 0xB0, 0xB7, 0xAF, 0xAC, 0xFE, 0xB2, 0xB4, 0xA0
|
||||
};
|
||||
unsigned char *o, *c;
|
||||
|
||||
switch (charset) {
|
||||
case 0: /* ISO */
|
||||
if (copy != original)
|
||||
(void)strcpy(copy, original);
|
||||
break;
|
||||
case 1: /* Mac */
|
||||
for (o = (unsigned char *)original, c = (unsigned char *)copy; *o; o++, c++)
|
||||
*c = macMap[*o];
|
||||
*c = '\0';
|
||||
break;
|
||||
|
||||
case 2: /* Dos */
|
||||
for (o = (unsigned char *)original, c = (unsigned char *)copy; *o; o++, c++)
|
||||
*c = dosMap[*o];
|
||||
*c = '\0';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
fromIso
|
||||
|
||||
Converts a string from global Iso format to native. Only used in
|
||||
interpreter so character set is known at compile time.
|
||||
|
||||
*/
|
||||
void fromIso(char copy[], /* OUT - Mapped string */
|
||||
char original[]) { /* IN - string to convert */
|
||||
if (copy != original)
|
||||
(void)strcpy(copy, original);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
toNative
|
||||
|
||||
Converts the incoming string to the native character set from any of
|
||||
the others. The original is in the current character set which in
|
||||
the case of the compiler might be other than the native.
|
||||
|
||||
*/
|
||||
void toNative(char copy[], /* OUT - Mapped string */
|
||||
char original[], /* IN - string to convert */
|
||||
int charset) { /* IN - the current character set */
|
||||
toIso(copy, original, charset);
|
||||
if (NATIVECHARSET != 0)
|
||||
fromIso(copy, copy);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
90
engines/glk/alan2/sysdep.h
Normal file
90
engines/glk/alan2/sysdep.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_SYSDEP
|
||||
#define GLK_ALAN2_SYSDEP
|
||||
|
||||
/* System dependencies file for Alan Adventure Language system
|
||||
*
|
||||
* N.B.The test for symbols used here should really be of three types
|
||||
* - processor name(like PC, x86, ...)
|
||||
* - os name(DOS, WIN32, Solaris2, ...)
|
||||
* - compiler name andversion(DJGPP, CYGWIN, GCC271, THINK-C, ...)
|
||||
*
|
||||
* The set symbols should indicate if a feature is on or off like the GNU
|
||||
* AUTOCONFIG package does.
|
||||
*
|
||||
* This is not completely done yet!
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
#define GLK
|
||||
#define __win__
|
||||
|
||||
#undef fprintf
|
||||
extern void fprintf(Common::WriteStream *ws, const char *fmt, ...);
|
||||
|
||||
/***********************/
|
||||
|
||||
/* Common case first */
|
||||
#define ISO 1
|
||||
#define NATIVECHARSET 0
|
||||
|
||||
/* Native character functions */
|
||||
extern int isSpace(int c); /* IN - Native character to test */
|
||||
extern int isLower(int c); /* IN - Native character to test */
|
||||
extern int isUpper(int c); /* IN - Native character to test */
|
||||
extern int isLetter(int c); /* IN - Native character to test */
|
||||
extern int toLower(int c); /* IN - Native character to convert */
|
||||
extern int toUpper(int c); /* IN - Native character to convert */
|
||||
extern char *strlow(char str[]); /* INOUT - Native string to convert */
|
||||
extern char *strupp(char str[]); /* INOUT - Native string to convert */
|
||||
|
||||
/* ISO character functions */
|
||||
extern int isISOLetter(int c); /* IN - ISO character to test */
|
||||
extern char toLowerCase(int c); /* IN - ISO character to convert */
|
||||
extern char toUpperCase(int c); /* IN - ISO character to convert */
|
||||
extern char *stringLower(char str[]); /* INOUT - ISO string to convert */
|
||||
extern char *stringUpper(char str[]); /* INOUT - ISO string to convert */
|
||||
|
||||
#if 0
|
||||
/* ISO string conversion functions */
|
||||
extern void toIso(char copy[], /* OUT - Mapped string */
|
||||
char original[], /* IN - string to convert */
|
||||
int charset); /* IN - The current character set */
|
||||
|
||||
extern void fromIso(char copy[], /* OUT - Mapped string */
|
||||
char original[]); /* IN - string to convert */
|
||||
|
||||
extern void toNative(char copy[], /* OUT - Mapped string */
|
||||
char original[], /* IN - string to convert */
|
||||
int charset); /* IN - current character set */
|
||||
#endif
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
52
engines/glk/alan2/types.cpp
Normal file
52
engines/glk/alan2/types.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan2/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
// This works around gcc errors for passing packed structure fields
|
||||
static void syncVal(Common::Serializer &s, void *fld) {
|
||||
uint32 v = READ_UINT32(fld);
|
||||
s.syncAsSint32LE(v);
|
||||
if (s.isLoading())
|
||||
WRITE_UINT32(fld, v);
|
||||
}
|
||||
|
||||
void CurVars::synchronize(Common::Serializer &s) {
|
||||
syncVal(s, &vrb);
|
||||
syncVal(s, &obj);
|
||||
syncVal(s, &loc);
|
||||
syncVal(s, &act);
|
||||
syncVal(s, &tick);
|
||||
syncVal(s, &score);
|
||||
syncVal(s, &visits);
|
||||
}
|
||||
|
||||
void EvtqElem::synchronize(Common::Serializer &s) {
|
||||
syncVal(s, &time);
|
||||
syncVal(s, &event);
|
||||
syncVal(s, &where);
|
||||
}
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
296
engines/glk/alan2/types.h
Normal file
296
engines/glk/alan2/types.h
Normal file
@@ -0,0 +1,296 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_TYPES
|
||||
#define GLK_ALAN2_TYPES
|
||||
|
||||
#include "glk/alan2/sysdep.h"
|
||||
#include "glk/alan2/acode.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
/* CONSTANTS */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (0==0)
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE (!TRUE)
|
||||
#endif
|
||||
|
||||
#define ACTMIN (header->actmin)
|
||||
#define ACTMAX (header->actmax)
|
||||
#define OBJMIN (header->objmin)
|
||||
#define OBJMAX (header->objmax)
|
||||
#define LOCMIN (header->locmin)
|
||||
#define LOCMAX (header->locmax)
|
||||
#define CNTMIN (header->cntmin)
|
||||
#define CNTMAX (header->cntmax)
|
||||
#define LITMIN (header->locmax+1)
|
||||
#define LITMAX (header->locmax+1+litCount)
|
||||
#define EVTMIN (header->evtmin)
|
||||
#define EVTMAX (header->evtmax)
|
||||
|
||||
#define HERO ACTMIN
|
||||
|
||||
|
||||
#define addrTo(x) (&memory[x])
|
||||
|
||||
/* The word classes are represented as numbers but in the dictonary they are generated as bits */
|
||||
#define isVerb(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_VRB))!=0)
|
||||
#define isConj(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_CONJ))!=0)
|
||||
#define isBut(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_BUT))!=0)
|
||||
#define isThem(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_THEM))!=0)
|
||||
#define isIt(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_IT))!=0)
|
||||
#define isNoun(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_NOUN))!=0)
|
||||
#define isAdj(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_ADJ))!=0)
|
||||
#define isPrep(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_PREP))!=0)
|
||||
#define isAll(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_ALL))!=0)
|
||||
#define isDir(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_DIR))!=0)
|
||||
#define isNoise(word) ((int)word < dictsize && (dict[word]._class&((Aword)1L<<WRD_NOISE))!=0)
|
||||
#define isLiteral(word) ((int)word >= dictsize)
|
||||
|
||||
|
||||
/* TYPES */
|
||||
|
||||
typedef int Boolean; /* Boolean values within interpreter */
|
||||
|
||||
/* Amachine variables */
|
||||
struct CurVars {
|
||||
int
|
||||
vrb,
|
||||
obj,
|
||||
loc,
|
||||
act,
|
||||
tick,
|
||||
score,
|
||||
visits;
|
||||
|
||||
/**
|
||||
* Read or write data to/from a save file
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
/* The various tables */
|
||||
struct WrdElem { /* Dictionary */
|
||||
Aaddr wrd; /* ACODE address to string */
|
||||
Aword _class; /* Word class */
|
||||
Aword code;
|
||||
Aaddr adjrefs; /* Address to reference list */
|
||||
Aaddr nounrefs; /* Address to reference list */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ActElem { /* ACTOR TABLE */
|
||||
Aword loc; /* Location */
|
||||
Abool describe; /* Description flag */
|
||||
Aaddr nam; /* Address to name printing code */
|
||||
Aaddr atrs; /* Address to attribute list */
|
||||
Aword cont; /* Code for the container props if any */
|
||||
Aword script; /* Which script is he using */
|
||||
Aaddr scradr; /* Address to script table */
|
||||
Aword step;
|
||||
Aword count;
|
||||
Aaddr vrbs;
|
||||
Aaddr dscr; /* Address of description code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ScrElem { /* SCRIPT TABLE */
|
||||
Aword code; /* Script number */
|
||||
Aaddr dscr; /* Optional description statements */
|
||||
Aaddr steps; /* Address to steps */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct StepElem { /* STEP TABLE */
|
||||
Aword after; /* After how many ticks? */
|
||||
Aaddr exp; /* Address to expression saying when */
|
||||
Aaddr stm; /* Address to the actual code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct LocElem { /* LOCATION TABLE */
|
||||
Aaddr nams; /* Address of name printing code */
|
||||
Aaddr dscr; /* Address of description code */
|
||||
Aaddr does; /* Address of does code */
|
||||
Aword describe; /* Description flag & counter */
|
||||
Aaddr atrs; /* Address of attribute list */
|
||||
Aaddr exts; /* Address of exit list */
|
||||
Aaddr vrbs; /* Address of local verb list */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ExtElem { /* EXIT TABLE structure */
|
||||
Abool done; /* Flag for reverse/convert process */
|
||||
Aword code; /* Direction code */
|
||||
Aaddr checks; /* Address of check table */
|
||||
Aaddr action; /* Address of action code */
|
||||
Aword next; /* Number of next location */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ChkElem { /* CHECK TABLE */
|
||||
Aaddr exp; /* ACODE address to expression code */
|
||||
Aaddr stms; /* ACODE address to statement code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct VrbElem { /* VERB TABLE */
|
||||
Aword code; /* Code for the verb */
|
||||
Aaddr alts; /* Address to alternatives */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct StxElem { /* SYNTAX TABLE */
|
||||
Aword code; /* Code for verb word */
|
||||
Aaddr elms; /* Address to element tables */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ElmElem26 { /* ELEMENT TABLES */
|
||||
Aword code; /* Code for this element, 0 -> parameter */
|
||||
Abool multiple; /* May be multiple (if parameter) */
|
||||
Aaddr next; /* Address to next element table ... */
|
||||
/* ... or class check if EOS */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ElmElem { /* ELEMENT TABLES */
|
||||
Aword code; /* Code for this element, 0 -> parameter */
|
||||
Aword flags; /* Flags for multiple/omni (if parameter) */
|
||||
/* CHANGED: v2.7 from Abool for multiple */
|
||||
Aaddr next; /* Address to next element table ... */
|
||||
/* ... or class check if EOS */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ClaElem { /* CLASS DEFINITION TABLE */
|
||||
Aword code; /* Parameter number */
|
||||
Aword classes; /* Parameter classes */
|
||||
Aaddr stms; /* Exception statements */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct AltElem { /* VERB ALTERNATIVE TABLE */
|
||||
Abool done; /* Flag for patching (reverse/convert) process */
|
||||
Aword param; /* Parameter number */
|
||||
Aword qual; /* Verb execution qualifier */
|
||||
Aaddr checks; /* Address of the check table */
|
||||
Aaddr action; /* Address of the action code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct AtrElem { /* ATTRIBUTE LIST */
|
||||
Aword val; /* Its value */
|
||||
Aaddr stradr; /* Address to the name */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ObjElem25 { /* OBJECT TABLE of 2.5 format*/
|
||||
Aword loc; /* Current location */
|
||||
Abool describe; /* Describe flag */
|
||||
Aaddr atrs; /* Address of attribute list */
|
||||
Aword cont; /* Index to container properties if any */
|
||||
Aaddr vrbs; /* Address to local verb table */
|
||||
Aaddr dscr1; /* Address to Aword description code */
|
||||
Aaddr dscr2; /* Address to short description code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ObjElem { /* OBJECT TABLE */
|
||||
Aword loc; /* Current location */
|
||||
Abool describe; /* Describe flag */
|
||||
Aaddr atrs; /* Address of attribute list */
|
||||
Aword cont; /* Index to container properties if any */
|
||||
Aaddr vrbs; /* Address to local verb table */
|
||||
Aaddr dscr1; /* Address to Aword description code */
|
||||
Aaddr art; /* Article printing code? Else use default */
|
||||
/* INTRODUCED: v2.6 */
|
||||
Aaddr dscr2; /* Address to short description code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct CntElem { /* CONTAINER TABLE */
|
||||
Aaddr lims; /* Address to limit check code */
|
||||
Aaddr header; /* Address to header code */
|
||||
Aaddr empty; /* Address to empty code */
|
||||
Aword parent; /* Object or actor index */
|
||||
Aaddr nam; /* Address to statement printing name */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct LimElem { /* LIMIT Type */
|
||||
Aword atr; /* Attribute that limits */
|
||||
Aword val; /* And the limiting value */
|
||||
Aaddr stms; /* Statements if fail */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct RulElem { /* RULE TABLE */
|
||||
Abool run; /* Is rule already run? */
|
||||
Aaddr exp; /* Address to expression code */
|
||||
Aaddr stms; /* Address to run */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct EvtElem { /* EVENT TABLE */
|
||||
Aaddr stradr; /* Address to name string */
|
||||
Aaddr code; /* Address of code to run */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct EvtqElem { /* EVENT QUEUE ELEMENT */
|
||||
int time;
|
||||
int event;
|
||||
int where;
|
||||
|
||||
/**
|
||||
* Read or write data to/from a save file
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct IniElem { /* STRING INITIALISATION TABLE */
|
||||
Aword fpos; /* File position */
|
||||
Aword len; /* Length */
|
||||
Aword adr; /* Where to store the string */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct MsgElem26 { /* MESSAGE TABLE */
|
||||
Aword fpos; /* File position */
|
||||
Aword len; /* Length of message */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct MsgElem { /* MESSAGE TABLE */
|
||||
Aaddr stms; /* Address to statements*/
|
||||
/* Changed v2.7 from fpos+len in .dat */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
|
||||
struct ParamElem { /* PARAMETER */
|
||||
Aword code; /* Code for this parameter (0=multiple) */
|
||||
Aword firstWord; /* Index to first word used by player */
|
||||
Aword lastWord; /* d:o to last */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
enum Type { TYPNUM, TYPSTR };
|
||||
|
||||
struct LitElem { /* LITERAL */
|
||||
Type type;
|
||||
Aptr value;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
#define MAXPARAMS 9
|
||||
#define MAXENTITY (header->actmax)
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
57
engines/glk/alan2/version.h
Normal file
57
engines/glk/alan2/version.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN2_VERSION
|
||||
#define GLK_ALAN2_VERSION
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan2 {
|
||||
|
||||
typedef int64 Time;
|
||||
|
||||
struct Version {
|
||||
const char *string;
|
||||
int version;
|
||||
int revision;
|
||||
int correction;
|
||||
Time time;
|
||||
const char *state;
|
||||
};
|
||||
|
||||
struct Product {
|
||||
const char *name;
|
||||
const char *slogan;
|
||||
const char *shortHeader;
|
||||
const char *longHeader;
|
||||
const char *date;
|
||||
const char *time;
|
||||
const char *user;
|
||||
const char *host;
|
||||
const char *ostype;
|
||||
const Version version;
|
||||
};
|
||||
|
||||
} // End of namespace Alan2
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user