From 25b066520ed1247e2b3cd70433f9aa86c3587f7c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 15 Feb 2019 19:23:53 -0800 Subject: GLK: FROTZ: Improved setup and handling of fg/bg colors --- engines/glk/frotz/config.cpp | 14 ++- engines/glk/frotz/config.h | 10 +- engines/glk/frotz/glk_interface.cpp | 99 +++++++++++++++--- engines/glk/frotz/glk_interface.h | 21 +++- engines/glk/frotz/processor.h | 10 ++ engines/glk/frotz/processor_screen.cpp | 178 ++++++++++++++++----------------- engines/glk/frotz/screen.cpp | 2 +- engines/glk/frotz/windows.cpp | 5 + engines/glk/glk_api.cpp | 10 ++ engines/glk/glk_api.h | 3 + 10 files changed, 242 insertions(+), 110 deletions(-) (limited to 'engines/glk') diff --git a/engines/glk/frotz/config.cpp b/engines/glk/frotz/config.cpp index ad0764a9ab..6e7c260599 100644 --- a/engines/glk/frotz/config.cpp +++ b/engines/glk/frotz/config.cpp @@ -145,7 +145,12 @@ void Header::loadHeader(Common::SeekableReadStream &f) { /*--------------------------------------------------------------------------*/ -UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true), _quetzal(true) { +UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true), _quetzal(true), _color_enabled(false), + _err_report_mode(ERR_REPORT_ONCE), _ignore_errors(false), _expand_abbreviations(false), _tandyBit(false), + _piracy(false), _script_cols(0), _left_margin(0), _right_margin(0) { +} + +void UserOptions::initialize(uint hVersion) { _err_report_mode = getConfigInt("err_report_mode", ERR_REPORT_ONCE, ERR_REPORT_FATAL); _ignore_errors = getConfigBool("ignore_errors"); _expand_abbreviations = getConfigBool("expand_abbreviations"); @@ -161,8 +166,11 @@ UserOptions::UserOptions() : _undo_slots(MAX_UNDO_SLOTS), _sound(true), _quetzal _object_locating = getConfigBool("object_locating"); _object_movement = getConfigBool("object_movement"); - _defaultForeground = getConfigInt("foreground", 0xffffff, 0xffffff); - _defaultBackground = getConfigInt("background", 0x000080, 0xffffff); + int defaultFg = hVersion == V6 ? 0 : 0xffffff; + int defaultBg = hVersion == V6 ? 0xffffff : 0; + + _defaultForeground = getConfigInt("foreground", defaultFg, 0xffffff); + _defaultBackground = getConfigInt("background", defaultBg, 0xffffff); } bool UserOptions::isInfocom() const { diff --git a/engines/glk/frotz/config.h b/engines/glk/frotz/config.h index 1086d7e51f..7099996474 100644 --- a/engines/glk/frotz/config.h +++ b/engines/glk/frotz/config.h @@ -148,14 +148,20 @@ struct UserOptions { int _undo_slots; int _script_cols; int _err_report_mode; - uint _defaultForeground; - uint _defaultBackground; + int _defaultForeground; + int _defaultBackground; + bool _color_enabled; /** * Constructor */ UserOptions(); + /** + * Initializes the options + */ + void initialize(uint hVersion); + /** * Returns true if the game being played is one of the original Infocom releases */ diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp index 42dcdac999..77f5d19d8a 100644 --- a/engines/glk/frotz/glk_interface.cpp +++ b/engines/glk/frotz/glk_interface.cpp @@ -33,13 +33,14 @@ namespace Frotz { GlkInterface::GlkInterface(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc), - _pics(nullptr), oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0), - curr_fg(zcolor_Current), curr_bg(zcolor_Current), curr_font(1), prev_font(1), temp_font(0), + _pics(nullptr), oldstyle(0), curstyle(0), cury(1), curx(1), curr_font(1), prev_font(1), temp_font(0), curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_curwin(nullptr), gos_linepending(0), gos_linebuf(nullptr), gos_linewin(nullptr), gos_channel(nullptr), cwin(0), mwin(0), mouse_x(0), mouse_y(0), - menu_selected(0), enable_wrapping(false), enable_scripting(false), enable_scrolling(false), - enable_buffering(false), next_sample(0), next_volume(0), _soundLocked(false), _soundPlaying(false) { + fixforced(0), menu_selected(0), enable_wrapping(false), enable_scripting(false), enable_scrolling(false), + enable_buffering(false), next_sample(0), next_volume(0), _soundLocked(false), _soundPlaying(false), + _reverseVideo(false) { Common::fill(&statusline[0], &statusline[256], '\0'); + Common::fill(&zcolors[0], &zcolors[zcolor_NUMCOLORS], 0); } GlkInterface::~GlkInterface() { @@ -49,6 +50,29 @@ GlkInterface::~GlkInterface() { void GlkInterface::initialize() { uint width, height; + /* Setup options */ + UserOptions::initialize(h_version); + + /* Setup colors array */ + const int COLOR_MAP[zcolor_NUMCOLORS - 2] = { + 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 + }; + + zcolors[0] = -2; // Current + zcolors[1] = -1; // Default + for (int i = 2; i < zcolor_NUMCOLORS; ++i) + zcolors[i] = zRGB(COLOR_MAP[i - 2]); + /* * Init glk stuff */ @@ -134,11 +158,27 @@ void GlkInterface::initialize() { h_interpreter_number = h_version == 6 ? INTERP_MSDOS : INTERP_AMIGA; h_interpreter_version = 'F'; - // Set these per spec 8.3.2. - h_default_foreground = WHITE_COLOUR; - h_default_background = BLACK_COLOUR; - if (h_flags & COLOUR_FLAG) - h_flags &= ~COLOUR_FLAG; + // Set up the foreground & background + _color_enabled = ((h_version >= 5) && (h_flags & COLOUR_FLAG)) + || (_defaultForeground != -1) || (_defaultBackground != -1); + + if (_color_enabled) { + h_config |= CONFIG_COLOUR; + h_flags |= COLOUR_FLAG; // FIXME: beyond zork handling? + + assert(_defaultForeground != -1 && _defaultBackground != -1); + h_default_foreground = BLACK_COLOUR; + h_default_background = WHITE_COLOUR; + zcolors[h_default_foreground] = _defaultForeground; + zcolors[h_default_background] = _defaultBackground; + } else { + // Set these per spec 8.3.2. + h_default_foreground = WHITE_COLOUR; + h_default_background = BLACK_COLOUR; + + if (h_flags & COLOUR_FLAG) + h_flags &= ~COLOUR_FLAG; + } /* * Open the windows @@ -147,6 +187,11 @@ void GlkInterface::initialize() { showBeyondZorkTitle(); _wp.setup(h_version == 6); + for (uint i = 0; i < _wp.size(); ++i) { + _wp[i][TRUE_FG_COLOR] = zcolors[h_default_foreground]; + _wp[i][TRUE_BG_COLOR] = zcolors[h_default_background]; + } + cwin = 0; gos_curwin = _wp._lower; @@ -366,9 +411,7 @@ void GlkInterface::erase_window(zword w) { if (w == 0) glk_window_clear(_wp._lower); else if (_wp._upper) { -#ifdef GARGLK - garglk_set_reversevideo_stream(glk_window_get_stream(_wp._upper), true); -#endif /* GARGLK */ + //os_set_reverse_video(glk_window_get_stream(_wp._upper), true); memset(statusline, ' ', sizeof statusline); glk_window_clear(_wp._upper); @@ -512,6 +555,31 @@ void GlkInterface::os_draw_picture(int picture, const Common::Rect &r) { r.width() * cell.x, r.height() * cell.y); } +int GlkInterface::os_peek_color() { + if (_color_enabled) { + return _defaultBackground; + } else { + return (_reverseVideo) ? h_default_foreground : h_default_background; + } +/* + if (u_setup.color_enabled) { +#ifdef COLOR_SUPPORT + short fg, bg; + pair_content(PAIR_NUMBER(inch() & A_COLOR), &fg, &bg); + switch(bg) { + case COLOR_BLACK: return BLACK_COLOUR; + case COLOR_RED: return RED_COLOUR; + case COLOR_GREEN: return GREEN_COLOUR; + case COLOR_YELLOW: return YELLOW_COLOUR; + case COLOR_BLUE: return BLUE_COLOUR; + case COLOR_MAGENTA: return MAGENTA_COLOUR; + case COLOR_CYAN: return CYAN_COLOUR; + case COLOR_WHITE: return WHITE_COLOUR; + } + return 0; +#endif /* COLOR_SUPPORT */ +} + zchar GlkInterface::os_read_key(int timeout, bool show_cursor) { event_t ev; winid_t win = gos_curwin ? gos_curwin : _wp._lower; @@ -622,5 +690,12 @@ uint GlkInterface::roundDiv(uint x, uint y) { return quotient; } +void GlkInterface::os_set_reverse_video(bool flag) { +#ifdef GARGLK + _reverseVideo = flag; + garglk_set_reversevideo(flag); +#endif +} + } // End of namespace Frotz } // End of namespace Glk diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h index 93d0ecd4d2..ea7a104b8a 100644 --- a/engines/glk/frotz/glk_interface.h +++ b/engines/glk/frotz/glk_interface.h @@ -30,6 +30,12 @@ namespace Glk { namespace Frotz { +#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) _screen->format.RGBToColor(zR(i), zG(i), zB(i)) +#define zcolor_NUMCOLORS (13) + enum SoundEffect { EFFECT_PREPARE = 1, EFFECT_PLAY = 2, @@ -50,16 +56,18 @@ class Pics; * and sound effect handling */ class GlkInterface : public GlkAPI, public virtual UserOptions, public virtual Mem { +private: + bool _reverseVideo; public: Pics *_pics; zchar statusline[256]; + int zcolors[zcolor_NUMCOLORS]; int oldstyle; int curstyle; int cury; int curx; int fixforced; - uint curr_fg, curr_bg; int curr_font; int prev_font; int temp_font; @@ -182,6 +190,12 @@ protected: */ void os_draw_picture(int picture, const Common::Rect &r); + /** + * Return the colour of the pixel below the cursor. This is used by V6 games to print + * text on top of pictures. The coulor need not be in the standard set of Z-machine colours. + */ + int os_peek_color(); + /** * Call the IO interface to play a sample. */ @@ -238,6 +252,11 @@ protected: * Waits for the user to type an input line */ zchar os_read_line(int max, zchar *buf, int timeout, int width, int continued); + + /** + * Set whether reverse video mode is active + */ + void os_set_reverse_video(bool flag); public: /** * Constructor diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h index e992a78100..dddcc7609a 100644 --- a/engines/glk/frotz/processor.h +++ b/engines/glk/frotz/processor.h @@ -346,6 +346,16 @@ protected: */ void screen_word(const zchar *s); + /** + * Erase the entire screen to background colour. + */ + void erase_screen(zword win); + + /** + * Erase a window to background colour. + */ + void erase_window(zword win); + /**@}*/ /** diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp index a440cfa013..29650451d6 100644 --- a/engines/glk/frotz/processor_screen.cpp +++ b/engines/glk/frotz/processor_screen.cpp @@ -189,6 +189,36 @@ void Processor::screen_word(const zchar *s) { } } +void Processor::erase_screen(zword win) { + int curr_fg = _wp[1][TRUE_FG_COLOR]; + int curr_bg = _wp[1][TRUE_BG_COLOR]; + + if (win == -1) { + if (_wp._upper) { + glk_set_window(_wp._upper); +#ifdef GARGLK + garglk_set_zcolors(curr_fg, curr_bg); +#endif /* GARGLK */ + glk_window_clear(_wp._upper); + } + + glk_window_clear(_wp._lower); + split_window(0); + glk_set_window(_wp._lower); + gos_curwin = _wp._lower; + } +} + +void Processor::erase_window(zword win) { + if (h_version == V6 && win != cwin && h_interpreter_number != INTERP_AMIGA) + garglk_set_zcolors(_wp[win][TRUE_FG_COLOR], _wp[win][TRUE_BG_COLOR]); + + glk_window_clear(_wp[win]); + + if (h_version == V6 && win != cwin && h_interpreter_number != INTERP_AMIGA) + garglk_set_zcolors(_wp[cwin][TRUE_FG_COLOR], _wp[cwin][TRUE_BG_COLOR]); +} + void Processor::z_buffer_mode() { // No implementation } @@ -208,34 +238,14 @@ void Processor::z_erase_line() { } void Processor::z_erase_window() { - short w = zargs[0]; - if (w == -2) { - if (_wp._upper) { - glk_set_window(_wp._upper); -#ifdef GARGLK - garglk_set_zcolors(curr_fg, curr_bg); -#endif /* GARGLK */ - glk_window_clear(_wp._upper); - glk_set_window(gos_curwin); - } - glk_window_clear(_wp._lower); - } - if (w == -1) { - if (_wp._upper) { - glk_set_window(_wp._upper); -#ifdef GARGLK - garglk_set_zcolors(curr_fg, curr_bg); -#endif /* GARGLK */ - glk_window_clear(_wp._upper); - } - glk_window_clear(_wp._lower); - split_window(0); - glk_set_window(_wp._lower); - gos_curwin = _wp._lower; - } + short w = (short)zargs[0]; + + flush_buffer(); - if (w >= 0 && _wp[w]) - glk_window_clear(_wp[w]); + if (w == -1 || w == -2) + erase_screen(w); + else + erase_window(winarg0()); } void Processor::z_get_cursor() { @@ -270,12 +280,6 @@ void Processor::z_print_table() { } } -#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) _screen->format.RGBToColor(zR(i), zG(i), zB(i)) - void Processor::z_set_true_colour() { int zfore = zargs[0]; int zback = zargs[1]; @@ -289,63 +293,61 @@ void Processor::z_set_true_colour() { #ifdef GARGLK garglk_set_zcolors(zfore, zback); #endif /* GARGLK */ - - curr_fg = (uint)zfore; - curr_bg = (uint)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]; + int fg = zargs[0]; + int bg = zargs[1]; + zword win = (h_version == V6) ? winarg2() : 0; - switch (zfore) { - case -1: - case 0: - case 1: - zfore = zcolor_map[zfore]; - break; - - default: - if (zfore < zcolor_NUMCOLORS) - zfore = zRGB(zcolor_map[zfore]); - break; - } - - switch (zback) { - case -1: - case 0: - case 1: - zback = zcolor_map[zback]; - break; + flush_buffer(); - default: - if (zback < zcolor_NUMCOLORS) - zback = zRGB(zcolor_map[zback]); - break; + if ((short)fg == -1) + // Get color at cursor + fg = os_peek_color(); + if ((short)bg == -1) + // Get color at cursor + bg = os_peek_color(); + + if (fg == 0) + // keep current colour + fg = _wp[win][TRUE_FG_COLOR]; + if (bg == 0) + bg = _wp[win][TRUE_BG_COLOR]; + + if (fg == 1) + fg = h_default_foreground; + if (bg == 1) + bg = h_default_background; + + if (fg < zcolor_NUMCOLORS) + fg = zcolors[fg]; + if (bg < zcolor_NUMCOLORS) + bg = zcolors[bg]; + + if (h_version == V6 && h_interpreter_number == INTERP_AMIGA) { + // Changing colours of window 0 affects the entire screen + if (win == 0) { + for (int i = 1; i < 8; ++i) { + int bg2 = _wp[i][TRUE_BG_COLOR]; + int fg2 = _wp[i][TRUE_FG_COLOR]; + + if (bg2 < 16) + bg2 = (bg2 == _wp[0][TRUE_BG_COLOR]) ? fg : bg; + if (fg2 < 16) + fg2 = (fg2 == _wp[0][TRUE_FG_COLOR]) ? fg : bg; + + _wp[i][TRUE_FG_COLOR] = fg2; + _wp[i][TRUE_BG_COLOR] = bg2; + } + } } - garglk_set_zcolors(zfore, zback); + _wp[win][TRUE_FG_COLOR] = fg; + _wp[win][TRUE_BG_COLOR] = bg; - curr_fg = zfore; - curr_bg = zback; + if (win == cwin || h_version != V6) + garglk_set_zcolors(fg, bg); } void Processor::z_set_font() { @@ -432,9 +434,7 @@ void Processor::z_set_text_style() { return; if (style & REVERSE_STYLE) { -#ifdef GARGLK - garglk_set_reversevideo(true); -#endif /* GARGLK */ + os_set_reverse_video(true); } if (style & FIXED_WIDTH_STYLE) { @@ -460,9 +460,7 @@ void Processor::z_set_text_style() { } if (curstyle == 0) { -#ifdef GARGLK - garglk_set_reversevideo(false); -#endif /* GARGLK */ + os_set_reverse_video(false); } } @@ -524,9 +522,7 @@ void Processor::z_show_status() { glk_set_window(_wp._upper); gos_curwin = _wp._upper; -#ifdef GARGLK - garglk_set_reversevideo(true); -#endif /* GARGLK */ + os_set_reverse_video(true); curx = cury = 1; glk_window_move_cursor(_wp._upper, 0, 0); diff --git a/engines/glk/frotz/screen.cpp b/engines/glk/frotz/screen.cpp index d62c0dc68d..b1f28e498a 100644 --- a/engines/glk/frotz/screen.cpp +++ b/engines/glk/frotz/screen.cpp @@ -66,7 +66,7 @@ void FrotzScreen::loadVersion6Fonts(Common::Archive *archive) { pi._lineSeparation = 0; g_vm->_defaultForeground = 0; - g_vm->_defaultBackground = zcolor_Transparent; + g_vm->_defaultBackground = (int)zcolor_Transparent; g_conf->_tMarginX = 3; for (uint idx = 0; idx < style_NUMSTYLES; ++idx) { diff --git a/engines/glk/frotz/windows.cpp b/engines/glk/frotz/windows.cpp index a9728e15a7..4f59666705 100644 --- a/engines/glk/frotz/windows.cpp +++ b/engines/glk/frotz/windows.cpp @@ -127,6 +127,11 @@ const zword &Window::getProperty(WindowProperty propType) { void Window::setProperty(WindowProperty propType, zword value) { switch (propType) { + case TRUE_FG_COLOR: + case TRUE_BG_COLOR: + _properties[propType] = value; + break; + default: warning("Setting window property %d not yet supported", (int)propType); } diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp index 21640afe62..61c7a55aea 100644 --- a/engines/glk/glk_api.cpp +++ b/engines/glk/glk_api.cpp @@ -1199,4 +1199,14 @@ void GlkAPI::garglk_set_reversevideo_stream(strid_t str, uint reverse) { } } +void GlkAPI::garglk_window_get_cursor(winid_t win, uint *xpos, uint *ypos) { + Point pos = win->getCursor(); + *xpos = pos.x; + *ypos = pos.y; +} + +void GlkAPI::garglk_window_get_cursor_current(uint *xpos, uint *ypos) { + garglk_window_get_cursor(_windows->getFocusWindow(), xpos, ypos); +} + } // End of namespace Glk diff --git a/engines/glk/glk_api.h b/engines/glk/glk_api.h index ea42b83054..55994fd3c1 100644 --- a/engines/glk/glk_api.h +++ b/engines/glk/glk_api.h @@ -280,6 +280,9 @@ public: void garglk_set_zcolors_stream(strid_t str, uint fg, uint bg); void garglk_set_reversevideo(uint reverse); void garglk_set_reversevideo_stream(strid_t str, uint reverse); + + void garglk_window_get_cursor(winid_t win, uint *xpos, uint *ypos); + void garglk_window_get_cursor_current(uint *xpos, uint *ypos); }; } // End of namespace Glk -- cgit v1.2.3