diff options
Diffstat (limited to 'engines/glk/frotz/processor_screen.cpp')
-rw-r--r-- | engines/glk/frotz/processor_screen.cpp | 528 |
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 |