aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/gfx/resource
diff options
context:
space:
mode:
authorJordi Vilalta Prat2009-02-15 06:10:59 +0000
committerJordi Vilalta Prat2009-02-15 06:10:59 +0000
commitfa6e10e9cec163845aa29e7940c86e9c9ab8a2bc (patch)
treece87338830cc8c149e1de545246bcefe4f45da00 /engines/sci/gfx/resource
parent7c148ddf021c990fa866b7600f979aac9a5b26c9 (diff)
downloadscummvm-rg350-fa6e10e9cec163845aa29e7940c86e9c9ab8a2bc.tar.gz
scummvm-rg350-fa6e10e9cec163845aa29e7940c86e9c9ab8a2bc.tar.bz2
scummvm-rg350-fa6e10e9cec163845aa29e7940c86e9c9ab8a2bc.zip
Import the SCI engine sources from the FreeSCI Glutton branch (it doesn't compile yet)
svn-id: r38192
Diffstat (limited to 'engines/sci/gfx/resource')
-rw-r--r--engines/sci/gfx/resource/Makefile.am7
-rw-r--r--engines/sci/gfx/resource/sci_cursor_0.c107
-rw-r--r--engines/sci/gfx/resource/sci_font.c153
-rw-r--r--engines/sci/gfx/resource/sci_pal_1.c178
-rw-r--r--engines/sci/gfx/resource/sci_pic_0.c2023
-rw-r--r--engines/sci/gfx/resource/sci_picfill.c429
-rw-r--r--engines/sci/gfx/resource/sci_picfill_aux.c205
-rw-r--r--engines/sci/gfx/resource/sci_resmgr.c341
-rw-r--r--engines/sci/gfx/resource/sci_view_0.c254
-rw-r--r--engines/sci/gfx/resource/sci_view_1.c554
10 files changed, 4251 insertions, 0 deletions
diff --git a/engines/sci/gfx/resource/Makefile.am b/engines/sci/gfx/resource/Makefile.am
new file mode 100644
index 0000000000..4a943e67f0
--- /dev/null
+++ b/engines/sci/gfx/resource/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_srcdir)/src/include @EXTRA_INCLUDES@
+LDADD = $(LDADD_ALL)
+EXTRA_DIST = sci_picfill.c sci_picfill_aux.c
+
+noinst_LIBRARIES = libsciresources.a
+libsciresources_a_SOURCES = sci_font.c sci_resmgr.c sci_pic_0.c sci_view_0.c sci_cursor_0.c sci_pal_1.c \
+ sci_view_1.c
diff --git a/engines/sci/gfx/resource/sci_cursor_0.c b/engines/sci/gfx/resource/sci_cursor_0.c
new file mode 100644
index 0000000000..18960516c3
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_cursor_0.c
@@ -0,0 +1,107 @@
+/***************************************************************************
+ cursor_0.c Copyright (C) 2000 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+
+#include <gfx_system.h>
+#include <gfx_resource.h>
+#include <gfx_tools.h>
+
+
+#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}};
+
+
+static gfx_pixmap_t *
+_gfxr_draw_cursor(int id, byte *resource, int size, int sci01)
+{
+ int colors[4] = {0, 1, GFX_CURSOR_TRANSPARENT, 1};
+ int line;
+ byte *data;
+ gfx_pixmap_t *retval;
+
+ if (sci01)
+ 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));
+ retval->colors = gfx_sci01_cursor_colors;
+ retval->colors_nr = sci01? GFX_SCI01_CURSOR_COLORS_NR : GFX_SCI0_CURSOR_COLORS_NR;
+ retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ retval->color_key = GFX_CURSOR_TRANSPARENT;
+
+ if (sci01) {
+ retval->xoffset = get_int_16(resource);
+ retval->yoffset = get_int_16(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 = get_int_16(resource + (line << 1));
+ int mask_b = get_int_16(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;
+}
+
+
+gfx_pixmap_t *
+gfxr_draw_cursor0(int id, byte *resource, int size)
+{
+ return _gfxr_draw_cursor(id, resource, size, 0);
+}
+
+gfx_pixmap_t *
+gfxr_draw_cursor01(int id, byte *resource, int size)
+{
+ return _gfxr_draw_cursor(id, resource, size, 1);
+}
+
diff --git a/engines/sci/gfx/resource/sci_font.c b/engines/sci/gfx/resource/sci_font.c
new file mode 100644
index 0000000000..5bdb3be1a1
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_font.c
@@ -0,0 +1,153 @@
+/***************************************************************************
+ sci_font.c Copyright (C) 2000 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+
+#include <sci_memory.h>
+#include <gfx_system.h>
+#include <gfx_resource.h>
+#include <gfx_tools.h>
+
+
+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 = get_int_16(resource + FONT_MAXCHAR_OFFSET);
+ font->line_height = max_height = get_int_16(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 = get_int_16(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 = get_int_16(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;
+}
+
+
diff --git a/engines/sci/gfx/resource/sci_pal_1.c b/engines/sci/gfx/resource/sci_pal_1.c
new file mode 100644
index 0000000000..72adb7b02a
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_pal_1.c
@@ -0,0 +1,178 @@
+/***************************************************************************
+ pal_1.c Copyright (C) 2000 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+/* SCI1 palette resource defrobnicator */
+
+#include <sci_memory.h>
+#include <gfx_system.h>
+#include <gfx_resource.h>
+
+#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
+
+gfx_pixmap_color_t *
+gfxr_read_pal11(int id, int *colors_nr, byte *resource, int size)
+{
+ int start_color = resource[25];
+ int format = resource[32];
+ int entry_size;
+ gfx_pixmap_color_t *retval;
+ byte *pal_data = resource + 37;
+ int _colors_nr = *colors_nr = getUInt16(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 = (gfx_pixmap_color_t *)
+ sci_malloc(sizeof(gfx_pixmap_color_t) * (_colors_nr + start_color));
+ memset(retval, 0, sizeof(gfx_pixmap_color_t) * (_colors_nr + start_color));
+
+ for (i = 0; i < start_color; i ++)
+ {
+ retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
+ retval[i].r = 0;
+ retval[i].g = 0;
+ retval[i].b = 0;
+ }
+ for (i = start_color; i < start_color + _colors_nr; i ++)
+ {
+ switch (format)
+ {
+ case SCI_PAL_FORMAT_CONSTANT_FLAGS:
+ retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
+ retval[i].r = pal_data[0];
+ retval[i].g = pal_data[1];
+ retval[i].b = pal_data[2];
+ break;
+ case SCI_PAL_FORMAT_VARIABLE_FLAGS:
+ retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
+ retval[i].r = pal_data[1];
+ retval[i].g = pal_data[2];
+ retval[i].b = pal_data[3];
+ break;
+ }
+ pal_data += entry_size;
+ }
+
+ return retval;
+}
+
+gfx_pixmap_color_t *
+gfxr_read_pal1(int id, int *colors_nr, byte *resource, int size)
+{
+ int counter = 0;
+ int pos;
+ unsigned int colors[MAX_COLORS] = {0};
+ gfx_pixmap_color_t *retval;
+
+ 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;
+ }
+
+ retval = (gfx_pixmap_color_t*)sci_malloc(sizeof(gfx_pixmap_color_t) * counter);
+#ifdef SATISFY_PURIFY
+ memset(retval, 0, sizeof(gfx_pixmap_color_t) * counter);
+#endif
+
+ *colors_nr = counter;
+ for (pos = 0; pos < counter; pos++) {
+ unsigned int color = colors[pos];
+
+ retval[pos].global_index = GFX_COLOR_INDEX_UNMAPPED;
+ retval[pos].r = (color >> 8) & 0xff;
+ retval[pos].g = (color >> 16) & 0xff;
+ retval[pos].b = (color >> 24) & 0xff;
+ }
+
+ return retval;
+}
+
+gfx_pixmap_color_t *
+gfxr_read_pal1_amiga(int *colors_nr, FILE *f)
+{
+ int i;
+ gfx_pixmap_color_t *retval;
+
+ retval = (gfx_pixmap_color_t*)sci_malloc(sizeof(gfx_pixmap_color_t) * 32);
+
+ for (i = 0; i < 32; i++) {
+ int b1, b2;
+
+ b1 = fgetc(f);
+ b2 = fgetc(f);
+
+ if (b1 == EOF || b2 == EOF) {
+ GFXERROR("Palette file ends prematurely\n");
+ return NULL;
+ }
+
+ retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
+ retval[i].r = (b1 & 0xf) * 0x11;
+ retval[i].g = ((b2 & 0xf0) >> 4) * 0x11;
+ retval[i].b = (b2 & 0xf) * 0x11;
+ }
+
+ *colors_nr = 32;
+ return retval;
+}
+
diff --git a/engines/sci/gfx/resource/sci_pic_0.c b/engines/sci/gfx/resource/sci_pic_0.c
new file mode 100644
index 0000000000..63130b53f4
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_pic_0.c
@@ -0,0 +1,2023 @@
+/***************************************************************************
+ sci_pic_0.c Copyright (C) 2000 Christoph Reichenbach
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+
+#include <sci_memory.h>
+#include <assert.h>
+#include <math.h>
+#include <time.h>
+#include <gfx_resource.h>
+#include <gfx_tools.h>
+
+#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 SCI_PIC0_MAX_FILL 30 /* Number of times to fill before yielding to scheduler */
+
+#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
+
+gfx_pixmap_color_t gfx_sci0_pic_colors[GFX_SCI0_PIC_COLORS_NR]; /* Initialized during initialization */
+
+static int _gfxr_pic0_colors_initialized = 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()
+{
+ int i;
+
+ if (!_gfxr_pic0_colors_initialized) {
+ for (i = 0; i < 256; i++) {
+ gfx_sci0_pic_colors[i].global_index = GFX_COLOR_INDEX_UNMAPPED;
+ gfx_sci0_pic_colors[i].r = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].r,
+ gfx_sci0_image_colors[sci0_palette][i >> 4].r);
+ gfx_sci0_pic_colors[i].g = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].g,
+ gfx_sci0_image_colors[sci0_palette][i >> 4].g);
+ gfx_sci0_pic_colors[i].b = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].b,
+ gfx_sci0_image_colors[sci0_palette][i >> 4].b);
+ }
+ WARNING("Uncomment me after fixing sci0_palette changes to reset me");
+ /* _gfxr_pic0_colors_initialized = 1; */
+ }
+}
+
+
+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));
+ pic->visual_map->colors = gfx_sci0_pic_colors;
+ pic->visual_map->colors_nr = GFX_SCI0_PIC_COLORS_NR;
+ pic->visual_map->color_key = GFX_PIXMAP_COLOR_KEY_NONE;
+
+ pic->visual_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ pic->priority_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ pic->control_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ 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->colors = gfx_sci0_image_colors[sci0_palette];
+ pic->priority_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+ pic->control_map->colors = gfx_sci0_image_colors[sci0_palette];
+ pic->control_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+
+ /* Initialize colors */
+ if (!sci1) {
+ pic->ID = ID;
+ gfxr_init_static_palette();
+ }
+
+ pic->undithered_buffer_size = pic->visual_map->index_xl * pic->visual_map->index_yl;
+ pic->undithered_buffer = NULL;
+ pic->internal = 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.xl;
+ dy = line.yl;
+ 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;
+ int color2 = color;
+
+ dx = line.xl;
+ dy = line.yl;
+ 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));
+ int i;
+
+ if (sizeof(unsigned long) == 8) { /* UltraSparc, Alpha, newer MIPSens, etc */
+ andmask |= (andmask << 32);
+ clearmask |= (clearmask << 32);
+ }
+
+ for (i = 0; i < GFXR_AUX_MAP_SIZE / sizeof(unsigned long); i++) {
+ unsigned long temp = *data & andmask;
+ temp >>= 3;
+ *data = (temp | *data) & clearmask;
+ ++data;
+ }
+}
+#endif
+
+
+static inline void
+_gfxr_auxbuf_tag_line(gfxr_pic_t *pic, int pos, int width)
+{
+ int i;
+ for (i = 0; i < width; i++)
+ pic->aux_map[i+pos] |= FRESH_PAINT;
+}
+
+
+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].xl = 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].xl > xr+1)
+ done = 1;
+
+ else if (intervals[!ivi][i].xr < xl-1) {
+ int o_xl = intervals[!ivi][i].xl;
+ 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].xl;
+ 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].xl <= 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].xl, 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)++;
+}
+
+
+
+/*** 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
+#define p0printf if (0)
+#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 inline 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); /* Ouch! */
+
+ _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); /* Ouch! */
+ 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.xl = ((xsize + 1) << 1) + 1;
+ boundaries.yl = (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 inline void
+_gfxr_draw_subline(gfxr_pic_t *pic, int x, int y, int ex, int ey, int color, int priority, int drawenable)
+{
+ point_t start;
+ point_t end;
+
+ start.x = x;
+ start.y = y;
+ end.x = ex;
+ end.y = ey;
+
+ if (ex >= pic->visual_map->index_xl || ey >= pic->visual_map->index_yl || x < 0 || y < 0) {
+ fprintf(stderr,"While drawing pic0: INVALID LINE %d,%d,%d,%d\n",
+ GFX_PRINT_POINT(start), GFX_PRINT_POINT(end));
+ 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.xl = ex - x;
+ line.yl = 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, gfx_point(x, y), gfx_point(x + line.xl, y + line.yl), 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.xl = scale_x;
+ drawrect.yl = 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 inline int /* returns -1 on failure, 0 on success */
+_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)
+{
+ 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
+
+/* 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 "sci_picfill_aux.c"
+# include "sci_picfill.c"
+#undef DRAW_SCALED
+#undef AUXBUF_FILL
+#undef AUXBUF_FILL_HELPER
+#undef FILL_FUNCTION_RECURSIVE
+#undef FILL_FUNCTION
+
+#endif /* defined(WITH_PIC_SCALING) */
+
+/* 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 "sci_picfill_aux.c"
+# include "sci_picfill.c"
+#undef AUXBUF_FILL
+#undef AUXBUF_FILL_HELPER
+#undef FILL_FUNCTION_RECURSIVE
+#undef FILL_FUNCTION
+
+
+#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++);
+
+
+inline 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) {
+ /* D'Oh! */
+ 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, byte *pic_index_data,
+ int posx, int posy,
+ int width, int height)
+{
+ int i,j;
+
+ 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,
+ gfx_pixmap_color_t *static_pal, int static_pal_nr)
+{
+ 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 i;
+ 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;
+ int fill_count = 0;
+ byte op, opx;
+
+#ifdef FILL_RECURSIVE_DEBUG
+ fillmagc = atoi(getenv("FOO"));
+ fillc = atoi(getenv("FOO2"));
+#endif /* FILL_RECURSIVE_DEBUG */
+
+ /* Initialize palette */
+ for (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);
+
+ if (fill_count++ > SCI_PIC0_MAX_FILL) {
+ sci_sched_yield();
+ fill_count = 0;
+ }
+
+#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) {
+
+ case PIC_SCI1_OPX_SET_PALETTE_ENTRIES:
+ GFXWARN("SCI1 Set palette entried not implemented\n");
+ goto end_op_loop;
+
+ case PIC_SCI0_OPX_SET_PALETTE_ENTRIES:
+ p0printf("Set palette entry @%d\n", pos);
+ while (*(resource + pos) < PIC_OP_FIRST) {
+ index = *(resource + pos++);
+ pal = index / GFXR_PIC0_PALETTE_SIZE;
+ index %= GFXR_PIC0_PALETTE_SIZE;
+
+ if (pal >= GFXR_PIC0_NUM_PALETTES) {
+ GFXERROR("Attempt to write to invalid palette %d\n", pal);
+ return;
+ }
+ palette[pal][index] = *(resource + pos++);
+ }
+ goto end_op_loop;
+
+
+ case PIC_SCI0_OPX_SET_PALETTE:
+ p0printf("Set palette @%d\n", pos);
+ pal = *(resource + pos++);
+ if (pal >= GFXR_PIC0_NUM_PALETTES) {
+ GFXERROR("Attempt to write to invalid palette %d\n", pal);
+ return;
+ }
+
+ p0printf(" palette[%d] <- (", pal);
+ for (index = 0; index < GFXR_PIC0_PALETTE_SIZE; index++) {
+ palette[pal][index] = *(resource + pos++);
+ if (index > 0)
+ p0printf(",");
+ if (!(index & 0x7))
+ p0printf("[%d]=", index);
+ p0printf("%02x", palette[pal][index]);
+ }
+ p0printf(")\n");
+ goto end_op_loop;
+
+ case PIC_SCI1_OPX_SET_PALETTE:
+ p0printf("Set palette @%d\n", pos);
+ pic->visual_map->flags &= ~GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ pic->visual_map->colors = gfxr_read_pal1(resid, &pic->visual_map->colors_nr,
+ resource+pos, SCI1_PALETTE_SIZE);
+ pos += SCI1_PALETTE_SIZE;
+ goto end_op_loop;
+
+ case PIC_SCI0_OPX_MONO0:
+ p0printf("Monochrome opx 0 @%d\n", pos);
+ pos += 41;
+ goto end_op_loop;
+
+
+ case PIC_SCI0_OPX_MONO1:
+ case PIC_SCI0_OPX_MONO3:
+ ++pos;
+ p0printf("Monochrome opx %d @%d\n", opx, pos);
+ goto end_op_loop;
+
+
+ case PIC_SCI0_OPX_MONO2:
+ case PIC_SCI0_OPX_MONO4: /* Monochrome ops: Ignored by us */
+ p0printf("Monochrome opx %d @%d\n", opx, pos);
+ goto end_op_loop;
+
+
+ case PIC_SCI0_OPX_EMBEDDED_VIEW:
+ case PIC_SCI1_OPX_EMBEDDED_VIEW:
+ {
+ int posx, posy;
+ int bytesize;
+/* byte *vismap = pic->visual_map->index_data; */
+ int nodraw = 0;
+
+ gfx_pixmap_t *view;
+ gfx_mode_t *mode;
+
+ p0printf("Embedded view @%d\n", pos);
+
+ /* Set up mode structure for resizing the view */
+ mode = gfx_new_mode(
+ pic->visual_map->index_xl/320,
+ pic->visual_map->index_yl/200,
+ 1, /* 1bpp, which handles masks and the rest for us */
+ 0, 0, 0, 0, 0, 0, 0, 0, 16, 0);
+
+ GET_ABS_COORDS(posx, posy);
+ bytesize = (*(resource + pos))+(*(resource + pos + 1) << 8);
+ p0printf("(%d, %d)\n", posx, posy);
+ pos += 2;
+ if (!sci1 && !nodraw)
+ view = gfxr_draw_cel0(-1,-1,-1, resource + pos, bytesize, NULL, 0);
+ else
+ view = gfxr_draw_cel1(-1,-1,-1, 0, resource + pos, bytesize, NULL,
+ static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR);
+ pos+=bytesize;
+ if (nodraw) continue;
+ p0printf("(%d, %d)-(%d, %d)\n",
+ posx,
+ posy,
+ posx + view->index_xl,
+ posy + view->index_yl);
+
+ /* we can only safely replace the palette if it's static
+ *if it's not for some reason, we should die
+ */
+ if (!(view->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE) && !sci1) {
+ sciprintf("gfx_draw_pic0(): can't set a non-static palette for an embedded view!\n");
+ }
+
+ /* For SCI0, use special color mapping to copy the low
+ ** nibble of the color index to the high
+ ** nibble.
+ */
+ if (sci1) {
+ if (static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR) {
+ /* Assume Amiga game */
+ pic->visual_map->colors = static_pal;
+ pic->visual_map->colors_nr = static_pal_nr;
+ pic->visual_map->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ }
+ view->colors = pic->visual_map->colors;
+ view->colors_nr = pic->visual_map->colors_nr;
+ } else
+ view->colors = embedded_view_colors;
+
+ /* Hack to prevent overflowing the visual map buffer.
+ Yes, this does happen otherwise. */
+ if (view->index_yl + sci_titlebar_size > 200)
+ sci_titlebar_size = 0;
+
+ gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE);
+
+ if (flags & DRAWPIC01_FLAG_OVERLAID_PIC)
+ view_transparentize(view, pic->visual_map->index_data,
+ posx, sci_titlebar_size+posy,
+ view->index_xl, view->index_yl);
+
+ _gfx_crossblit_simple(pic->visual_map->index_data+(sci_titlebar_size*320)+
+ posy*320+posx,
+ view->index_data,
+ pic->visual_map->index_xl, view->index_xl,
+ view->index_xl,
+ view->index_yl,
+ 1);
+
+ gfx_free_mode(mode);
+ gfx_free_pixmap(NULL, view);
+ }
+ goto end_op_loop;
+
+ case PIC_SCI0_OPX_SET_PRIORITY_TABLE:
+ case PIC_SCI1_OPX_PRIORITY_TABLE_EXPLICIT: {
+ int i;
+ int *pri_table;
+
+ p0printf("Explicit priority table @%d\n", pos);
+ if (!pic->internal)
+ {
+ pic->internal = sci_malloc(16 * sizeof(int));
+ } else
+ {
+ GFXERROR("pic->internal is not NULL (%08x); this only occurs with overlaid pics, otherwise it's a bug!\n", pic->internal);
+ }
+
+ pri_table = (int*)pic->internal;
+
+ pri_table[0] = 0;
+ pri_table[15] = 190;
+
+ for (i = 1; i < 15; i++)
+ pri_table[i] = resource[pos++];
+ }
+ goto end_op_loop;
+
+ case PIC_SCI1_OPX_PRIORITY_TABLE_EQDIST:
+ {
+ int first = getInt16(resource + pos);
+ int last = getInt16(resource + pos + 2);
+ int nr;
+ int *pri_table;
+
+ if (!pic->internal)
+ {
+ pic->internal = sci_malloc(16 * sizeof(int));
+ } else
+ {
+ GFXERROR("pic->internal is not NULL (%08x); possible memory corruption!\n", pic->internal);
+ }
+
+ pri_table = (int*)pic->internal;
+
+ for (nr = 0; nr < 16; nr ++)
+ pri_table[nr] = SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr);
+ pos += 4;
+ goto end_op_loop;
+ }
+
+ default: sciprintf("%s L%d: Warning: Unknown opx %02x\n", __FILE__, __LINE__, opx);
+ return;
+ }
+ goto end_op_loop;
+
+ case PIC_OP_TERMINATE:
+ p0printf("Terminator\n");
+ /* WARNING( "ARTIFACT REMOVAL CODE is commented out!") */
+ /* _gfxr_vismap_remove_artifacts(); */
+ return;
+
+ default: GFXWARN("Unknown op %02x\n", op);
+ return;
+ }
+end_op_loop:
+ {}
+ }
+
+ GFXWARN("Reached end of pic resource %04x\n", resid);
+}
+
+void
+gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size,
+ byte *resource, gfxr_pic0_params_t *style, int resid,
+ gfx_pixmap_color_t *static_pal, int static_pal_nr)
+{
+ int has_bitmap = getUInt16(resource + 4);
+ int vector_data_ptr = getUInt16(resource + 16);
+ int palette_data_ptr = getUInt16(resource + 28);
+ int bitmap_data_ptr = getUInt16(resource + 32);
+ int sci_titlebar_size = style->pic_port_bounds.y;
+ gfx_mode_t *mode;
+ gfx_pixmap_t *view = NULL;
+ /* Set up mode structure for resizing the view */
+ mode = gfx_new_mode(
+ pic->visual_map->index_xl/320,
+ pic->visual_map->index_yl/200,
+ 1, /* 1bpp, which handles masks and the rest for us */
+ 0, 0, 0, 0, 0, 0, 0, 0, 16, 0);
+
+ pic->visual_map->colors = gfxr_read_pal11(-1, &(pic->visual_map->colors_nr), resource + palette_data_ptr, 1284);
+
+ if (has_bitmap)
+ view = gfxr_draw_cel11(-1, 0, 0, 0, resource, resource + bitmap_data_ptr, size - bitmap_data_ptr, NULL);
+
+ if (view)
+ {
+ view->colors = pic->visual_map->colors;
+ view->colors_nr = pic->visual_map->colors_nr;
+
+ gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE);
+
+ if (flags & DRAWPIC01_FLAG_OVERLAID_PIC)
+ view_transparentize(view, pic->visual_map->index_data,
+ 0, 0,
+ view->index_xl, view->index_yl);
+
+ /* Hack to prevent overflowing the visual map buffer.
+ Yes, this does happen otherwise. */
+ if (view->index_yl + sci_titlebar_size > 200)
+ sci_titlebar_size = 0;
+
+ _gfx_crossblit_simple(pic->visual_map->index_data+sci_titlebar_size*view->index_xl,
+ view->index_data,
+ pic->visual_map->index_xl, view->index_xl,
+ view->index_xl,
+ view->index_yl,
+ 1);
+ } else
+ {
+ GFXWARN("No view was contained in SCI1.1 pic resource");
+ }
+
+
+
+ gfxr_draw_pic01(pic, flags, default_palette, size - vector_data_ptr,
+ resource + vector_data_ptr, style, resid, 1,
+ static_pal, static_pal_nr);
+}
+
+void
+gfxr_dither_pic0(gfxr_pic_t *pic, int dmode, int pattern)
+{
+ int xl = pic->visual_map->index_xl;
+ int yl = pic->visual_map->index_yl;
+ int xfrob_max = (pattern == GFXR_DITHER_PATTERN_1)? 1 : pic->mode->xfact;
+ int yfrob_max = (pattern == GFXR_DITHER_PATTERN_1)? 1 : pic->mode->yfact;
+ int xfrobc = 0, yfrobc = 0;
+ int selection = 0;
+ int x, y;
+ byte *data = pic->visual_map->index_data;
+
+ if (dmode == GFXR_DITHER_MODE_F256)
+ return; /* Nothing to do */
+
+ if (dmode == GFXR_DITHER_MODE_D16) { /* Limit to 16 colors */
+ pic->visual_map->colors = gfx_sci0_image_colors[sci0_palette];
+ pic->visual_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+ }
+
+ for (y = 0; y < yl; y++) {
+ for (x = 0; x < xl; x++) {
+
+ switch (dmode) {
+
+ case GFXR_DITHER_MODE_D16:
+ if (selection)
+ *data = (*data & 0xf0) >> 4;
+ else
+ *data = (*data & 0xf);
+ break;
+
+ case GFXR_DITHER_MODE_D256:
+ if (selection)
+ *data = ((*data & 0xf) << 4) | ((*data & 0xf0) >> 4);
+ break;
+
+ default:
+ GFXERROR("Invalid dither mode %d!\n", dmode);
+ return;
+ }
+
+ ++data;
+
+ if (++xfrobc == xfrob_max) {
+ selection = !selection;
+ xfrobc = 0;
+ }
+ }
+
+ if (++yfrobc == yfrob_max) {
+ selection = !selection;
+ yfrobc = 0;
+ }
+ }
+}
+
diff --git a/engines/sci/gfx/resource/sci_picfill.c b/engines/sci/gfx/resource/sci_picfill.c
new file mode 100644
index 0000000000..c7ecea08a7
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_picfill.c
@@ -0,0 +1,429 @@
+/***************************************************************************
+ Copyright (C) 2004 Christoph Reichenbach <reichenb@colorado.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public Licence as
+ published by the Free Software Foundaton; either version 2 of the
+ Licence, or (at your option) any later version.
+
+ It is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ merchantibility or fitness for a particular purpose. See the
+ GNU General Public Licence for more details.
+
+ You should have received a copy of the GNU General Public Licence
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+***************************************************************************/
+
+/* Generic pic filling code, to be included by sci_pic_0.c
+ *
+ *
+ * To use, define the following:
+ * 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.
+ *
+ */
+
+#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 /* defined(FILL_RECURSIVE_DEBUG) */
+
+ 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
+
+
+
diff --git a/engines/sci/gfx/resource/sci_picfill_aux.c b/engines/sci/gfx/resource/sci_picfill_aux.c
new file mode 100644
index 0000000000..70d8a822da
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_picfill_aux.c
@@ -0,0 +1,205 @@
+/***************************************************************************
+ Copyright (C) 2004 Christoph Reichenbach <reichenb@colorado.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public Licence as
+ published by the Free Software Foundaton; either version 2 of the
+ Licence, or (at your option) any later version.
+
+ It is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ merchantibility or fitness for a particular purpose. See the
+ GNU General Public Licence for more details.
+
+ You should have received a copy of the GNU General Public Licence
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+***************************************************************************/
+
+/* Generic pic auxbuf 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
+ *
+ * Define DRAW_SCALED to support scaled drawing, or leave it out for faster
+ * processing.
+ *
+ */
+
+#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
diff --git a/engines/sci/gfx/resource/sci_resmgr.c b/engines/sci/gfx/resource/sci_resmgr.c
new file mode 100644
index 0000000000..6475369230
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_resmgr.c
@@ -0,0 +1,341 @@
+/***************************************************************************
+ sci_resmgr.c Copyright (C) 2000 Christoph Reichenbach
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+/* The interpreter-specific part of the resource manager, for SCI */
+
+#include <sci_memory.h>
+#include <sciresource.h>
+#include <gfx_widgets.h>
+#include <gfx_resmgr.h>
+#include <gfx_options.h>
+
+int
+gfxr_interpreter_options_hash(gfx_resource_type_t type, int version,
+ gfx_options_t *options,
+ void *internal, int palette)
+{
+ switch (type) {
+
+ case GFX_RESOURCE_TYPE_VIEW:
+ return palette;
+
+ case GFX_RESOURCE_TYPE_PIC:
+ if (version >= SCI_VERSION_01_VGA)
+ return options->pic_port_bounds.y;
+ else
+ return (options->pic0_unscaled)? 0x10000 :
+ (options->pic0_dither_mode << 12)
+ | (options->pic0_dither_pattern << 8)
+ | (options->pic0_brush_mode << 4)
+ | (options->pic0_line_mode);
+
+ case GFX_RESOURCE_TYPE_FONT:
+ return 0;
+
+ case GFX_RESOURCE_TYPE_CURSOR:
+ return 0;
+
+ case GFX_RESOURCE_TYPES_NR:
+ default:
+ GFXERROR("Invalid resource type: %d\n", type);
+ return -1;
+ }
+}
+
+
+gfxr_pic_t *
+gfxr_interpreter_init_pic(int version, gfx_mode_t *mode, int ID, void *internal)
+{
+ return gfxr_init_pic(mode, ID, version >= SCI_VERSION_01_VGA);
+}
+
+
+void
+gfxr_interpreter_clear_pic(int version, gfxr_pic_t *pic, void *internal)
+{
+ gfxr_clear_pic0(pic, SCI_TITLEBAR_SIZE);
+}
+
+
+int
+gfxr_interpreter_calculate_pic(gfx_resstate_t *state, gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic,
+ int flags, int default_palette, int nr, void *internal)
+{
+ resource_mgr_t *resmgr = (resource_mgr_t *) state->misc_payload;
+ resource_t *res = scir_find_resource(resmgr, sci_pic, 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 (state->version >= SCI_VERSION_01_VGA) {
+ if (need_unscaled)
+ {
+ if (state->version == SCI_VERSION_1_1)
+ gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id,
+ state->static_palette, state->static_palette_entries);
+ else
+ gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 1,
+ state->static_palette, state->static_palette_entries);
+ }
+ 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)
+ gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id,
+ state->static_palette, state->static_palette_entries);
+ else
+ gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->version,
+ state->static_palette, state->static_palette_entries);
+ } else {
+ if (need_unscaled)
+ gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 0,
+ state->static_palette, state->static_palette_entries);
+
+ if (scaled_pic && scaled_pic->undithered_buffer)
+ memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size);
+
+ gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, 0,
+ state->static_palette, state->static_palette_entries);
+ 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;
+}
+
+
+void
+gfxr_palettize_view(gfxr_view_t *view, gfx_pixmap_color_t *source, int source_entries)
+{
+ int i;
+
+ for (i=0;i<MIN(view->colors_nr,source_entries);i++)
+ {
+ if ((view->colors[i].r == 0) &&
+ (view->colors[i].g == 0) &&
+ (view->colors[i].b == 0))
+ {
+ view->colors[i] = source[i];
+ }
+ }
+}
+
+gfxr_view_t *
+gfxr_draw_view11(int id, byte *resource, int size);
+
+gfxr_view_t *
+gfxr_interpreter_get_view(gfx_resstate_t *state, int nr, void *internal, int palette)
+{
+ resource_mgr_t *resmgr = (resource_mgr_t *) state->misc_payload;
+ resource_t *res = scir_find_resource(resmgr, sci_view, nr, 0);
+ int resid = GFXR_RES_ID(GFX_RESOURCE_TYPE_VIEW, nr);
+ gfxr_view_t *result;
+
+ if (!res || !res->data)
+ return NULL;
+
+ if (state->version < SCI_VERSION_01) palette=-1;
+
+ switch (state->version)
+ {
+ case SCI_VERSION_0:
+ case SCI_VERSION_01:
+ result=gfxr_draw_view0(resid, res->data, res->size, palette);
+ break;
+ case SCI_VERSION_01_VGA:
+ case SCI_VERSION_01_VGA_ODD:
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ result=gfxr_draw_view1(resid, res->data, res->size, state->static_palette, state->static_palette_entries);
+ break;
+ case SCI_VERSION_1_1:
+ case SCI_VERSION_32:
+ result=gfxr_draw_view11(resid, res->data, res->size);
+ break;
+ }
+
+ if (state->version >= SCI_VERSION_01_VGA)
+ {
+ if (!result->colors)
+ {
+ result->colors = (gfx_pixmap_color_t*)sci_malloc(sizeof(gfx_pixmap_color_t) * state->static_palette_entries);
+ memset(result->colors, 0, sizeof(gfx_pixmap_color_t) * state->static_palette_entries);
+ result->colors_nr = state->static_palette_entries;
+ }
+ gfxr_palettize_view(result, state->static_palette, state->static_palette_entries);
+ }
+ return result;
+}
+
+
+gfx_bitmap_font_t *
+gfxr_interpreter_get_font(gfx_resstate_t *state, int nr, void *internal)
+{
+ resource_mgr_t *resmgr = (resource_mgr_t *) state->misc_payload;
+ resource_t *res = scir_find_resource(resmgr, sci_font, nr, 0);
+ if (!res || !res->data)
+ return NULL;
+
+ return gfxr_read_font(res->id, res->data, res->size);
+}
+
+
+gfx_pixmap_t *
+gfxr_interpreter_get_cursor(gfx_resstate_t *state, int nr, void *internal)
+{
+ resource_mgr_t *resmgr = (resource_mgr_t *) state->misc_payload;
+ resource_t *res = scir_find_resource(resmgr, sci_cursor, nr, 0);
+ int resid = GFXR_RES_ID(GFX_RESOURCE_TYPE_CURSOR, nr);
+
+ if (!res || !res->data)
+ return NULL;
+
+ if (state->version >= SCI_VERSION_1_1) {
+ GFXWARN("Attempt to retreive cursor in SCI1.1 or later\n");
+ return NULL;
+ }
+
+ if (state->version == SCI_VERSION_0)
+ return gfxr_draw_cursor0(resid, res->data, res->size);
+ else
+ return gfxr_draw_cursor01(resid, res->data, res->size);
+}
+
+
+int *
+gfxr_interpreter_get_resources(gfx_resstate_t *state, gfx_resource_type_t type,
+ int version, int *entries_nr, void *internal)
+{
+ resource_mgr_t *resmgr = (resource_mgr_t *) state->misc_payload;
+ int restype;
+ int *resources;
+ int count = 0;
+ int top = sci_max_resource_nr[version] + 1;
+ int i;
+ switch (type) {
+
+ case GFX_RESOURCE_TYPE_VIEW: restype = sci_view;
+ break;
+
+ case GFX_RESOURCE_TYPE_PIC: restype = sci_pic;
+ break;
+
+ case GFX_RESOURCE_TYPE_CURSOR: restype = sci_cursor;
+ break;
+
+ case GFX_RESOURCE_TYPE_FONT: restype = sci_font;
+ break;
+
+ default:
+ GFX_DEBUG("Unsupported resource %d\n", type);
+ return NULL; /* unsupported resource */
+
+ }
+
+ resources = (int*)sci_malloc(sizeof(int) * top);
+
+ for (i = 0; i < top; i++)
+ if (scir_test_resource(resmgr, restype, i))
+ resources[count++] = i;
+
+ *entries_nr = count;
+
+ return resources;
+}
+
+gfx_pixmap_color_t *
+gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal)
+{
+ if (version >= SCI_VERSION_01_VGA)
+ return gfxr_interpreter_get_palette(state, version, colors_nr, internal, 999);
+
+ *colors_nr = GFX_SCI0_PIC_COLORS_NR;
+ return gfx_sci0_pic_colors;
+}
+
+gfx_pixmap_color_t *
+gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr,
+ void *internal, int nr)
+{
+ resource_mgr_t *resmgr = (resource_mgr_t *) state->misc_payload;
+ resource_t *res;
+
+ if (version < SCI_VERSION_01_VGA)
+ return NULL;
+
+ res = scir_find_resource(resmgr, sci_palette, nr, 0);
+ if (!res || !res->data)
+ return NULL;
+
+ switch (version)
+ {
+ case SCI_VERSION_01_VGA :
+ case SCI_VERSION_01_VGA_ODD :
+ case SCI_VERSION_1_EARLY :
+ case SCI_VERSION_1_LATE :
+ return gfxr_read_pal1(res->id, colors_nr, res->data, res->size);
+ case SCI_VERSION_1_1 :
+ case SCI_VERSION_32 :
+ GFX_DEBUG("Palettes are not yet supported in this SCI version\n");
+ return NULL;
+
+ default:
+ BREAKPOINT();
+ return NULL;
+ }
+}
+
+int
+gfxr_interpreter_needs_multicolored_pointers(int version, void *internal)
+{
+ return (version > SCI_VERSION_1);
+}
+
+
+
diff --git a/engines/sci/gfx/resource/sci_view_0.c b/engines/sci/gfx/resource/sci_view_0.c
new file mode 100644
index 0000000000..98b3654b3c
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_view_0.c
@@ -0,0 +1,254 @@
+/***************************************************************************
+ view_0.c Copyright (C) 2000 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+
+/* set optimisations for Win32: */
+#ifdef _WIN32
+# include <memory.h>
+//# pragma intrinsic( memcpy, memset )
+#endif
+
+#include <sci_memory.h>
+#include <gfx_system.h>
+#include <gfx_resource.h>
+#include <gfx_tools.h>
+
+
+gfx_pixmap_t *
+gfxr_draw_cel0(int id, int loop, int cel, byte *resource, int size, gfxr_view_t *view, int mirrored)
+{
+ int xl = get_int_16(resource);
+ int yl = get_int_16(resource + 2);
+ int xhot = ((signed char *) resource)[4];
+ int yhot = ((signed char *) resource)[5];
+ int color_key = resource[6];
+ int pos = 7;
+ int writepos = mirrored? xl : 0;
+ int pixmap_size = xl * yl;
+ int line_base = 0;
+ gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel));
+ byte *dest = retval->index_data;
+
+ retval->color_key = 255; /* Pick something larger than 15 */
+
+ retval->xoffset = mirrored? xhot : -xhot;
+ retval->yoffset = -yhot;
+
+ if (view) {
+ retval->colors = view->colors;
+ retval->colors_nr = view->colors_nr;
+ retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ } else
+ {
+ retval->colors = gfx_sci0_image_colors[sci0_palette];
+ retval->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+ retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ }
+
+ if (xl <= 0 || yl <= 0) {
+ gfx_free_pixmap(NULL, retval);
+ GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl);
+ return NULL;
+ }
+
+ if (mirrored) {
+
+ while (yl && pos < size) {
+ int op = resource[pos++];
+ int count = op >> 4;
+ int color = op & 0xf;
+
+ if (view->flags & GFX_PIXMAP_FLAG_PALETTIZED)
+ color = view->translation[color];
+
+ if (color == color_key)
+ color = retval->color_key;
+
+ while (count) {
+ int pixels = writepos - line_base;
+
+ if (pixels > count)
+ pixels = count;
+
+ writepos -= pixels;
+ memset(dest + writepos, color, pixels);
+ count -= pixels;
+
+ if (writepos == line_base) {
+ yl--;
+ writepos += (xl << 1);
+ line_base += xl;
+ }
+ }
+ }
+ } else {
+
+ while (writepos < pixmap_size && pos < size) {
+ int op = resource[pos++];
+ int count = op >> 4;
+ int color = op & 0xf;
+
+ if (view && (view->flags & GFX_PIXMAP_FLAG_PALETTIZED))
+ color = view->translation[color];
+
+ if (color == color_key)
+ color = retval->color_key;
+
+ if (writepos + count > pixmap_size) {
+ GFXERROR("View %02x:(%d/%d) writes RLE data over its designated end at rel. offset 0x%04x\n", id, loop, cel, pos);
+ return NULL;
+ }
+
+ memset(dest + writepos, color, count);
+ writepos += count;
+ }
+ }
+
+ return retval;
+}
+
+static int
+gfxr_draw_loop0(gfxr_loop_t *dest, int id, int loop, byte *resource, int offset, int size, gfxr_view_t *view, int mirrored)
+{
+ int i;
+ int cels_nr = get_int_16(resource + offset);
+
+ if (get_uint_16(resource + offset + 2)) {
+ GFXWARN("View %02x:(%d): Gray magic %04x in loop, expected white\n", id, loop, get_uint_16(resource + offset + 2));
+ }
+
+ if (cels_nr * 2 + 4 + offset > size) {
+ GFXERROR("View %02x:(%d): Offset array for %d cels extends beyond resource space\n", id, loop, cels_nr);
+ dest->cels_nr = 0; /* Mark as "delete no cels" */
+ dest->cels = NULL;
+ return 1;
+ }
+
+ dest->cels = (gfx_pixmap_t**)sci_malloc(sizeof(gfx_pixmap_t *) * cels_nr);
+
+ for (i = 0; i < cels_nr; i++) {
+ int cel_offset = get_uint_16(resource + offset + 4 + (i << 1));
+ gfx_pixmap_t *cel = NULL;
+
+ if (cel_offset >= size) {
+ GFXERROR("View %02x:(%d/%d) supposed to be at illegal offset 0x%04x\n", id, loop, i, cel_offset);
+ cel = NULL;
+ } else
+ cel = gfxr_draw_cel0(id, loop, i, resource + cel_offset, size - cel_offset, view, mirrored);
+
+
+ if (!cel) {
+ dest->cels_nr = i;
+ return 1;
+ }
+
+ dest->cels[i] = cel;
+ }
+
+ dest->cels_nr = cels_nr;
+
+ return 0;
+}
+
+
+#define V0_LOOPS_NR_OFFSET 0
+#define V0_FIRST_LOOP_OFFSET 8
+#define V0_MIRROR_LIST_OFFSET 2
+
+gfxr_view_t *
+gfxr_draw_view0(int id, byte *resource, int size, int palette)
+{
+ int i;
+ gfxr_view_t *view;
+ int mirror_bitpos = 1;
+ int mirror_bytepos = V0_MIRROR_LIST_OFFSET;
+ int palette_ofs = get_int_16(resource + 6);
+
+ if (size < V0_FIRST_LOOP_OFFSET + 8) {
+ GFXERROR("Attempt to draw empty view %04x\n", id);
+ return NULL;
+ }
+
+ view = (gfxr_view_t*)sci_malloc(sizeof(gfxr_view_t));
+ view->ID = id;
+
+ view->loops_nr = resource[V0_LOOPS_NR_OFFSET];
+
+ /* Set palette */
+ view->colors_nr = GFX_SCI0_IMAGE_COLORS_NR;
+ view->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ view->colors = gfx_sci0_image_colors[sci0_palette];
+
+ if ((palette_ofs)&&(palette>=0))
+ {
+ byte *paldata = resource + palette_ofs + (palette * GFX_SCI0_IMAGE_COLORS_NR);
+
+ for (i = 0; i < GFX_SCI0_IMAGE_COLORS_NR; i++)
+ view->translation[i] = *(paldata++);
+
+ view->flags |= GFX_PIXMAP_FLAG_PALETTIZED;
+ }
+
+ if (view->loops_nr * 2 + V0_FIRST_LOOP_OFFSET > size) {
+ GFXERROR("View %04x: Not enough space in resource to accomodate for the claimed %d loops\n", id, view->loops_nr);
+ free(view);
+ return NULL;
+ }
+
+ view->loops = (gfxr_loop_t*)sci_malloc(sizeof (gfxr_loop_t) * ((view->loops_nr)? view->loops_nr : 1)); /* Alloc 1 if no loop */
+
+ for (i = 0; i < view->loops_nr; i++) {
+ int error_token = 0;
+ int loop_offset = get_uint_16(resource + V0_FIRST_LOOP_OFFSET + (i << 1));
+ int mirrored = resource[mirror_bytepos] & mirror_bitpos;
+
+ if ((mirror_bitpos <<= 1) == 0x100) {
+ mirror_bytepos++;
+ mirror_bitpos = 1;
+ }
+
+ if (loop_offset >= size) {
+ GFXERROR("View %04x:(%d) supposed to be at illegal offset 0x%04x\n", id, i, loop_offset);
+ error_token = 1;
+ }
+
+ if (error_token || gfxr_draw_loop0(view->loops + i, id, i, resource, loop_offset, size, view, mirrored)) {
+ /* An error occured */
+ view->loops_nr = i;
+ gfxr_free_view(NULL, view);
+ return NULL;
+ }
+ }
+
+ return view;
+}
+
+
+
+
+
+
+
diff --git a/engines/sci/gfx/resource/sci_view_1.c b/engines/sci/gfx/resource/sci_view_1.c
new file mode 100644
index 0000000000..1387696416
--- /dev/null
+++ b/engines/sci/gfx/resource/sci_view_1.c
@@ -0,0 +1,554 @@
+/***************************************************************************
+ view_1.c Copyright (C) 2000 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+/* SCI 1 view resource defrobnicator */
+
+#include <sci_memory.h>
+#include <gfx_system.h>
+#include <gfx_resource.h>
+#include <gfx_tools.h>
+
+#define V1_LOOPS_NR_OFFSET 0
+#define V1_MIRROR_MASK 2
+#define V1_PALETTE_OFFSET 6
+#define V1_FIRST_LOOP_OFFSET 8
+
+#define V1_RLE 0x80 /* run-length encode? */
+#define V1_RLE_BG 0x40 /* background fill */
+
+#define NEXT_RUNLENGTH_BYTE(n) \
+ if (literal_pos == runlength_pos) \
+ literal_pos += n; \
+ runlength_pos += n;
+
+#define NEXT_LITERAL_BYTE(n) \
+ if (literal_pos == runlength_pos) \
+ runlength_pos += n; \
+ literal_pos += n;
+
+static int
+decompress_sci_view(int id, int loop, int cel, byte *resource, byte *dest, int mirrored, int pixmap_size, int size,
+ int runlength_pos, int literal_pos, int xl, int yl, int color_key)
+{
+ int writepos = mirrored? xl : 0;
+
+ if (mirrored) {
+ int linebase = 0;
+
+ while (linebase < pixmap_size && literal_pos < size && runlength_pos < size) {
+ int op = resource[runlength_pos];
+ int bytes;
+ int readbytes = 0;
+ int color;
+
+ NEXT_RUNLENGTH_BYTE(1);
+
+ if (op & V1_RLE) {
+ bytes = op & 0x3f;
+ op &= (V1_RLE | V1_RLE_BG);
+ readbytes = (op & V1_RLE_BG)? 0 : 1;
+ } else {
+ readbytes = bytes = op & 0x3f;
+ op = 0;
+ }
+
+ if (runlength_pos + readbytes > size)
+ {
+ GFXWARN("View %02x:(%d/%d) requires %d bytes to be read when %d are available at pos %d\n",
+ id, loop, cel, readbytes, size - runlength_pos, runlength_pos-1);
+ return 1;
+ }
+/*
+ if (writepos - bytes < 0) {
+ GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n",
+ id, loop, cel, writepos - bytes, pixmap_size, pos - 1);
+ bytes = pixmap_size - writepos;
+ }
+*/
+ if (op==V1_RLE)
+ {
+ color = resource[literal_pos];
+ NEXT_LITERAL_BYTE(1);
+ }
+
+ if (!op && literal_pos + bytes > size)
+ {
+ GFXWARN("View %02x:(%d/%d) requires %d bytes to be read when %d are available at pos %d\n",
+ id, loop, cel, bytes, size - literal_pos, literal_pos-1);
+ return 1;
+ }
+
+ while (bytes--)
+ {
+ if (op) {
+ if (op & V1_RLE_BG) {
+ writepos--;
+ *(dest + writepos) = color_key;
+ } else {
+ writepos--;
+ *(dest + writepos) = color;
+ }
+ } else {
+ writepos--;
+ *(dest + writepos) = *(resource + literal_pos);
+ NEXT_LITERAL_BYTE(1);
+
+ }
+ if (writepos == linebase)
+ {
+ writepos+=2*xl;
+ linebase+=xl;
+ }
+ }
+ }
+ }
+ else {
+ while (writepos < pixmap_size && literal_pos < size && runlength_pos < size) {
+ int op = resource[runlength_pos];
+ int bytes;
+ int readbytes = 0;
+
+ NEXT_RUNLENGTH_BYTE(1);
+
+ if (op & V1_RLE) {
+ bytes = op & 0x3f;
+ op &= (V1_RLE | V1_RLE_BG);
+ readbytes = (op & V1_RLE_BG)? 0 : 1;
+ } else {
+ readbytes = bytes = op & 0x3f;
+ op = 0;
+ }
+
+ if (runlength_pos + readbytes > size) {
+ return 1;
+ }
+
+ if (writepos + bytes > pixmap_size) {
+ GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n",
+ id, loop, cel, writepos-bytes, pixmap_size, runlength_pos - 1);
+ bytes = pixmap_size - writepos;
+ }
+
+ if (!op && literal_pos + bytes > size)
+ {
+ GFXWARN("View %02x:(%d/%d) requires %d bytes to be read when %d are available at pos %d\n",
+ id, loop, cel, bytes, size - literal_pos, literal_pos-1);
+ return 1;
+ }
+
+ if (writepos + bytes > pixmap_size)
+ {
+ GFXWARN("Writing out of bounds: %d bytes at %d > size %d\n", bytes, writepos, pixmap_size);
+ }
+
+ if (op) {
+ if (op & V1_RLE_BG)
+ memset(dest + writepos, color_key, bytes);
+ else {
+ int color = resource[literal_pos];
+
+ NEXT_LITERAL_BYTE(1);
+ memset(dest + writepos, color, bytes);
+ }
+ } else {
+ memcpy(dest + writepos, resource + literal_pos, bytes);
+ NEXT_LITERAL_BYTE(bytes);
+ }
+ writepos += bytes;
+
+ }
+
+ };
+
+ return 0;
+}
+
+static int
+decompress_sci_view_amiga(int id, int loop, int cel, byte *resource, byte *dest, int mirrored, int pixmap_size, int size,
+ int pos, int xl, int yl, int color_key)
+{
+ int writepos = mirrored? xl - 1 : 0;
+
+ while (writepos < pixmap_size && pos < size) {
+ int op = resource[pos++];
+ int bytes;
+ int color;
+
+ if (op & 0x07) {
+ bytes = op & 0x07;
+ color = op >> 3;
+ } else {
+ bytes = op >> 3;
+ color = color_key;
+ }
+
+ if (mirrored) {
+ while (bytes--) {
+ dest[writepos--] = color;
+ /* If we've just written the first pixel of a line... */
+ if (!((writepos + 1) % xl)) {
+ /* Then move to the end of next line */
+ writepos += 2 * xl;
+
+ if (writepos >= pixmap_size && bytes)
+ {
+ GFXWARN("View %02x:(%d/%d) writing out of bounds\n", id, loop, cel);
+ break;
+ }
+ }
+ }
+ } else {
+ if (writepos + bytes > pixmap_size) {
+ GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n",
+ id, loop, cel, writepos-bytes, pixmap_size, pos - 1);
+ bytes = pixmap_size - writepos;
+ }
+ memset(dest + writepos, color, bytes);
+ writepos += bytes;
+ }
+ }
+
+ if (writepos < pixmap_size) {
+ GFXWARN("View %02x:(%d/%d) not enough pixel data in view\n", id, loop, cel);
+ return 1;
+ }
+
+ return 0;
+}
+
+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)
+{
+ int xl = get_int_16(resource);
+ int yl = get_int_16(resource + 2);
+ int xhot = (gint8) resource[4];
+ int yhot = (guint8) resource[5];
+ int pos = 8;
+ int pixmap_size = xl * yl;
+ gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel));
+ byte *dest = retval->index_data;
+ int decompress_failed;
+
+ retval->color_key = resource[6];
+ retval->xoffset = (mirrored)? xhot : -xhot;
+ retval->yoffset = -yhot;
+
+ if (view) {
+ retval->colors = view->colors;
+ retval->colors_nr = view->colors_nr;
+ }
+
+ retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+
+ if (xl <= 0 || yl <= 0) {
+ gfx_free_pixmap(NULL, retval);
+ GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl);
+ return NULL;
+ }
+
+ if (amiga_game)
+ decompress_failed = decompress_sci_view_amiga(id, loop, cel,
+ resource, dest, mirrored, pixmap_size, size, pos,
+ xl, yl, retval->color_key);
+ else
+ decompress_failed = decompress_sci_view(id, loop, cel,
+ resource, dest, mirrored, pixmap_size, size, pos,
+ pos, xl, yl, retval->color_key);
+
+ if (decompress_failed) {
+ gfx_free_pixmap(NULL, retval);
+ return NULL;
+ }
+
+ return retval;
+}
+
+static int
+gfxr_draw_loop1(gfxr_loop_t *dest, int id, int loop, int mirrored, byte *resource, int offset, int size, gfxr_view_t *view, int amiga_game)
+{
+ int i;
+ int cels_nr = get_int_16(resource + offset);
+
+ if (get_uint_16(resource + offset + 2)) {
+ GFXWARN("View %02x:(%d): Gray magic %04x in loop, expected white\n", id, loop, get_uint_16(resource + offset + 2));
+ }
+
+ if (cels_nr * 2 + 4 + offset > size) {
+ GFXERROR("View %02x:(%d): Offset array for %d cels extends beyond resource space\n", id, loop, cels_nr);
+ dest->cels_nr = 0; /* Mark as "delete no cels" */
+ dest->cels = NULL;
+ return 1;
+ }
+
+ dest->cels = (gfx_pixmap_t**)sci_malloc(sizeof(gfx_pixmap_t *) * cels_nr);
+
+ for (i = 0; i < cels_nr; i++) {
+ int cel_offset = get_uint_16(resource + offset + 4 + (i << 1));
+ gfx_pixmap_t *cel;
+
+ if (cel_offset >= size) {
+ GFXERROR("View %02x:(%d/%d) supposed to be at illegal offset 0x%04x\n", id, loop, i, cel_offset);
+ cel = NULL;
+ } else
+ cel = gfxr_draw_cel1(id, loop, i, mirrored, resource + cel_offset, size - cel_offset, view, amiga_game);
+
+ if (!cel) {
+ dest->cels_nr = i;
+ return 1;
+ }
+
+ dest->cels[i] = cel;
+ }
+
+ dest->cels_nr = cels_nr;
+
+ return 0;
+}
+
+
+#define V1_FIRST_MAGIC 1
+#define V1_MAGICS_NR 5
+/*static byte view_magics[V1_MAGICS_NR] = {0x80, 0x00, 0x00, 0x00, 0x00};*/
+
+gfxr_view_t *
+gfxr_draw_view1(int id, byte *resource, int size, gfx_pixmap_color_t *static_pal,
+ int static_pal_nr)
+{
+ int i;
+ int palette_offset;
+ gfxr_view_t *view;
+ int mirror_mask;
+ int amiga_game = 0;
+
+ if (size < V1_FIRST_LOOP_OFFSET + 8) {
+ GFXERROR("Attempt to draw empty view %04x\n", id);
+ return NULL;
+ }
+
+ view = (gfxr_view_t*)sci_malloc(sizeof(gfxr_view_t));
+ view->ID = id;
+ view->flags = 0;
+
+ view->loops_nr = resource[V1_LOOPS_NR_OFFSET];
+ palette_offset = get_uint_16(resource + V1_PALETTE_OFFSET);
+ mirror_mask = get_uint_16(resource + V1_MIRROR_MASK);
+
+ if (view->loops_nr * 2 + V1_FIRST_LOOP_OFFSET > size) {
+ GFXERROR("View %04x: Not enough space in resource to accomodate for the claimed %d loops\n", id, view->loops_nr);
+ free(view);
+ return NULL;
+ }
+
+/* fprintf(stderr, "View flags are 0x%02x\n", resource[3]);*/
+
+/*
+ for (i = 0; i < V1_MAGICS_NR; i++)
+ if (resource[V1_FIRST_MAGIC + i] != view_magics[i]) {
+ GFXWARN("View %04x: View magic #%d should be %02x but is %02x\n",
+ id, i, view_magics[i], resource[V1_FIRST_MAGIC + i]);
+ }
+*/
+
+ if (palette_offset > 0)
+ {
+ if (palette_offset > size) {
+ GFXERROR("Palette is outside of view %04x\n", id);
+ free(view);
+ return NULL;
+ }
+ if (!(view->colors = gfxr_read_pal1(id, &(view->colors_nr),
+ resource + palette_offset, size - palette_offset))) {
+ GFXERROR("view %04x: Palette reading failed. Aborting...\n", id);
+ free(view);
+ return NULL;
+ }
+ } else if (static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR) {
+ /* Assume we're running an amiga game. */
+ amiga_game = 1;
+ view->colors = static_pal;
+ view->colors_nr = static_pal_nr;
+ view->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+ } else {
+ GFXWARN("view %04x: Doesn't have a palette. Can FreeSCI handle this?\n", view->ID);
+ view->colors = NULL;
+ view->colors_nr = 0;
+ }
+
+ view->loops = (gfxr_loop_t*)sci_malloc(sizeof (gfxr_loop_t) * view->loops_nr);
+
+ for (i = 0; i < view->loops_nr; i++) {
+ int error_token = 0;
+ int loop_offset = get_uint_16(resource + V1_FIRST_LOOP_OFFSET + (i << 1));
+
+ if (loop_offset >= size) {
+ GFXERROR("View %04x:(%d) supposed to be at illegal offset 0x%04x\n", id, i);
+ error_token = 1;
+ }
+
+ if (error_token || gfxr_draw_loop1(view->loops + i, id, i, mirror_mask & (1<<i),
+ resource, loop_offset, size, view, amiga_game)) {
+ /* An error occured */
+ view->loops_nr = i;
+ gfxr_free_view(NULL, view);
+ return NULL;
+ }
+ }
+
+ return view;
+}
+
+#define V2_HEADER_SIZE 0
+#define V2_LOOPS_NUM 2
+#define V2_PALETTE_OFFSET 8
+#define V2_BYTES_PER_LOOP 12
+#define V2_BYTES_PER_CEL 13
+
+#define V2_IS_MIRROR 1
+#define V2_COPY_OF_LOOP 2
+#define V2_CELS_NUM 4
+#define V2_LOOP_OFFSET 14
+
+#define V2_CEL_WIDTH 0
+#define V2_CEL_HEIGHT 2
+#define V2_X_DISPLACEMENT 4
+#define V2_Y_DISPLACEMENT 6
+#define V2_COLOR_KEY 8
+#define V2_RUNLENGTH_OFFSET 24
+#define V2_LITERAL_OFFSET 28
+
+gfx_pixmap_t *
+gfxr_draw_cel11(int id, int loop, int cel, int mirrored, byte *resource_base, byte *cel_base, int size, gfxr_view_t *view)
+{
+ int xl = get_uint_16(cel_base + V2_CEL_WIDTH);
+ int yl = get_uint_16(cel_base + V2_CEL_HEIGHT);
+ int xdisplace = get_uint_16(cel_base + V2_X_DISPLACEMENT);
+ int ydisplace = get_uint_16(cel_base + V2_Y_DISPLACEMENT);
+ int runlength_offset = get_uint_16(cel_base + V2_RUNLENGTH_OFFSET);
+ int literal_offset = get_uint_16(cel_base + V2_LITERAL_OFFSET);
+ int pixmap_size = xl * yl;
+
+ gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel));
+ byte *dest = retval->index_data;
+ int decompress_failed;
+
+ retval->color_key = cel_base[V2_COLOR_KEY];
+ retval->xoffset = (mirrored)? xdisplace : -xdisplace;
+ retval->yoffset = -ydisplace;
+
+ if (view) {
+ retval->colors = view->colors;
+ retval->colors_nr = view->colors_nr;
+ }
+
+ retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE;
+
+ if (xl <= 0 || yl <= 0) {
+ gfx_free_pixmap(NULL, retval);
+ GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl);
+ return NULL;
+ }
+
+ decompress_failed = decompress_sci_view(id, loop, cel, resource_base, dest, mirrored, pixmap_size, size,
+ runlength_offset, literal_offset, xl, yl, retval->color_key);
+
+ if (decompress_failed) {
+ gfx_free_pixmap(NULL, retval);
+ return NULL;
+ }
+
+ return retval;
+}
+
+gfxr_loop_t *
+gfxr_draw_loop11(int id, int loop, int mirrored, byte *resource_base, byte *loop_base, int size, int cels_nr,
+ gfxr_loop_t *result, gfxr_view_t *view, int bytes_per_cel)
+{
+ byte *seeker = loop_base;
+ int i;
+
+ result->cels_nr = cels_nr;
+ result->cels = (gfx_pixmap_t **)
+ sci_malloc(sizeof(gfx_pixmap_t *) * cels_nr);
+
+ for (i = 0; i < cels_nr; i++)
+ {
+ result->cels[i] = gfxr_draw_cel11(id, loop, i, mirrored, resource_base, seeker, size, view);
+ seeker += bytes_per_cel;
+ }
+
+ return result;
+}
+
+gfxr_view_t *
+gfxr_draw_view11(int id, byte *resource, int size)
+{
+ gfxr_view_t *view;
+ int header_size = get_uint_16(resource + V2_HEADER_SIZE);
+ int palette_offset = get_uint_16(resource + V2_PALETTE_OFFSET);
+ int bytes_per_loop = resource[V2_BYTES_PER_LOOP];
+ int loops_num = resource[V2_LOOPS_NUM];
+ int bytes_per_cel = resource[V2_BYTES_PER_CEL];
+ int i;
+ byte *seeker;
+
+ view = (gfxr_view_t*)sci_malloc(sizeof(gfxr_view_t));
+
+ memset(view, 0, sizeof(gfxr_view_t));
+ view->ID = id;
+ view->flags = 0;
+
+ view->loops_nr = loops_num;
+ view->loops = (gfxr_loop_t *)calloc(view->loops_nr, sizeof(gfxr_loop_t));
+
+ /* There is no indication of size here, but this is certainly large enough */
+ view->colors = gfxr_read_pal11(id, &view->colors_nr, resource + palette_offset, 1284);
+
+ seeker = resource + header_size;
+ for (i = 0; i < view->loops_nr; i++)
+ {
+ static char *truth[2] = {"not ",""};
+ int loop_offset = get_uint_16(seeker + V2_LOOP_OFFSET);
+ int cels = seeker[V2_CELS_NUM];
+ int mirrored = seeker[V2_IS_MIRROR];
+ int copy_entry = seeker[V2_COPY_OF_LOOP];
+
+ printf("%d\n", mirrored);
+ if (copy_entry == 255)
+ gfxr_draw_loop11(id, i, 0, resource, resource + loop_offset, size, cels, view->loops + i,
+ view, bytes_per_cel); else
+ {
+ byte *temp = resource + header_size + copy_entry * bytes_per_loop;
+ loop_offset = get_uint_16(temp + V2_LOOP_OFFSET);
+ cels = temp[V2_CELS_NUM];
+ gfxr_draw_loop11(id, i, 1, resource, resource + loop_offset, size, cels,
+ view->loops + i, view, bytes_per_cel);
+ }
+
+ seeker += bytes_per_loop;
+ }
+
+ return view;
+}