aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/frotz/processor_screen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/frotz/processor_screen.cpp')
-rw-r--r--engines/glk/frotz/processor_screen.cpp528
1 files changed, 528 insertions, 0 deletions
diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp
new file mode 100644
index 0000000000..87c190f3c5
--- /dev/null
+++ b/engines/glk/frotz/processor_screen.cpp
@@ -0,0 +1,528 @@
+/* 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/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+void Processor::screen_mssg_on() {
+ if (gos_curwin == gos_lower) {
+ oldstyle = curstyle;
+ glk_set_style(style_Preformatted);
+ glk_put_string("\n ");
+ }
+}
+
+void Processor::screen_mssg_off() {
+ if (gos_curwin == gos_lower) {
+ glk_put_char('\n');
+ zargs[0] = 0;
+ z_set_text_style();
+ zargs[0] = oldstyle;
+ z_set_text_style();
+ }
+}
+
+void Processor::screen_char(zchar c) {
+ if (gos_linepending && (gos_curwin == gos_linewin)) {
+ gos_cancel_pending_line();
+ if (gos_curwin == gos_upper) {
+ curx = 1;
+ cury ++;
+ }
+ if (c == '\n')
+ return;
+ }
+
+ // check fixed flag in header, game can change it at whim
+ int forcefix = ((h_flags & FIXED_FONT_FLAG) != 0);
+ int curfix = ((curstyle & FIXED_WIDTH_STYLE) != 0);
+ if (forcefix && !curfix) {
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ fixforced = true;
+ } else if (!forcefix && fixforced) {
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ fixforced = false;
+ }
+
+ if (gos_upper && gos_curwin == gos_upper) {
+ if (c == '\n' || c == ZC_RETURN) {
+ glk_put_char('\n');
+ curx = 1;
+ cury ++;
+ } else {
+ if (cury == 1) {
+ if (curx <= ((sizeof statusline / sizeof(zchar)) - 1)) {
+ statusline[curx - 1] = c;
+ statusline[curx] = 0;
+ }
+ if (curx < h_screen_cols) {
+ glk_put_char_uni(c);
+ } else if (curx == h_screen_cols) {
+ glk_put_char_uni(c);
+ glk_window_move_cursor(gos_curwin, curx-1, cury-1);
+ } else {
+ smartstatusline();
+ }
+
+ curx++;
+ } else {
+ if (curx < h_screen_cols) {
+ glk_put_char_uni(c);
+ } else if (curx == (h_screen_cols)) {
+ glk_put_char_uni(c);
+ glk_window_move_cursor(gos_curwin, curx-1, cury-1);
+ }
+
+ curx++;
+ }
+ }
+ } else if (gos_curwin == gos_lower) {
+ if (c == ZC_RETURN)
+ glk_put_char('\n');
+ else glk_put_char_uni(c);
+ }
+}
+
+void Processor::screen_new_line() {
+ screen_char('\n');
+}
+
+void Processor::screen_word(const zchar *s) {
+ zchar c;
+ while ((c = *s++) != 0) {
+ if (c == ZC_NEW_FONT)
+ s++;
+ else if (c == ZC_NEW_STYLE)
+ s++;
+ else
+ screen_char(c);
+ }
+}
+
+
+void Processor::z_buffer_mode() {
+ // No implementation
+}
+
+void Processor::z_buffer_screen() {
+ store(0);
+}
+
+void Processor::z_erase_line() {
+ int i;
+
+ if (gos_upper && gos_curwin == gos_upper) {
+ for (i = 0; i < h_screen_cols + 1 - curx; i++)
+ glk_put_char(' ');
+ glk_window_move_cursor(gos_curwin, curx - 1, cury - 1);
+ }
+}
+
+void Processor::z_erase_window() {
+ short w = zargs[0];
+ if (w == -2)
+ {
+ if (gos_upper) {
+ glk_set_window(gos_upper);
+#ifdef GARGLK
+ garglk_set_zcolors(curr_fg, curr_bg);
+#endif /* GARGLK */
+ glk_window_clear(gos_upper);
+ glk_set_window(gos_curwin);
+ }
+ glk_window_clear(gos_lower);
+ }
+ if (w == -1)
+ {
+ if (gos_upper) {
+ glk_set_window(gos_upper);
+#ifdef GARGLK
+ garglk_set_zcolors(curr_fg, curr_bg);
+#endif /* GARGLK */
+ glk_window_clear(gos_upper);
+ }
+ glk_window_clear(gos_lower);
+ split_window(0);
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+ }
+ if (w == 0)
+ glk_window_clear(gos_lower);
+ if (w == 1 && gos_upper)
+ glk_window_clear(gos_upper);
+}
+
+void Processor::z_get_cursor() {
+ storew((zword) (zargs[0] + 0), cury);
+ storew((zword) (zargs[0] + 2), curx);
+}
+
+void Processor::z_print_table() {
+ zword addr = zargs[0];
+ zword x;
+ int i, j;
+
+ // Supply default arguments
+ if (zargc < 3)
+ zargs[2] = 1;
+ if (zargc < 4)
+ zargs[3] = 0;
+
+ // Write text in width x height rectangle
+ x = curx;
+
+ for (i = 0; i < zargs[2]; i++) {
+ if (i != 0) {
+ cury += 1;
+ curx = x;
+ }
+
+ for (j = 0; j < zargs[1]; j++) {
+
+ zbyte c;
+
+ LOW_BYTE(addr, c);
+ addr++;
+
+ print_char(c);
+ }
+
+ addr += zargs[3];
+ }
+}
+
+#define zB(i) ((((i >> 10) & 0x1F) << 3) | (((i >> 10) & 0x1F) >> 2))
+#define zG(i) ((((i >> 5) & 0x1F) << 3) | (((i >> 5) & 0x1F) >> 2))
+#define zR(i) ((((i ) & 0x1F) << 3) | (((i ) & 0x1F) >> 2))
+
+#define zRGB(i) (zR(i) << 16 | zG(i) << 8 | zB(i))
+
+void Processor::z_set_true_colour() {
+ int zfore = zargs[0];
+ int zback = zargs[1];
+
+ if (!(zfore < 0))
+ zfore = zRGB(zargs[0]);
+
+ if (!(zback < 0))
+ zback = zRGB(zargs[1]);
+
+#ifdef GARGLK
+ garglk_set_zcolors(zfore, zback);
+#endif /* GARGLK */
+
+ curr_fg = zfore;
+ curr_bg = zback;
+}
+
+static const int zcolor_map[] = {
+ -2, ///< 0 = current
+ -1, ///< 1 = default
+ 0x0000, ///< 2 = black
+ 0x001D, ///< 3 = red
+ 0x0340, ///< 4 = green
+ 0x03BD, ///< 5 = yellow
+ 0x59A0, ///< 6 = blue
+ 0x7C1F, ///< 7 = magenta
+ 0x77A0, ///< 8 = cyan
+ 0x7FFF, ///< 9 = white
+ 0x5AD6, ///< 10 = light grey
+ 0x4631, ///< 11 = medium grey
+ 0x2D6B, ///< 12 = dark grey
+};
+
+#define zcolor_NUMCOLORS (13)
+
+void Processor::z_set_colour() {
+ int zfore = zargs[0];
+ int zback = zargs[1];
+
+ switch (zfore) {
+ case -1:
+ zfore = -3;
+ break;
+
+ case 0:
+ case 1:
+ zfore = zcolor_map[zfore];
+ break;
+
+ default:
+ if (zfore < zcolor_NUMCOLORS)
+ zfore = zRGB(zcolor_map[zfore]);
+ break;
+ }
+
+ switch (zback) {
+ case -1:
+ zback = -3;
+
+ case 0:
+ case 1:
+ zback = zcolor_map[zback];
+ break;
+
+ default:
+ if (zback < zcolor_NUMCOLORS)
+ zback = zRGB(zcolor_map[zback]);
+ break;
+ }
+
+#ifdef GARGLK
+ garglk_set_zcolors(zfore, zback);
+#endif /* GARGLK */
+
+ curr_fg = zfore;
+ curr_bg = zback;
+}
+
+void Processor::z_set_font() {
+ zword font = zargs[0];
+
+ switch (font) {
+ case 0:
+ // previous font
+ temp_font = curr_font;
+ curr_font = prev_font;
+ prev_font = temp_font;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store (curr_font);
+ break;
+
+ case 1: /* normal font */
+ prev_font = curr_font;
+ curr_font = 1;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store (prev_font);
+ break;
+
+ case 4: /* fixed-pitch font*/
+ prev_font = curr_font;
+ curr_font = 4;
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+ store (prev_font);
+ break;
+
+ case 2: // picture font, undefined per 1.1
+ case 3: // character graphics font
+ default: // unavailable
+ store (0);
+ break;
+ }
+}
+
+void Processor::z_set_cursor() {
+ cury = zargs[0];
+ curx = zargs[1];
+
+ if (gos_upper) {
+ if (cury > mach_status_ht) {
+ mach_status_ht = cury;
+ reset_status_ht();
+ }
+
+ glk_window_move_cursor(gos_upper, curx - 1, cury - 1);
+ }
+}
+
+void Processor::z_set_text_style() {
+ int style;
+
+ if (zargs[0] == 0)
+ curstyle = 0;
+ else if (zargs[0] != 0xf000) /* not tickle time */
+ curstyle |= zargs[0];
+
+ if (h_flags & FIXED_FONT_FLAG || curr_font == 4)
+ style = curstyle | FIXED_WIDTH_STYLE;
+ else
+ style = curstyle;
+
+ if (gos_linepending && gos_curwin == gos_linewin)
+ return;
+
+ if (style & REVERSE_STYLE) {
+#ifdef GARGLK
+ garglk_set_reversevideo(true);
+#endif /* GARGLK */
+ }
+
+ if (style & FIXED_WIDTH_STYLE) {
+ if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+ glk_set_style(style_BlockQuote); // monoz
+ else if (style & EMPHASIS_STYLE)
+ glk_set_style(style_Alert); // monoi
+ else if (style & BOLDFACE_STYLE)
+ glk_set_style(style_Subheader); // monob
+ else
+ glk_set_style(style_Preformatted); // monor
+ } else {
+ if (style & BOLDFACE_STYLE && style & EMPHASIS_STYLE)
+ glk_set_style(style_Note); // propz
+ else if (style & EMPHASIS_STYLE)
+ glk_set_style(style_Emphasized); // propi
+ else if (style & BOLDFACE_STYLE)
+ glk_set_style(style_Header); // propb
+ else
+ glk_set_style(style_Normal); // propr
+ }
+
+ if (curstyle == 0) {
+#ifdef GARGLK
+ garglk_set_reversevideo(false);
+#endif /* GARGLK */
+ }
+}
+
+void Processor::z_set_window() {
+ int win = zargs[0];
+
+ if (win == 0) {
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+ } else {
+ if (gos_upper)
+ glk_set_window(gos_upper);
+ gos_curwin = gos_upper;
+ }
+
+ if (win == 0)
+ enable_scripting = true;
+ else
+ enable_scripting = false;
+
+ zargs[0] = 0xf000; // tickle tickle!
+ z_set_text_style();
+}
+
+void Processor::pad_status_line(int column) {
+ int spaces;
+ spaces = (h_screen_cols + 1 - curx) - column;
+ while (spaces-- > 0)
+ print_char(' ');
+}
+
+void Processor::z_show_status() {
+ zword global0;
+ zword global1;
+ zword global2;
+ zword addr;
+
+ bool brief = false;
+
+ if (!gos_upper)
+ return;
+
+ // One V5 game (Wishbringer Solid Gold) contains this opcode by accident,
+ // so just return if the version number does not fit
+ if (h_version >= V4)
+ return;
+
+ // Read all relevant global variables from the memory of the Z-machine
+ // into local variables
+
+ addr = h_globals;
+ LOW_WORD(addr, global0);
+ addr += 2;
+ LOW_WORD(addr, global1);
+ addr += 2;
+ LOW_WORD(addr, global2);
+
+ // Move to top of the status window, and print in reverse style.
+ glk_set_window(gos_upper);
+ gos_curwin = gos_upper;
+
+#ifdef GARGLK
+ garglk_set_reversevideo(true);
+#endif /* GARGLK */
+
+ curx = cury = 1;
+ glk_window_move_cursor(gos_upper, 0, 0);
+
+ // If the screen width is below 55 characters then we have to use
+ // the brief status line format
+ if (h_screen_cols < 55)
+ brief = true;
+
+ // Print the object description for the global variable 0
+ print_char (' ');
+ print_object (global0);
+
+ // A header flag tells us whether we have to display the current
+ // time or the score/moves information
+ if (h_config & CONFIG_TIME) {
+ // print hours and minutes
+ zword hours = (global1 + 11) % 12 + 1;
+
+ pad_status_line (brief ? 15 : 20);
+
+ print_string ("Time: ");
+
+ if (hours < 10)
+ print_char (' ');
+ print_num (hours);
+
+ print_char (':');
+
+ if (global2 < 10)
+ print_char ('0');
+ print_num (global2);
+
+ print_char (' ');
+
+ print_char ((global1 >= 12) ? 'p' : 'a');
+ print_char ('m');
+
+ } else {
+ // print score and moves
+ pad_status_line (brief ? 15 : 30);
+
+ print_string (brief ? "S: " : "Score: ");
+ print_num (global1);
+
+ pad_status_line (brief ? 8 : 14);
+
+ print_string (brief ? "M: " : "Moves: ");
+ print_num (global2);
+ }
+
+ // Pad the end of the status line with spaces
+ pad_status_line (0);
+
+ // Return to the lower window
+ glk_set_window(gos_lower);
+ gos_curwin = gos_lower;
+}
+
+void Processor::z_split_window() {
+ split_window(zargs[0]);
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle