Initial commit
This commit is contained in:
45
engines/glk/alan3/acode.cpp
Normal file
45
engines/glk/alan3/acode.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
void AttributeEntry::synchronize(Common::Serializer &s) {
|
||||
// We have to do some annoying temporary copy of the fields to get around gcc
|
||||
// errors about getting references to fields of packed structures
|
||||
Aint c = code;
|
||||
Aptr v = value;
|
||||
Aaddr i = id;
|
||||
s.syncAsSint32LE(c);
|
||||
s.syncAsSint32LE(v);
|
||||
s.syncAsSint32LE(i);
|
||||
|
||||
if (s.isLoading()) {
|
||||
code = c;
|
||||
value = v;
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
736
engines/glk/alan3/acode.h
Normal file
736
engines/glk/alan3/acode.h
Normal file
@@ -0,0 +1,736 @@
|
||||
/* 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_ACODE
|
||||
#define GLK_ACODE
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
#define ACODEEXTENSION ".a3c"
|
||||
|
||||
typedef uint32 Aptr; /* Type for an ACODE memory address used in the structures */
|
||||
/* TODO: Here's the major 32->64bit problem: Aptrs are 32 bit to fit
|
||||
into the 32-bit structure of the Amachine, but sometimes this is
|
||||
used to store a *real* pointer value, which on 64-bit machines are
|
||||
64bits. */
|
||||
|
||||
typedef uint32 Aword; /* Type for an ACODE word */
|
||||
typedef uint32 Aaddr; /* Type for an ACODE address */
|
||||
typedef uint32 Aid; /* Type for an ACODE Instance Id value */
|
||||
typedef int32 Abool; /* Type for an ACODE Boolean value */
|
||||
typedef int32 Aint; /* Type for an ACODE Integer value */
|
||||
typedef int32 Aset; /* Type for an ACODE Set value */
|
||||
typedef int CodeValue; /* Definition for the packing process */
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (0==0)
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE (!TRUE)
|
||||
#endif
|
||||
|
||||
/* 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, bit positions */
|
||||
typedef int WordKind;
|
||||
#define SYNONYM_WORD 0
|
||||
#define SYNONYM_BIT (((Aword)1)<<SYNONYM_WORD)
|
||||
|
||||
#define ADJECTIVE_WORD (SYNONYM_WORD+1)
|
||||
#define ADJECTIVE_BIT (((Aword)1)<<ADJECTIVE_WORD)
|
||||
|
||||
#define ALL_WORD (ADJECTIVE_WORD+1)
|
||||
#define ALL_BIT (((Aword)1)<<ALL_WORD)
|
||||
|
||||
#define EXCEPT_WORD (ALL_WORD+1)
|
||||
#define EXCEPT_BIT (((Aword)1)<<EXCEPT_WORD)
|
||||
|
||||
#define CONJUNCTION_WORD (EXCEPT_WORD+1)
|
||||
#define CONJUNCTION_BIT (((Aword)1)<<CONJUNCTION_WORD)
|
||||
|
||||
#define PREPOSITION_WORD (CONJUNCTION_WORD+1)
|
||||
#define PREPOSITION_BIT (((Aword)1)<<PREPOSITION_WORD)
|
||||
|
||||
#define DIRECTION_WORD (PREPOSITION_WORD+1)
|
||||
#define DIRECTION_BIT (((Aword)1)<<DIRECTION_WORD)
|
||||
|
||||
#define IT_WORD (DIRECTION_WORD+1)
|
||||
#define IT_BIT (((Aword)1)<<IT_WORD)
|
||||
|
||||
#define NOISE_WORD (IT_WORD+1)
|
||||
#define NOISE_BIT (((Aword)1)<<NOISE_WORD)
|
||||
|
||||
#define NOUN_WORD (NOISE_WORD+1)
|
||||
#define NOUN_BIT (((Aword)1)<<NOUN_WORD)
|
||||
|
||||
#define THEM_WORD (NOUN_WORD+1)
|
||||
#define THEM_BIT (((Aword)1)<<THEM_WORD)
|
||||
|
||||
#define VERB_WORD (THEM_WORD+1)
|
||||
#define VERB_BIT (((Aword)1)<<VERB_WORD)
|
||||
|
||||
#define PRONOUN_WORD (VERB_WORD+1)
|
||||
#define PRONOUN_BIT (((Aword)1)<<PRONOUN_WORD)
|
||||
|
||||
#define WRD_CLASSES (PRONOUN_WORD+1)
|
||||
|
||||
|
||||
/* The #nowhere and NO_LOCATION constants */
|
||||
#define NO_LOCATION 0
|
||||
#define NOWHERE 1
|
||||
|
||||
|
||||
/* Syntax element classifications */
|
||||
// End of file/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
|
||||
};
|
||||
|
||||
/* AMACHINE Text Styles */
|
||||
enum TextStyle {
|
||||
NORMAL_STYLE,
|
||||
EMPHASIZED_STYLE,
|
||||
PREFORMATTED_STYLE,
|
||||
ALERT_STYLE,
|
||||
QUOTE_STYLE
|
||||
};
|
||||
|
||||
|
||||
#define CONSTANT(op) ((Aword)op)
|
||||
#define INSTRUCTION(op) ((((Aword)C_STMOP)<<28)|((Aword)op))
|
||||
#define CURVAR(op) ((((Aword)C_CURVAR)<<28)|((Aword)op))
|
||||
|
||||
enum InstClass {
|
||||
I_LINE, /* Source line debug info */
|
||||
I_PRINT, /* Print a string from the text file */
|
||||
I_STYLE, /* Set output text style */
|
||||
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, /* Set a boolean attribute to the */
|
||||
/* value on top of stack */
|
||||
I_SET, /* Set a numeric attribute to the */
|
||||
/* value on top of stack */
|
||||
I_SETSTR, /* Set a string valued attribute to */
|
||||
/* the string on top of stack, */
|
||||
/* deallocate current contents first */
|
||||
I_SETSET, /* Set a Set valued attribute to */
|
||||
/* the Set on top of stack, */
|
||||
/* deallocate current contents first */
|
||||
I_NEWSET, /* Push a new, empty set at the top of stack */
|
||||
I_ATTRIBUTE, /* Push the value of an attribute */
|
||||
I_ATTRSTR, /* Push a copy of a string attribute */
|
||||
I_ATTRSET, /* Push a copy of a set attribute */
|
||||
I_UNION, /* Add a set from the top of stack to a */
|
||||
/* set valued attribute */
|
||||
I_GETSTR, /* Get a string contents from text
|
||||
file, create a copy and push it
|
||||
on top of stack */
|
||||
I_INCR, /* Increase an attribute */
|
||||
I_DECR, /* Decrease a numeric attribute */
|
||||
I_INCLUDE, /* Include a value in the set on stack top */
|
||||
I_EXCLUDE, /* Remove a value from the set on stack top */
|
||||
I_SETSIZE, /* Push number of members in a set */
|
||||
I_SETMEMB, /* Push the member with index <top>-1
|
||||
from set <top> */
|
||||
I_CONTSIZE, /* Push number of members in a container */
|
||||
I_CONTMEMB, /* Push the member with index <top>-1
|
||||
from container <top> */
|
||||
I_USE,
|
||||
I_STOP,
|
||||
I_AT,
|
||||
I_IN,
|
||||
I_INSET,
|
||||
I_HERE,
|
||||
I_NEARBY,
|
||||
I_NEAR,
|
||||
I_WHERE, /* Current position of an instance */
|
||||
I_LOCATION, /* The *location* an instance is at */
|
||||
I_DESCRIBE,
|
||||
I_SAY,
|
||||
I_SAYINT,
|
||||
I_SAYSTR,
|
||||
I_IF,
|
||||
I_ELSE,
|
||||
I_ENDIF,
|
||||
I_AND,
|
||||
I_OR,
|
||||
I_NE,
|
||||
I_EQ,
|
||||
I_STREQ, /* String compare */
|
||||
I_STREXACT, /* Exact match */
|
||||
I_LE,
|
||||
I_GE,
|
||||
I_LT,
|
||||
I_GT,
|
||||
I_PLUS,
|
||||
I_MINUS,
|
||||
I_MULT,
|
||||
I_DIV,
|
||||
I_NOT,
|
||||
I_UMINUS,
|
||||
I_RND,
|
||||
I_RETURN,
|
||||
I_SYSTEM,
|
||||
I_RESTART,
|
||||
I_BTW,
|
||||
I_CONTAINS,
|
||||
I_DUP,
|
||||
I_DEPEND,
|
||||
I_DEPCASE,
|
||||
I_DEPEXEC,
|
||||
I_DEPELSE,
|
||||
I_ENDDEP,
|
||||
I_ISA,
|
||||
I_FRAME,
|
||||
I_SETLOCAL,
|
||||
I_GETLOCAL,
|
||||
I_ENDFRAME,
|
||||
I_LOOP,
|
||||
I_LOOPNEXT,
|
||||
I_LOOPEND,
|
||||
I_SUM, /* Aggregates: */
|
||||
I_MAX,
|
||||
I_MIN,
|
||||
I_COUNT, /* COUNT aggregate & limit meta-attribute */
|
||||
I_SHOW,
|
||||
I_PLAY,
|
||||
I_CONCAT,
|
||||
I_STRIP,
|
||||
I_POP,
|
||||
I_TRANSCRIPT,
|
||||
I_DUPSTR /* Duplicate the string on the top of the stack */
|
||||
};
|
||||
|
||||
enum SayForm {
|
||||
SAY_SIMPLE,
|
||||
SAY_DEFINITE,
|
||||
SAY_INDEFINITE,
|
||||
SAY_NEGATIVE,
|
||||
SAY_PRONOUN
|
||||
};
|
||||
|
||||
enum VarClass {
|
||||
V_PARAM,
|
||||
V_CURLOC,
|
||||
V_CURACT,
|
||||
V_CURVRB,
|
||||
V_SCORE,
|
||||
V_CURRENT_INSTANCE,
|
||||
V_MAX_INSTANCE
|
||||
};
|
||||
|
||||
/* For transitivity in HERE, IN etc. */
|
||||
enum ATrans {
|
||||
TRANSITIVE = 0,
|
||||
DIRECT = 1,
|
||||
INDIRECT = 2
|
||||
};
|
||||
|
||||
/* Predefined attributes, one is for containers and the other for locations
|
||||
and since instances cannot be both, the attributes can have the same number */
|
||||
#define OPAQUEATTRIBUTE 1
|
||||
#define VISITSATTRIBUTE 1
|
||||
#define PREDEFINEDATTRIBUTES OPAQUEATTRIBUTE
|
||||
|
||||
#define I_CLASS(x) ((x)>>28)
|
||||
#define I_OP(x) ((x&0x08000000)?(x)|0xf0000000:(x)&0x0fffffff)
|
||||
|
||||
|
||||
/* AMACHINE Table entry types */
|
||||
|
||||
#define AwordSizeOf(x) (sizeof(x)/sizeof(Aword))
|
||||
|
||||
#include "common/pack-start.h" // START STRUCT PACKING
|
||||
|
||||
struct ArticleEntry {
|
||||
Aaddr address; /* Address of article code */
|
||||
Abool isForm; /* Is the article a complete form? */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ClassEntry { /* CLASS TABLE */
|
||||
Aword code; /* Own code */
|
||||
Aaddr id; /* Address to identifier string */
|
||||
Aint parent; /* Code for the parent class, 0 if none */
|
||||
Aaddr name; /* Address to name printing code */
|
||||
Aint pronoun; /* Code for the pronoun word */
|
||||
Aaddr initialize; /* Address to initialization statements */
|
||||
Aaddr descriptionChecks; /* Address of description checks */
|
||||
Aaddr description; /* Address of description code */
|
||||
ArticleEntry definite; /* Definite article entry */
|
||||
ArticleEntry indefinite; /* Indefinite article entry */
|
||||
ArticleEntry negative; /* Negative article entry */
|
||||
Aaddr mentioned; /* Address of code for Mentioned clause */
|
||||
Aaddr verbs; /* Address of verb table */
|
||||
Aaddr entered; /* Address of code for Entered clause */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct InstanceEntry { /* INSTANCE TABLE */
|
||||
Aint code; /* Own code */
|
||||
Aaddr id; /* Address to identifier string */
|
||||
Aint parent; /* Code for the parent class, 0 if none */
|
||||
Aaddr name; /* Address to name printing code */
|
||||
Aint pronoun; /* Word code for the pronoun */
|
||||
Aint initialLocation; /* Code for current location */
|
||||
Aaddr initialize; /* Address to initialization statements */
|
||||
Aint container; /* Code for a possible container property */
|
||||
Aaddr initialAttributes; /* Address of attribute list */
|
||||
Aaddr checks; /* Address of description checks */
|
||||
Aaddr description; /* Address of description code */
|
||||
ArticleEntry definite; /* Definite article entry */
|
||||
ArticleEntry indefinite; /* Indefinite article entry */
|
||||
ArticleEntry negative; /* Negative article entry */
|
||||
Aaddr mentioned; /* Address to short description code */
|
||||
Aaddr verbs; /* Address of local verb list */
|
||||
Aaddr entered; /* Address of entered code (location only) */
|
||||
Aaddr exits; /* Address of exit list */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct AttributeEntry { /* ATTRIBUTE LIST */
|
||||
Aint code; /* Its code */
|
||||
Aptr value; /* Its value, a string has a dynamic
|
||||
string pointer, a set has a pointer
|
||||
to a dynamically allocated set */
|
||||
Aaddr id; /* Address to the name */
|
||||
|
||||
/**
|
||||
* Save/resotre data from save file
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct AttributeHeaderEntry { /* ATTRIBUTE LIST in header */
|
||||
Aint code; /* Its code */
|
||||
Aword value; /* Its value, a string has a dynamic
|
||||
string pointer, a set has a pointer
|
||||
to a dynamically allocated set */
|
||||
Aaddr id; /* Address to the name */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ExitEntry { /* EXIT TABLE structure */
|
||||
Aword code; /* Direction code */
|
||||
Aaddr checks; /* Address of check table */
|
||||
Aaddr action; /* Address of action code */
|
||||
Aword target; /* Id for the target location */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
|
||||
struct RuleEntry { /* RULE TABLE */
|
||||
Abool alreadyRun;
|
||||
Aaddr exp; /* Address to expression code */
|
||||
Aaddr stms; /* Address to run */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
|
||||
#define RESTRICTIONCLASS_CONTAINER (-2)
|
||||
#define RESTRICTIONCLASS_INTEGER (-3)
|
||||
#define RESTRICTIONCLASS_STRING (-4)
|
||||
|
||||
struct RestrictionEntry { /* PARAMETER RESTRICTION TABLE */
|
||||
Aint parameterNumber; /* Parameter number */
|
||||
Aint _class; /* Parameter class code */
|
||||
Aaddr stms; /* Exception statements */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ContainerEntry { /* CONTAINER TABLE */
|
||||
Aword owner; /* Owner instance index */
|
||||
Aint _class; /* Class to allow in container */
|
||||
Aaddr limits; /* Address to limit check code */
|
||||
Aaddr header; /* Address to header code */
|
||||
Aaddr empty; /* Address to code for header when empty */
|
||||
Aaddr extractChecks; /* Address to check before extracting */
|
||||
Aaddr extractStatements; /* Address to execute when extracting */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
|
||||
struct ElementEntry { /* SYNTAX ELEMENT TABLES */
|
||||
Aint code; /* Code for this element, 0 -> parameter */
|
||||
Aword flags; /* Flags for multiple/omni (if parameter), syntax number/verb of EOS */
|
||||
Aaddr next; /* Address to next element table ... */
|
||||
/* ... or restrictions if code == EOS */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct SyntaxEntryPreBeta2 { /* SYNTAX TABLE */
|
||||
Aint code; /* Code for verb word */
|
||||
Aaddr elms; /* Address to element tables */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct SyntaxEntry { /* SYNTAX TABLE */
|
||||
Aint code; /* Code for verb word, or 0 if starting with parameter */
|
||||
Aaddr elms; /* Address to element tables */
|
||||
Aaddr parameterNameTable; /* Address to a table of id-addresses giving the names of the parameters */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ParameterMapEntry { /* PARAMETER MAPPING TABLE */
|
||||
Aint syntaxNumber;
|
||||
Aaddr parameterMapping;
|
||||
Aint verbCode;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct EventEntry { /* EVENT TABLE */
|
||||
Aaddr id; /* Address to name string */
|
||||
Aaddr code;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct ScriptEntry { /* SCRIPT TABLE */
|
||||
Aaddr id; /* Address to name string */
|
||||
Aint code; /* Script number */
|
||||
Aaddr description; /* Optional description statements */
|
||||
Aaddr steps; /* Address to steps */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct StepEntry { /* STEP TABLE */
|
||||
Aaddr after; /* Expression to say after how many ticks? */
|
||||
Aaddr exp; /* Expression to condition saying when */
|
||||
Aaddr stms; /* Address to the actual code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct AltEntry { /* VERB ALTERNATIVE TABLE */
|
||||
Aword qual; /* Verb execution qualifier */
|
||||
Aint param; /* Parameter number */
|
||||
Aaddr checks; /* Address of the check table */
|
||||
Aaddr action; /* Address of the action code */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct SourceFileEntry { /* SOURCE FILE NAME TABLE */
|
||||
Aint fpos;
|
||||
Aint len;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct SourceLineEntry { /* SOURCE LINE TABLE */
|
||||
Aint file;
|
||||
Aint line;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct StringInitEntry { /* STRING INITIALISATION TABLE */
|
||||
Aword fpos; /* File position */
|
||||
Aword len; /* Length */
|
||||
Aint instanceCode; /* Where to store it */
|
||||
Aint attributeCode;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct SetInitEntry { /* SET INITIALISATION TABLE */
|
||||
Aint size; /* Size of the initial set */
|
||||
Aword setAddress; /* Address to the initial set */
|
||||
Aint instanceCode; /* Where to store it */
|
||||
Aint attributeCode;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct DictionaryEntry { /* Dictionary */
|
||||
Aaddr string; /* ACODE address to string */
|
||||
Aword classBits; /* Word class */
|
||||
Aword code;
|
||||
Aaddr adjectiveRefs; /* Address to reference list */
|
||||
Aaddr nounRefs; /* Address to reference list */
|
||||
Aaddr pronounRefs; /* Address to reference list */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
|
||||
|
||||
/* AMACHINE Header */
|
||||
|
||||
struct ACodeHeader {
|
||||
/* Important info */
|
||||
char tag[4]; /* "ALAN" */
|
||||
byte version[4]; /* Version of compiler */
|
||||
Aword uid; /* Unique id of the compiled game */
|
||||
Aword size; /* Size of ACD-file in Awords */
|
||||
/* Options */
|
||||
Abool pack; /* Is the text packed and encoded ? */
|
||||
Aword stringOffset; /* Offset to string data in game file */
|
||||
Aword pageLength; /* Length of a displayed page */
|
||||
Aword pageWidth; /* and width */
|
||||
Aword debug; /* Option: debug */
|
||||
/* Data structures */
|
||||
Aaddr classTableAddress;
|
||||
Aword classMax;
|
||||
Aword entityClassId;
|
||||
Aword thingClassId;
|
||||
Aword objectClassId;
|
||||
Aword locationClassId;
|
||||
Aword actorClassId;
|
||||
Aword literalClassId;
|
||||
Aword integerClassId;
|
||||
Aword stringClassId;
|
||||
Aaddr instanceTableAddress; /* Instance table */
|
||||
Aword instanceMax; /* Highest number of an instance */
|
||||
Aword theHero; /* The hero instance code (id) */
|
||||
Aaddr containerTableAddress;
|
||||
Aword containerMax;
|
||||
Aaddr scriptTableAddress;
|
||||
Aword scriptMax;
|
||||
Aaddr eventTableAddress;
|
||||
Aword eventMax;
|
||||
Aaddr syntaxTableAddress;
|
||||
Aaddr parameterMapAddress;
|
||||
Aword syntaxMax;
|
||||
Aaddr dictionary;
|
||||
Aaddr verbTableAddress;
|
||||
Aaddr ruleTableAddress;
|
||||
Aaddr messageTableAddress;
|
||||
/* Miscellaneous */
|
||||
Aint attributesAreaSize; /* Size of attribute data area in Awords */
|
||||
Aint maxParameters; /* Maximum number of parameters in any syntax */
|
||||
Aaddr stringInitTable; /* String init table address */
|
||||
Aaddr setInitTable; /* Set init table address */
|
||||
Aaddr start; /* Address to Start code */
|
||||
Aword maximumScore; /* Maximum score */
|
||||
Aaddr scores; /* Score table */
|
||||
Aint scoreCount; /* Max index into scores table */
|
||||
Aaddr sourceFileTable; /* Table of fpos/len for source filenames */
|
||||
Aaddr sourceLineTable; /* Table of available source lines to break on */
|
||||
Aaddr freq; /* Address to Char freq's for coding */
|
||||
Aword acdcrc; /* Checksum for acd code (excl. hdr) */
|
||||
Aword txtcrc; /* Checksum for text data file */
|
||||
Aaddr ifids; /* Address to IFIDS */
|
||||
Aaddr prompt;
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct Pre3_0beta2Header {
|
||||
/* Important info */
|
||||
char tag[4]; /* "ALAN" */
|
||||
byte version[4]; /* Version of compiler */
|
||||
Aword uid; /* Unique id of the compiled game */
|
||||
Aword size; /* Size of ACD-file in Awords */
|
||||
/* Options */
|
||||
Abool pack; /* Is the text packed ? */
|
||||
Aword stringOffset; /* Offset to string data in game file */
|
||||
Aword pageLength; /* Length of a page */
|
||||
Aword pageWidth; /* and width */
|
||||
Aword debug; /* Option: debug */
|
||||
/* Data structures */
|
||||
Aaddr classTableAddress; /* Class table */
|
||||
Aword classMax; /* Number of classes */
|
||||
Aword entityClassId;
|
||||
Aword thingClassId;
|
||||
Aword objectClassId;
|
||||
Aword locationClassId;
|
||||
Aword actorClassId;
|
||||
Aword literalClassId;
|
||||
Aword integerClassId;
|
||||
Aword stringClassId;
|
||||
Aaddr instanceTableAddress; /* Instance table */
|
||||
Aword instanceMax; /* Highest number of an instance */
|
||||
Aword theHero; /* The hero instance code (id) */
|
||||
Aaddr containerTableAddress;
|
||||
Aword containerMax;
|
||||
Aaddr scriptTableAddress;
|
||||
Aword scriptMax;
|
||||
Aaddr eventTableAddress;
|
||||
Aword eventMax;
|
||||
Aaddr syntaxTableAddress;
|
||||
Aaddr parameterMapAddress;
|
||||
Aword syntaxMax;
|
||||
Aaddr dictionary;
|
||||
Aaddr verbTableAddress;
|
||||
Aaddr ruleTableAddress;
|
||||
Aaddr messageTableAddress;
|
||||
/* Miscellaneous */
|
||||
Aint attributesAreaSize; /* Size of attribute data area in Awords */
|
||||
Aint maxParameters; /* Maximum number of parameters in any syntax */
|
||||
Aaddr stringInitTable; /* String init table address */
|
||||
Aaddr setInitTable; /* Set init table address */
|
||||
Aaddr start; /* Address to Start code */
|
||||
Aword maximumScore; /* Maximum score */
|
||||
Aaddr scores; /* Score table */
|
||||
Aint scoreCount; /* Max index into scores table */
|
||||
Aaddr sourceFileTable; /* Table of fpos/len for source filenames */
|
||||
Aaddr sourceLineTable; /* Table of available source lines to break on */
|
||||
Aaddr freq; /* Address to Char freq's for coding */
|
||||
Aword acdcrc; /* Checksum for acd code (excl. hdr) */
|
||||
Aword txtcrc; /* Checksum for text data file */
|
||||
Aaddr ifids; /* Address to IFIDS */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
struct Pre3_0alpha5Header {
|
||||
/* Important info */
|
||||
char tag[4]; /* "ALAN" */
|
||||
byte version[4]; /* Version of compiler */
|
||||
Aword uid; /* Unique id of the compiled game */
|
||||
Aword size; /* Size of ACD-file in Awords */
|
||||
/* Options */
|
||||
Abool pack; /* Is the text packed ? */
|
||||
Aword stringOffset; /* Offset to string data in game file */
|
||||
Aword pageLength; /* Length of a page */
|
||||
Aword pageWidth; /* and width */
|
||||
Aword debug; /* Option: debug */
|
||||
/* Data structures */
|
||||
Aaddr classTableAddress; /* Class table */
|
||||
Aword classMax; /* Number of classes */
|
||||
Aword entityClassId;
|
||||
Aword thingClassId;
|
||||
Aword objectClassId;
|
||||
Aword locationClassId;
|
||||
Aword actorClassId;
|
||||
Aword literalClassId;
|
||||
Aword integerClassId;
|
||||
Aword stringClassId;
|
||||
Aaddr instanceTableAddress; /* Instance table */
|
||||
Aword instanceMax; /* Highest number of an instance */
|
||||
Aword theHero; /* The hero instance code (id) */
|
||||
Aaddr containerTableAddress;
|
||||
Aword containerMax;
|
||||
Aaddr scriptTableAddress;
|
||||
Aword scriptMax;
|
||||
Aaddr eventTableAddress;
|
||||
Aword eventMax;
|
||||
Aaddr syntaxTableAddress;
|
||||
Aaddr parameterMapAddress;
|
||||
Aword syntaxMax;
|
||||
Aaddr dictionary;
|
||||
Aaddr verbTableAddress;
|
||||
Aaddr ruleTableAddress;
|
||||
Aaddr messageTableAddress;
|
||||
/* Miscellaneous */
|
||||
Aint attributesAreaSize; /* Size of attribute data area in Awords */
|
||||
Aint maxParameters; /* Maximum number of parameters in any syntax */
|
||||
Aaddr stringInitTable; /* String init table address */
|
||||
Aaddr setInitTable; /* Set init table address */
|
||||
Aaddr start; /* Address to Start code */
|
||||
Aword maximumScore; /* Maximum score */
|
||||
Aaddr scores; /* Score table */
|
||||
Aint scoreCount; /* Max index into scores table */
|
||||
Aaddr sourceFileTable; /* Table of fpos/len for source filenames */
|
||||
Aaddr sourceLineTable; /* Table of available source lines to break on */
|
||||
Aaddr freq; /* Address to Char freq's for coding */
|
||||
Aword acdcrc; /* Checksum for acd code (excl. hdr) */
|
||||
Aword txtcrc; /* Checksum for text data file */
|
||||
} PACKED_STRUCT;
|
||||
|
||||
#include "common/pack-end.h" // END STRUCT PACKING
|
||||
|
||||
/* Error message numbers */
|
||||
enum MsgKind {
|
||||
M_UNKNOWN_WORD,
|
||||
M_WHAT,
|
||||
M_WHAT_WORD,
|
||||
M_MULTIPLE,
|
||||
M_NOUN,
|
||||
M_AFTER_BUT,
|
||||
M_BUT_ALL,
|
||||
M_NOT_MUCH,
|
||||
M_WHICH_ONE_START,
|
||||
M_WHICH_ONE_COMMA,
|
||||
M_WHICH_ONE_OR,
|
||||
M_NO_SUCH,
|
||||
M_NO_WAY,
|
||||
M_CANT0,
|
||||
M_SEE_START,
|
||||
M_SEE_COMMA,
|
||||
M_SEE_AND,
|
||||
M_SEE_END,
|
||||
M_CONTAINS,
|
||||
M_CARRIES,
|
||||
M_CONTAINS_COMMA,
|
||||
M_CONTAINS_AND,
|
||||
M_CONTAINS_END,
|
||||
M_EMPTY,
|
||||
M_EMPTYHANDED,
|
||||
M_CANNOTCONTAIN,
|
||||
M_SCORE,
|
||||
M_MORE,
|
||||
M_AGAIN,
|
||||
M_SAVEWHERE,
|
||||
M_SAVEOVERWRITE,
|
||||
M_SAVEFAILED,
|
||||
M_RESTOREFROM,
|
||||
M_SAVEMISSING,
|
||||
M_NOTASAVEFILE,
|
||||
M_SAVEVERS,
|
||||
M_SAVENAME,
|
||||
M_REALLY,
|
||||
M_QUITACTION,
|
||||
M_UNDONE,
|
||||
M_NO_UNDO,
|
||||
M_WHICH_PRONOUN_START,
|
||||
M_WHICH_PRONOUN_FIRST,
|
||||
M_IMPOSSIBLE_WITH,
|
||||
M_CONTAINMENT_LOOP,
|
||||
M_CONTAINMENT_LOOP2,
|
||||
MSGMAX
|
||||
};
|
||||
|
||||
#define NO_MSG MSGMAX
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
128
engines/glk/alan3/act.cpp
Normal file
128
engines/glk/alan3/act.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/* 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/alan3/act.h"
|
||||
#include "glk/alan3/alt_info.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void executeCommand(CONTEXT, int verb, Parameter parameters[]) {
|
||||
static AltInfo *altInfos = nullptr; /* Need to survive lots of different exits...*/
|
||||
int altIndex;
|
||||
bool flag;
|
||||
|
||||
/* Did we leave anything behind last time... */
|
||||
if (altInfos != nullptr)
|
||||
free(altInfos);
|
||||
|
||||
altInfos = findAllAlternatives(verb, parameters);
|
||||
|
||||
FUNC2(anyCheckFailed, flag, altInfos, EXECUTE_CHECK_BODY_ON_FAIL)
|
||||
if (flag)
|
||||
return;
|
||||
|
||||
/* Check for anything to execute... */
|
||||
if (!anythingToExecute(altInfos))
|
||||
CALL1(error, M_CANT0)
|
||||
|
||||
/* Now perform actions! First try any BEFORE or ONLY from inside out */
|
||||
for (altIndex = lastAltInfoIndex(altInfos); altIndex >= 0; altIndex--) {
|
||||
if (altInfos[altIndex].alt != nullptr) // TODO Can this ever be NULL? Why?
|
||||
if (altInfos[altIndex].alt->qual == (Aword)Q_BEFORE
|
||||
|| altInfos[altIndex].alt->qual == (Aword)Q_ONLY) {
|
||||
FUNC1(executedOk, flag, &altInfos[altIndex])
|
||||
if (!flag)
|
||||
CALL0(abortPlayerCommand)
|
||||
if (altInfos[altIndex].alt->qual == (Aword)Q_ONLY)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then execute any not declared as AFTER, i.e. the default */
|
||||
for (altIndex = 0; !altInfos[altIndex].end; altIndex++) {
|
||||
if (altInfos[altIndex].alt != nullptr) {
|
||||
if (altInfos[altIndex].alt->qual != (Aword)Q_AFTER) {
|
||||
FUNC1(executedOk, flag, &altInfos[altIndex])
|
||||
if (!flag)
|
||||
CALL0(abortPlayerCommand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, the ones declared as AFTER */
|
||||
for (altIndex = lastAltInfoIndex(altInfos); altIndex >= 0; altIndex--) {
|
||||
if (altInfos[altIndex].alt != nullptr) {
|
||||
FUNC1(executedOk, flag, &altInfos[altIndex])
|
||||
if (!flag)
|
||||
CALL0(abortPlayerCommand)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
action()
|
||||
|
||||
Execute the command. Handles acting on multiple items
|
||||
such as ALL, THEM or lists of objects.
|
||||
|
||||
*/
|
||||
void action(CONTEXT, int verb, Parameter parameters[], Parameter multipleMatches[]) {
|
||||
int multiplePosition;
|
||||
char marker[10];
|
||||
|
||||
multiplePosition = findMultiplePosition(parameters);
|
||||
if (multiplePosition != -1) {
|
||||
Common::sprintf_s(marker, "($%d)", multiplePosition + 1); /* Prepare a printout with $1/2/3 */
|
||||
for (int i = 0; !isEndOfArray(&multipleMatches[i]); i++) {
|
||||
copyParameter(¶meters[multiplePosition], &multipleMatches[i]);
|
||||
setGlobalParameters(parameters); /* Need to do this here since the marker use them */
|
||||
output(marker);
|
||||
|
||||
// WARNING: The original did a temporary grabbing of the returnLabel setjmp point here.
|
||||
// Which is why I manually check the context return instead of using the CALL macro
|
||||
executeCommand(context, verb, parameters);
|
||||
if (context._break && context._label.hasPrefix("return"))
|
||||
context._break = false;
|
||||
if (context._break)
|
||||
return;
|
||||
|
||||
if (multipleMatches[i + 1].instance != EOD)
|
||||
para();
|
||||
}
|
||||
|
||||
parameters[multiplePosition].instance = 0;
|
||||
} else {
|
||||
setGlobalParameters(parameters);
|
||||
CALL2(executeCommand, verb, parameters)
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
38
engines/glk/alan3/act.h
Normal file
38
engines/glk/alan3/act.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN3_ACT
|
||||
#define GLK_ALAN3_ACT
|
||||
|
||||
/* Header file for action unit of ARUN Alan System interpreter */
|
||||
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/params.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern void action(CONTEXT, int verb, Parameter *parameters, Parameter *multipleMatches);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
81
engines/glk/alan3/actor.cpp
Normal file
81
engines/glk/alan3/actor.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* 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/alan3/actor.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/container.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*======================================================================*/
|
||||
ScriptEntry *scriptOf(int actor) {
|
||||
ScriptEntry *scr;
|
||||
|
||||
if (admin[actor].script != 0) {
|
||||
for (scr = (ScriptEntry *) pointerTo(header->scriptTableAddress); !isEndOfArray(scr); scr++)
|
||||
if (scr->code == admin[actor].script)
|
||||
break;
|
||||
if (!isEndOfArray(scr))
|
||||
return scr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
StepEntry *stepOf(int actor) {
|
||||
StepEntry *step;
|
||||
ScriptEntry *scr = scriptOf(actor);
|
||||
|
||||
if (scr == nullptr) return nullptr;
|
||||
|
||||
step = (StepEntry *)pointerTo(scr->steps);
|
||||
step = &step[admin[actor].step];
|
||||
|
||||
return step;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void describeActor(CONTEXT, int actor) {
|
||||
ScriptEntry *script = scriptOf(actor);
|
||||
|
||||
if (script != nullptr && script->description != 0) {
|
||||
CALL1(interpret, script->description)
|
||||
} else if (hasDescription(actor)) {
|
||||
CALL1(describeAnything, actor)
|
||||
} else {
|
||||
printMessageWithInstanceParameter(M_SEE_START, actor);
|
||||
printMessage(M_SEE_END);
|
||||
|
||||
if (instances[actor].container != 0)
|
||||
CALL1(describeContainer, actor)
|
||||
}
|
||||
admin[actor].alreadyDescribed = TRUE;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
39
engines/glk/alan3/actor.h
Normal file
39
engines/glk/alan3/actor.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_ALAN3_ACTOR
|
||||
#define GLK_ALAN3_ACTOR
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern ScriptEntry *scriptOf(int actor);
|
||||
extern StepEntry *stepOf(int actor);
|
||||
extern void describeActor(CONTEXT, int actor);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
124
engines/glk/alan3/alan3.cpp
Normal file
124
engines/glk/alan3/alan3.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/* 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/alan3/alan3.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/main.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/save.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "common/system.h"
|
||||
#include "common/error.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/serializer.h"
|
||||
#include "glk/glk.h"
|
||||
#include "glk/streams.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
Alan3 *g_vm = nullptr;
|
||||
|
||||
Alan3::Alan3(OSystem *syst, const GlkGameDescription &gameDesc) : GlkIO(syst, gameDesc) {
|
||||
g_vm = this;
|
||||
|
||||
// main
|
||||
codfil = nullptr;
|
||||
textFile = nullptr;
|
||||
memory = nullptr;
|
||||
|
||||
// exe
|
||||
printFlag = false;
|
||||
|
||||
// options
|
||||
verboseOption = false;
|
||||
ignoreErrorOption = false;
|
||||
debugOption = false;
|
||||
traceSectionOption = false;
|
||||
tracePushOption = false;
|
||||
traceStackOption = false;
|
||||
traceSourceOption = false;
|
||||
traceInstructionOption = false;
|
||||
transcriptOption = false;
|
||||
logOption = false;
|
||||
statusLineOption = true;
|
||||
regressionTestOption = false;
|
||||
|
||||
// output
|
||||
anyOutput = false;
|
||||
capitalize = false;
|
||||
needSpace = false;
|
||||
skipSpace = false;
|
||||
|
||||
// syserr
|
||||
setSyserrHandler(nullptr);
|
||||
}
|
||||
|
||||
void Alan3::runGame() {
|
||||
if (initialize())
|
||||
Glk::Alan3::run();
|
||||
|
||||
deinitialize();
|
||||
}
|
||||
|
||||
bool Alan3::initialize() {
|
||||
if (!GlkIO::initialize())
|
||||
syserr("FATAL ERROR: Cannot open initial window");
|
||||
|
||||
// Set up adventure name
|
||||
_advName = getFilename();
|
||||
if (_advName.size() > 4 && _advName[_advName.size() - 4] == '.')
|
||||
_advName = Common::String(_advName.c_str(), _advName.size() - 4);
|
||||
|
||||
// In Alan 3, the text data comes from the adventure file itself
|
||||
Common::File *txt = new Common::File();
|
||||
if (!txt->open(Common::Path(getFilename()))) {
|
||||
GUIErrorMessage("Could not open adventure file for text data");
|
||||
delete txt;
|
||||
return false;
|
||||
}
|
||||
textFile = txt;
|
||||
|
||||
// Set up the code file to point to the already opened game file
|
||||
codfil = &_gameFile;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Alan3::deinitialize() {
|
||||
free(memory);
|
||||
delete textFile;
|
||||
// delete logfil;
|
||||
}
|
||||
|
||||
Common::Error Alan3::readSaveData(Common::SeekableReadStream *rs) {
|
||||
return Glk::Alan3::restoreGame(rs) ? Common::kNoError : Common::kReadingFailed;
|
||||
}
|
||||
|
||||
Common::Error Alan3::writeGameData(Common::WriteStream *ws) {
|
||||
Glk::Alan3::saveGame(ws);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
83
engines/glk/alan3/alan3.h
Normal file
83
engines/glk/alan3/alan3.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* 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 Alan 3 interpreter 3.0beta6 */
|
||||
|
||||
#ifndef GLK_ALAN3
|
||||
#define GLK_ALAN3
|
||||
|
||||
#include "glk/alan3/glkio.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/**
|
||||
* Alan3 game interpreter
|
||||
*/
|
||||
class Alan3 : public GlkIO {
|
||||
public:
|
||||
Common::String _advName;
|
||||
private:
|
||||
/**
|
||||
* Initialization
|
||||
*/
|
||||
bool initialize();
|
||||
|
||||
/**
|
||||
* Deinitialization
|
||||
*/
|
||||
void deinitialize();
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Alan3(OSystem *syst, const GlkGameDescription &gameDesc);
|
||||
|
||||
/**
|
||||
* Run the game
|
||||
*/
|
||||
void runGame() override;
|
||||
|
||||
/**
|
||||
* Returns the running interpreter type
|
||||
*/
|
||||
InterpreterType getInterpreterType() const override {
|
||||
return INTERPRETER_ALAN3;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Alan3 *g_vm;
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
41
engines/glk/alan3/alan_version.cpp
Normal file
41
engines/glk/alan3/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/alan3/alan_version.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
const Product alan = {
|
||||
"Alan",
|
||||
"Adventure Language System",
|
||||
"Alan 3.0beta6",
|
||||
"Alan 3.0beta6 -- Adventure Language System (2017-09-08 10:18)",
|
||||
"2017-09-08",
|
||||
"10:18:25",
|
||||
"Thomas",
|
||||
"thoni64",
|
||||
"cygwin32",
|
||||
{"3.0beta6", 3, 0, 6, 1504858705, "beta"}
|
||||
};
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
35
engines/glk/alan3/alan_version.h
Normal file
35
engines/glk/alan3/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_ALAN3_ALAN_VERSION
|
||||
#define GLK_ALAN3_ALAN_VERSION
|
||||
|
||||
#include "glk/alan3/version.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern const Product alan;
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
379
engines/glk/alan3/alt_info.cpp
Normal file
379
engines/glk/alan3/alt_info.cpp
Normal file
@@ -0,0 +1,379 @@
|
||||
/* 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/alan3/alt_info.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/checkentry.h"
|
||||
#include "glk/alan3/debug.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/class.h"
|
||||
#include "glk/alan3/params.h"
|
||||
#include "glk/alan3/literal.h"
|
||||
#include "glk/alan3/syntax.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Types */
|
||||
typedef AltInfo *AltInfoFinder(int verb, Parameter parameters[]);
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void primeAltInfo(AltInfo *altInfo, int level, int parameter, int instance, int cls) {
|
||||
altInfo->level = level;
|
||||
altInfo->parameter = parameter;
|
||||
altInfo->instance = instance;
|
||||
altInfo->_class = cls;
|
||||
altInfo->done = FALSE;
|
||||
altInfo->end = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceInstanceAndItsClass(CONTEXT, Aid instance, Aid cls) {
|
||||
CALL1(traceSay, instance)
|
||||
printf("[%d]", instance);
|
||||
if (cls != NO_CLASS)
|
||||
printf(", inherited from %s[%d]", idOfClass(cls), cls);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceAltInfo(CONTEXT, AltInfo *alt) {
|
||||
switch (alt->level) {
|
||||
case GLOBAL_LEVEL:
|
||||
printf("GLOBAL");
|
||||
break;
|
||||
case LOCATION_LEVEL:
|
||||
printf("in (location) ");
|
||||
CALL2(traceInstanceAndItsClass, current.location, alt->_class)
|
||||
break;
|
||||
case PARAMETER_LEVEL: {
|
||||
char *parameterName = parameterNameInSyntax(current.verb, alt->parameter);
|
||||
if (parameterName != nullptr)
|
||||
printf("in parameter %s(#%d)=", parameterName, alt->parameter);
|
||||
else
|
||||
printf("in parameter #%d=", alt->parameter);
|
||||
CALL2(traceInstanceAndItsClass, globalParameters[alt->parameter - 1].instance, alt->_class)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceVerbCheck(CONTEXT, AltInfo *alt, bool execute) {
|
||||
if (traceSectionOption && execute) {
|
||||
printf("\n<VERB %d, ", current.verb);
|
||||
CALL1(traceAltInfo, alt)
|
||||
printf(", CHECK:>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool checkFailed(CONTEXT, AltInfo *altInfo, bool execute) {
|
||||
if (altInfo->alt != nullptr && altInfo->alt->checks != 0) {
|
||||
R0CALL2(traceVerbCheck, altInfo, execute)
|
||||
|
||||
// TODO Why does this not generate a regression error with !
|
||||
// Need a new regression case?
|
||||
R0FUNC2(checksFailed, fail, altInfo->alt->checks, execute)
|
||||
return fail;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceVerbExecution(CONTEXT, AltInfo *alt) {
|
||||
if (traceSectionOption) {
|
||||
printf("\n<VERB %d, ", current.verb);
|
||||
CALL1(traceAltInfo, alt)
|
||||
printf(", DOES");
|
||||
|
||||
switch (alt->alt->qual) {
|
||||
case Q_BEFORE:
|
||||
printf(" (BEFORE)");
|
||||
break;
|
||||
case Q_ONLY:
|
||||
printf(" (ONLY)");
|
||||
break;
|
||||
case Q_AFTER:
|
||||
printf(" (AFTER)");
|
||||
break;
|
||||
case Q_DEFAULT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf(":>\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool executedOk(CONTEXT, AltInfo *altInfo) {
|
||||
fail = FALSE;
|
||||
if (!altInfo->done && altInfo->alt->action != 0) {
|
||||
R0CALL1(traceVerbExecution, altInfo)
|
||||
current.instance = altInfo->instance;
|
||||
R0CALL1(interpret, altInfo->alt->action)
|
||||
}
|
||||
altInfo->done = TRUE;
|
||||
return !fail;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool canBeExecuted(AltInfo *altInfo) {
|
||||
return altInfo->alt != nullptr && altInfo->alt->action != 0;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
AltInfo *duplicateAltInfoArray(AltInfo original[]) {
|
||||
int size;
|
||||
AltInfo *duplicate;
|
||||
|
||||
for (size = 0; original[size].end != TRUE; size++)
|
||||
;
|
||||
size++;
|
||||
duplicate = (AltInfo *)allocate(size * sizeof(AltInfo));
|
||||
memcpy(duplicate, original, size * sizeof(AltInfo));
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int lastAltInfoIndex(AltInfo altInfo[]) {
|
||||
int altIndex;
|
||||
|
||||
/* Loop to last alternative */
|
||||
for (altIndex = -1; !altInfo[altIndex + 1].end; altIndex++)
|
||||
;
|
||||
return altIndex;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static AltInfo *nextFreeAltInfo(AltInfoArray altInfos) {
|
||||
return &altInfos[lastAltInfoIndex(altInfos) + 1];
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void addAlternative(AltInfoArray altInfos, int verb, int level, Aint parameterNumber, Aint theClass, Aid theInstance, AltEntryFinder finder) {
|
||||
AltInfo *altInfoP = nextFreeAltInfo(altInfos);
|
||||
|
||||
altInfoP->alt = (*finder)(verb, parameterNumber, theInstance, theClass);
|
||||
if (altInfoP->alt != nullptr) {
|
||||
primeAltInfo(altInfoP, level, parameterNumber, theInstance, theClass);
|
||||
altInfoP[1].end = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void addGlobalAlternatives(AltInfoArray altInfos, int verb, AltEntryFinder finder) {
|
||||
addAlternative(altInfos, verb, GLOBAL_LEVEL, NO_PARAMETER, NO_CLASS, NO_INSTANCE, finder);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void addAlternativesFromParents(AltInfoArray altInfos, int verb, int level, Aint parameterNumber, Aint theClass, Aid theInstance, AltEntryFinder finder) {
|
||||
if (classes[theClass].parent != 0)
|
||||
addAlternativesFromParents(altInfos, verb, level,
|
||||
parameterNumber,
|
||||
classes[theClass].parent,
|
||||
theInstance,
|
||||
finder);
|
||||
|
||||
addAlternative(altInfos, verb, level, parameterNumber, theClass, theInstance, finder);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void addAlternativesFromLocation(AltInfoArray altInfos, int verb, Aid location, AltEntryFinder finder) {
|
||||
if (admin[location].location != 0)
|
||||
addAlternativesFromLocation(altInfos, verb, admin[location].location, finder);
|
||||
|
||||
addAlternativesFromParents(altInfos, verb,
|
||||
LOCATION_LEVEL,
|
||||
NO_PARAMETER,
|
||||
instances[location].parent,
|
||||
location,
|
||||
finder);
|
||||
|
||||
addAlternative(altInfos, verb, LOCATION_LEVEL, NO_PARAMETER, NO_CLASS, location, finder);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void addAlternativesFromParameter(AltInfoArray altInfos, int verb, Parameter parameters[], int parameterNumber, AltEntryFinder finder) {
|
||||
Aid parent;
|
||||
Aid theInstance = parameters[parameterNumber - 1].instance;
|
||||
|
||||
if (isLiteral(theInstance))
|
||||
parent = literals[literalFromInstance(theInstance)]._class;
|
||||
else
|
||||
parent = instances[theInstance].parent;
|
||||
addAlternativesFromParents(altInfos, verb, PARAMETER_LEVEL, parameterNumber, parent, theInstance, finder);
|
||||
|
||||
if (!isLiteral(theInstance))
|
||||
addAlternative(altInfos, verb, PARAMETER_LEVEL, parameterNumber, NO_CLASS, theInstance, finder);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool anyCheckFailed(CONTEXT, AltInfoArray altInfo, bool execute) {
|
||||
int altIndex;
|
||||
bool flag;
|
||||
|
||||
if (altInfo != nullptr)
|
||||
for (altIndex = 0; !altInfo[altIndex].end; altIndex++) {
|
||||
current.instance = altInfo[altIndex].instance;
|
||||
|
||||
R0FUNC2(checkFailed, flag, &altInfo[altIndex], execute)
|
||||
return flag;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool anythingToExecute(AltInfo altInfo[]) {
|
||||
int altIndex;
|
||||
|
||||
/* Check for anything to execute... */
|
||||
if (altInfo != nullptr)
|
||||
for (altIndex = 0; !altInfo[altIndex].end; altIndex++)
|
||||
if (canBeExecuted(&altInfo[altIndex]))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static VerbEntry *findVerbEntry(int verbCode, VerbEntry *entries) {
|
||||
VerbEntry *verbEntry;
|
||||
for (verbEntry = entries; !isEndOfArray(verbEntry); verbEntry++) {
|
||||
if (verbEntry->code < 0) {
|
||||
/* Verb codes are negative for Meta verbs, if so they are also 1 off to avoid EOD */
|
||||
if (abs(verbEntry->code) - 1 == verbCode)
|
||||
return verbEntry;
|
||||
} else {
|
||||
if (verbEntry->code == verbCode)
|
||||
return verbEntry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static AltEntry *findAlternative(Aaddr verbTableAddress, int verbCode, int parameterNumber) {
|
||||
AltEntry *alt;
|
||||
VerbEntry *verbEntry;
|
||||
|
||||
if (verbTableAddress == 0) return nullptr;
|
||||
|
||||
verbEntry = findVerbEntry(verbCode, (VerbEntry *) pointerTo(verbTableAddress));
|
||||
if (verbEntry != nullptr)
|
||||
for (alt = (AltEntry *) pointerTo(verbEntry->alts); !isEndOfArray(alt); alt++) {
|
||||
if (alt->param == parameterNumber || alt->param == 0) {
|
||||
if (verbEntry->code < 0) current.meta = TRUE;
|
||||
return alt;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static AltEntry *alternativeFinder(int verb, int parameterNumber, int theInstance, int theClass) {
|
||||
if ((Aword)theClass != NO_CLASS)
|
||||
return findAlternative(classes[theClass].verbs, verb, parameterNumber);
|
||||
else if ((Aword)theInstance != NO_INSTANCE)
|
||||
return findAlternative(instances[theInstance].verbs, verb, parameterNumber);
|
||||
else
|
||||
return findAlternative(header->verbTableAddress, verb, parameterNumber);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
AltInfo *findAllAlternatives(int verb, Parameter parameters[]) {
|
||||
int parameterNumber;
|
||||
AltInfo altInfos[1000];
|
||||
altInfos[0].end = TRUE;
|
||||
|
||||
addGlobalAlternatives(altInfos, verb, &alternativeFinder);
|
||||
|
||||
addAlternativesFromLocation(altInfos, verb, current.location, &alternativeFinder);
|
||||
|
||||
for (parameterNumber = 1; !isEndOfArray(¶meters[parameterNumber - 1]); parameterNumber++) {
|
||||
addAlternativesFromParameter(altInfos, verb, parameters, parameterNumber, &alternativeFinder);
|
||||
}
|
||||
return duplicateAltInfoArray(altInfos);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool possibleWithFinder(CONTEXT, int verb, Parameter parameters[], AltInfoFinder *finder) {
|
||||
bool anything;
|
||||
AltInfo *allAlternatives;
|
||||
bool flag;
|
||||
|
||||
allAlternatives = finder(verb, parameters);
|
||||
|
||||
// TODO Need to do this since anyCheckFailed() call execute() which assumes the global parameters
|
||||
setGlobalParameters(parameters);
|
||||
R0FUNC2(anyCheckFailed, flag, allAlternatives, DONT_EXECUTE_CHECK_BODY_ON_FAIL)
|
||||
if (flag)
|
||||
anything = FALSE;
|
||||
else
|
||||
anything = anythingToExecute(allAlternatives);
|
||||
|
||||
if (allAlternatives != nullptr)
|
||||
deallocate(allAlternatives);
|
||||
|
||||
return (anything);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool possible(CONTEXT, int verb, Parameter inParameters[], ParameterPosition parameterPositions[]) {
|
||||
// This is a wrapper for possibleWithFinder() which is used in unit tests
|
||||
// possible() should be used "for real".
|
||||
|
||||
return possibleWithFinder(context, verb, inParameters, findAllAlternatives);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
88
engines/glk/alan3/alt_info.h
Normal file
88
engines/glk/alan3/alt_info.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* 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_ALAN3_ALT_INFO
|
||||
#define GLK_ALAN3_ALT_INFO
|
||||
|
||||
/* An info node about the Verb Alternatives found and possibly executed */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/params.h"
|
||||
#include "glk/alan3/parameter_position.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define GLOBAL_LEVEL (0)
|
||||
#define LOCATION_LEVEL (1)
|
||||
#define PARAMETER_LEVEL (2)
|
||||
|
||||
#define NO_PARAMETER ((Aword)-1)
|
||||
#define NO_INSTANCE ((Aword)-1)
|
||||
#define NO_CLASS ((Aword)-1)
|
||||
|
||||
/* tryCheck() flags */
|
||||
#define EXECUTE_CHECK_BODY_ON_FAIL TRUE
|
||||
#define DONT_EXECUTE_CHECK_BODY_ON_FAIL FALSE
|
||||
|
||||
|
||||
/* Types */
|
||||
|
||||
struct AltInfo {
|
||||
bool end; /* Indicator of end in AltInfoArray, first empty has TRUE here */
|
||||
AltEntry *alt;
|
||||
bool done;
|
||||
Aint level; /* 0 - Global, 1 - location, 2 - parameter */
|
||||
Aid _class; /* In which class, only used for tracing */
|
||||
Aid instance; /* In which instance the Alternative was found,
|
||||
used to set current.instance and tracing */
|
||||
Aid parameter; /* In which parameter, only used for tracing */
|
||||
};
|
||||
|
||||
typedef AltEntry *(*AltEntryFinder)(int verb, int parameterNumber, int theInstance, int theClass);
|
||||
|
||||
typedef AltInfo AltInfoArray[];
|
||||
|
||||
|
||||
|
||||
/* Data */
|
||||
|
||||
|
||||
/* Functions */
|
||||
extern void primeAltInfo(AltInfo *altInfo, int level, int parameter, int instance, int cls);
|
||||
extern bool executedOk(CONTEXT, AltInfo *altInfo);
|
||||
extern bool checkFailed(CONTEXT, AltInfo *altInfo, bool execute);
|
||||
extern bool canBeExecuted(AltInfo *altInfo);
|
||||
extern AltInfo *duplicateAltInfoArray(AltInfoArray altInfos);
|
||||
extern int lastAltInfoIndex(AltInfoArray altInfos);
|
||||
extern bool anyCheckFailed(CONTEXT, AltInfoArray altInfos, bool execute);
|
||||
extern bool anythingToExecute(AltInfoArray altInfos);
|
||||
extern bool possible(CONTEXT, int verb, Parameter parameters[], ParameterPosition parameterPositions[]);
|
||||
extern AltInfo *findAllAlternatives(int verb, Parameter parameters[]);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
59
engines/glk/alan3/attribute.cpp
Normal file
59
engines/glk/alan3/attribute.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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/alan3/attribute.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static AttributeEntry *findAttribute(AttributeEntry *attributeTable, int attributeCode) {
|
||||
AttributeEntry *attribute = attributeTable;
|
||||
while (attribute->code != attributeCode) {
|
||||
attribute++;
|
||||
if (isEndOfArray(attribute))
|
||||
syserr("Attribute not found.");
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Aptr getAttribute(AttributeEntry *attributeTable, int attributeCode) {
|
||||
AttributeEntry *attribute = findAttribute(attributeTable, attributeCode);
|
||||
|
||||
return attribute->value;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void setAttribute(AttributeEntry *attributeTable, int attributeCode, Aptr newValue) {
|
||||
AttributeEntry *attribute = findAttribute(attributeTable, attributeCode);
|
||||
|
||||
attribute->value = newValue;
|
||||
gameStateChanged = TRUE;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
37
engines/glk/alan3/attribute.h
Normal file
37
engines/glk/alan3/attribute.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_ALAN3_ATTRIBUTE
|
||||
#define GLK_ALAN3_ATTRIBUTE
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern Aptr getAttribute(AttributeEntry *attributeTable, int attributeCode);
|
||||
extern void setAttribute(AttributeEntry *attributeTable, int attributeCode, Aptr newValue);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
53
engines/glk/alan3/checkentry.cpp
Normal file
53
engines/glk/alan3/checkentry.cpp
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan3/checkentry.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
bool checksFailed(CONTEXT, Aaddr adr, bool execute) {
|
||||
CheckEntry *chk = (CheckEntry *) pointerTo(adr);
|
||||
bool flag;
|
||||
|
||||
if (chk->exp == 0) {
|
||||
if (execute == EXECUTE_CHECK_BODY_ON_FAIL)
|
||||
R0CALL1(interpret, chk->stms)
|
||||
return TRUE;
|
||||
} else {
|
||||
while (!isEndOfArray(chk)) {
|
||||
R0FUNC1(evaluate, flag, chk->exp)
|
||||
if (!flag) {
|
||||
if (execute == EXECUTE_CHECK_BODY_ON_FAIL)
|
||||
R0CALL1(interpret, chk->stms)
|
||||
return TRUE;
|
||||
}
|
||||
chk++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
56
engines/glk/alan3/checkentry.h
Normal file
56
engines/glk/alan3/checkentry.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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_ALAN3_CHECKENTRY
|
||||
#define GLK_ALAN3_CHECKENTRY
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* CONSTANTS */
|
||||
#ifndef EXECUTE_CHECK_BODY_ON_FAIL
|
||||
#define EXECUTE_CHECK_BODY_ON_FAIL TRUE
|
||||
#define DONT_EXECUTE_CHECK_BODY_ON_FAIL FALSE
|
||||
#endif
|
||||
|
||||
|
||||
/* TYPES */
|
||||
struct CheckEntry { /* CHECK TABLE */
|
||||
Aaddr exp; /* ACODE address to expression code */
|
||||
Aaddr stms; /* ACODE address to statement code */
|
||||
};
|
||||
|
||||
|
||||
/* DATA */
|
||||
typedef CheckEntry CheckEntryArray[];
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern bool checksFailed(CONTEXT, Aaddr adr, bool execute);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
37
engines/glk/alan3/class.cpp
Normal file
37
engines/glk/alan3/class.cpp
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan3/class.h"
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
ClassEntry *classes; /* Class table pointer */
|
||||
|
||||
/*======================================================================*/
|
||||
char *idOfClass(int theClass) {
|
||||
return (char *)pointerTo(classes[theClass].id);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
39
engines/glk/alan3/class.h
Normal file
39
engines/glk/alan3/class.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_ALAN3_CLASS
|
||||
#define GLK_ALAN3_CLASS
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern ClassEntry *classes; /* Class table pointer */
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern char *idOfClass(int theClass);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
68
engines/glk/alan3/compatibility.cpp
Normal file
68
engines/glk/alan3/compatibility.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/* 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/alan3/compatibility.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool is3_0Alpha(const byte version[]) {
|
||||
return version[3] == 3 && version[2] == 0 && version[0] == 'a';
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool is3_0Beta(const byte version[]) {
|
||||
return version[3] == 3 && version[2] == 0 && version[0] == 'b';
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int correction(const byte version[]) {
|
||||
return version[1];
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
bool isPreAlpha5(const byte version[4]) {
|
||||
return is3_0Alpha(version) && correction(version) < 5;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
bool isPreBeta2(const byte version[4]) {
|
||||
return is3_0Alpha(version) || (is3_0Beta(version) && correction(version) == 1);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
bool isPreBeta3(const byte version[4]) {
|
||||
return is3_0Alpha(version) || (is3_0Beta(version) && correction(version) <= 2);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
bool isPreBeta4(const byte version[4]) {
|
||||
return is3_0Alpha(version) || (is3_0Beta(version) && correction(version) <= 3);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
bool isPreBeta5(const byte version[4]) {
|
||||
return is3_0Alpha(version) || (is3_0Beta(version) && correction(version) <= 4);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
41
engines/glk/alan3/compatibility.h
Normal file
41
engines/glk/alan3/compatibility.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_ALAN3_COMPATIBILITY
|
||||
#define GLK_ALAN3_COMPATIBILITY
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* FUNCTIONS: */
|
||||
extern bool isPreAlpha5(const byte version[4]);
|
||||
extern bool isPreBeta2(const byte version[4]);
|
||||
extern bool isPreBeta3(const byte version[4]);
|
||||
extern bool isPreBeta4(const byte version[4]);
|
||||
extern bool isPreBeta5(const byte version[4]);
|
||||
extern char *decodedGameVersion(const byte version[]);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
185
engines/glk/alan3/container.cpp
Normal file
185
engines/glk/alan3/container.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
/* 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/alan3/container.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/output.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
ContainerEntry *containers; /* Container table pointer */
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int countInContainer(int containerIndex) { /* IN - the container to count in */
|
||||
int j = 0;
|
||||
|
||||
for (uint instanceIndex = 1; instanceIndex <= header->instanceMax; instanceIndex++)
|
||||
if (isIn(instanceIndex, containerIndex, DIRECT))
|
||||
/* Then it's in this container also */
|
||||
j++;
|
||||
return (j);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int sumAttributeInContainer(
|
||||
Aint containerIndex, /* IN - the container to sum */
|
||||
Aint attributeIndex /* IN - the attribute to sum over */
|
||||
) {
|
||||
uint instanceIndex;
|
||||
int sum = 0;
|
||||
|
||||
for (instanceIndex = 1; instanceIndex <= header->instanceMax; instanceIndex++)
|
||||
if (isIn(instanceIndex, containerIndex, DIRECT)) { /* Then it's directly in this cont */
|
||||
if (instances[instanceIndex].container != 0) /* This is also a container! */
|
||||
sum = sum + sumAttributeInContainer(instanceIndex, attributeIndex);
|
||||
sum = sum + getInstanceAttribute(instanceIndex, attributeIndex);
|
||||
}
|
||||
return (sum);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool containerIsEmpty(int container) {
|
||||
uint i;
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++)
|
||||
if (isDescribable(i) && isIn(i, container, TRANSITIVE))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void describeContainer(CONTEXT, int container) {
|
||||
if (!containerIsEmpty(container) && !isOpaque(container))
|
||||
CALL1(list, container)
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool passesContainerLimits(CONTEXT, Aint theContainer, Aint theAddedInstance) {
|
||||
LimitEntry *limit;
|
||||
Aword props;
|
||||
|
||||
if (!isAContainer(theContainer))
|
||||
syserr("Checking limits for a non-container.");
|
||||
|
||||
/* Find the container properties */
|
||||
props = instances[theContainer].container;
|
||||
|
||||
if (containers[props].limits != 0) { /* Any limits at all? */
|
||||
for (limit = (LimitEntry *) pointerTo(containers[props].limits); !isEndOfArray(limit); limit++)
|
||||
if ((int)limit->atr == 1 - I_COUNT) { /* TODO This is actually some encoding of the attribute number, right? */
|
||||
if (countInContainer(theContainer) >= (int)limit->val) {
|
||||
R0CALL1(interpret, limit->stms)
|
||||
return (FALSE);
|
||||
}
|
||||
} else {
|
||||
if (sumAttributeInContainer(theContainer, limit->atr) + getInstanceAttribute(theAddedInstance, limit->atr) > limit->val) {
|
||||
R0CALL1(interpret, limit->stms)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int containerSize(int container, ATrans trans) {
|
||||
Aword i;
|
||||
Aint count = 0;
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++) {
|
||||
if (isIn(i, container, trans))
|
||||
count++;
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void list(CONTEXT, int container) {
|
||||
uint i;
|
||||
Aword props;
|
||||
Aword foundInstance[2] = {0, 0};
|
||||
int found = 0;
|
||||
Aint previousThis = current.instance;
|
||||
|
||||
current.instance = container;
|
||||
|
||||
/* Find container table entry */
|
||||
props = instances[container].container;
|
||||
if (props == 0) syserr("Trying to list something not a container.");
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++) {
|
||||
if (isDescribable(i)) {
|
||||
/* We can only see objects and actors directly in this container... */
|
||||
if (admin[i].location == container) { /* Yes, it's in this container */
|
||||
if (found == 0) {
|
||||
if (containers[props].header != 0) {
|
||||
CALL1(interpret, containers[props].header)
|
||||
} else {
|
||||
if (isAActor(containers[props].owner))
|
||||
printMessageWithInstanceParameter(M_CARRIES, containers[props].owner);
|
||||
else
|
||||
printMessageWithInstanceParameter(M_CONTAINS, containers[props].owner);
|
||||
}
|
||||
foundInstance[0] = i;
|
||||
} else if (found == 1)
|
||||
foundInstance[1] = i;
|
||||
else {
|
||||
printMessageWithInstanceParameter(M_CONTAINS_COMMA, i);
|
||||
}
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found > 0) {
|
||||
if (found > 1)
|
||||
printMessageWithInstanceParameter(M_CONTAINS_AND, foundInstance[1]);
|
||||
printMessageWithInstanceParameter(M_CONTAINS_END, foundInstance[0]);
|
||||
} else {
|
||||
if (containers[props].empty != 0) {
|
||||
CALL1(interpret, containers[props].empty)
|
||||
} else {
|
||||
if (isAActor(containers[props].owner))
|
||||
printMessageWithInstanceParameter(M_EMPTYHANDED, containers[props].owner);
|
||||
else
|
||||
printMessageWithInstanceParameter(M_EMPTY, containers[props].owner);
|
||||
}
|
||||
}
|
||||
needSpace = TRUE;
|
||||
current.instance = previousThis;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
45
engines/glk/alan3/container.h
Normal file
45
engines/glk/alan3/container.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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_ALAN3_CONTAINER
|
||||
#define GLK_ALAN3_CONTAINER
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern ContainerEntry *containers; /* Container table pointer */
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern int containerSize(int container, ATrans trans);
|
||||
extern bool passesContainerLimits(CONTEXT, Aint container, Aint addedInstance);
|
||||
extern void describeContainer(CONTEXT, int container);
|
||||
extern void list(CONTEXT, int cnt);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
46
engines/glk/alan3/current.cpp
Normal file
46
engines/glk/alan3/current.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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/alan3/current.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
CurVars current;
|
||||
bool gameStateChanged = FALSE;
|
||||
|
||||
void CurVars::synchronize(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(syntax);
|
||||
s.syncAsSint32LE(verb);
|
||||
s.syncAsSint32LE(location);
|
||||
s.syncAsSint32LE(actor);
|
||||
s.syncAsSint32LE(instance);
|
||||
s.syncAsSint32LE(tick);
|
||||
s.syncAsSint32LE(score);
|
||||
s.syncAsSint32LE(visits);
|
||||
s.syncAsSint32LE(sourceLine);
|
||||
s.syncAsSint32LE(sourceFile);
|
||||
s.syncAsUint32LE(meta);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
57
engines/glk/alan3/current.h
Normal file
57
engines/glk/alan3/current.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_ALAN3_CURRENT
|
||||
#define GLK_ALAN3_CURRENT
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* TYPES */
|
||||
struct CurVars {
|
||||
int syntax,
|
||||
verb,
|
||||
location,
|
||||
actor,
|
||||
instance,
|
||||
tick,
|
||||
score,
|
||||
visits,
|
||||
sourceLine,
|
||||
sourceFile;
|
||||
bool meta;
|
||||
|
||||
/**
|
||||
* Save/load data from save file
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
/* DATA */
|
||||
extern CurVars current;
|
||||
extern bool gameStateChanged;
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
1107
engines/glk/alan3/debug.cpp
Normal file
1107
engines/glk/alan3/debug.cpp
Normal file
File diff suppressed because it is too large
Load Diff
58
engines/glk/alan3/debug.h
Normal file
58
engines/glk/alan3/debug.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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_ALAN3_DEBUG
|
||||
#define GLK_ALAN3_DEBUG
|
||||
|
||||
/* Header file for debug handler in Alan interpreter */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Types: */
|
||||
|
||||
struct Breakpoint {
|
||||
int line;
|
||||
int file;
|
||||
};
|
||||
|
||||
|
||||
/* Data: */
|
||||
extern int breakpointCount;
|
||||
extern Breakpoint breakpoint[];
|
||||
|
||||
/* Functions: */
|
||||
extern void saveInfo(void);
|
||||
extern void restoreInfo(void);
|
||||
extern int breakpointIndex(int file, int line);
|
||||
extern char *sourceFileName(int file);
|
||||
extern char *readSourceLine(int file, int line);
|
||||
extern void showSourceLine(int fileNumber, int line);
|
||||
extern void debug(CONTEXT, bool calledFromBreakpoint, int line, int fileNumber);
|
||||
extern void traceSay(CONTEXT, int item);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
176
engines/glk/alan3/decode.cpp
Normal file
176
engines/glk/alan3/decode.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/* 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/alan3/decode.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
Aword *freq; /* Cumulative character frequencies */
|
||||
|
||||
|
||||
/* PRIVATE DATA */
|
||||
/* 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(void) {
|
||||
int bit;
|
||||
|
||||
/* More bits available ? */
|
||||
if (!bitsToGo) {
|
||||
/* No, so get more */
|
||||
decodeBuffer = (textFile->pos() >= textFile->size()) ? EOD : textFile->readByte();
|
||||
if (decodeBuffer == (int)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(void) {
|
||||
int i;
|
||||
|
||||
bitsToGo = 0;
|
||||
garbageBits = 0;
|
||||
|
||||
value = 0;
|
||||
for (i = 0; i < VALUEBITS; i++)
|
||||
value = 2 * value + inputBit();
|
||||
low = 0;
|
||||
high = TOPVALUE;
|
||||
}
|
||||
|
||||
|
||||
int decodeChar(void) {
|
||||
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 */
|
||||
struct DecodeInfo {
|
||||
long fpos;
|
||||
int buffer;
|
||||
int bits;
|
||||
CodeValue value;
|
||||
CodeValue high;
|
||||
CodeValue low;
|
||||
};
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
pushDecode()
|
||||
|
||||
Save so much info about the decoding process so it is possible to
|
||||
restore and continue later.
|
||||
|
||||
*/
|
||||
void *pushDecode(void) {
|
||||
DecodeInfo *info;
|
||||
|
||||
info = (DecodeInfo *)allocate(sizeof(DecodeInfo));
|
||||
info->fpos = textFile->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;
|
||||
|
||||
textFile->seek(info->fpos);
|
||||
decodeBuffer = info->buffer;
|
||||
bitsToGo = info->bits;
|
||||
value = info->value;
|
||||
high = info->high;
|
||||
low = info->low;
|
||||
|
||||
free(info);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
45
engines/glk/alan3/decode.h
Normal file
45
engines/glk/alan3/decode.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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_ALAN3_DECODE
|
||||
#define GLK_ALAN3_DECODE
|
||||
|
||||
/* Arithmetic decoding module in Arun */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern Aword *freq; /* Cumulated character frequencies for text decoding */
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
extern void startDecoding(void);
|
||||
extern int decodeChar(void);
|
||||
extern void *pushDecode(void);
|
||||
extern void popDecode(void *info);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
98
engines/glk/alan3/detection.cpp
Normal file
98
engines/glk/alan3/detection.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/* 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/alan3/detection.h"
|
||||
#include "glk/alan3/detection_tables.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/md5.h"
|
||||
#include "engines/game.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
void Alan3MetaEngine::getSupportedGames(PlainGameList &games) {
|
||||
for (const PlainGameDescriptor *pd = ALAN3_GAME_LIST; pd->gameId; ++pd) {
|
||||
games.push_back(*pd);
|
||||
}
|
||||
}
|
||||
|
||||
const GlkDetectionEntry* Alan3MetaEngine::getDetectionEntries() {
|
||||
return ALAN3_GAMES;
|
||||
}
|
||||
|
||||
GameDescriptor Alan3MetaEngine::findGame(const char *gameId) {
|
||||
for (const PlainGameDescriptor *pd = ALAN3_GAME_LIST; pd->gameId; ++pd) {
|
||||
if (!strcmp(gameId, pd->gameId))
|
||||
return *pd;
|
||||
}
|
||||
|
||||
return GameDescriptor::empty();
|
||||
}
|
||||
|
||||
bool Alan3MetaEngine::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(".a3c");
|
||||
if (!hasExt)
|
||||
continue;
|
||||
|
||||
// Open up the file and calculate the md5
|
||||
Common::File gameFile;
|
||||
if (!gameFile.open(*file) || gameFile.readUint32BE() != MKTAG('A', 'L', 'A', 'N'))
|
||||
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 = ALAN3_GAMES;
|
||||
while (p->_gameId && (md5 != p->_md5 || filesize != p->_filesize))
|
||||
++p;
|
||||
|
||||
if (!p->_gameId) {
|
||||
const PlainGameDescriptor &desc = ALAN3_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, filename));
|
||||
}
|
||||
}
|
||||
|
||||
return !gameList.empty();
|
||||
}
|
||||
|
||||
void Alan3MetaEngine::detectClashes(Common::StringMap &map) {
|
||||
for (const PlainGameDescriptor *pd = ALAN3_GAME_LIST; pd->gameId; ++pd) {
|
||||
if (map.contains(pd->gameId))
|
||||
error("Duplicate game Id found - %s", pd->gameId);
|
||||
map[pd->gameId] = "";
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
67
engines/glk/alan3/detection.h
Normal file
67
engines/glk/alan3/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_ALAN3_DETECTION
|
||||
#define GLK_ALAN3_DETECTION
|
||||
|
||||
#include "common/fs.h"
|
||||
#include "common/hash-str.h"
|
||||
#include "engines/game.h"
|
||||
#include "glk/detection.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/**
|
||||
* Meta engine for Alan3 interpreter
|
||||
*/
|
||||
class Alan3MetaEngine {
|
||||
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 Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
74
engines/glk/alan3/detection_tables.h
Normal file
74
engines/glk/alan3/detection_tables.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* 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/language.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
const PlainGameDescriptor ALAN3_GAME_LIST[] = {
|
||||
{ "alan3", "Alan3 Game" },
|
||||
|
||||
{ "catchcat", "Catch That Cat" },
|
||||
{ "christmasparty", "The Christmas Party" },
|
||||
{ "deadleaves", "City of Dead Leaves" },
|
||||
{ "enterthedark", "Enter The Dark" },
|
||||
{ "fishmess", "A Very Hairy Fish-Mess" },
|
||||
{ "forbidden", "The Ngah Angah School of Forbidden Wisdom" },
|
||||
{ "hwmurders", "Hollywood Murders" },
|
||||
{ "indigosoul", "IN-D-I-GO SOUL" },
|
||||
{ "misguided", "Mis/Guided" },
|
||||
{ "onaar", "Onaar" },
|
||||
{ "room206", "Room 206" },
|
||||
{ "tedpaladin", "Ted Paladin And The Case Of The Abandoned House" },
|
||||
{ "tedstrikesback", "Ted Strikes Back" },
|
||||
{ "thesealedroom", "The Sealed Room" },
|
||||
{ "vrgambler", "VR Gambler" },
|
||||
{ "waldospie", "Waldo's Pie" },
|
||||
{ "wyldkyndproject", "The Wyldkynd Project" },
|
||||
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
const GlkDetectionEntry ALAN3_GAMES[] = {
|
||||
DT_ENTRY0("catchcat", "758325a2c46f72218a82f22736ea7017", 43878),
|
||||
DT_ENTRY0("christmasparty", "86b87969d124c213632398980ec87c23", 94892),
|
||||
DT_ENTRY0("deadleaves", "7c228698507508043d1d3938695e28cd", 90139),
|
||||
DT_ENTRY0("enterthedark", "739add0fec3dbd18a63389826ffeba4d", 78900),
|
||||
DT_ENTRY0("fishmess", "e9952cfbe2adef5dcef82abd57661f60", 312561),
|
||||
DT_ENTRY0("forbidden", "8ce2b96851d43a72c84144632d6a084f", 122072),
|
||||
DT_ENTRY0("hwmurders", "abadbb15faf7f0b7324222fdea6bd495", 213539),
|
||||
DT_ENTRY0("indigosoul", "2c87486c4a44f5ef5a704a0b55763c61", 163903),
|
||||
DT_ENTRY0("misguided", "cc2c6e724d599e731efa9b7a34ae4f51", 672613),
|
||||
DT_ENTRY0("onaar", "f809531286f1757ab113fe3592a49d3b", 1516301),
|
||||
DT_ENTRY0("room206", "eb5711ecfad102ee4d9fda7fcb3ddf78", 364156),
|
||||
DT_ENTRY0("tedpaladin", "6132d401ea7c05b474e598a37b642bd9", 292486),
|
||||
DT_ENTRY0("tedstrikesback", "6085ede584b3705370b2a689cc96419a", 407634),
|
||||
DT_ENTRY0("thesealedroom", "06a81cb30efff9c63e7f7d3aff554d3d", 306937),
|
||||
DT_ENTRY0("vrgambler", "c29b8276a9a1be1444193eb3724bf0fd", 938147),
|
||||
DT_ENTRY0("waldospie", "fcd53ac4669f85845c1cbbaad6082724", 511956),
|
||||
DT_ENTRY0("wyldkyndproject", "35b2f168cb78d7df46638dcb583f5e15", 1333195),
|
||||
DT_END_MARKER
|
||||
};
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
134
engines/glk/alan3/dictionary.cpp
Normal file
134
engines/glk/alan3/dictionary.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* 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/alan3/dictionary.h"
|
||||
#include "glk/alan3/word.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
DictionaryEntry *dictionary; /* Dictionary pointer */
|
||||
int dictionarySize;
|
||||
int conjWord; /* First conjunction in dictionary, for ',' */
|
||||
|
||||
|
||||
|
||||
/* Word class query methods, move to Word.c */
|
||||
/* Word classes are numbers but in the dictionary they are generated as bits */
|
||||
static bool isVerb(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & VERB_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isVerbWord(int wordIndex) {
|
||||
return isVerb(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
bool isConjunction(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & CONJUNCTION_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isConjunctionWord(int wordIndex) {
|
||||
return isConjunction(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isExcept(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & EXCEPT_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isExceptWord(int wordIndex) {
|
||||
return isExcept(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isThem(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & THEM_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isThemWord(int wordIndex) {
|
||||
return isThem(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isIt(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & IT_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isItWord(int wordIndex) {
|
||||
return isIt(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isNoun(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & NOUN_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isNounWord(int wordIndex) {
|
||||
return isNoun(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isAdjective(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & ADJECTIVE_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isAdjectiveWord(int wordIndex) {
|
||||
return isAdjective(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isPreposition(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & PREPOSITION_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isPrepositionWord(int wordIndex) {
|
||||
return isPreposition(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
bool isAll(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & ALL_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isAllWord(int wordIndex) {
|
||||
return isAll(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
static bool isDir(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & DIRECTION_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isDirectionWord(int wordIndex) {
|
||||
return isDir(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
bool isNoise(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & NOISE_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isPronoun(int wordCode) {
|
||||
return wordCode < dictionarySize && (dictionary[wordCode].classBits & PRONOUN_BIT) != 0;
|
||||
}
|
||||
|
||||
bool isPronounWord(int wordIndex) {
|
||||
return isPronoun(playerWords[wordIndex].code);
|
||||
}
|
||||
|
||||
bool isLiteralWord(int wordIndex) {
|
||||
return playerWords[wordIndex].code >= dictionarySize;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
59
engines/glk/alan3/dictionary.h
Normal file
59
engines/glk/alan3/dictionary.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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_ALAN3_DICTIONARY
|
||||
#define GLK_ALAN3_DICTIONARY
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern DictionaryEntry *dictionary;
|
||||
extern int dictionarySize;
|
||||
extern int conjWord; /* First conjunction in dictionary */
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern bool isVerbWord(int wordIndex);
|
||||
extern bool isConjunctionWord(int wordIndex);
|
||||
extern bool isExceptWord(int wordIndex);
|
||||
extern bool isThemWord(int wordIndex);
|
||||
extern bool isItWord(int wordIndex);
|
||||
extern bool isNounWord(int wordIndex);
|
||||
extern bool isAdjectiveWord(int wordIndex);
|
||||
extern bool isPrepositionWord(int wordIndex);
|
||||
extern bool isAllWord(int wordIndex);
|
||||
extern bool isDirectionWord(int wordIndex);
|
||||
extern bool isPronounWord(int wordIndex);
|
||||
extern bool isLiteralWord(int wordIndex);
|
||||
|
||||
extern bool isConjunction(int wordCode);
|
||||
extern bool isAll(int wordCode);
|
||||
extern bool isNoise(int wordCode);
|
||||
extern bool isPronoun(int wordCode);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
40
engines/glk/alan3/event.cpp
Normal file
40
engines/glk/alan3/event.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/* 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/alan3/event.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
int eventQueueSize = 0;
|
||||
EventQueueEntry *eventQueue = nullptr;
|
||||
int eventQueueTop = 0;
|
||||
EventEntry *events;
|
||||
|
||||
void EventQueueEntry::synchronize(Common::Serializer &s) {
|
||||
s.syncAsSint32LE(after);
|
||||
s.syncAsSint32LE(event);
|
||||
s.syncAsSint32LE(where);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
57
engines/glk/alan3/event.h
Normal file
57
engines/glk/alan3/event.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_ALAN3_EVENT
|
||||
#define GLK_ALAN3_EVENT
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/**
|
||||
* Event queue entries
|
||||
*/
|
||||
struct EventQueueEntry {
|
||||
int after;
|
||||
int event;
|
||||
int where;
|
||||
|
||||
/**
|
||||
* Save/load from a save file
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
|
||||
/* DATA */
|
||||
/* Event queue */
|
||||
extern int eventQueueSize;
|
||||
extern EventQueueEntry *eventQueue;
|
||||
extern int eventQueueTop; /* Event queue top pointer */
|
||||
extern EventEntry *events; /* Event table pointer */
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
664
engines/glk/alan3/exe.cpp
Normal file
664
engines/glk/alan3/exe.cpp
Normal file
@@ -0,0 +1,664 @@
|
||||
/* 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/alan3/exe.h"
|
||||
#include "glk/alan3/actor.h"
|
||||
#include "glk/alan3/alan3.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/decode.h"
|
||||
#include "glk/alan3/event.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/save.h"
|
||||
#include "glk/alan3/score.h"
|
||||
#include "glk/alan3/state.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/sysdep.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/utils.h"
|
||||
#include "glk/alan3/word.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
// PUBLIC DATA
|
||||
Common::SeekableReadStream *textFile;
|
||||
|
||||
// PUBLIC DATA - formerly method statics
|
||||
bool printFlag; // Printing already?
|
||||
|
||||
/* PRIVATE CONSTANTS */
|
||||
|
||||
#define WIDTH 80
|
||||
|
||||
/*======================================================================*/
|
||||
void print(Aword fpos, Aword len) {
|
||||
char str[2 * WIDTH]; /* String buffer */
|
||||
uint outlen = 0; /* Current output length */
|
||||
int ch = 0;
|
||||
int i;
|
||||
long savfp = 0; /* Temporary saved text file position */
|
||||
bool savedPrintFlag = printFlag;
|
||||
void *info = nullptr; /* Saved decoding info */
|
||||
|
||||
|
||||
if (len == 0) return;
|
||||
|
||||
if (isHere(HERO, /*TRUE*/ DIRECT)) { /* Check if the player will see it */
|
||||
if (printFlag) { /* Already printing? */
|
||||
/* Save current text file position and/or decoding info */
|
||||
if (header->pack)
|
||||
info = pushDecode();
|
||||
else
|
||||
savfp = textFile->pos();
|
||||
}
|
||||
printFlag = TRUE; /* We're printing now! */
|
||||
|
||||
/* Position to start of text */
|
||||
textFile->seek(fpos + header->stringOffset);
|
||||
|
||||
if (header->pack)
|
||||
startDecoding();
|
||||
for (outlen = 0; outlen != len; outlen = outlen + strlen(str)) {
|
||||
/* Fill the buffer from the beginning */
|
||||
for (i = 0; i <= WIDTH || (i > WIDTH && ch != ' '); i++) {
|
||||
if (outlen + i == len) /* No more characters? */
|
||||
break;
|
||||
if (header->pack)
|
||||
ch = decodeChar();
|
||||
else
|
||||
ch = textFile->readByte();
|
||||
|
||||
if (ch == EOFChar)
|
||||
break; // Or end of text?
|
||||
|
||||
str[i] = ch;
|
||||
}
|
||||
str[i] = '\0';
|
||||
|
||||
output(str);
|
||||
}
|
||||
|
||||
/* And restore */
|
||||
printFlag = savedPrintFlag;
|
||||
if (printFlag) {
|
||||
if (header->pack)
|
||||
popDecode(info);
|
||||
else
|
||||
textFile->seek(savfp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void sys(Aword fpos, Aword len) {
|
||||
syserr("sys calls are unsupported");
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
char *getStringFromFile(Aword fpos, Aword len) {
|
||||
char *buf = (char *)allocate(len + 1);
|
||||
char *bufp = buf;
|
||||
|
||||
/* Position to start of text */
|
||||
textFile->seek(fpos + header->stringOffset);
|
||||
|
||||
if (header->pack)
|
||||
startDecoding();
|
||||
while (len--)
|
||||
if (header->pack)
|
||||
*(bufp++) = decodeChar();
|
||||
else
|
||||
*(bufp++) = textFile->readByte();
|
||||
|
||||
/* Terminate string with zero */
|
||||
*bufp = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void score(Aword sc) {
|
||||
if (sc == 0) {
|
||||
ParameterArray messageParameters = newParameterArray();
|
||||
addParameterForInteger(messageParameters, current.score);
|
||||
addParameterForInteger(messageParameters, header->maximumScore);
|
||||
addParameterForInteger(messageParameters, current.tick);
|
||||
printMessageWithParameters(M_SCORE, messageParameters);
|
||||
freeParameterArray(messageParameters);
|
||||
} else {
|
||||
current.score += scores[sc - 1];
|
||||
scores[sc - 1] = 0;
|
||||
gameStateChanged = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void visits(Aword v) {
|
||||
current.visits = v;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void sayUndoneCommand(char *words) {
|
||||
static Parameter *messageParameters = nullptr;
|
||||
messageParameters = (Parameter *)ensureParameterArrayAllocated(messageParameters);
|
||||
|
||||
current.location = where(HERO, DIRECT);
|
||||
clearParameterArray(messageParameters);
|
||||
addParameterForString(&messageParameters[0], words);
|
||||
setEndOfArray(&messageParameters[1]);
|
||||
printMessageWithParameters(M_UNDONE, messageParameters);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void undo(CONTEXT) {
|
||||
forgetGameState();
|
||||
if (anySavedState()) {
|
||||
recallGameState();
|
||||
sayUndoneCommand(recreatePlayerCommand());
|
||||
} else {
|
||||
printMessage(M_NO_UNDO);
|
||||
}
|
||||
|
||||
LONG_JUMP_LABEL("returnUndo")
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void quitGame(CONTEXT) {
|
||||
char buf[80];
|
||||
bool flag;
|
||||
|
||||
current.location = where(HERO, DIRECT);
|
||||
para();
|
||||
while (!g_vm->shouldQuit()) {
|
||||
col = 1;
|
||||
CALL0(g_io->statusLine)
|
||||
printMessage(M_QUITACTION);
|
||||
|
||||
FUNC2(g_io->readLine, flag, buf, 80)
|
||||
if (!flag)
|
||||
CALL1(terminate, 0)
|
||||
|
||||
if (scumm_stricmp(buf, "restart") == 0) {
|
||||
LONG_JUMP_LABEL("restart")
|
||||
|
||||
} else if (scumm_stricmp(buf, "restore") == 0) {
|
||||
g_vm->loadGame();
|
||||
return;
|
||||
|
||||
} else if (scumm_stricmp(buf, "quit") == 0) {
|
||||
CALL1(terminate, 0)
|
||||
|
||||
} else if (scumm_stricmp(buf, "undo") == 0) {
|
||||
if (gameStateChanged) {
|
||||
rememberCommands();
|
||||
rememberGameState();
|
||||
CALL0(undo)
|
||||
} else {
|
||||
if (anySavedState()) {
|
||||
recallGameState();
|
||||
sayUndoneCommand(playerWordsAsCommandString());
|
||||
} else {
|
||||
printMessage(M_NO_UNDO);
|
||||
}
|
||||
|
||||
LONG_JUMP_LABEL("returnUndo")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syserr("Fallthrough in QUIT");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void restartGame(CONTEXT) {
|
||||
Aint previousLocation = current.location;
|
||||
current.location = where(HERO, DIRECT);
|
||||
para();
|
||||
|
||||
bool flag;
|
||||
FUNC1(confirm, flag, M_REALLY)
|
||||
if (flag) {
|
||||
LONG_JUMP_LABEL("restart")
|
||||
}
|
||||
|
||||
current.location = previousLocation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void cancelEvent(Aword theEvent) {
|
||||
int i;
|
||||
|
||||
for (i = eventQueueTop - 1; i >= 0; i--)
|
||||
if (eventQueue[i].event == (int)theEvent) {
|
||||
while (i < eventQueueTop - 1) {
|
||||
eventQueue[i].event = eventQueue[i + 1].event;
|
||||
eventQueue[i].after = eventQueue[i + 1].after;
|
||||
eventQueue[i].where = eventQueue[i + 1].where;
|
||||
i++;
|
||||
}
|
||||
eventQueueTop--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void increaseEventQueue(void) {
|
||||
eventQueue = (EventQueueEntry *)realloc(eventQueue, (eventQueueTop + 2) * sizeof(EventQueueEntry));
|
||||
if (eventQueue == nullptr) syserr("Out of memory in increaseEventQueue()");
|
||||
|
||||
eventQueueSize = eventQueueTop + 2;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void moveEvent(int to, int from) {
|
||||
eventQueue[to].event = eventQueue[from].event;
|
||||
eventQueue[to].after = eventQueue[from].after;
|
||||
eventQueue[to].where = eventQueue[from].where;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void schedule(Aword event, Aword where, Aword after) {
|
||||
uint i;
|
||||
|
||||
if (event == 0) syserr("NULL event");
|
||||
|
||||
cancelEvent(event);
|
||||
/* Check for overflow */
|
||||
if (eventQueue == nullptr || eventQueueTop == eventQueueSize) {
|
||||
increaseEventQueue();
|
||||
assert(eventQueue);
|
||||
}
|
||||
|
||||
/* Bubble this event down */
|
||||
for (i = eventQueueTop; i >= 1 && eventQueue[i - 1].after <= (int)after; i--) {
|
||||
moveEvent(i, i - 1);
|
||||
}
|
||||
|
||||
eventQueue[i].after = after;
|
||||
eventQueue[i].where = where;
|
||||
eventQueue[i].event = event;
|
||||
eventQueueTop++;
|
||||
}
|
||||
|
||||
|
||||
// TODO Move to string.c?
|
||||
/*======================================================================*/
|
||||
Aptr concat(Aptr as1, Aptr as2) {
|
||||
char *s1 = (char *)fromAptr(as1);
|
||||
char *s2 = (char *)fromAptr(as2);
|
||||
size_t ln = strlen(s1) + strlen(s2) + 1;
|
||||
char *result = (char *)allocate(ln);
|
||||
Common::strcpy_s(result, ln, s1);
|
||||
Common::strcat_s(result, ln, s2);
|
||||
return toAptr(result);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *stripCharsFromStringForwards(int count, char *initialString, char **theRest) {
|
||||
int stripPosition;
|
||||
char *strippedString;
|
||||
char *rest;
|
||||
|
||||
if (count > (int)strlen(initialString))
|
||||
stripPosition = strlen(initialString);
|
||||
else
|
||||
stripPosition = count;
|
||||
rest = scumm_strdup(&initialString[stripPosition]);
|
||||
strippedString = scumm_strdup(initialString);
|
||||
strippedString[stripPosition] = '\0';
|
||||
*theRest = rest;
|
||||
return strippedString;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *stripCharsFromStringBackwards(Aint count, char *initialString, char **theRest) {
|
||||
int stripPosition;
|
||||
char *strippedString;
|
||||
char *rest;
|
||||
|
||||
if (count > (int)strlen(initialString))
|
||||
stripPosition = 0;
|
||||
else
|
||||
stripPosition = strlen(initialString) - count;
|
||||
strippedString = scumm_strdup(&initialString[stripPosition]);
|
||||
rest = scumm_strdup(initialString);
|
||||
rest[stripPosition] = '\0';
|
||||
*theRest = rest;
|
||||
return strippedString;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int countLeadingBlanks(char *string, int position) {
|
||||
static char blanks[] = " ";
|
||||
return strspn(&string[position], blanks);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int skipWordForwards(char *string, int position) {
|
||||
char separators[] = " .,?";
|
||||
|
||||
uint i;
|
||||
|
||||
for (i = position; i <= strlen(string) && strchr(separators, string[i]) == nullptr; i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *stripWordsFromStringForwards(Aint count, char *initialString, char **theRest) {
|
||||
int skippedChars;
|
||||
int position = 0;
|
||||
char *stripped;
|
||||
int i;
|
||||
|
||||
for (i = count; i > 0; i--) {
|
||||
/* Ignore any initial blanks */
|
||||
skippedChars = countLeadingBlanks(initialString, position);
|
||||
position += skippedChars;
|
||||
position = skipWordForwards(initialString, position);
|
||||
}
|
||||
|
||||
stripped = (char *)allocate(position + 1);
|
||||
strncpy(stripped, initialString, position);
|
||||
stripped[position] = '\0';
|
||||
|
||||
skippedChars = countLeadingBlanks(initialString, position);
|
||||
*theRest = scumm_strdup(&initialString[position + skippedChars]);
|
||||
|
||||
return (stripped);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int skipWordBackwards(char *string, int position) {
|
||||
char separators[] = " .,?";
|
||||
int i;
|
||||
|
||||
for (i = position; i > 0 && strchr(separators, string[i - 1]) == nullptr; i--)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int countTrailingBlanks(char *string, int position) {
|
||||
int skippedChars, i;
|
||||
skippedChars = 0;
|
||||
|
||||
if (position > (int)strlen(string) - 1)
|
||||
syserr("position > length in countTrailingBlanks");
|
||||
for (i = position; i >= 0 && string[i] == ' '; i--)
|
||||
skippedChars++;
|
||||
return (skippedChars);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *stripWordsFromStringBackwards(Aint count, char *initialString, char **theRest) {
|
||||
int skippedChars;
|
||||
char *stripped;
|
||||
int strippedLength;
|
||||
int position = strlen(initialString);
|
||||
int i;
|
||||
|
||||
for (i = count; i > 0 && position > 0; i--) {
|
||||
position -= 1;
|
||||
/* Ignore trailing blanks */
|
||||
skippedChars = countTrailingBlanks(initialString, position);
|
||||
if (position - skippedChars < 0) break; /* No more words to strip */
|
||||
position -= skippedChars;
|
||||
position = skipWordBackwards(initialString, position);
|
||||
}
|
||||
|
||||
skippedChars = countLeadingBlanks(initialString, 0);
|
||||
strippedLength = strlen(initialString) - position - skippedChars;
|
||||
stripped = (char *)allocate(strippedLength + 1);
|
||||
strncpy(stripped, &initialString[position + skippedChars], strippedLength);
|
||||
stripped[strippedLength] = '\0';
|
||||
|
||||
if (position > 0) {
|
||||
skippedChars = countTrailingBlanks(initialString, position - 1);
|
||||
position -= skippedChars;
|
||||
}
|
||||
*theRest = scumm_strdup(initialString);
|
||||
(*theRest)[position] = '\0';
|
||||
return (stripped);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Aptr strip(bool stripFromBeginningNotEnd, int count, bool stripWordsNotChars, int id, int atr) {
|
||||
char *initialString = (char *)fromAptr(getInstanceAttribute(id, atr));
|
||||
char *theStripped;
|
||||
char *theRest;
|
||||
|
||||
if (stripFromBeginningNotEnd) {
|
||||
if (stripWordsNotChars)
|
||||
theStripped = stripWordsFromStringForwards(count, initialString, &theRest);
|
||||
else
|
||||
theStripped = stripCharsFromStringForwards(count, initialString, &theRest);
|
||||
} else {
|
||||
if (stripWordsNotChars)
|
||||
theStripped = stripWordsFromStringBackwards(count, initialString, &theRest);
|
||||
else
|
||||
theStripped = stripCharsFromStringBackwards(count, initialString, &theRest);
|
||||
}
|
||||
setInstanceStringAttribute(id, atr, theRest);
|
||||
return toAptr(theStripped);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int getContainerMember(int container, int index, bool directly) {
|
||||
uint i;
|
||||
Aint count = 0;
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++) {
|
||||
if (isIn(i, container, DIRECT)) {
|
||||
count++;
|
||||
if (count == index)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
apperr("Index not in container in 'containerMember()'");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************\
|
||||
|
||||
Description Handling
|
||||
|
||||
\***********************************************************************/
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void empty(CONTEXT, int cnt, int whr) {
|
||||
uint i;
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++)
|
||||
if (isIn(i, cnt, DIRECT))
|
||||
CALL2(locate, i, whr)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void use(CONTEXT, int actor, int script) {
|
||||
char str[80];
|
||||
StepEntry *step;
|
||||
|
||||
if (!isAActor(actor)) {
|
||||
Common::sprintf_s(str, "Instance is not an Actor (%d).", actor);
|
||||
syserr(str);
|
||||
}
|
||||
|
||||
admin[actor].script = script;
|
||||
admin[actor].step = 0;
|
||||
step = stepOf(actor);
|
||||
if (step != nullptr && step->after != 0) {
|
||||
FUNC1(evaluate, admin[actor].waitCount, step->after)
|
||||
}
|
||||
|
||||
gameStateChanged = TRUE;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void stop(int act) {
|
||||
char str[80];
|
||||
|
||||
if (!isAActor(act)) {
|
||||
Common::sprintf_s(str, "Instance is not an Actor (%d).", act);
|
||||
syserr(str);
|
||||
}
|
||||
|
||||
admin[act].script = 0;
|
||||
admin[act].step = 0;
|
||||
|
||||
gameStateChanged = TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int randomValue = 0;
|
||||
/*----------------------------------------------------------------------*/
|
||||
int randomInteger(int from, int to) {
|
||||
if (regressionTestOption) {
|
||||
int ret = from + randomValue;
|
||||
/* Generate them in sequence */
|
||||
if (ret > to) {
|
||||
ret = from;
|
||||
randomValue = 1;
|
||||
} else if (ret == to)
|
||||
randomValue = 0;
|
||||
else
|
||||
randomValue++;
|
||||
return ret;
|
||||
} else {
|
||||
if (to == from)
|
||||
return to;
|
||||
else if (to > from)
|
||||
return (g_vm->getRandomNumber(0x7fffffff) / 10) % (to - from + 1) + from;
|
||||
else
|
||||
return (g_vm->getRandomNumber(0x7fffffff) / 10) % (from - to + 1) + to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
bool between(int val, int low, int high) {
|
||||
if (high > low)
|
||||
return low <= val && val <= high;
|
||||
else
|
||||
return high <= val && val <= low;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool contains(Aptr string, Aptr substring) {
|
||||
bool found;
|
||||
|
||||
strlow((char *)fromAptr(string));
|
||||
strlow((char *)fromAptr(substring));
|
||||
|
||||
found = (strstr((char *)fromAptr(string), (char *)fromAptr(substring)) != nullptr);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool streq(char a[], char b[]) {
|
||||
bool eq;
|
||||
|
||||
strlow(a);
|
||||
strlow(b);
|
||||
|
||||
eq = (strcmp(a, b) == 0);
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void startTranscript(void) {
|
||||
if (logFile == nullptr) {
|
||||
Common::String filename = g_vm->getTargetName() + ".log";
|
||||
|
||||
uint fileUsage = transcriptOption ? fileusage_Transcript : fileusage_InputRecord;
|
||||
frefid_t logFileRef = g_vm->glk_fileref_create_by_name(fileUsage, filename.c_str(), 0);
|
||||
logFile = g_vm->glk_stream_open_file(logFileRef, filemode_Write, 0);
|
||||
|
||||
if (logFile == nullptr) {
|
||||
transcriptOption = FALSE;
|
||||
logOption = FALSE;
|
||||
} else {
|
||||
transcriptOption = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void stopTranscript(void) {
|
||||
if (logFile != nullptr) {
|
||||
if (transcriptOption || logOption)
|
||||
delete logFile;
|
||||
|
||||
logFile = nullptr;
|
||||
transcriptOption = FALSE;
|
||||
logOption = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
89
engines/glk/alan3/exe.h
Normal file
89
engines/glk/alan3/exe.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* 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_ALAN3_EXE
|
||||
#define GLK_ALAN3_EXE
|
||||
|
||||
/* Header file for instruction execution unit in Alan interpreter */
|
||||
|
||||
/* IMPORTS */
|
||||
#include "glk/alan3/sysdep.h"
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/set.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* CONSTANTS */
|
||||
#define NO_JUMP_RETURN 0
|
||||
#define ERROR_RETURN 1
|
||||
#define UNDO_RETURN 2
|
||||
|
||||
|
||||
/* DATA */
|
||||
|
||||
extern Common::SeekableReadStream *textFile; // The text and message file
|
||||
extern bool printFlag;
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void sys(Aword fpos, Aword len);
|
||||
extern void sayInteger(int val);
|
||||
extern void sayString(char *str);
|
||||
extern Aptr strip(bool stripFromBeginningNotEnd, int count, bool stripWordsNotChars, int id, int atr);
|
||||
extern Aptr concat(Aptr s1, Aptr s2);
|
||||
extern char *getStringFromFile(Aword fpos, Aword len);
|
||||
extern void print(Aword fpos, Aword len);
|
||||
extern void score(Aword sc);
|
||||
extern void visits(Aword v);
|
||||
extern void undo(CONTEXT);
|
||||
extern void quitGame(CONTEXT);
|
||||
extern void restartGame(CONTEXT);
|
||||
|
||||
extern void use(CONTEXT, int act, int scr);
|
||||
extern void stop(int act);
|
||||
|
||||
extern void empty(CONTEXT, int cnt, int whr);
|
||||
extern int getContainerMember(int container, int index, bool directly);
|
||||
extern int randomInContainer(int cont);
|
||||
|
||||
extern void schedule(Aword evt, Aword whr, Aword aft);
|
||||
extern void cancelEvent(Aword evt);
|
||||
|
||||
extern int randomInteger(int from, int to);
|
||||
extern bool between(int val, int from, int to);
|
||||
extern bool contains(Aptr string, Aptr substring);
|
||||
extern bool streq(char a[], char b[]);
|
||||
|
||||
extern void include(int instance, int atr, Aword member);
|
||||
extern void exclude(int instance, int atr, Aword member);
|
||||
extern void increase(int instance, int atr, Aword step);
|
||||
extern void decrease(int instance, int atr, Aword step);
|
||||
|
||||
extern void startTranscript(void);
|
||||
extern void stopTranscript(void);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
234
engines/glk/alan3/fnmatch.cpp
Normal file
234
engines/glk/alan3/fnmatch.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Guido van Rossum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
|
||||
* Compares a filename or pathname to a pattern.
|
||||
*/
|
||||
#include "glk/alan3/fnmatch.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
#define EOS '\0'
|
||||
|
||||
#define RANGE_MATCH 1
|
||||
#define RANGE_NOMATCH 0
|
||||
#define RANGE_ERROR (-1)
|
||||
|
||||
static int rangematch(const char *, char, int, char **);
|
||||
|
||||
int fnmatch(const char *pattern, const char *string, int flags) {
|
||||
const char *stringstart;
|
||||
char *newp;
|
||||
char c, test;
|
||||
|
||||
for (stringstart = string;;)
|
||||
switch (c = *pattern++) {
|
||||
case EOS:
|
||||
if ((flags & FNM_LEADING_DIR) && *string == '/')
|
||||
return (0);
|
||||
return (*string == EOS ? 0 : FNM_NOMATCH);
|
||||
case '?':
|
||||
if (*string == EOS)
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '/' && (flags & FNM_PATHNAME))
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
++string;
|
||||
break;
|
||||
case '*':
|
||||
c = *pattern;
|
||||
/* Collapse multiple stars. */
|
||||
while (c == '*')
|
||||
c = *++pattern;
|
||||
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
/* Optimize for pattern with * at end or before /. */
|
||||
if (c == EOS)
|
||||
if (flags & FNM_PATHNAME)
|
||||
return ((flags & FNM_LEADING_DIR) ||
|
||||
strchr(string, '/') == nullptr ?
|
||||
0 : FNM_NOMATCH);
|
||||
else
|
||||
return (0);
|
||||
else if (c == '/' && flags & FNM_PATHNAME) {
|
||||
if ((string = strchr(string, '/')) == nullptr)
|
||||
return (FNM_NOMATCH);
|
||||
break;
|
||||
}
|
||||
|
||||
/* General case, use recursion. */
|
||||
while ((test = *string) != EOS) {
|
||||
if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
|
||||
return (0);
|
||||
if (test == '/' && flags & FNM_PATHNAME)
|
||||
break;
|
||||
++string;
|
||||
}
|
||||
return (FNM_NOMATCH);
|
||||
case '[':
|
||||
if (*string == EOS)
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '/' && (flags & FNM_PATHNAME))
|
||||
return (FNM_NOMATCH);
|
||||
if (*string == '.' && (flags & FNM_PERIOD) &&
|
||||
(string == stringstart ||
|
||||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
|
||||
return (FNM_NOMATCH);
|
||||
|
||||
switch (rangematch(pattern, *string, flags, &newp)) {
|
||||
case RANGE_ERROR:
|
||||
goto norm;
|
||||
case RANGE_MATCH:
|
||||
pattern = newp;
|
||||
break;
|
||||
case RANGE_NOMATCH:
|
||||
return (FNM_NOMATCH);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++string;
|
||||
break;
|
||||
case '\\':
|
||||
if (!(flags & FNM_NOESCAPE)) {
|
||||
if ((c = *pattern++) == EOS) {
|
||||
c = '\\';
|
||||
--pattern;
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
norm:
|
||||
if (c == *string)
|
||||
;
|
||||
else if ((flags & FNM_CASEFOLD) &&
|
||||
(tolower((unsigned char)c) ==
|
||||
tolower((unsigned char)*string)))
|
||||
;
|
||||
else
|
||||
return (FNM_NOMATCH);
|
||||
string++;
|
||||
break;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
rangematch(const char *pattern, char test, int flags, char **newp) {
|
||||
int negate, ok;
|
||||
char c, c2;
|
||||
|
||||
/*
|
||||
* A bracket expression starting with an unquoted circumflex
|
||||
* character produces unspecified results (IEEE 1003.2-1992,
|
||||
* 3.13.2). This implementation treats it like '!', for
|
||||
* consistency with the regular expression syntax.
|
||||
* J.T. Conklin (conklin@ngai.kaleida.com)
|
||||
*/
|
||||
if ((negate = (*pattern == '!' || *pattern == '^')))
|
||||
++pattern;
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
test = tolower((unsigned char)test);
|
||||
|
||||
/*
|
||||
* A right bracket shall lose its special meaning and represent
|
||||
* itself in a bracket expression if it occurs first in the list.
|
||||
* -- POSIX.2 2.8.3.2
|
||||
*/
|
||||
ok = 0;
|
||||
c = *pattern++;
|
||||
do {
|
||||
if (c == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c = *pattern++;
|
||||
if (c == EOS)
|
||||
return (RANGE_ERROR);
|
||||
|
||||
if (c == '/' && (flags & FNM_PATHNAME))
|
||||
return (RANGE_NOMATCH);
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
c = tolower((unsigned char)c);
|
||||
|
||||
if (*pattern == '-'
|
||||
&& (c2 = *(pattern + 1)) != EOS && c2 != ']') {
|
||||
pattern += 2;
|
||||
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
|
||||
c2 = *pattern++;
|
||||
if (c2 == EOS)
|
||||
return (RANGE_ERROR);
|
||||
|
||||
if (flags & FNM_CASEFOLD)
|
||||
c2 = tolower((unsigned char)c2);
|
||||
|
||||
if (c <= test && test <= c2)
|
||||
ok = 1;
|
||||
} else if (c == test)
|
||||
ok = 1;
|
||||
} while ((c = *pattern++) != ']');
|
||||
|
||||
*newp = const_cast<char *>(pattern);
|
||||
return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
82
engines/glk/alan3/fnmatch.h
Normal file
82
engines/glk/alan3/fnmatch.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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_ALAN3_FNMATCH
|
||||
#define GLK_ALAN3_FNMATCH
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
|
||||
*/
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
#define FNM_NOMATCH 1 /* Match failed. */
|
||||
#define FNM_NOSYS 2 /* Function not supported (unused). */
|
||||
|
||||
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
|
||||
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
|
||||
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
|
||||
#define FNM_CASEFOLD 0x10 /* Case insensitive search. */
|
||||
#define FNM_IGNORECASE FNM_CASEFOLD
|
||||
#define FNM_FILE_NAME FNM_PATHNAME
|
||||
#endif
|
||||
|
||||
extern int fnmatch(const char *pattern, const char *string, int flags);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
|
||||
237
engines/glk/alan3/glkio.cpp
Normal file
237
engines/glk/alan3/glkio.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/* 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/alan3/glkio.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
GlkIO *g_io;
|
||||
|
||||
GlkIO::GlkIO(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
|
||||
glkMainWin(nullptr), glkStatusWin(nullptr), onStatusLine(false), _saveSlot(-1),
|
||||
_soundChannel(nullptr) {
|
||||
g_io = this;
|
||||
}
|
||||
|
||||
bool GlkIO::initialize() {
|
||||
// first, open a window for error output
|
||||
glkMainWin = glk_window_open(nullptr, 0, 0, wintype_TextBuffer, 0);
|
||||
if (glkMainWin == nullptr)
|
||||
return false;
|
||||
|
||||
glk_stylehint_set(wintype_TextGrid, style_User1, stylehint_ReverseColor, 1);
|
||||
glkStatusWin = glk_window_open(glkMainWin, winmethod_Above |
|
||||
winmethod_Fixed, 1, wintype_TextGrid, 0);
|
||||
glk_set_window(glkMainWin);
|
||||
|
||||
// Check for a save being loaded directly from the launcher
|
||||
_saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlkIO::print(const char *fmt, ...) {
|
||||
// If there's a savegame being loaded from the launcher, ignore any text out
|
||||
if (_saveSlot != -1)
|
||||
return;
|
||||
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
Common::String str = Common::String::vformat(fmt, argp);
|
||||
va_end(argp);
|
||||
|
||||
if (glkMainWin) {
|
||||
glk_put_string(str.c_str());
|
||||
} else {
|
||||
// assume stdio is available in this case only
|
||||
warning("%s", str.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void GlkIO::showImage(int image, int align) {
|
||||
uint ecode;
|
||||
if (_saveSlot != -1)
|
||||
return;
|
||||
|
||||
if ((glk_gestalt(gestalt_Graphics, 0) == 1) &&
|
||||
(glk_gestalt(gestalt_DrawImage, wintype_TextBuffer) == 1)) {
|
||||
glk_window_flow_break(glkMainWin);
|
||||
printf("\n");
|
||||
ecode = glk_image_draw(glkMainWin, image, imagealign_MarginLeft, 0);
|
||||
(void)ecode;
|
||||
}
|
||||
}
|
||||
|
||||
void GlkIO::playSound(int sound) {
|
||||
if (_saveSlot != -1)
|
||||
return;
|
||||
|
||||
#ifdef GLK_MODULE_SOUND
|
||||
if (glk_gestalt(gestalt_Sound, 0) == 1) {
|
||||
if (_soundChannel == nullptr)
|
||||
_soundChannel = glk_schannel_create(0);
|
||||
if (_soundChannel) {
|
||||
glk_schannel_stop(_soundChannel);
|
||||
(void)glk_schannel_play(_soundChannel, sound);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GlkIO::setStyle(int style) {
|
||||
switch (style) {
|
||||
case NORMAL_STYLE:
|
||||
glk_set_style(style_Normal);
|
||||
break;
|
||||
case EMPHASIZED_STYLE:
|
||||
glk_set_style(style_Emphasized);
|
||||
break;
|
||||
case PREFORMATTED_STYLE:
|
||||
glk_set_style(style_Preformatted);
|
||||
break;
|
||||
case ALERT_STYLE:
|
||||
glk_set_style(style_Alert);
|
||||
break;
|
||||
case QUOTE_STYLE:
|
||||
glk_set_style(style_BlockQuote);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GlkIO::statusLine(CONTEXT) {
|
||||
uint glkWidth;
|
||||
char line[100];
|
||||
int pcol = col;
|
||||
|
||||
if (!statusLineOption || _saveSlot != -1 || glkStatusWin == nullptr)
|
||||
return;
|
||||
|
||||
glk_set_window(glkStatusWin);
|
||||
glk_window_clear(glkStatusWin);
|
||||
glk_window_get_size(glkStatusWin, &glkWidth, nullptr);
|
||||
|
||||
onStatusLine = TRUE;
|
||||
col = 1;
|
||||
glk_window_move_cursor(glkStatusWin, 1, 0);
|
||||
CALL1(sayInstance, where(HERO, /*TRUE*/ TRANSITIVE))
|
||||
|
||||
// TODO Add status message1 & 2 as author customizable messages
|
||||
if (header->maximumScore > 0)
|
||||
Common::sprintf_s(line, "Score %d(%d)/%d moves", current.score, (int)header->maximumScore, current.tick);
|
||||
else
|
||||
Common::sprintf_s(line, "%d moves", current.tick);
|
||||
glk_window_move_cursor(glkStatusWin, glkWidth - strlen(line) - 1, 0);
|
||||
glk_put_string(line);
|
||||
needSpace = FALSE;
|
||||
|
||||
col = pcol;
|
||||
onStatusLine = FALSE;
|
||||
|
||||
glk_set_window(glkMainWin);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
readline()
|
||||
|
||||
Read a line from the user, with history and editing
|
||||
|
||||
*/
|
||||
|
||||
/* TODO - length of user buffer should be used */
|
||||
bool GlkIO::readLine(CONTEXT, char *buffer, size_t maxLen) {
|
||||
event_t event;
|
||||
static bool readingCommands = FALSE;
|
||||
static frefid_t commandFileRef;
|
||||
static strid_t commandFile;
|
||||
|
||||
if (_saveSlot != -1) {
|
||||
// Return a "restore" command
|
||||
forcePrint("> ");
|
||||
forcePrint("restore\n");
|
||||
Common::strcpy_s(buffer, maxLen, "restore");
|
||||
|
||||
} else if (readingCommands) {
|
||||
if (glk_get_line_stream(commandFile, buffer, maxLen) == 0) {
|
||||
glk_stream_close(commandFile, nullptr);
|
||||
readingCommands = FALSE;
|
||||
} else {
|
||||
glk_set_style(style_Input);
|
||||
printf(buffer);
|
||||
glk_set_style(style_Normal);
|
||||
}
|
||||
|
||||
} else {
|
||||
glk_request_line_event(glkMainWin, buffer, maxLen, 0);
|
||||
|
||||
do {
|
||||
glk_select(&event);
|
||||
if (shouldQuit())
|
||||
LONG_JUMP0
|
||||
|
||||
switch (event.type) {
|
||||
case evtype_Arrange:
|
||||
R0CALL0(g_io->statusLine)
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (event.type != evtype_LineInput);
|
||||
if (buffer[0] == '@') {
|
||||
buffer[event.val1] = 0;
|
||||
commandFileRef = glk_fileref_create_by_name(fileusage_InputRecord + fileusage_TextMode, &buffer[1], 0);
|
||||
commandFile = glk_stream_open_file(commandFileRef, filemode_Read, 0);
|
||||
if (commandFile != nullptr)
|
||||
if (glk_get_line_stream(commandFile, buffer, maxLen) != 0) {
|
||||
readingCommands = TRUE;
|
||||
glk_set_style(style_Input);
|
||||
printf(buffer);
|
||||
glk_set_style(style_Normal);
|
||||
}
|
||||
} else
|
||||
buffer[event.val1] = 0;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Common::Error GlkIO::loadGame() {
|
||||
if (_saveSlot != -1) {
|
||||
int saveSlot = _saveSlot;
|
||||
_saveSlot = -1;
|
||||
return loadGameState(saveSlot);
|
||||
} else {
|
||||
return GlkAPI::loadGame();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
98
engines/glk/alan3/glkio.h
Normal file
98
engines/glk/alan3/glkio.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/* 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_ALAN3_GLKIO
|
||||
#define GLK_ALAN3_GLKIO
|
||||
|
||||
#include "glk/glk_api.h"
|
||||
#include "glk/windows.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
class GlkIO : public GlkAPI {
|
||||
private:
|
||||
winid_t glkMainWin;
|
||||
winid_t glkStatusWin;
|
||||
schanid_t _soundChannel;
|
||||
int _saveSlot;
|
||||
public:
|
||||
bool onStatusLine;
|
||||
protected:
|
||||
/**
|
||||
* Does initialization
|
||||
*/
|
||||
bool initialize();
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
GlkIO(OSystem *syst, const GlkGameDescription &gameDesc);
|
||||
|
||||
/**
|
||||
* Print a string to the window
|
||||
*/
|
||||
void print(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* Outputs a string to the window, even during startup
|
||||
*/
|
||||
void forcePrint(const char *str) {
|
||||
glk_put_string(str);
|
||||
}
|
||||
|
||||
void showImage(int image, int align);
|
||||
|
||||
void playSound(int sound);
|
||||
|
||||
void setStyle(int style);
|
||||
|
||||
void statusLine(CONTEXT);
|
||||
|
||||
bool readLine(CONTEXT, char *usrBuf, size_t maxLen);
|
||||
|
||||
void clear() {
|
||||
glk_window_clear(glkMainWin);
|
||||
}
|
||||
|
||||
void flowBreak() {
|
||||
/* Make a new paragraph, i.e one empty line (one or two newlines). */
|
||||
if (_saveSlot == -1 && glk_gestalt(gestalt_Graphics, 0) == 1)
|
||||
glk_window_flow_break(glkMainWin);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a savegame was selected to be loaded from the launcher, then load it.
|
||||
* Otherwise, prompt the user for a savegame to load, and then load it
|
||||
*/
|
||||
Common::Error loadGame();
|
||||
};
|
||||
|
||||
extern GlkIO *g_io;
|
||||
|
||||
#undef printf
|
||||
#define printf g_io->print
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
1174
engines/glk/alan3/instance.cpp
Normal file
1174
engines/glk/alan3/instance.cpp
Normal file
File diff suppressed because it is too large
Load Diff
103
engines/glk/alan3/instance.h
Normal file
103
engines/glk/alan3/instance.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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_ALAN3_INSTANCE
|
||||
#define GLK_ALAN3_INSTANCE
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/set.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Types: */
|
||||
struct AdminEntry { /* Administrative data about instances */
|
||||
Aint location;
|
||||
AttributeEntry *attributes;
|
||||
Abool alreadyDescribed;
|
||||
Aint visitsCount;
|
||||
Aint script;
|
||||
Aint step;
|
||||
Aint waitCount;
|
||||
|
||||
/**
|
||||
* Save/Restore data
|
||||
*/
|
||||
void synchronize(Common::Serializer &s);
|
||||
};
|
||||
|
||||
|
||||
/* Data: */
|
||||
extern InstanceEntry *instances; /* Instance table pointer */
|
||||
|
||||
extern AdminEntry *admin; /* Administrative data about instances */
|
||||
extern AttributeEntry *attributes; /* Dynamic attribute values */
|
||||
|
||||
|
||||
/* Functions: */
|
||||
extern bool isA(int instance, int ancestor);
|
||||
extern bool isAObject(int instance);
|
||||
extern bool isAContainer(int instance);
|
||||
extern bool isAActor(int instance);
|
||||
extern bool isALocation(int instance);
|
||||
extern bool isLiteral(int instance);
|
||||
extern bool isANumeric(int instance);
|
||||
extern bool isAString(int instance);
|
||||
|
||||
extern Aptr getInstanceAttribute(int instance, int attribute);
|
||||
extern char *getInstanceStringAttribute(int instane, int attribute);
|
||||
extern Set *getInstanceSetAttribute(int instance, int attribute);
|
||||
|
||||
extern void setInstanceAttribute(int instance, int atr, Aptr value);
|
||||
extern void setInstanceStringAttribute(int instance, int attribute, char *string);
|
||||
extern void setInstanceSetAttribute(int instance, int atr, Aptr set);
|
||||
|
||||
extern void say(CONTEXT, int instance);
|
||||
extern void sayForm(CONTEXT, int instance, SayForm form);
|
||||
extern void sayInstance(CONTEXT, int instance);
|
||||
|
||||
extern bool hasDescription(int instance);
|
||||
extern bool isDescribable(int instance);
|
||||
extern void describeAnything(CONTEXT, int instance);
|
||||
extern void describeInstances(CONTEXT);
|
||||
extern bool describe(CONTEXT, int instance);
|
||||
|
||||
extern int where(int instance, ATrans trans);
|
||||
extern int positionOf(int instance);
|
||||
extern int locationOf(int instance);
|
||||
|
||||
extern bool isAt(int instance, int other, ATrans trans);
|
||||
extern bool isIn(int instance, int theContainer, ATrans trans);
|
||||
extern bool isHere(int instance, ATrans trans);
|
||||
extern bool isNearby(int instance, ATrans trans);
|
||||
extern bool isNear(int instance, int other, ATrans trans);
|
||||
|
||||
extern bool isOpaque(int container);
|
||||
|
||||
extern void locate(CONTEXT, int instance, int whr);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
1431
engines/glk/alan3/inter.cpp
Normal file
1431
engines/glk/alan3/inter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
54
engines/glk/alan3/inter.h
Normal file
54
engines/glk/alan3/inter.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_ALAN3_INTER
|
||||
#define GLK_ALAN3_INTER
|
||||
|
||||
/* The interpreter of Acode */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/stack.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA: */
|
||||
|
||||
extern bool stopAtNextLine;
|
||||
extern int currentLine;
|
||||
extern int recursionDepth;
|
||||
|
||||
/* Global failure flag */
|
||||
extern bool fail;
|
||||
|
||||
|
||||
/* FUNCTIONS: */
|
||||
|
||||
extern void setInterpreterMock(void (*mock)(Aaddr adr));
|
||||
extern void setInterpreterStack(Stack stack);
|
||||
extern void interpret(CONTEXT, Aaddr adr);
|
||||
extern Aword evaluate(CONTEXT, Aaddr adr);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
62
engines/glk/alan3/lists.cpp
Normal file
62
engines/glk/alan3/lists.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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/alan3/lists.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
void initArray(void *array) {
|
||||
implementationOfSetEndOfArray((Aword *)array);
|
||||
}
|
||||
|
||||
/* How to know we are at end of a table or array, first Aword == EOD */
|
||||
void implementationOfSetEndOfArray(Aword *adr) {
|
||||
*adr = EOD;
|
||||
}
|
||||
|
||||
|
||||
bool implementationOfIsEndOfList(Aword *adr) {
|
||||
return *adr == EOD;
|
||||
}
|
||||
|
||||
int lengthOfArrayImplementation(void *array_of_any_type, int element_size_in_bytes) {
|
||||
int length;
|
||||
int element_size = element_size_in_bytes / sizeof(Aword);
|
||||
Aword *array = (Aword *)array_of_any_type;
|
||||
if (array == nullptr)
|
||||
syserr("Taking length of NULL array");
|
||||
for (length = 0; !isEndOfArray(&array[length * element_size]); length++)
|
||||
;
|
||||
return length;
|
||||
}
|
||||
|
||||
void addElementImplementation(void *array_of_any_type, void *element, int element_size_in_bytes) {
|
||||
Aword *array = (Aword *)array_of_any_type;
|
||||
int length = lengthOfArray(array);
|
||||
int element_size_in_words = element_size_in_bytes / sizeof(Aword);
|
||||
memcpy(&array[length * element_size_in_words], element, element_size_in_bytes);
|
||||
setEndOfArray(&array[(length + 1)*element_size_in_words]);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
49
engines/glk/alan3/lists.h
Normal file
49
engines/glk/alan3/lists.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_ALAN3_LISTS
|
||||
#define GLK_ALAN3_LISTS
|
||||
|
||||
/* Various utility functions for handling lists and arrays */
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern void initArray(void *array);
|
||||
|
||||
#define isEndOfArray(x) implementationOfIsEndOfList((Aword *) (x))
|
||||
extern bool implementationOfIsEndOfList(Aword *adr);
|
||||
|
||||
#define setEndOfArray(x) implementationOfSetEndOfArray((Aword *) (x))
|
||||
extern void implementationOfSetEndOfArray(Aword *adr);
|
||||
|
||||
#define lengthOfArray(array) lengthOfArrayImplementation((array), sizeof(*(array)))
|
||||
extern int lengthOfArrayImplementation(void *array, int element_size_in_bytes);
|
||||
|
||||
#define addElement(array, element) addElementImplementation((array), (&element), sizeof(element))
|
||||
extern void addElementImplementation(void *array_of_any_type, void *element_of_any_size, int element_size_in_bytes);
|
||||
#endif
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
80
engines/glk/alan3/literal.cpp
Normal file
80
engines/glk/alan3/literal.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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/alan3/literal.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
int litCount = 0;
|
||||
static LiteralEntry literalTable[100];
|
||||
LiteralEntry *literals = literalTable;
|
||||
|
||||
|
||||
/* PRIVATE TYPES & DATA */
|
||||
|
||||
|
||||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
/*======================================================================*/
|
||||
int instanceFromLiteral(int literalIndex) {
|
||||
return literalIndex + header->instanceMax;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
void createIntegerLiteral(int integerValue) {
|
||||
litCount++;
|
||||
literals[litCount]._class = header->integerClassId;
|
||||
literals[litCount].type = NUMERIC_LITERAL;
|
||||
literals[litCount].value = integerValue;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
void createStringLiteral(char *unquotedString) {
|
||||
litCount++;
|
||||
literals[litCount]._class = header->stringClassId;
|
||||
literals[litCount].type = STRING_LITERAL;
|
||||
literals[litCount].value = toAptr(scumm_strdup(unquotedString));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
void freeLiterals() {
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= litCount; i++)
|
||||
if (literals[i].type == STRING_LITERAL && literals[i].value != 0) {
|
||||
deallocate((void *)fromAptr(literals[i].value));
|
||||
}
|
||||
litCount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int literalFromInstance(int instance) {
|
||||
return instance - header->instanceMax;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
57
engines/glk/alan3/literal.h
Normal file
57
engines/glk/alan3/literal.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_ALAN3_LITERAL
|
||||
#define GLK_ALAN3_LITERAL
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* TYPES */
|
||||
enum LiteralType {
|
||||
NO_LITERAL, NUMERIC_LITERAL, STRING_LITERAL
|
||||
};
|
||||
|
||||
struct LiteralEntry { /* LITERAL */
|
||||
Aint _class; /* Class id of the literal type */
|
||||
LiteralType type;
|
||||
Aptr value;
|
||||
};
|
||||
|
||||
|
||||
/* DATA */
|
||||
extern int litCount;
|
||||
extern LiteralEntry *literals;
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void createIntegerLiteral(int integerValue);
|
||||
extern void createStringLiteral(char *unquotedString);
|
||||
extern void freeLiterals(void);
|
||||
extern int literalFromInstance(int instance);
|
||||
extern int instanceFromLiteral(int literal);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
131
engines/glk/alan3/location.cpp
Normal file
131
engines/glk/alan3/location.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/* 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/alan3/location.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/word.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/checkentry.h"
|
||||
#include "glk/alan3/debug.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/dictionary.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/current.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceExit(CONTEXT, int location, int dir, const char *what) {
|
||||
printf("\n<EXIT %s[%d] from ",
|
||||
(char *)pointerTo(dictionary[playerWords[currentWordIndex - 1].code].string), dir);
|
||||
CALL1(traceSay, location)
|
||||
printf("[%d], %s:>\n", location, what);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void go(CONTEXT, int location, int dir) {
|
||||
ExitEntry *theExit;
|
||||
bool ok;
|
||||
Aword oldloc;
|
||||
|
||||
theExit = (ExitEntry *) pointerTo(instances[location].exits);
|
||||
if (instances[location].exits != 0) {
|
||||
while (!isEndOfArray(theExit)) {
|
||||
if (theExit->code == (uint)dir) {
|
||||
ok = TRUE;
|
||||
if (theExit->checks != 0) {
|
||||
if (traceSectionOption)
|
||||
CALL3(traceExit, location, dir, "Checking")
|
||||
|
||||
FUNC2(checksFailed, ok, theExit->checks, EXECUTE_CHECK_BODY_ON_FAIL)
|
||||
ok = !ok;
|
||||
}
|
||||
if (ok) {
|
||||
oldloc = location;
|
||||
if (theExit->action != 0) {
|
||||
if (traceSectionOption)
|
||||
CALL3(traceExit, location, dir, "Executing")
|
||||
CALL1(interpret, theExit->action)
|
||||
}
|
||||
/* Still at the same place? */
|
||||
if (where(HERO, TRANSITIVE) == (int)oldloc) {
|
||||
if (traceSectionOption)
|
||||
CALL3(traceExit, location, dir, "Moving")
|
||||
CALL2(locate, HERO, theExit->target)
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
CALL1(error, NO_MSG)
|
||||
}
|
||||
}
|
||||
theExit++;
|
||||
}
|
||||
}
|
||||
|
||||
CALL1(error, M_NO_WAY)
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool exitto(int to, int from) {
|
||||
ExitEntry *theExit;
|
||||
|
||||
if (instances[from].exits == 0)
|
||||
return FALSE; /* No exits */
|
||||
|
||||
for (theExit = (ExitEntry *) pointerTo(instances[from].exits); !isEndOfArray(theExit); theExit++)
|
||||
if (theExit->target == (uint)to)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void look(CONTEXT) {
|
||||
uint i;
|
||||
|
||||
/* Set describe flag for all objects and actors */
|
||||
for (i = 1; i <= header->instanceMax; i++)
|
||||
admin[i].alreadyDescribed = FALSE;
|
||||
|
||||
if (anyOutput)
|
||||
para();
|
||||
|
||||
setSubHeaderStyle();
|
||||
CALL1(sayInstance, current.location)
|
||||
setNormalStyle();
|
||||
|
||||
newline();
|
||||
capitalize = TRUE;
|
||||
if (describe(context, current.location) && !context._break)
|
||||
describeInstances(context);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
38
engines/glk/alan3/location.h
Normal file
38
engines/glk/alan3/location.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN3_LOCATION
|
||||
#define GLK_ALAN3_LOCATION
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern bool exitto(int to, int from);
|
||||
extern void go(CONTEXT, int location, int dir);
|
||||
extern void look(CONTEXT);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
833
engines/glk/alan3/main.cpp
Normal file
833
engines/glk/alan3/main.cpp
Normal file
@@ -0,0 +1,833 @@
|
||||
/* 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/alan3/main.h"
|
||||
#include "glk/alan3/alan_version.h"
|
||||
#include "glk/alan3/class.h"
|
||||
#include "glk/alan3/compatibility.h"
|
||||
#include "glk/alan3/container.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/debug.h"
|
||||
#include "glk/alan3/decode.h"
|
||||
#include "glk/alan3/dictionary.h"
|
||||
#include "glk/alan3/event.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/literal.h"
|
||||
#include "glk/alan3/location.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/parse.h"
|
||||
#include "glk/alan3/reverse.h"
|
||||
#include "glk/alan3/rules.h"
|
||||
#include "glk/alan3/scan.h"
|
||||
#include "glk/alan3/score.h"
|
||||
#include "glk/alan3/state.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/syntax.h"
|
||||
#include "glk/alan3/utils.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
|
||||
/* Amachine structures - Static */
|
||||
VerbEntry *vrbs; /* Verb table pointer */
|
||||
|
||||
|
||||
/* PRIVATE DATA */
|
||||
#define STACKSIZE 100
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
*
|
||||
* Event Handling
|
||||
*
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *eventName(int event) {
|
||||
return stringAt(events[event].id);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void runPendingEvents(CONTEXT) {
|
||||
int i;
|
||||
|
||||
resetRules();
|
||||
while (eventQueueTop != 0 && eventQueue[eventQueueTop - 1].after == 0) {
|
||||
eventQueueTop--;
|
||||
if (isALocation(eventQueue[eventQueueTop].where))
|
||||
current.location = eventQueue[eventQueueTop].where;
|
||||
else
|
||||
current.location = where(eventQueue[eventQueueTop].where, TRANSITIVE);
|
||||
if (traceSectionOption) {
|
||||
printf("\n<EVENT %s[%d] (at ", eventName(eventQueue[eventQueueTop].event),
|
||||
eventQueue[eventQueueTop].event);
|
||||
CALL1(traceSay, current.location)
|
||||
printf(" [%d]):>\n", current.location);
|
||||
}
|
||||
CALL1(interpret, events[eventQueue[eventQueueTop].event].code)
|
||||
CALL1(evaluateRules, rules)
|
||||
}
|
||||
|
||||
for (i = 0; i < eventQueueTop; i++)
|
||||
eventQueue[i].after--;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*\
|
||||
|
||||
Main program and initialisation
|
||||
|
||||
\*----------------------------------------------------------------------*/
|
||||
|
||||
Common::SeekableReadStream *codfil;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Calculate where to start calculating the CRC. Is different for
|
||||
different versions. CRC is calculated from pre-beta2 memory start to
|
||||
be compatible. If header size changes this should return beta2
|
||||
header size for later versions.
|
||||
*/
|
||||
static int crcStart(const byte version[4]) {
|
||||
/* Some earlier versions had a shorter header */
|
||||
if (isPreAlpha5(version))
|
||||
return sizeof(Pre3_0alpha5Header) / sizeof(Aword);
|
||||
else if (isPreBeta2(version))
|
||||
return sizeof(Pre3_0beta2Header) / sizeof(Aword);
|
||||
else
|
||||
return sizeof(ACodeHeader) / sizeof(Aword);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void readTemporaryHeader(CONTEXT, ACodeHeader *tmphdr) {
|
||||
codfil->seek(0);
|
||||
if (codfil->read(&tmphdr->tag[0], sizeof(ACodeHeader)) != sizeof(ACodeHeader) ||
|
||||
strncmp((char *)tmphdr, "ALAN", 4) != 0)
|
||||
playererr(context, "Not an Alan game file, does not start with \"ALAN\"");
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
static void reverseMemory() {
|
||||
if (debugOption || traceSectionOption || traceInstructionOption)
|
||||
output("<Hmm, this is a little-endian machine, fixing byte ordering....");
|
||||
reverseACD(); /* Reverse content of the ACD file */
|
||||
if (debugOption || traceSectionOption || traceInstructionOption)
|
||||
output("OK.>$n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void setupHeader(ACodeHeader tmphdr) {
|
||||
if (isPreBeta2(tmphdr.version)) {
|
||||
header = (ACodeHeader *)duplicate(&memory[0], sizeof(ACodeHeader));
|
||||
if (isPreAlpha5(tmphdr.version)) {
|
||||
header->ifids = 0;
|
||||
}
|
||||
header->prompt = 0;
|
||||
} else if (isPreBeta3(tmphdr.version)) {
|
||||
header = (ACodeHeader *)pointerTo(0);
|
||||
} else {
|
||||
header = (ACodeHeader *)pointerTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void loadAndCheckMemory(ACodeHeader tmphdr, Aword crc, char err[]) {
|
||||
int i;
|
||||
/* No memory allocated yet? */
|
||||
if (memory == nullptr) {
|
||||
memory = (Aword *)allocate(tmphdr.size * sizeof(Aword));
|
||||
}
|
||||
|
||||
memTop = tmphdr.size;
|
||||
codfil->seek(0);
|
||||
if (codfil->read(memory, sizeof(Aword) * memTop) != (sizeof(Aword) * memTop))
|
||||
syserr("Could not read all ACD code.");
|
||||
|
||||
/* Calculate checksum */
|
||||
for (i = crcStart(tmphdr.version); i < memTop; i++) {
|
||||
crc += memory[i] & 0xff;
|
||||
crc += (memory[i] >> 8) & 0xff;
|
||||
crc += (memory[i] >> 16) & 0xff;
|
||||
crc += (memory[i] >> 24) & 0xff;
|
||||
}
|
||||
if (crc != tmphdr.acdcrc) {
|
||||
Common::sprintf_s(err, 100, "Checksum error in Acode (.a3c) file (0x%lx instead of 0x%lx).",
|
||||
(unsigned long) crc, (unsigned long) tmphdr.acdcrc);
|
||||
if (!ignoreErrorOption)
|
||||
syserr(err);
|
||||
else {
|
||||
output("<WARNING! $$");
|
||||
output(err);
|
||||
output("$$ Ignored, proceed at your own risk.>$n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static const char *decodeState(int c) {
|
||||
static char state[3] = "\0\0";
|
||||
switch (c) {
|
||||
case 0:
|
||||
return ".";
|
||||
case 'd':
|
||||
return "dev";
|
||||
case 'a':
|
||||
return "alpha";
|
||||
case 'b':
|
||||
return "beta";
|
||||
default:
|
||||
state[0] = header->version[3];
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
char *decodedGameVersion(const byte version[]) {
|
||||
static char str[100];
|
||||
Common::sprintf_s(str, "%d.%d%s%d",
|
||||
(int)version[3],
|
||||
(int)version[2],
|
||||
decodeState(version[0]),
|
||||
(int)version[1]);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void incompatibleDevelopmentVersion(ACodeHeader *hdr) {
|
||||
Common::String msg = Common::String::format("Incompatible version of ACODE program. "
|
||||
"Development versions always require exact match. Game is %ld.%ld%s%ld, interpreter %ld.%ld%s%ld!",
|
||||
(long)(hdr->version[0]),
|
||||
(long)(hdr->version[1]),
|
||||
decodeState(hdr->version[3]),
|
||||
(long)(hdr->version[2]),
|
||||
(long)alan.version.version,
|
||||
(long)alan.version.revision,
|
||||
alan.version.state,
|
||||
(long)alan.version.correction);
|
||||
apperr(msg.c_str());
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void incompatibleVersion(ACodeHeader *hdr) {
|
||||
Common::String msg = Common::String::format("Incompatible version of ACODE program. Game is %ld.%ld, interpreter %ld.%ld.",
|
||||
(long)(hdr->version[0]),
|
||||
(long)(hdr->version[1]),
|
||||
(long)alan.version.version,
|
||||
(long)alan.version.revision);
|
||||
apperr(msg.c_str());
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void alphaRunningLaterGame(char gameState) {
|
||||
output("<WARNING! You are running an alpha interpreter, but the game is generated by a");
|
||||
if (gameState == 'b')
|
||||
output("beta");
|
||||
else
|
||||
output("release");
|
||||
output("state compiler which was released later. This might cause the game to not work fully as intended. Look for an upgraded game file.>\n");
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void nonDevelopmentRunningDevelopmentStateGame(const byte version[]) {
|
||||
char errorMessage[200];
|
||||
char versionString[100];
|
||||
|
||||
Common::strcpy_s(errorMessage, "Games generated by a development state compiler");
|
||||
Common::sprintf_s(versionString, "(this game is v%d.%d.%d%s)", version[0], version[1],
|
||||
version[2], decodeState(version[3]));
|
||||
Common::strcat_s(errorMessage, versionString);
|
||||
Common::strcat_s(errorMessage, "can only be run with a matching interpreter. Look for a game file generated with an alpha, beta or release state compiler.>\n");
|
||||
apperr(errorMessage);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void checkVersion(ACodeHeader *hdr) {
|
||||
/* Strategy for version matching is:
|
||||
1) Development interpreters/games require exact match
|
||||
2) Alpha, Beta and Release interpreters will not run development games
|
||||
3) Alpha interpreters must warn if they run beta or release games
|
||||
4) Beta interpreters may introduce changes which are not alpha compatible,
|
||||
if the change is a strict addition (i.e. if not used will not affect
|
||||
alpha interpreters, example is introduction of a new opcode if it is
|
||||
done at the end of the list)
|
||||
5) Release interpreters should run alpha and beta games without problems
|
||||
|
||||
NOTE that we are working with a non-reversed version string/word here.
|
||||
*/
|
||||
|
||||
char interpreterVersion[4];
|
||||
bool developmentVersion;
|
||||
bool alphaVersion;
|
||||
int compareLength;
|
||||
char gameState = hdr->version[3];
|
||||
|
||||
/* Construct our own version */
|
||||
interpreterVersion[0] = alan.version.version;
|
||||
interpreterVersion[1] = alan.version.revision;
|
||||
interpreterVersion[2] = alan.version.correction;
|
||||
interpreterVersion[3] = alan.version.state[0];
|
||||
|
||||
/* Check version of .ACD file */
|
||||
if (debugOption && !regressionTestOption) {
|
||||
printf("<Version of '%s' is %d.%d%s%d!>\n",
|
||||
g_vm->getFilename().c_str(),
|
||||
(int)hdr->version[0],
|
||||
(int)hdr->version[1],
|
||||
decodeState(hdr->version[3]),
|
||||
(int)hdr->version[2]);
|
||||
newline();
|
||||
}
|
||||
|
||||
/* Development version require exact match, else only 2 digit match */
|
||||
developmentVersion = (strcmp(alan.version.state, "dev") == 0);
|
||||
alphaVersion = (strcmp(alan.version.state, "alpha") == 0);
|
||||
compareLength = (developmentVersion ? 3 : 2);
|
||||
|
||||
if (gameState == 'd' && !developmentVersion)
|
||||
/* Development state game requires development state interpreter... */
|
||||
nonDevelopmentRunningDevelopmentStateGame(hdr->version);
|
||||
else {
|
||||
/* Compatible if version, revision (and correction if dev state) match... */
|
||||
if (memcmp(hdr->version, interpreterVersion, compareLength) != 0) {
|
||||
/* Mismatch! */
|
||||
if (!ignoreErrorOption) {
|
||||
if (developmentVersion)
|
||||
incompatibleDevelopmentVersion(hdr);
|
||||
else
|
||||
incompatibleVersion(hdr);
|
||||
} else
|
||||
output("<WARNING! Incompatible version of ACODE program.>\n");
|
||||
} else if (developmentVersion && gameState != 'd')
|
||||
/* ... unless interpreter is development and game not */
|
||||
incompatibleDevelopmentVersion(hdr);
|
||||
else if (alphaVersion && gameState != 'a') {
|
||||
/* If interpreter is alpha version and the game is later, warn! */
|
||||
alphaRunningLaterGame(gameState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void load(CONTEXT) {
|
||||
ACodeHeader tmphdr;
|
||||
Aword crc = 0;
|
||||
char err[100];
|
||||
|
||||
CALL1(readTemporaryHeader, &tmphdr)
|
||||
checkVersion(&tmphdr);
|
||||
|
||||
/* Allocate and load memory */
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
reverseHdr(&tmphdr);
|
||||
#endif
|
||||
|
||||
if (tmphdr.size <= sizeof(ACodeHeader) / sizeof(Aword))
|
||||
syserr("Malformed game file. Too small.");
|
||||
|
||||
loadAndCheckMemory(tmphdr, crc, err);
|
||||
|
||||
#ifdef SCUMM_LITTLE_ENDIAN
|
||||
reverseMemory();
|
||||
#endif
|
||||
setupHeader(tmphdr);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void checkDebug(CONTEXT) {
|
||||
/* Make sure he can't debug if not allowed! */
|
||||
if (!header->debug) {
|
||||
if (debugOption | traceSectionOption | traceInstructionOption) {
|
||||
printf("<Sorry, '%s' is not compiled for debug! Exiting.>\n", g_vm->getFilename().c_str());
|
||||
CALL1(terminate, 0)
|
||||
}
|
||||
para();
|
||||
debugOption = FALSE;
|
||||
traceSectionOption = FALSE;
|
||||
traceInstructionOption = FALSE;
|
||||
tracePushOption = FALSE;
|
||||
}
|
||||
|
||||
// If debugging, use no randomization
|
||||
if (debugOption || regressionTestOption)
|
||||
g_vm->setRandomNumberSeed(1);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void initStaticData(void) {
|
||||
/* Dictionary */
|
||||
dictionary = (DictionaryEntry *) pointerTo(header->dictionary);
|
||||
/* Find out number of entries in dictionary */
|
||||
for (dictionarySize = 0; !isEndOfArray(&dictionary[dictionarySize]); dictionarySize++);
|
||||
|
||||
/* Scores */
|
||||
|
||||
|
||||
/* All addresses to tables indexed by ids are converted to pointers,
|
||||
then adjusted to point to the (imaginary) element before the
|
||||
actual table so that [0] does not exist. Instead indices goes
|
||||
from 1 and we can use [1]. */
|
||||
|
||||
if (header->instanceTableAddress == 0)
|
||||
syserr("Instance table pointer == 0");
|
||||
instances = (InstanceEntry *) pointerTo(header->instanceTableAddress);
|
||||
instances--; /* Back up one so that first is no. 1 */
|
||||
|
||||
|
||||
if (header->classTableAddress == 0)
|
||||
syserr("Class table pointer == 0");
|
||||
classes = (ClassEntry *) pointerTo(header->classTableAddress);
|
||||
classes--; /* Back up one so that first is no. 1 */
|
||||
|
||||
if (header->containerTableAddress != 0) {
|
||||
containers = (ContainerEntry *) pointerTo(header->containerTableAddress);
|
||||
containers--;
|
||||
}
|
||||
|
||||
if (header->eventTableAddress != 0) {
|
||||
events = (EventEntry *) pointerTo(header->eventTableAddress);
|
||||
events--;
|
||||
}
|
||||
|
||||
/* Scores, if already allocated, copy initial data */
|
||||
if (scores == nullptr)
|
||||
scores = (Aword *)duplicate((Aword *) pointerTo(header->scores), header->scoreCount * sizeof(Aword));
|
||||
else
|
||||
memcpy(scores, pointerTo(header->scores), header->scoreCount * sizeof(Aword));
|
||||
|
||||
if (literals == nullptr)
|
||||
literals = (LiteralEntry *)allocate(sizeof(Aword) * (MAXPARAMS + 1));
|
||||
|
||||
stxs = (SyntaxEntry *) pointerTo(header->syntaxTableAddress);
|
||||
vrbs = (VerbEntry *) pointerTo(header->verbTableAddress);
|
||||
msgs = (MessageEntry *) pointerTo(header->messageTableAddress);
|
||||
initRules(header->ruleTableAddress);
|
||||
|
||||
if (header->pack)
|
||||
freq = (Aword *) pointerTo(header->freq);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void initStrings(void) {
|
||||
StringInitEntry *init;
|
||||
|
||||
for (init = (StringInitEntry *) pointerTo(header->stringInitTable); !isEndOfArray(init); init++)
|
||||
setInstanceAttribute(init->instanceCode, init->attributeCode, toAptr(getStringFromFile(init->fpos, init->len)));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static Aint sizeOfAttributeData(void) {
|
||||
uint i;
|
||||
int size = 0;
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++) {
|
||||
AttributeEntry *attribute = (AttributeEntry *)pointerTo(instances[i].initialAttributes);
|
||||
while (!isEndOfArray(attribute)) {
|
||||
size += AwordSizeOf(AttributeEntry);
|
||||
attribute++;
|
||||
}
|
||||
size += 1; /* For EOD */
|
||||
}
|
||||
|
||||
if (size != header->attributesAreaSize
|
||||
&& (sizeof(AttributeHeaderEntry) == sizeof(AttributeEntry)))
|
||||
syserr("Attribute area size calculated wrong.");
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static AttributeEntry *initializeAttributes(int awordSize) {
|
||||
Aword *attributeArea = (Aword *)allocate(awordSize * sizeof(Aword));
|
||||
Aword *currentAttributeArea = attributeArea;
|
||||
uint i;
|
||||
|
||||
for (i = 1; i <= header->instanceMax; i++) {
|
||||
AttributeHeaderEntry *originalAttribute = (AttributeHeaderEntry *)pointerTo(instances[i].initialAttributes);
|
||||
admin[i].attributes = (AttributeEntry *)currentAttributeArea;
|
||||
while (!isEndOfArray(originalAttribute)) {
|
||||
((AttributeEntry *)currentAttributeArea)->code = originalAttribute->code;
|
||||
((AttributeEntry *)currentAttributeArea)->value = originalAttribute->value;
|
||||
((AttributeEntry *)currentAttributeArea)->id = originalAttribute->id;
|
||||
currentAttributeArea += AwordSizeOf(AttributeEntry);
|
||||
originalAttribute++;
|
||||
}
|
||||
*((Aword *)currentAttributeArea) = EOD;
|
||||
currentAttributeArea += 1;
|
||||
}
|
||||
|
||||
return (AttributeEntry *)attributeArea;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void initDynamicData(void) {
|
||||
uint instanceId;
|
||||
|
||||
/* Allocate for administrative table */
|
||||
admin = (AdminEntry *)allocate((header->instanceMax + 1) * sizeof(AdminEntry));
|
||||
|
||||
/* Create game state copy of attributes */
|
||||
attributes = initializeAttributes(sizeOfAttributeData());
|
||||
|
||||
/* Initialise string & set attributes */
|
||||
initStrings();
|
||||
initSets((SetInitEntry *)pointerTo(header->setInitTable));
|
||||
|
||||
/* Set initial locations */
|
||||
for (instanceId = 1; instanceId <= header->instanceMax; instanceId++)
|
||||
admin[instanceId].location = instances[instanceId].initialLocation;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void runInheritedInitialize(CONTEXT, Aint theClass) {
|
||||
if (theClass == 0) return;
|
||||
CALL1(runInheritedInitialize, classes[theClass].parent)
|
||||
|
||||
if (classes[theClass].initialize)
|
||||
interpret(context, classes[theClass].initialize);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void runInitialize(CONTEXT, Aint theInstance) {
|
||||
CALL1(runInheritedInitialize, instances[theInstance].parent)
|
||||
|
||||
if (instances[theInstance].initialize != 0)
|
||||
interpret(context, instances[theInstance].initialize);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void initializeInstances(CONTEXT) {
|
||||
uint instanceId;
|
||||
|
||||
/* Set initial locations */
|
||||
for (instanceId = 1; instanceId <= header->instanceMax; instanceId++) {
|
||||
current.instance = instanceId;
|
||||
CALL1(runInitialize, instanceId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void start(CONTEXT) {
|
||||
int startloc;
|
||||
|
||||
current.tick = 0;
|
||||
current.location = startloc = where(HERO, TRANSITIVE);
|
||||
current.actor = HERO;
|
||||
current.score = 0;
|
||||
|
||||
CALL0(initializeInstances)
|
||||
|
||||
if (traceSectionOption)
|
||||
printf("\n<START:>\n");
|
||||
CALL1(interpret, header->start)
|
||||
para();
|
||||
|
||||
if (where(HERO, TRANSITIVE) == startloc) {
|
||||
if (traceSectionOption)
|
||||
printf("<CURRENT LOCATION:>");
|
||||
CALL0(look)
|
||||
}
|
||||
|
||||
resetAndEvaluateRules(context, rules, header->version);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void openFiles(void) {
|
||||
/* If logging open log file */
|
||||
if (transcriptOption || logOption) {
|
||||
startTranscript();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void init(CONTEXT) {
|
||||
int i;
|
||||
|
||||
/* Initialise some status */
|
||||
eventQueueTop = 0; /* No pending events */
|
||||
initStaticData();
|
||||
initDynamicData();
|
||||
initParsing();
|
||||
CALL0(checkDebug)
|
||||
|
||||
getPageSize();
|
||||
|
||||
/* Find first conjunction and use that for ',' handling */
|
||||
for (i = 0; i < dictionarySize; i++)
|
||||
if (isConjunction(i)) {
|
||||
conjWord = i;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start the adventure */
|
||||
if (debugOption) {
|
||||
CALL3(debug, FALSE, 0, 0)
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
|
||||
start(context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool traceActor(CONTEXT, int theActor) {
|
||||
if (traceSectionOption) {
|
||||
printf("\n<ACTOR ");
|
||||
R0CALL1(traceSay, theActor)
|
||||
printf("[%d]", theActor);
|
||||
if (current.location != 0) {
|
||||
printf(" (at ");
|
||||
R0CALL1(traceSay, current.location)
|
||||
} else
|
||||
printf(" (nowhere");
|
||||
printf("[%d])", current.location);
|
||||
}
|
||||
return traceSectionOption;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *scriptName(int theActor, int theScript) {
|
||||
ScriptEntry *scriptEntry = (ScriptEntry *)pointerTo(header->scriptTableAddress);
|
||||
|
||||
while (theScript > 1) {
|
||||
scriptEntry++;
|
||||
theScript--;
|
||||
}
|
||||
return (char *)pointerTo(scriptEntry->id);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void moveActor(CONTEXT, int theActor) {
|
||||
ScriptEntry *scr;
|
||||
StepEntry *step;
|
||||
Aint previousInstance = current.instance;
|
||||
bool flag;
|
||||
|
||||
if (context._break) {
|
||||
// forfeit setjmp replacement destination
|
||||
assert(context._label == "forfeit");
|
||||
context.clear();
|
||||
current.instance = previousInstance;
|
||||
return;
|
||||
}
|
||||
|
||||
current.actor = theActor;
|
||||
current.instance = theActor;
|
||||
current.location = where(theActor, TRANSITIVE);
|
||||
|
||||
if (theActor == (int)HERO) {
|
||||
// Ask him!
|
||||
CALL0(parse)
|
||||
capitalize = TRUE;
|
||||
fail = FALSE; // fail only aborts one actor
|
||||
|
||||
} else if (admin[theActor].script != 0) {
|
||||
for (scr = (ScriptEntry *) pointerTo(header->scriptTableAddress); !isEndOfArray(scr); scr++) {
|
||||
if (scr->code == admin[theActor].script) {
|
||||
/* Find correct step in the list by indexing */
|
||||
step = (StepEntry *) pointerTo(scr->steps);
|
||||
step = (StepEntry *) &step[admin[theActor].step];
|
||||
/* Now execute it, maybe. First check wait count */
|
||||
if (admin[theActor].waitCount > 0) { /* Wait some more ? */
|
||||
FUNC1(traceActor, flag, theActor)
|
||||
if (flag)
|
||||
printf(", SCRIPT %s[%ld], STEP %ld, Waiting another %ld turns>\n",
|
||||
scriptName(theActor, admin[theActor].script),
|
||||
(long)admin[theActor].script, (long)admin[theActor].step + 1,
|
||||
(long)admin[theActor].waitCount);
|
||||
|
||||
admin[theActor].waitCount--;
|
||||
break;
|
||||
}
|
||||
/* Then check possible expression to wait for */
|
||||
if (step->exp != 0) {
|
||||
FUNC1(traceActor, flag, theActor)
|
||||
if (flag)
|
||||
printf(", SCRIPT %s[%ld], STEP %ld, Evaluating:>\n",
|
||||
scriptName(theActor, admin[theActor].script),
|
||||
(long)admin[theActor].script, (long)admin[theActor].step + 1);
|
||||
FUNC1(evaluate, flag, step->exp)
|
||||
if (!flag)
|
||||
break; /* Break loop, don't execute step*/
|
||||
}
|
||||
/* OK, so finally let him do his thing */
|
||||
admin[theActor].step++; /* Increment step number before executing... */
|
||||
if (!isEndOfArray(step + 1) && (step + 1)->after != 0) {
|
||||
FUNC1(evaluate, admin[theActor].waitCount, (step + 1)->after)
|
||||
}
|
||||
|
||||
FUNC1(traceActor, flag, theActor)
|
||||
if (flag)
|
||||
printf(", SCRIPT %s[%ld], STEP %ld, Executing:>\n",
|
||||
scriptName(theActor, admin[theActor].script),
|
||||
(long)admin[theActor].script,
|
||||
(long)admin[theActor].step);
|
||||
CALL1(interpret, step->stms)
|
||||
step++;
|
||||
/* ... so that we can see if he failed or is USEing another script now */
|
||||
if (fail || (admin[theActor].step != 0 && isEndOfArray(step)))
|
||||
/* No more steps in this script, so stop him */
|
||||
admin[theActor].script = 0;
|
||||
fail = FALSE; /* fail only aborts one actor */
|
||||
break; /* We have executed a script so leave loop */
|
||||
}
|
||||
}
|
||||
if (isEndOfArray(scr))
|
||||
syserr("Unknown actor script.");
|
||||
} else {
|
||||
FUNC1(traceActor, flag, theActor)
|
||||
if (flag) {
|
||||
printf(", Idle>\n");
|
||||
}
|
||||
}
|
||||
|
||||
current.instance = previousInstance;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void run(void) {
|
||||
Stack theStack = nullptr;
|
||||
Context ctx;
|
||||
|
||||
openFiles();
|
||||
load(ctx); // Load program
|
||||
|
||||
do {
|
||||
ctx.clear();
|
||||
if (ctx._break)
|
||||
break;
|
||||
|
||||
if (theStack)
|
||||
deleteStack(theStack);
|
||||
|
||||
theStack = createStack(STACKSIZE);
|
||||
setInterpreterStack(theStack);
|
||||
|
||||
initStateStack();
|
||||
|
||||
// Initialise and start the adventure
|
||||
init(ctx);
|
||||
|
||||
while (!g_vm->shouldQuit()) {
|
||||
if (!(ctx._break && ctx._label == "forfeit")) {
|
||||
if (ctx._break) {
|
||||
assert(ctx._label.hasPrefix("return"));
|
||||
|
||||
if (ctx._label == "returnError") {
|
||||
forgetGameState();
|
||||
forceNewPlayerInput();
|
||||
} else if (ctx._label == "returnUndo") {
|
||||
forceNewPlayerInput();
|
||||
}
|
||||
|
||||
ctx.clear();
|
||||
} else {
|
||||
if (debugOption)
|
||||
debug(ctx, FALSE, 0, 0);
|
||||
|
||||
if (!ctx._break) {
|
||||
if (stackDepth(theStack) != 0)
|
||||
syserr("Stack is not empty in main loop");
|
||||
|
||||
if (!current.meta)
|
||||
runPendingEvents(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
recursionDepth = 0;
|
||||
|
||||
// Move all characters, hero first
|
||||
rememberGameState();
|
||||
current.meta = FALSE;
|
||||
}
|
||||
|
||||
moveActor(ctx, header->theHero);
|
||||
|
||||
if (!ctx._break) {
|
||||
if (gameStateChanged)
|
||||
rememberCommands();
|
||||
else
|
||||
forgetGameState();
|
||||
|
||||
if (!current.meta) {
|
||||
current.tick++;
|
||||
|
||||
// Remove this call? Since Eval is done up there after each event...
|
||||
resetAndEvaluateRules(ctx, rules, header->version);
|
||||
|
||||
if (!ctx._break) {
|
||||
// Then all the other actors...
|
||||
for (uint i = 1; i <= header->instanceMax; i++) {
|
||||
if (i != header->theHero && isAActor(i)) {
|
||||
moveActor(ctx, i);
|
||||
if (ctx._break)
|
||||
break;
|
||||
|
||||
resetAndEvaluateRules(ctx, rules, header->version);
|
||||
if (ctx._break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx._break && ctx._label == "restart")
|
||||
break;
|
||||
}
|
||||
} while (!g_vm->shouldQuit() && ctx._label == "restart");
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
44
engines/glk/alan3/main.h
Normal file
44
engines/glk/alan3/main.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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_ALAN3_MAIN
|
||||
#define GLK_ALAN3_MAIN
|
||||
|
||||
/* Header file for main unit of ARUN Alan System interpreter */
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern Common::SeekableReadStream *codfil;
|
||||
|
||||
extern VerbEntry *vrbs; // Verb table pointer
|
||||
|
||||
extern void run();
|
||||
extern void usage();
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
115
engines/glk/alan3/memory.cpp
Normal file
115
engines/glk/alan3/memory.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/* 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/alan3/memory.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
|
||||
Aword *memory = nullptr;
|
||||
static ACodeHeader dummyHeader; /* Dummy to use until memory allocated */
|
||||
ACodeHeader *header = &dummyHeader;
|
||||
int memTop = 0; /* Top of load memory */
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void *allocate(unsigned long lengthInBytes) {
|
||||
void *p = (void *)calloc((size_t)lengthInBytes, 1);
|
||||
|
||||
if (p == nullptr)
|
||||
syserr("Out of memory.");
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void deallocate(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void *duplicate(void *original, unsigned long len) {
|
||||
void *p = allocate(len + 1);
|
||||
|
||||
memcpy(p, original, len);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
Aptr aptr;
|
||||
void *voidp;
|
||||
} PointerMapEntry;
|
||||
|
||||
static PointerMapEntry *pointerMap = nullptr;
|
||||
static int pointerMapSize = 0;
|
||||
static int nextAptr = 1;
|
||||
|
||||
/*======================================================================*/
|
||||
void resetPointerMap(void) {
|
||||
if (pointerMap != nullptr) free(pointerMap);
|
||||
pointerMap = nullptr;
|
||||
pointerMapSize = 0;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void *fromAptr(Aptr aptr) {
|
||||
int index;
|
||||
|
||||
for (index = 0; index < pointerMapSize && pointerMap[index].aptr != aptr; index++)
|
||||
;
|
||||
|
||||
if (index == pointerMapSize)
|
||||
syserr("No pointerMap entry for Aptr");
|
||||
|
||||
return pointerMap[index].voidp;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Aptr toAptr(void *ptr) {
|
||||
int index;
|
||||
|
||||
if (pointerMap == nullptr) {
|
||||
pointerMap = (PointerMapEntry *)allocate(sizeof(PointerMapEntry));
|
||||
pointerMapSize = 1;
|
||||
}
|
||||
|
||||
for (index = 0; index < pointerMapSize && pointerMap[index].voidp != nullptr; index++)
|
||||
;
|
||||
if (index == pointerMapSize) {
|
||||
pointerMap = (PointerMapEntry *)realloc(pointerMap, (index + 1) * sizeof(PointerMapEntry));
|
||||
pointerMapSize++;
|
||||
}
|
||||
|
||||
pointerMap[index].voidp = ptr;
|
||||
pointerMap[index].aptr = nextAptr++;
|
||||
return pointerMap[index].aptr;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
49
engines/glk/alan3/memory.h
Normal file
49
engines/glk/alan3/memory.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_ALAN3_MEMORY
|
||||
#define GLK_ALAN3_MEMORY
|
||||
|
||||
#include "glk/alan3/sysdep.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern Aword *memory;
|
||||
extern ACodeHeader *header;
|
||||
extern int memTop;
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void *allocate(unsigned long lengthInBytes);
|
||||
extern void *duplicate(void *original, unsigned long len);
|
||||
extern void deallocate(void *ptr);
|
||||
|
||||
extern void resetPointerMap();
|
||||
extern void *fromAptr(Aptr aptr);
|
||||
extern Aptr toAptr(void *ptr);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
103
engines/glk/alan3/msg.cpp
Normal file
103
engines/glk/alan3/msg.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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/alan3/msg.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
MessageEntry *msgs; /* Message table pointer */
|
||||
|
||||
/*======================================================================*/
|
||||
void printMessage(MsgKind msg) { /* IN - message number */
|
||||
Context ctx;
|
||||
interpret(ctx, msgs[msg].stms);
|
||||
}
|
||||
|
||||
|
||||
static void (*errorHandler)(MsgKind msg) = nullptr;
|
||||
|
||||
/*======================================================================*/
|
||||
void setErrorHandler(void (*handler)(MsgKind msg)) { /* IN - The error message number */
|
||||
// N.B. The error handler must not return because the standard handler does not...
|
||||
errorHandler = handler;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void error(CONTEXT, MsgKind msgno) { /* IN - The error message number */
|
||||
if (errorHandler != nullptr)
|
||||
errorHandler(msgno);
|
||||
else {
|
||||
/* Print an error message and longjmp to main loop. */
|
||||
if (msgno != NO_MSG)
|
||||
printMessage(msgno);
|
||||
LONG_JUMP_LABEL("returnError");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void abortPlayerCommand(CONTEXT) {
|
||||
error(context, NO_MSG);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void printMessageWithInstanceParameter(MsgKind message, int instanceId) {
|
||||
ParameterArray parameters = newParameterArray();
|
||||
addParameterForInstance(parameters, instanceId);
|
||||
printMessageWithParameters(message, parameters);
|
||||
freeParameterArray(parameters);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void printMessageUsing2InstanceParameters(MsgKind message, int instance1, int instance2) {
|
||||
ParameterArray parameters = newParameterArray();
|
||||
addParameterForInstance(parameters, instance1);
|
||||
addParameterForInstance(parameters, instance2);
|
||||
printMessageWithParameters(message, parameters);
|
||||
freeParameterArray(parameters);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void printMessageWithParameters(MsgKind msg, Parameter *messageParameters) {
|
||||
Parameter *savedParameters = newParameterArray();
|
||||
Context ctx;
|
||||
|
||||
copyParameterArray(savedParameters, globalParameters);
|
||||
copyParameterArray(globalParameters, messageParameters);
|
||||
|
||||
interpret(ctx, msgs[msg].stms);
|
||||
|
||||
copyParameterArray(globalParameters, savedParameters);
|
||||
freeParameterArray(savedParameters);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
56
engines/glk/alan3/msg.h
Normal file
56
engines/glk/alan3/msg.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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_ALAN3_MSG
|
||||
#define GLK_ALAN3_MSG
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/params.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* TYPES */
|
||||
typedef struct MessageEntry { /* MESSAGE TABLE */
|
||||
Aaddr stms; /* Address to statements*/
|
||||
} MessageEntry;
|
||||
|
||||
|
||||
/* DATA */
|
||||
extern MessageEntry *msgs; /* Message table pointer */
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void setErrorHandler(void (*handler)(MsgKind));
|
||||
extern void abortPlayerCommand(CONTEXT);
|
||||
extern void error(CONTEXT, MsgKind msg);
|
||||
extern bool confirm(CONTEXT, MsgKind msgno);
|
||||
extern void printMessage(MsgKind msg);
|
||||
extern void printMessageWithParameters(MsgKind msg, Parameter *messageParameters);
|
||||
extern void printMessageWithInstanceParameter(MsgKind message, int i);
|
||||
extern void printMessageUsing2InstanceParameters(MsgKind message, int instance1, int instance2);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
39
engines/glk/alan3/options.cpp
Normal file
39
engines/glk/alan3/options.cpp
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
bool verboseOption;
|
||||
bool ignoreErrorOption;
|
||||
bool debugOption;
|
||||
bool traceSectionOption;
|
||||
bool tracePushOption;
|
||||
bool traceStackOption;
|
||||
bool traceSourceOption;
|
||||
bool traceInstructionOption;
|
||||
bool transcriptOption;
|
||||
bool logOption;
|
||||
bool statusLineOption;
|
||||
bool regressionTestOption;
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
46
engines/glk/alan3/options.h
Normal file
46
engines/glk/alan3/options.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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_ALAN3_OPTIONS
|
||||
#define GLK_ALAN3_OPTIONS
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern bool verboseOption;
|
||||
extern bool ignoreErrorOption;
|
||||
extern bool debugOption;
|
||||
extern bool traceSectionOption;
|
||||
extern bool tracePushOption;
|
||||
extern bool traceStackOption;
|
||||
extern bool traceSourceOption;
|
||||
extern bool traceInstructionOption;
|
||||
extern bool transcriptOption;
|
||||
extern bool logOption;
|
||||
extern bool statusLineOption;
|
||||
extern bool regressionTestOption;
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
453
engines/glk/alan3/output.cpp
Normal file
453
engines/glk/alan3/output.cpp
Normal file
@@ -0,0 +1,453 @@
|
||||
/* 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 "common/stream.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/word.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/dictionary.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/sysdep.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
bool anyOutput;
|
||||
bool capitalize;
|
||||
bool needSpace;
|
||||
bool skipSpace;
|
||||
|
||||
/* Screen formatting info */
|
||||
int col, lin;
|
||||
int pageLength, pageWidth;
|
||||
|
||||
/* Logfile */
|
||||
strid_t logFile;
|
||||
|
||||
|
||||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
/*
|
||||
getPageSize()
|
||||
|
||||
Try to get the current page size from the system, else use the ones
|
||||
from the header.
|
||||
|
||||
*/
|
||||
void getPageSize(void) {
|
||||
pageLength = 0;
|
||||
pageWidth = 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int updateColumn(int currentColumn, const char *string) {
|
||||
const char *newlinePosition = strrchr(string, '\n');
|
||||
if (newlinePosition != nullptr)
|
||||
return &string[strlen(string)] - newlinePosition;
|
||||
else
|
||||
return currentColumn + strlen(string);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void setSubHeaderStyle(void) {
|
||||
g_io->glk_set_style(style_Subheader);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void setNormalStyle(void) {
|
||||
g_io->glk_set_style(style_Normal);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void newline(void) {
|
||||
printAndLog("\n");
|
||||
col = 1;
|
||||
needSpace = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void para(void) {
|
||||
g_io->flowBreak();
|
||||
|
||||
if (col != 1)
|
||||
newline();
|
||||
newline();
|
||||
capitalize = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void clear(void) {
|
||||
g_io->clear();
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void capitalizeFirst(Common::String &str) {
|
||||
uint i = 0;
|
||||
|
||||
// Skip over space...
|
||||
while (i < str.size() && isSpace(str[i])) i++;
|
||||
|
||||
if (i < str.size()) {
|
||||
str.setChar(toUpper(str[i]), i);
|
||||
capitalize = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void printAndLog(const char *string) {
|
||||
static int column = 0;
|
||||
char *stringCopy;
|
||||
char *stringPart;
|
||||
|
||||
printf("%s", string);
|
||||
if (!g_io->onStatusLine && transcriptOption) {
|
||||
// TODO Is this assuming only 70-char wide windows for GLK?
|
||||
if ((int)strlen(string) > 70 - column) {
|
||||
stringCopy = scumm_strdup(string); /* Make sure we can write NULLs */
|
||||
stringPart = stringCopy;
|
||||
while ((int)strlen(stringPart) > 70 - column) {
|
||||
int p;
|
||||
for (p = 70 - column; p > 0 && !Common::isSpace((int)stringPart[p]); p--);
|
||||
stringPart[p] = '\0';
|
||||
g_io->glk_put_string_stream(logFile, stringPart);
|
||||
g_io->glk_put_char_stream(logFile, '\n');
|
||||
column = 0;
|
||||
stringPart = &stringPart[p + 1];
|
||||
}
|
||||
g_io->glk_put_string_stream(logFile, stringPart);
|
||||
column = updateColumn(column, stringPart);
|
||||
free(stringCopy);
|
||||
} else {
|
||||
g_io->glk_put_string_stream(logFile, string);
|
||||
column = updateColumn(column, string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void justify(const char *str) {
|
||||
Common::String tempStr(str);
|
||||
|
||||
if (capitalize)
|
||||
capitalizeFirst(tempStr);
|
||||
|
||||
printAndLog(tempStr.c_str());
|
||||
col = col + tempStr.size(); // Update column
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void space(void) {
|
||||
if (skipSpace)
|
||||
skipSpace = FALSE;
|
||||
else {
|
||||
if (needSpace) {
|
||||
printAndLog(" ");
|
||||
col++;
|
||||
}
|
||||
}
|
||||
needSpace = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void sayPlayerWordsForParameter(int p) {
|
||||
int i;
|
||||
|
||||
for (i = globalParameters[p].firstWord; i <= globalParameters[p].lastWord; i++) {
|
||||
justify((char *)pointerTo(dictionary[playerWords[i].code].string));
|
||||
if (i < globalParameters[p].lastWord)
|
||||
justify(" ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void sayParameter(CONTEXT, int p, int form) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= p; i++)
|
||||
if (isEndOfArray(&globalParameters[i]))
|
||||
apperr("Nonexistent parameter referenced.");
|
||||
|
||||
#ifdef ALWAYS_SAY_PARAMETERS_USING_PLAYER_WORDS
|
||||
if (params[p].firstWord != EOD) /* Any words he used? */
|
||||
/* Yes, so use them... */
|
||||
sayPlayerWordsForParameter(p);
|
||||
else
|
||||
CALL2(sayForm(params[p].code, form)
|
||||
#else
|
||||
if (globalParameters[p].useWords) {
|
||||
/* Ambiguous instance referenced, so use the words he used */
|
||||
sayPlayerWordsForParameter(p);
|
||||
} else {
|
||||
CALL2(sayForm, globalParameters[p].instance, (SayForm)form)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
Print an expanded symbolic reference.
|
||||
|
||||
N = newline
|
||||
I = indent on a new line
|
||||
P = new paragraph
|
||||
L = current location name
|
||||
O = current object -> first parameter!
|
||||
<n> = n:th parameter
|
||||
+<n> = definite form of n:th parameter
|
||||
0<n> = indefinite form of n:th parameter
|
||||
!<n> = pronoun for the n:th parameter
|
||||
V = current verb
|
||||
A = current actor
|
||||
T = tabulation
|
||||
$ = no space needed after this, and don't capitalize
|
||||
_ = interpret this as a single dollar, if in doubt or conflict with other symbols
|
||||
|
||||
str - The string starting with '$'
|
||||
*/
|
||||
static char *printSymbol(CONTEXT, char str[]) {
|
||||
int advance = 2;
|
||||
|
||||
if (*str == '\0') printAndLog("$");
|
||||
else switch (toLower(str[1])) {
|
||||
case 'n':
|
||||
newline();
|
||||
needSpace = FALSE;
|
||||
break;
|
||||
case 'i':
|
||||
newline();
|
||||
printAndLog(" ");
|
||||
col = 5;
|
||||
needSpace = FALSE;
|
||||
break;
|
||||
case 'o':
|
||||
space();
|
||||
R0CALL2(sayParameter, 0, 0)
|
||||
needSpace = TRUE; /* We did print something non-white */
|
||||
break;
|
||||
case '+':
|
||||
case '0':
|
||||
case '-':
|
||||
case '!':
|
||||
space();
|
||||
if (Common::isDigit((int)str[2])) {
|
||||
int form;
|
||||
switch (str[1]) {
|
||||
case '+':
|
||||
form = SAY_DEFINITE;
|
||||
break;
|
||||
case '0':
|
||||
form = SAY_INDEFINITE;
|
||||
break;
|
||||
case '-':
|
||||
form = SAY_NEGATIVE;
|
||||
break;
|
||||
case '!':
|
||||
form = SAY_PRONOUN;
|
||||
break;
|
||||
default:
|
||||
form = SAY_SIMPLE;
|
||||
break;
|
||||
}
|
||||
R0CALL2(sayParameter, str[2] - '1', form)
|
||||
needSpace = TRUE;
|
||||
}
|
||||
advance = 3;
|
||||
break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
space();
|
||||
R0CALL2(sayParameter, str[1] - '1', SAY_SIMPLE)
|
||||
needSpace = TRUE; /* We did print something non-white */
|
||||
break;
|
||||
case 'l':
|
||||
space();
|
||||
R0CALL1(say, current.location)
|
||||
needSpace = TRUE; /* We did print something non-white */
|
||||
break;
|
||||
case 'a':
|
||||
space();
|
||||
R0CALL1(say, current.actor)
|
||||
needSpace = TRUE; /* We did print something non-white */
|
||||
break;
|
||||
case 'v':
|
||||
space();
|
||||
justify((const char *)pointerTo(dictionary[verbWord].string));
|
||||
needSpace = TRUE; /* We did print something non-white */
|
||||
break;
|
||||
case 'p':
|
||||
para();
|
||||
needSpace = FALSE;
|
||||
break;
|
||||
case 't': {
|
||||
int i;
|
||||
int spaces = 4 - (col - 1) % 4;
|
||||
|
||||
for (i = 0; i < spaces; i++) printAndLog(" ");
|
||||
col = col + spaces;
|
||||
needSpace = FALSE;
|
||||
break;
|
||||
}
|
||||
case '$':
|
||||
skipSpace = TRUE;
|
||||
capitalize = FALSE;
|
||||
break;
|
||||
case '_':
|
||||
advance = 2;
|
||||
printAndLog("$");
|
||||
break;
|
||||
default:
|
||||
advance = 1;
|
||||
printAndLog("$");
|
||||
break;
|
||||
}
|
||||
|
||||
return &str[advance];
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool inhibitSpace(char *str) {
|
||||
return str[0] != '\0' && str[0] == '$' && str[1] == '$';
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool isSpaceEquivalent(char str[]) {
|
||||
if (str[0] == ' ')
|
||||
return TRUE;
|
||||
else
|
||||
return strncmp(str, "$p", 2) == 0
|
||||
|| strncmp(str, "$n", 2) == 0
|
||||
|| strncmp(str, "$i", 2) == 0
|
||||
|| strncmp(str, "$t", 2) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool punctuationNext(char *str) {
|
||||
const char *punctuation = strchr(".,!?", str[0]);
|
||||
bool end = str[1] == '\0';
|
||||
bool space = isSpaceEquivalent(&str[1]);
|
||||
return (punctuation != nullptr && (end || space));
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char lastCharOf(char *str) {
|
||||
return str[strlen(str) - 1];
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void output(const char *original) {
|
||||
char ch;
|
||||
char *str, *copy;
|
||||
char *symptr;
|
||||
Context ctx;
|
||||
|
||||
copy = scumm_strdup(original);
|
||||
str = copy;
|
||||
|
||||
if (inhibitSpace(str) || punctuationNext(str))
|
||||
needSpace = FALSE;
|
||||
else
|
||||
space(); /* Output space if needed (& not inhibited) */
|
||||
|
||||
/* Output string up to symbol and handle the symbol */
|
||||
while ((symptr = strchr(str, '$')) != (char *) nullptr) {
|
||||
ch = *symptr; /* Terminate before symbol */
|
||||
*symptr = '\0';
|
||||
if (strlen(str) > 0) {
|
||||
skipSpace = FALSE; /* Only let skipSpace through if it is
|
||||
last in the string */
|
||||
if (lastCharOf(str) == ' ') {
|
||||
str[strlen(str) - 1] = '\0'; /* Truncate space character */
|
||||
justify(str); /* Output part before '$' */
|
||||
needSpace = TRUE;
|
||||
} else {
|
||||
justify(str); /* Output part before '$' */
|
||||
needSpace = FALSE;
|
||||
}
|
||||
}
|
||||
*symptr = ch; /* restore '$' */
|
||||
str = printSymbol(ctx, symptr); /* Print the symbolic reference and advance */
|
||||
}
|
||||
|
||||
if (str[0] != 0) {
|
||||
justify(str); /* Output trailing part */
|
||||
skipSpace = FALSE;
|
||||
if (lastCharOf(str) != ' ')
|
||||
needSpace = TRUE;
|
||||
}
|
||||
|
||||
if (needSpace)
|
||||
capitalize = strchr("!?.", str[strlen(str) - 1]) != nullptr;
|
||||
|
||||
anyOutput = TRUE;
|
||||
free(copy);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool confirm(CONTEXT, MsgKind msgno) {
|
||||
char buf[80];
|
||||
bool flag;
|
||||
|
||||
/* This is a bit of a hack since we really want to compare the input,
|
||||
it could be affirmative, but for now any input is NOT! */
|
||||
printMessage(msgno);
|
||||
|
||||
R0FUNC2(g_io->readLine, flag, buf, 80)
|
||||
if (!flag)
|
||||
return TRUE;
|
||||
col = 1;
|
||||
|
||||
return (buf[0] == '\0');
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
56
engines/glk/alan3/output.h
Normal file
56
engines/glk/alan3/output.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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_ALAN3_OUTPUT
|
||||
#define GLK_ALAN3_OUTPUT
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/streams.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern int col, lin; // TODO Move to current.column & current.line?
|
||||
extern int pageLength, pageWidth;
|
||||
|
||||
extern bool anyOutput;
|
||||
extern bool needSpace;
|
||||
extern bool capitalize;
|
||||
extern bool skipSpace;
|
||||
|
||||
/* Log file */
|
||||
extern strid_t logFile;
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void getPageSize();
|
||||
extern void setSubHeaderStyle(void);
|
||||
extern void setNormalStyle(void);
|
||||
extern void newline(void);
|
||||
extern void para(void);
|
||||
extern void clear(void);
|
||||
extern void printAndLog(const char *string);
|
||||
extern void output(const char *string);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
102
engines/glk/alan3/parameter_position.cpp
Normal file
102
engines/glk/alan3/parameter_position.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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/alan3/parameter_position.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*======================================================================*/
|
||||
void deallocateParameterPositions(ParameterPosition *parameterPositions) {
|
||||
int i;
|
||||
for (i = 0; !parameterPositions[i].endOfList; i++) {
|
||||
ParameterPosition *position = ¶meterPositions[i];
|
||||
freeParameterArray(position->parameters);
|
||||
if (position->exceptions)
|
||||
freeParameterArray(position->exceptions);
|
||||
}
|
||||
deallocate(parameterPositions);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void uncheckAllParameterPositions(ParameterPosition parameterPositions[]) {
|
||||
int position;
|
||||
for (position = 0; position < MAXPARAMS; position++) {
|
||||
parameterPositions[position].checked = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void copyParameterPositions(ParameterPosition originalParameterPositions[], ParameterPosition parameterPositions[]) {
|
||||
int i;
|
||||
for (i = 0; !originalParameterPositions[i].endOfList; i++)
|
||||
parameterPositions[i] = originalParameterPositions[i];
|
||||
parameterPositions[i].endOfList = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool equalParameterPositions(ParameterPosition parameterPositions1[], ParameterPosition parameterPositions2[]) {
|
||||
int i;
|
||||
for (i = 0; !parameterPositions1[i].endOfList; i++) {
|
||||
if (parameterPositions2[i].endOfList)
|
||||
return FALSE;
|
||||
if (!equalParameterArrays(parameterPositions1[i].parameters, parameterPositions2[i].parameters))
|
||||
return FALSE;
|
||||
}
|
||||
return parameterPositions2[i].endOfList;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int findMultipleParameterPosition(ParameterPosition parameterPositions[]) {
|
||||
Aint parameterNumber;
|
||||
for (parameterNumber = 0; !parameterPositions[parameterNumber].endOfList; parameterNumber++)
|
||||
if (parameterPositions[parameterNumber].explicitMultiple)
|
||||
return parameterNumber;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void markExplicitMultiple(ParameterPosition parameterPositions[], Parameter parameters[]) {
|
||||
int parameterCount;
|
||||
for (parameterCount = 0; !parameterPositions[parameterCount].endOfList; parameterCount++)
|
||||
if (parameterPositions[parameterCount].explicitMultiple)
|
||||
parameters[parameterCount].instance = 0;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void convertPositionsToParameters(ParameterPosition parameterPositions[], Parameter parameters[]) {
|
||||
ParameterPosition *position = parameterPositions;
|
||||
|
||||
clearParameterArray(parameters);
|
||||
while (!position->endOfList) {
|
||||
addParameterToParameterArray(parameters, &position->parameters[0]);
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
76
engines/glk/alan3/parameter_position.h
Normal file
76
engines/glk/alan3/parameter_position.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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_ALAN3_PARAMETER_POSITION
|
||||
#define GLK_ALAN3_PARAMETER_POSITION
|
||||
|
||||
/* ParameterPosition
|
||||
|
||||
Represents on position in the player input holding a parameter. That
|
||||
position is filled with some words from the player, those words must
|
||||
be disambiguated to one or more instances. There are three cases:
|
||||
|
||||
1) words presuming it would be a single instance (it
|
||||
might actually not be) "the chair"
|
||||
|
||||
2) words indicating explicit mentioning of multiple instances, "the
|
||||
book and the chair"
|
||||
|
||||
3) implicit multiple using "all" or "everything except the blue
|
||||
ball"
|
||||
|
||||
For all those cases the position must be able to deliver the words,
|
||||
possible explicit or implicit multiple, and the resulting set of
|
||||
instances.
|
||||
*/
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/params.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Types: */
|
||||
struct ParameterPosition {
|
||||
bool endOfList;
|
||||
bool explicitMultiple;
|
||||
bool all;
|
||||
bool them;
|
||||
bool checked;
|
||||
Aword flags;
|
||||
Parameter *parameters;
|
||||
Parameter *exceptions;
|
||||
};
|
||||
|
||||
/* Functions: */
|
||||
extern void deallocateParameterPositions(ParameterPosition *parameterPositions);
|
||||
extern void uncheckAllParameterPositions(ParameterPosition parameterPositions[]);
|
||||
extern void copyParameterPositions(ParameterPosition originalParameterPositions[], ParameterPosition parameterPositions[]);
|
||||
extern bool equalParameterPositions(ParameterPosition parameterPositions1[], ParameterPosition parameterPositions2[]);
|
||||
extern int findMultipleParameterPosition(ParameterPosition parameterPositions[]);
|
||||
extern void markExplicitMultiple(ParameterPosition parameterPositions[], Parameter parameters[]);
|
||||
extern void convertPositionsToParameters(ParameterPosition parameterPositions[], Parameter parameters[]);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
323
engines/glk/alan3/params.cpp
Normal file
323
engines/glk/alan3/params.cpp
Normal file
@@ -0,0 +1,323 @@
|
||||
/* 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/alan3/params.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/literal.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
Parameter *globalParameters = nullptr;
|
||||
|
||||
/*======================================================================*/
|
||||
Parameter *newParameter(int id) {
|
||||
Parameter *parameter = NEW(Parameter);
|
||||
parameter->instance = id;
|
||||
parameter->candidates = nullptr;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Parameter *newParameterArray(void) {
|
||||
Parameter *newArray = (Parameter *)allocate((MAXINSTANCE + 1) * sizeof(Parameter));
|
||||
setEndOfArray(newArray);
|
||||
return newArray;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void freeParameterArray(ParameterArray arrayPointer) {
|
||||
Parameter *p;
|
||||
|
||||
for (p = arrayPointer; !isEndOfArray(p); p++)
|
||||
if (p->candidates != nullptr)
|
||||
freeParameterArray(p->candidates);
|
||||
deallocate(arrayPointer);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Parameter *ensureParameterArrayAllocated(ParameterArray currentArray) {
|
||||
if (currentArray == nullptr)
|
||||
return newParameterArray();
|
||||
else {
|
||||
clearParameterArray(currentArray);
|
||||
return currentArray;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool parameterArrayIsEmpty(ParameterArray array) {
|
||||
return array == nullptr || lengthOfParameterArray(array) == 0;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void clearParameter(Parameter *parameter) {
|
||||
Parameter *candidates = parameter->candidates;
|
||||
memset(parameter, 0, sizeof(Parameter));
|
||||
parameter->candidates = candidates;
|
||||
if (parameter->candidates != nullptr)
|
||||
clearParameterArray(parameter->candidates);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void setGlobalParameters(ParameterArray newParameters) {
|
||||
if (globalParameters == nullptr)
|
||||
globalParameters = newParameterArray();
|
||||
copyParameterArray(globalParameters, newParameters);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Parameter *getGlobalParameters(void) {
|
||||
if (globalParameters == nullptr)
|
||||
globalParameters = newParameterArray();
|
||||
return globalParameters;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Parameter *getGlobalParameter(int parameterIndex) {
|
||||
return &globalParameters[parameterIndex];
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Parameter *findEndOfParameterArray(Parameter *parameters) {
|
||||
Parameter *parameter;
|
||||
for (parameter = parameters; !isEndOfArray(parameter); parameter++);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
/* A parameter position with code == 0 means this is a multiple position.
|
||||
* We must loop over this position (and replace it by each present in the
|
||||
* matched list)
|
||||
*/
|
||||
int findMultiplePosition(Parameter parameters[]) {
|
||||
// TODO: this should look at the isAll and isExplicitMultiple flags instead
|
||||
int multiplePosition;
|
||||
for (multiplePosition = 0; !isEndOfArray(¶meters[multiplePosition]); multiplePosition++)
|
||||
if (parameters[multiplePosition].instance == 0)
|
||||
return multiplePosition;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void compressParameterArray(Parameter theArray[]) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; !isEndOfArray(&theArray[j]); j++)
|
||||
if (theArray[j].instance != 0)
|
||||
theArray[i++] = theArray[j];
|
||||
setEndOfArray(&theArray[i]);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int lengthOfParameterArray(Parameter theArray[]) {
|
||||
int i = 0;
|
||||
|
||||
if (theArray == nullptr) return 0;
|
||||
|
||||
while (!isEndOfArray(&theArray[i]))
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool equalParameterArrays(Parameter parameters1[], Parameter parameters2[]) {
|
||||
int i;
|
||||
|
||||
if ((parameters1 == nullptr) != (parameters2 == nullptr))
|
||||
return FALSE;
|
||||
if (parameters1 == nullptr) // Because then parameter2 is also NULL
|
||||
return TRUE;
|
||||
for (i = 0; !isEndOfArray(¶meters1[i]); i++) {
|
||||
if (isEndOfArray(¶meters2[i])) return FALSE;
|
||||
if (parameters1[i].instance != parameters2[i].instance) return FALSE;
|
||||
}
|
||||
return isEndOfArray(¶meters2[i]);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool inParameterArray(Parameter theArray[], Aword theCode) {
|
||||
int i;
|
||||
|
||||
for (i = 0; !isEndOfArray(&theArray[i]) && theArray[i].instance != theCode; i++);
|
||||
return (theArray[i].instance == theCode);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void copyParameter(Parameter *to, Parameter *from) {
|
||||
Parameter *toCandidates = to->candidates;
|
||||
|
||||
*to = *from;
|
||||
if (from->candidates != nullptr) {
|
||||
if (toCandidates == nullptr)
|
||||
to->candidates = newParameterArray();
|
||||
else
|
||||
to->candidates = toCandidates;
|
||||
copyParameterArray(to->candidates, from->candidates);
|
||||
} else if (toCandidates != nullptr)
|
||||
freeParameterArray(toCandidates);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void addParameterToParameterArray(ParameterArray theArray, Parameter *theParameter) {
|
||||
if (theArray == nullptr) syserr("Adding to null parameter array");
|
||||
|
||||
uint i;
|
||||
|
||||
for (i = 0; !isEndOfArray(&theArray[i]) && i < MAXINSTANCE; i++)
|
||||
;
|
||||
if (isEndOfArray(&theArray[i])) {
|
||||
copyParameter(&theArray[i], theParameter);
|
||||
setEndOfArray(&theArray[i + 1]);
|
||||
} else
|
||||
syserr("Couldn't find end of ParameterArray");
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void copyParameterArray(ParameterArray to, ParameterArray from) {
|
||||
int i;
|
||||
|
||||
if (to == nullptr && from == nullptr) return;
|
||||
|
||||
if (to == nullptr)
|
||||
syserr("Copying to null parameter array");
|
||||
else {
|
||||
clearParameterArray(to);
|
||||
for (i = 0; !isEndOfArray(&from[i]); i++)
|
||||
addParameterToParameterArray(to, &from[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void subtractParameterArrays(Parameter theArray[], Parameter remove[]) {
|
||||
int i;
|
||||
|
||||
if (remove == nullptr) return;
|
||||
|
||||
for (i = 0; !isEndOfArray(&theArray[i]); i++)
|
||||
if (inParameterArray(remove, theArray[i].instance))
|
||||
theArray[i].instance = 0; /* Mark empty */
|
||||
compressParameterArray(theArray);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void clearParameterArray(Parameter theArray[]) {
|
||||
Parameter *p = &theArray[0];
|
||||
|
||||
for (p = &theArray[0]; !isEndOfArray(p); p++)
|
||||
clearParameter(p);
|
||||
setEndOfArray(theArray);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void intersectParameterArrays(Parameter one[], Parameter other[]) {
|
||||
int i, last = 0;
|
||||
|
||||
|
||||
for (i = 0; !isEndOfArray(&one[i]); i++)
|
||||
if (inParameterArray(other, one[i].instance))
|
||||
one[last++] = one[i];
|
||||
setEndOfArray(&one[last]);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void copyReferencesToParameterArray(Aint references[], Parameter parameterArray[]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; !isEndOfArray(&references[i]); i++) {
|
||||
parameterArray[i].instance = references[i];
|
||||
parameterArray[i].firstWord = EOD; /* Ensure that there is no word that can be used */
|
||||
}
|
||||
setEndOfArray(¶meterArray[i]);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void addParameterForInstance(Parameter *parameters, int instance) {
|
||||
Parameter *parameter = findEndOfParameterArray(parameters);
|
||||
|
||||
parameter->instance = instance;
|
||||
parameter->useWords = FALSE;
|
||||
|
||||
setEndOfArray(parameter + 1);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void addParameterForInteger(ParameterArray parameters, int value) {
|
||||
Parameter *parameter = findEndOfParameterArray(parameters);
|
||||
|
||||
createIntegerLiteral(value);
|
||||
parameter->instance = instanceFromLiteral(litCount);
|
||||
parameter->useWords = FALSE;
|
||||
|
||||
setEndOfArray(parameter + 1);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void addParameterForString(Parameter *parameters, char *value) {
|
||||
Parameter *parameter = findEndOfParameterArray(parameters);
|
||||
|
||||
createStringLiteral(value);
|
||||
parameter->instance = instanceFromLiteral(litCount);
|
||||
parameter->useWords = FALSE;
|
||||
|
||||
setEndOfArray(parameter + 1);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void printParameterArray(Parameter parameters[]) {
|
||||
int i;
|
||||
printf("[");
|
||||
for (i = 0; !isEndOfArray(¶meters[i]); i++) {
|
||||
printf("%d ", (int)parameters[i].instance);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
90
engines/glk/alan3/params.h
Normal file
90
engines/glk/alan3/params.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_ALAN3_PARAMS
|
||||
#define GLK_ALAN3_PARAMS
|
||||
|
||||
/* Various utility functions for handling parameters */
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* TYPES */
|
||||
struct Parameter { /* PARAMETER */
|
||||
Aid instance; /* Instance code for the parameter (0=multiple) */
|
||||
bool isLiteral;
|
||||
bool isPronoun;
|
||||
bool isThem;
|
||||
bool useWords; /* Indicate to use words instead of instance code when saying */
|
||||
int firstWord; /* Index to first word used by player */
|
||||
int lastWord; /* d:o to last */
|
||||
struct Parameter *candidates; /* Array of instances possibly matching this parameter depending on player input */
|
||||
};
|
||||
|
||||
typedef Parameter *ParameterArray;
|
||||
|
||||
|
||||
/* DATA */
|
||||
extern Parameter *globalParameters;
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
/* Single Parameter: */
|
||||
extern Parameter *newParameter(int instanceId);
|
||||
extern void clearParameter(Parameter *parameter);
|
||||
extern void copyParameter(Parameter *theCopy, Parameter *theOriginal);
|
||||
|
||||
/* ParameterArray: */
|
||||
extern ParameterArray newParameterArray(void);
|
||||
extern ParameterArray ensureParameterArrayAllocated(ParameterArray currentArray);
|
||||
extern void freeParameterArray(Parameter *array);
|
||||
|
||||
extern bool parameterArrayIsEmpty(ParameterArray parameters);
|
||||
extern void addParameterToParameterArray(ParameterArray theArray, Parameter *theParameter);
|
||||
extern void addParameterForInstance(ParameterArray parameters, int instance);
|
||||
extern void addParameterForInteger(ParameterArray parameters, int value);
|
||||
extern void addParameterForString(ParameterArray parameters, char *value);
|
||||
extern Parameter *findEndOfParameterArray(ParameterArray parameters);
|
||||
extern void compressParameterArray(ParameterArray a);
|
||||
extern int lengthOfParameterArray(ParameterArray a);
|
||||
extern bool equalParameterArrays(ParameterArray parameters1, ParameterArray parameters2);
|
||||
extern bool inParameterArray(ParameterArray l, Aword e);
|
||||
extern void copyParameterArray(ParameterArray to, ParameterArray from);
|
||||
extern void clearParameterArray(ParameterArray list);
|
||||
extern void subtractParameterArrays(ParameterArray a, ParameterArray b);
|
||||
extern void mergeParameterArrays(ParameterArray a, ParameterArray b);
|
||||
extern void intersectParameterArrays(ParameterArray a, ParameterArray b);
|
||||
extern void copyReferencesToParameterArray(Aint *references, ParameterArray parameters);
|
||||
extern void printParameterArray(ParameterArray parameters);
|
||||
|
||||
extern int findMultiplePosition(ParameterArray parameters);
|
||||
|
||||
/* Global Parameters: */
|
||||
extern void setGlobalParameters(ParameterArray parameters);
|
||||
extern ParameterArray getGlobalParameters(void);
|
||||
extern ParameterArray getGlobalParameter(int parameterIndex);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
1520
engines/glk/alan3/parse.cpp
Normal file
1520
engines/glk/alan3/parse.cpp
Normal file
File diff suppressed because it is too large
Load Diff
42
engines/glk/alan3/parse.h
Normal file
42
engines/glk/alan3/parse.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* 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_ALAN3_PARSE
|
||||
#define GLK_ALAN3_PARSE
|
||||
|
||||
/* Parse data for ALAN interpreter module. */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/params.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
extern void parse(CONTEXT);
|
||||
extern void initParsing(void);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
39
engines/glk/alan3/resources.h
Normal file
39
engines/glk/alan3/resources.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_ALAN3_RESOURCES
|
||||
#define GLK_ALAN3_RESOURCES
|
||||
|
||||
#define IDC_STATIC (-1)
|
||||
|
||||
#define IDR_ARUN 25000
|
||||
#define IDR_ABOUT 27000
|
||||
|
||||
#define IDD_ABOUT 26000
|
||||
#define ID_MENU_RESTART 26001
|
||||
#define ID_MENU_SAVE 26002
|
||||
#define ID_MENU_RECORD 26003
|
||||
#define ID_MENU_PLAYBACK 26004
|
||||
#define ID_MENU_TRANSCRIPT 26005
|
||||
#define ID_MENU_RESTORE 26006
|
||||
#define ID_MENU_ABOUT 26007
|
||||
|
||||
#endif
|
||||
655
engines/glk/alan3/reverse.cpp
Normal file
655
engines/glk/alan3/reverse.cpp
Normal file
@@ -0,0 +1,655 @@
|
||||
/* 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/alan3/types.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/checkentry.h"
|
||||
#include "glk/alan3/rules.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/utils.h"
|
||||
#include "glk/alan3/compatibility.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern Aword *memory;
|
||||
|
||||
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
static Aaddr memorySize = 0;
|
||||
static Aword *addressesDone = nullptr;
|
||||
static int numberDone = 0;
|
||||
static int doneSize = 0;
|
||||
|
||||
static bool alreadyDone(Aaddr address) {
|
||||
int i;
|
||||
|
||||
if (address == 0) return TRUE;
|
||||
|
||||
/* Have we already done it? */
|
||||
for (i = 0; i < numberDone; i++)
|
||||
if (addressesDone[i] == address)
|
||||
return TRUE;
|
||||
|
||||
if (doneSize == numberDone) {
|
||||
doneSize += 100;
|
||||
addressesDone = (Aword *)realloc(addressesDone, doneSize * sizeof(Aword));
|
||||
}
|
||||
addressesDone[numberDone] = address;
|
||||
numberDone++;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define NATIVE(w) \
|
||||
( (((Aword)((w)[3]) ) & 0x000000ff) \
|
||||
| (((Aword)((w)[2]) << 8) & 0x0000ff00) \
|
||||
| (((Aword)((w)[1]) << 16) & 0x00ff0000) \
|
||||
| (((Aword)((w)[0]) << 24) & 0xff000000))
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
Aword reversed(Aword w) { /* IN - The ACODE word to swap bytes of */
|
||||
#ifdef TRYNATIVE
|
||||
return NATIVE(&w);
|
||||
#else
|
||||
Aword s; /* The swapped ACODE word */
|
||||
char *wp, *sp;
|
||||
uint i;
|
||||
|
||||
wp = (char *) &w;
|
||||
sp = (char *) &s;
|
||||
|
||||
for (i = 0; i < sizeof(Aword); i++)
|
||||
sp[sizeof(Aword) - 1 - i] = wp[i];
|
||||
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void reverseWord(Aword *w) { /* IN - The ACODE word to reverse bytes in */
|
||||
*w = reversed(*w);
|
||||
}
|
||||
|
||||
void reverse(Aword *w) { /* IN - The ACODE word to reverse bytes in */
|
||||
if (w < &memory[0] || w > &memory[memorySize])
|
||||
syserr("Reversing address outside of memory");
|
||||
reverseWord(w);
|
||||
}
|
||||
|
||||
|
||||
static void reverseTable(Aword adr, int elementSize) {
|
||||
Aword *e = &memory[adr];
|
||||
uint i;
|
||||
|
||||
if (elementSize < (int)sizeof(Aword) || elementSize % (int)sizeof(Aword) != 0)
|
||||
syserr("***Wrong size in 'reverseTable()' ***");
|
||||
|
||||
if (adr == 0) return;
|
||||
|
||||
while (!isEndOfArray(e)) {
|
||||
for (i = 0; i < elementSize / sizeof(Aword); i++) {
|
||||
reverse(e);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseStms(Aword adr) {
|
||||
Aword *e = &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
while (TRUE) {
|
||||
reverse(e);
|
||||
if (*e == ((Aword)C_STMOP << 28 | (Aword)I_RETURN)) break;
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseMsgs(Aword adr) {
|
||||
MessageEntry *e = (MessageEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(MessageEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseDictionary(Aword adr) {
|
||||
DictionaryEntry *e = (DictionaryEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(DictionaryEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
if ((e->classBits & SYNONYM_BIT) == 0) { /* Do not do this for synonyms */
|
||||
reverseTable(e->adjectiveRefs, sizeof(Aword));
|
||||
reverseTable(e->nounRefs, sizeof(Aword));
|
||||
reverseTable(e->pronounRefs, sizeof(Aword));
|
||||
}
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseChks(Aword adr) {
|
||||
CheckEntry *e = (CheckEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(CheckEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->exp);
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseAlts(Aword adr) {
|
||||
AltEntry *e = (AltEntry *)&memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(AltEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseChks(e->checks);
|
||||
reverseStms(e->action);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseVerbs(Aword adr) {
|
||||
VerbEntry *e = (VerbEntry *)&memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(VerbEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseAlts(e->alts);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseSteps(Aword adr) {
|
||||
StepEntry *e = (StepEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(StepEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->after);
|
||||
reverseStms(e->exp);
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseScrs(Aword adr) {
|
||||
ScriptEntry *e = (ScriptEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(ScriptEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->description);
|
||||
reverseSteps(e->steps);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseExits(Aword adr) {
|
||||
ExitEntry *e = (ExitEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(ExitEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseChks(e->checks);
|
||||
reverseStms(e->action);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseClasses(Aword adr) {
|
||||
ClassEntry *e = (ClassEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(ClassEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->name);
|
||||
reverseStms(e->initialize);
|
||||
reverseChks(e->descriptionChecks);
|
||||
reverseStms(e->description);
|
||||
reverseStms(e->entered);
|
||||
reverseStms(e->definite.address);
|
||||
reverseStms(e->indefinite.address);
|
||||
reverseStms(e->negative.address);
|
||||
reverseStms(e->mentioned);
|
||||
reverseVerbs(e->verbs);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseInstances(Aword adr) {
|
||||
InstanceEntry *e = (InstanceEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(InstanceEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->name);
|
||||
reverseTable(e->initialAttributes, sizeof(AttributeHeaderEntry));
|
||||
reverseStms(e->initialize);
|
||||
reverseStms(e->definite.address);
|
||||
reverseStms(e->indefinite.address);
|
||||
reverseStms(e->negative.address);
|
||||
reverseStms(e->mentioned);
|
||||
reverseChks(e->checks);
|
||||
reverseStms(e->description);
|
||||
reverseVerbs(e->verbs);
|
||||
reverseStms(e->entered);
|
||||
reverseExits(e->exits);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseRestrictions(Aword adr) {
|
||||
RestrictionEntry *e = (RestrictionEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(RestrictionEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseElms(Aword adr) {
|
||||
ElementEntry *e = (ElementEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(ElementEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
if ((uint)e->code == EOS) reverseRestrictions(e->next);
|
||||
else reverseElms(e->next);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseSyntaxTableCurrent(Aword adr) {
|
||||
SyntaxEntry *e = (SyntaxEntry *) &memory[adr];
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(SyntaxEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseElms(e->elms);
|
||||
reverseTable(e->parameterNameTable, sizeof(Aaddr));
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseSyntaxTablePreBeta2(Aword adr) {
|
||||
SyntaxEntryPreBeta2 *e = (SyntaxEntryPreBeta2 *) &memory[adr];
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(SyntaxEntryPreBeta2));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseElms(e->elms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseSyntaxTable(Aword adr, byte version[]) {
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (isPreBeta2(version))
|
||||
reverseSyntaxTablePreBeta2(adr);
|
||||
else
|
||||
reverseSyntaxTableCurrent(adr);
|
||||
}
|
||||
|
||||
|
||||
static void reverseParameterNames(Aaddr parameterMapAddress) {
|
||||
Aaddr *e;
|
||||
Aaddr adr;
|
||||
|
||||
adr = addressAfterTable(parameterMapAddress, sizeof(ParameterMapEntry));
|
||||
reverse(&memory[adr]);
|
||||
adr = memory[adr];
|
||||
|
||||
reverseTable(adr, sizeof(Aaddr));
|
||||
|
||||
e = (Aaddr *) &memory[adr];
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseTable(*e, sizeof(Aaddr));
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseParameterTable(Aword adr) {
|
||||
ParameterMapEntry *e = (ParameterMapEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(ParameterMapEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseTable(e->parameterMapping, sizeof(Aword));
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseEvts(Aword adr) {
|
||||
EventEntry *e = (EventEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(EventEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->code);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseLims(Aword adr) {
|
||||
LimitEntry *e = (LimitEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(LimitEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseContainers(Aword adr) {
|
||||
ContainerEntry *e = (ContainerEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(ContainerEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseLims(e->limits);
|
||||
reverseStms(e->header);
|
||||
reverseStms(e->empty);
|
||||
reverseChks(e->extractChecks);
|
||||
reverseStms(e->extractStatements);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseRuls(Aword adr) {
|
||||
RuleEntry *e = (RuleEntry *) &memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(RuleEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseStms(e->exp);
|
||||
reverseStms(e->stms);
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void reverseSetInitTable(Aaddr adr) {
|
||||
SetInitEntry *e = (SetInitEntry *)&memory[adr];
|
||||
|
||||
if (!adr || alreadyDone(adr)) return;
|
||||
|
||||
if (!isEndOfArray(e)) {
|
||||
reverseTable(adr, sizeof(SetInitEntry));
|
||||
while (!isEndOfArray(e)) {
|
||||
reverseTable(e->setAddress, sizeof(Aword));
|
||||
e++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void reversePreAlpha5Header(Pre3_0alpha5Header *hdr) {
|
||||
uint i;
|
||||
|
||||
/* Reverse all words in the header except the tag */
|
||||
for (i = 1; i < sizeof(*hdr) / sizeof(Aword); i++)
|
||||
reverseWord(&((Aword *)hdr)[i]);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void reversePreAlpha5() {
|
||||
/* NOTE that the reversePreXXX() have different header definitions */
|
||||
Pre3_0alpha5Header *hdr = (Pre3_0alpha5Header *)memory;
|
||||
|
||||
reversePreAlpha5Header(hdr);
|
||||
memorySize = hdr->size;
|
||||
|
||||
reverseDictionary(hdr->dictionary);
|
||||
reverseSyntaxTable(hdr->syntaxTableAddress, hdr->version);
|
||||
reverseParameterTable(hdr->parameterMapAddress);
|
||||
reverseVerbs(hdr->verbTableAddress);
|
||||
reverseClasses(hdr->classTableAddress);
|
||||
reverseInstances(hdr->instanceTableAddress);
|
||||
reverseScrs(hdr->scriptTableAddress);
|
||||
reverseContainers(hdr->containerTableAddress);
|
||||
reverseEvts(hdr->eventTableAddress);
|
||||
reverseRuls(hdr->ruleTableAddress);
|
||||
reverseTable(hdr->stringInitTable, sizeof(StringInitEntry));
|
||||
reverseSetInitTable(hdr->setInitTable);
|
||||
reverseTable(hdr->sourceFileTable, sizeof(SourceFileEntry));
|
||||
reverseTable(hdr->sourceLineTable, sizeof(SourceLineEntry));
|
||||
reverseStms(hdr->start);
|
||||
reverseMsgs(hdr->messageTableAddress);
|
||||
|
||||
reverseTable(hdr->scores, sizeof(Aword));
|
||||
reverseTable(hdr->freq, sizeof(Aword));
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void reversePreBeta2Header(Pre3_0beta2Header *hdr) {
|
||||
uint i;
|
||||
|
||||
/* Reverse all words in the header except the tag */
|
||||
for (i = 1; i < sizeof(*hdr) / sizeof(Aword); i++)
|
||||
reverseWord(&((Aword *)hdr)[i]);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void reversePreBeta2() {
|
||||
/* NOTE that the reversePreXXX() have different header definitions */
|
||||
Pre3_0beta2Header *hdr = (Pre3_0beta2Header *)memory;
|
||||
|
||||
reversePreBeta2Header(hdr);
|
||||
memorySize = hdr->size;
|
||||
|
||||
reverseDictionary(hdr->dictionary);
|
||||
reverseSyntaxTable(hdr->syntaxTableAddress, hdr->version);
|
||||
reverseParameterTable(hdr->parameterMapAddress);
|
||||
reverseVerbs(hdr->verbTableAddress);
|
||||
reverseClasses(hdr->classTableAddress);
|
||||
reverseInstances(hdr->instanceTableAddress);
|
||||
reverseScrs(hdr->scriptTableAddress);
|
||||
reverseContainers(hdr->containerTableAddress);
|
||||
reverseEvts(hdr->eventTableAddress);
|
||||
reverseRuls(hdr->ruleTableAddress);
|
||||
reverseTable(hdr->stringInitTable, sizeof(StringInitEntry));
|
||||
reverseSetInitTable(hdr->setInitTable);
|
||||
reverseTable(hdr->sourceFileTable, sizeof(SourceFileEntry));
|
||||
reverseTable(hdr->sourceLineTable, sizeof(SourceLineEntry));
|
||||
reverseStms(hdr->start);
|
||||
reverseMsgs(hdr->messageTableAddress);
|
||||
|
||||
reverseTable(hdr->scores, sizeof(Aword));
|
||||
reverseTable(hdr->freq, sizeof(Aword));
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void reverseHdr(ACodeHeader *hdr) {
|
||||
uint i;
|
||||
|
||||
/* Reverse all words in the header except the tag and the version marking */
|
||||
for (i = 1; i < sizeof(*hdr) / sizeof(Aword); i++)
|
||||
reverseWord(&((Aword *)hdr)[i]);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void reverseInstanceIdTable(ACodeHeader *hdr) {
|
||||
reverseTable(hdr->instanceTableAddress + hdr->instanceMax * sizeof(InstanceEntry) / sizeof(Aword) + 1, sizeof(Aword));
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void reverseNative() {
|
||||
/* NOTE that the reversePreXXX() have different hdr definitions */
|
||||
ACodeHeader *hdr = (ACodeHeader *)memory;
|
||||
|
||||
reverseHdr(hdr);
|
||||
memorySize = hdr->size;
|
||||
|
||||
reverseDictionary(hdr->dictionary);
|
||||
reverseSyntaxTable(hdr->syntaxTableAddress, hdr->version);
|
||||
if (hdr->debug && !isPreBeta3(hdr->version))
|
||||
reverseParameterNames(hdr->parameterMapAddress);
|
||||
reverseParameterTable(hdr->parameterMapAddress);
|
||||
reverseVerbs(hdr->verbTableAddress);
|
||||
reverseClasses(hdr->classTableAddress);
|
||||
reverseInstances(hdr->instanceTableAddress);
|
||||
if (hdr->debug && !isPreBeta3(hdr->version))
|
||||
reverseInstanceIdTable(hdr);
|
||||
reverseScrs(hdr->scriptTableAddress);
|
||||
reverseContainers(hdr->containerTableAddress);
|
||||
reverseEvts(hdr->eventTableAddress);
|
||||
reverseRuls(hdr->ruleTableAddress);
|
||||
reverseTable(hdr->stringInitTable, sizeof(StringInitEntry));
|
||||
reverseSetInitTable(hdr->setInitTable);
|
||||
reverseTable(hdr->sourceFileTable, sizeof(SourceFileEntry));
|
||||
reverseTable(hdr->sourceLineTable, sizeof(SourceLineEntry));
|
||||
reverseStms(hdr->prompt);
|
||||
reverseStms(hdr->start);
|
||||
reverseMsgs(hdr->messageTableAddress);
|
||||
|
||||
reverseTable(hdr->scores, sizeof(Aword));
|
||||
reverseTable(hdr->freq, sizeof(Aword));
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================
|
||||
|
||||
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(void) {
|
||||
ACodeHeader *hdr = (ACodeHeader *)memory;
|
||||
byte version[4];
|
||||
int i;
|
||||
|
||||
/* Make a copy of the version marking to reverse */
|
||||
for (i = 0; i <= 3; i++)
|
||||
version[i] = hdr->version[i];
|
||||
reverseWord((Aword *)&version);
|
||||
|
||||
if (isPreAlpha5(version))
|
||||
reversePreAlpha5();
|
||||
else if (isPreBeta2(version))
|
||||
reversePreBeta2();
|
||||
else
|
||||
reverseNative();
|
||||
|
||||
free(addressesDone);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
42
engines/glk/alan3/reverse.h
Normal file
42
engines/glk/alan3/reverse.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* 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_ALAN3_REVERSE
|
||||
#define GLK_ALAN3_REVERSE
|
||||
|
||||
/* Header file for reverse-module in Alan Interpreter */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Functions: */
|
||||
|
||||
extern void reverseHdr(ACodeHeader *hdr);
|
||||
extern void reverseACD(void);
|
||||
extern void reverse(Aword *word);
|
||||
extern Aword reversed(Aword word);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
263
engines/glk/alan3/rules.cpp
Normal file
263
engines/glk/alan3/rules.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/* 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/alan3/types.h"
|
||||
#include "glk/alan3/rules.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/debug.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/compatibility.h"
|
||||
|
||||
#ifdef HAVE_GLK
|
||||
#include "glk/alan3/glkio.h"
|
||||
#endif
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA: */
|
||||
RuleEntry *rules; /* Rule table pointer */
|
||||
bool anyRuleRun;
|
||||
|
||||
|
||||
/* PRIVATE TYPES: */
|
||||
typedef struct RulesAdmin {
|
||||
bool lastEval;
|
||||
bool alreadyRun;
|
||||
} RulesAdmin;
|
||||
|
||||
/* PRIVATE DATA: */
|
||||
static int ruleCount;
|
||||
static RulesAdmin *rulesAdmin; /* Table for administration of the rules */
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void clearRulesAdmin(int numRules) {
|
||||
int r;
|
||||
for (r = 0; r < numRules; r++) {
|
||||
rulesAdmin[r].lastEval = FALSE;
|
||||
rulesAdmin[r].alreadyRun = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void initRulesAdmin(int numRules) {
|
||||
int r;
|
||||
|
||||
rulesAdmin = (RulesAdmin *)allocate(numRules * sizeof(RulesAdmin) + sizeof(EOD));
|
||||
for (r = 0; r < numRules; r++)
|
||||
;
|
||||
setEndOfArray(&rulesAdmin[r]);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void initRules(Aaddr ruleTableAddress) {
|
||||
|
||||
rules = (RuleEntry *) pointerTo(ruleTableAddress);
|
||||
|
||||
if (ruleCount == 0) { /* Not initiated */
|
||||
for (ruleCount = 0; !isEndOfArray(&rules[ruleCount]); ruleCount++)
|
||||
;
|
||||
initRulesAdmin(ruleCount);
|
||||
}
|
||||
clearRulesAdmin(ruleCount);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceRuleStart(CONTEXT, int rule, const char *what) {
|
||||
printf("\n<RULE %d", rule);
|
||||
if (current.location != 0) {
|
||||
printf(" (at ");
|
||||
CALL1(traceSay, current.location)
|
||||
} else
|
||||
printf(" (nowhere");
|
||||
printf("[%d]), %s", current.location, what);
|
||||
}
|
||||
|
||||
static bool detailedTraceOn() {
|
||||
return traceInstructionOption || traceSourceOption || tracePushOption || traceStackOption;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceRuleEvaluation(CONTEXT, int rule) {
|
||||
if (traceSectionOption) {
|
||||
if (detailedTraceOn()) {
|
||||
CALL2(traceRuleStart, rule, "Evaluating:>")
|
||||
if (!traceInstructionOption)
|
||||
printf("\n");
|
||||
} else {
|
||||
CALL2(traceRuleStart, rule, "Evaluating to ")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceRuleResult(int rule, bool result) {
|
||||
if (traceSectionOption) {
|
||||
if (detailedTraceOn())
|
||||
printf("<RULE %d %s%s", rule, "Evaluated to ", result ? ": true>\n" : ": false>\n");
|
||||
else
|
||||
printf(result ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void traceRuleExecution(CONTEXT, int rule) {
|
||||
if (traceSectionOption) {
|
||||
if (!traceInstructionOption && !traceSourceOption)
|
||||
printf(", Executing:>\n");
|
||||
else {
|
||||
CALL2(traceRuleStart, rule, "Executing:>")
|
||||
if (!traceInstructionOption)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void evaluateRulesPreBeta2(CONTEXT) {
|
||||
bool change = TRUE;
|
||||
bool flag;
|
||||
int i;
|
||||
|
||||
for (i = 1; !isEndOfArray(&rules[i - 1]); i++)
|
||||
rules[i - 1].alreadyRun = FALSE;
|
||||
|
||||
while (change) {
|
||||
change = FALSE;
|
||||
for (i = 1; !isEndOfArray(&rules[i - 1]); i++)
|
||||
if (!rules[i - 1].alreadyRun) {
|
||||
CALL1(traceRuleEvaluation, i)
|
||||
FUNC1(evaluate, flag, rules[i - 1].exp)
|
||||
if (flag) {
|
||||
change = TRUE;
|
||||
rules[i - 1].alreadyRun = TRUE;
|
||||
CALL1(traceRuleExecution, i)
|
||||
CALL1(interpret, rules[i - 1].stms)
|
||||
} else if (traceSectionOption && !traceInstructionOption)
|
||||
printf(":>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* This is how beta2 thought rules should be evaluated:
|
||||
*/
|
||||
static void evaluateRulesBeta2(CONTEXT) {
|
||||
bool change = TRUE;
|
||||
bool triggered;
|
||||
int i;
|
||||
|
||||
for (i = 1; !isEndOfArray(&rules[i - 1]); i++)
|
||||
rules[i - 1].alreadyRun = FALSE;
|
||||
|
||||
current.location = NOWHERE;
|
||||
current.actor = 0;
|
||||
|
||||
while (change) {
|
||||
change = FALSE;
|
||||
for (i = 1; !isEndOfArray(&rules[i - 1]); i++)
|
||||
if (!rules[i - 1].alreadyRun) {
|
||||
CALL1(traceRuleEvaluation, i)
|
||||
FUNC1(evaluate, triggered, rules[i - 1].exp)
|
||||
|
||||
if (triggered) {
|
||||
if (rulesAdmin[i - 1].lastEval == false) {
|
||||
change = TRUE;
|
||||
rules[i - 1].alreadyRun = TRUE;
|
||||
CALL1(traceRuleExecution, i)
|
||||
CALL1(interpret, rules[i - 1].stms)
|
||||
}
|
||||
rulesAdmin[i - 1].lastEval = triggered;
|
||||
} else {
|
||||
rulesAdmin[i - 1].lastEval = false;
|
||||
if (traceSectionOption && !traceInstructionOption)
|
||||
printf(":>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void resetRules() {
|
||||
int i;
|
||||
for (i = 1; !isEndOfArray(&rules[i - 1]); i++) {
|
||||
rulesAdmin[i - 1].alreadyRun = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void evaluateRules(CONTEXT, RuleEntry ruleList[]) {
|
||||
bool change = TRUE;
|
||||
bool evaluated_value;
|
||||
int rule;
|
||||
|
||||
current.location = NOWHERE;
|
||||
current.actor = 0;
|
||||
|
||||
while (change) {
|
||||
change = FALSE;
|
||||
for (rule = 1; !isEndOfArray(&ruleList[rule - 1]); rule++) {
|
||||
CALL1(traceRuleEvaluation, rule)
|
||||
FUNC1(evaluate, evaluated_value, ruleList[rule - 1].exp)
|
||||
traceRuleResult(rule, evaluated_value);
|
||||
|
||||
if (evaluated_value == true && rulesAdmin[rule - 1].lastEval == false
|
||||
&& !rulesAdmin[rule - 1].alreadyRun) {
|
||||
change = TRUE;
|
||||
CALL1(traceRuleExecution, rule)
|
||||
CALL1(interpret, ruleList[rule - 1].stms)
|
||||
rulesAdmin[rule - 1].alreadyRun = TRUE;
|
||||
anyRuleRun = TRUE;
|
||||
} else {
|
||||
if (traceSectionOption && !(traceInstructionOption || traceSourceOption))
|
||||
printf(":>\n");
|
||||
}
|
||||
rulesAdmin[rule - 1].lastEval = evaluated_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
void resetAndEvaluateRules(CONTEXT, RuleEntry ruleList[], const byte *version) {
|
||||
if (isPreBeta2(version))
|
||||
evaluateRulesPreBeta2(context);
|
||||
else if (isPreBeta3(version))
|
||||
evaluateRulesBeta2(context);
|
||||
else {
|
||||
resetRules();
|
||||
evaluateRules(context, ruleList);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
46
engines/glk/alan3/rules.h
Normal file
46
engines/glk/alan3/rules.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* 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_ALAN3_RULES
|
||||
#define GLK_ALAN3_RULES
|
||||
|
||||
/* Header file for rules handler in Alan interpreter */
|
||||
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern RuleEntry *rules; /* Rule table pointer */
|
||||
extern bool anyRuleRun; /* Did any rule run? */
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void initRules(Aaddr rulesTableAddress);
|
||||
extern void resetAndEvaluateRules(CONTEXT, RuleEntry rules[], const byte *version);
|
||||
extern void resetRules(void);
|
||||
extern void evaluateRules(CONTEXT, RuleEntry rules[]);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
158
engines/glk/alan3/save.cpp
Normal file
158
engines/glk/alan3/save.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/* 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/alan3/save.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/event.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/score.h"
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
static void saveGameInfo(Common::WriteStream *saveFile) {
|
||||
saveFile->writeUint32BE(MKTAG('A', 'S', 'A', 'V'));
|
||||
saveFile->write(header->version, 4);
|
||||
saveFile->writeUint32LE(header->uid);
|
||||
}
|
||||
|
||||
static void verifySaveFile(CONTEXT, Common::SeekableReadStream *saveFile) {
|
||||
if (saveFile->readUint32BE() != MKTAG('A', 'S', 'A', 'V'))
|
||||
error(context, M_NOTASAVEFILE);
|
||||
}
|
||||
|
||||
static void verifyCompilerVersion(CONTEXT, Common::SeekableReadStream *saveFile) {
|
||||
char savedVersion[4];
|
||||
|
||||
saveFile->read(&savedVersion, 4);
|
||||
if (!ignoreErrorOption && memcmp(savedVersion, header->version, 4))
|
||||
error(context, M_SAVEVERS);
|
||||
}
|
||||
|
||||
static void verifyGameId(CONTEXT, Common::SeekableReadStream *saveFile) {
|
||||
Aword savedUid = saveFile->readUint32LE();
|
||||
if (!ignoreErrorOption && savedUid != header->uid)
|
||||
error(context, M_SAVEVERS);
|
||||
}
|
||||
|
||||
void syncGame(Common::Serializer &s) {
|
||||
// Current values
|
||||
current.synchronize(s);
|
||||
|
||||
// Attributes area
|
||||
for (Aint i = 0; i < header->attributesAreaSize / 3; ++i)
|
||||
attributes[i].synchronize(s);
|
||||
|
||||
// Admin data
|
||||
for (uint i = 1; i <= header->instanceMax; i++)
|
||||
admin[i].synchronize(s);
|
||||
|
||||
// Event queue
|
||||
s.syncAsSint32LE(eventQueueTop);
|
||||
for (int i = 0; i < eventQueueTop; ++i)
|
||||
eventQueue[i].synchronize(s);
|
||||
|
||||
// Scores
|
||||
for (Aint i = 0; i < header->scoreCount; ++i)
|
||||
s.syncAsUint32LE(scores[i]);
|
||||
|
||||
// Strings
|
||||
if (header->stringInitTable != 0)
|
||||
for (StringInitEntry *initEntry = (StringInitEntry *)pointerTo(header->stringInitTable);
|
||||
!isEndOfArray(initEntry); initEntry++) {
|
||||
|
||||
if (s.isSaving()) {
|
||||
char *attr = (char *)getInstanceStringAttribute(initEntry->instanceCode, initEntry->attributeCode);
|
||||
Aint length = strlen(attr) + 1;
|
||||
s.syncAsUint32LE(length);
|
||||
s.syncBytes((byte *)attr, length);
|
||||
} else {
|
||||
Aint length = 0;
|
||||
s.syncAsUint32LE(length);
|
||||
char *string = (char *)allocate(length + 1);
|
||||
s.syncBytes((byte *)string, length);
|
||||
setInstanceAttribute(initEntry->instanceCode, initEntry->attributeCode, toAptr(string));
|
||||
}
|
||||
}
|
||||
|
||||
// Sets
|
||||
if (header->setInitTable != 0) {
|
||||
for (SetInitEntry *initEntry = (SetInitEntry *)pointerTo(header->setInitTable);
|
||||
!isEndOfArray(initEntry); initEntry++) {
|
||||
|
||||
if (s.isSaving()) {
|
||||
Set *attr = (Set *)getInstanceSetAttribute(initEntry->instanceCode, initEntry->attributeCode);
|
||||
s.syncAsUint32LE(attr->size);
|
||||
for (int i = 0; i < attr->size; ++i)
|
||||
s.syncAsUint32LE(attr->members[i]);
|
||||
|
||||
} else {
|
||||
Aword setSize = 0, member = 0;
|
||||
s.syncAsUint32BE(setSize);
|
||||
Set *set = newSet(setSize);
|
||||
for (uint i = 0; i < setSize; ++i) {
|
||||
s.syncAsUint32LE(member);
|
||||
addToSet(set, member);
|
||||
}
|
||||
|
||||
setInstanceAttribute(initEntry->instanceCode, initEntry->attributeCode, toAptr(set));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void saveGame(Common::WriteStream *saveFile) {
|
||||
// Save tag, version of interpreter, and unique id of game
|
||||
saveGameInfo(saveFile);
|
||||
|
||||
// Save game data
|
||||
Common::Serializer s(nullptr, saveFile);
|
||||
syncGame(s);
|
||||
}
|
||||
|
||||
bool restoreGame(Common::SeekableReadStream *saveFile) {
|
||||
Context ctx;
|
||||
verifySaveFile(ctx, saveFile);
|
||||
if (ctx._break) return false;
|
||||
|
||||
// Verify version of compiler/interpreter of saved game with us
|
||||
verifyCompilerVersion(ctx, saveFile);
|
||||
if (ctx._break) return false;
|
||||
|
||||
// Verify unique id of game
|
||||
verifyGameId(ctx, saveFile);
|
||||
if (ctx._break) return false;
|
||||
|
||||
// Restore game data
|
||||
Common::Serializer s(saveFile, nullptr);
|
||||
syncGame(s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
36
engines/glk/alan3/save.h
Normal file
36
engines/glk/alan3/save.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_ALAN3_SAVE
|
||||
#define GLK_ALAN3_SAVE
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
extern void saveGame(Common::WriteStream *saveFile);
|
||||
extern bool restoreGame(Common::SeekableReadStream *saveFile);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
243
engines/glk/alan3/scan.cpp
Normal file
243
engines/glk/alan3/scan.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/* 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/alan3/scan.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/dictionary.h"
|
||||
#include "glk/alan3/debug.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/inter.h"
|
||||
#include "glk/alan3/literal.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/params.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/word.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
bool continued = FALSE;
|
||||
|
||||
|
||||
/* PRIVATE DATA */
|
||||
static char buf[1000]; /* The input buffer */
|
||||
static char isobuf[1000]; /* The input buffer in ISO */
|
||||
static bool eol = TRUE; /* Looking at End of line? Yes, initially */
|
||||
static char *token = nullptr;
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void forceNewPlayerInput() {
|
||||
setEndOfArray(&playerWords[currentWordIndex]);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void unknown(CONTEXT, char tok[]) {
|
||||
char *str = scumm_strdup(tok);
|
||||
Parameter *messageParameters = newParameterArray();
|
||||
|
||||
addParameterForString(messageParameters, str);
|
||||
printMessageWithParameters(M_UNKNOWN_WORD, messageParameters);
|
||||
deallocate(messageParameters);
|
||||
free(str);
|
||||
CALL0(abortPlayerCommand)
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int number(char tok[]) {
|
||||
int i;
|
||||
|
||||
(void)sscanf(tok, "%d", &i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int lookup(CONTEXT, char wrd[]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; !isEndOfArray(&dictionary[i]); i++) {
|
||||
if (compareStrings(wrd, (char *) pointerTo(dictionary[i].string)) == 0) {
|
||||
return (i);
|
||||
}
|
||||
}
|
||||
R0CALL1(unknown, wrd)
|
||||
return (int)EOD;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static bool isWordCharacter(int ch) {
|
||||
return isISOLetter(ch) || Common::isDigit(ch) || ch == '\'' || ch == '-' || ch == '_';
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char *gettoken(char *txtBuf) {
|
||||
static char *marker;
|
||||
static char oldch;
|
||||
|
||||
if (txtBuf == nullptr)
|
||||
*marker = oldch;
|
||||
else
|
||||
marker = txtBuf;
|
||||
while (*marker != '\0' && isSpace(*marker) && *marker != '\n')
|
||||
marker++;
|
||||
txtBuf = marker;
|
||||
if (isISOLetter(*marker))
|
||||
while (*marker && isWordCharacter(*marker))
|
||||
marker++;
|
||||
else if (Common::isDigit((int)*marker))
|
||||
while (Common::isDigit((int)*marker))
|
||||
marker++;
|
||||
else if (*marker == '\"') {
|
||||
marker++;
|
||||
while (*marker != '\"')
|
||||
marker++;
|
||||
marker++;
|
||||
} else if (*marker == '\0' || *marker == '\n' || *marker == ';')
|
||||
return nullptr;
|
||||
else
|
||||
marker++;
|
||||
oldch = *marker;
|
||||
*marker = '\0';
|
||||
return txtBuf;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
// TODO replace dependency to exe.c with injection of quitGame() and undo()
|
||||
static void getLine(CONTEXT) {
|
||||
para();
|
||||
do {
|
||||
CALL0(g_io->statusLine)
|
||||
|
||||
if (header->prompt) {
|
||||
anyOutput = FALSE;
|
||||
CALL1(interpret, header->prompt)
|
||||
|
||||
if (anyOutput)
|
||||
printAndLog(" ");
|
||||
needSpace = FALSE;
|
||||
} else
|
||||
printAndLog("> ");
|
||||
|
||||
bool flag;
|
||||
FUNC2(g_io->readLine, flag, buf, 255);
|
||||
if (!flag) {
|
||||
newline();
|
||||
CALL0(quitGame)
|
||||
}
|
||||
|
||||
getPageSize();
|
||||
anyOutput = FALSE;
|
||||
if (transcriptOption || logOption) {
|
||||
// TODO: Refactor out the logging to log.c?
|
||||
g_io->glk_put_string_stream(logFile, buf);
|
||||
g_io->glk_put_char_stream(logFile, '\n');
|
||||
}
|
||||
/* If the player input an empty command he forfeited his command */
|
||||
if (strlen(buf) == 0) {
|
||||
clearWordList(playerWords);
|
||||
LONG_JUMP_LABEL("forfeit")
|
||||
}
|
||||
|
||||
Common::strcpy_s(isobuf, buf);
|
||||
token = gettoken(isobuf);
|
||||
if (token != nullptr) {
|
||||
if (strcmp("debug", token) == 0 && header->debug) {
|
||||
debugOption = TRUE;
|
||||
CALL3(debug, FALSE, 0, 0)
|
||||
|
||||
token = nullptr;
|
||||
} else if (strcmp("undo", token) == 0) {
|
||||
token = gettoken(nullptr);
|
||||
if (token != nullptr) /* More tokens? */
|
||||
CALL1(error, M_WHAT)
|
||||
CALL0(undo)
|
||||
}
|
||||
}
|
||||
} while (token == nullptr);
|
||||
eol = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void scan(CONTEXT) {
|
||||
int i;
|
||||
int w;
|
||||
|
||||
if (continued) {
|
||||
/* Player used '.' to separate commands. Read next */
|
||||
para();
|
||||
token = gettoken(nullptr); /* Or did he just finish the command with a full stop? */
|
||||
if (token == nullptr) {
|
||||
CALL0(getLine)
|
||||
}
|
||||
continued = FALSE;
|
||||
} else {
|
||||
CALL0(getLine)
|
||||
}
|
||||
|
||||
freeLiterals();
|
||||
playerWords[0].code = 0; // TODO This means what?
|
||||
i = 0;
|
||||
do {
|
||||
ensureSpaceForPlayerWords(i + 1);
|
||||
playerWords[i].start = token;
|
||||
playerWords[i].end = strchr(token, '\0');
|
||||
if (isISOLetter(token[0])) {
|
||||
FUNC1(lookup, w, token);
|
||||
if (!isNoise(w))
|
||||
playerWords[i++].code = w;
|
||||
} else if (Common::isDigit((int)token[0]) || token[0] == '\"') {
|
||||
if (Common::isDigit((int)token[0])) {
|
||||
createIntegerLiteral(number(token));
|
||||
} else {
|
||||
char *unquotedString = scumm_strdup(token);
|
||||
unquotedString[strlen(token) - 1] = '\0';
|
||||
createStringLiteral(&unquotedString[1]);
|
||||
free(unquotedString);
|
||||
}
|
||||
playerWords[i++].code = dictionarySize + litCount; /* Word outside dictionary = literal */
|
||||
} else if (token[0] == ',') {
|
||||
playerWords[i++].code = conjWord;
|
||||
} else if (token[0] == '.') {
|
||||
continued = TRUE;
|
||||
setEndOfArray(&playerWords[i]);
|
||||
eol = TRUE;
|
||||
break;
|
||||
} else
|
||||
CALL1(unknown, token)
|
||||
setEndOfArray(&playerWords[i]);
|
||||
eol = (token = gettoken(nullptr)) == nullptr;
|
||||
} while (!eol);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
45
engines/glk/alan3/scan.h
Normal file
45
engines/glk/alan3/scan.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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_ALAN3_SCAN
|
||||
#define GLK_ALAN3_SCAN
|
||||
|
||||
/* Player input scanner for ALAN interpreter module. */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern bool continued;
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
||||
extern void forceNewPlayerInput();
|
||||
extern void scan(CONTEXT);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
31
engines/glk/alan3/score.cpp
Normal file
31
engines/glk/alan3/score.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/* 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/alan3/score.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
Aword *scores; // Score table pointer
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
36
engines/glk/alan3/score.h
Normal file
36
engines/glk/alan3/score.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_ALAN3_SCORE
|
||||
#define GLK_ALAN3_SCORE
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern Aword *scores;
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
169
engines/glk/alan3/set.cpp
Normal file
169
engines/glk/alan3/set.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/* 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/alan3/set.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
#define EXTENT 5
|
||||
|
||||
/*======================================================================*/
|
||||
Set *newSet(int allocation) {
|
||||
Set *theSet = NEW(Set);
|
||||
|
||||
if (allocation) {
|
||||
theSet->members = (Aword *)allocate(allocation * sizeof(theSet->members[0]));
|
||||
theSet->size = 0;
|
||||
theSet->allocated = allocation;
|
||||
}
|
||||
return theSet;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void initSets(SetInitEntry *initTable) {
|
||||
SetInitEntry *init;
|
||||
int i;
|
||||
|
||||
for (init = initTable; !isEndOfArray(init); init++) {
|
||||
Set *set = newSet(init->size);
|
||||
Aword *member = (Aword *)pointerTo(init->setAddress);
|
||||
for (i = 0; i < init->size; i++, member++)
|
||||
addToSet(set, *member);
|
||||
setInstanceAttribute(init->instanceCode, init->attributeCode, toAptr(set));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int setSize(Set *theSet) {
|
||||
return theSet->size;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void clearSet(Set *theSet) {
|
||||
theSet->size = 0;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Set *copySet(Set *theSet) {
|
||||
Set *nset = newSet(theSet->size);
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= theSet->size; i++)
|
||||
addToSet(nset, getSetMember(theSet, i));
|
||||
return nset;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Aword getSetMember(Set *theSet, Aint theMember) {
|
||||
if (theMember > theSet->size || theMember < 1)
|
||||
apperr("Accessing nonexisting member in a set");
|
||||
return theSet->members[theMember - 1];
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool inSet(Set *theSet, Aword member) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= theSet->size; i++)
|
||||
if (getSetMember(theSet, i) == member)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
Set *setUnion(Set *set1, Set *set2) {
|
||||
Set *theUnion = newSet(set1->size + set2->size);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < set1->size; i++)
|
||||
addToSet(theUnion, set1->members[i]);
|
||||
for (i = 0; i < set2->size; i++)
|
||||
addToSet(theUnion, set2->members[i]);
|
||||
return theUnion;
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
void addToSet(Set *theSet, Aword newMember) {
|
||||
if (inSet(theSet, newMember)) return;
|
||||
if (theSet->size == theSet->allocated) {
|
||||
theSet->allocated += EXTENT;
|
||||
theSet->members = (Aword *)realloc(theSet->members, theSet->allocated * sizeof(theSet->members[0]));
|
||||
}
|
||||
theSet->members[theSet->size] = newMember;
|
||||
theSet->size++;
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
void removeFromSet(Set *theSet, Aword member) {
|
||||
int i, j;
|
||||
|
||||
if (!inSet(theSet, member)) return;
|
||||
|
||||
for (i = 0; i < theSet->size; i++) {
|
||||
if ((Aword)theSet->members[i] == member) {
|
||||
for (j = i; j < theSet->size - 1; j++)
|
||||
theSet->members[j] = theSet->members[j + 1];
|
||||
theSet->size--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
bool equalSets(Set *set1, Set *set2) {
|
||||
int i;
|
||||
|
||||
if (set1->size != set2->size) return FALSE;
|
||||
|
||||
for (i = 0; i < set1->size; i++) {
|
||||
if (!inSet(set2, set1->members[i]))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void freeSet(Set *theSet) {
|
||||
if (theSet != nullptr) {
|
||||
if (theSet->members != nullptr)
|
||||
deallocate(theSet->members);
|
||||
deallocate(theSet);
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
63
engines/glk/alan3/set.h
Normal file
63
engines/glk/alan3/set.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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_ALAN3_SET
|
||||
#define GLK_ALAN3_SET
|
||||
|
||||
/* Abstract datatype Set for Alan interpreter
|
||||
|
||||
A set is implemented as a struct holding a size and a
|
||||
dynamically allocated array of members. Members can be
|
||||
integers or instance numbers. Attributes of Set type is
|
||||
allocated and the pointer to it is used as the attribute
|
||||
value. As members are only references, clearing a set can
|
||||
simply be done by setting the size to zero.
|
||||
*/
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
struct Set {
|
||||
int size;
|
||||
int allocated;
|
||||
Aword *members;
|
||||
};
|
||||
|
||||
extern Set *newSet(int size);
|
||||
extern void initSets(SetInitEntry *initTable);
|
||||
extern int setSize(Set *theSet);
|
||||
extern void clearSet(Set *theSet);
|
||||
extern Set *copySet(Set *theSet);
|
||||
extern Aword getSetMember(Set *theSet, Aint member);
|
||||
extern bool inSet(Set *theSet, Aword member);
|
||||
extern void addToSet(Set *theSet, Aword newMember);
|
||||
extern void removeFromSet(Set *theSet, Aword member);
|
||||
extern Set *setUnion(Set *theSet, Set *other);
|
||||
extern bool equalSets(Set *theSet, Set *other);
|
||||
extern void freeSet(Set *theSet);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
174
engines/glk/alan3/stack.cpp
Normal file
174
engines/glk/alan3/stack.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/* 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/alan3/stack.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*======================================================================*/
|
||||
Stack createStack(int size) {
|
||||
StackStructure *theStack = NEW(StackStructure);
|
||||
|
||||
theStack->stack = (Aword *)allocate(size * sizeof(Aptr));
|
||||
theStack->stackSize = size;
|
||||
theStack->framePointer = -1;
|
||||
|
||||
return theStack;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void deleteStack(Stack theStack) {
|
||||
if (theStack == nullptr)
|
||||
syserr("deleting a NULL stack");
|
||||
|
||||
deallocate(theStack->stack);
|
||||
deallocate(theStack);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
int stackDepth(Stack theStack) {
|
||||
return theStack->stackp;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void dumpStack(Stack theStack) {
|
||||
int i;
|
||||
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
printf("[");
|
||||
for (i = 0; i < theStack->stackp; i++)
|
||||
printf("%ld ", (unsigned long) theStack->stack[i]);
|
||||
printf("]");
|
||||
if (!traceInstructionOption && !tracePushOption)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void push(Stack theStack, Aptr i) {
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
if (theStack->stackp == theStack->stackSize)
|
||||
syserr("Out of stack space.");
|
||||
theStack->stack[(theStack->stackp)++] = i;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Aptr pop(Stack theStack) {
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
if (theStack->stackp == 0)
|
||||
syserr("Stack underflow.");
|
||||
return theStack->stack[--(theStack->stackp)];
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
Aptr top(Stack theStack) {
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
return theStack->stack[theStack->stackp - 1];
|
||||
}
|
||||
|
||||
|
||||
/* The AMACHINE Block Frames */
|
||||
|
||||
/*======================================================================*/
|
||||
void newFrame(Stack theStack, Aint noOfLocals) {
|
||||
int n;
|
||||
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
push(theStack, theStack->framePointer);
|
||||
theStack->framePointer = theStack->stackp;
|
||||
for (n = 0; n < noOfLocals; n++)
|
||||
push(theStack, 0);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
/* Local variables are numbered 1 and up and stored on their index-1 */
|
||||
Aptr getLocal(Stack theStack, Aint framesBelow, Aint variableNumber) {
|
||||
int frame;
|
||||
int frameCount;
|
||||
|
||||
if (variableNumber < 1)
|
||||
syserr("Reading a non-existing block-local variable.");
|
||||
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
frame = theStack->framePointer;
|
||||
|
||||
if (framesBelow != 0)
|
||||
for (frameCount = framesBelow; frameCount != 0; frameCount--)
|
||||
frame = theStack->stack[frame - 1];
|
||||
|
||||
return theStack->stack[frame + variableNumber - 1];
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void setLocal(Stack theStack, Aint framesBelow, Aint variableNumber, Aptr value) {
|
||||
int frame;
|
||||
int frameCount;
|
||||
|
||||
if (variableNumber < 1)
|
||||
syserr("Writing a non-existing block-local variable.");
|
||||
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
frame = theStack->framePointer;
|
||||
if (framesBelow != 0)
|
||||
for (frameCount = framesBelow; frameCount != 0; frameCount--)
|
||||
frame = theStack->stack[frame - 1];
|
||||
|
||||
theStack->stack[frame + variableNumber - 1] = value;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void endFrame(Stack theStack) {
|
||||
if (theStack == nullptr)
|
||||
syserr("NULL stack not supported anymore");
|
||||
|
||||
theStack->stackp = theStack->framePointer;
|
||||
theStack->framePointer = pop(theStack);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
61
engines/glk/alan3/stack.h
Normal file
61
engines/glk/alan3/stack.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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_ALAN3_STACK
|
||||
#define GLK_ALAN3_STACK
|
||||
|
||||
/* Header file for stack handler in Alan interpreter */
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
struct StackStructure {
|
||||
Aword *stack; // Array that can take Awords
|
||||
int stackSize;
|
||||
int stackp;
|
||||
int framePointer;
|
||||
};
|
||||
|
||||
typedef StackStructure *Stack;
|
||||
|
||||
/* FUNCTIONS: */
|
||||
|
||||
/* NB: The stack uses Aptr size elements since we need to be able to store pointers to allocated memory */
|
||||
|
||||
extern Stack createStack(int size);
|
||||
extern void deleteStack(Stack stack);
|
||||
extern void dumpStack(Stack theStack);
|
||||
extern Aptr pop(Stack stack);
|
||||
extern void push(Stack stack, Aptr item);
|
||||
extern Aptr top(Stack theStack);
|
||||
extern int stackDepth(Stack theStack);
|
||||
|
||||
extern void newFrame(Stack theStack, Aint noOfLocals);
|
||||
extern void setLocal(Stack theStack, Aint blocksBelow, Aint variableNumber, Aptr value);
|
||||
extern Aptr getLocal(Stack theStack, Aint level, Aint variable);
|
||||
extern void endFrame(Stack theStack);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
357
engines/glk/alan3/state.cpp
Normal file
357
engines/glk/alan3/state.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
/* 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/alan3/state.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/word.h"
|
||||
#include "glk/alan3/state_stack.h"
|
||||
#include "glk/alan3/instance.h"
|
||||
#include "glk/alan3/attribute.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/score.h"
|
||||
#include "glk/alan3/event.h"
|
||||
#include "glk/alan3/set.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PRIVATE TYPES */
|
||||
|
||||
/* Implementation of the abstract type typedef struct game_state GameState */
|
||||
struct game_state {
|
||||
/* Event queue */
|
||||
EventQueueEntry *eventQueue;
|
||||
int eventQueueTop; /* Event queue top pointer */
|
||||
|
||||
/* Scores */
|
||||
int score;
|
||||
Aword *scores; /* Score table pointer */
|
||||
|
||||
/* Instance data */
|
||||
AdminEntry *admin; /* Administrative data about instances */
|
||||
AttributeEntry *attributes; /* Attributes data area */
|
||||
/* Sets and strings are dynamically allocated areas for which the
|
||||
attribute is just a pointer to. So they are not catched by the
|
||||
saving of attributes, instead they require special storage */
|
||||
Set **sets; /* Array of set pointers */
|
||||
char **strings; /* Array of string pointers */
|
||||
};
|
||||
|
||||
/* PRIVATE DATA */
|
||||
static GameState gameState; /* TODO: Make pointer, then we don't have to copy to stack, we can just use the pointer */
|
||||
static StateStackP stateStack = nullptr;
|
||||
|
||||
static char *playerCommand;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int countStrings(void) {
|
||||
StringInitEntry *entry;
|
||||
int count = 0;
|
||||
|
||||
if (header->stringInitTable != 0)
|
||||
for (entry = (StringInitEntry *)pointerTo(header->stringInitTable); * (Aword *)entry != EOD; entry++)
|
||||
count++;
|
||||
return (count);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void deallocateStrings(GameState *gState) {
|
||||
int count = countStrings();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
deallocate(gState->strings[i]);
|
||||
deallocate(gState->strings);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int countSets(void) {
|
||||
SetInitEntry *entry;
|
||||
int count = 0;
|
||||
|
||||
if (header->setInitTable != 0)
|
||||
for (entry = (SetInitEntry *)pointerTo(header->setInitTable); * (Aword *)entry != EOD; entry++)
|
||||
count++;
|
||||
return (count);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void deallocateSets(GameState *gState) {
|
||||
int count = countSets();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
freeSet(gState->sets[i]);
|
||||
deallocate(gState->sets);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void deallocateGameState(GameState *gState) {
|
||||
|
||||
deallocate(gState->admin);
|
||||
deallocate(gState->attributes);
|
||||
|
||||
if (gState->eventQueueTop > 0) {
|
||||
deallocate(gState->eventQueue);
|
||||
gState->eventQueue = nullptr;
|
||||
}
|
||||
if (gState->scores)
|
||||
deallocate(gState->scores);
|
||||
|
||||
deallocateStrings(gState);
|
||||
deallocateSets(gState);
|
||||
|
||||
memset(gState, 0, sizeof(GameState));
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void forgetGameState(void) {
|
||||
char *playerCmd;
|
||||
popGameState(stateStack, &gameState, &playerCmd);
|
||||
deallocateGameState(&gameState);
|
||||
if (playerCmd != nullptr)
|
||||
deallocate(playerCmd);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void initStateStack(void) {
|
||||
if (stateStack != nullptr)
|
||||
deleteStateStack(stateStack);
|
||||
stateStack = createStateStack(sizeof(GameState));
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void terminateStateStack(void) {
|
||||
deleteStateStack(stateStack);
|
||||
stateStack = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool anySavedState(void) {
|
||||
return !stateStackIsEmpty(stateStack);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static Set **collectSets(void) {
|
||||
SetInitEntry *entry;
|
||||
int count = countSets();
|
||||
Set **sets;
|
||||
int i;
|
||||
|
||||
if (count == 0) return nullptr;
|
||||
|
||||
sets = (Set **)allocate(count * sizeof(Set));
|
||||
|
||||
entry = (SetInitEntry *)pointerTo(header->setInitTable);
|
||||
for (i = 0; i < count; i++)
|
||||
sets[i] = getInstanceSetAttribute(entry[i].instanceCode, entry[i].attributeCode);
|
||||
|
||||
return sets;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static char **collectStrings(void) {
|
||||
StringInitEntry *entry;
|
||||
int count = countStrings();
|
||||
char **strings;
|
||||
int i;
|
||||
|
||||
if (count == 0) return nullptr;
|
||||
|
||||
strings = (char **)allocate(count * sizeof(char *));
|
||||
|
||||
entry = (StringInitEntry *)pointerTo(header->stringInitTable);
|
||||
for (i = 0; i < count; i++)
|
||||
strings[i] = getInstanceStringAttribute(entry[i].instanceCode, entry[i].attributeCode);
|
||||
|
||||
return strings;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void rememberCommands(void) {
|
||||
char *command = playerWordsAsCommandString();
|
||||
attachPlayerCommandsToLastState(stateStack, command);
|
||||
deallocate(command);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void collectEvents(void) {
|
||||
gameState.eventQueueTop = eventQueueTop;
|
||||
if (eventQueueTop > 0)
|
||||
gameState.eventQueue = (EventQueueEntry *)duplicate(eventQueue, eventQueueTop * sizeof(EventQueueEntry));
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void collectInstanceData(void) {
|
||||
gameState.admin = (AdminEntry *)duplicate(admin, (header->instanceMax + 1) * sizeof(AdminEntry));
|
||||
gameState.attributes = (AttributeEntry *)duplicate(attributes, header->attributesAreaSize * sizeof(Aword));
|
||||
gameState.sets = collectSets();
|
||||
gameState.strings = collectStrings();
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void collectScores(void) {
|
||||
gameState.score = current.score;
|
||||
if (scores == nullptr)
|
||||
gameState.scores = nullptr;
|
||||
else
|
||||
gameState.scores = (Aword *)duplicate(scores, header->scoreCount * sizeof(Aword));
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void rememberGameState(void) {
|
||||
collectEvents();
|
||||
collectInstanceData();
|
||||
collectScores();
|
||||
|
||||
if (stateStack == nullptr)
|
||||
initStateStack();
|
||||
|
||||
pushGameState(stateStack, &gameState);
|
||||
gameStateChanged = FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void freeCurrentSetAttributes(void) {
|
||||
SetInitEntry *entry;
|
||||
|
||||
if (header->setInitTable == 0) return;
|
||||
for (entry = (SetInitEntry *)pointerTo(header->setInitTable); * (Aword *)entry != EOD; entry++) {
|
||||
Aptr attributeValue = getAttribute(admin[entry->instanceCode].attributes, entry->attributeCode);
|
||||
freeSet((Set *)fromAptr(attributeValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void recallSets(Set **sets) {
|
||||
SetInitEntry *entry;
|
||||
int count = countSets();
|
||||
int i;
|
||||
|
||||
if (header->setInitTable == 0) return;
|
||||
|
||||
entry = (SetInitEntry *)pointerTo(header->setInitTable);
|
||||
for (i = 0; i < count; i++) {
|
||||
setAttribute(admin[entry[i].instanceCode].attributes, entry[i].attributeCode, toAptr(sets[i]));
|
||||
sets[i] = nullptr; /* Since we reuse the saved set, we need to clear the pointer */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void freeCurrentStringAttributes(void) {
|
||||
StringInitEntry *entry;
|
||||
|
||||
if (header->stringInitTable == 0) return;
|
||||
for (entry = (StringInitEntry *)pointerTo(header->stringInitTable); * (Aword *)entry != EOD; entry++) {
|
||||
Aptr attributeValue = getAttribute(admin[entry->instanceCode].attributes, entry->attributeCode);
|
||||
deallocate(fromAptr(attributeValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void recallStrings(char **strings) {
|
||||
StringInitEntry *entry;
|
||||
int count = countStrings();
|
||||
int i;
|
||||
|
||||
if (header->stringInitTable == 0) return;
|
||||
|
||||
entry = (StringInitEntry *)pointerTo(header->stringInitTable);
|
||||
for (i = 0; i < count; i++) {
|
||||
setAttribute(admin[entry[i].instanceCode].attributes, entry[i].attributeCode, toAptr(strings[i]));
|
||||
strings[i] = nullptr; /* Since we reuse the saved, we need to clear the state */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void recallEvents(void) {
|
||||
eventQueueTop = gameState.eventQueueTop;
|
||||
if (eventQueueTop > 0) {
|
||||
memcpy(eventQueue, gameState.eventQueue,
|
||||
(eventQueueTop + 1)*sizeof(EventQueueEntry));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void recallInstances(void) {
|
||||
|
||||
if (admin == nullptr)
|
||||
syserr("admin[] == NULL in recallInstances()");
|
||||
|
||||
memcpy(admin, gameState.admin,
|
||||
(header->instanceMax + 1)*sizeof(AdminEntry));
|
||||
|
||||
freeCurrentSetAttributes(); /* Need to free previous set values */
|
||||
freeCurrentStringAttributes(); /* Need to free previous string values */
|
||||
|
||||
memcpy(attributes, gameState.attributes,
|
||||
header->attributesAreaSize * sizeof(Aword));
|
||||
|
||||
recallSets(gameState.sets);
|
||||
recallStrings(gameState.strings);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void recallScores(void) {
|
||||
current.score = gameState.score;
|
||||
memcpy(scores, gameState.scores, header->scoreCount * sizeof(Aword));
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void recallGameState(void) {
|
||||
popGameState(stateStack, &gameState, &playerCommand);
|
||||
recallEvents();
|
||||
recallInstances();
|
||||
recallScores();
|
||||
deallocateGameState(&gameState);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
char *recreatePlayerCommand(void) {
|
||||
return playerCommand;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
50
engines/glk/alan3/state.h
Normal file
50
engines/glk/alan3/state.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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_ALAN3_STATE
|
||||
#define GLK_ALAN3_STATE
|
||||
|
||||
/* Header file for instruction state and undo handling in Alan interpreter */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
struct game_state;
|
||||
typedef struct game_state GameState;
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern bool anySavedState(void);
|
||||
extern void initStateStack(void);
|
||||
extern void rememberGameState(void);
|
||||
extern void forgetGameState(void);
|
||||
extern void rememberCommands(void);
|
||||
extern void recallGameState(void);
|
||||
extern char *recreatePlayerCommand(void);
|
||||
extern void terminateStateStack(void);
|
||||
extern void deallocateGameState(GameState *gameState);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
125
engines/glk/alan3/state_stack.cpp
Normal file
125
engines/glk/alan3/state_stack.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/* 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/alan3/state_stack.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/state.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* CONSTANTS: */
|
||||
#define EXTENT 10
|
||||
|
||||
|
||||
/* PRIVATE TYPES: */
|
||||
struct StateStackStructure {
|
||||
void **states;
|
||||
char **commands;
|
||||
int stackSize;
|
||||
int stackPointer; /* Points above used stack, 0 initially */
|
||||
int elementSize; /* Size of elements in the stack */
|
||||
};
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void *reallocate(void *from, int newSize) {
|
||||
void *newArea = realloc(from, newSize * sizeof(void *));
|
||||
if (newArea == nullptr)
|
||||
syserr("Out of memory in 'reallocateStack()'");
|
||||
return newArea;
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
StateStackP createStateStack(int elementSize) {
|
||||
StateStackP stack = NEW(StateStackStructure);
|
||||
stack->stackSize = 0;
|
||||
stack->stackPointer = 0;
|
||||
stack->elementSize = elementSize;
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void deleteStateStack(StateStackP stateStack) {
|
||||
if (stateStack != nullptr) {
|
||||
while (stateStack->stackPointer > 0) {
|
||||
stateStack->stackPointer--;
|
||||
deallocateGameState((GameState *)stateStack->states[stateStack->stackPointer]);
|
||||
deallocate(stateStack->states[stateStack->stackPointer]);
|
||||
deallocate(stateStack->commands[stateStack->stackPointer]);
|
||||
}
|
||||
if (stateStack->stackSize > 0) {
|
||||
deallocate(stateStack->states);
|
||||
deallocate(stateStack->commands);
|
||||
}
|
||||
deallocate(stateStack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
bool stateStackIsEmpty(StateStackP stateStack) {
|
||||
return stateStack->stackPointer == 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void ensureSpaceForGameState(StateStackP stack) {
|
||||
if (stack->stackPointer == stack->stackSize) {
|
||||
stack->states = (void **)reallocate(stack->states, stack->stackSize + EXTENT);
|
||||
stack->commands = (char **)reallocate(stack->commands, stack->stackSize + EXTENT);
|
||||
stack->stackSize += EXTENT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void pushGameState(StateStackP stateStack, void *gameState) {
|
||||
void *element = allocate(stateStack->elementSize);
|
||||
memcpy(element, gameState, stateStack->elementSize);
|
||||
ensureSpaceForGameState(stateStack);
|
||||
stateStack->commands[stateStack->stackPointer] = nullptr;
|
||||
stateStack->states[stateStack->stackPointer++] = element;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void attachPlayerCommandsToLastState(StateStackP stateStack, char *playerCommands) {
|
||||
stateStack->commands[stateStack->stackPointer - 1] = scumm_strdup(playerCommands);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void popGameState(StateStackP stateStack, void *gameState, char **playerCommand) {
|
||||
if (stateStack->stackPointer == 0)
|
||||
syserr("Popping GameState from empty stack");
|
||||
else {
|
||||
stateStack->stackPointer--;
|
||||
memcpy(gameState, stateStack->states[stateStack->stackPointer], stateStack->elementSize);
|
||||
deallocate(stateStack->states[stateStack->stackPointer]);
|
||||
*playerCommand = stateStack->commands[stateStack->stackPointer];
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
44
engines/glk/alan3/state_stack.h
Normal file
44
engines/glk/alan3/state_stack.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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_ALAN3_STATE_STACK
|
||||
#define GLK_ALAN3_STATE_STACK
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* TYPES */
|
||||
typedef struct StateStackStructure *StateStackP;
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern StateStackP createStateStack(int elementSize);
|
||||
extern bool stateStackIsEmpty(StateStackP stateStack);
|
||||
extern void pushGameState(StateStackP stateStack, void *state);
|
||||
extern void popGameState(StateStackP stateStack, void *state, char **playerCommandPointer);
|
||||
extern void attachPlayerCommandsToLastState(StateStackP stateStack, char *playerCommand);
|
||||
extern void deleteStateStack(StateStackP stateStack);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
94
engines/glk/alan3/syntax.cpp
Normal file
94
engines/glk/alan3/syntax.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/* 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/alan3/syntax.h"
|
||||
#include "glk/alan3/word.h"
|
||||
#include "glk/alan3/msg.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/compatibility.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
SyntaxEntry *stxs; /* Syntax table pointer */
|
||||
|
||||
|
||||
/* PRIVATE TYPES & DATA */
|
||||
|
||||
|
||||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
/*======================================================================*/
|
||||
ElementEntry *elementTreeOf(SyntaxEntry *stx) {
|
||||
return (ElementEntry *) pointerTo(stx->elms);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static SyntaxEntry *findSyntaxEntryForPreBeta2(int verbCode, SyntaxEntry *foundStx) {
|
||||
SyntaxEntryPreBeta2 *stx;
|
||||
for (stx = (SyntaxEntryPreBeta2 *)stxs; !isEndOfArray(stx); stx++)
|
||||
if (stx->code == verbCode) {
|
||||
foundStx = (SyntaxEntry *)stx;
|
||||
break;
|
||||
}
|
||||
return (foundStx);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static SyntaxEntry *findSyntaxEntry(int verbCode) {
|
||||
SyntaxEntry *stx;
|
||||
for (stx = stxs; !isEndOfArray(stx); stx++)
|
||||
if (stx->code == verbCode) {
|
||||
return stx;
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
SyntaxEntry *findSyntaxTreeForVerb(CONTEXT, int verbCode) {
|
||||
SyntaxEntry *foundStx = nullptr;
|
||||
if (isPreBeta2(header->version)) {
|
||||
foundStx = findSyntaxEntryForPreBeta2(verbCode, foundStx);
|
||||
} else {
|
||||
foundStx = findSyntaxEntry(verbCode);
|
||||
}
|
||||
if (foundStx == nullptr)
|
||||
// No matching syntax
|
||||
R0CALL1(error, M_WHAT)
|
||||
return foundStx;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
char *parameterNameInSyntax(int syntaxNumber, int parameterNumber) {
|
||||
Aaddr adr = addressAfterTable(header->parameterMapAddress, sizeof(ParameterMapEntry));
|
||||
Aaddr *syntaxParameterNameTable = (Aaddr *)pointerTo(memory[adr]);
|
||||
Aaddr *parameterNameTable = (Aaddr *)pointerTo(syntaxParameterNameTable[syntaxNumber - 1]);
|
||||
return stringAt(parameterNameTable[parameterNumber - 1]);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
44
engines/glk/alan3/syntax.h
Normal file
44
engines/glk/alan3/syntax.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* 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_ALAN3_SYNTAX
|
||||
#define GLK_ALAN3_SYNTAX
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/jumps.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* DATA */
|
||||
extern SyntaxEntry *stxs; /* Syntax table pointer */
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern ElementEntry *elementTreeOf(SyntaxEntry *stx);
|
||||
extern char *parameterNameInSyntax(int syntaxNumber, int parameterNumber);
|
||||
extern SyntaxEntry *findSyntaxTreeForVerb(CONTEXT, int verbCode);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
332
engines/glk/alan3/sysdep.cpp
Normal file
332
engines/glk/alan3/sysdep.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
/* 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/alan3/sysdep.h"
|
||||
#include "glk/alan3/alan3.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* 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 .A3C 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 const byte spaceCharacters[] = {
|
||||
0x0A, /* linefeed */
|
||||
0x20, /* space */
|
||||
0xA0, /* non-breaking space */
|
||||
0x00
|
||||
};
|
||||
|
||||
static const byte lowerCaseCharacters[] = {
|
||||
0x61, /* a */ 0x62, /* b */ 0x63, /* c */ 0x64, /* d */
|
||||
0x65, /* e */ 0x66, /* f */ 0x67, /* g */ 0x68, /* h */
|
||||
0x69, /* i */ 0x6A, /* j */ 0x6B, /* k */ 0x6C, /* l */
|
||||
0x6D, /* m */ 0x6E, /* n */ 0x6F, /* o */ 0x70, /* p */
|
||||
0x71, /* q */ 0x72, /* r */ 0x73, /* s */ 0x74, /* t */
|
||||
0x75, /* u */ 0x76, /* v */ 0x77, /* w */ 0x78, /* x */
|
||||
0x79, /* y */ 0x7A, /* z */ 0xDF, /* ss <small sharp s> */
|
||||
0xE0, /* a grave */ 0xE1, /* a acute */
|
||||
0xE2, /* a circumflex */ 0xE3, /* a tilde */
|
||||
0xE4, /* a diaeresis */ 0xE5, /* a ring */
|
||||
0xE6, /* ae */ 0xE7, /* c cedilla */
|
||||
0xE8, /* e grave */ 0xE9, /* e acute */
|
||||
0xEA, /* e circumflex */ 0xEB, /* e diaeresis */
|
||||
0xEC, /* i grave */ 0xED, /* i acute */
|
||||
0xEE, /* i circumflex */ 0xEF, /* i diaeresis */
|
||||
0xF0, /* <small eth> */ 0xF1, /* n tilde */
|
||||
0xF2, /* o grave */ 0xF3, /* o acute */
|
||||
0xF4, /* o circumflex */ 0xF5, /* o tilde */
|
||||
0xF6, /* o diaeresis */ 0xF8, /* o slash */
|
||||
0xF9, /* u grave */ 0xFA, /* u acute */
|
||||
0xFB, /* u circumflex */ 0xFC, /* u diaeresis */
|
||||
0xFD, /* y acute */ 0xFE, /* <small thorn> */
|
||||
0xFF, /* y diaeresis */ 0x00
|
||||
};
|
||||
|
||||
/* FIXME: ss <small sharp s> and y diaeresis have no UC analogues
|
||||
Are they really considered LC?
|
||||
*/
|
||||
|
||||
static const byte upperCaseCharacters[] = {
|
||||
0x41, /* A */ 0x42, /* B */ 0x43, /* C */ 0x44, /* D */
|
||||
0x45, /* E */ 0x46, /* F */ 0x47, /* G */ 0x48, /* H */
|
||||
0x49, /* I */ 0x4A, /* J */ 0x4B, /* K */ 0x4C, /* L */
|
||||
0x4D, /* M */ 0x4E, /* N */ 0x4F, /* O */ 0x50, /* P */
|
||||
0x51, /* Q */ 0x52, /* R */ 0x53, /* S */ 0x54, /* T */
|
||||
0x55, /* U */ 0x56, /* V */ 0x57, /* W */ 0x58, /* X */
|
||||
0x59, /* Y */ 0x5A, /* Z */
|
||||
0xC0, /* A grave */ 0xC1, /* A acute */
|
||||
0xC2, /* A circumflex */ 0xC3, /* A tilde */
|
||||
0xC4, /* A diaeresis */ 0xC5, /* A ring */
|
||||
0xC6, /* AE */ 0xC7, /* C cedilla */
|
||||
0xC8, /* E grave */ 0xC9, /* E acute */
|
||||
0xCA, /* E circumflex */ 0xCB, /* E diaeresis */
|
||||
0xCC, /* I grave */ 0xCD, /* I acute */
|
||||
0xCE, /* I circumflex */ 0xCF, /* I diaeresis */
|
||||
0xD0, /* <capital eth> */ 0xD1, /* N tilde */
|
||||
0xD2, /* O grave */ 0xD3, /* O acute */
|
||||
0xD4, /* O circumflex */ 0xD5, /* O tilde */
|
||||
0xD6, /* O diaeresis */ 0xD8, /* O slash */
|
||||
0xD9, /* U grave */ 0xDA, /* U acute */
|
||||
0xDB, /* U circumflex */ 0xDC, /* U diaeresis */
|
||||
0xDD, /* Y acute */ 0xDE, /* <capital thorn> */
|
||||
0x00
|
||||
};
|
||||
|
||||
|
||||
int isSpace(unsigned int c) {
|
||||
return (c != '\0' && strchr((const char *)spaceCharacters, c) != nullptr);
|
||||
}
|
||||
|
||||
|
||||
int isLower(unsigned int c) {
|
||||
return (c != '\0' && strchr((const char *)lowerCaseCharacters, c) != nullptr);
|
||||
}
|
||||
|
||||
|
||||
int isUpper(unsigned int c) {
|
||||
return (c != '\0' && strchr((const char *)upperCaseCharacters, c) != nullptr);
|
||||
}
|
||||
|
||||
int isLetter(unsigned int c) {
|
||||
return (c != '\0' && (isLower(c) ? !0 : isUpper(c)));
|
||||
}
|
||||
|
||||
|
||||
int toLower(unsigned int c) {
|
||||
return g_vm->glk_char_to_lower(c);
|
||||
}
|
||||
|
||||
int toUpper(unsigned int c) {
|
||||
return g_vm->glk_char_to_upper(c);
|
||||
}
|
||||
|
||||
char *strlow(char str[]) {
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = toLower(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
char *strupp(char str[]) {
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = toUpper(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
/* The following work on ISO characters */
|
||||
|
||||
int isLowerCase(unsigned int c) {
|
||||
uint i;
|
||||
for (i = 0; i < strlen((const char *)lowerCaseCharacters); i++)
|
||||
if (((unsigned int)lowerCaseCharacters[i]) == c) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int isUpperCase(unsigned int c) {
|
||||
uint i;
|
||||
for (i = 0; i < strlen((const char *)upperCaseCharacters); i++)
|
||||
if (upperCaseCharacters[i] == c) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int isISOLetter(int c) {
|
||||
return (isLowerCase(c) || isUpperCase(c));
|
||||
}
|
||||
|
||||
|
||||
char IsoToLowerCase(int c) {
|
||||
return (isUpperCase(c) ? c + ('a' - 'A') : c);
|
||||
}
|
||||
|
||||
|
||||
char IsoToUpperCase(int c) {
|
||||
return (isLowerCase(c) ? c - ('a' - 'A') : c);
|
||||
}
|
||||
|
||||
|
||||
char *stringLower(char str[]) {
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = IsoToLowerCase(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
char *stringUpper(char str[]) {
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++)
|
||||
*s = IsoToUpperCase(*s);
|
||||
return (str);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
int compareStrings(char *str1, char *str2) {
|
||||
char *s1 = str1, *s2 = str2;
|
||||
|
||||
while (*s1 != '\0' && *s2 != '\0') {
|
||||
if (IsoToLowerCase(*s1) < IsoToLowerCase(*s2)) return -1;
|
||||
if (IsoToLowerCase(*s1) > IsoToLowerCase(*s2)) return 1;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return IsoToLowerCase(*s2) - IsoToLowerCase(*s1);
|
||||
}
|
||||
|
||||
|
||||
#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 const 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 const 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[], char original[]) {
|
||||
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.
|
||||
copy - Mapped string
|
||||
original - string to convert
|
||||
charset - the current character set
|
||||
*/
|
||||
void toNative(char copy[], char original[], int charset) {
|
||||
toIso(copy, original, charset);
|
||||
if (NATIVECHARSET != 0)
|
||||
fromIso(copy, copy);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
char *baseNameStart(char *fullPathName) {
|
||||
const char *delimiters = "\\>]/:";
|
||||
int i;
|
||||
|
||||
for (i = strlen(fullPathName) - 1; i > 0; i--)
|
||||
if (strchr(delimiters, fullPathName[i]) != nullptr)
|
||||
return &fullPathName[i + 1];
|
||||
return (fullPathName);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
121
engines/glk/alan3/sysdep.h
Normal file
121
engines/glk/alan3/sysdep.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/* 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_ALAN3_SYSDEP
|
||||
#define GLK_ALAN3_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 and version (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/util.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
#define GLK
|
||||
#define HAVE_GLK
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
Below follows OS and compiler dependent settings. They should not be
|
||||
changed except for introducing new sections when porting to new
|
||||
environments.
|
||||
|
||||
*/
|
||||
|
||||
/***********************/
|
||||
/* ISO character sets? */
|
||||
/***********************/
|
||||
|
||||
/* Common case first */
|
||||
#define ISO 1
|
||||
#define NATIVECHARSET 0
|
||||
|
||||
#undef ISO
|
||||
#define ISO 1
|
||||
#undef NATIVECHARSET
|
||||
#define NATIVECHARSET 0
|
||||
|
||||
/**************************/
|
||||
/* Strings for file modes */
|
||||
/**************************/
|
||||
#define READ_MODE "rb"
|
||||
#define WRITE_MODE "wb"
|
||||
|
||||
|
||||
/****************/
|
||||
|
||||
/* don't need TERMIO */
|
||||
#undef HAVE_TERMIO
|
||||
/* don't need ANSI */
|
||||
#undef HAVE_ANSI
|
||||
|
||||
#define USE_READLINE
|
||||
|
||||
|
||||
/* Native character functions */
|
||||
extern int isSpace(unsigned int c); /* IN - Native character to test */
|
||||
extern int isLower(unsigned int c); /* IN - Native character to test */
|
||||
extern int isUpper(unsigned int c); /* IN - Native character to test */
|
||||
extern int isLetter(unsigned int c); /* IN - Native character to test */
|
||||
extern int toLower(unsigned int c); /* IN - Native character to convert */
|
||||
extern int toUpper(unsigned 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 IsoToLowerCase(int c); /* IN - ISO character to convert */
|
||||
extern char IsoToUpperCase(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 */
|
||||
extern int compareStrings(char str1[], char str2[]); /* Case-insensitive compare */
|
||||
|
||||
#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
|
||||
|
||||
extern char *baseNameStart(char *fullPathName);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
103
engines/glk/alan3/syserr.cpp
Normal file
103
engines/glk/alan3/syserr.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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/alan3/syserr.h"
|
||||
#include "glk/alan3/current.h"
|
||||
#include "glk/alan3/debug.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/utils.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
static void (*handler)(const char *);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void runtimeError(CONTEXT, const char *errorClassification, const char *errorDescription, const char *blurb) {
|
||||
output("$n$nAs you enter the twilight zone of Adventures, you stumble \
|
||||
and fall to your knees. In front of you, you can vaguely see the outlines \
|
||||
of an Adventure that never was.$n$n");
|
||||
output(errorClassification);
|
||||
output(errorDescription);
|
||||
newline();
|
||||
|
||||
if (current.sourceLine != 0) {
|
||||
printf("At source line %d in '%s':\n", current.sourceLine, sourceFileName(current.sourceFile));
|
||||
printf("%s", readSourceLine(current.sourceFile, current.sourceLine));
|
||||
}
|
||||
|
||||
newline();
|
||||
output(blurb);
|
||||
|
||||
terminate(context, 2);
|
||||
}
|
||||
|
||||
static void runtimeError(const char *errorClassification, const char *errorDescription, const char *blurb) {
|
||||
::error("%s%s %s", errorClassification, errorDescription, blurb);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void setSyserrHandler(void (*f)(const char *)) {
|
||||
handler = f;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
// TODO Make syserr() use ... as printf()
|
||||
void syserr(const char *description) {
|
||||
lin = 0;
|
||||
if (handler == nullptr) {
|
||||
const char *blurb = "<If you are the creator of this piece of Interactive Fiction, \
|
||||
please help debug this Alan system error. Collect *all* the sources, and, if possible, an \
|
||||
exact transcript of the commands that led to this error, in a zip-file and send \
|
||||
it to support@alanif.se. Thank you!>";
|
||||
runtimeError("SYSTEM ERROR: ", description, blurb);
|
||||
} else
|
||||
handler(description);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void apperr(const char *description) {
|
||||
if (handler == nullptr) {
|
||||
const char *blurb = "<If you are playing this piece of Interactive Fiction, \
|
||||
please help the author to debug this programming error. Send an exact \
|
||||
transcript of the commands that led to this error to the author. Thank you! \
|
||||
If you *are* the author, then you have to figure this out before releasing the game.>";
|
||||
runtimeError("APPLICATION ERROR: ", description, blurb);
|
||||
} else
|
||||
handler(description);
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void playererr(CONTEXT, const char *description) {
|
||||
if (handler == nullptr) {
|
||||
const char *blurb = "<You have probably done something that is not exactly right.>";
|
||||
runtimeError(context, "PLAYER ERROR: ", description, blurb);
|
||||
} else
|
||||
handler(description);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
41
engines/glk/alan3/syserr.h
Normal file
41
engines/glk/alan3/syserr.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_ALAN3_SYSERR
|
||||
#define GLK_ALAN3_SYSERR
|
||||
|
||||
/* Header file for syserr unit of ARUN Alan System interpreter */
|
||||
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* Functions: */
|
||||
extern void syserr(const char *msg);
|
||||
extern void apperr(const char *msg);
|
||||
extern void playererr(CONTEXT, const char *msg);
|
||||
extern void setSyserrHandler(void (*handler)(const char *));
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
37
engines/glk/alan3/types.cpp
Normal file
37
engines/glk/alan3/types.cpp
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*======================================================================*/
|
||||
Aaddr addressAfterTable(Aaddr adr, int size) {
|
||||
while (!isEndOfArray(&memory[adr])) {
|
||||
adr += size / sizeof(Aword);
|
||||
}
|
||||
return adr + 1;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
75
engines/glk/alan3/types.h
Normal file
75
engines/glk/alan3/types.h
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN3_TYPES
|
||||
#define GLK_ALAN3_TYPES
|
||||
|
||||
/* Header file for the Alan interpreter module. */
|
||||
|
||||
#include "glk/alan3/sysdep.h"
|
||||
#include "glk/alan3/acode.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PREPROCESSOR */
|
||||
#define FORWARD
|
||||
#define NEW(type) ((type *)allocate(sizeof(type)))
|
||||
|
||||
|
||||
/* CONSTANTS */
|
||||
|
||||
#define HERO (header->theHero)
|
||||
#define ENTITY (header->entityClassId)
|
||||
#define OBJECT (header->objectClassId)
|
||||
#define LOCATION (header->locationClassId)
|
||||
#define THING (header->thingClassId)
|
||||
#define ACTOR (header->actorClassId)
|
||||
|
||||
#define MAXPARAMS (header->maxParameters)
|
||||
#define MAXINSTANCE (header->instanceMax)
|
||||
|
||||
#define pointerTo(x) ((void *)&memory[x])
|
||||
#define addressOf(x) ((((long)x)-((long)memory))/sizeof(Aword))
|
||||
#define stringAt(x) ((char *)pointerTo(x))
|
||||
|
||||
#define ASIZE(x) (sizeof(x)/sizeof(Aword))
|
||||
|
||||
/* The various tables */
|
||||
struct VerbEntry { /* VERB TABLE */
|
||||
Aint code; /* Code for the verb */
|
||||
Aaddr alts; /* Address to alternatives */
|
||||
};
|
||||
|
||||
struct LimitEntry { /* LIMIT Type */
|
||||
Aword atr; /* Attribute that limits */
|
||||
Aword val; /* And the limiting value */
|
||||
Aaddr stms; /* Statements if fail */
|
||||
};
|
||||
|
||||
/* Functions: */
|
||||
extern Aaddr addressAfterTable(Aaddr adr, int size);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
97
engines/glk/alan3/utils.cpp
Normal file
97
engines/glk/alan3/utils.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/* 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/alan3/utils.h"
|
||||
#include "glk/alan3/alan_version.h"
|
||||
#include "glk/alan3/glkio.h"
|
||||
#include "glk/alan3/options.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/output.h"
|
||||
#include "glk/alan3/exe.h"
|
||||
#include "glk/alan3/state.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
#include "glk/alan3/fnmatch.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/*======================================================================
|
||||
|
||||
terminate()
|
||||
|
||||
Terminate the execution of the adventure, e.g. close windows,
|
||||
return buffers...
|
||||
|
||||
*/
|
||||
void terminate(CONTEXT, int code) {
|
||||
newline();
|
||||
|
||||
terminateStateStack();
|
||||
|
||||
stopTranscript();
|
||||
|
||||
if (memory) {
|
||||
deallocate(memory);
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
g_io->glk_exit();
|
||||
LONG_JUMP
|
||||
}
|
||||
|
||||
/*======================================================================*/
|
||||
void printVersion(int buildNumber) {
|
||||
printf("Arun - Adventure Language Interpreter version %s", alan.version.string);
|
||||
if (buildNumber != 0) printf("-%d", buildNumber);
|
||||
printf(" (%s %s)", alan.date, alan.time);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void usage(const char *programName) {
|
||||
printVersion(0);
|
||||
printf("\n\nUsage:\n\n");
|
||||
printf(" %s [<switches>] <adventure>\n\n", programName);
|
||||
printf("where the possible optional switches are:\n");
|
||||
|
||||
g_io->glk_set_style(style_Preformatted);
|
||||
printf(" -v verbose mode\n");
|
||||
printf(" -l log transcript to a file\n");
|
||||
printf(" -c log player commands to a file\n");
|
||||
printf(" -n no Status Line\n");
|
||||
printf(" -d enter debug mode\n");
|
||||
printf(" -t[<n>] trace game execution, higher <n> gives more trace\n");
|
||||
printf(" -i ignore version and checksum errors\n");
|
||||
printf(" -r make regression test easier (don't timestamp, page break, randomize...)\n");
|
||||
g_io->glk_set_style(style_Normal);
|
||||
}
|
||||
|
||||
|
||||
#ifndef FNM_CASEFOLD
|
||||
#define FNM_CASEFOLD 0
|
||||
#endif
|
||||
/*======================================================================*/
|
||||
bool match(const char *pattern, char *input) {
|
||||
return fnmatch(pattern, input, FNM_CASEFOLD) == 0;
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
42
engines/glk/alan3/utils.h
Normal file
42
engines/glk/alan3/utils.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* 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_ALAN3_UTILS
|
||||
#define GLK_ALAN3_UTILS
|
||||
|
||||
/* Utility functions for the Alan interpreter */
|
||||
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/jumps.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* FUNCTIONS: */
|
||||
extern void terminate(CONTEXT, int code);
|
||||
extern void usage(const char *programName);
|
||||
extern void printVersion(int buildNumber);
|
||||
extern bool match(const char *pattern, char *input);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
57
engines/glk/alan3/version.h
Normal file
57
engines/glk/alan3/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_ALAN3_VERSION
|
||||
#define GLK_ALAN3_VERSION
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
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;
|
||||
Version version;
|
||||
};
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
81
engines/glk/alan3/word.cpp
Normal file
81
engines/glk/alan3/word.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* 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/alan3/word.h"
|
||||
#include "glk/alan3/types.h"
|
||||
#include "glk/alan3/memory.h"
|
||||
#include "glk/alan3/syserr.h"
|
||||
#include "glk/alan3/lists.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
/* PUBLIC DATA */
|
||||
|
||||
/* List of parsed words, index into dictionary */
|
||||
Word *playerWords = nullptr;
|
||||
int currentWordIndex; /* An index into the list of playerWords */
|
||||
int firstWord, lastWord; /* Index for the first and last words for this command */
|
||||
|
||||
/* Some variable for dynamically allocating the playerWords, which will happen in scan() */
|
||||
static int playerWordsLength = 0;
|
||||
#define PLAYER_WORDS_EXTENT 20
|
||||
|
||||
/* What did the user say? */
|
||||
int verbWord; /* The word he used as a verb, dictionary index */
|
||||
int verbWordCode; /* The code for that verb */
|
||||
|
||||
|
||||
/* PRIVATE TYPES & DATA */
|
||||
|
||||
|
||||
/*+++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
void ensureSpaceForPlayerWords(int size) {
|
||||
int newLength = playerWordsLength + PLAYER_WORDS_EXTENT;
|
||||
|
||||
if (playerWordsLength < size + 1) {
|
||||
playerWords = (Word *)realloc(playerWords, newLength * sizeof(Word));
|
||||
if (playerWords == nullptr)
|
||||
syserr("Out of memory in 'ensureSpaceForPlayerWords()'");
|
||||
playerWordsLength = newLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
char *playerWordsAsCommandString(void) {
|
||||
char *commandString;
|
||||
int size = playerWords[lastWord].end - playerWords[firstWord].start;
|
||||
commandString = (char *)allocate(size + 1);
|
||||
strncpy(commandString, playerWords[firstWord].start, size);
|
||||
commandString[size] = '\0';
|
||||
return commandString;
|
||||
}
|
||||
|
||||
|
||||
/*======================================================================*/
|
||||
void clearWordList(Word list[]) {
|
||||
implementationOfSetEndOfArray((Aword *)list);
|
||||
}
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
55
engines/glk/alan3/word.h
Normal file
55
engines/glk/alan3/word.h
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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_ALAN3_WORD
|
||||
#define GLK_ALAN3_WORD
|
||||
|
||||
namespace Glk {
|
||||
namespace Alan3 {
|
||||
|
||||
typedef struct WordEntry {
|
||||
int code; /* The dictionary index for that word */
|
||||
char *start; /* Where does it start */
|
||||
char *end; /* .. and end */
|
||||
} Word;
|
||||
|
||||
|
||||
/* DATA */
|
||||
|
||||
extern Word *playerWords; /* List of Parsed Word */
|
||||
extern int currentWordIndex; /* and an index into it */
|
||||
extern int firstWord;
|
||||
extern int lastWord;
|
||||
|
||||
extern int verbWord;
|
||||
extern int verbWordCode;
|
||||
|
||||
|
||||
|
||||
/* FUNCTIONS */
|
||||
extern void ensureSpaceForPlayerWords(int count);
|
||||
extern char *playerWordsAsCommandString(void);
|
||||
extern void clearWordList(Word *list);
|
||||
|
||||
} // End of namespace Alan3
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user