/* 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 Glk { namespace Frotz { static struct { Story story_id; int pic; int pic1; int pic2; } mapper[] = { { ZORK_ZERO, 5, 497, 498 }, { ZORK_ZERO, 6, 501, 502 }, { ZORK_ZERO, 7, 499, 500 }, { ZORK_ZERO, 8, 503, 504 }, { ARTHUR, 54, 170, 171 }, { SHOGUN, 50, 61, 62 }, { UNKNOWN, 0, 0, 0 } }; void Processor::z_draw_picture() { zword pic = zargs[0]; zword y = zargs[1]; zword x = zargs[2]; int i; flush_buffer(); if (!x || !y) { // Currently I only support getting the cursor for the text grid area assert(cwin == 1); winid_t win = _wp._upper; Point cursPos = win->getCursor(); // use cursor column if x-coordinate is 0 if (!x) x = cursPos.x; // use cursor line if y-coordinate is 0 if (!y) y = cursPos.y; } // y += cwp->y_pos - 1; // x += cwp->x_pos - 1; /* The following is necessary to make Amiga and Macintosh story * files work with MCGA graphics files. Some screen-filling * pictures of the original Amiga release like the borders of * Zork Zero were split into several MCGA pictures (left, right * and top borders). We pretend this has not happened. */ for (i = 0; mapper[i].story_id != UNKNOWN; i++) { if (_storyId == mapper[i].story_id && pic == mapper[i].pic) { uint height1, width1; uint height2, width2; int delta = 0; os_picture_data(pic, &height1, &width1); os_picture_data(mapper[i].pic2, &height2, &width2); if (_storyId == ARTHUR && pic == 54) delta = h_screen_width / 160; 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, _wp._lower, Point(x, y)); if (_storyId == SHOGUN && pic == 3) { uint height, width; os_picture_data(59, &height, &width); os_draw_picture(59, _wp._lower, Point(h_screen_width - width + 1, y)); } } void Processor::z_picture_data() { zword pic = zargs[0]; zword table = zargs[1]; uint height, width; int i; bool avail = os_picture_data(pic, &height, &width); for (i = 0; mapper[i].story_id != UNKNOWN; i++) { if (_storyId == mapper[i].story_id) { if (pic == mapper[i].pic) { uint height2, width2; avail &= os_picture_data(mapper[i].pic1, &height2, &width2); avail &= os_picture_data(mapper[i].pic2, &height2, &width2); height += height2; } else if (pic == mapper[i].pic1 || pic == mapper[i].pic2) { avail = false; } } } storew((zword)(table + 0), (zword)(height)); storew((zword)(table + 2), (zword)(width)); branch(avail); } void Processor::z_erase_picture() { #ifdef TODO int height, width; zword y = zargs[1]; zword x = zargs[2]; flush_buffer(); /* Do nothing if the background is transparent */ if (hi(cwp->colour) == TRANSPARENT_COLOUR) return; if (y == 0) /* use cursor line if y-coordinate is 0 */ y = cwp->y_cursor; if (x == 0) /* use cursor column if x-coordinate is 0 */ x = cwp->x_cursor; os_picture_data(zargs[0], &height, &width); y += cwp->y_pos - 1; x += cwp->x_pos - 1; os_erase_area(y, x, y + height - 1, x + width - 1, -1); #endif } void Processor::z_set_margins() { #ifdef TODO zword win = winarg2(); flush_buffer(); wp[win].left = zargs[0]; wp[win].right = zargs[1]; /* Protect the margins */ if (wp[win].x_cursor <= zargs[0] || wp[win].x_cursor > wp[win].x_size - zargs[1]) { wp[win].x_cursor = zargs[0] + 1; if (win == cwin) update_cursor(); } #endif } void Processor::z_move_window(void) { flush_buffer(); zword win = winarg0(); _wp[win].setPosition(Point(zargs[2], zargs[1])); } void Processor::z_window_size() { flush_buffer(); zword win = winarg0(); _wp[win].setSize(Point(zargs[2], zargs[1])); } void Processor::z_window_style() { #ifdef TODO zword win = winarg0(); zword flags = zargs[1]; flush_buffer(); /* Supply default arguments */ if (zargc < 3) zargs[2] = 0; /* Set window style */ switch (zargs[2]) { case 0: wp[win].attribute = flags; break; case 1: wp[win].attribute |= flags; break; case 2: wp[win].attribute &= ~flags; break; case 3: wp[win].attribute ^= flags; break; } if (cwin == win) update_attributes(); #endif } void Processor::z_get_wind_prop() { flush_buffer(); zword win = winarg0(); zword prop = zargs[1]; if (prop <= TRUE_BG_COLOR) store(_wp[win][(WindowProperty)prop]); else runtimeError(ERR_ILL_WIN_PROP); } void Processor::z_put_wind_prop() { #ifdef TODO flush_buffer(); if (zargs[1] >= 16) runtimeError(ERR_ILL_WIN_PROP); ((zword *)(wp + winarg0()))[zargs[1]] = zargs[2]; #endif } void Processor::z_scroll_window() { #ifdef TODO zword win = winarg0(); zword y, x; flush_buffer(); /* Use the correct set of colours when scrolling the window */ if (win != cwin && !amiga_screen_model()) os_set_colour(lo(wp[win].colour), hi(wp[win].colour)); y = wp[win].y_pos; x = wp[win].x_pos; os_scroll_area(y, x, y + wp[win].y_size - 1, x + wp[win].x_size - 1, (short)zargs[1]); if (win != cwin && !amiga_screen_model()) os_set_colour(lo(cwp->colour), hi(cwp->colour)); #endif } void Processor::z_mouse_window() { // No implementation - since ScummVM can run as a window, it's better // not to constrain the area the mouse can move } void Processor::z_picture_table() { /* This opcode is used by Shogun and Zork Zero when the player * encounters built-in games such as Peggleboz. Nowadays it is * not very helpful to hold the picture data in memory because * even a small disk cache avoids re-loading of data. */ } zword Processor::winarg0() { if (h_version == V6 && (short)zargs[0] == -3) return cwin; if (zargs[0] >= ((h_version == V6) ? 8 : 2)) runtimeError(ERR_ILL_WIN); return zargs[0]; } zword Processor::winarg2() { if (zargc < 3 || (short)zargs[2] == -3) return cwin; if (zargs[2] >= 8) runtimeError(ERR_ILL_WIN); return zargs[2]; } } // End of namespace Frotz } // End of namespace Glk