From 2765ba9afa4918e46ab0835c0f6e9183c57b612a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 8 May 2019 17:29:07 +1000 Subject: GLK: HUGO: Added Glk interface methods --- engines/glk/hugo/heglk.cpp | 571 +++++++++++++++++++++++++++++++++++++++- engines/glk/hugo/hugo.cpp | 12 +- engines/glk/hugo/hugo.h | 136 +++++++++- engines/glk/hugo/hugo_defines.h | 127 +++++++++ engines/glk/hugo/hugo_types.h | 18 -- 5 files changed, 833 insertions(+), 31 deletions(-) create mode 100644 engines/glk/hugo/hugo_defines.h (limited to 'engines') diff --git a/engines/glk/hugo/heglk.cpp b/engines/glk/hugo/heglk.cpp index 8b56f32de0..86be90c268 100644 --- a/engines/glk/hugo/heglk.cpp +++ b/engines/glk/hugo/heglk.cpp @@ -44,13 +44,578 @@ void Hugo::hugo_init_screen() { SCREENWIDTH/FIXEDCHARWIDTH, SCREENHEIGHT/FIXEDLINEHEIGHT); } -void Hugo::hugo_cleanup_screen() { - // No implementation +void Hugo::hugo_getline(const char *prmpt) { + event_t ev; + char gotline = 0; + + /* Just in case we try to get line input from a Glk-illegal + window that hasn't been created, switch as a failsafe + to mainwin + */ + if (currentwin == NULL) + glk_set_window(currentwin = mainwin); + + /* Print prompt */ + glk_put_string(prmpt); + + /* Request line input */ + glk_request_line_event(currentwin, buffer, MAXBUFFER, 0); + + while (!gotline) + { + /* Grab an event */ + glk_select(&ev); + + switch (ev.type) + { + case evtype_LineInput: + /* (Will always be currentwin, but anyway) */ + if (ev.window == currentwin) { + gotline = true; + } + break; + } + } + + /* The line we have received in commandbuf is not null-terminated */ + buffer[ev.val1] = '\0'; /* i.e., the length */ + + /* Copy the input to the script file (if open) */ + if (script) { + Common::String line = Common::String::format("%s%s\n", prompt, buffer); + script->putBuffer(line.c_str(), line.size()); + } +} + +int Hugo::hugo_waitforkey() { + event_t ev; + char gotchar = 0; + + /* Just in case we try to get key input from a Glk-illegal + window that hasn't been created, switch as a failsafe + to mainwin + */ + if (currentwin == NULL) + glk_set_window(currentwin = mainwin); + +#if defined (NO_KEYPRESS_CURSOR) + if (currentwin != mainwin) + { + glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); + hugo_print("*"); + glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); + } +#endif + + glk_request_char_event(currentwin); + + while (!gotchar) + { + /* Grab an event */ + glk_select(&ev); + + switch (ev.type) + { + case evtype_CharInput: + /* (Will always be mainwin, but anyway) */ + if (ev.window == currentwin) { + gotchar = true; + } + break; + } + } + + /* Convert Glk special keycodes: */ + switch (ev.val1) + { + case keycode_Left: ev.val1 = 8; break; + case keycode_Right: ev.val1 = 21; break; + case keycode_Up: ev.val1 = 11; break; + case keycode_Down: ev.val1 = 10; break; + case keycode_Return: ev.val1 = 13; break; + case keycode_Escape: ev.val1 = 27; break; + } + +#if defined (NO_KEYPRESS_CURSOR) + if (currentwin != mainwin) + { + glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); + hugo_print(" "); + glk_window_move_cursor(currentwin, currentpos / CHARWIDTH, currentline - 1); + } +#endif + + return ev.val1; +} + +int Hugo::hugo_iskeywaiting() { + var[system_status] = STAT_UNAVAILABLE; + return 0; +} + +int Hugo::hugo_timewait(int n) { + uint32 millisecs; + event_t ev; + + if (!glk_gestalt(gestalt_Timer, 0)) + return false; + if (n == 0) return true; + + + millisecs = 1000 / n; + if (millisecs == 0) + millisecs = 1; + + // For the time being, we're going to disallow + // millisecond delays in Glk (1) because there's no + // point, and (2) so that we can tell we're running + // under Glk. + if (millisecs < 1000) return false; + + glk_request_timer_events(millisecs); + while (1) + { + glk_select(&ev); + if (ev.type == evtype_Timer) + break; + } + glk_request_timer_events(0); + return true; +} + +void Hugo::hugo_clearfullscreen() { + glk_window_clear(mainwin); + if (secondwin) glk_window_clear(secondwin); + if (auxwin) glk_window_clear(auxwin); + + /* See hugo_print() for the need for this */ + if (currentwin == mainwin) mainwin_bgcolor = glk_bgcolor; + + /* Must be set: */ + currentpos = 0; + currentline = 1; + + if (!inwindow) just_cleared_screen = true; +} + +void Hugo::hugo_clearwindow() { + /* Clears the currently defined window, moving the cursor to the top-left + corner of the window */ + + /* If the engine thinks we're in a window, but Glk was + unable to comply, don't clear the window, because it's + not really a window + */ + if (inwindow && currentwin == mainwin) return; + if (currentwin == NULL) return; + + glk_window_clear(currentwin); + + /* See hugo_print() for the need for this */ + if (currentwin == mainwin) mainwin_bgcolor = glk_bgcolor; + + /* If we're in a fixed-font (i.e., textgrid) auxiliary + window when we call for a clear, close auxwin and reset + the current window to mainwin + */ + if (auxwin) + { + stream_result_t sr; + + glk_window_close(auxwin, &sr); + auxwin = NULL; + glk_set_window(currentwin = mainwin); + } + + /* Must be set: */ + currentpos = 0; + currentline = 1; + + if (!inwindow) just_cleared_screen = true; +} + +void Hugo::hugo_settextmode() { + charwidth = FIXEDCHARWIDTH; + lineheight = FIXEDLINEHEIGHT; } void Hugo::hugo_settextwindow(int left, int top, int right, int bottom) { - // TODO + /* Hugo's arbitrarily positioned windows don't currently + mesh with what Glk has to offer, so we have to ignore any + non-Glk-ish Windows and just maintain the current + parameters + */ + if ((top != 1 || bottom >= physical_windowbottom / FIXEDLINEHEIGHT + 1) + /* Pre-v2.4 didn't support proper windowing */ + && (game_version >= 24 || !inwindow)) + { + in_valid_window = false; + + /* Glk-illegal floating window; setting currentwin + to NULL will tell hugo_print() not to print in it: + */ + if (bottom= ' ') /* alphanumeric characters */ + + return CHARWIDTH; /* for non-proportional */ + + return 0; +} + +int Hugo::hugo_textwidth(const char *a) const { + int i, slen, len = 0; + + slen = (int)strlen(a); + + for (i = 0; i. + */ + void hugo_getline(const char *prmpt); + + /** + * Provided to be replaced by multitasking systems where cycling while waiting + * for a keystroke may not be such a hot idea. + */ + int hugo_waitforkey(); + + /** + * Returns true if a keypress is waiting to be retrieved. + */ + int hugo_iskeywaiting(); + + /** + * Waits for 1/n seconds. Returns false if waiting is unsupported. + */ + int hugo_timewait(int n); + + /** + * Clears everything on the screen, moving the cursor to the top-left corner of the screen + */ + void hugo_clearfullscreen(); + + /** + * Clears the currently defined window, moving the cursor to the top-left corner of the window + */ + void hugo_clearwindow(); + + /** + * This function does whatever is necessary to set the system up for a standard text display + */ + void hugo_settextmode(); void hugo_settextwindow(int left, int top, int right, int bottom); + /** + * Specially accommodated in GetProp() While the engine thinks that the linelength is 0x7fff, + this tells things like the display object the actual length. (Defined as ACTUAL_LINELENGTH) + */ + int heglk_get_linelength(); + + /** + * Similar to heglk_get_linelength(). (Defined as ACTUAL_SCREENHEIGHT) + */ + int heglk_get_screenheight(); + + void hugo_settextpos(int x, int y); + + /** + * Essentially the same as printf() without formatting, since printf() generally doesn't take + * into account color setting, font changes, windowing, etc. + * + * The newline character '\n' must be explicitly included at the end of a line in order to + * produce a linefeed. The new cursor position is set to the end of this printed text. + * Upon hitting the right edge of the screen, the printing position wraps to the start + * of the next line. + */ + void hugo_print(const char *a); + + /** + * Scroll the text window + */ + void hugo_scrollwindowup() { + // No implementation. Glk takes care of it + } + + /** + * Set the font + * @param f The argument is a mask containing any or none of: + * BOLD_FONT, UNDERLINE_FONT, ITALIC_FONT, PROP_FONT. + */ + void hugo_font(int f); + + /** + * Set the foreground (print) color + */ + void hugo_settextcolor(int c); + + /** + * Set the background color + */ + void hugo_setbackcolor(int c); + + /** + * Color-setting functions should always pass the color through hugo_color() + * in order to properly set default fore/background colors + */ + int hugo_color(int c); + + /** + * Get the width of a character + * @remarks As given here, this function works only for non-proportional printing. + * For proportional printing, hugo_charwidth() should return the width of the supplied + * character in the current font and style. + */ + int hugo_charwidth(char a) const; + + /** + * Return the width of a string + */ + int hugo_textwidth(const char *a) const; + + /** + * Return the length of a string + */ + int hugo_strlen(const char *a) const; + + void hugo_setgametitle(const char *t); + + int hugo_hasvideo() const; + + int hugo_playvideo(HUGO_FILE infile, long reslength, char loop_flag, char background, int volume); + + void hugo_stopvideo(); + /**@}*/ private: /** diff --git a/engines/glk/hugo/hugo_defines.h b/engines/glk/hugo/hugo_defines.h new file mode 100644 index 0000000000..caa1755b82 --- /dev/null +++ b/engines/glk/hugo/hugo_defines.h @@ -0,0 +1,127 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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_HUGO_DEFINES +#define GLK_HUGO_DEFINES + +#include "common/scummsys.h" + +namespace Glk { +namespace Hugo { + +#define MAX_CONTEXT_COMMANDS 32 +#define MAXBUFFER 255 +#define MAXUNDO 1024 +#define CHARWIDTH 1 +#define STAT_UNAVAILABLE (-1) + +#define HUGO_FILE strid_t +#define MAXPATH 256 +#define MAXFILENAME 256 +#define MAXDRIVE 256 +#define MAXDIR 256 +#define MAXEXT 256 + +#define DEF_PRN "" +#define DEF_FCOLOR 0 +#define DEF_BGCOLOR 15 +#define DEF_SLFCOLOR 15 +#define DEF_SLBGCOLOR 1 + +/* These static values are not changeable--they depend largely on internals of the Engine. */ +#define MAXATTRIBUTES 128 +#define MAXGLOBALS 240 +#define MAXLOCALS 16 +#define MAXPOBJECTS 256 /* contenders for disambiguation */ +#define MAXWORDS 32 /* in an input line */ +#define MAXSTACKDEPTH 256 /* for nesting {...} */ + + +/* The positions of various data in the header: */ +#define H_GAMEVERSION 0x00 +#define H_ID 0x01 +#define H_SERIAL 0x03 +#define H_CODESTART 0x0B + +#define H_OBJTABLE 0x0D /* data tables */ +#define H_PROPTABLE 0x0F +#define H_EVENTTABLE 0x11 +#define H_ARRAYTABLE 0x13 +#define H_DICTTABLE 0x15 +#define H_SYNTABLE 0x17 + +#define H_INIT 0x19 /* junction routines */ +#define H_MAIN 0x1B +#define H_PARSE 0x1D +#define H_PARSEERROR 0x1F +#define H_FINDOBJECT 0x21 +#define H_ENDGAME 0x23 +#define H_SPEAKTO 0x25 +#define H_PERFORM 0x27 + +#define H_TEXTBANK 0x29 + +/* additional debugger header information */ +#define H_DEBUGGABLE 0x3A +#define H_DEBUGDATA 0x3B +#define H_DEBUGWORKSPACE 0x3E + +/* Printing control codes--embedded in strings printed by AP(). */ +#define FONT_CHANGE 1 +#define COLOR_CHANGE 2 +#define NO_CONTROLCHAR 3 +#define NO_NEWLINE 30 +#define FORCED_SPACE 31 /* Can't be <= # colors/font codes + 1 +(See AP() for the reason) */ + +/* Font control codes--these bitmasks follow FONT_CHANGE codes. */ +#define NORMAL_FONT 0 +#define BOLD_FONT 1 +#define ITALIC_FONT 2 +#define UNDERLINE_FONT 4 +#define PROP_FONT 8 + +/* CHAR_TRANSLATION is simply a value that is added to an ASCII character +in order to encode the text, i.e., make it unreadable to casual +browsing. +*/ +#define CHAR_TRANSLATION 0x14 + +/* Passed to GetWord() */ +#define PARSE_STRING_VAL 0xFFF0 +#define SERIAL_STRING_VAL 0xFFF1 + +/* Returned by FindWord() */ +#define UNKNOWN_WORD 0xFFFF + +/* Bitmasks for certain qualities of properties */ +#define ADDITIVE_FLAG 1 +#define COMPLEX_FLAG 2 + +/* Property-table indicators */ +#define PROP_END 255 +#define PROP_ROUTINE 255 + +} // End of namespace Hugo +} // End of namespace Glk + +#endif diff --git a/engines/glk/hugo/hugo_types.h b/engines/glk/hugo/hugo_types.h index 8082842cc4..43b2899f93 100644 --- a/engines/glk/hugo/hugo_types.h +++ b/engines/glk/hugo/hugo_types.h @@ -28,24 +28,6 @@ namespace Glk { namespace Hugo { -#define MAX_CONTEXT_COMMANDS 32 -#define MAXBUFFER 255 -#define MAXUNDO 1024 -#define CHARWIDTH 1 - -#define HUGO_FILE strid_t -#define MAXPATH 256 -#define MAXFILENAME 256 -#define MAXDRIVE 256 -#define MAXDIR 256 -#define MAXEXT 256 - -#define DEF_PRN "" -#define DEF_FCOLOR 0 -#define DEF_BGCOLOR 15 -#define DEF_SLFCOLOR 15 -#define DEF_SLBGCOLOR 1 - /** * Library/engine globals */ -- cgit v1.2.3