diff --git a/engines/glk/frotz/glk_interface.cpp b/engines/glk/frotz/glk_interface.cpp index 4aa2ba4e78e3..514435aaf041 100644 --- a/engines/glk/frotz/glk_interface.cpp +++ b/engines/glk/frotz/glk_interface.cpp @@ -33,13 +33,11 @@ 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(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0), - curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr), - gos_lower(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), + _pics(nullptr), oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0), curr_fg(-2), curr_bg(-2), + 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) { Common::fill(&statusline[0], &statusline[256], '\0'); } @@ -103,47 +101,14 @@ void GlkInterface::initialize() { * Get the screen size */ - gos_lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0); - if (!gos_lower) - gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0); - glk_window_get_size(gos_lower, &width, &height); - glk_window_close(gos_lower, nullptr); + _wp._lower = glk_window_open(0, 0, 0, wintype_TextGrid, 0); + if (!_wp._lower) + _wp._lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0); + glk_window_get_size(_wp._lower, &width, &height); + glk_window_close(_wp._lower, nullptr); gos_channel = nullptr; - /* - * Icky magic bit setting - */ - - if (h_version == V3 && _tandyBit) - h_config |= CONFIG_TANDY; - - if (h_version == V3 && gos_upper) - h_config |= CONFIG_SPLITSCREEN; - - if (h_version == V3 && !gos_upper) - h_config |= CONFIG_NOSTATUSLINE; - - if (h_version >= V4) - h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS | - CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR; - - if (h_version >= V5) - h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG); - - if ((h_version >= 5) && (h_flags & SOUND_FLAG)) - h_flags |= SOUND_FLAG; - - if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG)) - h_flags |= OLD_SOUND_FLAG; - - if ((h_version == 6) && (_sound != 0)) - h_config |= CONFIG_SOUND; - - if (h_version >= V5 && (h_flags & UNDO_FLAG)) - if (_undo_slots == 0) - h_flags &= ~UNDO_FLAG; - h_screen_cols = width; h_screen_rows = height; @@ -180,14 +145,48 @@ void GlkInterface::initialize() { if (_storyId == BEYOND_ZORK) showBeyondZorkTitle(); - gos_lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0); - gos_upper = glk_window_open(gos_lower, - winmethod_Above | winmethod_Fixed, - 0, - wintype_TextGrid, 0); + _wp._lower = glk_window_open(0, 0, 0, wintype_TextBuffer, 0); + _wp._upper = glk_window_open(_wp._lower, winmethod_Above | winmethod_Fixed, 0, wintype_TextGrid, 0); - glk_set_window(gos_lower); - gos_curwin = gos_lower; + glk_set_window(_wp._lower); + gos_curwin = _wp._lower; + + /* + * Icky magic bit setting + */ + + if (h_version == V3 && _tandyBit) + h_config |= CONFIG_TANDY; + + if (h_version == V3 && _wp._upper) + h_config |= CONFIG_SPLITSCREEN; + + if (h_version == V3 && !_wp._upper) + h_config |= CONFIG_NOSTATUSLINE; + + if (h_version >= V4) + h_config |= CONFIG_BOLDFACE | CONFIG_EMPHASIS | + CONFIG_FIXED | CONFIG_TIMEDINPUT | CONFIG_COLOUR; + + if (h_version >= V5) + h_flags &= ~(GRAPHICS_FLAG | MOUSE_FLAG | MENU_FLAG); + + if ((h_version >= 5) && (h_flags & SOUND_FLAG)) + h_flags |= SOUND_FLAG; + + if ((h_version == 3) && (h_flags & OLD_SOUND_FLAG)) + h_flags |= OLD_SOUND_FLAG; + + if ((h_version == 6) && (_sound != 0)) + h_config |= CONFIG_SOUND; + + if (h_version >= V5 && (h_flags & UNDO_FLAG)) + if (_undo_slots == 0) + h_flags &= ~UNDO_FLAG; + + /* + * Miscellaneous + */ // Set the screen colors garglk_set_zcolors(_defaultForeground, _defaultBackground); @@ -199,7 +198,7 @@ void GlkInterface::initialize() { // since the arrow keys the original used are in use now for cycling prior commands if (_storyId == BEYOND_ZORK) { uint32 KEYCODES[2] = { keycode_PageUp, keycode_PageDown }; - glk_set_terminators_line_event(gos_lower, KEYCODES, 2); + glk_set_terminators_line_event(_wp._lower, KEYCODES, 2); } } @@ -322,12 +321,12 @@ void GlkInterface::start_next_sample() { void GlkInterface::gos_update_width() { uint width; - if (gos_upper) { - glk_window_get_size(gos_upper, &width, nullptr); + if (_wp._upper) { + glk_window_get_size(_wp._upper, &width, nullptr); h_screen_cols = width; SET_BYTE(H_SCREEN_COLS, width); if ((uint)curx > width) { - glk_window_move_cursor(gos_upper, 0, cury - 1); + glk_window_move_cursor(_wp._upper, 0, cury - 1); curx = 1; } } @@ -337,8 +336,8 @@ void GlkInterface::gos_update_height() { uint height_upper; uint height_lower; if (gos_curwin) { - glk_window_get_size(gos_upper, nullptr, &height_upper); - glk_window_get_size(gos_lower, nullptr, &height_lower); + glk_window_get_size(_wp._upper, nullptr, &height_upper); + glk_window_get_size(_wp._lower, nullptr, &height_lower); h_screen_rows = height_upper + height_lower + 1; SET_BYTE(H_SCREEN_ROWS, h_screen_rows); } @@ -346,11 +345,11 @@ void GlkInterface::gos_update_height() { void GlkInterface::reset_status_ht() { uint height; - if (gos_upper) { - glk_window_get_size(gos_upper, nullptr, &height); + if (_wp._upper) { + glk_window_get_size(_wp._upper, nullptr, &height); if ((uint)mach_status_ht != height) { glk_window_set_arrangement( - glk_window_get_parent(gos_upper), + glk_window_get_parent(_wp._upper), winmethod_Above | winmethod_Fixed, mach_status_ht, nullptr); } @@ -359,23 +358,21 @@ void GlkInterface::reset_status_ht() { void GlkInterface::erase_window(zword w) { if (w == 0) - glk_window_clear(gos_lower); - else if (gos_upper) { + glk_window_clear(_wp._lower); + else if (_wp._upper) { #ifdef GARGLK - garglk_set_reversevideo_stream( - glk_window_get_stream(gos_upper), - true); + garglk_set_reversevideo_stream(glk_window_get_stream(_wp._upper), true); #endif /* GARGLK */ memset(statusline, ' ', sizeof statusline); - glk_window_clear(gos_upper); + glk_window_clear(_wp._upper); reset_status_ht(); curr_status_ht = 0; } } void GlkInterface::split_window(zword lines) { - if (!gos_upper) + if (!_wp._upper) return; // The top line is always set for V1 to V3 games @@ -385,10 +382,10 @@ void GlkInterface::split_window(zword lines) { if (!lines || lines > curr_status_ht) { uint height; - glk_window_get_size(gos_upper, nullptr, &height); + glk_window_get_size(_wp._upper, nullptr, &height); if (lines != height) glk_window_set_arrangement( - glk_window_get_parent(gos_upper), + glk_window_get_parent(_wp._upper), winmethod_Above | winmethod_Fixed, lines, nullptr); curr_status_ht = lines; @@ -396,13 +393,13 @@ void GlkInterface::split_window(zword lines) { mach_status_ht = lines; if (cury > lines) { - glk_window_move_cursor(gos_upper, 0, 0); + glk_window_move_cursor(_wp._upper, 0, 0); curx = cury = 1; } gos_update_width(); if (h_version == V3) - glk_window_clear(gos_upper); + glk_window_clear(_wp._upper); } void GlkInterface::restart_screen() { @@ -471,9 +468,9 @@ void GlkInterface::smartstatusline() { memcpy(buf + 1 + scoreofs, c, scorelen * sizeof(zchar)); memcpy(buf + 1, a, roomlen * sizeof(zchar)); - glk_window_move_cursor(gos_upper, 0, 0); + glk_window_move_cursor(_wp._upper, 0, 0); glk_put_buffer_uni(buf, h_screen_cols); - glk_window_move_cursor(gos_upper, cury - 1, curx - 1); + glk_window_move_cursor(_wp._upper, cury - 1, curx - 1); } void GlkInterface::gos_cancel_pending_line() { @@ -510,7 +507,7 @@ void GlkInterface::os_draw_picture(int picture, winid_t win, const Common::Rect zchar GlkInterface::os_read_key(int timeout, bool show_cursor) { event_t ev; - winid_t win = gos_curwin ? gos_curwin : gos_lower; + winid_t win = gos_curwin ? gos_curwin : _wp._lower; if (gos_linepending) gos_cancel_pending_line(); @@ -536,7 +533,7 @@ zchar GlkInterface::os_read_key(int timeout, bool show_cursor) { glk_request_timer_events(0); - if (gos_upper && mach_status_ht < curr_status_ht) + if (_wp._upper && mach_status_ht < curr_status_ht) reset_status_ht(); curr_status_ht = 0; @@ -558,7 +555,7 @@ zchar GlkInterface::os_read_key(int timeout, bool show_cursor) { zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, int continued) { event_t ev; - winid_t win = gos_curwin ? gos_curwin : gos_lower; + winid_t win = gos_curwin ? gos_curwin : _wp._lower; if (!continued && gos_linepending) gos_cancel_pending_line(); @@ -592,7 +589,7 @@ zchar GlkInterface::os_read_line(int max, zchar *buf, int timeout, int width, in buf[ev.val1] = '\0'; // If the upper status line area was expanded to show a text box/quotation, restore it back - if (gos_upper && mach_status_ht < curr_status_ht) + if (_wp._upper && mach_status_ht < curr_status_ht) reset_status_ht(); curr_status_ht = 0; diff --git a/engines/glk/frotz/glk_interface.h b/engines/glk/frotz/glk_interface.h index 4d691515608e..5027edb4d566 100644 --- a/engines/glk/frotz/glk_interface.h +++ b/engines/glk/frotz/glk_interface.h @@ -25,6 +25,7 @@ #include "glk/glk_api.h" #include "glk/frotz/mem.h" +#include "glk/frotz/windows.h" namespace Glk { namespace Frotz { @@ -67,9 +68,8 @@ class GlkInterface : public GlkAPI, public virtual UserOptions, public virtual M int curr_status_ht; int mach_status_ht; + Windows _wp; winid_t gos_status; - winid_t gos_upper; - winid_t gos_lower; winid_t gos_curwin; int gos_linepending; zchar *gos_linebuf; diff --git a/engines/glk/frotz/processor_screen.cpp b/engines/glk/frotz/processor_screen.cpp index 33c91081ca7a..60672c85abff 100644 --- a/engines/glk/frotz/processor_screen.cpp +++ b/engines/glk/frotz/processor_screen.cpp @@ -26,7 +26,7 @@ namespace Glk { namespace Frotz { void Processor::screen_mssg_on() { - if (gos_curwin == gos_lower) { + if (gos_curwin == _wp._lower) { oldstyle = curstyle; glk_set_style(style_Preformatted); glk_put_string("\n "); @@ -34,7 +34,7 @@ void Processor::screen_mssg_on() { } void Processor::screen_mssg_off() { - if (gos_curwin == gos_lower) { + if (gos_curwin == _wp._lower) { glk_put_char('\n'); zargs[0] = 0; z_set_text_style(); @@ -98,7 +98,7 @@ uint32 Processor::zchar_to_unicode_rune(zchar c) { void Processor::screen_char(zchar c) { if (gos_linepending && (gos_curwin == gos_linewin)) { gos_cancel_pending_line(); - if (gos_curwin == gos_upper) { + if (gos_curwin == _wp._upper) { curx = 1; cury ++; } @@ -119,7 +119,7 @@ void Processor::screen_char(zchar c) { fixforced = false; } - if (gos_upper && gos_curwin == gos_upper) { + if (_wp._upper && gos_curwin == _wp._upper) { if (c == '\n' || c == ZC_RETURN) { glk_put_char('\n'); curx = 1; @@ -151,7 +151,7 @@ void Processor::screen_char(zchar c) { curx++; } } - } else if (gos_curwin == gos_lower) { + } else if (gos_curwin == _wp._lower) { if (c == ZC_RETURN) glk_put_char('\n'); else { @@ -200,7 +200,7 @@ store((zword)os_buffer_screen((zargs[0] == (zword)-1) ? -1 : zargs[0])); void Processor::z_erase_line() { int i; - if (gos_upper && gos_curwin == gos_upper) { + if (_wp._upper && gos_curwin == _wp._upper) { for (i = 0; i < h_screen_cols + 1 - curx; i++) glk_put_char(' '); glk_window_move_cursor(gos_curwin, curx - 1, cury - 1); @@ -211,34 +211,33 @@ void Processor::z_erase_window() { short w = zargs[0]; if (w == -2) { - if (gos_upper) { - glk_set_window(gos_upper); + if (_wp._upper) { + glk_set_window(_wp._upper); #ifdef GARGLK garglk_set_zcolors(curr_fg, curr_bg); #endif /* GARGLK */ - glk_window_clear(gos_upper); + glk_window_clear(_wp._upper); glk_set_window(gos_curwin); } - glk_window_clear(gos_lower); + glk_window_clear(_wp._lower); } if (w == -1) { - if (gos_upper) { - glk_set_window(gos_upper); + if (_wp._upper) { + glk_set_window(_wp._upper); #ifdef GARGLK garglk_set_zcolors(curr_fg, curr_bg); #endif /* GARGLK */ - glk_window_clear(gos_upper); + glk_window_clear(_wp._upper); } - glk_window_clear(gos_lower); + glk_window_clear(_wp._lower); split_window(0); - glk_set_window(gos_lower); - gos_curwin = gos_lower; + glk_set_window(_wp._lower); + gos_curwin = _wp._lower; } - if (w == 0) - glk_window_clear(gos_lower); - if (w == 1 && gos_upper) - glk_window_clear(gos_upper); + + if (w >= 0 && _wp[w]) + glk_window_clear(_wp[w]); } void Processor::z_get_cursor() { @@ -260,7 +259,7 @@ void Processor::z_print_table() { // Write text in width x height rectangle for (i = 0; i < zargs[2]; i++, curx = xs, cury++) { - glk_window_move_cursor(cwin == 0 ? gos_lower : gos_upper, xs - 1, cury - 1); + glk_window_move_cursor(_wp[cwin], xs - 1, cury - 1); for (j = 0; j < zargs[1]; j++) { LOW_BYTE(addr, c); @@ -384,7 +383,7 @@ void Processor::z_set_font() { void Processor::z_set_cursor() { int x = (int16)zargs[1], y = (int16)zargs[0]; - assert(gos_upper); + assert(_wp._upper); flush_buffer(); @@ -394,7 +393,8 @@ void Processor::z_set_cursor() { } if (!x || !y) { - Point cursorPos = gos_upper->getCursor(); + winid_t win = _wp._upper; + Point cursorPos = win->getCursor(); if (!x) x = cursorPos.x; if (!y) @@ -409,7 +409,7 @@ void Processor::z_set_cursor() { reset_status_ht(); } - glk_window_move_cursor(gos_upper, curx - 1, cury - 1); + glk_window_move_cursor(_wp._upper, curx - 1, cury - 1); } void Processor::z_set_text_style() { @@ -468,12 +468,12 @@ void Processor::z_set_window() { cwin = zargs[0]; if (cwin == 0) { - glk_set_window(gos_lower); - gos_curwin = gos_lower; + glk_set_window(_wp._lower); + gos_curwin = _wp._lower; } else { - if (gos_upper) - glk_set_window(gos_upper); - gos_curwin = gos_upper; + if (_wp._upper) + glk_set_window(_wp._upper); + gos_curwin = _wp._upper; } if (cwin == 0) @@ -500,7 +500,7 @@ void Processor::z_show_status() { bool brief = false; - if (!gos_upper) + if (!_wp._upper) return; // One V5 game (Wishbringer Solid Gold) contains this opcode by accident, @@ -519,15 +519,15 @@ void Processor::z_show_status() { 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; + glk_set_window(_wp._upper); + gos_curwin = _wp._upper; #ifdef GARGLK garglk_set_reversevideo(true); #endif /* GARGLK */ curx = cury = 1; - glk_window_move_cursor(gos_upper, 0, 0); + glk_window_move_cursor(_wp._upper, 0, 0); // If the screen width is below 55 characters then we have to use // the brief status line format @@ -580,8 +580,8 @@ void Processor::z_show_status() { pad_status_line (0); // Return to the lower window - glk_set_window(gos_lower); - gos_curwin = gos_lower; + glk_set_window(_wp._lower); + gos_curwin = _wp._lower; } void Processor::z_split_window() { diff --git a/engines/glk/frotz/processor_windows.cpp b/engines/glk/frotz/processor_windows.cpp index c0a1e3feeedc..ad16bbafe611 100644 --- a/engines/glk/frotz/processor_windows.cpp +++ b/engines/glk/frotz/processor_windows.cpp @@ -51,7 +51,8 @@ void Processor::z_draw_picture() { if (!x || !y) { // Currently I only support getting the cursor for the text grid area assert(cwin == 1); - Point cursPos = gos_upper->getCursor(); + winid_t win = _wp._upper; + Point cursPos = win->getCursor(); // use cursor column if x-coordinate is 0 if (!x) x = cursPos.x; @@ -82,18 +83,18 @@ void Processor::z_draw_picture() { if (_storyId == ARTHUR && pic == 54) delta = h_screen_width / 160; - os_draw_picture(mapper[i].pic1, gos_lower, Point(x + delta, y + height1)); - os_draw_picture(mapper[i].pic2, gos_lower, Point(x + width1 - width2 - delta, y + height1)); + os_draw_picture(mapper[i].pic1, _wp._lower, Point(x + delta, y + height1)); + os_draw_picture(mapper[i].pic2, _wp._lower, Point(x + width1 - width2 - delta, y + height1)); } } - os_draw_picture(pic, gos_lower, Point(x, y)); + os_draw_picture(pic, _wp._lower, Point(x, y)); if (_storyId == SHOGUN && pic == 3) { uint height, width; os_picture_data(59, &height, &width); - os_draw_picture(59, gos_lower, Point(h_screen_width - width + 1, y)); + os_draw_picture(59, _wp._lower, Point(h_screen_width - width + 1, y)); } } diff --git a/engines/glk/frotz/windows.cpp b/engines/glk/frotz/windows.cpp new file mode 100644 index 000000000000..8bdfafd8799f --- /dev/null +++ b/engines/glk/frotz/windows.cpp @@ -0,0 +1,97 @@ +/* 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/screen.h" +#include "glk/conf.h" +#include "common/file.h" +#include "graphics/fonts/ttf.h" +#include "image/bmp.h" + +namespace Glk { +namespace Frotz { + +FrotzScreen::FrotzScreen() : Glk::Screen() { + g_conf->_tStyles[style_User1].font = CUSTOM; + g_conf->_gStyles[style_User1].font = CUSTOM; + g_conf->_tStyles[style_User2].font = CUSTOM2; +} + +void FrotzScreen::loadFonts(Common::Archive *archive) { + Screen::loadFonts(archive); + + // Add character graphics font + Image::BitmapDecoder decoder; + Common::File f; + if (!f.open("infocom_graphics.bmp", *archive)) + error("Could not load font"); + + Common::Point fontSize(_fonts[0]->getMaxCharWidth(), _fonts[0]->getFontHeight()); + decoder.loadStream(f); + _fonts.push_back(new Frotz::BitmapFont(*decoder.getSurface(), fontSize)); + f.close(); + + // Add Runic font. It provides cleaner versions of the runic characters in the + // character graphics font + if (!f.open("NotoSansRunic-Regular.ttf", *archive)) + error("Could not load font"); + + _fonts.push_back(Graphics::loadTTFFont(f, g_conf->_propInfo._size, Graphics::kTTFSizeModeCharacter)); + f.close(); +} + +/*--------------------------------------------------------------------------*/ + +BitmapFont::BitmapFont(const Graphics::Surface &src, const Common::Point &size, + uint srcWidth, uint srcHeight, unsigned char startingChar) : + _startingChar(startingChar), _size(size) { + assert(src.format.bytesPerPixel == 1); + assert((src.w % srcWidth) == 0); + assert((src.h % srcHeight) == 0); + + // Set up a characters array + _chars.resize((src.w / srcWidth) * (src.h / srcHeight)); + + // Iterate through loading characters + Common::Rect r(srcWidth, srcHeight); + int charsPerRow = src.w / srcWidth; + for (uint idx = 0; idx < _chars.size(); ++idx) { + r.moveTo((idx % charsPerRow) * srcWidth, (idx / charsPerRow) * srcHeight); + + _chars[idx].create(size.x, size.y, src.format); + _chars[idx].transBlitFrom(src, r, Common::Rect(0, 0, size.x, size.y)); + } +} + +void BitmapFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 color) const { + const Graphics::ManagedSurface &c = _chars[chr - _startingChar]; + for (int yCtr = 0; yCtr < c.h; ++yCtr) { + const byte *srcP = (const byte *)c.getBasePtr(0, yCtr); + + for (int xCtr = 0; xCtr < c.w; ++xCtr, ++srcP) { + if (!*srcP) + dst->hLine(x + xCtr, y + yCtr, x + xCtr, color); + } + } +} + +} // End of namespace Scott +} // End of namespace Glk diff --git a/engines/glk/frotz/windows.h b/engines/glk/frotz/windows.h new file mode 100644 index 000000000000..566d2fd5c808 --- /dev/null +++ b/engines/glk/frotz/windows.h @@ -0,0 +1,97 @@ +/* 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_FROTZ_WINDOWS +#define GLK_FROTZ_WINDOWS + +namespace Glk { +namespace Frotz { + +/** + * Represents one of the virtual windows + */ +class Window { +private: + winid_t _win; +public: + /** + * Constructor + */ + Window() : _win(nullptr) {} + + /** + * Assignment operator + */ + Window &operator=(winid_t win) { + _win = win; + return *this; + } + + /** + * Cast operator for getting a Glk window + */ + operator winid_t() const { return _win; } + + /** + * Cast operator for testing if the window is valid (present) + */ + operator bool() const { return _win != nullptr; } + + /** + * Property access. There are the following properties defined by the spec: + * 0 y coordinate 6 left margin size 12 font number + * 1 x coordinate 7 right margin size 13 font size + * 2 y size 8 newline interrupt routine 14 attributes + * 3 x size 9 interrupt countdown 15 line count + * 4 y cursor 10 text style 16 true foreground colour + * 5 x cursor 11 colour data 17 true background colour + */ +}; + +/** + * The Z-machine has 8 virtual windows + */ +class Windows { +private: + Window _windows[8]; +public: + Window &_lower; + Window &_upper; +public: + /** + * Constructor + */ + Windows() : _lower(_windows[0]), _upper(_windows[1]) {} + + /** + * Array access + */ + Window &operator[](uint idx) { + assert(idx < 8); + return _windows[idx]; + } +}; + +} // End of namespace Frotz +} // End of namespace Glk + +#endif diff --git a/engines/glk/module.mk b/engines/glk/module.mk index da3de68fdec2..38f19c5a8afb 100644 --- a/engines/glk/module.mk +++ b/engines/glk/module.mk @@ -53,6 +53,7 @@ MODULE_OBJS := \ frotz/quetzal.o \ frotz/screen.o \ frotz/sound_folder.o \ + frotz/windows.o \ glulxe/detection.o \ glulxe/glulxe.o \ magnetic/detection.o \