[Scummvm-cvs-logs] SF.net SVN: scummvm:[39515] scummvm/trunk/engines/sci

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Wed Mar 18 14:24:47 CET 2009


Revision: 39515
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39515&view=rev
Author:   thebluegr
Date:     2009-03-18 13:24:47 +0000 (Wed, 18 Mar 2009)

Log Message:
-----------
Renamed resmgr.cpp -> gfx_resmgr.cpp
Moved all files from gfx/resource/* to gfx/*

Modified Paths:
--------------
    scummvm/trunk/engines/sci/module.mk

Added Paths:
-----------
    scummvm/trunk/engines/sci/gfx/gfx_resmgr.cpp
    scummvm/trunk/engines/sci/gfx/picfill.cpp
    scummvm/trunk/engines/sci/gfx/res_cursor.cpp
    scummvm/trunk/engines/sci/gfx/res_font.cpp
    scummvm/trunk/engines/sci/gfx/res_pal.cpp
    scummvm/trunk/engines/sci/gfx/res_pic.cpp
    scummvm/trunk/engines/sci/gfx/res_view0.cpp
    scummvm/trunk/engines/sci/gfx/res_view1.cpp

Removed Paths:
-------------
    scummvm/trunk/engines/sci/gfx/resmgr.cpp
    scummvm/trunk/engines/sci/gfx/resource/

Copied: scummvm/trunk/engines/sci/gfx/gfx_resmgr.cpp (from rev 39505, scummvm/trunk/engines/sci/gfx/resmgr.cpp)
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_resmgr.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/gfx_resmgr.cpp	2009-03-18 13:24:47 UTC (rev 39515)
@@ -0,0 +1,623 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Resource manager core part
+
+// FIXME/TODO: The name "(Graphics) resource manager", and the associated
+// filenames, are misleading. This should be renamed to "Graphics manager"
+// or something like that.
+
+#include "sci/gfx/gfx_resource.h"
+#include "sci/gfx/gfx_tools.h"
+#include "sci/gfx/gfx_driver.h"
+#include "sci/gfx/gfx_resmgr.h"
+#include "sci/gfx/gfx_state_internal.h"
+#include "sci/gfx/font.h"
+
+#include "common/system.h"
+
+namespace Sci {
+
+// Invalid hash mode: Used to invalidate modified pics
+#define MODE_INVALID -1
+
+struct param_struct {
+	int args[4];
+	gfx_driver_t *driver;
+};
+
+#define DRAW_PIC01(pic, picStyle, isSci1) \
+	gfxr_draw_pic01((pic), flags, default_palette, res->size, res->data, (picStyle), res->id, (isSci1), state->static_palette);
+
+#define DRAW_PIC11(pic, picStyle) \
+	gfxr_draw_pic11((pic), flags, default_palette, res->size, res->data, (picStyle), res->id, state->static_palette);
+
+/* Calculate a picture
+** Parameters: (gfx_resstate_t *) state: The resource state, containing options and version information
+**             (gfxr_pic_t *) scaled_pic: The pic structure that is to be written to
+**             (gfxr_pic_t *) unscaled_pic: The pic structure the unscaled pic is to be written to,
+**                                          or NULL if it isn't needed.
+**             (int) flags: Pic drawing flags (interpreter dependant)
+**             (int) default_palette: The default palette to use for pic drawing (interpreter dependant)
+**             (int) nr: pic resource number
+** Returns   : (int) GFX_ERROR if the resource could not be found, GFX_OK otherwise
+*/
+int calculatePic(gfx_resstate_t *state, gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic, int flags, int default_palette, int nr) {
+	Resource *res = state->resManager->findResource(kResourceTypePic, nr, 0);
+	int need_unscaled = unscaled_pic != NULL;
+	gfxr_pic0_params_t style, basic_style;
+
+	basic_style.line_mode = GFX_LINE_MODE_CORRECT;
+	basic_style.brush_mode = GFX_BRUSH_MODE_SCALED;
+	basic_style.pic_port_bounds = state->options->pic_port_bounds;
+
+	style.line_mode = state->options->pic0_line_mode;
+	style.brush_mode = state->options->pic0_brush_mode;
+	style.pic_port_bounds = state->options->pic_port_bounds;
+
+	if (!res || !res->data)
+		return GFX_ERROR;
+
+	if (need_unscaled) {
+		if (state->version == SCI_VERSION_1_1)
+			DRAW_PIC11(unscaled_pic, &basic_style)
+		else
+			DRAW_PIC01(unscaled_pic, &basic_style, state->version >= SCI_VERSION_01_VGA)
+	}
+
+	if (scaled_pic && scaled_pic->undithered_buffer)
+		memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size);
+
+	if (state->version == SCI_VERSION_1_1)
+		DRAW_PIC11(scaled_pic, &style)
+	else
+		DRAW_PIC01(scaled_pic, &style, state->version >= SCI_VERSION_01_VGA)
+
+	if (state->version < SCI_VERSION_01_VGA) {
+		if (need_unscaled)
+			gfxr_remove_artifacts_pic0(scaled_pic, unscaled_pic);
+
+		if (!scaled_pic->undithered_buffer)
+			scaled_pic->undithered_buffer = sci_malloc(scaled_pic->undithered_buffer_size);
+
+		memcpy(scaled_pic->undithered_buffer, scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer_size);
+
+		gfxr_dither_pic0(scaled_pic, state->options->pic0_dither_mode, state->options->pic0_dither_pattern);
+	}
+
+	// Mark default palettes
+	if (scaled_pic)
+		scaled_pic->visual_map->loop = default_palette;
+
+	if (unscaled_pic)
+		unscaled_pic->visual_map->loop = default_palette;
+
+	return GFX_OK;
+}
+
+gfx_resstate_t *gfxr_new_resource_manager(int version, gfx_options_t *options, gfx_driver_t *driver, ResourceManager *resManager) {
+	gfx_resstate_t *state = new gfx_resstate_t();
+
+	state->version = version;
+	state->options = options;
+	state->driver = driver;
+	state->resManager = resManager;
+	state->static_palette = 0;
+
+	state->tag_lock_counter = state->lock_counter = 0;
+
+	return state;
+}
+
+int GfxResManager::getOptionsHash(gfx_resource_type_t type) {
+	switch (type) {
+	case GFX_RESOURCE_TYPE_VIEW:
+		// This should never happen
+		error("getOptionsHash called on a VIEW resource");
+
+	case GFX_RESOURCE_TYPE_PIC:
+		if (_state->version >= SCI_VERSION_01_VGA)
+			return _state->options->pic_port_bounds.y;
+		else
+			return (_state->options->pic0_unscaled) ? 0x10000 : (_state->options->pic0_dither_mode << 12)
+			       | (_state->options->pic0_dither_pattern << 8) | (_state->options->pic0_brush_mode << 4) 
+				   | (_state->options->pic0_line_mode);
+
+	case GFX_RESOURCE_TYPE_FONT:
+	case GFX_RESOURCE_TYPE_CURSOR:
+		return 0;
+
+	case GFX_RESOURCE_TYPES_NR:
+	default:
+		GFXERROR("Invalid resource type: %d\n", type);
+		return -1;
+	}
+}
+
+#define FREEALL(freecmd, type) \
+	if (resource->scaled_data.type) \
+		freecmd(resource->scaled_data.type); \
+	resource->scaled_data.type = NULL; \
+	if (resource->unscaled_data.type) \
+		freecmd(resource->unscaled_data.type); \
+	resource->unscaled_data.type = NULL;
+
+void gfxr_free_resource(gfx_resource_t *resource, int type) {
+	if (!resource)
+		return;
+
+	switch (type) {
+
+	case GFX_RESOURCE_TYPE_VIEW:
+		FREEALL(gfxr_free_view, view);
+		break;
+
+	case GFX_RESOURCE_TYPE_PIC:
+		FREEALL(gfxr_free_pic, pic);
+		break;
+
+	case GFX_RESOURCE_TYPE_FONT:
+		FREEALL(gfxr_free_font, font);
+		break;
+
+	case GFX_RESOURCE_TYPE_CURSOR:
+		FREEALL(gfx_free_pixmap, pointer);
+		break;
+
+	default:
+		GFXWARN("Attempt to free invalid resource type %d\n", type);
+	}
+
+	free(resource);
+}
+
+void GfxResManager::freeAllResources() {
+	for (int type = 0; type < GFX_RESOURCE_TYPES_NR; ++type) {
+		for (IntResMap::iterator iter = _state->_resourceMaps[type].begin(); iter != _state->_resourceMaps[type].end(); ++iter) {
+			gfxr_free_resource(iter->_value, type);
+			iter->_value = 0;
+		}
+	}
+}
+
+void GfxResManager::freeResManager() {
+	freeAllResources();
+	delete _state;
+}
+
+void GfxResManager::freeTaggedResources() {
+	// Current heuristics: free tagged views and old pics
+
+	IntResMap::iterator iter;
+	int type;
+	const int tmp = _state->tag_lock_counter;
+
+	type = GFX_RESOURCE_TYPE_VIEW;
+	for (iter = _state->_resourceMaps[type].begin(); iter != _state->_resourceMaps[type].end(); ++iter) {
+		gfx_resource_t *resource = iter->_value;
+
+		if (resource) {
+			if (resource->lock_sequence_nr < tmp) {
+				gfxr_free_resource(resource, type);
+				iter->_value = 0;
+			} else {
+				resource->lock_sequence_nr = 0;
+			}
+		}
+	}
+
+	type = GFX_RESOURCE_TYPE_PIC;
+	for (iter = _state->_resourceMaps[type].begin(); iter != _state->_resourceMaps[type].end(); ++iter) {
+		gfx_resource_t *resource = iter->_value;
+
+		if (resource) {
+			if (resource->lock_sequence_nr < 0) {
+				gfxr_free_resource(resource, type);
+				iter->_value = 0;
+			} else {
+				resource->lock_sequence_nr--;
+			}
+		}
+	}
+
+	_state->tag_lock_counter = 0;
+}
+
+#define XLATE_AS_APPROPRIATE(key, entry) \
+	if (maps & key) { \
+		if (res->unscaled_data.pic&& (force || !res->unscaled_data.pic->entry->data)) { \
+				if (key == GFX_MASK_VISUAL) \
+					gfx_get_res_config(options, res->unscaled_data.pic->entry); \
+			        gfx_xlate_pixmap(res->unscaled_data.pic->entry, mode, filter); \
+		} if (scaled && res->scaled_data.pic && (force || !res->scaled_data.pic->entry->data)) { \
+				if (key == GFX_MASK_VISUAL) \
+					gfx_get_res_config(options, res->scaled_data.pic->entry); \
+				gfx_xlate_pixmap(res->scaled_data.pic->entry, mode, filter); \
+		} \
+	}
+
+static gfxr_pic_t *gfxr_pic_xlate_common(gfx_resource_t *res, int maps, int scaled, int force, gfx_mode_t *mode,
+										 gfx_xlate_filter_t filter, int endianize, gfx_options_t *options) {
+	XLATE_AS_APPROPRIATE(GFX_MASK_VISUAL, visual_map);
+	XLATE_AS_APPROPRIATE(GFX_MASK_PRIORITY, priority_map);
+	XLATE_AS_APPROPRIATE(GFX_MASK_CONTROL, control_map);
+
+	if (endianize && (maps & GFX_MASK_VISUAL) && res->scaled_data.pic->visual_map)
+		gfxr_endianness_adjust(res->scaled_data.pic->visual_map, mode);
+
+	return scaled ? res->scaled_data.pic : res->unscaled_data.pic;
+}
+#undef XLATE_AS_APPROPRIATE
+
+gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_palette, bool scaled) {
+	gfxr_pic_t *npic = NULL;
+	IntResMap &resMap = _state->_resourceMaps[GFX_RESOURCE_TYPE_PIC];
+	gfx_resource_t *res = NULL;
+	int hash = getOptionsHash(GFX_RESOURCE_TYPE_PIC);
+	int must_post_process_pic = 0;
+	int need_unscaled = (_state->driver->mode->xfact != 1 || _state->driver->mode->yfact != 1);
+
+	hash |= (flags << 20) | ((default_palette & 0x7) << 28);
+
+	res = resMap.contains(num) ? resMap[num] : NULL;
+
+	if (!res || res->mode != hash) {
+		gfxr_pic_t *pic;
+		gfxr_pic_t *unscaled_pic = NULL;
+
+		if (_state->options->pic0_unscaled) {
+			need_unscaled = 0;
+			pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _state->version >= SCI_VERSION_01_VGA);
+		} else
+			pic = gfxr_init_pic(_state->driver->mode, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _state->version >= SCI_VERSION_01_VGA);
+		if (!pic) {
+			GFXERROR("Failed to allocate scaled pic!\n");
+			return NULL;
+		}
+
+		gfxr_clear_pic0(pic, SCI_TITLEBAR_SIZE);
+
+		if (need_unscaled) {
+			unscaled_pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _state->version >= SCI_VERSION_01_VGA);
+			if (!unscaled_pic) {
+				GFXERROR("Failed to allocate unscaled pic!\n");
+				return NULL;
+			}
+			gfxr_clear_pic0(pic, SCI_TITLEBAR_SIZE);
+		}
+		if (calculatePic(_state, pic, unscaled_pic, flags, default_palette, num)) {
+			gfxr_free_pic(pic);
+			if (unscaled_pic)
+				gfxr_free_pic(unscaled_pic);
+			return NULL;
+		}
+		if (!res) {
+			res = (gfx_resource_t *)sci_malloc(sizeof(gfx_resource_t));
+			res->ID = GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num);
+			res->lock_sequence_nr = _state->options->buffer_pics_nr;
+			resMap[num] = res;
+		} else {
+			gfxr_free_pic(res->scaled_data.pic);
+			if (res->unscaled_data.pic)
+				gfxr_free_pic(res->unscaled_data.pic);
+		}
+
+		res->mode = hash;
+		res->scaled_data.pic = pic;
+		res->unscaled_data.pic = unscaled_pic;
+	} else {
+		res->lock_sequence_nr = _state->options->buffer_pics_nr; // Update lock counter
+	}
+
+	must_post_process_pic = res->scaled_data.pic->visual_map->data == NULL;
+	// If the pic was only just drawn, we'll have to endianness-adjust it now
+
+	npic = gfxr_pic_xlate_common(res, maps, scaled || _state->options->pic0_unscaled, 0, _state->driver->mode,
+	                             _state->options->pic_xlate_filter, 0, _state->options);
+
+
+	if (must_post_process_pic) {
+		gfxr_endianness_adjust(npic->visual_map, _state->driver->mode);
+	}
+
+	return npic;
+}
+
+static void set_pic_id(gfx_resource_t *res, int id) {
+	if (res->scaled_data.pic) {
+		gfxr_pic_t *pic = res->scaled_data.pic;
+		pic->control_map->ID = id;
+		pic->priority_map->ID = id;
+		pic->visual_map->ID = id;
+	}
+
+	if (res->unscaled_data.pic) {
+		gfxr_pic_t *pic = res->unscaled_data.pic;
+		pic->control_map->ID = id;
+		pic->priority_map->ID = id;
+		pic->visual_map->ID = id;
+	}
+}
+
+static int get_pic_id(gfx_resource_t *res) {
+	if (res->scaled_data.pic)
+		return res->scaled_data.pic->visual_map->ID;
+	else
+		return res->unscaled_data.pic->visual_map->ID;
+}
+
+static void _gfxr_unscale_pixmap_index_data(gfx_pixmap_t *pxm, gfx_mode_t *mode) {
+	int xmod = mode->xfact; // Step size horizontally
+	int ymod = pxm->index_width * mode->yfact; // Vertical step size
+	int maxpos = pxm->index_width * pxm->index_height;
+	int pos;
+	byte *dest = pxm->index_data;
+
+	if (!(pxm->flags & GFX_PIXMAP_FLAG_SCALED_INDEX))
+		return; // It's not scaled!
+
+	for (pos = 0; pos < maxpos; pos += ymod) {
+		int c;
+
+		for (c = 0; c < pxm->index_width; c += xmod)
+			*dest++ = pxm->index_data[pos + c];
+			// No overwrite since line and offset readers move much faster (proof by in-duction, trivial
+			// and left to the reader)
+	}
+
+	pxm->index_width /= mode->xfact;
+	pxm->index_height /= mode->yfact;
+	pxm->flags &= ~GFX_PIXMAP_FLAG_SCALED_INDEX;
+}
+
+gfxr_pic_t *GfxResManager::addToPic(int old_nr, int new_nr, int flags, int old_default_palette, int default_palette) {
+	IntResMap &resMap = _state->_resourceMaps[GFX_RESOURCE_TYPE_PIC];
+	gfxr_pic_t *pic = NULL;
+	gfx_resource_t *res = NULL;
+	int hash = getOptionsHash(GFX_RESOURCE_TYPE_PIC);
+	int need_unscaled = !(_state->options->pic0_unscaled) && (_state->driver->mode->xfact != 1 || _state->driver->mode->yfact != 1);
+
+	res = resMap.contains(old_nr) ? resMap[old_nr] : NULL;
+
+	if (!res || (res->mode != MODE_INVALID && res->mode != hash)) {
+		// FIXME: the initialization of the GFX resource manager should
+		// be pushed up, and it shouldn't occur here
+		GfxResManager *_gfx = new GfxResManager(_state);
+		_gfx->getPic(old_nr, 0, flags, old_default_palette, 1);
+		delete _gfx;
+
+		res = resMap.contains(old_nr) ? resMap[old_nr] : NULL;
+
+		if (!res) {
+			GFXWARN("Attempt to add pic %d to non-existing pic %d\n", new_nr, old_nr);
+			return NULL;
+		}
+	}
+
+	if (_state->options->pic0_unscaled) // Unscale priority map, if we scaled it earlier
+		_gfxr_unscale_pixmap_index_data(res->scaled_data.pic->priority_map, _state->driver->mode);
+
+	// The following two operations are needed when returning scaled maps (which is always the case here)
+	res->lock_sequence_nr = _state->options->buffer_pics_nr;
+	calculatePic(_state, res->scaled_data.pic, need_unscaled ? res->unscaled_data.pic : NULL,
+		                               flags | DRAWPIC01_FLAG_OVERLAID_PIC, default_palette, new_nr);
+
+	res->mode = MODE_INVALID; // Invalidate
+
+	if (_state->options->pic0_unscaled) // Scale priority map again, if needed
+		res->scaled_data.pic->priority_map = gfx_pixmap_scale_index_data(res->scaled_data.pic->priority_map, _state->driver->mode);
+	{
+		int old_ID = get_pic_id(res);
+		set_pic_id(res, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, new_nr)); // To ensure that our graphical translation optoins work properly
+		pic = gfxr_pic_xlate_common(res, GFX_MASK_VISUAL, 1, 1, _state->driver->mode, _state->options->pic_xlate_filter, 1, _state->options);
+		set_pic_id(res, old_ID);
+	}
+
+	return pic;
+}
+
+gfxr_view_t *gfxr_draw_view11(int id, byte *resource, int size);
+
+gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) {
+	IntResMap &resMap = _state->_resourceMaps[GFX_RESOURCE_TYPE_VIEW];
+	gfx_resource_t *res = NULL;
+	int hash = palette;
+	gfxr_view_t *view = NULL;
+	gfxr_loop_t *loop_data = NULL;
+	gfx_pixmap_t *cel_data = NULL;
+
+	res = resMap.contains(nr) ? resMap[nr] : NULL;
+
+	if (!res || res->mode != hash) {
+		Resource *viewRes = _state->resManager->findResource(kResourceTypeView, nr, 0);
+		if (!viewRes || !viewRes->data)
+			return NULL;
+
+		int resid = GFXR_RES_ID(GFX_RESOURCE_TYPE_VIEW, nr);
+
+		if (_state->version < SCI_VERSION_01)
+			view = gfxr_draw_view0(resid, viewRes->data, viewRes->size, -1);
+		else if (_state->version == SCI_VERSION_01)
+			view = gfxr_draw_view0(resid, viewRes->data, viewRes->size, palette);
+		else if (_state->version >= SCI_VERSION_01_VGA && _state->version <= SCI_VERSION_1_LATE)
+			view = gfxr_draw_view1(resid, viewRes->data, viewRes->size, _state->static_palette);
+		else if (_state->version >= SCI_VERSION_1_1)
+			view = gfxr_draw_view11(resid, viewRes->data, viewRes->size);
+
+		if (_state->version >= SCI_VERSION_01_VGA) {
+			if (!view->palette) {
+				view->palette = new Palette(_state->static_palette->size());
+				view->palette->name = "interpreter_get_view";
+			}
+			
+			// Palettize view
+			for (unsigned i = 0; i < MIN(view->palette->size(), _state->static_palette->size()); i++) {
+				const PaletteEntry& vc = view->palette->getColor(i);
+				if (vc.r == 0 && vc.g == 0 && vc.b == 0) {
+					const PaletteEntry& sc = _state->static_palette->getColor(i);
+					view->palette->setColor(i, sc.r, sc.g, sc.b);
+				}
+			}
+
+		}
+
+		if (!res) {
+			res = (gfx_resource_t *)sci_malloc(sizeof(gfx_resource_t));
+			res->scaled_data.view = NULL;
+			res->ID = GFXR_RES_ID(GFX_RESOURCE_TYPE_VIEW, nr);
+			res->lock_sequence_nr = _state->tag_lock_counter;
+			res->mode = hash;
+			resMap[nr] = res;
+		} else {
+			gfxr_free_view(res->unscaled_data.view);
+		}
+
+		res->mode = hash;
+		res->unscaled_data.view = view;
+
+	} else {
+		res->lock_sequence_nr = _state->tag_lock_counter; // Update lock counter
+		view = res->unscaled_data.view;
+	}
+
+	*loop = CLIP<int>(*loop, 0, view->loops_nr - 1);
+
+	if (*loop < 0) {
+		GFXWARN("View %d has no loops\n", nr);
+		return NULL;
+	}
+
+	loop_data = view->loops + (*loop);
+	if (loop_data == NULL) {
+		GFXWARN("Trying to load invalid loop %d of view %d\n", *loop, nr);
+		return NULL;
+	}
+
+	*cel = CLIP<int>(*cel, 0, loop_data->cels_nr - 1);
+
+	if (*cel < 0) {
+		GFXWARN("View %d loop %d has no cels\n", nr, *loop);
+		return NULL;
+	}
+
+	cel_data = loop_data->cels[*cel];
+	if (loop_data == NULL) {
+		GFXWARN("Trying to load invalid view/loop/cel %d/%d/%d\n", nr, *loop, *cel);
+		return NULL;
+	}
+
+	if (!cel_data->data) {
+		gfx_get_res_config(_state->options, cel_data);
+		gfx_xlate_pixmap(cel_data, _state->driver->mode, _state->options->view_xlate_filter);
+		gfxr_endianness_adjust(cel_data, _state->driver->mode);
+	}
+
+	return view;
+}
+
+gfx_bitmap_font_t *GfxResManager::getFont(int num, bool scaled) {
+	IntResMap &resMap = _state->_resourceMaps[GFX_RESOURCE_TYPE_FONT];
+	gfx_resource_t *res = NULL;
+	int hash = getOptionsHash(GFX_RESOURCE_TYPE_FONT);
+
+	res = resMap.contains(num) ? resMap[num] : NULL;
+
+	if (!res || res->mode != hash) {
+		Resource *fontRes = _state->resManager->findResource(kResourceTypeFont, num, 0);
+		if (!fontRes || !fontRes->data)
+			return NULL;
+
+		gfx_bitmap_font_t *font = gfxr_read_font(fontRes->id, fontRes->data, fontRes->size);
+
+		if (!res) {
+			res = (gfx_resource_t *)sci_malloc(sizeof(gfx_resource_t));
+			res->scaled_data.font = NULL;
+			res->ID = GFXR_RES_ID(GFX_RESOURCE_TYPE_FONT, num);
+			res->lock_sequence_nr = _state->tag_lock_counter;
+			res->mode = hash;
+			resMap[num] = res;
+		} else {
+			gfxr_free_font(res->unscaled_data.font);
+		}
+
+		res->unscaled_data.font = font;
+
+		return font;
+	} else {
+		res->lock_sequence_nr = _state->tag_lock_counter; // Update lock counter
+		if (res->unscaled_data.pointer)
+			return res->unscaled_data.font;
+		else
+			return res->scaled_data.font;
+	}
+}
+
+gfx_pixmap_t *GfxResManager::getCursor(int num) {
+	IntResMap &resMap = _state->_resourceMaps[GFX_RESOURCE_TYPE_CURSOR];
+	gfx_resource_t *res = NULL;
+	int hash = getOptionsHash(GFX_RESOURCE_TYPE_CURSOR);
+
+	res = resMap.contains(num) ? resMap[num] : NULL;
+
+	if (!res || res->mode != hash) {
+		Resource *cursorRes = _state->resManager->findResource(kResourceTypeCursor, num, 0);
+		if (!cursorRes || !cursorRes->data)
+			return NULL;
+
+		if (_state->version >= SCI_VERSION_1_1) {
+			GFXWARN("Attempt to retrieve cursor in SCI1.1 or later\n");
+			return NULL;
+		}
+
+		gfx_pixmap_t *cursor = gfxr_draw_cursor(GFXR_RES_ID(GFX_RESOURCE_TYPE_CURSOR, num), 
+										cursorRes->data, cursorRes->size, _state->version != SCI_VERSION_0);
+
+		if (!cursor)
+			return NULL;
+
+		if (!res) {
+			res = (gfx_resource_t *)sci_malloc(sizeof(gfx_resource_t));
+			res->scaled_data.pointer = NULL;
+			res->ID = GFXR_RES_ID(GFX_RESOURCE_TYPE_CURSOR, num);
+			res->lock_sequence_nr = _state->tag_lock_counter;
+			res->mode = hash;
+			resMap[num] = res;
+		} else {
+			gfx_free_pixmap(res->unscaled_data.pointer);
+		}
+		gfx_get_res_config(_state->options, cursor);
+		gfx_xlate_pixmap(cursor, _state->driver->mode, _state->options->cursor_xlate_filter);
+		gfxr_endianness_adjust(cursor, _state->driver->mode);
+
+		res->unscaled_data.pointer = cursor;
+
+		return cursor;
+	} else {
+		res->lock_sequence_nr = _state->tag_lock_counter; // Update lock counter
+		return res->unscaled_data.pointer;
+	}
+}
+
+} // End of namespace Sci


Property changes on: scummvm/trunk/engines/sci/gfx/gfx_resmgr.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:mergeinfo
   + 
Added: svn:eol-style
   + native

Copied: scummvm/trunk/engines/sci/gfx/picfill.cpp (from rev 39505, scummvm/trunk/engines/sci/gfx/resource/picfill.cpp)
===================================================================
--- scummvm/trunk/engines/sci/gfx/picfill.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/picfill.cpp	2009-03-18 13:24:47 UTC (rev 39515)
@@ -0,0 +1,600 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/gfx/gfx_resource.h"
+
+/* Generic pic filling code, to be included by sci_pic_0.c
+ *
+ *
+ * To use, define the following:
+ *    AUXBUF_FILL: Name of the exported floodfill function
+ *    AUXBUF_FILL_HELPER: Name of the helper function
+ *    FILL_FUNCTION: Name of the exported floodfill function
+ *    FILL_FUNCTION_RECURSIVE: Name of the helper function 
+ *
+ * Define DRAW_SCALED to support scaled drawing, or leave it out for faster
+ * processing.
+ *
+ */
+ 
+namespace Sci {
+
+#define CLIPMASK_HARD_BOUND 0x80 /* ensures that we don't re-fill filled stuff */
+
+static void AUXBUF_FILL_HELPER(gfxr_pic_t *pic, int old_xl, int old_xr, int y, int dy,
+	int clipmask, int control, int sci_titlebar_size) {
+	int xl, xr;
+	int oldytotal = y * 320;
+#ifdef DRAW_SCALED
+	unsigned const char fillmask = CLIPMASK_HARD_BOUND | 0x78;
+#else
+	unsigned const char fillmask = CLIPMASK_HARD_BOUND | 0x84;
+#endif
+
+	do {
+		int ytotal = oldytotal + (320 * dy);
+		int xcont;
+		int state;
+
+		y += dy;
+
+		if (y < sci_titlebar_size || y > 199)
+			return;
+
+		xl = old_xl;
+		if (!(pic->aux_map[ytotal + xl] & clipmask)) { // go left
+			while (xl && !(pic->aux_map[ytotal + xl - 1] & clipmask))
+				--xl;
+		} else // go right and look for the first valid spot
+			while ((xl <= old_xr) && (pic->aux_map[ytotal + xl] & clipmask))
+				++xl;
+
+		if (xl > old_xr) // No fillable strip above the last one
+			return;
+
+		if ((ytotal + xl) < 0) {
+			fprintf(stderr, "AARGH-%d\n", __LINE__);
+			BREAKPOINT();
+		}
+
+		xr = xl;
+		while (xr < 320 && !(pic->aux_map[ytotal + xr] & clipmask)) {
+			pic->aux_map[ytotal + xr] |= fillmask;
+			++xr;
+		}
+
+		if ((ytotal + xr) > 64000) {
+			fprintf(stderr, "AARGH-%d\n", __LINE__);
+			BREAKPOINT();
+		}
+
+		--xr;
+
+		if (xr < xl)
+			return;
+
+		// Check whether we need to recurse on branches in the same direction
+		if ((y > sci_titlebar_size && dy < 0) || (y < 199 && dy > 0)) {
+			state = 0;
+			xcont = xr + 1;
+			while (xcont <= old_xr) {
+				if (pic->aux_map[ytotal + xcont] & clipmask)
+					state = 0;
+				else if (!state) { // recurse
+					state = 1;
+					AUXBUF_FILL_HELPER(pic, xcont, old_xr, y - dy, dy, clipmask, control, sci_titlebar_size);
+				}
+				++xcont;
+			}
+		}
+
+		// Check whether we need to recurse on backward branches:
+		// left
+		if (xl < old_xl - 1) {
+			state = 0;
+			for (xcont = old_xl - 1; xcont >= xl; xcont--) {
+				if (pic->aux_map[oldytotal + xcont] & clipmask)
+					state = xcont;
+				else if (state) { // recurse
+					AUXBUF_FILL_HELPER(pic, xcont, state, y, -dy, clipmask, control, sci_titlebar_size);
+					state = 0;
+				}
+			}
+		}
+
+		// right
+		if (xr > old_xr + 1) {
+			state = 0;
+			for (xcont = old_xr + 1; xcont <= xr; xcont++) {
+				if (pic->aux_map[oldytotal + xcont] & clipmask)
+					state = xcont;
+				else if (state) { // recurse
+					AUXBUF_FILL_HELPER(pic, state, xcont, y, -dy, clipmask, control, sci_titlebar_size);
+					state = 0;
+				}
+			}
+		}
+
+		if ((ytotal + xl) < 0) {
+			fprintf(stderr, "AARGH-%d\n", __LINE__);
+			BREAKPOINT()
+		}
+		if ((ytotal + xr + 1) > 64000) {
+			fprintf(stderr, "AARGH-%d\n", __LINE__);
+			BREAKPOINT();
+		}
+
+		if (control)
+			memset(pic->control_map->index_data + ytotal + xl, control, xr - xl + 1);
+
+		oldytotal = ytotal;
+		old_xr = xr;
+		old_xl = xl;
+
+	} while (1);
+}
+
+
+static void AUXBUF_FILL(gfxr_pic_t *pic, int x, int y, int clipmask, int control, int sci_titlebar_size) {
+	// Fills the aux buffer and the control map (if control != 0)
+	int xl, xr;
+	int ytotal = y * 320;
+#ifdef DRAW_SCALED
+	unsigned const char fillmask = 0x78;
+#else
+	unsigned const char fillmask = 0x4;
+#endif
+
+#ifndef DRAW_SCALED
+	if (!control || !(clipmask & 4))
+		return; // Without pic scaling, we only do this to fill the control map
+#endif
+
+	if (clipmask & 1)
+		clipmask = 1; // vis
+	else if (clipmask & 2)
+		clipmask = 2; // pri
+	else if (clipmask & 4)
+		clipmask = 4; // ctl
+	else return;
+
+#ifdef DRAW_SCALED
+	clipmask |= fillmask; // Bits 3-5
+#endif
+
+	if (pic->aux_map[ytotal + x] & clipmask)
+		return;
+
+	pic->aux_map[ytotal + x] |= fillmask;
+
+	xl = x;
+	while (xl && !(pic->aux_map[ytotal + xl - 1] & clipmask)) {
+		--xl;
+		pic->aux_map[ytotal + xl] |= fillmask;
+	}
+
+	xr = x;
+	while ((xr < 319) && !(pic->aux_map[ytotal + xr + 1] & clipmask)) {
+		++xr;
+		pic->aux_map[ytotal + xr] |= fillmask;
+	}
+
+	clipmask |= CLIPMASK_HARD_BOUND; // Guarantee clipping
+
+	if (control) // Draw the same strip on the control map
+		memset(pic->control_map->index_data + ytotal + xl, control, xr - xl + 1);
+
+	if (y > sci_titlebar_size)
+		AUXBUF_FILL_HELPER(pic, xl, xr, y, -1, clipmask, control, sci_titlebar_size);
+
+	if (y < 199)
+		AUXBUF_FILL_HELPER(pic, xl, xr, y, + 1, clipmask, control, sci_titlebar_size);
+}
+
+
+#undef CLIPMASK_HARD_BOUND
+
+
+#ifdef FILL_RECURSIVE_DEBUG
+#  define PRINT_DEBUG0(s) if (!fillmagc) fprintf(stderr, s)
+#  define PRINT_DEBUG1(s,p1) if (!fillmagc) fprintf(stderr, s, p1)
+#  define PRINT_DEBUG4(s,p1,p2,p3,p4) if (!fillmagc) fprintf(stderr, s, p1)
+#else
+#  define PRINT_DEBUG0(s)
+#  define PRINT_DEBUG1(s,p1)
+#  define PRINT_DEBUG4(s,p1,p2,p3,p4)
+#endif
+
+#ifdef DRAW_SCALED
+#  define SCALED_CHECK(x) (x)
+#  define IS_BOUNDARY(x, y, index)  (((index) & legalmask) != legalcolor)
+#else
+#  define SCALED_CHECK(x) 1
+#  define IS_BOUNDARY(x, y, index) (								\
+	(((x)+(y)) & 1)? /* figure out which part of the mask to use, to simulate dithering */	\
+	   ((((index)) & ((legalmask) )) != ((legalcolor) & ((legalmask)))) /* odd coordinate */			\
+	 : ((((index)) & ((legalmask) >> 8)) != ((legalcolor) & ((legalmask) >> 8))) /* even coordinate */			\
+	)
+#endif
+
+static void FILL_FUNCTION_RECURSIVE(gfxr_pic_t *pic, int old_xl, int old_xr, int y, int dy, byte *bounds,
+	int legalcolor, int legalmask, int color, int priority, int drawenable, int sci_titlebar_size) {
+	int linewidth = pic->mode->xfact * 320;
+	int miny = pic->mode->yfact * sci_titlebar_size;
+	int maxy = pic->mode->yfact * 200;
+	int xl, xr;
+	int oldytotal = y * linewidth;
+#ifdef DRAW_SCALED
+	int old_proj_y = -42;
+	int proj_y;
+	int proj_ytotal;
+	int proj_x;
+	int proj_xl_bound = 0;
+	int proj_xr_bound = 0;
+#endif
+
+	do {
+		int ytotal = oldytotal + (linewidth * dy);
+		int xcont;
+		int state;
+
+		y += dy;
+
+#ifdef FILL_RECURSIVE_DEBUG
+		if (!fillc)
+			return;
+		else if (!fillmagc) {
+			--fillc;
+		}
+#endif
+
+		if (y < miny || y >= maxy) {
+			PRINT_DEBUG0("ABRT on failed initial assertion!\n");
+			return;
+		}
+#ifdef DRAW_SCALED
+		proj_y = y / pic->mode->yfact;
+
+		if (proj_y != old_proj_y) {
+			// First, find the projected coordinates, unless known already:
+			proj_ytotal = proj_y * 320;
+			proj_x = old_xl / pic->mode->xfact;
+
+			proj_xl_bound = proj_x;
+			if (SCALED_CHECK(pic->aux_map[proj_ytotal + proj_xl_bound] & FRESH_PAINT)) {
+				while (proj_xl_bound && pic->aux_map[proj_ytotal + proj_xl_bound - 1] & FRESH_PAINT)
+					--proj_xl_bound;
+			} else {
+				while (proj_xl_bound < 319 && !(pic->aux_map[proj_ytotal + proj_xl_bound + 1] & FRESH_PAINT))
+					++proj_xl_bound;
+
+				if (proj_xl_bound < 319)
+					++proj_xl_bound;
+			}
+
+			if (proj_xl_bound == 319
+			        && !(pic->aux_map[proj_ytotal + proj_xl_bound] & FRESH_PAINT)) {
+				PRINT_DEBUG0("ABRT because proj_xl_bound couldn't be found\n");
+				return;
+			}
+
+			proj_xr_bound = (proj_xl_bound > proj_x) ? proj_xl_bound : proj_x;
+			while ((proj_xr_bound < 319)
+			        && pic->aux_map[proj_ytotal + proj_xr_bound + 1] & FRESH_PAINT)
+				++proj_xr_bound;
+
+#ifdef FILL_RECURSIVE_DEBUG
+			if (!fillmagc) {
+				fprintf(stderr, "l%d: {%d,%d} | ", proj_y, proj_xl_bound, proj_xr_bound);
+				pic->aux_map[proj_y*320 + proj_xl_bound] |= 0x2;
+				pic->aux_map[proj_y*320 + proj_xr_bound] |= 0x2;
+			}
+#endif
+
+			proj_xl_bound *= pic->mode->xfact;
+			if (proj_xl_bound)
+				proj_xl_bound -= pic->mode->xfact - 1;
+
+			if (proj_xr_bound < 319)
+				++proj_xr_bound;
+			proj_xr_bound *= pic->mode->xfact;
+			proj_xr_bound += pic->mode->xfact - 1;
+
+			old_proj_y = proj_y;
+		}
+#else
+#  define proj_xl_bound 0
+#  define proj_xr_bound 319
+#endif
+
+		// Now we have the projected limits, get the real ones:
+
+		xl = (old_xl > proj_xl_bound) ? old_xl : proj_xl_bound;
+		if (!IS_BOUNDARY(xl, y + 1, bounds[ytotal + xl])) { // go left as far as possible
+			while (xl > proj_xl_bound && (!IS_BOUNDARY(xl - 1, y + 1, bounds[ytotal + xl - 1])))
+				--xl;
+		} else // go right until the fillable area starts
+			while (xl < proj_xr_bound && (IS_BOUNDARY(xl, y + 1, bounds[ytotal + xl])))
+				++xl;
+
+
+		PRINT_DEBUG1("<%d,", xl);
+
+		if ((xl > proj_xr_bound)
+		        || (xl > old_xr)) {
+			PRINT_DEBUG0("ABRT because xl > xr_bound\n");
+			return;
+		}
+
+		xr = (xl > old_xl) ? xl : old_xl;
+		while (xr < proj_xr_bound && (!IS_BOUNDARY(xr + 1, y + 1, bounds[ytotal + xr + 1])))
+			++xr;
+
+		PRINT_DEBUG1("%d> -> ", xr);
+
+		if (IS_BOUNDARY(xl, y + 1,  bounds[ytotal + xl])) {
+			PRINT_DEBUG0("ABRT because xl illegal\n");
+			return;
+		}
+
+#ifdef DRAW_SCALED
+		PRINT_DEBUG4("[%d[%d,%d]%d]\n", proj_xl_bound, xl, xr, proj_xr_bound);
+
+		if (xl < proj_xl_bound && xr - 3*pic->mode->xfact < proj_xl_bound) {
+			PRINT_DEBUG0("ABRT interval left of zone\n");
+			return;
+		}
+
+		if (xr > proj_xr_bound && xl + 3*pic->mode->xfact > proj_xr_bound) {
+			PRINT_DEBUG0("ABRT because interval right of zone\n");
+			return;
+		}
+#endif
+
+		if (drawenable & GFX_MASK_VISUAL)
+			memset(pic->visual_map->index_data + ytotal + xl, color, xr - xl + 1);
+
+		if (drawenable & GFX_MASK_PRIORITY)
+			memset(pic->priority_map->index_data + ytotal + xl, priority, xr - xl + 1);
+
+
+		// Check whether we need to recurse on branches in the same direction
+		state = 0;
+		xcont = xr + 1;
+		while (xcont <= old_xr) {
+			if (IS_BOUNDARY(xcont, y + 1, bounds[ytotal + xcont]))
+				state = xcont;
+			else if (state) { // recurse
+				PRINT_DEBUG4("[%d[%d,%d],%d]: ", old_xl, xl, xr, old_xr);
+				PRINT_DEBUG4("rec BRANCH %d [%d,%d] l%d\n", dy, state, xcont, y - dy);
+
+				FILL_FUNCTION_RECURSIVE(pic, state, xcont, y - dy, dy, bounds, legalcolor,
+				                        legalmask, color, priority, drawenable, sci_titlebar_size);
+				state = 0;
+			}
+			++xcont;
+		}
+
+		// Check whether we need to recurse on backward branches:
+		// left
+		if (xl < old_xl - 1) {
+			state = 0;
+			for (xcont = old_xl - 1; xcont >= xl; xcont--) {
+				if (IS_BOUNDARY(xcont, y, bounds[oldytotal + xcont]))
+					state = xcont;
+				else if (state) { // recurse
+					PRINT_DEBUG4("[%d[%d,%d],%d]: ", old_xl, xl, xr, old_xr);
+					PRINT_DEBUG4("rec BACK-LEFT %d [%d,%d] l%d\n", -dy, state, xcont, y);
+
+					FILL_FUNCTION_RECURSIVE(pic, xcont, state, y, -dy, bounds,
+					                        legalcolor, legalmask, color, priority, drawenable,
+					                        sci_titlebar_size);
+					state = 0;
+				}
+			}
+		}
+
+		// right
+		if (xr > old_xr + 1) {
+			state = 0;
+			for (xcont = old_xr + 1; xcont <= xr; xcont++) {
+				if (IS_BOUNDARY(xcont, y, bounds[oldytotal + xcont]))
+					state = xcont;
+				else if (state) { // recurse
+					PRINT_DEBUG4("[%d[%d,%d],%d]: ", old_xl, xl, xr, old_xr);
+					PRINT_DEBUG4("rec BACK-RIGHT %d [%d,%d] l%d\n", -dy, state, xcont, y);
+
+					FILL_FUNCTION_RECURSIVE(pic, state, xcont, y, -dy, bounds,
+					                        legalcolor, legalmask, color, priority, drawenable,
+					                        sci_titlebar_size);
+					state = 0;
+				}
+			}
+		}
+
+		oldytotal = ytotal;
+		old_xl = xl;
+		old_xr = xr;
+
+	} while (1);
+}
+
+
+static void FILL_FUNCTION(gfxr_pic_t *pic, int x_320, int y_200, int color, int priority, int control, int drawenable,
+	int sci_titlebar_size) {
+	int linewidth = pic->mode->xfact * 320;
+	int x, y;
+	int xl, xr;
+	int ytotal;
+	int bitmask;
+	byte *bounds = NULL;
+	int legalcolor, legalmask;
+#ifdef DRAW_SCALED
+	int min_x, min_y, max_x, max_y;
+#endif
+	int original_drawenable = drawenable; // Backup, since we need the unmodified value
+					      // for filling the aux and control map
+
+	// Restrict drawenable not to restrict itself to zero
+	if (pic->control_map->index_data[y_200 * 320 + x_320] != 0)
+		drawenable &= ~GFX_MASK_CONTROL;
+
+	if (color == 0xff)
+		drawenable &= ~GFX_MASK_VISUAL;
+
+	if (priority == 0) {
+		drawenable &= ~GFX_MASK_PRIORITY;
+		original_drawenable &= ~GFX_MASK_PRIORITY;
+	}
+
+	AUXBUF_FILL(pic, x_320, y_200, original_drawenable, (drawenable & GFX_MASK_CONTROL) ? control : 0,
+	            sci_titlebar_size);
+
+#ifdef DRAW_SCALED
+	_gfxr_auxbuf_spread(pic, &min_x, &min_y, &max_x, &max_y);
+
+	if (_gfxr_find_fill_point(pic, min_x, min_y, max_x, max_y, x_320, y_200, color, drawenable, &x, &y)) {
+		//GFXWARN("Could not find scaled fill point, but unscaled fill point was available!\n");
+		drawenable &= GFX_MASK_PRIORITY;
+		if (!drawenable)
+			_gfxr_auxbuf_propagate_changes(pic, 0);
+	}
+#else
+	x = x_320;
+	y = y_200;
+#endif
+
+	ytotal = y * linewidth;
+
+	if (!drawenable)
+		return;
+
+	if (drawenable & GFX_MASK_VISUAL) {
+		bounds = pic->visual_map->index_data;
+#if 0
+		// Code disabled, as removing it fixes qg1 pic.095 (unscaled). However,
+		// it MAY be of relevance to scaled pic drawing...
+
+		if ((color & 0xf) == 0xf // When dithering with white, do more
+					 // conservative checks
+		        || (color & 0xf0) == 0xf0)
+			legalcolor = 0xff;
+		else
+			legalcolor = 0xf0; // Only check the second color
+#endif
+#ifdef DRAW_SCALED
+		legalcolor = 0xff;
+		legalmask = legalcolor;
+#else
+		legalmask = 0x0ff0;
+		legalcolor = 0xff;
+#endif
+	} else if (drawenable & GFX_MASK_PRIORITY) {
+		bounds = pic->priority_map->index_data;
+		legalcolor = 0;
+		legalmask = 0x0f0f;
+	} else {
+		legalcolor = 0;
+		legalmask = 0x0f0f;
+	}
+
+	if (!bounds || IS_BOUNDARY(x, y, bounds[ytotal + x]))
+		return;
+
+	if (bounds) {
+#ifdef DRAW_SCALED
+		int proj_y = y_200;
+		int proj_ytotal = proj_y * 320;
+		int proj_x = x_320;
+		int proj_xl_bound;
+		int proj_xr_bound;
+		int proj_xl, proj_xr;
+
+		ytotal = y * linewidth;
+
+		proj_xl_bound = proj_x;
+		if (SCALED_CHECK(pic->aux_map[proj_ytotal + proj_xl_bound] & FRESH_PAINT)) {
+			while (proj_xl_bound && SCALED_CHECK(pic->aux_map[proj_ytotal + proj_xl_bound - 1] & FRESH_PAINT))
+				--proj_xl_bound;
+		} else
+			while (proj_xl_bound < 319 && SCALED_CHECK(!(pic->aux_map[proj_ytotal + proj_xl_bound + 1] & FRESH_PAINT)))
+				++proj_xl_bound;
+
+		proj_xr_bound = (proj_xl_bound > proj_x) ? proj_xl_bound : proj_x;
+		while ((proj_xr_bound < 319) && SCALED_CHECK(pic->aux_map[proj_ytotal + proj_xr_bound + 1] & FRESH_PAINT))
+			++proj_xr_bound;
+
+		proj_xl = proj_xl_bound;
+		proj_xr = proj_xr_bound;
+
+		proj_xl_bound *= pic->mode->xfact;
+		if (proj_xl_bound)
+			proj_xl_bound -= pic->mode->xfact - 1;
+
+		if (proj_xr_bound < 319)
+			++proj_xr_bound;
+		proj_xr_bound *= pic->mode->xfact;
+		proj_xr_bound += pic->mode->xfact - 1;
+#endif
+		xl = x;
+		while (xl > proj_xl_bound && (!IS_BOUNDARY(xl - 1, y, bounds[ytotal + xl -1])))
+			--xl;
+
+		while (x < proj_xr_bound && (!IS_BOUNDARY(x + 1, y, bounds[ytotal + x + 1])))
+			++x;
+		xr = x;
+
+		if (drawenable & GFX_MASK_VISUAL)
+			memset(pic->visual_map->index_data + ytotal + xl, color, xr - xl + 1);
+
+		if (drawenable & GFX_MASK_PRIORITY)
+			memset(pic->priority_map->index_data + ytotal + xl, priority, xr - xl + 1);
+
+		FILL_FUNCTION_RECURSIVE(pic, xl, xr, y, -1, bounds, legalcolor, legalmask, color, priority, drawenable,
+		                        sci_titlebar_size);
+		FILL_FUNCTION_RECURSIVE(pic, xl, xr, y, + 1, bounds, legalcolor, legalmask, color, priority, drawenable,
+		                        sci_titlebar_size);
+	}
+
+	// Now finish the aux buffer
+	bitmask = drawenable & (((color != 0xff) ? 1 : 0) | ((priority) ? 2 : 0) | ((control) ? 4 : 0));
+
+#ifdef DRAW_SCALED
+#  ifdef FILL_RECURSIVE_DEBUG
+	if (fillmagc)
+#  endif
+		_gfxr_auxbuf_propagate_changes(pic, bitmask);
+#endif
+}
+
+#undef SCALED_CHECK
+#undef IS_BOUNDARY
+
+#ifndef DRAW_SCALED
+#  undef proj_xl_bound
+#  undef proj_xr_bound
+#endif
+
+} // End of namespace Sci

Copied: scummvm/trunk/engines/sci/gfx/res_cursor.cpp (from rev 39505, scummvm/trunk/engines/sci/gfx/resource/res_cursor.cpp)
===================================================================
--- scummvm/trunk/engines/sci/gfx/res_cursor.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/res_cursor.cpp	2009-03-18 13:24:47 UTC (rev 39515)
@@ -0,0 +1,92 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* SCI cursor functions */
+
+#include "sci/gfx/gfx_system.h"
+#include "sci/gfx/gfx_resource.h"
+#include "sci/gfx/gfx_tools.h"
+
+namespace Sci {
+
+#define CURSOR_RESOURCE_SIZE 68
+#define CURSOR_SIZE 16
+
+#define GFX_SCI01_CURSOR_COLORS_NR 3
+#define GFX_SCI0_CURSOR_COLORS_NR 2
+
+#define GFX_CURSOR_TRANSPARENT 255
+
+gfx_pixmap_color_t gfx_sci01_cursor_colors[GFX_SCI01_CURSOR_COLORS_NR] = {
+	{GFX_COLOR_INDEX_UNMAPPED, 0x00, 0x00, 0x00},
+	{GFX_COLOR_INDEX_UNMAPPED, 0xff, 0xff, 0xff},
+	{GFX_COLOR_INDEX_UNMAPPED, 0xaa, 0xaa, 0xaa}
+};
+
+gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, bool isSci01) {
+	int colors[4] = {0, 1, GFX_CURSOR_TRANSPARENT, 1};
+	int line;
+	byte *data;
+	gfx_pixmap_t *retval;
+
+	if (isSci01)
+		colors[3] = 2;
+
+	if (size != CURSOR_RESOURCE_SIZE) {
+		GFXERROR("Expected resource size of %d, but found %d\n", CURSOR_RESOURCE_SIZE, size);
+		return NULL;
+	}
+
+	retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(CURSOR_SIZE, CURSOR_SIZE, id, 0, 0));
+	// FIXME: don't copy palette
+ 	retval->palette = new Palette(gfx_sci01_cursor_colors, isSci01 ? GFX_SCI01_CURSOR_COLORS_NR : GFX_SCI0_CURSOR_COLORS_NR);
+ 	retval->palette->name = "cursor"; 
+	retval->color_key = GFX_CURSOR_TRANSPARENT;
+
+	if (isSci01) {
+		retval->xoffset = READ_LE_UINT16(resource);
+		retval->yoffset = READ_LE_UINT16(resource + 2);
+	} else if (resource[3]) // center
+		retval->xoffset = retval->yoffset = CURSOR_SIZE / 2;
+	else
+		retval->xoffset = retval->yoffset = 0;
+
+	resource += 4;
+
+	data = retval->index_data;
+	for (line = 0; line < 16; line++) {
+		int mask_a = READ_LE_UINT16(resource + (line << 1));
+		int mask_b = READ_LE_UINT16(resource + 32 + (line << 1));
+		int i;
+
+		for (i = 0; i < 16; i++) {
+			int color_code = ((mask_a << i) & 0x8000) | (((mask_b << i) >> 1) & 0x4000);
+			*data++ = colors[color_code >> 14];
+		}
+	}
+	return retval;
+}
+
+} // End of namespace Sci


Property changes on: scummvm/trunk/engines/sci/gfx/res_cursor.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:mergeinfo
   + 
Added: svn:eol-style
   + native

Copied: scummvm/trunk/engines/sci/gfx/res_font.cpp (from rev 39505, scummvm/trunk/engines/sci/gfx/resource/res_font.cpp)
===================================================================
--- scummvm/trunk/engines/sci/gfx/res_font.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/res_font.cpp	2009-03-18 13:24:47 UTC (rev 39515)
@@ -0,0 +1,143 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci_memory.h"
+#include "sci/gfx/gfx_system.h"
+#include "sci/gfx/gfx_resource.h"
+#include "sci/gfx/gfx_tools.h"
+#include "sci/gfx/font.h"
+
+namespace Sci {
+
+extern int font_counter;
+
+#define FONT_HEIGHT_OFFSET 4
+#define FONT_MAXCHAR_OFFSET 2
+
+static int calc_char(byte *dest, int total_width, int total_height, byte *src, int size) {
+	int width = src[0];
+	int height = src[1];
+	int byte_width = (width + 7) >> 3;
+	int y;
+
+	src += 2;
+
+	if ((width >> 3) > total_width || height > total_height) {
+		GFXERROR("Weird character: width=%d/%d, height=%d/%d\n", width, total_width, height, total_height);
+		return GFX_ERROR;
+	}
+
+	if (byte_width * height + 2 > size) {
+		GFXERROR("Character extends to %d of %d allowed bytes\n", byte_width * height + 2, size);
+		return GFX_ERROR;
+	}
+
+	for (y = 0; y < height; y++) {
+		memcpy(dest, src, byte_width);
+		src += byte_width;
+		dest += total_width;
+	}
+
+	return GFX_OK;
+}
+
+gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size) {
+	gfx_bitmap_font_t *font = (gfx_bitmap_font_t*)sci_calloc(sizeof(gfx_bitmap_font_t), 1);
+	int chars_nr;
+	int max_width = 0, max_height;
+	int i;
+
+	++font_counter;
+
+	if (size < 6) {
+		GFXERROR("Font %04x size is %d- this is a joke, right?\n", id, size);
+		gfxr_free_font(font);
+		return NULL;
+	}
+
+	font->chars_nr = chars_nr = READ_LE_UINT16(resource + FONT_MAXCHAR_OFFSET);
+	font->line_height = max_height = READ_LE_UINT16(resource + FONT_HEIGHT_OFFSET);
+
+	if (chars_nr < 0 || chars_nr > 256 || max_height < 0) {
+		if (chars_nr < 0 || chars_nr > 256)
+			GFXERROR("Font %04x: Invalid number of characters: %d\n", id, chars_nr);
+		if (max_height < 0)
+			GFXERROR("Font %04x: Invalid font height: %d\n", id, max_height);
+		gfxr_free_font(font);
+		return NULL;
+	}
+
+	if (size < 6 + chars_nr * 2) {
+		GFXERROR("Font %04x: Insufficient space for %d characters in font\n", id, chars_nr);
+		gfxr_free_font(font);
+		return NULL;
+	}
+
+	font->ID = id;
+	font->widths = (int*)sci_malloc(sizeof(int) * chars_nr);
+
+	for (i = 0; i < chars_nr; i++) {
+		int offset = READ_LE_UINT16(resource + (i << 1) + 6);
+
+		if (offset >= size) {
+			GFXERROR("Font %04x: Error: Character 0x%02x is at offset 0x%04x (beyond 0x%04x)\n", id, i, offset, size);
+			gfxr_free_font(font);
+			return NULL;
+		}
+
+		if ((resource[offset]) > max_width)
+			max_width = resource[offset];
+		if ((resource[offset + 1]) > max_height)
+			max_height = resource[offset + 1];
+
+		font->widths[i] = resource[offset];
+	}
+
+	font->height = max_height;
+	font->row_size = (max_width + 7) >> 3;
+
+	if (font->row_size == 3)
+		font->row_size = 4;
+
+	if (font->row_size > 4)
+		font->row_size = (font->row_size + 3) & ~3;
+
+	font->char_size = font->row_size * max_height;
+	font->data = (byte *)sci_calloc(font->char_size, chars_nr);
+
+	for (i = 0; i < chars_nr; i++) {
+		int offset = READ_LE_UINT16(resource + (i << 1) + 6);
+
+		if (calc_char(font->data + (font->char_size * i), font->row_size, max_height, resource + offset, size - offset)) {
+			GFXERROR("Problem occured in font %04x, char %d/%d\n", id, i, chars_nr);
+			gfxr_free_font(font);
+			return NULL;
+		}
+	}
+
+	return font;
+}
+
+} // End of namespace Sci

Copied: scummvm/trunk/engines/sci/gfx/res_pal.cpp (from rev 39505, scummvm/trunk/engines/sci/gfx/resource/res_pal.cpp)
===================================================================
--- scummvm/trunk/engines/sci/gfx/res_pal.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/res_pal.cpp	2009-03-18 13:24:47 UTC (rev 39515)
@@ -0,0 +1,147 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/* SCI1 palette resource defrobnicator */
+
+#include "common/file.h"
+#include "sci/sci_memory.h"
+#include "sci/gfx/gfx_system.h"
+#include "sci/gfx/gfx_resource.h"
+
+namespace Sci {
+
+#define MAX_COLORS 256
+#define PALETTE_START 260
+#define COLOR_OK 0x01
+
+#define SCI_PAL_FORMAT_VARIABLE_FLAGS 0
+#define SCI_PAL_FORMAT_CONSTANT_FLAGS 1
+
+Palette *gfxr_read_pal11(int id, byte *resource, int size) {
+	int start_color = resource[25];
+	int format = resource[32];
+	int entry_size = 0;
+	Palette *retval;
+	byte *pal_data = resource + 37;
+	int _colors_nr = READ_LE_UINT16(resource + 29);
+	int i;
+
+	switch (format) {
+	case SCI_PAL_FORMAT_VARIABLE_FLAGS :
+		entry_size = 4;
+		break;
+	case SCI_PAL_FORMAT_CONSTANT_FLAGS :
+		entry_size = 3;
+		break;
+	}
+
+	retval = new Palette(_colors_nr + start_color);
+	char buf[100];
+	sprintf(buf, "read_pal11 (id %d)", id);
+	retval->name = buf;
+
+	for (i = 0; i < start_color; i ++) {
+		retval->setColor(i, 0, 0, 0);
+	}
+	for (i = start_color; i < start_color + _colors_nr; i ++) {
+		switch (format) {
+		case SCI_PAL_FORMAT_CONSTANT_FLAGS:
+			retval->setColor(i, pal_data[0], pal_data[1], pal_data[2]);
+			break;
+		case SCI_PAL_FORMAT_VARIABLE_FLAGS:
+			retval->setColor(i, pal_data[1], pal_data[2], pal_data[3]);
+			break;
+		}
+		pal_data += entry_size;
+	}
+
+	return retval;
+}
+
+Palette *gfxr_read_pal1(int id, byte *resource, int size) {
+	int counter = 0;
+	int pos;
+	unsigned int colors[MAX_COLORS] = {0};
+
+	if (size < PALETTE_START + 4) {
+		GFXERROR("Palette resource too small in %04x\n", id);
+		return NULL;
+	}
+
+	pos = PALETTE_START;
+
+	while (pos < size/* && resource[pos] == COLOR_OK && counter < MAX_COLORS*/) {
+		int color = resource[pos] | (resource[pos + 1] << 8) | (resource[pos + 2] << 16) | (resource[pos + 3] << 24);
+
+		pos += 4;
+
+		colors[counter++] = color;
+	}
+
+	if (counter < MAX_COLORS && resource[pos] != COLOR_OK) {
+		GFXERROR("Palette %04x uses unknown palette color prefix 0x%02x at offset 0x%04x\n", id, resource[pos], pos);
+		return NULL;
+	}
+
+	if (counter < MAX_COLORS) {
+		GFXERROR("Palette %04x ends prematurely\n", id);
+		return NULL;
+	}
+
+	Palette *retval = new Palette(counter);
+	char buf[100];
+	sprintf(buf, "read_pal1 (id %d)", id);
+	retval->name = buf;
+
+	for (pos = 0; pos < counter; pos++) {
+		unsigned int color = colors[pos];
+		retval->setColor(pos, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff);
+	}
+
+	return retval;
+}
+
+Palette *gfxr_read_pal1_amiga(Common::File &file) {
+	int i;
+	Palette *retval = new Palette(32);
+
+	for (i = 0; i < 32; i++) {
+		int b1, b2;
+
+		b1 = file.readByte();
+		b2 = file.readByte();
+
+		if (b1 == EOF || b2 == EOF) {
+			GFXERROR("Palette file ends prematurely\n");
+			return NULL;
+		}
+
+		retval->setColor(i, (b1 & 0xf) * 0x11, ((b2 & 0xf0) >> 4) * 0x11, (b2 & 0xf) * 0x11);
+	}
+
+	return retval;
+}
+
+} // End of namespace Sci

Copied: scummvm/trunk/engines/sci/gfx/res_pic.cpp (from rev 39505, scummvm/trunk/engines/sci/gfx/resource/res_pic.cpp)
===================================================================
--- scummvm/trunk/engines/sci/gfx/res_pic.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/gfx/res_pic.cpp	2009-03-18 13:24:47 UTC (rev 39515)
@@ -0,0 +1,1881 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include <time.h>	// for time() to seed rand() via srand()
+#include "sci/sci_memory.h"
+#include "sci/gfx/gfx_resource.h"
+#include "sci/gfx/gfx_tools.h"
+
+namespace Sci {
+
+#undef GFXR_DEBUG_PIC0 // Enable to debug pic0 messages
+#undef FILL_RECURSIVE_DEBUG // Enable for verbose fill debugging
+
+#define GFXR_PIC0_PALETTE_SIZE 40
+#define GFXR_PIC0_NUM_PALETTES 4
+
+#define INTERCOL(a, b) ((int) sqrt((((3.3 * (a))*(a)) + ((1.7 * (b))*(b))) / 5.0))
+// Macro for color interpolation
+
+#define SCI0_MAX_PALETTE 2
+
+int sci0_palette = 0;
+
+// Copied from include/kernel.h
+#define SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr) ((((nr) == 0)? 0 :  \
+	((first) + (((nr)-1) * (last - first)) / 14)))
+
+// Default color maps
+gfx_pixmap_color_t gfx_sci0_image_colors[SCI0_MAX_PALETTE+1][GFX_SCI0_IMAGE_COLORS_NR] = {
+	{{GFX_COLOR_SYSTEM, 0x00, 0x00, 0x00}, {GFX_COLOR_SYSTEM, 0x00, 0x00, 0xaa},
+		{GFX_COLOR_SYSTEM, 0x00, 0xaa, 0x00}, {GFX_COLOR_SYSTEM, 0x00, 0xaa, 0xaa},
+		{GFX_COLOR_SYSTEM, 0xaa, 0x00, 0x00}, {GFX_COLOR_SYSTEM, 0xaa, 0x00, 0xaa},
+		{GFX_COLOR_SYSTEM, 0xaa, 0x55, 0x00}, {GFX_COLOR_SYSTEM, 0xaa, 0xaa, 0xaa},
+		{GFX_COLOR_SYSTEM, 0x55, 0x55, 0x55}, {GFX_COLOR_SYSTEM, 0x55, 0x55, 0xff},
+		{GFX_COLOR_SYSTEM, 0x55, 0xff, 0x55}, {GFX_COLOR_SYSTEM, 0x55, 0xff, 0xff},
+		{GFX_COLOR_SYSTEM, 0xff, 0x55, 0x55}, {GFX_COLOR_SYSTEM, 0xff, 0x55, 0xff},
+		{GFX_COLOR_SYSTEM, 0xff, 0xff, 0x55}, {GFX_COLOR_SYSTEM, 0xff, 0xff, 0xff}}, // "Normal" EGA
+
+
+	{{GFX_COLOR_SYSTEM, 0x00, 0x00, 0x00}, {GFX_COLOR_SYSTEM, 0x00, 0x00, 0xff},
+		{GFX_COLOR_SYSTEM, 0x00, 0xaa, 0x00}, {GFX_COLOR_SYSTEM, 0x00, 0xaa, 0xaa},
+		{GFX_COLOR_SYSTEM, 0xce, 0x00, 0x00}, {GFX_COLOR_SYSTEM, 0xbe, 0x71, 0xde},
+		{GFX_COLOR_SYSTEM, 0x8d, 0x50, 0x00}, {GFX_COLOR_SYSTEM, 0xbe, 0xbe, 0xbe},
+		{GFX_COLOR_SYSTEM, 0x55, 0x55, 0x55}, {GFX_COLOR_SYSTEM, 0x00, 0xbe, 0xff},
+		{GFX_COLOR_SYSTEM, 0x00, 0xce, 0x55}, {GFX_COLOR_SYSTEM, 0x55, 0xff, 0xff},
+		{GFX_COLOR_SYSTEM, 0xff, 0x9d, 0x8d}, {GFX_COLOR_SYSTEM, 0xff, 0x55, 0xff},
+		{GFX_COLOR_SYSTEM, 0xff, 0xff, 0x00}, {GFX_COLOR_SYSTEM, 0xff, 0xff, 0xff}}, // AGI Amiga-ish
+
+// RGB and I intensities (former taken from the GIMP)
+#define GR 30
+#define GG 59
+#define GB 11
+#define GI 15
+
+#define FULL (GR+GG+GB+GI)
+
+#define CC(x) (((x)*255)/FULL),(((x)*255)/FULL),(((x)*255)/FULL)         // Combines color intensities
+
+	{{GFX_COLOR_SYSTEM, CC(0)           }, {GFX_COLOR_SYSTEM, CC(GB)          },
+		{GFX_COLOR_SYSTEM, CC(GG)          }, {GFX_COLOR_SYSTEM, CC(GB + GG)       },
+		{GFX_COLOR_SYSTEM, CC(GR)          }, {GFX_COLOR_SYSTEM, CC(GB + GR)       },
+		{GFX_COLOR_SYSTEM, CC(GG + GR)       }, {GFX_COLOR_SYSTEM, CC(GB + GG + GR)    },
+		{GFX_COLOR_SYSTEM, CC(GI)          }, {GFX_COLOR_SYSTEM, CC(GB + GI)       },
+		{GFX_COLOR_SYSTEM, CC(GG + GI)       }, {GFX_COLOR_SYSTEM, CC(GB + GG + GI)    },
+		{GFX_COLOR_SYSTEM, CC(GR + GI)       }, {GFX_COLOR_SYSTEM, CC(GB + GR + GI)    },
+		{GFX_COLOR_SYSTEM, CC(GG + GR + GI)    }, {GFX_COLOR_SYSTEM, CC(GB + GG + GR + GI) }}
+}; // Grayscale
+
+#undef GR
+#undef GG
+#undef GB
+#undef GI
+
+#undef FULL
+
+#undef C2
+#undef C3
+#undef C4
+
+Palette* gfx_sci0_pic_colors = 0; // Initialized during initialization
+Palette* gfx_sci0_image_pal[SCI0_MAX_PALETTE+1];
+Palette* embedded_view_pal = 0;
+
+#define SCI1_PALETTE_SIZE 1284
+
+#ifdef FILL_RECURSIVE_DEBUG
+/************************************/
+int fillc = 100000000;
+int fillmagc = 30000000;
+/************************************/
+#endif
+
+// Color mapping used while scaling embedded views.
+gfx_pixmap_color_t embedded_view_colors[16] = {
+	{0x00, 0, 0, 0}, {0x11, 0, 0, 0}, {0x22, 0, 0, 0}, {0x33, 0, 0, 0},
+	{0x44, 0, 0, 0}, {0x55, 0, 0, 0}, {0x66, 0, 0, 0}, {0x77, 0, 0, 0},
+	{0x88, 0, 0, 0}, {0x99, 0, 0, 0}, {0xaa, 0, 0, 0}, {0xbb, 0, 0, 0},
+	{0xcc, 0, 0, 0}, {0xdd, 0, 0, 0}, {0xee, 0, 0, 0}, {0xff, 0, 0, 0}
+};
+
+void gfxr_init_static_palette() {
+	if (!gfx_sci0_pic_colors) {
+		gfx_sci0_pic_colors = new Palette(256);
+		gfx_sci0_pic_colors->name = "gfx_sci0_pic_colors";
+		for (int i = 0; i < 256; i++) {
+			byte r = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].r,
+			                  gfx_sci0_image_colors[sci0_palette][i >> 4].r);
+			byte g = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].g,
+			                  gfx_sci0_image_colors[sci0_palette][i >> 4].g);
+			byte b = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].b,
+			                  gfx_sci0_image_colors[sci0_palette][i >> 4].b);
+			gfx_sci0_pic_colors->setColor(i,r,g,b);
+		}
+		//warning("Uncomment me after fixing sci0_palette changes to reset me");
+		//_gfxr_pic0_colors_initialized = 1;
+
+		for (int i = 0; i <= SCI0_MAX_PALETTE; ++i) {
+			gfx_sci0_image_pal[i] = new Palette(gfx_sci0_image_colors[i], GFX_SCI0_IMAGE_COLORS_NR);
+			gfx_sci0_image_pal[i]->name = "gfx_sci0_image_pal[i]";
+		}
+
+		embedded_view_pal = new Palette(embedded_view_colors, 16);
+		embedded_view_pal->name = "embedded_view_pal";
+	}
+}
+
+
+gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, int sci1) {
+	gfxr_pic_t *pic = (gfxr_pic_t*)sci_malloc(sizeof(gfxr_pic_t));
+
+	pic->mode = mode;
+
+	pic->control_map = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320, 200, ID, 2, 0));
+
+	pic->priority_map = gfx_pixmap_alloc_index_data(gfx_new_pixmap(mode->xfact * 320, mode->yfact * 200,
+	                    ID, 1, 0));
+
+
+	pic->visual_map = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320 * mode->xfact,
+	                  200 * mode->yfact, ID, 0, 0));
+
+	// Initialize colors
+	if (!sci1) {
+		pic->ID = ID;
+		gfxr_init_static_palette();
+	}
+
+	pic->visual_map->palette = gfx_sci0_pic_colors->getref();
+	pic->visual_map->color_key = GFX_PIXMAP_COLOR_KEY_NONE;
+
+	pic->visual_map->flags = 0;
+	pic->priority_map->flags = 0;
+	pic->control_map->flags = 0;
+	if (mode->xfact > 1 || mode->yfact > 1) {
+		pic->visual_map->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX;
+		pic->priority_map->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX;
+	}
+
+	pic->priority_map->palette = gfx_sci0_image_pal[sci0_palette]->getref();
+	pic->control_map->palette = gfx_sci0_image_pal[sci0_palette]->getref();
+
+	pic->undithered_buffer_size = pic->visual_map->index_width * pic->visual_map->index_height;
+	pic->undithered_buffer = NULL;
+	pic->priorityTable = NULL;
+
+	return pic;
+}
+
+// Pic rendering operations
+
+void gfxr_clear_pic0(gfxr_pic_t *pic, int sci_titlebar_size) {
+	memset(pic->visual_map->index_data, 0x00, (320 * pic->mode->xfact * sci_titlebar_size * pic->mode->yfact));
+	memset(pic->visual_map->index_data + (320 * pic->mode->xfact * sci_titlebar_size * pic->mode->yfact),
+	       0xff, pic->mode->xfact * 320 * pic->mode->yfact * (200 - sci_titlebar_size)); // white
+	memset(pic->priority_map->index_data + (320 * pic->mode->xfact * sci_titlebar_size * pic->mode->yfact),
+	       0x0, pic->mode->xfact * 320 * pic->mode->yfact * (200 - sci_titlebar_size));
+	memset(pic->priority_map->index_data, 0x0a, sci_titlebar_size * (pic->mode->yfact * 320 * pic->mode->xfact));
+	memset(pic->control_map->index_data, 0, GFXR_AUX_MAP_SIZE);
+	memset(pic->aux_map, 0, GFXR_AUX_MAP_SIZE);
+}
+
+
+//** Basic operations on the auxiliary buffer **
+
+#define FRESH_PAINT 0x40
+// freshly filled or near to something that is
+
+#define LINEMACRO(startx, starty, deltalinear, deltanonlinear, linearvar, nonlinearvar, \
+                  linearend, nonlinearstart, linearmod, nonlinearmod, operation) \
+	x = (startx); y = (starty); \
+	incrNE = ((deltalinear) > 0)? (deltalinear) : -(deltalinear); \
+	incrNE <<= 1; \
+	deltanonlinear <<= 1; \
+	incrE = ((deltanonlinear) > 0) ? -(deltanonlinear) : (deltanonlinear);  \
+	d = nonlinearstart-1;  \
+	while (linearvar != (linearend)) { \
+		buffer[linewidth * y + x] operation color; \
+/* color ^= color2; color2 ^= color; color ^= color2; */ /* Swap colors */ \
+		linearvar += linearmod; \
+		if ((d+=incrE) < 0) { \
+			d += incrNE; \
+			nonlinearvar += nonlinearmod; \
+		}; \
+	}; \
+	buffer[linewidth * y + x] operation color;
+
+static void _gfxr_auxbuf_line_draw(gfxr_pic_t *pic, rect_t line, int color, int color2, int sci_titlebar_size) {
+	int dx, dy, incrE, incrNE, d, finalx, finaly;
+	int x = line.x;
+	int y = line.y + sci_titlebar_size;
+	unsigned char *buffer = pic->aux_map;
+	int linewidth = 320;
+
+	dx = line.width;
+	dy = line.height;
+	finalx = x + dx;
+	finaly = y + dy;
+
+	dx = abs(dx);
+	dy = abs(dy);
+
+	if (dx > dy) {
+		if (finalx < x) {
+			if (finaly < y) { // llu == left-left-up
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, -1, -1, |=);
+			} else {         // lld
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, -1, 1, |=);
+			}
+		} else { // x1 >= x
+			if (finaly < y) { // rru
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, 1, -1, |=);
+			} else {         // rrd
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, 1, 1, |=);
+			}
+		}
+	} else { // dx <= dy
+		if (finaly < y) {
+			if (finalx < x) { // luu
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, -1, -1, |=);
+			} else {         // ruu
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, -1, 1, |=);
+			}
+		} else { // y1 >= y
+			if (finalx < x) { // ldd
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, 1, -1, |=);
+			} else {         // rdd
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, 1, 1, |=);
+			}
+		}
+	}
+}
+
+static void _gfxr_auxbuf_line_clear(gfxr_pic_t *pic, rect_t line, int color, int sci_titlebar_size) {
+	int dx, dy, incrE, incrNE, d, finalx, finaly;
+	int x = line.x;
+	int y = line.y + sci_titlebar_size;
+	unsigned char *buffer = pic->aux_map;
+	int linewidth = 320;
+
+	dx = line.width;
+	dy = line.height;
+	finalx = x + dx;
+	finaly = y + dy;
+
+	dx = abs(dx);
+	dy = abs(dy);
+
+	if (dx > dy) {
+		if (finalx < x) {
+			if (finaly < y) { // llu == left-left-up
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, -1, -1, &=);
+			} else {         // lld
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, -1, 1, &=);
+			}
+		} else { // x1 >= x
+			if (finaly < y) { // rru
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, 1, -1, &=);
+			} else {         // rrd
+				LINEMACRO(x, y, dx, dy, x, y, finalx, dx, 1, 1, &=);
+			}
+		}
+	} else { // dx <= dy
+		if (finaly < y) {
+			if (finalx < x) { // luu
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, -1, -1, &=);
+			} else {         // ruu
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, -1, 1, &=);
+			}
+		} else { // y1 >= y
+			if (finalx < x) { // ldd
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, 1, -1, &=);
+			} else {         // rdd
+				LINEMACRO(x, y, dy, dx, y, x, finaly, dy, 1, 1, &=);
+			}
+		}
+	}
+}
+
+#undef LINEMACRO
+
+#ifdef WITH_PIC_SCALING
+static void _gfxr_auxbuf_propagate_changes(gfxr_pic_t *pic, int bitmask) {
+	// Propagates all filled bits into the planes described by bitmask
+	unsigned long *data = (unsigned long *)pic->aux_map;
+	unsigned long clearmask = 0x07070707;
+	unsigned long andmask = (bitmask << 3) | (bitmask << (3 + 8)) | (bitmask << (3 + 16)) | (bitmask << (3 + 24));
+
+	if (sizeof(unsigned long) == 8) { // UltraSparc, Alpha, newer MIPSens, etc
+		andmask |= (andmask << 32);
+		clearmask |= (clearmask << 32);
+	}
+
+	for (int i = 0; i < GFXR_AUX_MAP_SIZE / sizeof(unsigned long); i++) {
+		unsigned long temp = *data & andmask;
+		temp >>= 3;
+		*data = (temp | *data) & clearmask;
+		++data;
+	}
+}
+#endif
+
+
+#if 0
+// Unreferenced - removed
+static void _gfxr_auxbuf_tag_line(gfxr_pic_t *pic, int pos, int width) {
+	for (int i = 0; i < width; i++)
+		pic->aux_map[i+pos] |= FRESH_PAINT;
+}
+
+// Unreferenced - removed
+static void _gfxr_auxbuf_spread(gfxr_pic_t *pic, int *min_x, int *min_y, int *max_x, int *max_y) {
+	// Tries to spread by approximating the first derivation of the border function.
+	// Draws to the current and the last line, thus taking up to twice as long as neccessary.
+	// Other than that, it's O(n^2)
+
+	int intervals_nr = 0, old_intervals_nr;
+	int x, y, i, pos = 10 * 320;
+	struct interval_struct {
+		int xl, xr, tag;
+	} intervals[2][160];
+
+	*max_x = *max_y = -1;
+	*min_x = *min_y = 320;
+
+#ifdef FILL_RECURSIVE_DEBUG
+	if (!fillmagc) {
+		fprintf(stderr, "------------------------------------------------\n");
+		fprintf(stderr, "LineID:   ");
+		for (i = 0; i < 5; i++)
+			fprintf(stderr, "  %d       ", i);
+		fprintf(stderr, "\n");
+	}
+#endif
+
+	for (y = 10; y < 200; y++) {
+		int ivi = y & 1; // InterVal Index: Current intervals; !ivi is the list of old ones
+		int old_intervals_start_offset = 0;
+		int width = 0;
+
+		old_intervals_nr = intervals_nr;
+		intervals_nr = 0;
+
+		for (x = 0; x < 321; x++)
+			if (x < 320 && pic->aux_map[pos+x] & 0x10)
+				width++;
+			else if (width) { // Found one interval
+				int xl = x - width;
+				int xr = x - 1;
+				int done = 0;
+				int found_interval = 0;
+
+				intervals[ivi][intervals_nr].width = xl;
+				intervals[ivi][intervals_nr].tag = 0;
+				intervals[ivi][intervals_nr++].xr = xr;
+
+				if (xl < *min_x)
+					*min_x = xl;
+				if (xr > *max_x)
+					*max_x = xr;
+
+				i = old_intervals_start_offset;
+				while (!done && i < old_intervals_nr) {
+					if (intervals[!ivi][i].width > xr + 1)
+						done = 1;
+
+					else if (intervals[!ivi][i].xr < xl - 1) {
+						int o_xl = intervals[!ivi][i].width;
+						int o_xr = intervals[!ivi][i].xr;
+						if (o_xr == o_xl && !intervals[!ivi][i].tag) { // thin bar
+							memcpy(intervals[ivi] + intervals_nr, intervals[ivi] + intervals_nr - 1, sizeof(struct interval_struct));
+							memcpy(intervals[ivi] + intervals_nr - 1, intervals[!ivi] + i, sizeof(struct interval_struct));
+							intervals[!ivi][i].tag = 1;
+							pic->aux_map[pos - 320 + o_xl] |= FRESH_PAINT;
+							++intervals_nr;
+						}
+
+						old_intervals_start_offset = i;
+					} else {
+						int k = i;
+						int old_xl = intervals[!ivi][i].width;
+						int dwidth_l = abs(old_xl - xl);
+						int old_xr, dwidth_r;
+						int write_left_width, write_right_width;
+
+						intervals[!ivi][i].tag = 1;
+						while (k + 1 < old_intervals_nr && intervals[!ivi][k+1].width <= xr) {
+							++k;
+							intervals[!ivi][i].tag = 1;
+						}
+
+						old_xr = intervals[!ivi][k].xr;
+						dwidth_r = abs(old_xr - xr);
+
+						// Current line
+						write_left_width = (dwidth_l > xl) ? xl : dwidth_l;
+						_gfxr_auxbuf_tag_line(pic, pos + xl - write_left_width, write_left_width);
+
+						write_right_width = (dwidth_r + xr > 319) ? 320 - xr : dwidth_r;
+						_gfxr_auxbuf_tag_line(pic, pos + xr, write_right_width);
+
+						if (xl - write_left_width < *min_x)
+							*min_x = xl - write_left_width;
+						if (xr + write_right_width > *max_x)
+							*max_x = xr + write_right_width;
+
+						// Previous line
+						write_left_width = (dwidth_l > old_xl) ? old_xl : dwidth_l;
+						write_right_width = (dwidth_r + old_xr > 319) ? 320 - old_xr : dwidth_r;
+
+						if (i == k) { // Only one predecessor interval
+							_gfxr_auxbuf_tag_line(pic, pos - 320 + old_xl - write_left_width, write_left_width);
+							_gfxr_auxbuf_tag_line(pic, pos - 320 + old_xr, write_right_width);
+						} else // Fill entire line
+							_gfxr_auxbuf_tag_line(pic, pos - 320 + old_xl - write_left_width, old_xr - old_xl
+							                      + 1 + write_left_width + write_right_width);
+
+						if (xl - write_left_width < *min_x)
+							*min_x = xl - write_left_width;
+						if (xr + write_right_width > *max_x)
+							*max_x = xr + write_right_width;
+
+						found_interval = done = 1;
+					}
+					i++;
+				}
+				width = 0;
+			}
+
+#ifdef FILL_RECURSIVE_DEBUG
+		if (!fillmagc && intervals_nr) {
+			fprintf(stderr, "AI L#%03d:", y);
+			for (int j = 0; j < intervals_nr; j++)
+				fprintf(stderr, "%c[%03d,%03d]", intervals[ivi][j].tag ? ' ' : '-', intervals[ivi][j].width, intervals[ivi][j].xr);
+			fprintf(stderr, "\n");
+		}
+#endif
+
+		if (intervals_nr) {
+			if (y < *min_y)
+				*min_y = y;
+			*max_y = y;
+		}
+
+		pos += 320;
+	}
+
+	for (pos = 320 * 200 - 1; pos >= 320; pos--)
+		if (pic->aux_map[pos - 320] & 0x40)
+			pic->aux_map[pos] |= 0x40;
+
+	if (*max_y < 199)
+		(*max_y)++;
+}
+
+#endif
+
+
+/*** Regular drawing operations ***/
+
+#define PATTERN_FLAG_RECTANGLE 0x10
+#define PATTERN_FLAG_USE_PATTERN 0x20
+
+#define PIC_OP_FIRST 0xf0
+
+enum {
+	PIC_OP_SET_COLOR = 0xf0,
+	PIC_OP_DISABLE_VISUAL = 0xf1,
+	PIC_OP_SET_PRIORITY = 0xf2,
+	PIC_OP_DISABLE_PRIORITY = 0xf3,
+	PIC_OP_SHORT_PATTERNS = 0xf4,
+	PIC_OP_MEDIUM_LINES = 0xf5,
+	PIC_OP_LONG_LINES = 0xf6,
+	PIC_OP_SHORT_LINES = 0xf7,
+	PIC_OP_FILL = 0xf8,
+	PIC_OP_SET_PATTERN = 0xf9,
+	PIC_OP_ABSOLUTE_PATTERN = 0xfa,
+	PIC_OP_SET_CONTROL = 0xfb,
+	PIC_OP_DISABLE_CONTROL = 0xfc,
+	PIC_OP_MEDIUM_PATTERNS = 0xfd,
+	PIC_OP_OPX = 0xfe,
+	PIC_OP_TERMINATE = 0xff
+};
+
+enum {
+	PIC_SCI0_OPX_SET_PALETTE_ENTRIES = 0,
+	PIC_SCI0_OPX_SET_PALETTE = 1,
+	PIC_SCI0_OPX_MONO0 = 2,
+	PIC_SCI0_OPX_MONO1 = 3,
+	PIC_SCI0_OPX_MONO2 = 4,
+	PIC_SCI0_OPX_MONO3 = 5,
+	PIC_SCI0_OPX_MONO4 = 6,
+	PIC_SCI0_OPX_EMBEDDED_VIEW,
+	PIC_SCI0_OPX_SET_PRIORITY_TABLE
+};
+
+// We use this so we can keep OPX handling in one switch.
+// We simply add this constant to the op number if we're running an SCI1 game,
+// and offset the OPX constants below correspondingly.
+#define SCI1_OP_OFFSET 42
+
+enum {
+	PIC_SCI1_OPX_SET_PALETTE_ENTRIES = 0 + SCI1_OP_OFFSET,
+	PIC_SCI1_OPX_EMBEDDED_VIEW = 1 + SCI1_OP_OFFSET,
+	PIC_SCI1_OPX_SET_PALETTE = 2 + SCI1_OP_OFFSET,
+	PIC_SCI1_OPX_PRIORITY_TABLE_EQDIST = 3 + SCI1_OP_OFFSET,
+	PIC_SCI1_OPX_PRIORITY_TABLE_EXPLICIT = 4 + SCI1_OP_OFFSET
+};
+
+
+#ifdef GFXR_DEBUG_PIC0
+#define p0printf sciprintf
+#else
+void do_nothing(...) { }
+#define p0printf do_nothing
+#endif
+
+enum {
+	ELLIPSE_SOLID, // Normal filled ellipse
+	ELLIPSE_OR     // color ORred to the buffer
+};
+
+static void _gfxr_fill_ellipse(gfxr_pic_t *pic, byte *buffer, int linewidth, int x, int y,
+		int rad_x, int rad_y, int color, int fillstyle) {
+	int xx = 0, yy = rad_y;
+	int i, x_i, y_i;
+	int xr = 2 * rad_x * rad_x;
+	int yr = 2 * rad_y * rad_y;
+
+	x_i = 1;
+	y_i = xr * rad_y - 1;
+	i = y_i >> 1;
+
+	while (yy >= 0) {
+		int oldxx = xx;
+		int oldyy = yy;
+
+		if (i >= 0) {
+			x_i += yr;
+			i -= x_i + 1;
+			++xx;
+		}
+
+		if (i < 0) {
+			y_i -= xr;
+			i += y_i - 1;
+			--yy;
+		}
+
+		if (oldyy != yy) {
+			int j;
+			int offset0 = (y - oldyy) * linewidth;
+			int offset1 = (y + oldyy) * linewidth;
+
+			offset0 += x - oldxx;
+			offset1 += x - oldxx;
+
+			if (oldyy == 0)
+				offset1 = 0; // We never have to draw ellipses in the menu bar
+
+			oldyy = yy;
+
+			switch (fillstyle) {
+
+			case ELLIPSE_SOLID:
+				memset(buffer + offset0, color, (oldxx << 1) + 1);
+				if (offset1)
+					memset(buffer + offset1, color, (oldxx << 1) + 1);
+				break;
+
+			case ELLIPSE_OR:
+				for (j = 0; j < (oldxx << 1) + 1; j++) {
+					buffer[offset0 + j] |= color;
+					if (offset1)
+						buffer[offset1 + j] |= color;
+				}
+				break;
+
+			default:
+				fprintf(stderr, "%s L%d: Invalid ellipse fill mode!\n", __FILE__, __LINE__);
+				return;
+
+			}
+		}
+	}
+}
+
+static void _gfxr_auxplot_brush(gfxr_pic_t *pic, byte *buffer, int yoffset, int offset, int plot,
+	int color, gfx_brush_mode_t brush_mode, int randseed) {
+	// yoffset 63680, offset 320, plot 1, color 34, brush_mode 0, randseed 432)*/
+	// Auxplot: Used by plot_aux_pattern to plot to visual and priority
+	int xc, yc;
+	int line_width = 320 * pic->mode->xfact;
+	int full_offset = (yoffset * pic->mode->yfact + offset) * pic->mode->xfact;
+
+	if (yoffset + offset >= 64000) {
+		BREAKPOINT();
+	}
+
+	switch (brush_mode) {
+	case GFX_BRUSH_MODE_SCALED:
+		if (plot)
+			for (yc = 0; yc < pic->mode->yfact; yc++) {
+				memset(buffer + full_offset, color, pic->mode->xfact);
+				full_offset += line_width;
+			}
+		break;
+
+	case GFX_BRUSH_MODE_ELLIPSES:
+		if (plot) {
+			int x = offset * pic->mode->xfact + ((pic->mode->xfact - 1) >> 1);
+			int y = (yoffset / 320) * pic->mode->yfact + ((pic->mode->yfact - 1) >> 1);
+
+			_gfxr_fill_ellipse(pic, buffer, line_width, x, y, pic->mode->xfact >> 1, pic->mode->yfact >> 1, color, ELLIPSE_SOLID);
+		}
+		break;
+
+	case GFX_BRUSH_MODE_RANDOM_ELLIPSES:
+		if (plot) {
+			int x = offset * pic->mode->xfact + ((pic->mode->xfact - 1) >> 1);
+			int y = (yoffset / 320) * pic->mode->yfact + ((pic->mode->yfact - 1) >> 1);
+			int sizex = pic->mode->xfact >> 1;
+			int sizey = pic->mode->yfact >> 1;
+
+			srand(randseed);
+
+			x -= (int)((sizex * rand() * 1.0) / (RAND_MAX + 1.0));
+			x += (int)((sizex * rand() * 1.0) / (RAND_MAX + 1.0));
+			y -= (int)((sizey * rand() * 1.0) / (RAND_MAX + 1.0));
+			y += (int)((sizey * rand() * 1.0) / (RAND_MAX + 1.0));
+			sizex = (int)((sizex * rand() * 1.0) / (RAND_MAX + 1.0));
+			sizey = (int)((sizey * rand() * 1.0) / (RAND_MAX + 1.0));
+
+			_gfxr_fill_ellipse(pic, buffer, line_width, x, y, pic->mode->xfact >> 1, pic->mode->yfact >> 1,
+			                   color, ELLIPSE_SOLID);
+			srand(time(NULL)); // Make sure we don't accidently forget to re-init the random number generator
+		}
+		break;
+
+	case GFX_BRUSH_MODE_MORERANDOM: {
+		int mask = plot ? 7 : 1;
+		srand(randseed);
+		for (yc = 0; yc < pic->mode->yfact; yc++) {
+			for (xc = 0; xc < pic->mode->xfact; xc++)
+				if ((rand() & 7) < mask)
+					buffer[full_offset + xc] = color;
+			full_offset += line_width;
+		}
+		srand(time(NULL)); // Make sure we don't accidently forget to re-init the random number generator
+	}
+	break;
+	}
+}
+
+#define PLOT_AUX_PATTERN_NO_RANDOM -1
+
+static void _gfxr_plot_aux_pattern(gfxr_pic_t *pic, int x, int y, int size, int circle, int random,
+	int mask, int color, int priority, int control, gfx_brush_mode_t brush_mode, int map_nr) {
+	// Plots an appropriate pattern to the aux buffer and the control buffer,
+	// if mask & GFX_MASK_CONTROL
+	// random should be set to the random index, or -1 to disable
+
+	// These circle offsets uniquely identify the circles used by Sierra:
+	int circle_data[][8] = {
+		{0},
+		{1, 0},
+		{2, 2, 1},
+		{3, 3, 2, 1},
+		{4, 4, 4, 3, 1},
+		{5, 5, 4, 4, 3, 1},
+		{6, 6, 6, 5, 5, 4, 2},
+		{7, 7, 7, 6, 6, 5, 4, 2}
+	};
+
+	// 'Random' fill patterns, provided by Carl Muckenhoupt:
+	byte random_data[32] = {
+		0x20, 0x94, 0x02, 0x24, 0x90, 0x82, 0xa4, 0xa2, 0x82, 0x09, 0x0a, 0x22,
+		0x12, 0x10, 0x42, 0x14, 0x91, 0x4a, 0x91, 0x11, 0x08, 0x12, 0x25, 0x10,
+		0x22, 0xa8, 0x14, 0x24, 0x00, 0x50, 0x24, 0x04
+	};
+
+	// 'Random' fill offsets, provided by Carl Muckenhoupt:
+	byte random_offset[128] = {
+		0x00, 0x18, 0x30, 0xc4, 0xdc, 0x65, 0xeb, 0x48,
+		0x60, 0xbd, 0x89, 0x05, 0x0a, 0xf4, 0x7d, 0x7d,
+		0x85, 0xb0, 0x8e, 0x95, 0x1f, 0x22, 0x0d, 0xdf,
+		0x2a, 0x78, 0xd5, 0x73, 0x1c, 0xb4, 0x40, 0xa1,
+		0xb9, 0x3c, 0xca, 0x58, 0x92, 0x34, 0xcc, 0xce,
+		0xd7, 0x42, 0x90, 0x0f, 0x8b, 0x7f, 0x32, 0xed,
+		0x5c, 0x9d, 0xc8, 0x99, 0xad, 0x4e, 0x56, 0xa6,
+		0xf7, 0x68, 0xb7, 0x25, 0x82, 0x37, 0x3a, 0x51,
+		0x69, 0x26, 0x38, 0x52, 0x9e, 0x9a, 0x4f, 0xa7,
+		0x43, 0x10, 0x80, 0xee, 0x3d, 0x59, 0x35, 0xcf,
+		0x79, 0x74, 0xb5, 0xa2, 0xb1, 0x96, 0x23, 0xe0,
+		0xbe, 0x05, 0xf5, 0x6e, 0x19, 0xc5, 0x66, 0x49,
+		0xf0, 0xd1, 0x54, 0xa9, 0x70, 0x4b, 0xa4, 0xe2,
+		0xe6, 0xe5, 0xab, 0xe4, 0xd2, 0xaa, 0x4c, 0xe3,
+		0x06, 0x6f, 0xc6, 0x4a, 0xa4, 0x75, 0x97, 0xe1
+	};
+
+	int offset = 0, width = 0;
+	int yoffset = (y - size) * 320;
+	int i;
+	int random_index = 0;
+	gfx_pixmap_t *map = NULL;
+
+	switch (map_nr) {
+	case GFX_MASK_VISUAL:
+		map = pic->visual_map;
+		break;
+	case GFX_MASK_PRIORITY:
+		map = pic->priority_map;
+		break;
+	default:
+		map = pic->control_map;
+		break;
+	}
+
+	if (random >= 0)
+		random_index = random_offset[random];
+
+	if (!circle) {
+		offset = -size;
+		width = (size << 1) + 2;
+	}
+
+	for (i = -size; i <= size; i++) {
+		int j;
+		int height;
+
+		if (circle) {
+			offset = circle_data[size][abs(i)];
+			height = width = (offset << 1) + 1;
+			offset = -offset;
+		} else
+			height = width - 1;
+
+		if (random == PLOT_AUX_PATTERN_NO_RANDOM) {
+
+			if (mask & map_nr)
+				memset(map->index_data + yoffset + offset + x, control, width);
+
+			if (map_nr == GFX_MASK_CONTROL)
+				for (j = x; j < x + width; j++)
+					pic->aux_map[yoffset + offset + j] |= mask;
+
+		} else { // Semi-Random!
+			for (j = 0; j < height; j++) {
+				if (random_data[random_index >> 3] & (0x80 >> (random_index & 7))) {
+					// The 'seemingly' random decision
+					if (mask & GFX_MASK_CONTROL)
+						pic->control_map->index_data[yoffset + x + offset + j] = control;
+
+					pic->aux_map[yoffset + x + offset + j] |= mask;
+
+					if (mask & GFX_MASK_VISUAL)
+						_gfxr_auxplot_brush(pic, pic->visual_map->index_data, yoffset, x + offset + j,
+						                    1, color, brush_mode, random_index + x);
+
+					if (mask & GFX_MASK_PRIORITY)
+						_gfxr_auxplot_brush(pic, pic->priority_map->index_data, yoffset, x + offset + j,
+						                    1, priority, brush_mode, random_index + x);
+
+				} else {
+					if (mask & GFX_MASK_VISUAL)
+						_gfxr_auxplot_brush(pic, pic->visual_map->index_data, yoffset, x + offset + j,
+						                    0, color, brush_mode, random_index + x);
+
+					if (mask & GFX_MASK_PRIORITY)
+						_gfxr_auxplot_brush(pic, pic->priority_map->index_data, yoffset, x + offset + j,
+						                    0, priority, brush_mode, random_index + x);
+				}
+				random_index = (random_index + 1) & 0xff;
+			}
+		}
+		yoffset += 320;
+	}
+}
+
+static void _gfxr_draw_pattern(gfxr_pic_t *pic, int x, int y, int color, int priority, int control, int drawenable,
+	int pattern_code, int pattern_size, int pattern_nr, gfx_brush_mode_t brush_mode, int sci_titlebar_size) {
+	int xsize = (pattern_size + 1) * pic->mode->xfact - 1;
+	int ysize = (pattern_size + 1) * pic->mode->yfact - 1;
+	int scaled_x, scaled_y;
+	rect_t boundaries;
+	int max_x = (pattern_code & PATTERN_FLAG_RECTANGLE) ? 318 : 319; // Rectangles' width is size+1
+
+	p0printf(stderr, "Pattern at (%d,%d) size %d, rand=%d, code=%02x\n", x, y, pattern_size, pattern_nr, pattern_code);
+
+	y += sci_titlebar_size;
+
+	if (x - pattern_size < 0)
+		x = pattern_size;
+
+	if (y - pattern_size < sci_titlebar_size)
+		y = sci_titlebar_size + pattern_size;
+
+	if (x + pattern_size > max_x)
+		x = max_x - pattern_size;
+
+	if (y + pattern_size > 199)
+		y = 199 - pattern_size;
+
+	scaled_x = x * pic->mode->xfact + ((pic->mode->xfact - 1) >> 1);
+	scaled_y = y * pic->mode->yfact + ((pic->mode->yfact - 1) >> 1);
+
+	if (scaled_x < xsize)
+		scaled_x = xsize;
+
+	if (scaled_y < ysize + sci_titlebar_size * pic->mode->yfact)
+		scaled_y = ysize + sci_titlebar_size * pic->mode->yfact;
+
+	if (scaled_x > (320 * pic->mode->xfact) - 1 - xsize)
+		scaled_x = (320 * pic->mode->xfact) - 1 - xsize;
+
+	if (scaled_y > (200 * pic->mode->yfact) - 1 - ysize)
+		scaled_y = (200 * pic->mode->yfact) - 1 - ysize;
+
+	if (pattern_code & PATTERN_FLAG_RECTANGLE) {
+		// Rectangle
+		boundaries.x = scaled_x - xsize;
+		boundaries.y = scaled_y - ysize;
+		boundaries.width = ((xsize + 1) << 1) + 1;
+		boundaries.height = (ysize << 1) + 1;
+
+		if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+			_gfxr_plot_aux_pattern(pic, x, y, pattern_size, 0, pattern_nr, drawenable, color, priority,
+			                       control, brush_mode, GFX_MASK_CONTROL);
+		} else {
+			_gfxr_plot_aux_pattern(pic, x, y, pattern_size, 0, PLOT_AUX_PATTERN_NO_RANDOM, drawenable, 0, 0, control,
+			                       GFX_BRUSH_MODE_SCALED, GFX_MASK_CONTROL);
+
+			if (drawenable & GFX_MASK_VISUAL)
+				gfx_draw_box_pixmap_i(pic->visual_map, boundaries, color);
+
+			if (drawenable & GFX_MASK_PRIORITY)
+				gfx_draw_box_pixmap_i(pic->priority_map, boundaries, priority);
+		}
+
+	} else {
+		// Circle
+
+		if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+
+			_gfxr_plot_aux_pattern(pic, x, y, pattern_size, 1, pattern_nr, drawenable, color, priority,
+			                       control, brush_mode, GFX_MASK_CONTROL);
+		} else {
+			_gfxr_plot_aux_pattern(pic, x, y, pattern_size, 1, PLOT_AUX_PATTERN_NO_RANDOM,
+			                       drawenable, 0, 0, control, GFX_BRUSH_MODE_SCALED, GFX_MASK_CONTROL);
+
+			if (pic->mode->xfact == 1 && pic->mode->yfact == 1) {
+				if (drawenable & GFX_MASK_VISUAL)
+					_gfxr_plot_aux_pattern(pic, x, y, pattern_size, 1, PLOT_AUX_PATTERN_NO_RANDOM,
+					                       drawenable, 0, 0, color, GFX_BRUSH_MODE_SCALED, GFX_MASK_VISUAL);
+
+				if (drawenable & GFX_MASK_PRIORITY)
+					_gfxr_plot_aux_pattern(pic, x, y, pattern_size, 1, PLOT_AUX_PATTERN_NO_RANDOM,
+					                       drawenable, 0, 0, priority, GFX_BRUSH_MODE_SCALED, GFX_MASK_PRIORITY);
+			} else {
+				if (drawenable & GFX_MASK_VISUAL)
+					_gfxr_fill_ellipse(pic, pic->visual_map->index_data, 320 * pic->mode->xfact,
+					                   scaled_x, scaled_y, xsize, ysize, color, ELLIPSE_SOLID);
+
+				if (drawenable & GFX_MASK_PRIORITY)
+					_gfxr_fill_ellipse(pic, pic->priority_map->index_data, 320 * pic->mode->xfact,
+					                   scaled_x, scaled_y, xsize, ysize, priority, ELLIPSE_SOLID);
+			}
+		}
+	}
+}
+
+static void _gfxr_draw_subline(gfxr_pic_t *pic, int x, int y, int ex, int ey, int color, int priority, int drawenable) {
+	Common::Point start;
+	Common::Point end;
+
+	start.x = x;
+	start.y = y;
+	end.x = ex;
+	end.y = ey;
+
+	if (ex >= pic->visual_map->index_width || ey >= pic->visual_map->index_height || x < 0 || y < 0) {
+		fprintf(stderr, "While drawing pic0: INVALID LINE %d,%d,%d,%d\n",
+		        start.x, start.y, end.x, end.y);
+		return;
+	}
+
+	if (drawenable & GFX_MASK_VISUAL)
+		gfx_draw_line_pixmap_i(pic->visual_map, start, end, color);
+
+	if (drawenable & GFX_MASK_PRIORITY)
+		gfx_draw_line_pixmap_i(pic->priority_map, start, end, priority);
+
+}
+
+static void _gfxr_draw_line(gfxr_pic_t *pic, int x, int y, int ex, int ey, int color,
+	int priority, int control, int drawenable, int line_mode, int cmd, int sci_titlebar_size) {
+	int scale_x = pic->mode->xfact;
+	int scale_y = pic->mode->yfact;
+	int xc, yc;
+	rect_t line;
+	int mask;
+	int partially_white = (drawenable & GFX_MASK_VISUAL) && (((color & 0xf0) == 0xf0) || ((color & 0x0f) == 0x0f));
+
+	line.x = x;
+	line.y = y;
+	line.width = ex - x;
+	line.height = ey - y;
+
+	if (x > 319 || y > 199 || x < 0 || y < 0 || ex > 319 || ey > 199 || ex < 0 || ey < 0) {
+		GFXWARN("While building pic: Attempt to draw line (%d,%d) to (%d,%d): cmd was %d\n", x, y, ex, ey, cmd);
+		return;
+	}
+
+	y += sci_titlebar_size;
+	ey += sci_titlebar_size;
+
+	if (drawenable & GFX_MASK_CONTROL) {
+		p0printf(" ctl:%x", control);
+		gfx_draw_line_pixmap_i(pic->control_map, Common::Point(x, y), Common::Point(x + line.width, y + line.height), control);
+	}
+
+	// Calculate everything that is changed to SOLID
+	mask = drawenable & (((color != 0xff) ? 1 : 0) | ((priority) ? 2 : 0) | ((control) ? 4 : 0));
+
+	if (mask) {
+		int mask2 = mask;
+		if (partially_white)
+			mask2 = mask &= ~GFX_MASK_VISUAL;
+		_gfxr_auxbuf_line_draw(pic, line, mask, mask2, sci_titlebar_size);
+	}
+
+	// Calculate everything that is changed to TRANSPARENT
+	mask = drawenable & (((color == 0xff) ? 1 : 0) | ((!priority) ? 2 : 0) | ((!control) ? 4 : 0));
+
+	if (mask)
+		_gfxr_auxbuf_line_clear(pic, line, ~mask, sci_titlebar_size);
+
+	x *= scale_x;
+	y *= scale_y;
+	ex *= scale_x;
+	ey *= scale_y;
+
+	if (drawenable & GFX_MASK_VISUAL)
+		p0printf(" col:%02x", color);
+
+	if (drawenable & GFX_MASK_PRIORITY)
+		p0printf(" pri:%x", priority);
+
+	if (line_mode == GFX_LINE_MODE_FINE) {  // Adjust lines to extend over the full visual
+		x = (x * ((320 + 1) * scale_x - 1)) / (320 * scale_x);
+		y = (y * ((200 + 1) * scale_y - 1)) / (200 * scale_y);
+		ex = (ex * ((320 + 1) * scale_x - 1)) / (320 * scale_x);
+		ey = (ey * ((200 + 1) * scale_y - 1)) / (200 * scale_y);
+
+		_gfxr_draw_subline(pic, x, y, ex, ey, color, priority, drawenable);
+	} else {
+		if (x == ex && y == ey) { // Just one single point?
+			rect_t drawrect;
+			drawrect.x = x;
+			drawrect.y = y;
+			drawrect.width = scale_x;
+			drawrect.height = scale_y;
+
+			if (drawenable & GFX_MASK_VISUAL)
+				gfx_draw_box_pixmap_i(pic->visual_map, drawrect, color);
+
+			if (drawenable & GFX_MASK_PRIORITY)
+				gfx_draw_box_pixmap_i(pic->priority_map, drawrect, priority);
+
+		} else {
+			int width = scale_x;
+			int height = scale_y;
+			int x_offset = 0;
+			int y_offset = 0;
+
+			if (line_mode == GFX_LINE_MODE_FAST) {
+				width = (width + 1) >> 1;
+				height = (height + 1) >> 1;
+				x_offset = (width >> 1);
+				y_offset = (height >> 1);
+			}
+
+			for (xc = 0; xc < width; xc++)
+				_gfxr_draw_subline(pic, x + xc + x_offset, y + y_offset, ex + xc + x_offset, ey + y_offset,
+				                   color, priority, drawenable);
+
+			if (height > 0)
+				for (xc = 0; xc < width; xc++)
+					_gfxr_draw_subline(pic, x + xc + x_offset, y + height - 1 + y_offset,
+					                   ex + xc + x_offset, ey + height - 1 + y_offset, color, priority, drawenable);
+
+			if (height > 1) {
+				for (yc = 1; yc < height - 1; yc++)
+					_gfxr_draw_subline(pic, x + x_offset, y + yc + y_offset, ex + x_offset, ey + yc + y_offset,
+					                   color, priority, drawenable);
+				if (width > 0)
+					for (yc = 1; yc < height - 1; yc++)
+						_gfxr_draw_subline(pic, x + width - 1 + x_offset, y + yc + y_offset,
+						                   ex + width - 1 + x_offset, ey + yc + y_offset, color, priority, drawenable);
+			}
+		}
+	}
+
+	p0printf("\n");
+}
+
+
+#define IS_FILL_BOUNDARY(x) (((x) & legalmask) != legalcolor)
+
+#ifdef WITH_PIC_SCALING
+
+#define TEST_POINT(xx, yy) \
+	if (pic->aux_map[(yy) * 320 + (xx)] & FRESH_PAINT) { \
+		mpos = (((yy) * 320 * pic->mode->yfact) + (xx)) * pic->mode->xfact; \
+		for (iy = 0; iy < pic->mode->yfact; iy++) { \
+			for (ix = 0; ix < pic->mode->xfact; ix++) { \
+				if (!IS_FILL_BOUNDARY(test_map[mpos + ix])) { \
+					*x = ix + (xx) * pic->mode->xfact; \
+					*y = iy + (yy) * pic->mode->yfact; \
+					return 0; \
+				} \
+				mpos += linewidth; \
+			} \
+		} \
+	}
+
+static int _gfxr_find_fill_point(gfxr_pic_t *pic, int min_x, int min_y, int max_x, int max_y, int x_320,
+	int y_200, int color, int drawenable, int *x, int *y) {
+	// returns -1 on failure, 0 on success
+	int linewidth = pic->mode->xfact * 320;
+	int mpos, ix, iy;
+	int size_x = (max_x - min_x + 1) >> 1;
+	int size_y = (max_y - min_y + 1) >> 1;
+	int mid_x = min_x + size_x;
+	int mid_y = min_y + size_y;
+	int max_size = (size_x > size_y) ? size_x : size_y;
+	int size;
+	int legalcolor;
+	int legalmask;
+	byte *test_map;
+	*x = x_320 * pic->mode->xfact;
+	*y = y_200 * pic->mode->yfact;
+
+	if (size_x < 0 || size_y < 0)
+		return 0;
+
+	if (drawenable & GFX_MASK_VISUAL) {
+		test_map = pic->visual_map->index_data;
+
+		if ((color & 0xf) == 0xf // When dithering with white, do more
+								// conservative checks
+		        || (color & 0xf0) == 0xf0)
+			legalcolor = 0xff;
+		else
+			legalcolor = 0xf0; // Only check the second color
+
+		legalmask = legalcolor;
+	} else if (drawenable & GFX_MASK_PRIORITY) {
+		test_map = pic->priority_map->index_data;
+		legalcolor = 0;
+		legalmask = 0xf;
+	} else return -3;
+
+	TEST_POINT(x_320, y_200); // Most likely candidate
+	TEST_POINT(mid_x, mid_y); // Second most likely candidate
+
+	for (size = 1; size <= max_size; size++) {
+		int i;
+
+		if (size <= size_y) {
+			int limited_size = (size > size_x) ? size_x : size;
+
+			for (i = mid_x - limited_size; i <= mid_x + limited_size; i++) {
+				TEST_POINT(i, mid_y - size);
+				TEST_POINT(i, mid_y + size);
+			}
+		}
+
+		if (size <= size_x) {
+			int limited_size = (size - 1 > size_y) ? size_y : size - 1;
+
+			for (i = mid_y - limited_size; i <= mid_y + limited_size; i++) {
+				TEST_POINT(mid_x - size, i);
+				TEST_POINT(mid_x + size, i);
+			}
+		}
+	}
+
+	return -1;
+}
+
+#undef TEST_POINT
+
+} // End of namespace Sci
+
+// Now include the actual filling code (with scaling support)
+#define FILL_FUNCTION _gfxr_fill_any
+#define FILL_FUNCTION_RECURSIVE _gfxr_fill_any_recursive
+#define AUXBUF_FILL_HELPER _gfxr_auxbuf_fill_any_recursive
+#define AUXBUF_FILL _gfxr_auxbuf_fill_any
+#define DRAW_SCALED
+# include "picfill.cpp"
+#undef DRAW_SCALED
+#undef AUXBUF_FILL
+#undef AUXBUF_FILL_HELPER
+#undef FILL_FUNCTION_RECURSIVE
+#undef FILL_FUNCTION
+
+namespace Sci {
+
+#endif // defined(WITH_PIC_SCALING)
+
+} // End of namespace Sci
+
+// Include again, but this time without support for scaling
+#define FILL_FUNCTION _gfxr_fill_1
+#define FILL_FUNCTION_RECURSIVE _gfxr_fill_1_recursive
+#define AUXBUF_FILL_HELPER _gfxr_auxbuf_fill_1_recursive
+#define AUXBUF_FILL _gfxr_auxbuf_fill_1
+# include "picfill.cpp"
+#undef AUXBUF_FILL
+#undef AUXBUF_FILL_HELPER
+#undef FILL_FUNCTION_RECURSIVE
+#undef FILL_FUNCTION
+
+namespace Sci {
+
+#define GET_ABS_COORDS(x, y) \
+	temp = *(resource + pos++); \
+	x = *(resource + pos++); \
+	y = *(resource + pos++); \
+	x |= (temp & 0xf0) << 4; \
+	y |= (temp & 0x0f) << 8;
+
+#define GET_REL_COORDS(x, y) \
+	temp = *(resource + pos++); \
+	if (temp & 0x80) \
+		x -= ((temp >> 4) & 0x7); \
+	else \
+		x += (temp >> 4); \
+	\
+	if (temp & 0x08) \
+		y -= (temp & 0x7); \
+	else \
+		y += (temp & 0x7);
+
+#define GET_MEDREL_COORDS(oldx, oldy) \
+	temp = *(resource + pos++); \
+	if (temp & 0x80) \
+		y = oldy - (temp & 0x7f); \
+	else \
+		y = oldy + temp; \
+	x = oldx + *((signed char *) resource + pos++);
+
+
+static void check_and_remove_artifact(byte *dest, byte* srcp, int legalcolor, byte l, byte r, byte u, byte d) {
+	if (*dest == legalcolor) {
+		if (*srcp == legalcolor)
+			return;
+		if (l) {
+			if (srcp[-1] == legalcolor)
+				return;
+			if (u && srcp[-320 - 1] == legalcolor)
+				return;
+			if (d && srcp[320 - 1] == legalcolor)
+				return;
+		}
+		if (r) {
+			if (srcp[1] == legalcolor)
+				return;
+			if (u && srcp[-320 + 1] == legalcolor)
+				return;
+			if (d && srcp[320 + 1] == legalcolor)
+				return;
+		}
+
+		if (u && srcp[-320] == legalcolor)
+			return;
+
+		if (d && srcp[-320] == legalcolor)
+			return;
+
+		*dest = *srcp;
+	}
+}
+
+void gfxr_remove_artifacts_pic0(gfxr_pic_t *dest, gfxr_pic_t *src) {
+	int x_320, y_200;
+	int bound_x = dest->mode->xfact;
+	int bound_y = dest->mode->yfact;
+	int scaled_line_size = bound_x * 320;
+	int read_offset = 0;
+
+	assert(src->mode->xfact == 1);
+	assert(src->mode->yfact == 1);
+
+	if (bound_x == 1 && bound_y == 1) {
+		GFXWARN("attempt to remove artifacts from unscaled pic!\n");
+		return;
+	}
+
+	for (y_200 = 0; y_200 < 200; y_200++) {
+		for (x_320 = 0; x_320 < 320; x_320++) {
+			int write_offset = (y_200 * bound_y * scaled_line_size) + (x_320 * bound_x);
+			int sub_x, sub_y;
+			byte *src_visualp = &(src->visual_map->index_data[read_offset]);
+			byte *src_priorityp = &(src->priority_map->index_data[read_offset]);
+
+			for (sub_y = 0; sub_y < bound_y; sub_y++) {
+				for (sub_x = 0; sub_x < bound_x; sub_x++) {
+					check_and_remove_artifact(dest->visual_map->index_data + write_offset, src_visualp, (int)0xff,
+					                          (byte)x_320, (byte)(x_320 < 319), (byte)(y_200 > 10), (byte)(y_200 < 199));
+					check_and_remove_artifact(dest->priority_map->index_data + write_offset, src_priorityp, 0,
+					                          (byte)x_320, (byte)(x_320 < 319), (byte)(y_200 > 10), (byte)(y_200 < 199));
+					++write_offset;
+				}
+				write_offset += scaled_line_size - bound_x;
+			}
+			++read_offset;
+		}
+	}
+
+}
+
+static void view_transparentize(gfx_pixmap_t *view, gfx_pixmap_t *background, int posx, int posy, int width, int height) {
+	int i, j;
+	byte *pic_index_data = background->index_data;
+
+	// FIXME: this assumes view and background have the same palette...
+	// We may want to do a reverse mapping or similar to make it general,
+	// but this (hopefully...) suffices for the current uses of this function.
+
+	for (i = 0;i < width;i++)
+		for (j = 0;j < height;j++) {
+			if (view->index_data[j*width+i] == view->color_key) {
+				view->index_data[j*width+i] = pic_index_data[(j+posy)*width+i+posx];
+			}
+		}
+}
+
+extern gfx_pixmap_t *gfxr_draw_cel0(int id, int loop, int cel, byte *resource, int size, gfxr_view_t *view, int mirrored);
+extern gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *resource, int size, gfxr_view_t *view, int amiga_game);
+extern void _gfx_crossblit_simple(byte *dest, byte *src, int dest_line_width, int src_line_width, int xl, int yl, int bpp);
+
+void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, byte *resource,
+					 gfxr_pic0_params_t *style, int resid, int sci1, Palette *static_pal) {
+	const int default_palette_table[GFXR_PIC0_PALETTE_SIZE] = {
+		0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+		0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88,
+		0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x88,
+		0x88, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+		0x08, 0x91, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x88
+	};
+
+	const int default_priority_table[GFXR_PIC0_PALETTE_SIZE] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+	};
+	int palette[GFXR_PIC0_NUM_PALETTES][GFXR_PIC0_PALETTE_SIZE];
+	int priority_table[GFXR_PIC0_PALETTE_SIZE];
+	int drawenable = GFX_MASK_VISUAL | GFX_MASK_PRIORITY;
+	int priority = 0;
+	int color = 0;
+	int pattern_nr = 0;
+	int pattern_code = 0;
+	int pattern_size = 0;
+	int control = 0;
+	int pos = 0;
+	int x, y;
+	int oldx, oldy;
+	int pal, index;
+	int temp;
+	int line_mode = style->line_mode;
+	int sci_titlebar_size = style->pic_port_bounds.y;
+	byte op, opx;
+
+#ifdef FILL_RECURSIVE_DEBUG
+	fillmagc = atoi(getenv("FOO"));
+	fillc = atoi(getenv("FOO2"));
+#endif
+
+	// Initialize palette
+	for (int i = 0; i < GFXR_PIC0_NUM_PALETTES; i++)
+		memcpy(palette[i], default_palette_table, sizeof(int) * GFXR_PIC0_PALETTE_SIZE);
+
+	memcpy(priority_table, default_priority_table, sizeof(int) * GFXR_PIC0_PALETTE_SIZE);
+
+	// Main loop
+	while (pos < size) {
+		op = *(resource + pos++);
+
+		switch (op) {
+
+		case PIC_OP_SET_COLOR:
+			p0printf("Set color @%d\n", pos);
+
+			if (!sci1) {
+				pal = *(resource + pos++);
+				index = pal % GFXR_PIC0_PALETTE_SIZE;
+				pal /= GFXR_PIC0_PALETTE_SIZE;
+
+				pal += default_palette;
+
+				if (pal >= GFXR_PIC0_NUM_PALETTES) {
+					GFXERROR("Attempt to access invalid palette %d\n", pal);
+					return;
+				}
+
+				color = palette[pal][index];
+			} else
+				color = *(resource + pos++);
+			p0printf("  color <- %02x [%d/%d]\n", color, pal, index);
+			drawenable |= GFX_MASK_VISUAL;
+			goto end_op_loop;
+
+		case PIC_OP_DISABLE_VISUAL:
+			p0printf("Disable visual @%d\n", pos);
+			drawenable &= ~GFX_MASK_VISUAL;
+			goto end_op_loop;
+
+		case PIC_OP_SET_PRIORITY:
+			p0printf("Set priority @%d\n", pos);
+
+			if (!sci1) {
+				pal = *(resource + pos++);
+				index = pal % GFXR_PIC0_PALETTE_SIZE;
+				pal /= GFXR_PIC0_PALETTE_SIZE; // Ignore pal
+
+				priority = priority_table[index];
+			} else priority = *(resource + pos++);
+
+			p0printf("  priority <- %d [%d/%d]\n", priority, pal, index);
+			drawenable |= GFX_MASK_PRIORITY;
+			goto end_op_loop;
+
+		case PIC_OP_DISABLE_PRIORITY:
+			p0printf("Disable priority @%d\n", pos);
+			drawenable &= ~GFX_MASK_PRIORITY;
+			goto end_op_loop;
+
+		case PIC_OP_SHORT_PATTERNS:
+			p0printf("Short patterns @%d\n", pos);
+			if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+				pattern_nr = ((*(resource + pos++)) >> 1) & 0x7f;
+				p0printf("  pattern_nr <- %d\n", pattern_nr);
+			}
+
+			GET_ABS_COORDS(x, y);
+
+			_gfxr_draw_pattern(pic, x, y, color, priority, control, drawenable, pattern_code,
+			                   pattern_size, pattern_nr, style->brush_mode, sci_titlebar_size);
+
+			while (*(resource + pos) < PIC_OP_FIRST) {
+				if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+					pattern_nr = ((*(resource + pos++)) >> 1) & 0x7f;
+					p0printf("  pattern_nr <- %d\n", pattern_nr);
+				}
+
+				GET_REL_COORDS(x, y);
+
+				_gfxr_draw_pattern(pic, x, y, color, priority, control, drawenable, pattern_code,
+				                   pattern_size, pattern_nr, style->brush_mode, sci_titlebar_size);
+			}
+			goto end_op_loop;
+
+		case PIC_OP_MEDIUM_LINES:
+			p0printf("Medium lines @%d\n", pos);
+			GET_ABS_COORDS(oldx, oldy);
+			while (*(resource + pos) < PIC_OP_FIRST) {
+#if 0
+				fprintf(stderr, "Medium-line: [%04x] from %d,%d, data %02x %02x (dx=%d)", pos, oldx, oldy,
+				        0xff & resource[pos], 0xff & resource[pos+1], *((signed char *) resource + pos + 1));
+#endif
+				GET_MEDREL_COORDS(oldx, oldy);
+#if 0
+				fprintf(stderr, " to %d,%d\n", x, y);
+#endif
+				_gfxr_draw_line(pic, oldx, oldy, x, y, color, priority, control, drawenable, line_mode,
+				                PIC_OP_MEDIUM_LINES, sci_titlebar_size);
+				oldx = x;
+				oldy = y;
+			}
+			goto end_op_loop;
+
+		case PIC_OP_LONG_LINES:
+			p0printf("Long lines @%d\n", pos);
+			GET_ABS_COORDS(oldx, oldy);
+			while (*(resource + pos) < PIC_OP_FIRST) {
+				GET_ABS_COORDS(x, y);
+				_gfxr_draw_line(pic, oldx, oldy, x, y, color, priority, control, drawenable, line_mode,
+				                PIC_OP_LONG_LINES, sci_titlebar_size);
+				oldx = x;
+				oldy = y;
+			}
+			goto end_op_loop;
+
+		case PIC_OP_SHORT_LINES:
+			p0printf("Short lines @%d\n", pos);
+			GET_ABS_COORDS(oldx, oldy);
+			x = oldx;
+			y = oldy;
+			while (*(resource + pos) < PIC_OP_FIRST) {
+				GET_REL_COORDS(x, y);
+				_gfxr_draw_line(pic, oldx, oldy, x, y, color, priority, control, drawenable, line_mode,
+				                PIC_OP_SHORT_LINES, sci_titlebar_size);
+				oldx = x;
+				oldy = y;
+			}
+			goto end_op_loop;
+
+		case PIC_OP_FILL:
+			p0printf("Fill @%d\n", pos);
+			while (*(resource + pos) < PIC_OP_FIRST) {
+				//fprintf(stderr,"####################\n");
+				GET_ABS_COORDS(x, y);
+				p0printf("Abs coords %d,%d\n", x, y);
+				//fprintf(stderr,"C=(%d,%d)\n", x, y + sci_titlebar_size);
+#ifdef WITH_PIC_SCALING
+				if (pic->mode->xfact > 1 || pic->mode->yfact > 1)
+					_gfxr_fill_any(pic, x, y + sci_titlebar_size, (flags & DRAWPIC01_FLAG_FILL_NORMALLY) ?
+					               color : 0, priority, control, drawenable, sci_titlebar_size);
+
+				else
+#endif
+					_gfxr_fill_1(pic, x, y + sci_titlebar_size, (flags & DRAWPIC01_FLAG_FILL_NORMALLY) ?
+					             color : 0, priority, control, drawenable, sci_titlebar_size);
+
+#ifdef FILL_RECURSIVE_DEBUG
+				if (!fillmagc) {
+					int x, y;
+					if (getenv("FOO1"))
+						for (x = 0; x < 320; x++)
+							for (y = 0; y < 200; y++) {
+								int aux = pic->aux_map[x + y*320];
+								int pix = (aux & 0xf);
+								int i;
+
+								if (aux & 0x40) {
+									if (x == 0 || !(pic->aux_map[x-1 + y * 320] & 0x40))
+										for (i = 0; i < pic->mode->yfact; i++)
+											pic->visual_map->index_data[(x + ((y*pic->mode->yfact)+i)*320) * pic->mode->xfact] ^= 0xff;
+
+									if (x == 319 || !(pic->aux_map[x+1 + y * 320] & 0x40))
+										for (i = 0; i < pic->mode->yfact; i++)
+											pic->visual_map->index_data[pic->mode->xfact - 1 +(x + ((y*pic->mode->yfact)+i)*320) * pic->mode->xfact] ^= 0xff;
+
+									if (y == 0 || !(pic->aux_map[x + (y-1) * 320] & 0x40))
+										for (i = 0; i < pic->mode->yfact; i++)
+											pic->visual_map->index_data[i+(x + ((y*pic->mode->yfact))*320) * pic->mode->xfact] ^= 0xff;
+
+									if (y == 199 || !(pic->aux_map[x + (y+1) * 320] & 0x40))
+										for (i = 0; i < pic->mode->yfact; i++)
+											pic->visual_map->index_data[i+(x + ((y*pic->mode->yfact)+pic->mode->yfact - 1)*320) * pic->mode->xfact] ^= 0xff;
+								}
+
+								pix |= (aux & 0x40) >> 4;
+								pix |= (pix << 4);
+
+								pic->visual_map->index_data[x + y*320*pic->mode->xfact] = pix;
+							}
+					return;
+				}
+				--fillmagc;
+#endif // GFXR_DEBUG_PIC0
+			}
+			goto end_op_loop;
+
+		case PIC_OP_SET_PATTERN:
+			p0printf("Set pattern @%d\n", pos);
+			pattern_code = (*(resource + pos++));
+			pattern_size = pattern_code & 0x07;
+			goto end_op_loop;
+
+		case PIC_OP_ABSOLUTE_PATTERN:
+			p0printf("Absolute pattern @%d\n", pos);
+			while (*(resource + pos) < PIC_OP_FIRST) {
+				if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+					pattern_nr = ((*(resource + pos++)) >> 1) & 0x7f;
+					p0printf("  pattern_nr <- %d\n", pattern_nr);
+				}
+
+				GET_ABS_COORDS(x, y);
+
+				_gfxr_draw_pattern(pic, x, y, color, priority, control, drawenable, pattern_code,
+				                   pattern_size, pattern_nr, style->brush_mode, sci_titlebar_size);
+			}
+			goto end_op_loop;
+
+		case PIC_OP_SET_CONTROL:
+			p0printf("Set control @%d\n", pos);
+			control = (*(resource + pos++)) & 0xf;
+			drawenable |= GFX_MASK_CONTROL;
+			goto end_op_loop;
+
+
+		case PIC_OP_DISABLE_CONTROL:
+			p0printf("Disable control @%d\n", pos);
+			drawenable &= ~GFX_MASK_CONTROL;
+			goto end_op_loop;
+
+
+		case PIC_OP_MEDIUM_PATTERNS:
+			p0printf("Medium patterns @%d\n", pos);
+			if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+				pattern_nr = ((*(resource + pos++)) >> 1) & 0x7f;
+				p0printf("  pattern_nr <- %d\n", pattern_nr);
+			}
+
+			GET_ABS_COORDS(oldx, oldy);
+
+			_gfxr_draw_pattern(pic, oldx, oldy, color, priority, control, drawenable, pattern_code,
+			                   pattern_size, pattern_nr, style->brush_mode, sci_titlebar_size);
+
+			x = oldx;
+			y = oldy;
+			while (*(resource + pos) < PIC_OP_FIRST) {
+				if (pattern_code & PATTERN_FLAG_USE_PATTERN) {
+					pattern_nr = ((*(resource + pos++)) >> 1) & 0x7f;
+					p0printf("  pattern_nr <- %d\n", pattern_nr);
+				}
+
+				GET_MEDREL_COORDS(x, y);
+
+				_gfxr_draw_pattern(pic, x, y, color, priority, control, drawenable, pattern_code,
+				                   pattern_size, pattern_nr, style->brush_mode, sci_titlebar_size);
+			}
+			goto end_op_loop;
+
+		case PIC_OP_OPX:
+			opx = *(resource + pos++);
+			p0printf("OPX: ");
+
+			if (sci1)
+				opx += SCI1_OP_OFFSET; // See comment at the definition of SCI1_OP_OFFSET.
+
+			switch (opx) {
+

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list