Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
/* 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 JACL {
#define MAX_WORDS 20
#define STACK_SIZE 20
#define MAX_UNDO 100
#define MAX_OBJECTS 1000
/* LOCATION ATTRIBUTE VALUES */
#define VISITED 1
#define DARK 2
#define ON_WATER 4
#define UNDER_WATER 8
#define WITHOUT_AIR 16
#define OUTDOORS 32
#define MID_AIR 64
#define TIGHT_ROPE 128
#define POLLUTED 256
#define SOLVED 512
#define MID_WATER 1024
#define DARKNESS 2048
#define MAPPED 4096
#define KNOWN 8192
/* OBJECT ATTRIBUTE VALUES */
#define CLOSED 1
#define LOCKED 2
#define DEAD 4
#define IGNITABLE 8
#define WORN 16
#define CONCEALING 32
#define LUMINOUS 64
#define WEARABLE 128
#define CLOSABLE 256
#define LOCKABLE 512
#define ANIMATE 1024
#define LIQUID 2048
#define CONTAINER 4096
#define SURFACE 8192
#define PLURAL 16384
#define FLAMMABLE 32768
#define BURNING 65536
#define LOCATION 131072
#define ON 262144
#define DAMAGED 524288
#define FEMALE 1048576
#define POSSESSIVE 2097152
#define OUT_OF_REACH 4194304
#define TOUCHED 8388608
#define SCORED 16777216
#define SITTING 33554432
#define NPC 67108864
#define DONE 134217728
#define GAS 268435456
#define NO_TAB 536870912
#define NOT_IMPORTANT 1073741824
/* LOCATION INTEGER ARRAY INDEXES */
#define NORTH_DIR 0
#define SOUTH_DIR 1
#define EAST_DIR 2
#define WEST_DIR 3
#define NORTHEAST_DIR 4
#define NORTHWEST_DIR 5
#define SOUTHEAST_DIR 6
#define SOUTHWEST_DIR 7
#define UP_DIR 8
#define DOWN_DIR 9
#define IN_DIR 10
#define OUT_DIR 11
/* ALL UP, THERE ARE 16 OBJECT ELEMENTS, THESE 6
ARE THE ONLY ONES ACCESSED BY THE INTERPRETER */
#define PARENT integer[0]
#define QUANTITY integer[1]
#define MASS integer[2]
#define BEARING integer[3]
#define VELOCITY integer[4]
#define X integer[14]
#define Y integer[15]
/* SYSTEM VARIABLES */
#define COMPASS integer_resolve("compass")
#define DESTINATION integer_resolve("destination")
#define TOTAL_MOVES integer_resolve("total_moves")
#define TIME integer_resolve("time")
#define SCORE integer_resolve("score")
#define INTERNAL_VERSION integer_resolve("internal_version")
#define DISPLAY_MODE integer_resolve("display_mode")
#define MAX_RAND integer_resolve("max_rand")
#define INTERRUPTED integer_resolve("interrupted")
#define SOUND_ENABLED integer_resolve("sound_enabled")
#define GRAPHICS_ENABLED integer_resolve("graphics_enabled")
#define TIMER_ENABLED integer_resolve("timer_enabled")
#define MULTI_PREFIX integer_resolve("multi_prefix")
#define NOTIFY integer_resolve("notify")
#define DEBUG integer_resolve("debug")
/* SYSTEM INTEGER CONSTANTS */
#define SOUND_SUPPORTED cinteger_resolve("sound_supported")
#define GRAPHICS_SUPPORTED cinteger_resolve("graphics_supported")
#define TIMER_SUPPORTED cinteger_resolve("timer_supported")
/* ABBREVIATIONS */
#define HELD player
#define HERE get_here()
/* CONSTANTS */
#define SYSTEM_ATTRIBUTE 0
#define USER_ATTRIBUTE 1
#define FALSE 0
#define TRUE 1
#define UNRESTRICT 0
#define RESTRICT 1
#define SEEK_SET 0
#define SEEK_END 2
#define SCENERY 100
#define HEAVY 99
#define NOWHERE 0
#define LOG_ONLY 0
#define PLUS_STDOUT 1
#define PLUS_STDERR 2
#define ONLY_STDERR 3
#define ONLY_STDOUT 4
#define INT_TYPE 1
#define STR_TYPE 2
#define CINT_TYPE 3
#define CSTR_TYPE 4
#define ATT_TYPE 5
#define OBJ_TYPE 6
#define CRI_NONE 0
#define CRI_ATTRIBUTE 1
#define CRI_USER_ATTRIBUTE 2
#define CRI_PARENT 3
#define CRI_SCOPE 4
#define BOLD 1
#define NOTE 2
#define INPUT 3
#define HEADER 4
#define SUBHEADER 5
#define REVERSE 6
#define PRE 7
} // End of namespace JACL
} // End of namespace Glk

105
engines/glk/jacl/csv.h Normal file
View File

@@ -0,0 +1,105 @@
/* 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 JACL_CSV
#define JACL_CSV
#include "common/stream.h"
namespace Glk {
namespace JACL {
#define CSV_MAJOR 3
#define CSV_MINOR 0
#define CSV_RELEASE 0
/* Error Codes */
#define CSV_SUCCESS 0
#define CSV_EPARSE 1 /* Parse error in strict mode */
#define CSV_ENOMEM 2 /* Out of memory while increasing buffer size */
#define CSV_ETOOBIG 3 /* Buffer larger than SIZE_MAX needed */
#define CSV_EINVALID 4 /* Invalid code,should never be received from csv_error*/
/* parser options */
#define CSV_STRICT 1 /* enable strict mode */
#define CSV_REPALL_NL 2 /* report all unquoted carriage returns and linefeeds */
#define CSV_STRICT_FINI 4 /* causes csv_fini to return CSV_EPARSE if last
field is quoted and doesn't containg ending
quote */
#define CSV_APPEND_NULL 8 /* Ensure that all fields are null-ternimated */
/* Character values */
#define CSV_TAB 0x09
#define CSV_SPACE 0x20
#define CSV_CR 0x0d
#define CSV_LF 0x0a
#define CSV_COMMA 0x2c
#define CSV_QUOTE 0x22
struct csv_parser {
int pstate; /* Parser state */
int quoted; /* Is the current field a quoted field? */
size_t spaces; /* Number of continious spaces after quote or in a non-quoted field */
unsigned char *entry_buf; /* Entry buffer */
size_t entry_pos; /* Current position in entry_buf (and current size of entry) */
size_t entry_size; /* Size of entry buffer */
int status; /* Operation status */
unsigned char options;
unsigned char quote_char;
unsigned char delim_char;
int (*is_space)(unsigned char);
int (*is_term)(unsigned char);
size_t blk_size;
void *(*malloc_func)(size_t);
void *(*realloc_func)(void *, size_t);
void (*free_func)(void *);
};
/* Function Prototypes */
int csv_init(struct csv_parser *p, unsigned char options);
int csv_fini(struct csv_parser *p, void (*cb1)(void *, size_t, void *), void (*cb2)(int, void *), void *data);
void csv_free(struct csv_parser *p);
int csv_error(struct csv_parser *p);
const char *csv_strerror(int error);
size_t csv_parse(struct csv_parser *p, const void *s, size_t len, void (*cb1)(void *, size_t, void *), void (*cb2)(int, void *), void *data);
size_t csv_write(void *dest, size_t dest_size, const void *src, size_t src_size);
int csv_fwrite(Common::WriteStream *fp, const void *src, size_t src_size);
size_t csv_write2(void *dest, size_t dest_size, const void *src, size_t src_size, unsigned char quote);
int csv_fwrite2(Common::WriteStream *fp, const void *src, size_t src_size, unsigned char quote);
int csv_get_opts(struct csv_parser *p);
int csv_set_opts(struct csv_parser *p, unsigned char options);
void csv_set_delim(struct csv_parser *p, unsigned char c);
void csv_set_quote(struct csv_parser *p, unsigned char c);
unsigned char csv_get_delim(struct csv_parser *p);
unsigned char csv_get_quote(struct csv_parser *p);
void csv_set_space_func(struct csv_parser *p, int (*f)(unsigned char));
void csv_set_term_func(struct csv_parser *p, int (*f)(unsigned char));
void csv_set_realloc_func(struct csv_parser *p, void *(*)(void *, size_t));
void csv_set_free_func(struct csv_parser *p, void (*)(void *));
void csv_set_blk_size(struct csv_parser *p, size_t);
size_t csv_get_buffer_size(struct csv_parser *p);
} // End of namespace JACL
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,96 @@
/* 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/jacl/detection.h"
#include "glk/jacl/detection_tables.h"
#include "common/debug.h"
#include "common/file.h"
#include "common/md5.h"
#include "engines/game.h"
namespace Glk {
namespace JACL {
void JACLMetaEngine::getSupportedGames(PlainGameList &games) {
for (const PlainGameDescriptor *pd = JACL_GAME_LIST; pd->gameId; ++pd)
games.push_back(*pd);
}
const GlkDetectionEntry* JACLMetaEngine::getDetectionEntries() {
return JACL_GAMES;
}
GameDescriptor JACLMetaEngine::findGame(const char *gameId) {
for (const PlainGameDescriptor *pd = JACL_GAME_LIST; pd->gameId; ++pd) {
if (!strcmp(gameId, pd->gameId))
return *pd;
}
return GameDescriptor::empty();
}
bool JACLMetaEngine::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();
if (!filename.hasSuffixIgnoreCase(".j2") && !filename.hasSuffixIgnoreCase(".jac"))
continue;
Common::File gameFile;
if (!gameFile.open(*file))
continue;
gameFile.seek(0);
Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
uint32 filesize = gameFile.size();
// Scan through the JACL game list for a match
const GlkDetectionEntry *p = JACL_GAMES;
while (p->_md5 && p->_filesize != filesize && md5 != p->_md5)
++p;
if (!p->_gameId) {
const PlainGameDescriptor &desc = JACL_GAME_LIST[0];
gameList.push_back(GlkDetectedGame(desc.gameId, desc.description, filename, md5, filesize));
} else {
// Found a match
PlainGameDescriptor gameDesc = findGame(p->_gameId);
gameList.push_back(GlkDetectedGame(p->_gameId, gameDesc.description, p->_extra, filename, p->_language));
}
}
return !gameList.empty();
}
void JACLMetaEngine::detectClashes(Common::StringMap &map) {
for (const PlainGameDescriptor *pd = JACL_GAME_LIST; pd->gameId; ++pd) {
if (map.contains(pd->gameId))
error("Duplicate game Id found - %s", pd->gameId);
map[pd->gameId] = "";
}
}
} // End of namespace JACL
} // End of namespace Glk

View File

@@ -0,0 +1,64 @@
/* 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 JACL_DETECTION
#define JACL_DETECTION
#include "common/fs.h"
#include "common/hash-str.h"
#include "engines/game.h"
#include "glk/detection.h"
namespace Glk {
namespace JACL {
class JACLMetaEngine {
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 JACL
} // End of namespace Glk
#endif

View File

@@ -0,0 +1,48 @@
/* 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 JACL {
const PlainGameDescriptor JACL_GAME_LIST[] = {
{ "bloodyguns", "The Bloody Guns" },
{ "eldor", "The Curse of Eldor" }, // Competition 96
{ "prisonbreak", "Prisoner Break" },
{ "unholygrail", "The Unholy Grail" }, // Competition 97
{ nullptr, nullptr }
};
const GlkDetectionEntry JACL_GAMES[] = {
DT_ENTRY0("bloodyguns", "7c4463e92b1c202f8be485030ef4ace5", 159505),
DT_ENTRY1("eldor", "r3/crashing", "c1435d28e7eb577fa58c7456d4fa7009", 168119),
DT_ENTRY0("prisonbreak", "e2e85c5e60a63575bf0cd0481f0f3958", 199403),
DT_ENTRY1("unholygrail", "original/crashing", "2cf04cb897ba799c17cbeb407be67acb", 456730),
DT_ENTRY1("unholygrail", "002", "7d40e485c8cf8c9d5c4958a79337d6c7", 447833),
DT_END_MARKER
};
} // End of namespace JACL
} // End of namespace Glk

View File

@@ -0,0 +1,264 @@
/* 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/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
extern char temp_buffer[];
extern char function_name[];
extern struct object_type *object[];
extern struct variable_type *variable[];
extern const char *word[];
extern int player;
extern int wp;
extern int objects;
extern int custom_error;
extern int spaced;
int check_light(int where) {
int index;
if ((object[where]->attributes & DARK) == FALSE)
return (TRUE);
else {
for (index = 1; index <= objects; index++) {
if ((object[index]->attributes & LUMINOUS)
&& scope(index, "*present"))
return (TRUE);
}
}
return (FALSE);
}
char *sentence_output(int index, int capital) {
if (!strcmp(object[index]->article, "name")) {
Common::strcpy_s(temp_buffer, 1024, object[index]->inventory);
} else {
Common::strcpy_s(temp_buffer, 1024, object[index]->definite);
Common::strcat_s(temp_buffer, 1024, " ");
Common::strcat_s(temp_buffer, 1024, object[index]->inventory);
}
if (capital)
temp_buffer[0] = toupper(temp_buffer[0]);
return (temp_buffer);
}
char *isnt_output(int index, bool) {
if (object[index]->attributes & PLURAL)
return (cstring_resolve("ARENT")->value);
else
return (cstring_resolve("ISNT")->value);
}
char *is_output(int index, bool) {
if (object[index]->attributes & PLURAL)
return (cstring_resolve("ARE")->value);
else
return (cstring_resolve("IS")->value);
}
char *sub_output(int index, int capital) {
if (object[index]->attributes & PLURAL) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("THEY_WORD")->value);
} else {
if (index == player) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("YOU_WORD")->value);
} else if (object[index]->attributes & ANIMATE) {
if (object[index]->attributes & FEMALE) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("SHE_WORD")->value);
} else {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("HE_WORD")->value);
}
} else {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("IT_WORD")->value);
}
}
if (capital)
temp_buffer[0] = toupper(temp_buffer[0]);
return temp_buffer;
}
char *obj_output(int index, int capital) {
if (object[index]->attributes & PLURAL) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("THEM_WORD")->value);
} else {
if (index == player) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("YOURSELF_WORD")->value);
} else if (object[index]->attributes & ANIMATE) {
if (object[index]->attributes & FEMALE) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("HER_WORD")->value);
} else {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("HIM_WORD")->value);
}
} else {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("IT_WORD")->value);
}
}
if (capital)
temp_buffer[0] = toupper(temp_buffer[0]);
return temp_buffer;
}
char *it_output(int index, bool) {
if (object[index]->attributes & ANIMATE) {
return sentence_output(index, FALSE);
} else {
if (object[index]->attributes & PLURAL) {
return (cstring_resolve("THEM_WORD")->value);
} else {
return (cstring_resolve("IT_WORD")->value);
}
}
}
char *that_output(int index, int capital) {
if (object[index]->attributes & PLURAL) {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("THOSE_WORD")->value);
} else {
Common::strcpy_s(temp_buffer, 1024, cstring_resolve("THAT_WORD")->value);
}
if (capital)
temp_buffer[0] = toupper(temp_buffer[0]);
return temp_buffer;
}
char *doesnt_output(int index, bool) {
if (object[index]->attributes & PLURAL)
return (cstring_resolve("DONT")->value);
else
return (cstring_resolve("DOESNT")->value);
}
char *does_output(int index, bool) {
if (object[index]->attributes & PLURAL)
return (cstring_resolve("DO")->value);
else
return (cstring_resolve("DOES")->value);
}
char *list_output(int index, int capital) {
if (!strcmp(object[index]->article, "name")) {
Common::strcpy_s(temp_buffer, 1024, object[index]->inventory);
} else {
Common::strcpy_s(temp_buffer, 1024, object[index]->article);
Common::strcat_s(temp_buffer, 1024, " ");
Common::strcat_s(temp_buffer, 1024, object[index]->inventory);
}
if (capital)
temp_buffer[0] = toupper(temp_buffer[0]);
return (temp_buffer);
}
char *plain_output(int index, int capital) {
Common::strcpy_s(temp_buffer, 1024, object[index]->inventory);
if (capital)
temp_buffer[0] = toupper(temp_buffer[0]);
return (temp_buffer);
}
char *long_output(int index) {
if (!strcmp(object[index]->described, "function")) {
Common::strcpy_s(function_name, 1024, "long_");
Common::strcat_s(function_name, 1024, object[index]->label);
if (execute(function_name) == FALSE) {
unkfunrun(function_name);
}
// THE BUFFER IS RETURNED EMPTY AS THE TEXT IS OUTPUT BY
// WRITE STATEMENTS IN THE FUNCTION CALLED
temp_buffer[0] = 0;
return (temp_buffer);
} else {
return (object[index]->described);
}
}
void no_it() {
write_text(cstring_resolve("NO_IT")->value);
write_text(word[wp]);
write_text(cstring_resolve("NO_IT_END")->value);
custom_error = TRUE;
}
void look_around() {
/* THIS FUNCTION DISPLAYS THE DESCRIPTION OF THE CURRENT LOCATION ALONG
* WITH ANY OBJECTS CURRENTLY IN IT */
if (!check_light(HERE)) {
/* THE CURRENT LOCATION HAS 'DARK' AND NO SOURCE OF LIGHT IS
* CURRENTLY PRESENT */
execute("+dark_description");
return;
}
if (execute("+before_look") != FALSE)
return;
execute("+title");
if (DISPLAY_MODE->value) {
/* THE INTERPRETER IS IN VERBOSE MODE SO TEMPORARILY TAKE AWAYS THE
* 'VISITED' ATTRIBUTE */
object[HERE]->attributes &= ~1L;
}
Common::strcpy_s(function_name, 81, "look_");
Common::strcat_s(function_name, 81, object[HERE]->label);
execute(function_name);
/* GIVE THE LOCATION THE ATTRIBUTES 'VISITED', 'KNOWN', AND 'MAPPED' NOW
* THAT THE LOOK FUNCTION HAS RUN */
object[HERE]->attributes = object[HERE]->attributes | KNOWN;
object[HERE]->attributes = object[HERE]->attributes | VISITED;
object[HERE]->attributes = object[HERE]->attributes | MAPPED;
execute("+object_descriptions");
Common::strcpy_s(function_name, 81, "after_look_");
Common::strcat_s(function_name, 81, object[HERE]->label);
execute(function_name);
execute("+after_look");
}
} // End of namespace JACL
} // End of namespace Glk

View File

@@ -0,0 +1,278 @@
/* 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/jacl/jacl.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
extern struct synonym_type *synonym_table;
extern struct filter_type *filter_table;
char text_buffer[1024];
/* THIS IS A STRING CONSTANT TO POINT TO WHENEVER A COMMA IS
* USED IN THE PLAYER'S INPUT */
const char *comma = "comma\0";
const char *then = "then\0";
const char *word[MAX_WORDS];
int quoted[MAX_WORDS];
int percented[MAX_WORDS];
int wp;
void
encapsulate() {
int index,
length;
int position = 0;
int new_word = TRUE;
length = strlen(text_buffer);
/* QUOTED IS USED TO STORE WHETHER EACH WORD WAS ENCLOSED IN QUOTES
* IN THE PLAYERS COMMAND - RESET EACH WORD TO NO */
for (index = 0; index < MAX_WORDS; index++) {
quoted[index] = 0;
percented[index] = 0;
}
for (index = 0; index < length; index++) {
switch (text_buffer[index]) {
case ':':
case '\t':
case ' ':
case ',':
text_buffer[index] = 0;
new_word = TRUE;
break;
case ';':
case '#':
case '\r':
case '\n':
/* TERMINATE THE WHOLE COMMAND ON HITTING A NEWLINE CHARACTER, A
* SEMICOLON OR A HASH */
text_buffer[index] = 0;
index = length;
break;
case '"':
index++;
/* NEED TO REMEMBER THAT THIS WORD WAS ENCLOSED IN QUOTES FOR
* THE COMMAND 'write'*/
quoted[position] = 1;
word[position] = &text_buffer[index];
if (position < MAX_WORDS)
position++;
/* IF A WORD IS ENCLOSED IN QUOTES, KEEP GOING UNTIL THE END
* OF THE LINE OR A CLOSING QUOTE IS FOUND, NOT BREAKING AT
* WHITESPACE AS USUAL */
for (; index < length; index++) {
if (text_buffer[index] == '"') {
text_buffer[index] = 0;
new_word = TRUE;
break;
} else if (text_buffer[index] == '\r' || text_buffer[index] == '\n') {
text_buffer[index] = 0;
index = length;
break;
}
}
break;
default:
if (new_word) {
if (text_buffer[index] == '%' && text_buffer[index + 1] != ' ' && text_buffer[index + 1] != '\t') {
percented[position]++;
break;
}
word[position] = &text_buffer[index];
new_word = FALSE;
if (position < MAX_WORDS)
position++;
}
break;
}
}
/* NULL OUT ALL THE WORD POINTERS BEYOND THE LAST WORD */
for (index = position; index < MAX_WORDS; index++)
word[index] = nullptr;
wp = 0;
}
// THIS VERSION OF ENCAPSULATE DOESN'T LOOK FOR CERTAIN SPECIAL CHARACTERS
void
command_encapsulate() {
int index,
length;
int position = 0;
int new_word = TRUE;
length = strlen(text_buffer);
// QUOTED IS USED TO STORE WHETHER EACH WORD WAS ENCLOSED IN QUOTES
// IN THE PLAYERS COMMAND - RESET EACH WORD TO NO
for (index = 0; index < MAX_WORDS; index++) {
quoted[index] = 0;
}
for (index = 0; index < length; index++) {
// REDUSE EVERYTHING TO LOWER CASE EXCEPT TEXT ENCLOSED IN QUOTES
text_buffer[index] = tolower((int) text_buffer[index]);
switch (text_buffer[index]) {
case ':':
case '\t':
case ' ':
text_buffer[index] = 0;
new_word = TRUE;
break;
case ',':
text_buffer[index] = 0;
// SET THIS WORD TO POINT TO A STRING CONSTANT OF 'comma' AS THE
// COMMA ITSELF WILL BE NULLED OUT TO TERMINATE THE PRECEDING
// WORD IN THE COMMAND.
word[position] = comma;
if (position < MAX_WORDS)
position++;
new_word = TRUE;
break;
case '.':
text_buffer[index] = 0;
// SET THIS WORD TO POINT TO A STRING CONSTANT OF 'comma' AS THE
// COMMA ITSELF WILL BE NULLED OUT TO TERMINATE THE PRECEDING
// WORD IN THE COMMAND
word[position] = then;
if (position < MAX_WORDS)
position++;
new_word = TRUE;
break;
case ';':
case '\r':
case '\n':
// TERMINATE THE WHOLE COMMAND ON HITTING A NEWLINE CHARACTER, A
// SEMICOLON OR A HASH
text_buffer[index] = 0;
index = length;
break;
case '"':
index++;
// NEED TO REMEMBER THAT THIS WORD WAS ENCLOSED IN QUOTES FOR
// THE COMMAND 'write'
quoted[position] = 1;
word[position] = &text_buffer[index];
if (position < MAX_WORDS)
position++;
// IF A WORD IS ENCLOSED IN QUOTES, KEEP GOING UNTIL THE END
// OF THE LINE OR A CLOSING QUOTE IS FOUND, NOT BREAKING AT
// WHITESPACE AS USUAL
for (; index < length; index++) {
if (text_buffer[index] == '"') {
text_buffer[index] = 0;
new_word = TRUE;
break;
} else if (text_buffer[index] == '\r' || text_buffer[index] == '\n') {
text_buffer[index] = 0;
index = length;
break;
}
}
break;
default:
if (new_word) {
word[position] = &text_buffer[index];
new_word = FALSE;
if (position < MAX_WORDS)
position++;
}
break;
}
}
// NULL OUT ALL THE WORD POINTERS BEYOND THE LAST WORD
for (index = position; index < MAX_WORDS; index++) {
word[index] = nullptr;
}
wp = 0;
}
void
jacl_truncate() {
int index,
counter,
match;
int position = 0;
struct synonym_type *synonym;
struct filter_type *filter = filter_table;
// REMOVE ALL THE DEFINED 'filter's FROM THE PLAYER'S COMMAND
if (filter != nullptr) {
while (word[position] != nullptr) {
match = FALSE;
do {
if (!strcmp(word[position], filter->word)) {
for (index = position; word[index + 1] != nullptr;
index++)
word[index] = word[index + 1];
word[index] = nullptr;
match = TRUE;
}
filter = filter->next_filter;
} while (filter != nullptr && !match);
filter = filter_table;
if (!match)
position++;
};
}
// SUBTITUTE ALL THE DEFINED 'synonym's IN THE PLAYER'S COMMAND
if (synonym_table != nullptr) {
for (counter = 0; word[counter] != nullptr; counter++) {
synonym = synonym_table;
do {
if (!strcmp(word[counter], synonym->original)) {
word[counter] = synonym->standard;
break;
}
if (synonym->next_synonym != nullptr)
synonym = synonym->next_synonym;
else
break;
} while (TRUE);
}
}
}
} // End of namespace JACL
} // End of namespace Glk

168
engines/glk/jacl/errors.cpp Normal file
View File

@@ -0,0 +1,168 @@
/* 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/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
extern struct function_type *executing_function;
extern const char *word[];
extern char error_buffer[];
void badparrun() {
Common::sprintf_s(error_buffer, 1024, BAD_PARENT, executing_function->name);
log_error(error_buffer, PLUS_STDERR);
}
void notintrun() {
Common::sprintf_s(error_buffer, 1024, NOT_INTEGER, executing_function->name, word[0]);
log_error(error_buffer, PLUS_STDERR);
}
void unkfunrun(const char *name) {
Common::sprintf_s(error_buffer, 1024, UNKNOWN_FUNCTION_RUN, name);
log_error(error_buffer, PLUS_STDOUT);
}
void unkkeyerr(int line, int wordno) {
Common::sprintf_s(error_buffer, 1024, UNKNOWN_KEYWORD_ERR, line, word[wordno]);
log_error(error_buffer, PLUS_STDERR);
}
void unkatterr(int line, int wordno) {
Common::sprintf_s(error_buffer, 1024, UNKNOWN_ATTRIBUTE_ERR, line,
word[wordno]);
log_error(error_buffer, PLUS_STDERR);
}
void unkvalerr(int line, int wordno) {
Common::sprintf_s(error_buffer, 1024, UNKNOWN_VALUE_ERR, line,
word[wordno]);
log_error(error_buffer, PLUS_STDERR);
}
void noproprun(int) {
Common::sprintf_s(error_buffer, 1024, INSUFFICIENT_PARAMETERS_RUN, executing_function->name, word[0]);
log_error(error_buffer, PLUS_STDOUT);
}
void noobjerr(int line) {
Common::sprintf_s(error_buffer, 1024, NO_OBJECT_ERR,
line, word[0]);
log_error(error_buffer, PLUS_STDERR);
}
void noproperr(int line) {
Common::sprintf_s(error_buffer, 1024, INSUFFICIENT_PARAMETERS_ERR,
line, word[0]);
log_error(error_buffer, PLUS_STDERR);
}
void nongloberr(int line) {
Common::sprintf_s(error_buffer, 1024, NON_GLOBAL_FIRST, line);
log_error(error_buffer, PLUS_STDERR);
}
void nofnamerr(int line) {
Common::sprintf_s(error_buffer, 1024, NO_NAME_FUNCTION, line);
log_error(error_buffer, PLUS_STDERR);
}
void unkobjerr(int line, int wordno) {
Common::sprintf_s(error_buffer, 1024, UNDEFINED_ITEM_ERR, line, word[wordno]);
log_error(error_buffer, PLUS_STDERR);
}
void maxatterr(int line, int wordno) {
Common::sprintf_s(error_buffer, 1024,
MAXIMUM_ATTRIBUTES_ERR, line, word[wordno]);
log_error(error_buffer, PLUS_STDERR);
}
void unkobjrun(int wordno) {
Common::sprintf_s(error_buffer, 1024, UNDEFINED_ITEM_RUN, executing_function->name, word[wordno]);
log_error(error_buffer, PLUS_STDOUT);
}
void unkattrun(int wordno) {
Common::sprintf_s(error_buffer, 1024, UNKNOWN_ATTRIBUTE_RUN, executing_function->name, word[wordno]);
log_error(error_buffer, PLUS_STDOUT);
}
void unkdirrun(int wordno) {
Common::sprintf_s(error_buffer, 1024, UNDEFINED_DIRECTION_RUN,
executing_function->name, word[wordno]);
log_error(error_buffer, PLUS_STDOUT);
}
void badparun() {
Common::sprintf_s(error_buffer, 1024, BAD_PARENT, executing_function->name);
log_error(error_buffer, PLUS_STDOUT);
}
void badplrrun(int value) {
Common::sprintf_s(error_buffer, 1024, BAD_PLAYER, executing_function->name, value);
log_error(error_buffer, PLUS_STDOUT);
}
void badptrrun(const char *name, int value) {
Common::sprintf_s(error_buffer, 1024, BAD_POINTER, executing_function->name, name, value);
log_error(error_buffer, PLUS_STDOUT);
}
void unkvarrun(const char *variable) {
Common::sprintf_s(error_buffer, 1024, UNDEFINED_CONTAINER_RUN, executing_function->name, arg_text_of(variable));
log_error(error_buffer, PLUS_STDOUT);
}
void unkstrrun(const char *variable) {
Common::sprintf_s(error_buffer, 1024, UNDEFINED_STRING_RUN, executing_function->name, variable);
log_error(error_buffer, PLUS_STDOUT);
}
void unkscorun(const char *scope) {
Common::sprintf_s(error_buffer, 1024, UNKNOWN_SCOPE_RUN, executing_function->name, scope);
log_error(error_buffer, PLUS_STDOUT);
}
void totalerrs(int errors) {
if (errors == 1)
Common::sprintf_s(error_buffer, 1024, ERROR_DETECTED);
else {
Common::sprintf_s(error_buffer, 1024, ERRORS_DETECTED, errors);
}
log_error(error_buffer, PLUS_STDERR);
}
void outofmem() {
log_error(OUT_OF_MEMORY, PLUS_STDERR);
error("Terminated");
}
} // End of namespace JACL
} // End of namespace Glk

View File

@@ -0,0 +1,319 @@
/* 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/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
extern struct object_type *object[];
extern int objects;
/**************************************/
/* Queue functions */
/**************************************/
struct QueueNode {
int val;
int val2;
struct QueueNode *next;
};
struct Queue {
QueueNode *head;
QueueNode *tail;
};
void qInit(Queue *q) {
q->head = q->tail = nullptr;
}
void qDelete(Queue *q) {
QueueNode *node, *next;
for (node = q->head; node != nullptr; node = next) {
next = node->next;
free(node);
}
q->head = q->tail = nullptr;
}
int qIsEmpty(Queue *q) {
return (q->head == nullptr);
}
void qDebug(Queue *q) {
debug("Queue:");
if (q->head == nullptr) {
debug(" empty");
} else {
QueueNode *node;
for (node = q->head; node != nullptr; node = node->next) {
debug(" %d (%d)", node->val, node->val2);
}
}
debug("\n");
}
void qAppend(Queue *q, int val, int val2) {
QueueNode *node = (QueueNode *) malloc(sizeof(QueueNode));
node->val = val;
node->val2 = val2;
node->next = nullptr;
if (q->head == nullptr) {
q->head = q->tail = node;
} else {
q->tail->next = node;
q->tail = node;
}
}
void qPop(Queue *q, int *val, int *val2) {
//assert(q->head != NULL);
*val = q->head->val;
*val2 = q->head->val2;
if (q->head == q->tail) {
q->head = q->tail = nullptr;
} else {
q->head = q->head->next;
}
}
void qTest() {
int val, val2;
Queue q;
qInit(&q);
qDebug(&q);
debug("\nAdd 3, 0\n");
qAppend(&q, 3, 0);
qDebug(&q);
debug("\nAdd 4, 2\n");
qAppend(&q, 4, 2);
qDebug(&q);
debug("\nAdd 5, 1\n");
qAppend(&q, 5, 1);
qDebug(&q);
qPop(&q, &val, &val2);
debug("\nPop %d, %d\n", val, val2);
qDebug(&q);
qPop(&q, &val, &val2);
debug("\nPop %d, %d\n", val, val2);
qDebug(&q);
debug("\nAdd 6, 3\n");
qAppend(&q, 6, 3);
qDebug(&q);
debug("\nDelete all\n");
qDelete(&q);
qDebug(&q);
}
/**************************************/
/* Set functions */
/**************************************/
/* linked list for hash table */
struct SetNode {
int val;
struct SetNode *next;
};
#define SET_HASHSIZE 101
struct Set {
SetNode *node[SET_HASHSIZE];
};
void setInit(Set *set) {
int n;
for (n = 0; n < SET_HASHSIZE; n++) {
set->node[n] = nullptr;
}
}
void setDelete(Set *set) {
int n;
for (n = 0; n < SET_HASHSIZE; n++) {
SetNode *node, *next;
for (node = set->node[n]; node != nullptr; node = next) {
next = node->next;
free(node);
}
set->node[n] = nullptr;
}
}
void setDebug(Set *set) {
int n;
debug("Set:");
for (n = 0; n < SET_HASHSIZE; n++) {
SetNode *node;
for (node = set->node[n]; node != nullptr; node = node->next) {
debug(" %d", node->val);
}
}
debug("\n");
}
int setHash(int val) {
return abs(val) % SET_HASHSIZE;
}
void setAdd(Set *set, int val) {
SetNode *node;
int n = setHash(val);
/* check if val is already in the set */
for (node = set->node[n]; node != nullptr; node = node->next) {
if (node->val == val) {
return;
}
}
node = (SetNode *) malloc(sizeof(SetNode));
node->val = val;
node->next = set->node[n];
set->node[n] = node;
}
/* returns 1 if the set contains val, otherwise returns 0 */
int setContains(Set *set, int val) {
SetNode *node;
int n = setHash(val);
for (node = set->node[n]; node != nullptr; node = node->next) {
if (node->val == val) {
return 1;
}
}
return 0;
}
void setTest() {
Set s;
setInit(&s);
setDebug(&s);
debug("\nAdd 34\n");
setAdd(&s, 34);
setDebug(&s);
debug("\nAdd 56\n");
setAdd(&s, 56);
setDebug(&s);
debug("\nAdd 34 again\n");
setAdd(&s, 34);
setDebug(&s);
debug("\nAdd %d\n", 34 + SET_HASHSIZE);
setAdd(&s, 34 + SET_HASHSIZE);
setDebug(&s);
debug("\nAdd 78\n");
setAdd(&s, 78);
setDebug(&s);
debug("\nDelete all\n");
setDelete(&s);
setDebug(&s);
}
/**************************************/
#define DIR_NONE -1
int find_route(int fromRoom, int toRoom, int known) {
Set visited;
Queue q;
int firstTime;
int result = DIR_NONE;
setInit(&visited);
qInit(&q);
qAppend(&q, fromRoom, DIR_NONE);
setAdd(&visited, fromRoom);
firstTime = 1;
while (!qIsEmpty(&q)) {
int n, dir, firstDir;
qPop(&q, &n, &firstDir);
if (n == toRoom) {
result = firstDir;
break;
}
for (dir = 0; dir < 12 ; dir++) {
int dest = object[n]->integer[dir];
if (dest < 1 || dest > objects) continue;
if (object[dest] == nullptr) continue;
if (dest != NOWHERE && !setContains(&visited, dest)) {
if (!known || (object[dest]->attributes & KNOWN)) {
qAppend(&q, dest, (firstTime ? dir : firstDir));
setAdd(&visited, dest);
}
}
}
firstTime = 0;
}
setDelete(&visited);
qDelete(&q);
return result;
}
} // End of namespace JACL
} // End of namespace Glk

View 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/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
extern struct object_type *object[];
extern struct integer_type *integer_table;
extern struct integer_type *integer[];
extern struct function_type *function_table;
extern struct string_type *string_table;
extern schanid_t sound_channel[];
extern char temp_buffer[];
extern int objects;
extern int integers;
extern int functions;
extern int strings;
extern int player;
extern int it;
extern int them[];
extern int her;
extern int him;
extern int parent;
extern int noun[];
bool save_game(strid_t save) {
integer_type *current_integer = integer_table;
function_type *current_function = function_table;
string_type *current_string = string_table;
int index, counter;
// This is written to help validate the saved game when it's loaded
write_integer(save, objects);
write_integer(save, integers);
write_integer(save, functions);
write_integer(save, strings);
while (current_integer != nullptr) {
write_integer(save, current_integer->value);
current_integer = current_integer->next_integer;
}
while (current_function != nullptr) {
write_integer(save, current_function->call_count);
current_function = current_function->next_function;
}
for (index = 1; index <= objects; index++) {
if (object[index]->nosave)
continue;
for (counter = 0; counter < 16; counter++) {
write_integer(save, object[index]->integer[counter]);
}
write_long(save, object[index]->attributes);
write_long(save, object[index]->user_attributes);
}
// Write out all the current values of the string variables
while (current_string != nullptr) {
for (index = 0; index < 255; index++) {
g_vm->glk_put_char_stream(save, current_string->value[index]);
}
current_string = current_string->next_string;
}
write_integer(save, player);
write_integer(save, noun[3]);
// Save the current volume of each of the sound channels
for (index = 0; index < 8; index++) {
Common::sprintf_s(temp_buffer, 1024, "volume[%d]", index);
write_integer(save, cinteger_resolve(temp_buffer)->value);
}
// Save the current value of the GLK timer
write_integer(save, cinteger_resolve("timer")->value);
TIME->value = FALSE;
return true;
}
bool restore_game(strid_t save, bool warn) {
integer_type *current_integer = integer_table;
function_type *current_function = function_table;
string_type *current_string = string_table;
int index, counter;
int file_objects, file_integers, file_functions, file_strings;
// Read properties to validate the savegame is for this game
file_objects = read_integer(save);
file_integers = read_integer(save);
file_functions = read_integer(save);
file_strings = read_integer(save);
if (file_objects != objects
|| file_integers != integers
|| file_functions != functions
|| file_strings != strings) {
if (warn == FALSE) {
log_error(cstring_resolve("BAD_SAVED_GAME")->value, PLUS_STDOUT);
}
g_vm->glk_stream_close(save, nullptr);
return (FALSE);
}
while (current_integer != nullptr) {
current_integer->value = read_integer(save);
current_integer = current_integer->next_integer;
}
while (current_function != nullptr) {
current_function->call_count = read_integer(save);
current_function = current_function->next_function;
}
for (index = 1; index <= objects; index++) {
if (object[index]->nosave)
continue;
for (counter = 0; counter < 16; counter++) {
object[index]->integer[counter] = read_integer(save);
}
object[index]->attributes = read_integer(save);
object[index]->user_attributes = read_integer(save);
}
while (current_string != nullptr) {
for (index = 0; index < 255; index++) {
current_string->value[index] = g_vm->glk_get_char_stream(save);
}
current_string = current_string->next_string;
}
player = read_integer(save);
noun[3] = read_integer(save);
// Restore the current volume of each of the sound channels
for (index = 0; index < 8; index++) {
Common::sprintf_s(temp_buffer, 1024, "volume[%d]", index);
counter = read_integer(save);
cinteger_resolve(temp_buffer)->value = counter;
if (SOUND_SUPPORTED->value) {
// Set the GLK volume
g_vm->glk_schannel_set_volume(sound_channel[index], (glui32) counter);
}
}
// Restore the current value of the GLK timer
counter = read_integer(save);
cinteger_resolve("timer")->value = counter;
// Set the GLK timer
g_vm->glk_request_timer_events((glui32) counter);
TIME->value = FALSE;
return true;
}
void write_integer(strid_t stream, int x) {
unsigned char c;
c = (unsigned char)(x) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
c = (unsigned char)(x >> 8) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
c = (unsigned char)(x >> 16) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
c = (unsigned char)(x >> 24) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
}
int read_integer(strid_t stream) {
int a, b, c, d;
a = (int) g_vm->glk_get_char_stream(stream);
b = (int) g_vm->glk_get_char_stream(stream);
c = (int) g_vm->glk_get_char_stream(stream);
d = (int) g_vm->glk_get_char_stream(stream);
return a | (b << 8) | (c << 16) | (d << 24);
}
void write_long(strid_t stream, long x) {
unsigned char c;
c = (unsigned char)(x) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
c = (unsigned char)(x >> 8) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
c = (unsigned char)(x >> 16) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
c = (unsigned char)(x >> 24) & 0xFF;
g_vm->glk_put_char_stream(stream, c);
}
long read_long(strid_t stream) {
long a, b, c, d;
a = (long) g_vm->glk_get_char_stream(stream);
b = (long) g_vm->glk_get_char_stream(stream);
c = (long) g_vm->glk_get_char_stream(stream);
d = (long) g_vm->glk_get_char_stream(stream);
return a | (b << 8) | (c << 16) | (d << 24);
}
} // End of namespace JACL
} // End of namespace Glk

File diff suppressed because it is too large Load Diff

83
engines/glk/jacl/jacl.cpp Normal file
View 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/>.
*
*/
#include "glk/jacl/jacl.h"
#include "glk/jacl/prototypes.h"
#include "glk/jacl/types.h"
#include "common/config-manager.h"
namespace Glk {
namespace JACL {
JACL *g_vm;
extern strid_t game_stream;
extern void glk_main();
JACL::JACL(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
_saveSlot(-1) {
g_vm = this;
}
void JACL::runGame() {
// Check for savegame
_saveSlot = ConfMan.hasKey("save_slot") ? ConfMan.getInt("save_slot") : -1;
// Open up the game file as a stream, and play the game
game_stream = _streams->openStream(&_gameFile);
glk_main();
}
bool JACL::initialize() {
return true;
}
void JACL::deinitialize() {
}
Common::Error JACL::readSaveData(Common::SeekableReadStream *rs) {
strid_t data_stream = _streams->openStream(rs);
bool success = restore_game(data_stream);
_streams->deleteStream(data_stream);
return success ? Common::kNoError : Common::kReadingFailed;
}
Common::Error JACL::writeGameData(Common::WriteStream *ws) {
strid_t data_stream = _streams->openStream(ws);
bool success = save_game(data_stream);
_streams->deleteStream(data_stream);
return success ? Common::kNoError : Common::kWritingFailed;
}
bool JACL::loadLauncherSavegame() {
int saveSlot = _saveSlot;
_saveSlot = -1;
if (loadGameState(saveSlot).getCode() == Common::kNoError)
return true;
write_text(cstring_resolve("CANT_RESTORE")->value);
return false;
}
} // End of namespace JACL
} // End of namespace Glk

96
engines/glk/jacl/jacl.h Normal file
View File

@@ -0,0 +1,96 @@
/* 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 the JACL interpreter version 3.0.0 */
#ifndef JACL_JACL
#define JACL_JACL
#include "glk/glk_api.h"
namespace Glk {
namespace JACL {
#define GLK
/**
* JACL game interpreter
*/
class JACL : public GlkAPI {
private:
int _saveSlot;
private:
/**
* Engine initialization
*/
bool initialize();
/**
* Engine cleanup
*/
void deinitialize();
public:
/**
* Constructor
*/
JACL(OSystem *syst, const GlkGameDescription &gameDesc);
/**
* Run the game
*/
void runGame() override;
/**
* Returns the running interpreter type
*/
InterpreterType getInterpreterType() const override {
return INTERPRETER_JACL;
}
/**
* Savegames aren't supported for JACL games
*/
Common::Error readSaveData(Common::SeekableReadStream *rs) override;
/**
* Savegames aren't supported for JACL games
*/
Common::Error writeGameData(Common::WriteStream *ws) override;
/**
* Returns true if a savegame is being loaded directly from the ScummVM launcher
*/
bool loadingSavegame() const {
return _saveSlot != -1;
}
/**
* Does the actual loading of the savegame from a luancher
*/
bool loadLauncherSavegame();
};
extern JACL *g_vm;
} // End of namespace JACL
} // End of namespace Glk
#endif

File diff suppressed because it is too large Load Diff

236
engines/glk/jacl/jpp.cpp Normal file
View File

@@ -0,0 +1,236 @@
/* jpp.c --- The JACL Preprocessor
(C) 2001 Andreas Matthias
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 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "glk/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
#include "glk/jacl/version.h"
#include "common/file.h"
namespace Glk {
namespace JACL {
extern char text_buffer[];
extern char temp_buffer[];
extern const char *word[];
extern short int quoted[];
extern short int punctuated[];
extern int wp;
extern char user_id[];
extern char prefix[];
extern char game_path[];
extern char game_file[];
extern char processed_file[];
extern short int encrypted;
extern char include_directory[];
extern char temp_directory[];
extern char error_buffer[];
int lines_written;
Common::WriteStream *outputFile = nullptr;
Common::SeekableReadStream *inputFile = nullptr;
char *stripped_line;
/* INDICATES THAT THE CURRENT '.j2' FILE BEING WORKED
* WITH BEING PREPARED FOR RELEASE (DON'T INCLUDE DEBUG LIBARIES) */
short int release = FALSE;
/* INDICATES THAT THE CURRENT '.j2' FILE BEING WORKED
* SHOULD BE ENCRYPTED */
short int do_encrypt = TRUE;
/* INDICATES THAT THE CURRENT '.processed' FILE BRING WRITTEN SHOULD NOW
* HAVE EACH LINE ENCRYPTED AS THE FIRST NONE COMMENT LINE HAS BEEN HIT */
short int encrypting = FALSE;
int jpp() {
// TODO: Find out if this is actually used
#ifdef UNUSED
int game_version;
lines_written = 0;
/* CHECK IF GAME FILE IS ALREADY A PROCESSED FILE BY LOOKING FOR THE
* STRING "#encrypted" OR "#processed" WITHIN THE FIRST FIVE LINES OF
* THE GAME FILE IF SO, RETURN THE GAME FILE AS THE PROCESSED FILE */
inputFile = File::open(game_file);
if (inputFile) {
int index = 0;
char *result = NULL;
if (inputFile->read(text_buffer, 1024) != 1024) {
Common::sprintf_s(error_buffer, 1024, CANT_OPEN_SOURCE, game_file);
return (FALSE);
}
while (inputFile->pos() < inputFile->size() && index < 10) {
if (strstr(text_buffer, "#processed")) {
/* THE GAME FILE IS ALREADY A PROCESSED FILE, JUST USE IT
* DIRECTLY */
if (sscanf(text_buffer, "#processed:%d", &game_version)) {
if (INTERPRETER_VERSION < game_version) {
Common::sprintf_s(error_buffer, 1024, OLD_INTERPRETER, game_version);
return (FALSE);
}
}
Common::strcpy_s(processed_file, 256, game_file);
return (TRUE);
}
if (inputFile->read(text_buffer, 1024) != 1024)
break;
index++;
}
delete inputFile;
} else {
Common::sprintf_s(error_buffer, 1024, NOT_FOUND);
return (FALSE);
}
/* SAVE A TEMPORARY FILENAME INTO PROCESSED_FILE */
Common::sprintf_s(processed_file, "%s%s.j2", temp_directory, prefix);
/* ATTEMPT TO OPEN THE PROCESSED FILE IN THE TEMP DIRECTORY */
if ((outputFile = fopen(processed_file, "w")) == NULL) {
/* NO LUCK, TRY OPEN THE PROCESSED FILE IN THE CURRENT DIRECTORY */
Common::sprintf_s(processed_file, "%s.j2", prefix);
if ((outputFile = fopen(processed_file, "w")) == NULL) {
/* NO LUCK, CAN'T CONTINUE */
Common::sprintf_s(error_buffer, 1024, CANT_OPEN_PROCESSED, processed_file);
return (FALSE);
}
}
if (process_file(game_file, (const char *) NULL) == FALSE) {
return (FALSE);
}
fclose(outputFile);
#else
error("TODO");
#endif
/* ALL OKAY, RETURN TRUE */
return (TRUE);
}
int process_file(const char *sourceFile1, char *sourceFile2) {
char temp_buffer1[1025];
char temp_buffer2[1025];
Common::File *srcFile = nullptr;
char *includeFile = nullptr;
/* THIS FUNCTION WILL CREATE A PROCESSED FILE THAT HAS HAD ALL
* LEADING AND TRAILING WHITE SPACE REMOVED AND ALL INCLUDED
* FILES INSERTED */
srcFile = File::openForReading(sourceFile1);
if (!srcFile) {
if (sourceFile2 != nullptr) {
srcFile = File::openForReading(sourceFile2);
if (!srcFile) {
Common::sprintf_s(error_buffer, 1024, CANT_OPEN_OR, sourceFile1, sourceFile2);
return (FALSE);
}
} else {
Common::sprintf_s(error_buffer, 1024, CANT_OPEN_SOURCE, sourceFile1);
return (FALSE);
}
}
*text_buffer = 0;
if (srcFile->read(text_buffer, 1024) != 1024) {
Common::sprintf_s(error_buffer, 1024, READ_ERROR);
delete srcFile;
return (FALSE);
}
while (srcFile->pos() < srcFile->size() && *text_buffer != 0) {
if (!strncmp(text_buffer, "#include", 8) ||
(!strncmp(text_buffer, "#debug", 6) & !release)) {
includeFile = strrchr(text_buffer, '"');
if (includeFile != nullptr)
*includeFile = 0;
includeFile = strchr(text_buffer, '"');
if (includeFile != nullptr) {
Common::strcpy_s(temp_buffer1, game_path);
Common::strcat_s(temp_buffer1, includeFile + 1);
Common::strcpy_s(temp_buffer2, include_directory);
Common::strcat_s(temp_buffer2, includeFile + 1);
if (process_file(temp_buffer1, temp_buffer2) == FALSE) {
return (FALSE);
}
} else {
Common::sprintf_s(error_buffer, 1024, BAD_INCLUDE);
return (FALSE);
}
} else {
/* STRIP WHITESPACE FROM LINE BEFORE WRITING TO OUTPUTFILE. */
stripped_line = stripwhite(text_buffer);
if (!encrypting && *stripped_line != '#' && *stripped_line != '\0' && do_encrypt & release) {
/* START ENCRYPTING FROM THE FIRST NON-COMMENT LINE IN
* THE SOURCE FILE */
outputFile->writeString("#encrypted\n");
encrypting = TRUE;
}
/* ENCRYPT PROCESSED FILE IF REQUIRED */
if (encrypting) {
jacl_encrypt(stripped_line);
}
outputFile->writeString(stripped_line);
lines_written++;
if (lines_written == 1) {
Common::sprintf_s(temp_buffer, 1024, "#processed:%d\n", INTERPRETER_VERSION);
outputFile->writeString(temp_buffer);
}
}
*text_buffer = 0;
if (srcFile->read(text_buffer, 1024) != 1024)
// EOF HAS BEEN REACHED
break;
}
delete srcFile;
/* ALL OKAY, RETURN TRUE */
return (TRUE);
}
} // End of namespace JACL
} // End of namespace Glk

570
engines/glk/jacl/language.h Normal file
View File

@@ -0,0 +1,570 @@
/* 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 JACL {
/* THIS FILE CONTAINS ALL THE TEXT OUTPUT INTERNALLY BY THE INTERPRETER.
THE STRINGS FOR ANY GIVEN LANGUAGE ARE DIVIDED INTO TWO SECTIONS, ONE
THAT CONTAINS THE TEXT OUTPUT DURING REGULAR PLAY AND ONE THAT CONTAINS
THE TEXT OUTPUT DURING ERROR CONDITIONS (POSSIBLY BEFORE ANY GIVEN GAME
HAS FINISHED LOADING.
TO TRANSLATE A GAME TO LANGUAGE THAT IS NOT CURRENTLY SUPPORTED YOU
NEED TO TRANSLATE english.library AND verbs.library INTO YOUR CHOSEN
LANGUAGE.
THE NATIVE_LANGUAGE CONSTANT BELOW INDICATES WHAT SHOULD BE THE DEFAULT
LANGUAGE OF THE INTERPRETER WHEN IT IS COMPILED. THE 'GAME MESSAGES'
BLOCK CONTAINS THE SAME STRINGS AS THE FILE english.library (AND OTHER
LANGUAGES) AND THESE ARE THE VALUES USED BY THE INTERPRETER IF THOSE
CONSTANTS ARE NO DEFINED BY ANY GIVEN GAME.
THE 'SYSTEM MESSAGES' BLOCK CONTAINS ERROR MESSAGES AND OTHER SYSTEM-
LEVEL MESSAGES THAT ARE MOST COMMONLY SEEN DURING THE DEVELOPMENT OF A
GAME. THESE MESSAGES CANNOT BE OVERRIDDEN BY ANY SPECIFIC GAME. */
#define ENGLISH 1
#define GERMAN 2
#define FRENCH 3
#define NATIVE_LANGUAGE ENGLISH
#if NATIVE_LANGUAGE==ENGLISH
/* GAME MESSAGES */
#define COMMENT_IGNORED "No transcript running, comment ignored.^"
#define COMMENT_RECORDED "Comment recorded.^"
#define YES_WORD "yes"
#define NO_WORD "no"
#define YES_OR_NO "^Please enter ~yes~ or ~no~: "
#define INVALID_SELECTION "Invalid selection.^"
#define RESTARTING "^Restarting...^"
#define RETURN_GAME "^Returning to game.^"
#define SCRIPTING_ON "Scripting on.^"
#define SCRIPTING_OFF "Scripting off.^"
#define SCRIPTING_ALREADY_OFF "Scripting already off.^"
#define SCRIPTING_ALREADY_ON "Scripting already on.^"
#define CANT_WRITE_SCRIPT "Unable to write to script file.^"
#define ERROR_READING_WALKTHRU "Error reading walkthru file.^"
#define BAD_OOPS "You must follow the ~oops~ command with the word you wish to use instead.^"
#define CANT_CORRECT "I can't correct the last command using ~oops~, sorry.^"
#define SURE_QUIT "Are you sure you want to quit?^"
#define SURE_RESTART "Are you sure you want to restart?^"
#define NOT_CLEVER "It wasn't so clever as to be worth repeating.^"
#define NO_MOVES "But you haven't done anything yet!^"
#define TYPE_NUMBER "^Type a number between %d and %d: "
#define BY "By ~"
#define REFERRING_TO "~, are you referring to:^"
#define WALKTHRU_WORD "walkthru"
#define INFO_WORD "info"
#define RESTART_WORD "restart"
#define AGAIN_WORD "again"
#define SCRIPT_WORD "script"
#define UNSCRIPT_WORD "unscript"
#define QUIT_WORD "quit"
#define UNDO_WORD "undo"
#define OOPS_WORD "oops"
#define FROM_WORD "from"
#define EXCEPT_WORD "except"
#define FOR_WORD "for"
#define BUT_WORD "but"
#define AND_WORD "and"
#define THEN_WORD "then"
#define OF_WORD "of"
#define SHE_WORD "she"
#define HE_WORD "he"
#define THAT_WORD "that"
#define THEM_WORD "them"
#define THOSE_WORD "those"
#define THEY_WORD "they"
#define IT_WORD "it"
#define ITSELF_WORD "itself"
#define HIM_WORD "him"
#define HIMSELF_WORD "himself"
#define HER_WORD "her"
#define HERSELF_WORD "herself"
#define THEMSELVES_WORD "themselves"
#define YOU_WORD "you"
#define YOURSELF_WORD "yourself"
#define ONES_WORD "ones"
#define NO_MULTI_VERB "You can't refer to multiple objects directly after the word ~%s~.^"
#define NO_MULTI_START "You can't refer to multiple objects at the start of a command.^"
#define PERSON_CONCEALING "%s doesn't seem to be carrying any such thing.^"
#define PERSON_POSSESSIVE "%s isn't about to let you take anything of theirs.^"
#define CONTAINER_CLOSED "%s is closed.^"
#define CONTAINER_CLOSED_FEM "%s is closed.^"
#define FROM_NON_CONTAINER "The word ~%s~ must be followed by a container.^"
#define DOUBLE_EXCEPT "You can only use the word ~%s~ once per object reference.^"
#define NONE_HELD "You are not holding anything like that.^"
#define NO_OBJECTS "I don't see what you are referring to.^"
#define NO_FILENAME "Save and restore commands must be followed by a filename.^"
#define MOVE_UNDONE "Previous move undone.^^"
#define NO_UNDO "Nothing to undo.^"
#define CANT_SAVE "Unable to save game state to file.^"
#define CANT_RESTORE "Unable to restore game state from file.^"
#define GAME_SAVED "Game saved.^"
#define INCOMPLETE_SENTENCE "The sentence you typed was incomplete.^"
#define UNKNOWN_OBJECT "You can't see any such thing as ~"
#define UNKNOWN_OBJECT_END "~.^"
#define CANT_USE_WORD "You can't use the word ~"
#define IN_CONTEXT "~ in that context.^"
#define DONT_SEE "You don't see "
#define HERE_WORD " here.^"
#define BAD_SAVED_GAME "Attempt to restore incompatible saved-game file."
#define ARENT "aren't"
#define ISNT "isn't"
#define ARE "are"
#define IS "is"
#define DONT "don't"
#define DOESNT "doesn't"
#define DO "do"
#define DOES "does"
#define SCORE_UP "^[YOUR SCORE JUST WENT UP BY "
#define POINT " POINT]^"
#define POINTS " POINTS]^"
#define STARTING "Starting."
#define NO_IT "You must have referred to an appropriate noun previously to use the word ~"
#define NO_IT_END "~.^"
#define BACK_REFERENCE "You must have referred to a noun previously in the same sentence to use the word ~"
#define BACK_REFERENCE_END "~.^"
#define WHEN_YOU_SAY "When you say ~"
#define MUST_SPECIFY "~, you must specify whether you mean "
#define OR_WORD " or "
/* SYSTEM MESSAGES */
#define READ_ERROR "Error reading game file."
#define OLD_INTERPRETER "Interpreter version is older than game file (v%d), can't continue."
#define BAD_CURSOR "You can only use the ~cursor~ command in the status window.^"
#define INCOMPLETE_GRAMMAR "Incomplete grammar statement."
#define GAME_MODIFIED "Game file modified, reloading.\n"
#define NOT_INTEGER "In function \"%s\", \"%s\" command requires integer parameter."
#define NO_NAME_FUNCTION "In line %d, a function must have at least one name."
#define MAXIMUM_ATTRIBUTES_ERR "In line %d, unable to create attribute \"%s\", maximum number of attributes already defined."
#define BAD_PLAYER "In function \"%s\", attempt to use object pointer \"player\" while it does not point to an object (%d)."
#define BAD_PARENT "In function \"%s\", attempt to use the variable 'here' while the variable 'player' does not have a legal parent."
#define BAD_POINTER "In function \"%s\", attempt to use object pointer \"%s\" that does not point to an object (%d)."
#define ILLEGAL_LABEL "In line %d, reserved word \"%s\" used as label."
#define USED_LABEL_INT "In line %d, \"%s\" is already used as a variable label."
#define USED_LABEL_CINT "In line %d, \"%s\" is already used as an integer constant label."
#define USED_LABEL_STR "In line %d, \"%s\" is already used as a string label."
#define USED_LABEL_CSTR "In line %d, \"%s\" is already used as a string constant label."
#define USED_LABEL_ATT "In line %d, \"%s\" is already used as an attribute label."
#define USED_LABEL_OBJ "In line %d, \"%s\" is already used as an object or location label."
#define NO_OBJECT_ERR "In line %d, property \"%s\" defined before first object or location."
#define BAD_INCLUDE "'#include' directive must be followed by file name enclosed in double quotes."
#define BAD_PARAMETER "Unknown or inappropriate type of container '%s' associated with parameter '%s'."
#define BAD_VALUE "Value '%s' cannot be stored in container '%s'."
#define NO_MEDIA "WebJACL: Media file \"%s\" not found, external media support disabled.\n"
#define MEDIA_REGISTERED "WebJACL: Registered %d media.\n"
#define CLEANING_UP "WebJACL: Cleaning up...\n"
#define NO_GAME "No game file specified, can't continue."
#define NO_PORT "WebJACL: No port number specified (-p <number>), using default port %d.\n"
#define WEBJACL_CONFIGURED "WebJACL server configured on %s:%d\n"
#define NOT_FOUND "Unable to open game file, can't continue."
#define CANT_OPEN "Unable to open processed file \"%s\", can't continue."
#define CANT_RUN "A JACL game must contain at least one object (to represent the player), and at least one location (for the player to start in).^"
#define NO_PLAYER "The object pointer 'player' does not point to an object.^"
#define SELF_REFERENCE "In function \"%s\", reference to object \"%s\" whose parent is itself."
#define EXECUTING "Executing function \"%s\".\n"
#define NO_WHILE "In function \"%s\", 'endwhile' command without matching 'while' command."
#define NO_ITERATE "In function \"%s\", 'enditerate' command without matching 'iterate' command."
#define NO_UPDATE "In function \"%s\", 'endupdate' command without matching 'update' command."
#define NO_REPEAT "In function \"%s\", 'until' command without matching 'repeat' command."
#define NO_LOOP "In function \"%s\", 'endloop' command without matching 'loop' command."
#define UNDEFINED_FUNCTION "In function \"%s\", attempt to execute undefined function \"%s\"."
#define DIVIDE_BY_ZERO "In function \"%s\", division by zero error."
#define ILLEGAL_OPERATOR "In function \"%s\", illegal operator \"%s\"."
#define UNKNOWN_COMMAND "In function \"%s\", unknown command \"%s\"."
#define STACK_OVERFLOW "Stack overflow."
#define ILLEGAL_OPERATOR "In function \"%s\", illegal operator \"%s\"."
#define OUT_OF_RANGE "In function \"%s\", element \"%s\" out of range (%d)."
#define GLOBAL_SELF "Reference to 'self' from global function \"%s\"."
#define NON_GLOBAL_FIRST "In line %d, non-global function before object or location."
#define MAXIMUM_EXCEEDED "Maximum number of objects exceeded, can't continue."
#define ERROR_DETECTED "1 error detected."
#define ERRORS_DETECTED "%d errors detected."
#define UNKNOWN_FUNCTION_RUN "Attempt to execute unknown function \"%s\"."
#define UNKNOWN_KEYWORD_ERR "In line %d, unknown keyword \"%s\"."
#define UNKNOWN_ATTRIBUTE_ERR "In line %d, unknown attribute \"%s\"."
#define UNKNOWN_VALUE_ERR "In line %d, unable to resolve value \"%s\"."
#define UNKNOWN_ATTRIBUTE_RUN "In function \"%s\", reference to unknown attribute \"%s\"."
#define INSUFFICIENT_PARAMETERS_RUN "In function \"%s\", \"%s\" command with insufficient parameters."
#define INSUFFICIENT_PARAMETERS_ERR "In line %d, \"%s\" keyword with insufficient parameters."
#define UNDEFINED_ITEM_ERR "In line %d, reference to undefined item \"%s\"."
#define UNDEFINED_ITEM_RUN "In function \"%s\", reference to undefined object \"%s\"."
#define UNDEFINED_DIRECTION_RUN "In function \"%s\", reference to undefined direction \"%s\"."
#define UNKNOWN_SCOPE_RUN "In function \"%s\", reference to unknown scope \"%s\"."
#define UNDEFINED_STRING_RUN "In function \"%s\", reference to undefined string \"%s\"."
#define UNDEFINED_CONTAINER_RUN "In function \"%s\", reference to undefined container \"%s\"."
#define OUT_OF_MEMORY "Out of memory, can't continue."
#define CANT_OPEN_PROCESSED "Unable to open output file \"%s\" for writing, can't continue."
#define CANT_OPEN_OR "Unable to open source file \"%s\" or \"%s\", can't continue."
#define CANT_OPEN_SOURCE "Unable to open source file \"%s\", can't continue."
#endif
#if NATIVE_LANGUAGE==FRENCH
/* GAME MESSAGES */
#define COMMENT_IGNORED "Pas de transcription en cours, commentaire ignoré.^"
#define COMMENT_RECORDED "Commentaire enregistré.^"
#define YES_WORD "oui"
#define NO_WORD "no"
#define YES_OR_NO "^Merci d'entrer ~oui~ ou ~non~: "
#define INVALID_SELECTION "Sélection invalide.^"
#define RESTARTING "^En train de recommencer...^"
#define RETURN_GAME "^Retour au jeu.^"
#define SCRIPTING_ON "Début de transcription.^"
#define SCRIPTING_OFF "Fin de transcription.^"
#define SCRIPTING_ALREADY_OFF "Transcription déjà terminée.^"
#define SCRIPTING_ALREADY_ON "Transcription déjà en cours.^"
#define CANT_WRITE_SCRIPT "Impossible d'écrire le fichier de transcription.^"
#define ERROR_READING_WALKTHRU "Erreur lors de la lecture du fichier de solution.^"
#define BAD_OOPS "Vous devez faire suivre la commande ~oops~ par le mot que vous souhaitez remplacer.^"
#define CANT_CORRECT "Désolé, je ne peux corriger la dernière commande en utilisant ~oops~.^"
#define SURE_QUIT "Êtes-vous certain de vouloir quitter ?^"
#define SURE_RESTART "Êtes-vous certain de vouloir recommencer ?^"
#define NOT_CLEVER "Ce n'était pas si intelligent au point de vouloir répéter cela.^"
#define NO_MOVES "Mais vous n'avez rien fait pour le moment !^"
#define TYPE_NUMBER "^Entrez un nombre entre %d et %d: "
#define BY "By ~"
#define REFERRING_TO "Faites-vous référence à :^"
#define WALKTHRU_WORD "solution"
#define INFO_WORD "info"
#define RESTART_WORD "recommencer"
#define AGAIN_WORD "encore"
#define SCRIPT_WORD "script"
#define UNSCRIPT_WORD "unscript"
#define QUIT_WORD "quitter"
#define UNDO_WORD "annuler"
#define OOPS_WORD "oops"
#define FROM_WORD "depuis"
#define EXCEPT_WORD "excepté"
#define FOR_WORD "pour"
#define BUT_WORD "mais"
#define AND_WORD "et"
#define THEN_WORD "puis"
#define OF_WORD "de"
#define SHE_WORD "elle"
#define HE_WORD "il"
#define THAT_WORD "ce"
#define THEM_WORD "ces"
#define THOSE_WORD "ceux"
#define THEY_WORD "ils"
#define IT_WORD "il"
#define ITSELF_WORD "lui-même"
#define HIM_WORD "him"
#define HIMSELF_WORD "lui-même"
#define HER_WORD "her"
#define HERSELF_WORD "elle-même"
#define THEMSELVES_WORD "eux-même"
#define YOU_WORD "you"
#define YOURSELF_WORD "yourself"
#define ONES_WORD "ceux"
#define NO_MULTI_VERB "Vous ne pouvez vous référer à de multiples objets après le mot \"%s\".^"
#define NO_MULTI_START "Vous ne pouvez vous référer à de multiples objets au début d'une commande.^"
#define PERSON_CONCEALING "%s ne semble par porter cela.^"
#define PERSON_POSSESSIVE "%s ne vous laissera pas lui prendre ses affaires.^"
#define CONTAINER_CLOSED "%s est fermé.^"
#define CONTAINER_CLOSED_FEM "%s est fermé.^"
#define FROM_NON_CONTAINER "Le mot \"%s\" doit être suivi par un contenant.^"
#define DOUBLE_EXCEPT "Vous ne pouvez utiliser le mot \"%s\" qu'une fois par référence d'objet.^"
#define NONE_HELD "Vous ne portez rien de cela.^"
#define NO_OBJECTS "Je ne comprends pas ce à quoi vous vous réferez.^"
#define NO_FILENAME "Les commandes de sauvegarde et lecture doivent être suivies par un nom de fichier.^"
#define MOVE_UNDONE "Le tour précédent a été annulé.^^"
#define NO_UNDO "Il n'y a rien à annuler.^"
#define CANT_SAVE "Impossible de sauvegarder l'état du jeu sur fichier.^"
#define CANT_RESTORE "Impossible de récupérer l'état du jeu depuis le fichier.^"
#define GAME_SAVED "Jeu sauvegardé.^"
#define INCOMPLETE_SENTENCE "La phrase que vous avez tapée n'est pas complète.^"
#define UNKNOWN_OBJECT "Vous ne pouvez voir ~"
#define UNKNOWN_OBJECT_END "~.^"
#define CANT_USE_WORD "Vous ne pouvez utiliser le mot ~"
#define IN_CONTEXT "~ dans ce contexte.^"
#define DONT_SEE "Vous ne voyez pas "
#define HERE_WORD " ici.^"
#define BAD_SAVED_GAME "Ficher de sauvegarde incompatible."
#define ARENT "ne sont pas"
#define ISNT "n'est pas"
#define ARE "sont"
#define IS "est"
#define DONT "ne font pas"
#define DOESNT "ne fait pas"
#define DO "font"
#define DOES "fait"
#define SCORE_UP "^[VOTRE SCORE VIENT D'AUGMENTER DE "
#define POINT " POINT]^"
#define POINTS " POINTS]^"
#define STARTING "Démarrage."
#define NO_IT "Vous devez préalablement avoir fait référence à un nom reconnu pour pouvoir utiliser le mot ~"
#define NO_IT_END "~.^"
#define BACK_REFERENCE "Vous devez préalablement avoir fait référence à un nom reconnu dans la même phrase pour pouvoir utiliser le mot ~"
#define BACK_REFERENCE_END "~.^"
#define WHEN_YOU_SAY "When you say ~"
#define MUST_SPECIFY "~, vous devez spécifier si vous voulez dire "
#define OR_WORD " ou "
/* SYSTEM MESSAGES */
#define READ_ERROR "Erreur de lecture du fichier de jeu."
#define OLD_INTERPRETER "La version de l'interpréteur est plus ancienne que le fichier de jeu (v%d), impossible de continuer."
#define BAD_CURSOR "You can only use the ~cursor~ command in the status window.^"
#define INCOMPLETE_GRAMMAR "Incomplete grammar statement."
#define GAME_MODIFIED "Game file modified, reloading.\n"
#define NOT_INTEGER "In function \"%s\", \"%s\" command requires integer parameter."
#define NO_NAME_FUNCTION "In line %d, a function must have at least one name."
#define MAXIMUM_ATTRIBUTES_ERR "In line %d, unable to create attribute \"%s\", maximum number of attributes already defined."
#define BAD_PLAYER "In function \"%s\", attempt to use object pointer \"player\" while it does not point to an object (%d)."
#define BAD_PARENT "In function \"%s\", attempt to use the variable 'here' while the variable 'player' does not have a legal parent."
#define BAD_POINTER "In function \"%s\", attempt to use object pointer \"%s\" that does not point to an object (%d)."
#define ILLEGAL_LABEL "In line %d, reserved word \"%s\" used as label."
#define USED_LABEL_INT "In line %d, \"%s\" is already used as a variable label."
#define USED_LABEL_CINT "In line %d, \"%s\" is already used as an integer constant label."
#define USED_LABEL_STR "In line %d, \"%s\" is already used as a string label."
#define USED_LABEL_CSTR "In line %d, \"%s\" is already used as a string constant label."
#define USED_LABEL_ATT "In line %d, \"%s\" is already used as an attribute label."
#define USED_LABEL_OBJ "In line %d, \"%s\" is already used as an object or location label."
#define NO_OBJECT_ERR "In line %d, property \"%s\" defined before first object or location."
#define BAD_INCLUDE "'#include' directive must be followed by file name enclosed in double quotes."
#define BAD_PARAMETER "Unknown or inappropriate type of container '%s' associated with parameter '%s'."
#define BAD_VALUE "Value '%s' cannot be stored in container '%s'."
#define NO_MEDIA "WebJACL: Media file \"%s\" not found, external media support disabled.\n"
#define MEDIA_REGISTERED "WebJACL: Registered %d media.\n"
#define CLEANING_UP "WebJACL: Cleaning up...\n"
#define NO_GAME "No game file specified, can't continue."
#define NO_PORT "WebJACL: No port number specified (-p <number>), using default port %d.\n"
#define WEBJACL_CONFIGURED "WebJACL server configured on %s:%d\n"
#define NOT_FOUND "Unable to open game file, can't continue."
#define CANT_OPEN "Unable to open processed file \"%s\", can't continue."
#define CANT_RUN "A JACL game must contain at least one object (to represent the player), and at least one location (for the player to start in).^"
#define NO_PLAYER "The object pointer 'player' does not point to an object.^"
#define SELF_REFERENCE "In function \"%s\", reference to object \"%s\" whose parent is itself."
#define EXECUTING "Executing function \"%s\".\n"
#define NO_WHILE "In function \"%s\", 'endwhile' command without matching 'while' command."
#define NO_ITERATE "In function \"%s\", 'enditerate' command without matching 'iterate' command."
#define NO_UPDATE "In function \"%s\", 'endupdate' command without matching 'update' command."
#define NO_REPEAT "In function \"%s\", 'until' command without matching 'repeat' command."
#define NO_LOOP "In function \"%s\", 'endloop' command without matching 'loop' command."
#define UNDEFINED_FUNCTION "In function \"%s\", attempt to execute undefined function \"%s\"."
#define DIVIDE_BY_ZERO "In function \"%s\", division by zero error."
#define ILLEGAL_OPERATOR "In function \"%s\", illegal operator \"%s\"."
#define UNKNOWN_COMMAND "In function \"%s\", unknown command \"%s\"."
#define STACK_OVERFLOW "Stack overflow."
#define ILLEGAL_OPERATOR "In function \"%s\", illegal operator \"%s\"."
#define OUT_OF_RANGE "In function \"%s\", element \"%s\" out of range (%d)."
#define GLOBAL_SELF "Reference to 'self' from global function \"%s\"."
#define NON_GLOBAL_FIRST "In line %d, non-global function before object or location."
#define MAXIMUM_EXCEEDED "Maximum number of objects exceeded, can't continue."
#define ERROR_DETECTED "1 error detected."
#define ERRORS_DETECTED "%d errors detected."
#define UNKNOWN_FUNCTION_RUN "Attempt to execute unknown function \"%s\"."
#define UNKNOWN_KEYWORD_ERR "In line %d, unknown keyword \"%s\"."
#define UNKNOWN_ATTRIBUTE_ERR "In line %d, unknown attribute \"%s\"."
#define UNKNOWN_VALUE_ERR "In line %d, unable to resolve value \"%s\"."
#define UNKNOWN_ATTRIBUTE_RUN "In function \"%s\", reference to unknown attribute \"%s\"."
#define INSUFFICIENT_PARAMETERS_RUN "In function \"%s\", \"%s\" command with insufficient parameters."
#define INSUFFICIENT_PARAMETERS_ERR "In line %d, \"%s\" keyword with insufficient parameters."
#define UNDEFINED_ITEM_ERR "In line %d, reference to undefined item \"%s\"."
#define UNDEFINED_ITEM_RUN "In function \"%s\", reference to undefined object \"%s\"."
#define UNDEFINED_DIRECTION_RUN "In function \"%s\", reference to undefined direction \"%s\"."
#define UNKNOWN_SCOPE_RUN "In function \"%s\", reference to unknown scope \"%s\"."
#define UNDEFINED_STRING_RUN "In function \"%s\", reference to undefined string \"%s\"."
#define UNDEFINED_CONTAINER_RUN "In function \"%s\", reference to undefined container \"%s\"."
#define OUT_OF_MEMORY "Out of memory, can't continue."
#define CANT_OPEN_PROCESSED "Unable to open output file \"%s\" for writing, can't continue."
#define CANT_OPEN_OR "Unable to open source file \"%s\" or \"%s\", can't continue."
#define CANT_OPEN_SOURCE "Unable to open source file \"%s\", can't continue."
#endif
#if NATIVE_LANGUAGE==GERMAN
/* GAME MESSAGES */
#define COMMENT_IGNORED "No transcript running, comment ignored.^"
#define COMMENT_RECORDED "Comment recorded.^"
#define YES_WORD "yes"
#define NO_WORD "no"
#define YES_OR_NO "^Please enter ~yes~ or ~no~: "
#define YES_WORD "yes"
#define NO_WORD "no"
#define INVALID_SELECTION "Invalid selection.^"
#define RESTARTING "^Restarting...^"
#define RETURN_GAME "^Returning to game.^"
#define SCRIPTING_ON "Scripting on.^"
#define SCRIPTING_OFF "Scripting off.^"
#define SCRIPTING_ALREADY_OFF "Scripting already off.^"
#define SCRIPTING_ALREADY_ON "Scripting already on.^"
#define CANT_WRITE_SCRIPT "Unable to write to script file.^"
#define ERROR_READING_WALKTHRU "Error reading walkthru file.^"
#define BAD_OOPS "You must follow the ~oops~ command with the word you wish to use instead.^"
#define CANT_CORRECT "I can't correct the last command using ~oops~, sorry.^"
#define SURE_QUIT "Are you sure you want to quit?^"
#define SURE_RESTART "Are you sure you want to restart?^"
#define NOT_CLEVER "It wasn't so clever as to be worth repeating.^"
#define NO_MOVES "But you haven't done anything yet!^"
#define TYPE_NUMBER "^Type a number between %d and %d: "
#define BY "By ~"
#define REFERRING_TO "~, are you referring to:^"
#define WALKTHRU_WORD "walkthru"
#define INFO_WORD "info"
#define RESTART_WORD "restart"
#define AGAIN_WORD "again"
#define SCRIPT_WORD "script"
#define UNSCRIPT_WORD "unscript"
#define QUIT_WORD "quit"
#define UNDO_WORD "undo"
#define OOPS_WORD "oops"
#define FROM_WORD "from"
#define EXCEPT_WORD "except"
#define FOR_WORD "for"
#define BUT_WORD "but"
#define AND_WORD "and"
#define THEN_WORD "then"
#define OF_WORD "of"
#define SHE_WORD "she"
#define HE_WORD "he"
#define THAT_WORD "that"
#define THEM_WORD "them"
#define THOSE_WORD "those"
#define THEY_WORD "they"
#define IT_WORD "it"
#define ITSELF_WORD "itself"
#define HIM_WORD "him"
#define HIMSELF_WORD "himself"
#define HER_WORD "her"
#define HERSELF_WORD "herself"
#define THEMSELVES_WORD "themselves"
#define YOU_WORD "you"
#define YOURSELF_WORD "yourself"
#define ONES_WORD "ones"
#define NO_MULTI_VERB "You can't refer to multiple objects directly after the word ~%s~.^"
#define NO_MULTI_START "You can't refer to multiple objects at the start of a command.^"
#define PERSON_CONCEALING "%s doesn't seem to be carrying any such thing.^"
#define PERSON_POSSESSIVE "%s isn't about to let you take anything of theirs.^"
#define CONTAINER_CLOSED "%s is closed.^"
#define CONTAINER_CLOSED_FEM "%s is closed.^"
#define FROM_NON_CONTAINER "The word ~%s~ must be followed by a container.^"
#define DOUBLE_EXCEPT "You can only use the word ~%s~ once per object reference.^"
#define NONE_HELD "You are not holding anything like that.^"
#define NO_OBJECTS "I don't see what you are referring to.^"
#define NO_FILENAME "Save and restore commands must be followed by a filename.^"
#define MOVE_UNDONE "Previous move undone.^^"
#define NO_UNDO "Nothing to undo.^"
#define CANT_SAVE "Unable to save game state to file.^"
#define CANT_RESTORE "Unable to restore game state from file.^"
#define GAME_SAVED "Game saved.^"
#define INCOMPLETE_SENTENCE "The sentence you typed was incomplete.^"
#define UNKNOWN_OBJECT "You can't see any such thing as ~"
#define UNKNOWN_OBJECT_END "~.^"
#define CANT_USE_WORD "You can't use the word ~"
#define IN_CONTEXT "~ in that context.^"
#define DONT_SEE "You don't see "
#define HERE_WORD " here.^"
#define BAD_SAVED_GAME "Attempt to restore incompatible saved-game file."
#define ARENT "aren't"
#define ISNT "isn't"
#define ARE "are"
#define IS "is"
#define DONT "don't"
#define DOESNT "doesn't"
#define DO "do"
#define DOES "does"
#define SCORE_UP "^[YOUR SCORE JUST WENT UP BY "
#define POINT " POINT]^"
#define POINTS " POINTS]^"
#define STARTING "Starting."
#define NO_IT "You must have referred to an appropriate noun previously to use the word ~"
#define NO_IT_END "~.^"
#define BACK_REFERENCE "You must have referred to a noun previously in the same sentence to use the word ~"
#define BACK_REFERENCE_END "~.^"
#define WHEN_YOU_SAY "When you say ~"
#define MUST_SPECIFY "~, you must specify whether you mean "
#define OR_WORD " or "
/* SYSTEM MESSAGES */
#define READ_ERROR "Error reading game file."
#define OLD_INTERPRETER "Interpreter version is older than game file (v%d), can't continue."
#define BAD_CURSOR "You can only use the ~cursor~ command in the status window.^"
#define INCOMPLETE_GRAMMAR "Incomplete grammar statement."
#define GAME_MODIFIED "Game file modified, reloading.\n"
#define NOT_INTEGER "In function \"%s\", \"%s\" command requires integer parameter."
#define NO_NAME_FUNCTION "In line %d, a function must have at least one name."
#define MAXIMUM_ATTRIBUTES_ERR "In line %d, unable to create attribute \"%s\", maximum number of attributes already defined."
#define BAD_PLAYER "In function \"%s\", attempt to use object pointer \"player\" while it does not point to an object (%d)."
#define BAD_PARENT "In function \"%s\", attempt to use the variable 'here' while the variable 'player' does not have a legal parent."
#define BAD_POINTER "In function \"%s\", attempt to use object pointer \"%s\" that does not point to an object (%d)."
#define ILLEGAL_LABEL "In line %d, reserved word \"%s\" used as label."
#define USED_LABEL_INT "In line %d, \"%s\" is already used as a variable label."
#define USED_LABEL_CINT "In line %d, \"%s\" is already used as an integer constant label."
#define USED_LABEL_STR "In line %d, \"%s\" is already used as a string label."
#define USED_LABEL_CSTR "In line %d, \"%s\" is already used as a string constant label."
#define USED_LABEL_ATT "In line %d, \"%s\" is already used as an attribute label."
#define USED_LABEL_OBJ "In line %d, \"%s\" is already used as an object or location label."
#define NO_OBJECT_ERR "In line %d, property \"%s\" defined before first object or location."
#define BAD_INCLUDE "'#include' directive must be followed by file name enclosed in double quotes."
#define BAD_PARAMETER "Unknown or inappropriate type of container '%s' associated with parameter '%s'."
#define BAD_VALUE "Value '%s' cannot be stored in container '%s'."
#define NO_MEDIA "WebJACL: Media file \"%s\" not found, external media support disabled.\n"
#define MEDIA_REGISTERED "WebJACL: Registered %d media.\n"
#define CLEANING_UP "WebJACL: Cleaning up...\n"
#define NO_GAME "No game file specified, can't continue."
#define NO_PORT "WebJACL: No port number specified (-p <number>), using default port %d.\n"
#define WEBJACL_CONFIGURED "WebJACL server configured on %s:%d\n"
#define NOT_FOUND "Unable to open game file, can't continue."
#define CANT_OPEN "Unable to open processed file \"%s\", can't continue."
#define CANT_RUN "A JACL game must contain at least one object (to represent the player), and at least one location (for the player to start in).^"
#define NO_PLAYER "The object pointer 'player' does not point to an object.^"
#define SELF_REFERENCE "In function \"%s\", reference to object \"%s\" whose parent is itself."
#define EXECUTING "Executing function \"%s\".\n"
#define NO_WHILE "In function \"%s\", 'endwhile' command without matching 'while' command."
#define NO_ITERATE "In function \"%s\", 'enditerate' command without matching 'iterate' command."
#define NO_UPDATE "In function \"%s\", 'endupdate' command without matching 'update' command."
#define NO_REPEAT "In function \"%s\", 'until' command without matching 'repeat' command."
#define NO_LOOP "In function \"%s\", 'endloop' command without matching 'loop' command."
#define UNDEFINED_FUNCTION "In function \"%s\", attempt to execute undefined function \"%s\"."
#define DIVIDE_BY_ZERO "In function \"%s\", division by zero error."
#define ILLEGAL_OPERATOR "In function \"%s\", illegal operator \"%s\"."
#define UNKNOWN_COMMAND "In function \"%s\", unknown command \"%s\"."
#define STACK_OVERFLOW "Stack overflow."
#define ILLEGAL_OPERATOR "In function \"%s\", illegal operator \"%s\"."
#define OUT_OF_RANGE "In function \"%s\", element \"%s\" out of range (%d)."
#define GLOBAL_SELF "Reference to 'self' from global function \"%s\"."
#define NON_GLOBAL_FIRST "In line %d, non-global function before object or location."
#define MAXIMUM_EXCEEDED "Maximum number of objects exceeded, can't continue."
#define ERROR_DETECTED "1 error detected."
#define ERRORS_DETECTED "%d errors detected."
#define UNKNOWN_FUNCTION_RUN "Attempt to execute unknown function \"%s\"."
#define UNKNOWN_KEYWORD_ERR "In line %d, unknown keyword \"%s\"."
#define UNKNOWN_ATTRIBUTE_ERR "In line %d, unknown attribute \"%s\"."
#define UNKNOWN_VALUE_ERR "In line %d, unable to resolve value \"%s\"."
#define UNKNOWN_ATTRIBUTE_RUN "In function \"%s\", reference to unknown attribute \"%s\"."
#define INSUFFICIENT_PARAMETERS_RUN "In function \"%s\", \"%s\" command with insufficient parameters."
#define INSUFFICIENT_PARAMETERS_ERR "In line %d, \"%s\" keyword with insufficient parameters."
#define UNDEFINED_ITEM_ERR "In line %d, reference to undefined item \"%s\"."
#define UNDEFINED_ITEM_RUN "In function \"%s\", reference to undefined object \"%s\"."
#define UNDEFINED_DIRECTION_RUN "In function \"%s\", reference to undefined direction \"%s\"."
#define UNKNOWN_SCOPE_RUN "In function \"%s\", reference to unknown scope \"%s\"."
#define UNDEFINED_STRING_RUN "In function \"%s\", reference to undefined string \"%s\"."
#define UNDEFINED_CONTAINER_RUN "In function \"%s\", reference to undefined container \"%s\"."
#define OUT_OF_MEMORY "Out of memory, can't continue."
#define CANT_OPEN_PROCESSED "Unable to open output file \"%s\" for writing, can't continue."
#define CANT_OPEN_OR "Unable to open source file \"%s\" or \"%s\", can't continue."
#define CANT_OPEN_SOURCE "Unable to open source file \"%s\", can't continue."
#endif
} // End of namespace JACL
} // End of namespace Glk

533
engines/glk/jacl/libcsv.cpp Normal file
View File

@@ -0,0 +1,533 @@
/* 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/jacl/csv.h"
namespace Glk {
namespace JACL {
#define VERSION "3.0.0"
//#define MAX_INT ((size_t)-1)
#define ROW_NOT_BEGUN 0
#define FIELD_NOT_BEGUN 1
#define FIELD_BEGUN 2
#define FIELD_MIGHT_HAVE_ENDED 3
#define MAX_INT 0x7fff
/*
Explanation of states
ROW_NOT_BEGUN There have not been any fields encountered for this row
FIELD_NOT_BEGUN There have been fields but we are currently not in one
FIELD_BEGUN We are in a field
FIELD_MIGHT_HAVE_ENDED
We encountered a double quote inside a quoted field, the
field is either ended or the quote is literal
*/
#define MEM_BLK_SIZE 128
#define SUBMIT_FIELD(p) \
do { \
if (!quoted) \
entry_pos -= spaces; \
if (p->options & CSV_APPEND_NULL) \
((p)->entry_buf[entry_pos+1]) = '\0'; \
if (cb1) \
cb1(p->entry_buf, entry_pos, data); \
pstate = FIELD_NOT_BEGUN; \
entry_pos = quoted = spaces = 0; \
} while (0)
#define SUBMIT_ROW(p, c) \
do { \
if (cb2) \
cb2(c, data); \
pstate = ROW_NOT_BEGUN; \
entry_pos = quoted = spaces = 0; \
} while (0)
#define SUBMIT_CHAR(p, c) ((p)->entry_buf[entry_pos++] = (c))
static const char *csv_errors[] = {"success",
"error parsing data while strict checking enabled",
"memory exhausted while increasing buffer size",
"data size too large",
"invalid status code"
};
int csv_error(struct csv_parser *p) {
/* Return the current status of the parser */
return p->status;
}
const char *csv_strerror(int status) {
/* Return a textual description of status */
if (status >= CSV_EINVALID || status < 0)
return csv_errors[CSV_EINVALID];
else
return csv_errors[status];
}
int csv_get_opts(struct csv_parser *p) {
/* Return the currently set options of parser */
if (p == nullptr)
return -1;
return p->options;
}
int csv_set_opts(struct csv_parser *p, unsigned char options) {
/* Set the options */
if (p == nullptr)
return -1;
p->options = options;
return 0;
}
int csv_init(struct csv_parser *p, unsigned char options) {
/* Initialize a csv_parser object returns 0 on success, -1 on error */
if (p == nullptr)
return -1;
p->entry_buf = nullptr;
p->pstate = ROW_NOT_BEGUN;
p->quoted = 0;
p->spaces = 0;
p->entry_pos = 0;
p->entry_size = 0;
p->status = 0;
p->options = options;
p->quote_char = CSV_QUOTE;
p->delim_char = CSV_COMMA;
p->is_space = nullptr;
p->is_term = nullptr;
p->blk_size = MEM_BLK_SIZE;
p->malloc_func = nullptr;
p->realloc_func = realloc;
p->free_func = free;
return 0;
}
void csv_free(struct csv_parser *p) {
/* Free the entry_buffer of csv_parser object */
if (p == nullptr)
return;
if (p->entry_buf)
p->free_func(p->entry_buf);
p->entry_buf = nullptr;
p->entry_size = 0;
return;
}
int csv_fini(struct csv_parser *p, void (*cb1)(void *, size_t, void *), void (*cb2)(int c, void *), void *data) {
/* Finalize parsing. Needed, for example, when file does not end in a newline */
int quoted = p->quoted;
int pstate = p->pstate;
size_t spaces = p->spaces;
size_t entry_pos = p->entry_pos;
if (p == nullptr)
return -1;
if (p->pstate == FIELD_BEGUN && p->quoted && p->options & CSV_STRICT && p->options & CSV_STRICT_FINI) {
/* Current field is quoted, no end-quote was seen, and CSV_STRICT_FINI is set */
p->status = CSV_EPARSE;
return -1;
}
switch (p->pstate) {
case FIELD_MIGHT_HAVE_ENDED:
p->entry_pos -= p->spaces + 1; /* get rid of spaces and original quote */
/* Fall-through */
case FIELD_NOT_BEGUN:
case FIELD_BEGUN:
quoted = p->quoted, pstate = p->pstate;
spaces = p->spaces, entry_pos = p->entry_pos;
SUBMIT_FIELD(p);
SUBMIT_ROW(p, -1);
case ROW_NOT_BEGUN: /* Already ended properly */
;
default:
break;
}
/* Reset parser */
p->spaces = p->quoted = p->entry_pos = p->status = 0;
p->pstate = ROW_NOT_BEGUN;
(void)pstate;
return 0;
}
void csv_set_delim(struct csv_parser *p, unsigned char c) {
/* Set the delimiter */
if (p) p->delim_char = c;
}
void csv_set_quote(struct csv_parser *p, unsigned char c) {
/* Set the quote character */
if (p) p->quote_char = c;
}
unsigned char csv_get_delim(struct csv_parser *p) {
/* Get the delimiter */
return p->delim_char;
}
unsigned char csv_get_quote(struct csv_parser *p) {
/* Get the quote character */
return p->quote_char;
}
void csv_set_space_func(struct csv_parser *p, int (*f)(unsigned char)) {
/* Set the space function */
if (p) p->is_space = f;
}
void csv_set_term_func(struct csv_parser *p, int (*f)(unsigned char)) {
/* Set the term function */
if (p) p->is_term = f;
}
void csv_set_realloc_func(struct csv_parser *p, void *(*f)(void *, size_t)) {
/* Set the realloc function used to increase buffer size */
if (p && f) p->realloc_func = f;
}
void csv_set_free_func(struct csv_parser *p, void (*f)(void *)) {
/* Set the free function used to free the buffer */
if (p && f) p->free_func = f;
}
void csv_set_blk_size(struct csv_parser *p, size_t size) {
/* Set the block size used to increment buffer size */
if (p) p->blk_size = size;
}
size_t csv_get_buffer_size(struct csv_parser *p) {
/* Get the size of the entry buffer */
if (p)
return p->entry_size;
return 0;
}
static int csv_increase_buffer(struct csv_parser *p) {
/* Increase the size of the entry buffer. Attempt to increase size by
* p->blk_size, if this is larger than MAX_INT try to increase current
* buffer size to MAX_INT. If allocation fails, try to allocate halve
* the size and try again until successful or increment size is zero.
*/
size_t to_add = p->blk_size;
void *vp;
if (p->entry_size >= MAX_INT - to_add)
to_add = MAX_INT - p->entry_size;
if (!to_add) {
p->status = CSV_ETOOBIG;
return -1;
}
while ((vp = p->realloc_func(p->entry_buf, p->entry_size + to_add)) == nullptr) {
to_add /= 2;
if (!to_add) {
p->status = CSV_ENOMEM;
return -1;
}
}
/* Update entry buffer pointer and entry_size if successful */
p->entry_buf = (unsigned char *)vp;
p->entry_size += to_add;
return 0;
}
size_t csv_parse(struct csv_parser *p, const void *s, size_t len, void (*cb1)(void *, size_t, void *),
void (*cb2)(int c, void *), void *data) {
unsigned const char *us = (unsigned const char *)s; /* Access input data as array of unsigned char */
unsigned char c; /* The character we are currently processing */
size_t pos = 0; /* The number of characters we have processed in this call */
/* Store key fields into local variables for performance */
unsigned char delim = p->delim_char;
unsigned char quote = p->quote_char;
int (*is_space)(unsigned char) = p->is_space;
int (*is_term)(unsigned char) = p->is_term;
int quoted = p->quoted;
int pstate = p->pstate;
size_t spaces = p->spaces;
size_t entry_pos = p->entry_pos;
if (!p->entry_buf && pos < len) {
/* Buffer hasn't been allocated yet and len > 0 */
if (csv_increase_buffer(p) != 0) {
p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos;
return pos;
}
}
while (pos < len) {
/* Check memory usage, increase buffer if necessary */
if (entry_pos == ((p->options & CSV_APPEND_NULL) ? p->entry_size - 1 : p->entry_size)) {
if (csv_increase_buffer(p) != 0) {
p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos;
return pos;
}
}
c = us[pos++];
switch (pstate) {
case ROW_NOT_BEGUN:
case FIELD_NOT_BEGUN:
if (is_space ? is_space(c) : c == CSV_SPACE || c == CSV_TAB) { /* Space or Tab */
continue;
} else if (is_term ? is_term(c) : c == CSV_CR || c == CSV_LF) { /* Carriage Return or Line Feed */
if (pstate == FIELD_NOT_BEGUN) {
SUBMIT_FIELD(p);
SUBMIT_ROW(p, (unsigned char)c);
} else { /* ROW_NOT_BEGUN */
/* Don't submit empty rows by default */
if (p->options & CSV_REPALL_NL) {
SUBMIT_ROW(p, (unsigned char)c);
}
}
continue;
} else if (c == delim) { /* Comma */
SUBMIT_FIELD(p);
break;
} else if (c == quote) { /* Quote */
pstate = FIELD_BEGUN;
quoted = 1;
} else { /* Anything else */
pstate = FIELD_BEGUN;
quoted = 0;
SUBMIT_CHAR(p, c);
}
break;
case FIELD_BEGUN:
if (c == quote) { /* Quote */
if (quoted) {
SUBMIT_CHAR(p, c);
pstate = FIELD_MIGHT_HAVE_ENDED;
} else {
/* STRICT ERROR - double quote inside non-quoted field */
if (p->options & CSV_STRICT) {
p->status = CSV_EPARSE;
p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos;
return pos - 1;
}
SUBMIT_CHAR(p, c);
spaces = 0;
}
} else if (c == delim) { /* Comma */
if (quoted) {
SUBMIT_CHAR(p, c);
} else {
SUBMIT_FIELD(p);
}
} else if (is_term ? is_term(c) : c == CSV_CR || c == CSV_LF) { /* Carriage Return or Line Feed */
if (!quoted) {
SUBMIT_FIELD(p);
SUBMIT_ROW(p, (unsigned char)c);
} else {
SUBMIT_CHAR(p, c);
}
} else if (!quoted && (is_space ? is_space(c) : c == CSV_SPACE || c == CSV_TAB)) { /* Tab or space for non-quoted field */
SUBMIT_CHAR(p, c);
spaces++;
} else { /* Anything else */
SUBMIT_CHAR(p, c);
spaces = 0;
}
break;
case FIELD_MIGHT_HAVE_ENDED:
/* This only happens when a quote character is encountered in a quoted field */
if (c == delim) { /* Comma */
entry_pos -= spaces + 1; /* get rid of spaces and original quote */
SUBMIT_FIELD(p);
} else if (is_term ? is_term(c) : c == CSV_CR || c == CSV_LF) { /* Carriage Return or Line Feed */
entry_pos -= spaces + 1; /* get rid of spaces and original quote */
SUBMIT_FIELD(p);
SUBMIT_ROW(p, (unsigned char)c);
} else if (is_space ? is_space(c) : c == CSV_SPACE || c == CSV_TAB) { /* Space or Tab */
SUBMIT_CHAR(p, c);
spaces++;
} else if (c == quote) { /* Quote */
if (spaces) {
/* STRICT ERROR - unescaped double quote */
if (p->options & CSV_STRICT) {
p->status = CSV_EPARSE;
p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos;
return pos - 1;
}
spaces = 0;
SUBMIT_CHAR(p, c);
} else {
/* Two quotes in a row */
pstate = FIELD_BEGUN;
}
} else { /* Anything else */
/* STRICT ERROR - unescaped double quote */
if (p->options & CSV_STRICT) {
p->status = CSV_EPARSE;
p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos;
return pos - 1;
}
pstate = FIELD_BEGUN;
spaces = 0;
SUBMIT_CHAR(p, c);
}
break;
default:
break;
}
}
p->quoted = quoted, p->pstate = pstate, p->spaces = spaces, p->entry_pos = entry_pos;
return pos;
}
size_t csv_write(void *dest, size_t dest_size, const void *src, size_t src_size) {
unsigned char *cdest = (unsigned char *)dest;
const unsigned char *csrc = (const unsigned char *)src;
size_t chars = 0;
if (src == nullptr)
return 0;
if (cdest == nullptr)
dest_size = 0;
if (dest_size > 0)
*cdest++ = '"';
chars++;
while (src_size) {
if (*csrc == '"') {
if (dest_size > chars)
*cdest++ = '"';
if (chars < MAX_INT) chars++;
}
if (dest_size > chars)
*cdest++ = *csrc;
if (chars < MAX_INT) chars++;
src_size--;
csrc++;
}
if (dest_size > chars)
*cdest = '"';
if (chars < MAX_INT) chars++;
return chars;
}
int csv_fwrite(Common::WriteStream *fp, const void *src, size_t src_size) {
const unsigned char *csrc = (const unsigned char *)src;
if (fp == nullptr || src == nullptr)
return 0;
fp->writeByte('"');
while (src_size) {
if (*csrc == '"') {
fp->writeByte('"');
}
fp->writeByte(*csrc);
src_size--;
csrc++;
}
fp->writeByte('"');
return 0;
}
size_t csv_write2(void *dest, size_t dest_size, const void *src, size_t src_size, unsigned char quote) {
unsigned char *cdest = (unsigned char *)dest;
const unsigned char *csrc = (const unsigned char *)src;
size_t chars = 0;
if (src == nullptr)
return 0;
if (dest == nullptr)
dest_size = 0;
if (dest_size > 0)
*cdest++ = quote;
chars++;
while (src_size) {
if (*csrc == quote) {
if (dest_size > chars)
*cdest++ = quote;
if (chars < MAX_INT) chars++;
}
if (dest_size > chars)
*cdest++ = *csrc;
if (chars < MAX_INT) chars++;
src_size--;
csrc++;
}
if (dest_size > chars)
*cdest = quote;
if (chars < MAX_INT) chars++;
return chars;
}
int csv_fwrite2(Common::WriteStream *fp, const void *src, size_t src_size, unsigned char quote) {
const unsigned char *csrc = (const unsigned char *)src;
if (fp == nullptr || src == nullptr)
return 0;
fp->writeByte(quote);
while (src_size) {
if (*csrc == quote) {
fp->writeByte(quote);
}
fp->writeByte(*csrc);
src_size--;
csrc++;
}
fp->writeByte(quote);
return 0;
}
} // End of namespace JACL
} // End of namespace Glk

1674
engines/glk/jacl/loader.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
/* 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/jacl/jacl.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
#include "glk/jacl/language.h"
namespace Glk {
namespace JACL {
extern char user_id[];
extern char prefix[];
void log_error(const char *message, int console) {
/* LOG A MESSAGE TO THE CONSOLE */
char consoleMessage[256];
event_t event;
// BUILD A STRING SUITABLE FOR DISPLAY ON THE CONSOLE.
Common::sprintf_s(consoleMessage, "ERROR: %s^", message);
g_vm->glk_set_style(style_Alert);
write_text(consoleMessage);
g_vm->glk_set_style(style_Normal);
// FLUSH THE GLK WINDOW SO THE ERROR GETS DISPLAYED IMMEDIATELY.
g_vm->glk_select_poll(&event);
}
} // End of namespace JACL
} // End of namespace Glk

1917
engines/glk/jacl/parser.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
/* 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 JACL {
#ifdef GLK
extern strid_t open_glk_file(uint usage, uint mode, char *filename);
extern glui32 glk_get_bin_line_stream(strid_t file_stream, char *buffer, glui32 max_length);
extern glui32 parse_utf8(unsigned char *buf, glui32 buflen, glui32 *out, glui32 outlen);
extern void convert_to_utf8(glui32 *text, int len);
#else
extern void update_parameters();
#endif
extern int bearing(double x1, double y1, double x2, double y2);
extern int distance(double x1, double y1, double x2, double y2);
extern int strcondition();
extern int and_strcondition();
extern int logic_test(int first);
extern int str_test(int first);
extern int first_available(int list_number);
extern int validate(const char *string);
extern int noun_resolve(struct word_type *scope_word, int finding_from, int noun_number);
extern int get_from_object(struct word_type *scope_word, int noun_number);
extern int is_direct_child_of_from(int child);
extern int is_child_of_from(int child);
extern int verify_from_object(int from_object);
extern int find_parent(int index);
extern int scope(int index, const char *expected, int restricted = 0);
extern int object_element_resolve(const char *textstring);
extern int execute(const char *funcname);
extern int object_resolve(const char *object_string);
extern int random_number();
extern void log_error(const char *message, int console);
extern int parent_of(int parent_, int child, int restricted);
extern int grand_of(int child, int objs_only);
extern int check_light(int where);
extern int find_route(int fromRoom, int toRoom, int known);
extern int exit_function(int return_code);
extern int count_resolve(const char *textstring);
extern void jacl_set_window(winid_t new_window);
extern void create_cstring(const char *name, const char *value);
extern void create_string(const char *name, const char *value);
extern void create_integer(const char *name, int value);
extern void create_cinteger(const char *name, int value);
extern void scripting();
extern void undoing();
extern void walking_thru();
#ifndef GLK
extern void create_paths(char *full_path);
#endif
extern int get_key();
extern char get_character(const char *message);
extern int get_yes_or_no();
extern void get_string(char *string_buffer);
extern int get_number(int insist, int low, int high);
extern int save_interaction();
extern int restore_interaction();
extern void jacl_encrypt(char *string);
extern void jacl_decrypt(char *string);
//extern void log_message(const char *message, int console);
extern void set_them(int noun_number);
extern void preparse();
extern void inspect(int object_num);
extern void add_all(struct word_type *scope_word, int noun_number);
extern void add_to_list(int noun_number, int resolved_object);
extern void call_functions(const char *base_name);
extern int build_object_list(struct word_type *scope_word, int noun_number);
extern long value_of(const char *value, int run_time = 0);
extern long attribute_resolve(const char *attribute);
extern long user_attribute_resolve(const char *name);
extern struct word_type *exact_match(struct word_type *pointer);
extern struct word_type *object_match(struct word_type *iterator, int noun_number);
extern struct integer_type *integer_resolve(const char *name);
extern struct integer_type *integer_resolve_indexed(const char *name, int index);
extern struct function_type *function_resolve(const char *name);
extern struct string_type *string_resolve(const char *name);
extern struct string_type *string_resolve_indexed(const char *name, int index);
extern struct string_type *cstring_resolve(const char *name);
extern struct string_type *cstring_resolve_indexed(const char *name, int index);
extern struct cinteger_type *cinteger_resolve(const char *name);
extern struct cinteger_type *cinteger_resolve_indexed(const char *name, int index);
extern int array_length_resolve(const char *textstring);
extern int legal_label_check(const char *word, int line, int type);
extern char *object_names(int object_index, char *names_buffer);
extern const char *arg_text_of(const char *string);
extern const char *arg_text_of_word(int wordnumber);
extern const char *var_text_of_word(int wordnumber);
extern const char *text_of(const char *string);
extern const char *text_of_word(int wordnumber);
extern const char *expand_function(const char *name);
extern int *container_resolve(const char *container_name);
extern int condition();
extern int and_condition();
extern void free_from(struct word_type *x);
extern void eachturn();
extern int jacl_whitespace(char character);
extern int get_here();
extern char *stripwhite(char *string);
extern void command_encapsulate();
extern void encapsulate();
extern void jacl_truncate();
extern void parser();
extern void diagnose();
extern void look_around();
extern char *macro_resolve(const char *textstring);
extern char *plain_output(int index, int capital);
extern char *sub_output(int index, int capital);
extern char *obj_output(int index, int capital);
extern char *that_output(int index, int capital);
extern char *sentence_output(int index, int capital);
extern char *isnt_output(int index, bool unused = false);
extern char *is_output(int index, bool unused = false);
extern char *it_output(int index, bool unused = false);
extern char *doesnt_output(int index, bool unused = false);
extern char *does_output(int index, bool unused = false);
extern char *list_output(int index, int capital);
extern char *long_output(int index);
extern void terminate(int code);
extern void set_arguments(const char *function_call);
extern void pop_stack();
extern void push_stack(int32 file_pointer);
extern void pop_proxy();
extern void push_proxy();
extern void write_text(const char *string_buffer);
extern void status_line();
extern void newline();
extern bool save_game(strid_t save);
extern bool restore_game(strid_t save, bool warn = false);
extern void write_integer(strid_t stream, int x);
extern int read_integer(strid_t stream);
extern void write_long(strid_t stream, long x);
extern long read_long(strid_t stream);
extern void save_game_state();
extern void restore_game_state();
extern void add_cstring(const char *name, const char *value);
extern void clear_cstring(const char *name);
extern void add_cinteger(const char *name, int value);
extern void clear_cinteger(const char *name);
extern void restart_game();
extern void read_gamefile();
extern void new_position(double x1, double y1, double bearing, double velocity);
extern void build_grammar_table(struct word_type *pointer);
extern void unkvalerr(int line, int wordno);
extern void totalerrs(int errors);
extern void unkatterr(int line, int wordno);
extern void unkfunrun(const char *name);
extern void nofnamerr(int line);
extern void nongloberr(int line);
extern void unkkeyerr(int line, int wordno);
extern void maxatterr(int line, int wordno);
extern void unkattrun(int wordno);
extern void badptrrun(const char *name, int value);
extern void badplrrun(int value);
extern void badparrun();
extern void notintrun();
extern void noproprun(int unused = 0);
extern void noproperr(int line);
extern void noobjerr(int line);
extern void unkobjerr(int line, int wordno);
extern void unkobjrun(int wordno);
extern void unkdirrun(int wordno);
extern void unkscorun(const char *scope);
extern void unkstrrun(const char *variable);
extern void unkvarrun(const char *variable);
extern void outofmem();
extern void set_defaults();
extern void no_it();
extern void more(const char *message);
extern int jpp();
extern int process_file(const char *sourceFile1, char *sourceFile2);
extern char *strip_return(char *string);
extern const char *object_generator(const char *text, int state);
extern const char *verb_generator(const char *text, int state);
extern void add_word(const char *word);
extern void create_language_constants();
extern int select_next();
extern void jacl_sleep(unsigned int mseconds);
} // End of namespace JACL
} // End of namespace Glk

File diff suppressed because it is too large Load Diff

223
engines/glk/jacl/types.h Normal file
View File

@@ -0,0 +1,223 @@
/* 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/jacl/constants.h"
#include "common/file.h"
namespace Glk {
namespace JACL {
#define DIR_SEPARATOR '/'
#define DATA_DIR "data/"
#define TEMP_DIR "temp/"
#define INCLUDE_DIR "include/"
// THIS STRUCTURE CONTAINS ALL THE INFORMATION THAT NEEDS TO BE
// SAVED IN ORDER TO CALL parse() RECURSIVELY
struct proxy_type {
int object_pointers[4]; // NOUN1 -> NOUN4
int integer[MAX_WORDS]; // THE COMANDS INTEGERS
char text[MAX_WORDS][256]; // THE COMANDS STRINGS
char command[MAX_WORDS][256]; // THE WHOLE COMMAND
int object_list[4][MAX_OBJECTS]; // THE RESOLVED OBJECTS
int list_size[4]; // THE SIZE OF THE ABOVE LISTS
int max_size[4]; // THE LAST USED INDEX OF THE ABOVE LISTS
int start_of_this_command; // PREPARSE STATE
int start_of_last_command; // PREPARSE STATE
int integercount; // THE NUMBER OF INTEGERS SAVED
int textcount; // THE NUMBER OF STRINGS SAVED
int commandcount; // THE NUMBER OF WORDS IN COMMAND
int last_exact; // WORD POINTER FOR MATCH
int after_from; // WORD POINTER FOR FROM WORD
};
struct stack_type {
Common::SeekableReadStream *infile;
Common::WriteStream *outfile;
int arguments[MAX_WORDS];
char str_arguments[MAX_WORDS][256];
char text_buffer[1024];
char called_name[1024];
char _override[84];
char scope_criterion[24];
char default_function[84];
const char *word[MAX_WORDS];
int quoted[MAX_WORDS];
int wp;
int argcount;
int *loop_integer;
int *select_integer;
int criterion_value;
int criterion_type;
int criterion_negate;
int current_level;
int execution_level;
#ifdef GLK
int top_of_loop;
int top_of_select;
int top_of_while;
int top_of_iterate;
int top_of_update;
int top_of_do_loop;
int address;
#else
long top_of_loop;
long top_of_select;
long top_of_while;
long top_of_iterate;
long top_of_update;
long top_of_do_loop;
long address;
#endif
struct function_type *function;
};
struct object_type {
char label[44];
char article[12];
char definite[12];
struct name_type *first_name;
struct name_type *first_plural;
char inventory[44];
char described[84];
int user_attributes;
int user_attributes_backup;
int attributes;
int attributes_backup;
int integer[16];
int integer_backup[16];
int nosave;
};
struct integer_type {
char name[44];
int value;
int value_backup;
struct integer_type *next_integer;
};
struct cinteger_type {
char name[44];
int value;
struct cinteger_type *next_cinteger;
};
struct attribute_type {
char name[44];
int value;
struct attribute_type *next_attribute;
};
struct string_type {
char name[44];
char value[256];
struct string_type *next_string;
};
struct function_type {
char name[84];
#ifdef GLK
glui32 position;
#else
long position;
#endif
int self;
int call_count;
int call_count_backup;
struct function_type *next_function;
};
struct command_type {
char word[44];
struct command_type *next;
};
#ifdef GLK
struct window_type {
char name[44];
winid_t glk_window;
glui32 glk_type;
struct window_type *next_window;
};
#endif
struct word_type {
char word[44];
struct word_type *first_child;
struct word_type *next_sibling;
};
struct synonym_type {
char original[44];
char standard[44];
struct synonym_type *next_synonym;
};
struct name_type {
char name[44];
struct name_type *next_name;
};
struct filter_type {
char word[44];
struct filter_type *next_filter;
};
#ifndef GLK
struct parameter_type {
char name[44];
char container[44];
int low;
int high;
struct parameter_type *next_parameter;
};
#endif
class File : public Common::File {
public:
static File *openForReading(const Common::String &name) {
File *f = new File();
if (f->open(Common::Path(name)))
return f;
delete f;
return nullptr;
}
static Common::WriteStream *openForWriting(const Common::String &name) {
Common::DumpFile *df = new Common::DumpFile();
if (df->open(Common::Path(name)))
return df;
delete df;
return nullptr;
}
public:
File() : Common::File() {}
File(const Common::Path &name) {
Common::File::open(name);
assert(isOpen());
}
};
} // End of namespace JACL
} // End of namespace Glk

248
engines/glk/jacl/utils.cpp Normal file
View File

@@ -0,0 +1,248 @@
/* 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/jacl/jacl.h"
#include "glk/jacl/language.h"
#include "glk/jacl/types.h"
#include "glk/jacl/prototypes.h"
namespace Glk {
namespace JACL {
extern char function_name[];
extern struct object_type *object[];
extern struct variable_type *variable[];
extern int objects;
extern int player;
extern char game_file[];
extern char game_path[];
extern char prefix[];
extern char blorb[];
extern char bookmark[];
extern char walkthru[];
extern char include_directory[];
extern char temp_directory[];
extern char data_directory[];
extern char temp_buffer[];
void eachturn() {
/* INCREMENT THE TOTAL NUMBER OF MOVES MADE AND CALL THE 'EACHTURN'
* FUNCTION FOR THE CURRENT LOCATION AND THE GLOBAL 'EACHTURN'
* FUNCTION. THESE FUNCTIONS CONTAIN ANY CODE THAT SIMULATED EVENTS
* OCCURRING DUE TO THE PASSING OF TIME */
TOTAL_MOVES->value++;
execute("+eachturn");
Common::strcpy_s(function_name, 81, "eachturn_");
Common::strcat_s(function_name, 81, object[HERE]->label);
execute(function_name);
execute("+system_eachturn");
/* SET TIME TO FALSE SO THAT NO MORE eachturn FUNCTIONS ARE EXECUTED
* UNTIL EITHER THE COMMAND PROMPT IS RETURNED TO (AND TIME IS SET
* TO TRUE AGAIN, OR IT IS MANUALLY SET TO TRUE BY A VERB THAT CALLS
* MORE THAN ONE proxy COMMAND. THIS IS BECAUSE OTHERWISE A VERB THAT
* USES A proxy COMMAND TO TRANSLATE THE VERB IS RESULT IN TWO MOVES
* (OR MORE) HAVING PASSED FOR THE ONE ACTION. */
TIME->value = FALSE;
}
int get_here() {
/* THIS FUNCTION RETURNS THE VALUE OF 'here' IN A SAFE, ERROR CHECKED
* WAY */
if (player < 1 || player > objects) {
badplrrun(player);
terminate(44);
return 0;
} else if (object[player]->PARENT < 1 || object[player]->PARENT > objects || object[player]->PARENT == player) {
badparrun();
terminate(44);
return 0;
} else {
return (object[player]->PARENT);
}
}
char *strip_return(char *string) {
/* STRIP ANY TRAILING RETURN OR NEWLINE OFF THE END OF A STRING */
int index;
int length = strlen(string);
for (index = 0; index < length; index++) {
switch (string[index]) {
case '\r':
case '\n':
string[index] = 0;
break;
default:
break;
}
}
return string;
}
int random_number() {
return g_vm->getRandomNumber(0x7fffffff);
}
#ifndef GLK
void create_paths(char *full_path) {
int index;
char *last_slash;
/* SAVE A COPY OF THE SUPPLIED GAMEFILE NAME */
strcpy(game_file, full_path);
/* FIND THE LAST SLASH IN THE SPECIFIED GAME PATH AND REMOVE THE GAME
* FILE SUFFIX IF ANY EXISTS */
last_slash = (char *)nullptr;
/* GET A POINTER TO THE LAST SLASH IN THE FULL PATH */
last_slash = strrchr(full_path, DIR_SEPARATOR);
for (index = strlen(full_path); index >= 0; index--) {
if (full_path[index] == DIR_SEPARATOR) {
/* NO '.' WAS FOUND BEFORE THE LAST SLASH WAS REACHED,
* THERE IS NO FILE EXTENSION */
break;
} else if (full_path[index] == '.') {
full_path[index] = 0;
break;
}
}
/* STORE THE GAME PATH AND THE GAME FILENAME PARTS SEPARATELY */
if (last_slash == (const char *) nullptr) {
/* GAME MUST BE IN CURRENT DIRECTORY SO THERE WILL BE NO GAME PATH */
strcpy(prefix, full_path);
game_path[0] = 0;
/* THIS ADDITION OF ./ TO THE FRONT OF THE GAMEFILE IF IT IS IN THE
* CURRENT DIRECTORY IS REQUIRED TO KEEP Gargoyle HAPPY. */
#ifdef __NDS__
Common::sprintf_s(temp_buffer, "%c%s", DIR_SEPARATOR, game_file);
#else
Common::sprintf_s(temp_buffer, ".%c%s", DIR_SEPARATOR, game_file);
#endif
strcpy(game_file, temp_buffer);
} else {
/* STORE THE DIRECTORY THE GAME FILE IS IN WITH THE TRAILING
* SLASH IF THERE IS ONE */
last_slash++;
strcpy(prefix, last_slash);
*last_slash = '\0';
strcpy(game_path, full_path);
}
#ifdef GLK
/* SET DEFAULT WALKTHRU FILE NAME */
Common::sprintf_s(walkthru, "%s.walkthru", prefix);
/* SET DEFAULT SAVED GAME FILE NAME */
Common::sprintf_s(bookmark, "%s.bookmark", prefix);
/* SET DEFAULT BLORB FILE NAME */
Common::sprintf_s(blorb, "%s.blorb", prefix);
#endif
/* SET DEFAULT FILE LOCATIONS IF NOT SET BY THE USER IN CONFIG */
if (include_directory[0] == 0) {
strcpy(include_directory, game_path);
strcat(include_directory, INCLUDE_DIR);
}
if (temp_directory[0] == 0) {
strcpy(temp_directory, game_path);
strcat(temp_directory, TEMP_DIR);
}
if (data_directory[0] == 0) {
strcpy(data_directory, game_path);
strcat(data_directory, DATA_DIR);
}
}
#endif
int jacl_whitespace(char character) {
/* CHECK IF A CHARACTER IS CONSIDERED WHITE SPACE IN THE JACL LANGUAGE */
switch (character) {
case ':':
case '\t':
case ' ':
return (TRUE);
default:
return (FALSE);
}
}
char *stripwhite(char *string) {
int i;
/* STRIP WHITESPACE FROM THE START AND END OF STRING. */
while (jacl_whitespace(*string)) string++;
i = strlen(string) - 1;
while (i >= 0 && ((jacl_whitespace(*(string + i))) || *(string + i) == '\n' || *(string + i) == '\r')) i--;
#ifdef WIN32
i++;
*(string + i) = '\r';
#endif
i++;
*(string + i) = '\n';
i++;
*(string + i) = '\0';
return string;
}
void jacl_encrypt(char *string) {
int index, length;
length = strlen(string);
for (index = 0; index < length; index++) {
if (string[index] == '\n' || string[index] == '\r') {
return;
}
string[index] = string[index] ^ 255;
}
}
void jacl_decrypt(char *string) {
int index, length;
length = strlen(string);
for (index = 0; index < length; index++) {
if (string[index] == '\n' || string[index] == '\r') {
return;
}
string[index] = string[index] ^ 255;
}
}
} // End of namespace JACL
} // End of namespace Glk

View File

@@ -0,0 +1,25 @@
/* 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/>.
*
*/
#define J_VERSION 2
#define J_RELEASE 9
#define J_BUILD 0
#define INTERPRETER_VERSION 209