mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-08 19:00:57 +00:00
GLK: TADS: Add a number of GLK interface methods
This commit is contained in:
parent
5ab65b0954
commit
41b62ab00d
@ -394,7 +394,7 @@ void GlkAPI::glk_put_string_stream(strid_t str, const char *s) {
|
||||
str->putBuffer(s, strlen(s));
|
||||
}
|
||||
|
||||
void GlkAPI::glk_put_buffer(char *buf, glui32 len) {
|
||||
void GlkAPI::glk_put_buffer(const char *buf, glui32 len) {
|
||||
_streams->getCurrent()->putBuffer(buf, len);
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ public:
|
||||
void glk_put_char_stream(strid_t str, unsigned char ch);
|
||||
void glk_put_string(const char *s);
|
||||
void glk_put_string_stream(strid_t str, const char *s);
|
||||
void glk_put_buffer(char *buf, glui32 len);
|
||||
void glk_put_buffer(const char *buf, glui32 len);
|
||||
void glk_put_buffer_stream(strid_t str, const char *buf, glui32 len);
|
||||
void glk_set_style(glui32 styl);
|
||||
void glk_set_style_stream(strid_t str, glui32 styl);
|
||||
|
@ -46,6 +46,7 @@ MODULE_OBJS := \
|
||||
tads/detection.o \
|
||||
tads/tads.o \
|
||||
tads/tads2/ler.o \
|
||||
tads/tads2/os.o \
|
||||
tads/tads2/tads2.o \
|
||||
tads/tads3/tads3.o
|
||||
|
||||
|
@ -31,33 +31,34 @@ TADS::TADS(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gam
|
||||
/*
|
||||
* GLK Initialization
|
||||
*/
|
||||
mainwin = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
|
||||
|
||||
if (!mainwin)
|
||||
// Open the story window
|
||||
story_win = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
|
||||
if (!story_win)
|
||||
error("fatal: could not open window!\n");
|
||||
|
||||
// get default colors for main window
|
||||
if (!glk_style_measure(mainwin, style_Normal, stylehint_TextColor, &mainfg))
|
||||
if (!glk_style_measure(story_win, style_Normal, stylehint_TextColor, &mainfg))
|
||||
mainfg = 0;
|
||||
|
||||
if (!glk_style_measure(mainwin, style_Normal, stylehint_BackColor, &mainbg))
|
||||
if (!glk_style_measure(story_win, style_Normal, stylehint_BackColor, &mainbg))
|
||||
mainbg = 0;
|
||||
|
||||
// get default colors for status window
|
||||
statuswin = glk_window_open(mainwin, winmethod_Above | winmethod_Fixed, 1,
|
||||
status_win = glk_window_open(story_win, winmethod_Above | winmethod_Fixed, 1,
|
||||
wintype_TextGrid, 0);
|
||||
|
||||
if (!glk_style_measure(statuswin, style_Normal, stylehint_TextColor, &statusfg))
|
||||
if (!glk_style_measure(status_win, style_Normal, stylehint_TextColor, &statusfg))
|
||||
statusfg = 0;
|
||||
|
||||
if (!glk_style_measure(statuswin, style_Normal, stylehint_BackColor, &statusbg))
|
||||
if (!glk_style_measure(status_win, style_Normal, stylehint_BackColor, &statusbg))
|
||||
statusbg = 0;
|
||||
|
||||
// close status window; reopened on request
|
||||
glk_window_close(statuswin, 0);
|
||||
statuswin = nullptr;
|
||||
glk_window_close(status_win, 0);
|
||||
status_win = nullptr;
|
||||
|
||||
glk_set_window(mainwin);
|
||||
glk_set_window(story_win);
|
||||
}
|
||||
|
||||
Common::Error TADS::loadGameData(strid_t file) {
|
||||
|
@ -34,7 +34,7 @@ namespace TADS {
|
||||
*/
|
||||
class TADS : public GlkAPI {
|
||||
protected:
|
||||
winid_t mainwin, statuswin;
|
||||
winid_t story_win, status_win;
|
||||
glui32 mainfg, mainbg;
|
||||
glui32 statusfg, statusbg;
|
||||
public:
|
||||
|
@ -26,7 +26,9 @@ namespace Glk {
|
||||
namespace TADS {
|
||||
namespace TADS2 {
|
||||
|
||||
int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
|
||||
#define TRDLOGERR_PREFIX "\n[An error has occurred within TADS: "
|
||||
|
||||
int errcxdef::errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
|
||||
int outlen = 0;
|
||||
int argi = 0;
|
||||
int len;
|
||||
@ -125,54 +127,25 @@ int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv) {
|
||||
return outlen;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) && !defined(ERR_NO_MACRO)
|
||||
void errjmp(jmp_buf buf, int e) {
|
||||
longjmp(buf, e);
|
||||
void errcxdef::errcxlog(void *ctx0, char *fac, int err, int argc, erradef *argv) {
|
||||
#ifdef TODO
|
||||
errcxdef *ctx = (errcxdef *)ctx0;
|
||||
char buf[256];
|
||||
char msg[256];
|
||||
|
||||
// display the prefix message to the console and log file
|
||||
sprintf(buf, TRDLOGERR_PREFIX, fac, err);
|
||||
trdptf("%s", buf);
|
||||
out_logfile_print(buf, false);
|
||||
|
||||
/* display the error message text to the console and log file */
|
||||
errmsg(ctx, msg, (uint)sizeof(msg), err);
|
||||
errfmt(buf, (int)sizeof(buf), msg, argc, argv);
|
||||
trdptf("%s]\n", buf);
|
||||
out_logfile_print(buf, false);
|
||||
out_logfile_print("]", true);
|
||||
#endif
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef ERR_NO_MACRO
|
||||
|
||||
void errsign(errcxdef *ctx, int e, char *facility) {
|
||||
strncpy(ctx->errcxptr->errfac, facility, ERRFACMAX);
|
||||
ctx->errcxptr->errfac[ERRFACMAX] = '\0';
|
||||
ctx->errcxofs = 0;
|
||||
longjmp(ctx->errcxptr->errbuf, e);
|
||||
}
|
||||
|
||||
void errsigf(errcxdef *ctx, char *facility, int e) {
|
||||
errargc(ctx, 0);
|
||||
errsign(ctx, e, facility);
|
||||
}
|
||||
|
||||
char *errstr(errcxdef *ctx, const char *str, int len) {
|
||||
char *ret = &ctx->errcxbuf[ctx->errcxofs];
|
||||
|
||||
memcpy(ret, str, (size_t)len);
|
||||
ret[len] = '\0';
|
||||
ctx->errcxofs += len + 1;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void errrse1(errcxdef *ctx, errdef *fr) {
|
||||
errargc(ctx, fr->erraac);
|
||||
memcpy(ctx->errcxptr->erraav, fr->erraav,
|
||||
(size_t)(fr->erraac * sizeof(erradef)));
|
||||
errsign(ctx, fr->errcode, fr->errfac);
|
||||
}
|
||||
|
||||
void errlogn(errcxdef *ctx, int err, char *facility) {
|
||||
ctx->errcxofs = 0;
|
||||
(*ctx->errcxlog)(ctx->errcxlgc, facility, err, ctx->errcxptr->erraac,
|
||||
ctx->errcxptr->erraav);
|
||||
}
|
||||
|
||||
void errlogf(errcxdef *ctx, char *facility, int err) {
|
||||
errargc(ctx, 0);
|
||||
errlogn(ctx, err, facility);
|
||||
}
|
||||
|
||||
#endif /* ERR_NO_MACRO */
|
||||
|
||||
} // End of namespace TADS2
|
||||
} // End of namespace TADS
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/algorithm.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace TADS {
|
||||
@ -49,26 +50,47 @@ struct errdef {
|
||||
|
||||
#define ERRBUFSIZ 512
|
||||
|
||||
class TADS2;
|
||||
|
||||
// seek location record for an error message by number
|
||||
struct errmfdef {
|
||||
uint errmfnum; // error number
|
||||
size_t errmfseek; // seek location of this message
|
||||
};
|
||||
|
||||
struct errcxdef {
|
||||
errdef *errcxptr; // current error frame
|
||||
void (*errcxlog)(void *, char *fac, int err, int argc, erradef *);
|
||||
// error logging callback function
|
||||
class errcxdef {
|
||||
public:
|
||||
errdef *errcxptr; // current error frame
|
||||
void *errcxlgc; // context for error logging callback
|
||||
int errcxofs; // offset in argument buffer
|
||||
char errcxbuf[ERRBUFSIZ]; // space for argument strings
|
||||
Common::SeekableReadStream *errcxfp; // message file, if one is being used
|
||||
Common::SeekableReadStream *errcxfp; // message file, if one is being used
|
||||
errmfdef *errcxseek; // seek locations of messages in file
|
||||
uint errcxsksz; // size of errcxseek array
|
||||
size_t errcxbase; // offset in physical file of logical error file
|
||||
struct appctxdef *errcxappctx; // host application context
|
||||
TADS2 * errcxappctx; // host application context
|
||||
public:
|
||||
/**
|
||||
* Format an error message, sprintf-style, using arguments in an
|
||||
* erradef array (which is passed to the error-logging callback).
|
||||
* Returns the length of the output string, even if the actual
|
||||
* output string was truncated because the outbuf was too short.
|
||||
* (If called with outbufl == 0, nothing will be written out, but
|
||||
* the size of the buffer needed, minus the terminating null byte,
|
||||
* will be computed and returned.)
|
||||
*/
|
||||
static int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv);
|
||||
public:
|
||||
errcxdef() : errcxptr(nullptr), errcxlgc(nullptr), errcxofs(0),
|
||||
errcxseek(nullptr), errcxsksz(0), errcxbase(0), errcxappctx(nullptr) {
|
||||
Common::fill(&errcxbuf[0], &errcxbuf[ERRBUFSIZ], '\0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Error logging method
|
||||
*/
|
||||
void errcxlog(void *ctx0, char *fac, int err, int argc, erradef *argv);
|
||||
};
|
||||
typedef struct errcxdef errcxdef;
|
||||
|
||||
// begin protected code
|
||||
#define ERRBEGIN(ctx) \
|
||||
@ -252,18 +274,7 @@ void errlogf(errcxdef *ctx, char *facility, int err);
|
||||
(errargv(ctx,0,typ1,arg1),errargv(ctx,1,typ2,arg2),\
|
||||
errargc(ctx,2),errlogn(ctx,e,fac))
|
||||
|
||||
|
||||
/**
|
||||
* Format an error message, sprintf-style, using arguments in an
|
||||
* erradef array (which is passed to the error-logging callback).
|
||||
* Returns the length of the output string, even if the actual
|
||||
* output string was truncated because the outbuf was too short.
|
||||
* (If called with outbufl == 0, nothing will be written out, but
|
||||
* the size of the buffer needed, minus the terminating null byte,
|
||||
* will be computed and returned.)
|
||||
*/
|
||||
extern int errfmt(char *outbuf, int outbufl, char *fmt, int argc, erradef *argv);
|
||||
|
||||
|
||||
// get the text of an error
|
||||
void errmsg(errcxdef *ctx, char *outbuf, uint outbufl, uint err);
|
||||
|
||||
|
309
engines/glk/tads/tads2/os.cpp
Normal file
309
engines/glk/tads/tads2/os.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/tads/tads2/os.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace TADS {
|
||||
namespace TADS2 {
|
||||
|
||||
OS::OS(OSystem *syst, const GlkGameDescription &gameDesc) : TADS(syst, gameDesc),
|
||||
status_mode(0) {
|
||||
Common::fill(&status_left[0], &status_left[OSS_STATUS_STRING_LEN], '\0');
|
||||
Common::fill(&status_right[0], &status_right[OSS_STATUS_STRING_LEN], '\0');
|
||||
}
|
||||
|
||||
void OS::os_terminate(int rc) {
|
||||
glk_exit();
|
||||
}
|
||||
|
||||
glui32 OS::oss_convert_prompt_type(int type) {
|
||||
if (type == OS_AFP_OPEN)
|
||||
return filemode_Read;
|
||||
return filemode_ReadWrite;
|
||||
}
|
||||
|
||||
glui32 OS::oss_convert_file_type(int type) {
|
||||
if (type == OSFTSAVE)
|
||||
return fileusage_SavedGame;
|
||||
if (type == OSFTLOG || type == OSFTTEXT)
|
||||
return fileusage_Transcript;
|
||||
return fileusage_Data;
|
||||
}
|
||||
|
||||
glui32 OS::oss_convert_fileref_to_string(frefid_t file_to_convert, char *buffer, int buf_len) {
|
||||
char temp_string[32];
|
||||
glui32 value, i = 0, digit,
|
||||
digit_flag = false, // Have we put a digit in the string yet?
|
||||
divisor = 1e9; // The max 32-bit integer is 4294967295
|
||||
|
||||
// This could probably be done by using sprintf("%s%ld%s") but I don't want to risk it
|
||||
value = (glui32)file_to_convert;
|
||||
while (divisor != 1) {
|
||||
digit = (char)(value / divisor);
|
||||
if (digit != 0 || digit_flag) { // This lets us handle, eg, 102
|
||||
temp_string[i++] = digit + '0';
|
||||
digit_flag = true;
|
||||
}
|
||||
value = value % divisor;
|
||||
divisor /= 10;
|
||||
}
|
||||
temp_string[i++] = (char)value + '0';
|
||||
temp_string[i] = 0;
|
||||
if (strlen(temp_string) + strlen(OSS_FILEREF_STRING_PREFIX) +
|
||||
strlen(OSS_FILEREF_STRING_SUFFIX) > (size_t)buf_len)
|
||||
return false;
|
||||
sprintf(buffer, "%s%s%s", OSS_FILEREF_STRING_PREFIX,
|
||||
temp_string, OSS_FILEREF_STRING_SUFFIX);
|
||||
return true;
|
||||
}
|
||||
|
||||
frefid_t OS::oss_convert_string_to_fileref(char *buffer, glui32 usage) {
|
||||
char temp_string[32];
|
||||
glui32 value = 0, i, multiplier = 1;
|
||||
|
||||
// Does the buffer contain a hashed fileref?
|
||||
if (oss_is_string_a_fileref(buffer)) {
|
||||
// If so, we need only decode the string in the middle and return its value
|
||||
strcpy(temp_string, buffer + strlen(OSS_FILEREF_STRING_PREFIX));
|
||||
i = strlen(temp_string) - strlen(OSS_FILEREF_STRING_SUFFIX);
|
||||
temp_string[i] = 0;
|
||||
while (i != 0) {
|
||||
i--;
|
||||
value += ((glui32)(temp_string[i] - '0') * multiplier);
|
||||
multiplier *= 10;
|
||||
}
|
||||
return ((frefid_t)value);
|
||||
}
|
||||
|
||||
// If not, return the new fileref
|
||||
return (glk_fileref_create_by_name(usage, os_get_root_name(buffer), 0));
|
||||
}
|
||||
|
||||
bool OS::oss_is_string_a_fileref(char *buffer) {
|
||||
if ((strncmp(buffer, OSS_FILEREF_STRING_PREFIX,
|
||||
strlen(OSS_FILEREF_STRING_PREFIX)) == 0) &&
|
||||
(strncmp(buffer + strlen(buffer) - strlen(OSS_FILEREF_STRING_SUFFIX),
|
||||
OSS_FILEREF_STRING_SUFFIX,
|
||||
strlen(OSS_FILEREF_STRING_SUFFIX)) == 0))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char OS::oss_convert_keystroke_to_tads(glui32 key) {
|
||||
// Characters 0 - 255 we return per normal */
|
||||
if (key <= 255)
|
||||
return ((unsigned char)key);
|
||||
switch (key) {
|
||||
case keycode_Up:
|
||||
return CMD_UP;
|
||||
case keycode_Down:
|
||||
return CMD_DOWN;
|
||||
case keycode_Left:
|
||||
return CMD_LEFT;
|
||||
case keycode_Right:
|
||||
return CMD_RIGHT;
|
||||
case keycode_PageUp:
|
||||
return CMD_PGUP;
|
||||
case keycode_PageDown:
|
||||
return CMD_PGDN;
|
||||
case keycode_Home:
|
||||
return CMD_HOME;
|
||||
case keycode_End:
|
||||
return CMD_END;
|
||||
case keycode_Func1:
|
||||
return CMD_F1;
|
||||
case keycode_Func2:
|
||||
return CMD_F2;
|
||||
case keycode_Func3:
|
||||
return CMD_F3;
|
||||
case keycode_Func4:
|
||||
return CMD_F4;
|
||||
case keycode_Func5:
|
||||
return CMD_F5;
|
||||
case keycode_Func6:
|
||||
return CMD_F6;
|
||||
case keycode_Func7:
|
||||
return CMD_F7;
|
||||
case keycode_Func8:
|
||||
return CMD_F8;
|
||||
case keycode_Func9:
|
||||
return CMD_F9;
|
||||
case keycode_Func10:
|
||||
return CMD_F10;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool OS::oss_check_path(char *filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OS::oss_revert_path() {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
osfildef *OS::oss_open_stream(char *buffer, glui32 tadsusage, glui32 tbusage,
|
||||
glui32 fmode, glui32 rock) {
|
||||
frefid_t fileref;
|
||||
strid_t osf;
|
||||
int changed_dirs;
|
||||
|
||||
fileref = oss_convert_string_to_fileref(buffer,
|
||||
oss_convert_file_type(tadsusage) | tbusage);
|
||||
changed_dirs = oss_check_path(buffer);
|
||||
osf = glk_stream_open_file(fileref, (FileMode)fmode, rock);
|
||||
if (changed_dirs)
|
||||
oss_revert_path();
|
||||
return *osf;
|
||||
}
|
||||
|
||||
void OS::oss_put_string_with_hilite(winid_t win, const char *str, size_t len) {
|
||||
glk_set_window(win);
|
||||
glk_put_buffer(str, len);
|
||||
}
|
||||
|
||||
void OS::oss_draw_status_line(void) {
|
||||
glui32 width, height, division;
|
||||
|
||||
if (status_win == nullptr) return; // In case this is a CheapGlk port
|
||||
|
||||
glk_window_get_size(status_win, &width, &height);
|
||||
if (height == 0) return; // Don't bother if status is invisible
|
||||
division = width - strlen(status_right) - 1;
|
||||
glk_set_window(status_win);
|
||||
glk_window_clear(status_win);
|
||||
oss_put_string_with_hilite(status_win, status_left, strlen(status_left));
|
||||
glk_window_move_cursor(status_win, division, 0);
|
||||
glk_put_string(status_right);
|
||||
}
|
||||
|
||||
void OS::oss_change_status_string(char *dest, const char *src, size_t len) {
|
||||
if (len > OSS_STATUS_STRING_LEN - 1)
|
||||
len = OSS_STATUS_STRING_LEN - 1;
|
||||
memcpy(dest, src, len);
|
||||
dest[len] = '\0';
|
||||
}
|
||||
|
||||
void OS::oss_change_status_left(const char *str, size_t len) {
|
||||
oss_change_status_string(status_left, str, len);
|
||||
oss_draw_status_line();
|
||||
}
|
||||
|
||||
void OS::oss_change_status_right(const char *str) {
|
||||
oss_change_status_string(status_right, str, strlen(str));
|
||||
oss_draw_status_line();
|
||||
}
|
||||
|
||||
int OS::memicmp(char *s1, char *s2, int len) {
|
||||
char *x1, *x2;
|
||||
int i, result;
|
||||
|
||||
x1 = (char *)malloc(len); x2 = (char *)malloc(len);
|
||||
|
||||
if (!x1 || !x2) {
|
||||
glk_set_window(story_win);
|
||||
glk_put_string("memicmp has run out of memory. Quitting.\n");
|
||||
os_waitc();
|
||||
glk_exit();
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (Common::isUpper(s1[i]))
|
||||
x1[i] = glk_char_to_lower((unsigned char)s1[i]);
|
||||
else x1[i] = s1[i];
|
||||
|
||||
if (Common::isUpper(s2[i]))
|
||||
x2[i] = glk_char_to_lower((unsigned char)s2[i]);
|
||||
else x2[i] = s2[i];
|
||||
}
|
||||
|
||||
result = memcmp(x1, x2, len);
|
||||
free(x1);
|
||||
free(x2);
|
||||
return result;
|
||||
}
|
||||
|
||||
void OS::os_flush() {
|
||||
glk_tick();
|
||||
}
|
||||
|
||||
void OS::os_print(const char *str, size_t len) {
|
||||
int current_status_mode;
|
||||
|
||||
// Decide what to do based on our status mode
|
||||
current_status_mode = os_get_status();
|
||||
if (current_status_mode == OSS_STATUS_MODE_STORY) {
|
||||
oss_put_string_with_hilite(story_win, str, len);
|
||||
} else if (current_status_mode == OSS_STATUS_MODE_STATUS) {
|
||||
const char *p;
|
||||
size_t rem;
|
||||
|
||||
// The string requires some fiddling for the status window
|
||||
for (p = str, rem = len; rem != 0 && *p == '\n'; p++, --rem);
|
||||
if (rem != 0 && p[rem - 1] == '\n')
|
||||
--rem;
|
||||
|
||||
// if that leaves anything, update the statusline
|
||||
if (rem != 0)
|
||||
oss_change_status_left(p, rem);
|
||||
}
|
||||
}
|
||||
|
||||
void OS::os_expause() {
|
||||
os_printz("(Strike any key to exit...)");
|
||||
os_flush();
|
||||
os_waitc();
|
||||
}
|
||||
|
||||
int OS::oss_getc_from_window(winid_t win) {
|
||||
static unsigned char buffered_char = 0;
|
||||
int i;
|
||||
event_t ev;
|
||||
|
||||
if (buffered_char != 0) {
|
||||
i = (int)buffered_char;
|
||||
buffered_char = 0;
|
||||
return i;
|
||||
}
|
||||
glk_request_char_event(win);
|
||||
do {
|
||||
glk_select(&ev);
|
||||
if (ev.type == evtype_Arrange)
|
||||
oss_draw_status_line();
|
||||
} while (ev.type != evtype_CharInput);
|
||||
if (ev.val1 == keycode_Return)
|
||||
ev.val1 = '\n';
|
||||
else if (ev.val1 == keycode_Tab)
|
||||
ev.val1 = '\t';
|
||||
if (ev.val1 <= 255)
|
||||
return ((int)ev.val1);
|
||||
|
||||
// We got a special character, so handle it appropriately
|
||||
buffered_char = oss_convert_keystroke_to_tads(ev.val1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace TADS2
|
||||
} // End of namespace TADS
|
||||
} // End of namespace Glk
|
334
engines/glk/tads/tads2/os.h
Normal file
334
engines/glk/tads/tads2/os.h
Normal file
@ -0,0 +1,334 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLK_TADS_TADS2_OS
|
||||
#define GLK_TADS_TADS2_OS
|
||||
|
||||
#include "glk/tads/tads.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace TADS {
|
||||
namespace TADS2 {
|
||||
|
||||
/**
|
||||
* The character (or characters) which mark the beginning of a special fileref string.
|
||||
* The important thing is that the string be one that is either not allowed in
|
||||
* filenames on your platform or is unlikely to be the first part of a filename.
|
||||
*/
|
||||
#define OSS_FILEREF_STRING_PREFIX ":"
|
||||
|
||||
/**
|
||||
* The character (or characters) which mark the end of a special fileref string.
|
||||
* Using this and OSS_FILEREF_STRING_PREFIX, you should be able to come up with
|
||||
* something which forms an invalid filename
|
||||
*/
|
||||
#define OSS_FILEREF_STRING_SUFFIX ""
|
||||
|
||||
/**
|
||||
* Maximum length of status line text
|
||||
*/
|
||||
#define OSS_STATUS_STRING_LEN 80
|
||||
|
||||
/**
|
||||
* Important note: do not change these values when porting TADS. These
|
||||
* values can be used by games, so they must be the same on all platforms.
|
||||
*/
|
||||
enum {
|
||||
OS_AFP_OPEN = 1, ///< choose an existing file to open for reading
|
||||
OS_AFP_SAVE = 2 ///< choose a filename for saving to a file
|
||||
};
|
||||
|
||||
/**
|
||||
* File types.These type codes are used when opening or creating a file,
|
||||
* so that the OS routine can set appropriate file system metadata
|
||||
* to describe or find the file type.
|
||||
*
|
||||
* The type os_filetype_t is defined for documentary purposes; it's
|
||||
* always just an int.
|
||||
*/
|
||||
enum os_filetype_t {
|
||||
OSFTGAME = 0, ///< a game data file (.gam)
|
||||
OSFTSAVE = 1, ///< a saved game (.sav)
|
||||
OSFTLOG = 2, ///< a transcript (log) file
|
||||
OSFTSWAP = 3, ///< swap file
|
||||
OSFTDATA = 4, ///< user data file (used with the TADS fopen() call)
|
||||
OSFTCMD = 5, ///< QA command/log file
|
||||
OSFTERRS = 6, ///< error message file
|
||||
OSFTTEXT = 7, ///< text file - used for source files
|
||||
OSFTBIN = 8, ///< binary file of unknown type - resources, etc
|
||||
OSFTCMAP = 9, ///< character mapping file
|
||||
OSFTPREF = 10, ///< preferences file
|
||||
OSFTUNK = 11, ///< unknown - as a filter, matches any file type
|
||||
OSFTT3IMG = 12, ///< T3 image file (.t3 - formerly .t3x)
|
||||
OSFTT3OBJ = 13, ///< T3 object file (.t3o)
|
||||
OSFTT3SYM = 14, ///< T3 symbol export file (.t3s)
|
||||
OSFTT3SAV = 15 ///< T3 saved state file (.t3v)
|
||||
};
|
||||
|
||||
/**
|
||||
* Constants for os_getc() when returning commands. When used for command line
|
||||
* editing, special keys (arrows, END, etc.) should cause os_getc() to return 0,
|
||||
* and return the appropriate CMD_ value on the NEXT call. Hence, os_getc() must
|
||||
* keep the appropriate information around statically for the next call when a
|
||||
* command key is issued.
|
||||
*
|
||||
* The comments indicate which CMD_xxx codes are "translated" codes and which are
|
||||
* "raw"; the difference is that, when a particular keystroke could be interpreted
|
||||
* as two different CMD_xxx codes, one translated and the other raw, os_getc()
|
||||
* should always return the translated version of the key, and os_getc_raw()
|
||||
* should return the raw version.
|
||||
*/
|
||||
enum KeyCmd {
|
||||
CMD_UP = 1, ///< move up/up arrow (translated)
|
||||
CMD_DOWN = 2, ///< move down/down arrow (translated)
|
||||
CMD_RIGHT = 3, ///< move right/right arrow (translated)
|
||||
CMD_LEFT = 4, ///< move left/left arrow (translated)
|
||||
CMD_END = 5, ///< move cursor to end of line (translated)
|
||||
CMD_HOME = 6, ///< move cursor to start of line (translated)
|
||||
CMD_DEOL = 7, ///< delete to end of line (translated)
|
||||
CMD_KILL = 8, ///< delete entire line (translated)
|
||||
CMD_DEL = 9, ///< delete current character (translated)
|
||||
CMD_SCR = 10, ///< toggle scrollback mode (translated)
|
||||
CMD_PGUP = 11, ///< page up (translated)
|
||||
CMD_PGDN = 12, ///< page down (translated)
|
||||
CMD_TOP = 13, ///< top of file (translated)
|
||||
CMD_BOT = 14, ///< bottom of file (translated)
|
||||
CMD_F1 = 15, ///< function key F1 (raw)
|
||||
CMD_F2 = 16, ///< function key F2 (raw)
|
||||
CMD_F3 = 17, ///< function key F3 (raw)
|
||||
CMD_F4 = 18, ///< function key F4 (raw)
|
||||
CMD_F5 = 19, ///< function key F5 (raw)
|
||||
CMD_F6 = 20, ///< function key F6 (raw)
|
||||
CMD_F7 = 21, ///< function key F7 (raw)
|
||||
CMD_F8 = 22, ///< function key F8 (raw)
|
||||
CMD_F9 = 23, ///< function key F9 (raw)
|
||||
CMD_F10 = 24, ///< function key F10 (raw)
|
||||
CMD_CHOME = 25, ///< control-home (raw)
|
||||
CMD_TAB = 26, ///< tab (translated)
|
||||
CMD_SF2 = 27, ///< shift-F2 (raw)
|
||||
///< not used (obsolete) - 28
|
||||
CMD_WORD_LEFT = 29, ///< word left (ctrl-left on dos) (translated)
|
||||
CMD_WORD_RIGHT = 30, ///< word right (ctrl-right on dos) (translated)
|
||||
CMD_WORDKILL = 31, ///< delete word right (translated)
|
||||
CMD_EOF = 32, ///< end-of-file (raw)
|
||||
CMD_BREAK = 33, ///< break (Ctrl-C or local equivalent) (translated)
|
||||
CMD_INS = 34, ///< insert key (raw)
|
||||
|
||||
/**
|
||||
* ALT-keys - add alphabetical code to CMD_ALT: ALT-A == CMD_ALT + 0,
|
||||
* ALT-B == CMD_ALT + 1, ALT-C == CMD_ALT + 2, etc
|
||||
*
|
||||
* These keys are all raw (untranslated).
|
||||
*/
|
||||
CMD_ALT = 128 ///< start of ALT keys
|
||||
};
|
||||
|
||||
/**
|
||||
* Status mode codes
|
||||
*/
|
||||
enum StatusMode {
|
||||
OSS_STATUS_MODE_STORY = 0,
|
||||
OSS_STATUS_MODE_STATUS = 1
|
||||
};
|
||||
|
||||
typedef Common::SeekableReadStream osfildef;
|
||||
|
||||
/**
|
||||
* Operating system compatibility layer
|
||||
*/
|
||||
class OS : public TADS {
|
||||
protected:
|
||||
char status_left[OSS_STATUS_STRING_LEN];
|
||||
char status_right[OSS_STATUS_STRING_LEN];
|
||||
int status_mode;
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
OS(OSystem *syst, const GlkGameDescription &gameDesc);
|
||||
|
||||
/**
|
||||
* Terminates the game
|
||||
*/
|
||||
void os_terminate(int rc);
|
||||
|
||||
/**
|
||||
* \defgroup Type Conversions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Change a TADS prompt type (OS_AFP_*) into a Glk prompt type.
|
||||
*/
|
||||
glui32 oss_convert_prompt_type(int type);
|
||||
|
||||
/**
|
||||
* Change a TADS file type (OSFT*) into a Glk file type.
|
||||
*/
|
||||
glui32 oss_convert_file_type(int type);
|
||||
|
||||
/**
|
||||
* Change a fileref ID (frefid_t) to a special string and put it in the
|
||||
* buffer which is passed to it. The string is given by
|
||||
* OSS_FILEREF_STRING_PREFIX + 'nnnnn' + OSS_FILEREF_STRING_SUFFIX
|
||||
* where 'nnnnn' is the frefid_t pointer converted into a string of decimal
|
||||
* numbers. This is only really practical for 32-bit pointers; if we use
|
||||
* 64-bit pointers I'll have to start using a hash table or use hex
|
||||
* numbers.
|
||||
*/
|
||||
glui32 oss_convert_fileref_to_string(frefid_t file_to_convert, char *buffer, int buf_len);
|
||||
|
||||
/**
|
||||
* Turn a filename or a special fileref string into an actual fileref.
|
||||
* Notice that, since Glk doesn't know paths, we take this opportunity to
|
||||
* call oss_check_path, which should do the OS-dependent path changing
|
||||
* in the event that the filename contains path information
|
||||
*/
|
||||
frefid_t oss_convert_string_to_fileref(char *buffer, glui32 usage);
|
||||
|
||||
/**
|
||||
* Tell us if the passed string is a hashed fileref or not
|
||||
*/
|
||||
bool oss_is_string_a_fileref(char *buffer);
|
||||
|
||||
/**
|
||||
* Change a Glk key into a TADS one, using the CMD_xxx codes
|
||||
*/
|
||||
unsigned char oss_convert_keystroke_to_tads(glui32 key);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \defgroup Directory/File methods
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* If a filename contains path information, change dirs to that path.
|
||||
* Returns true if the path was fiddled with
|
||||
*/
|
||||
bool oss_check_path(char *filename);
|
||||
|
||||
/**
|
||||
* In case we changed directories in oss_check_path, change back to the
|
||||
* original executable directory
|
||||
*/
|
||||
void oss_revert_path();
|
||||
|
||||
/**
|
||||
* Open a stream, given a string, usage, and a filemode. tadsusage is the
|
||||
* TADS filemode (OSFT*); tbusage is either fileusage_TextMode or
|
||||
* fileusage_BinaryMode (from Glk).
|
||||
*/
|
||||
osfildef *oss_open_stream(char *buffer, glui32 tadsusage, glui32 tbusage,
|
||||
glui32 fmode, glui32 rock);
|
||||
|
||||
/**
|
||||
* Get a pointer to the root name portion of a filename. This is the part
|
||||
* of the filename after any path or directory prefix. For example, on
|
||||
* Unix, given the string "/home/mjr/deep.gam", this function should return
|
||||
* a pointer to the 'd' in "deep.gam". If the filename doesn't appear to
|
||||
* have a path prefix, it should simply return the argument unchanged.
|
||||
*/
|
||||
const char *os_get_root_name(const char *buf) const { return buf; }
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \defgroup The main text area print routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Process hilighting codes while printing a string
|
||||
*/
|
||||
void oss_put_string_with_hilite(winid_t win, const char *str, size_t len);
|
||||
|
||||
/**
|
||||
* Status line handling
|
||||
*/
|
||||
void oss_draw_status_line();
|
||||
|
||||
void oss_change_status_string(char *dest, const char *src, size_t len);
|
||||
void oss_change_status_left(const char *str, size_t len);
|
||||
void oss_change_status_right(const char *str);
|
||||
int os_get_status() const { return status_mode; }
|
||||
|
||||
/**
|
||||
* Flush the output
|
||||
*/
|
||||
void os_flush();
|
||||
|
||||
/**
|
||||
* Print a null terminated string
|
||||
*/
|
||||
void os_printz(const char *str) { os_print(str, strlen(str)); }
|
||||
|
||||
/**
|
||||
* Print a string
|
||||
*/
|
||||
void os_print(const char *str, size_t len);
|
||||
|
||||
/**
|
||||
* Compare two strings
|
||||
*/
|
||||
int memicmp(char *s1, char *s2, int len);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \defgroup Input routines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Wait for a key to be hit
|
||||
*/
|
||||
void os_waitc(void) { os_getc(); }
|
||||
|
||||
/**
|
||||
* Get a character from the keyboard. For extended characters, return 0,
|
||||
* then return the extended key at the next call to this function
|
||||
*/
|
||||
int os_getc() {
|
||||
return oss_getc_from_window(story_win);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a keystroke in the passed window
|
||||
*/
|
||||
int oss_getc_from_window(winid_t win);
|
||||
|
||||
|
||||
/**
|
||||
* Print a message (with os_print) and wait for a key
|
||||
*/
|
||||
void os_expause();
|
||||
|
||||
/**@}*/
|
||||
};
|
||||
|
||||
} // End of namespace TADS2
|
||||
} // End of namespace TADS
|
||||
} // End of namespace Glk
|
||||
|
||||
#endif
|
@ -26,11 +26,46 @@ namespace Glk {
|
||||
namespace TADS {
|
||||
namespace TADS2 {
|
||||
|
||||
TADS2::TADS2(OSystem *syst, const GlkGameDescription &gameDesc) : TADS(syst, gameDesc) {
|
||||
TADS2::TADS2(OSystem *syst, const GlkGameDescription &gameDesc) : OS(syst, gameDesc) {
|
||||
}
|
||||
|
||||
void TADS2::runGame(Common::SeekableReadStream *gameFile) {
|
||||
// TODO
|
||||
errcxdef errctx;
|
||||
errctx.errcxlgc = &errctx;
|
||||
errctx.errcxfp = nullptr;
|
||||
errctx.errcxofs = 0;
|
||||
errctx.errcxappctx = this;
|
||||
|
||||
/* copyright-date-string */
|
||||
#ifdef T2_COPYRIGHT_NOTICE
|
||||
trdptf("%s - A %s TADS %s Interpreter.\n",
|
||||
G_tads_oem_app_name, G_tads_oem_display_mode,
|
||||
TADS_RUNTIME_VERSION);
|
||||
trdptf("%sopyright (c) 1993, 2012 by Michael J. Roberts.\n",
|
||||
G_tads_oem_copyright_prefix ? "TADS c" : "C");
|
||||
trdptf("%s\n", G_tads_oem_author);
|
||||
#endif
|
||||
|
||||
trdmain1(&errctx);
|
||||
|
||||
// pause before exiting if the OS desires it
|
||||
os_expause();
|
||||
}
|
||||
|
||||
void TADS2::trdmain1(errcxdef *errctx) {
|
||||
|
||||
}
|
||||
|
||||
void TADS2::trdptf(const char *fmt, ...) {
|
||||
va_list va;
|
||||
|
||||
// format the string */
|
||||
va_start(va, fmt);
|
||||
Common::String msg = Common::String::vformat(fmt, va);
|
||||
va_end(va);
|
||||
|
||||
// print the formatted buffer
|
||||
os_printz(msg);
|
||||
}
|
||||
|
||||
} // End of namespace TADS2
|
||||
|
@ -23,7 +23,8 @@
|
||||
#ifndef GLK_TADS_TADS2
|
||||
#define GLK_TADS_TADS2
|
||||
|
||||
#include "glk/tads/tads.h"
|
||||
#include "glk/tads/tads2/os.h"
|
||||
#include "glk/tads/tads2/ler.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace TADS {
|
||||
@ -32,7 +33,10 @@ namespace TADS2 {
|
||||
/**
|
||||
* TADS 2 game interpreter
|
||||
*/
|
||||
class TADS2 : public TADS {
|
||||
class TADS2 : public OS {
|
||||
private:
|
||||
// STUBS
|
||||
void os_printz(const Common::String &s) {}
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
@ -48,8 +52,17 @@ public:
|
||||
* Returns the running interpreter type
|
||||
*/
|
||||
virtual InterpreterType getInterpreterType() const override { return INTERPRETER_TADS2; }
|
||||
|
||||
void trdmain1(errcxdef *errctx);
|
||||
|
||||
/**
|
||||
* printf-style formatting
|
||||
*/
|
||||
void trdptf(const char *fmt, ...);
|
||||
};
|
||||
|
||||
typedef TADS2 appctxdef;
|
||||
|
||||
} // End of namespace TADS2
|
||||
} // End of namespace TADS
|
||||
} // End of namespace Glk
|
||||
|
Loading…
Reference in New Issue
Block a user