diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 64b7601..436abd6 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -332,18 +332,18 @@ SciKernelFunction kfunct_mappers[] = {
 	DEFUN("ShowMovie", kShowMovie, "..*"),
 	DEFUN("SetVideoMode", kSetVideoMode, "i"),
 	DEFUN("Platform", kPlatform, "i*"),
-	DEFUN("PalVary", kPalVary, "ii*"),
+	DEFUN("TextColors", kTextColors, ".*"),
+	DEFUN("TextFonts", kTextFonts, ".*"),
 
 #if 0
 	// Stub functions
+	DEFUN("PalVary", kPalVary, "ii*"),
 	DEFUN("ShiftScreen", kShiftScreen, ".*"),
 	DEFUN("MemorySegment", kMemorySegment, ".*"),
 	DEFUN("ListOps", kListOps, ".*"),
 	DEFUN("ATan", kATan, ".*"),
 	DEFUN("MergePoly", kMergePoly, ".*"),
 	DEFUN("AssertPalette", kAssertPalette, ".*"),
-	DEFUN("TextColors", kTextColors, ".*"),
-	DEFUN("TextFonts", kTextFonts, ".*"),
 	DEFUN("Record", kRecord, ".*"),
 	DEFUN("PlayBack", kPlayBack, ".*"),
 	DEFUN("DbugStr", kDbugStr, ".*"),
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index bb88fab..2e9025e 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -454,7 +454,8 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv);
 reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv);
 reg_t kStrSplit(EngineState *s, int argc, reg_t *argv);
 reg_t kPlatform(EngineState *s, int argc, reg_t *argv);
-reg_t kPalVary(EngineState *s, int argc, reg_t *argv);
+reg_t kTextColors(EngineState *s, int argc, reg_t *argv);
+reg_t kTextFonts(EngineState *s, int argc, reg_t *argv);
 
 } // End of namespace Sci
 
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index d86fcdd..728dad0 100644
--- a/engines/sci/engine/kevent.cpp
+++ b/engines/sci/engine/kevent.cpp
@@ -206,11 +206,13 @@ reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) {
 	SegManager *segMan = s->segMan;
 
 	if (obj.segment) {
-		int x = GET_SEL32V(obj, x);
-		int y = GET_SEL32V(obj, y);
+		int16 x = GET_SEL32V(obj, x);
+		int16 y = GET_SEL32V(obj, y);
 
-		PUT_SEL32V(obj, x, x - s->port->zone.x);
-		PUT_SEL32V(obj, y, y - s->port->zone.y);
+		s->gui->globalToLocal(&x, &y);
+
+		PUT_SEL32V(obj, x, x);
+		PUT_SEL32V(obj, y, y);
 	}
 
 	return s->r_acc;
@@ -222,11 +224,13 @@ reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) {
 	SegManager *segMan = s->segMan;
 
 	if (obj.segment) {
-		int x = GET_SEL32V(obj, x);
-		int y = GET_SEL32V(obj, y);
+		int16 x = GET_SEL32V(obj, x);
+		int16 y = GET_SEL32V(obj, y);
+
+		s->gui->localToGlobal(&x, &y);
 
-		PUT_SEL32V(obj, x, x + s->port->zone.x);
-		PUT_SEL32V(obj, y, y + s->port->zone.y);
+		PUT_SEL32V(obj, x, x);
+		PUT_SEL32V(obj, y, y);
 	}
 
 	return s->r_acc;
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 353c21a..9894f3e 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -105,7 +105,8 @@ static inline int sign_extend_byte(int value) {
 		return value;
 }
 
-static void assert_primary_widget_lists(EngineState *s) {
+// was static
+void assert_primary_widget_lists(EngineState *s) {
 	if (!s->dyn_views) {
 		rect_t bounds = s->picture_port->_bounds;
 
@@ -123,7 +124,8 @@ static void assert_primary_widget_lists(EngineState *s) {
 	}
 }
 
-static void reparentize_primary_widget_lists(EngineState *s, GfxPort *newport) {
+// static
+void reparentize_primary_widget_lists(EngineState *s, GfxPort *newport) {
 	if (!newport)
 		newport = s->picture_port;
 
@@ -264,24 +266,6 @@ PaletteEntry get_pic_color(EngineState *s, int color) {
 	}
 }
 
-static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int control) {
-	gfx_color_t retval;
-
-	if (!s->resMan->isVGA()) {
-		retval = s->ega_colors[(color >=0 && color < 16)? color : 0];
-		gfxop_set_color(s->gfx_state, &retval, (color < 0) ? -1 : retval.visual.r, retval.visual.g, retval.visual.b,
-		                (color == -1) ? 255 : 0, priority, control);
-	} else {
-		retval.visual = get_pic_color(s, color);
-		retval.alpha = 0;
-		retval.priority = priority;
-		retval.control = control;
-		retval.mask = GFX_MASK_VISUAL | ((priority >= 0) ? GFX_MASK_PRIORITY : 0) | ((control >= 0) ? GFX_MASK_CONTROL : 0);
-	};
-
-	return retval;
-}
-
 static reg_t kSetCursorSci0(EngineState *s, int argc, reg_t *argv) {
 	int16 cursor = argv[0].toSint16();
 
@@ -353,27 +337,8 @@ reg_t kSetCursor(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kMoveCursor(EngineState *s, int argc, reg_t *argv) {
-	Common::Point newPos;
-
-	newPos = s->gfx_state->pointer_pos;
-
-	if (argc == 1) {
-		// Case ignored on IBM PC
-	} else {
-		newPos.x = argv[0].toSint16() + s->port->zone.x;
-		newPos.y = argv[1].toSint16() + s->port->zone.y;
-
-		if (newPos.x > s->port->zone.x + s->port->zone.width)
-			newPos.x = s->port->zone.x + s->port->zone.width;
-		if (newPos.y > s->port->zone.y + s->port->zone.height)
-			newPos.y = s->port->zone.y + s->port->zone.height;
-
-		if (newPos.x < 0) newPos.x = 0;
-		if (newPos.y < 0) newPos.y = 0;
-	}
-
-	gfxop_set_pointer_position(s->gfx_state, newPos);
-
+	if (argc == 2)
+		s->gui->moveCursor(argv[0].toSint16(), argv[1].toSint16());
 	return s->r_acc;
 }
 
@@ -439,116 +404,73 @@ void _k_redraw_box(EngineState *s, int x1, int y1, int x2, int y2) {
 #endif
 }
 
-void _k_graph_rebuild_port_with_color(EngineState *s, gfx_color_t newbgcolor) {
-	GfxPort *port = s->port;
-	GfxPort *newport;
-
-	newport = sciw_new_window(s, port->zone, port->_font, port->_color, newbgcolor,
-	                          s->titlebar_port->_font, s->ega_colors[15], s->ega_colors[8],
-	                          port->_title_text.c_str(), port->port_flags & ~kWindowTransparent);
-
-	if (s->dyn_views) {
-		int found = 0;
-		GfxContainer *parent = s->dyn_views->_parent;
-
-		while (parent && !(found |= (parent == port)))
-			parent = parent->_parent;
-
-		s->dyn_views = NULL;
+reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
+	int rectLeft = 0, rectTop = 0, rectRight = 0, rectBottom = 0;
+	uint16 flags;
+	int16 priority, control, color, colorMask;
+
+	Common::Rect rect;
+	if (argc>=5) {
+		rectLeft = argv[2].toSint16(); rectTop = argv[1].toSint16();
+		rectRight = argv[4].toSint16(); rectBottom = argv[3].toSint16();
+		// Fixup data, so that a valid rectangle is formed
+		if (rectLeft > rectRight) {
+			rectRight = rectLeft; rectLeft = argv[4].toSint16();
+		}
+		if (rectTop > rectBottom) {
+			rectBottom = rectTop; rectTop = argv[3].toSint16();
+		}
+		rect = Common::Rect (rectLeft, rectTop, rectRight, rectBottom);
 	}
 
-	port->_parent->add((GfxContainer *)port->_parent, newport);
-	delete port;
-}
-
-static bool activated_icon_bar = false;	// FIXME: Avoid non-const global vars
-static int port_origin_x = 0;	// FIXME: Avoid non-const global vars
-static int port_origin_y = 0;	// FIXME: Avoid non-const global vars
-
-reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
-	rect_t area;
+	// old code, may be removed later after class migration
 	GfxPort *port = s->port;
 	int redraw_port = 0;
-
+	rect_t area;
 	area = gfx_rect(argv[2].toSint16(), argv[1].toSint16() , argv[4].toSint16(), argv[3].toSint16());
-
 	area.width = area.width - area.x; // Since the actual coordinates are absolute
 	area.height = area.height - area.y;
 
 	switch (argv[0].toSint16()) {
 
 	case K_GRAPH_GET_COLORS_NR:
-
 		return make_reg(0, !s->resMan->isVGA() ? 0x10 : 0x100);
 		break;
 
-	case K_GRAPH_DRAW_LINE: {
-		int16 priority = (argc > 6) ? argv[6].toSint16() : -1;
-		int16 control = (argc > 7) ? argv[7].toSint16() : -1;
-		gfx_color_t gfxcolor = graph_map_color(s, argv[5].toSint16(), priority, control);
+	case K_GRAPH_DRAW_LINE:
+		priority = (argc > 6) ? argv[6].toSint16() : -1;
+		control = (argc > 7) ? argv[7].toSint16() : -1;
+		color = argv[5].toSint16();
 
-		debugC(2, kDebugLevelGraphics, "draw_line((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n",
-		          argv[2].toSint16(), argv[1].toSint16(), argv[4].toSint16(), argv[3].toSint16(), argv[5].toSint16(), priority, control, gfxcolor.mask);
-
-		redraw_port = 1;
-
-		// Note: it's quite possible that the coordinates of the line will *not* form a valid rectangle (e.g. it might
-		// have negative width/height). The actual dirty rectangle is constructed in gfxdr_add_dirty().
-		// FIXME/TODO: We need to change the semantics of this call, so that no fake rectangles are used. As it is, it's
-		// not possible change rect_t to Common::Rect, as we assume that Common::Rect forms a *valid* rectangle.
-		ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_line(Common::Point(argv[2].toSint16(), argv[1].toSint16()), Common::Point(argv[4].toSint16(), argv[3].toSint16()),
-		                               gfxcolor, GFX_LINE_MODE_CORRECT, GFX_LINE_STYLE_NORMAL));
-
-	}
-	break;
+		// FIXME: rect must be changed to 2 Common::Point
+		s->gui->graphDrawLine(rect, color, priority, control);
+		break;
 
 	case K_GRAPH_SAVE_BOX:
-
-		area.x += s->port->zone.x + port_origin_x;
-		area.y += s->port->zone.y + port_origin_y;
-		area.width += -port_origin_x;
-		area.height += -port_origin_y;
-
-		return(graph_save_box(s, area));
+		flags = (argc > 5) ? argv[5].toUint16() : 0;
+		return s->gui->graphSaveBox(rect, flags);
 		break;
 
 	case K_GRAPH_RESTORE_BOX:
-
-		graph_restore_box(s, argv[1]);
+		s->gui->graphRestoreBox(argv[1]);
 		break;
 
 	case K_GRAPH_FILL_BOX_BACKGROUND:
-
-		_k_graph_rebuild_port_with_color(s, port->_bgcolor);
-		port = s->port;
-
-		redraw_port = 1;
+		s->gui->graphFillBoxBackground(rect);
 		break;
 
 	case K_GRAPH_FILL_BOX_FOREGROUND:
-
-		_k_graph_rebuild_port_with_color(s, port->_color);
-		port = s->port;
-
-		redraw_port = 1;
+		s->gui->graphFillBoxForeground(rect);
 		break;
 
-	case K_GRAPH_FILL_BOX_ANY: {
-		int16 priority = (argc > 7) ? argv[7].toSint16() : -1;
-		int16 control = (argc > 8) ? argv[8].toSint16() : -1;
-		gfx_color_t color = graph_map_color(s, argv[6].toSint16(), priority, control);
-
-		color.mask = (byte)argv[5].toUint16();
-
-		debugC(2, kDebugLevelGraphics, "fill_box_any((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n",
-		          argv[2].toSint16(), argv[1].toSint16(), argv[4].toSint16(), argv[3].toSint16(), argv[6].toSint16(), priority, control, argv[5].toUint16());
+	case K_GRAPH_FILL_BOX_ANY:
+		priority = (argc > 7) ? argv[7].toSint16() : -1;
+		control = (argc > 8) ? argv[8].toSint16() : -1;
+		color = argv[6].toSint16();
+		colorMask = argv[5].toUint16();
 
-		// FIXME/TODO: this is not right, as some of the dialogs are drawn *behind* some widgets. But at least it works for now
-		//ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT));	// old code
-		s->picture_port->add((GfxContainer *)s->picture_port, gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT));
-
-	}
-	break;
+		s->gui->graphFillBox(rect, colorMask, color, priority, control);
+		break;
 
 	case K_GRAPH_UPDATE_BOX: {
 
@@ -557,14 +479,12 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
 		area.x += s->port->zone.x;
 		area.y += s->port->zone.y;
 
-		gfxop_update_box(s->gfx_state, area);
-
+		// FIXME: Change to class calling
+		//gfxop_update_box(s->gfx_state, area);
 	}
 	break;
 
 	case K_GRAPH_REDRAW_BOX: {
-
-
 		debugC(2, kDebugLevelGraphics, "redraw_box(%d, %d, %d, %d)\n", argv[1].toSint16(), argv[2].toSint16(), argv[3].toSint16(), argv[4].toSint16());
 
 		area.x += s->port->zone.x;
@@ -573,10 +493,9 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
 		if (s->dyn_views && s->dyn_views->_parent == (GfxContainer *)s->port)
 			s->dyn_views->draw(Common::Point(0, 0));
 
-		gfxop_update_box(s->gfx_state, area);
-
+		// FIXME: Change to class calling
+		//gfxop_update_box(s->gfx_state, area);
 	}
-
 	break;
 
 	case K_GRAPH_ADJUST_PRIORITY:
@@ -601,22 +520,19 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
-	int width, height;
+	int16 textWidth, textHeight;
 	Common::String text = s->segMan->getString(argv[1]);
 	reg_t *dest = s->segMan->derefRegPtr(argv[0], 4);
 	int maxwidth = (argc > 3) ? argv[3].toUint16() : 0;
 	int font_nr = argv[2].toUint16();
 
 	Common::String sep_str;
-	const char *sep = NULL; 
+	const char *sep = NULL;
 	if ((argc > 4) && (argv[4].segment)) {
 		sep_str = s->segMan->getString(argv[4]);
 		sep = sep_str.c_str();
 	}
 
-	if (maxwidth < 0)
-		maxwidth = 0;
-
 	dest[0] = dest[1] = NULL_REG;
 
 	if (text.empty() || !dest) { // Empty text
@@ -625,20 +541,19 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
 		return s->r_acc;
 	}
 
-	gfxop_get_text_params(s->gfx_state, font_nr, s->strSplit(text.c_str(), sep).c_str(), maxwidth ? maxwidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
-	                                 &width, &height, 0, NULL, NULL, NULL);
-	debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text.c_str(), width, height);
-
-	dest[2] = make_reg(0, height);
-//	dest[3] = make_reg(0, maxwidth? maxwidth : width);
-	dest[3] = make_reg(0, width);
+	textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16();
+	s->gui->textSize(s->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+	debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d\n", text.c_str(), textWidth, textHeight);
 
+	dest[2] = make_reg(0, textHeight);
+	dest[3] = make_reg(0, textWidth);
 	return s->r_acc;
 }
 
 reg_t kWait(EngineState *s, int argc, reg_t *argv) {
-	uint32 time;
 	int sleep_time = argv[0].toUint16();
+#if 0
+	uint32 time;
 
 	time = g_system->getMillis();
 	s->r_acc = make_reg(0, ((long)time - (long)s->last_wait_time) * 60 / 1000);
@@ -650,6 +565,11 @@ reg_t kWait(EngineState *s, int argc, reg_t *argv) {
 	// Reset speed throttler: Game is playing along nicely anyway
 	if (sleep_time > 0)
 		s->speedThrottler->reset();
+#endif
+
+	// FIXME: we should not be asking from the GUI to wait. The kernel sounds
+	// like a better place
+	s->gui->wait(sleep_time);
 
 	return s->r_acc;
 }
@@ -977,72 +897,25 @@ void _k_view_list_free_backgrounds(EngineState *s, ViewObject *list, int list_nr
 #define K_DRAWPIC_FLAG_MIRRORED (1 << 14)
 
 reg_t kDrawPic(EngineState *s, int argc, reg_t *argv) {
-	drawn_pic_t dp;
-	bool add_to_pic = (argc > 2) ? !argv[2].toSint16() : false;
-	gfx_color_t transparent = s->wm_port->_bgcolor;
-	int picFlags = DRAWPIC01_FLAG_FILL_NORMALLY;
-
-	if (s->_kernel->usesOldGfxFunctions())
-		add_to_pic = (argc > 2) ? argv[2].toSint16() : false;
-
-	dp.nr = argv[0].toSint16();
-	dp.palette = (argc > 3) ? argv[3].toSint16() : 0;
-
-	if ((argc > 1) && (argv[1].toUint16() & K_DRAWPIC_FLAG_MIRRORED))
-		picFlags |= DRAWPIC1_FLAG_MIRRORED;
-
-	gfxop_disable_dirty_frames(s->gfx_state);
-
-	if (NULL != s->old_screen) {
-		gfxop_free_pixmap(s->gfx_state, s->old_screen);
-	}
-
-	s->old_screen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 10, 320, 190));
-
-	debugC(2, kDebugLevelGraphics, "Drawing pic.%03d\n", argv[0].toSint16());
-
-	if (add_to_pic) {
-		gfxop_add_to_pic(s->gfx_state, dp.nr, picFlags, dp.palette);
-	} else {
-		gfxop_new_pic(s->gfx_state, dp.nr, picFlags, dp.palette);
+	sciResourceId pictureId = argv[0].toUint16();
+	uint16 flags = 0;
+	uint16 style = 1;
+	int16 EGApaletteNo = -1;
+
+	if (argc >= 2)
+		style = argv[1].toUint16();
+	if (argc >= 3) {
+		if (!s->_kernel->usesOldGfxFunctions())
+			flags = !argv[2].toUint16();
+		else
+			flags = argv[2].toUint16();
 	}
+	if (argc >= 4)
+		EGApaletteNo = argv[3].toUint16();
 
-	delete s->wm_port;
-	delete s->picture_port;
-	delete s->iconbar_port;
-
-	s->wm_port = new GfxPort(s->visual, s->gfx_state->pic_port_bounds, s->ega_colors[0], transparent);
-	s->picture_port = new GfxPort(s->visual, s->gfx_state->pic_port_bounds, s->ega_colors[0], transparent);
-
-	s->iconbar_port = new GfxPort(s->visual, gfx_rect(0, 0, 320, 200), s->ega_colors[0], transparent);
-	s->iconbar_port->_flags |= GFXW_FLAG_NO_IMPLICIT_SWITCH;
-
-	s->visual->add((GfxContainer *)s->visual, s->picture_port);
-	s->visual->add((GfxContainer *)s->visual, s->wm_port);
-	s->visual->add((GfxContainer *)s->visual, s->iconbar_port);
-
-	s->port = s->picture_port;
-
-	s->pic_priority_table = gfxop_get_pic_metainfo(s->gfx_state);
-
-	if (argc > 1)
-		s->pic_animate = argv[1].toSint16() & 0xff; // The animation used during kAnimate() later on
-
-	s->dyn_views = NULL;
-	s->drop_views = NULL;
-
-	s->priority_first = 42;
-
-	if (s->_kernel->usesOldGfxFunctions())
-		s->priority_last = 200;
-	else
-		s->priority_last = 190;
-
-	s->pic_not_valid = 1;
-	s->pic_is_new = 1;
+	s->gui->drawPicture(pictureId, style, flags, EGApaletteNo);
 
 	return s->r_acc;
-
 }
 
 Common::Rect set_base(EngineState *s, reg_t object) {
@@ -1230,9 +1103,14 @@ reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
+//	warning("kPalette %d", argv[0].toUint16());
 	switch (argv[0].toUint16()) {
 	case 1:
-		debug(5, "STUB: kPalette() effect 1, direct palette set");
+		if (argc==3) {
+			int resourceNo = argv[1].toUint16();
+			int flags = argv[2].toUint16();
+			s->gui->paletteSet(resourceNo, flags);
+		}
 		break;
 	case 2:
 		debug(5, "STUB: kPalette() effect 2, set flag to colors");
@@ -1263,26 +1141,15 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
 		int g = argv[2].toUint16();
 		int b = argv[3].toUint16();
 
-		int i, delta, bestindex = -1, bestdelta = 200000;
-
-		for (i = 0; i < s->gfx_state->gfxResMan->getColorCount(); i++) {
-			int dr = abs(s->gfx_state->gfxResMan->getColor(i).r - r);
-			int dg = abs(s->gfx_state->gfxResMan->getColor(i).g - g);
-			int db = abs(s->gfx_state->gfxResMan->getColor(i).b - b);
-
-			delta = dr * dr + dg * dg + db * db;
-
-			if (delta < bestdelta) {
-				bestdelta = delta;
-				bestindex = i;
-			}
-		}
-		// Don't warn about inexact mappings -- it's actually the
-		// rule rather than the exception
-		return make_reg(0, bestindex);
+		return make_reg(0, s->gui->paletteFind(r, g, b));
 	}
 	case 6:
-		debug(5, "STUB: kPalette() effect 6, animate palette");
+		if (argc==4) {
+			int fromColor = argv[1].toUint16();
+			int toColor = argv[2].toUint16();
+			int speed = argv[3].toSint16();
+			s->gui->paletteAnimate(fromColor, toColor, speed);
+		}
 		break;
 	case 7:
 		debug(5, "STUB: kPalette() effect 7, save palette to heap");
@@ -1297,12 +1164,7 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
 	return s->r_acc;
 }
 
-reg_t kPalVary(EngineState *s, int argc, reg_t *argv) {
-	warning("STUB: kPalVary()");
-	return NULL_REG;
-}
-
-static void _k_draw_control(EngineState *s, reg_t obj, int inverse);
+static void _k_draw_control(EngineState *s, reg_t obj, bool inverse);
 
 static void disableCertainButtons(SegManager *segMan, Common::String gameName, reg_t obj) {
 	reg_t text_pos = GET_SEL32(obj, text);
@@ -1349,15 +1211,15 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) {
 	reg_t obj = argv[0];
 
 	disableCertainButtons(s->segMan, s->_gameName, obj);
-	_k_draw_control(s, obj, 0);
-	FULL_REDRAW();
+	_k_draw_control(s, obj, false);
+//	FULL_REDRAW();
 	return NULL_REG;
 }
 
 reg_t kHiliteControl(EngineState *s, int argc, reg_t *argv) {
 	reg_t obj = argv[0];
 
-	_k_draw_control(s, obj, 1);
+	_k_draw_control(s, obj, true);
 
 	return s->r_acc;
 }
@@ -1541,15 +1403,17 @@ reg_t kEditControl(EngineState *s, int argc, reg_t *argv) {
 		case K_CONTROL_ICON:
 		case K_CONTROL_BOX:
 		case K_CONTROL_BUTTON:
-			if (event.segment) PUT_SEL32V(event, claimed, 1);
-			_k_draw_control(s, obj, 0);
+			// Control shall not be redrawn here, Original Sierra interpreter doesn't do it and it will mangle up
+			// menus in at least SQ5
+			//if (event.segment) PUT_SEL32V(event, claimed, 1);
+			//_k_draw_control(s, obj, false);
 			return NULL_REG;
 			break;
 
 		case K_CONTROL_TEXT: {
 			int state = GET_SEL32V(obj, state);
 			PUT_SEL32V(obj, state, state | kControlStateDitherFramed);
-			_k_draw_control(s, obj, 0);
+			_k_draw_control(s, obj, false);
 			PUT_SEL32V(obj, state, state);
 		}
 		break;
@@ -1562,7 +1426,7 @@ reg_t kEditControl(EngineState *s, int argc, reg_t *argv) {
 	return s->r_acc;
 }
 
-static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
+static void _k_draw_control(EngineState *s, reg_t obj, bool inverse) {
 	SegManager *segMan = s->segMan;
 	int x = (int16)GET_SEL32V(obj, nsLeft);
 	int y = (int16)GET_SEL32V(obj, nsTop);
@@ -1570,6 +1434,9 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
 	int yl = (int16)GET_SEL32V(obj, nsBottom) - y;
 	rect_t area = gfx_rect(x, y, xl, yl);
 
+	Common::Rect rect;
+	rect = Common::Rect (x, y, (int16)GET_SEL32V(obj, nsRight), (int16)GET_SEL32V(obj, nsBottom));
+
 	int font_nr = GET_SEL32V(obj, font);
 	reg_t text_pos = GET_SEL32(obj, text);
 	Common::String text;
@@ -1578,7 +1445,7 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
 	int view = GET_SEL32V(obj, view);
 	int cel = sign_extend_byte(GET_SEL32V(obj, cel));
 	int loop = sign_extend_byte(GET_SEL32V(obj, loop));
-	gfx_alignment_t mode;
+	int mode;
 
 	int type = GET_SEL32V(obj, type);
 	int state = GET_SEL32V(obj, state);
@@ -1588,18 +1455,14 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
 	switch (type) {
 	case K_CONTROL_BUTTON:
 		debugC(2, kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y);
-		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, s->strSplit(text.c_str(), NULL).c_str(), font_nr,
-		                          (int8)(state & kControlStateFramed), (int8)inverse, (int8)(state & kControlStateDisabled)));
-		break;
+		s->gui->drawControlButton(rect, obj, s->strSplit(text.c_str(), NULL).c_str(), font_nr, state, inverse);
+		return;
 
 	case K_CONTROL_TEXT:
 		mode = (gfx_alignment_t) GET_SEL32V(obj, mode);
-
 		debugC(2, kDebugLevelGraphics, "drawing text %04x:%04x to %d,%d, mode=%d\n", PRINT_REG(obj), x, y, mode);
-
-		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, s->strSplit(text.c_str()).c_str(), font_nr, mode,
-									(int8)(!!(state & kControlStateDitherFramed)), (int8)inverse));
-		break;
+		s->gui->drawControlText(rect, obj, s->strSplit(text.c_str(), NULL).c_str(), font_nr, mode, state, inverse);
+		return;
 
 	case K_CONTROL_EDIT:
 		debugC(2, kDebugLevelGraphics, "drawing edit control %04x:%04x to %d,%d\n", PRINT_REG(obj), x, y);
@@ -1676,9 +1539,9 @@ static void _k_draw_control(EngineState *s, reg_t obj, int inverse) {
 					selection = i + 1;
 			}
 		}
+
 		ADD_TO_CURRENT_PICTURE_PORT(sciw_new_list_control(s->port, obj, area, font_nr, entries_list, entries_nr,
 		                          list_top, selection, (int8)inverse));
-
 		free(entries_list);
 		delete[] strings;
 	}
@@ -2350,75 +2213,34 @@ reg_t kAddToPic(EngineState *s, int argc, reg_t *argv) {
 }
 
 reg_t kGetPort(EngineState *s, int argc, reg_t *argv) {
-	return make_reg(0, s->port->_ID);
+	return s->gui->getPort();
 }
 
 reg_t kSetPort(EngineState *s, int argc, reg_t *argv) {
-	if (activated_icon_bar && argc == 6) {
-		port_origin_x = port_origin_y = 0;
-		activated_icon_bar = false;
-		return s->r_acc;
-	}
-
+	uint16 portPtr;
+	Common::Rect picRect;
+	int16 picTop, picLeft;
+	
 	switch (argc) {
-	case 1 : {
-		unsigned int port_nr = argv[0].toSint16();
-		GfxPort *new_port;
-
-		/* We depart from official semantics here, sorry!
-		   Reasoning: Sierra SCI does not clip ports while we do.
-		   Therefore a draw to the titlebar port (which is the
-		   official semantics) would cut off the lower part of the
-		   icons in an SCI1 icon bar. Instead we have an
-		   iconbar_port that does not exist in SSCI. */
-		if (port_nr == (unsigned int) - 1) port_nr = s->iconbar_port->_ID;
-
-		new_port = s->visual->getPort(port_nr);
-
-		if (!new_port) {
-			warning("Invalid port %04x requested", port_nr);
-			return NULL_REG;
-		}
-
-		s->port->draw(gfxw_point_zero); // Update the port we're leaving
-		s->port = new_port;
-		return s->r_acc;
-	}
-	case 6 : {
-		port_origin_y = argv[0].toSint16();
-		port_origin_x = argv[1].toSint16();
-
-		if (argv[0].toSint16() == -10) {
-			s->port->draw(gfxw_point_zero); // Update the port we're leaving
-			s->port = s->iconbar_port;
-			activated_icon_bar = true;
-			return s->r_acc;
-		}
-
-		// Notify the graphics resource manager that the pic port bounds changed
-		s->gfx_state->gfxResMan->changePortBounds(argv[5].toUint16(), argv[4].toUint16(), argv[3].toUint16() + argv[5].toUint16(), argv[2].toUint16() + argv[4].toUint16());
-
-		// LSL6 calls kSetPort to extend the screen to draw the GUI. If we free all resources
-		// here, the background picture is freed too, and this makes everything a big mess.
-		// FIXME/TODO: This code really needs to be rewritten to conform to the original behavior
-		if (s->_gameName != "lsl6") {
-			s->gfx_state->pic_port_bounds = gfx_rect(argv[5].toUint16(), argv[4].toUint16(), argv[3].toUint16(), argv[2].toUint16());
-
-			// FIXME: Should really only invalidate all loaded pic resources here;
-			// this is overkill
-			s->gfx_state->gfxResMan->freeAllResources();
-		} else {
-			// WORKAROUND for LSL6
-			printf("SetPort case 6 called in LSL6. Origin: %d, %d - Clip rect: %d, %d, %d, %d\n", argv[1].toSint16(), argv[0].toSint16(), argv[5].toUint16(), argv[4].toUint16(), argv[3].toUint16(), argv[2].toUint16());
-		}
+		case 1:
+		portPtr = argv[0].toSint16();
+		s->gui->setPort(portPtr);
+		break;
 
+		case 6:
+		picRect.top = argv[0].toSint16();
+		picRect.left = argv[1].toSint16();
+		picRect.bottom = argv[2].toSint16();
+		picRect.right = argv[3].toSint16();
+		picTop = argv[4].toSint16();
+		picLeft = argv[5].toSint16();
+		s->gui->setPortPic(picRect, picTop, picLeft);
 		break;
-	}
-	default :
+
+		default:
 		error("SetPort was called with %d parameters", argc);
 		break;
 	}
-
 	return NULL_REG;
 }
 
@@ -2428,142 +2250,37 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) {
 	int cel = argv[2].toSint16();
 	int x = argv[3].toSint16();
 	int y = argv[4].toSint16();
-	int priority = (argc > 5) ? argv[5].toSint16() : -1;
-	GfxView *new_view;
-
-	gfxop_check_cel(s->gfx_state, view, &loop, &cel);
-
-	debugC(2, kDebugLevelGraphics, "DrawCel((%d,%d), (view.%d, %d, %d), p=%d)\n", x, y, view, loop, cel, priority);
+	int priority = (argc > 5) ? argv[5].toUint16()  : -1;
+	int paletteNo = (argc > 6) ? argv[6].toSint16() : 0;
 
-	new_view = gfxw_new_view(s->gfx_state, Common::Point(x, y), view, loop, cel, 0, priority, -1,
-	                         ALIGN_LEFT, ALIGN_TOP, GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET);
-
-	ADD_TO_CURRENT_PICTURE_PORT(new_view);
-	FULL_REDRAW();
+	s->gui->drawCell(view, loop, cel, x, y, priority, paletteNo);
 
 	return s->r_acc;
 }
 
 reg_t kDisposeWindow(EngineState *s, int argc, reg_t *argv) {
-	unsigned int goner_nr = argv[0].toSint16();
-	GfxPort *goner;
-	GfxPort *pred;
-
-	goner = s->visual->getPort(goner_nr);
-	if ((goner_nr < 3) || (goner == NULL)) {
-		error("Removal of invalid window %04x requested", goner_nr);
-		return s->r_acc;
-	}
-
-	if (s->dyn_views && (GfxContainer *)s->dyn_views->_parent == (GfxContainer *)goner) {
-		reparentize_primary_widget_lists(s, (GfxPort *) goner->_parent);
-	}
-
-	if (s->drop_views && (GfxContainer *)s->drop_views->_parent == (GfxContainer *)goner)
-		s->drop_views = NULL; // Kill it
-
-	pred = gfxw_remove_port(s->visual, goner);
-
-	if (goner == s->port) // Did we kill the active port?
-		s->port = pred;
-
-	// Find the last port that exists and that isn't marked no-switch
-	int id = s->visual->_portRefs.size() - 1;
-	while (id > 0 && (!s->visual->_portRefs[id] || (s->visual->_portRefs[id]->_flags & GFXW_FLAG_NO_IMPLICIT_SWITCH)))
-		id--;
-
-	debugC(2, kDebugLevelGraphics, "Activating port %d after disposing window %d\n", id, goner_nr);
-	s->port = (id >= 0) ? s->visual->_portRefs[id] : 0;
-
-	if (!s->port)
-		s->port = gfxw_find_default_port(s->visual);
-
-	gfxop_update(s->gfx_state);
+	int goner_nr = argv[0].toSint16();
+	int arg2 = (argc != 2 || argv[2].toUint16() == 0 ? 0 : 1);
 
+	s->gui->disposeWindow(goner_nr, arg2);
 	return s->r_acc;
 }
 
 reg_t kNewWindow(EngineState *s, int argc, reg_t *argv) {
-	GfxPort *window;
-	int x, y, xl, yl, flags;
-	gfx_color_t bgcolor;
-	gfx_color_t fgcolor;
-	gfx_color_t black;
-	gfx_color_t lWhite;
-	int priority;
+	Common::Rect rect1 (argv[1].toSint16(), argv[0].toSint16(), argv[3].toSint16(), argv[2].toSint16());
+	Common::Rect rect2;
 	int argextra = argc == 13 ? 4 : 0; // Triggers in PQ3 and SCI1.1 games
+	int	style = argv[5 + argextra].toSint16();
+	int	priority = (argc > 6 + argextra) ? argv[6 + argextra].toSint16() : -1;
+	int colorPen = (argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0;
+	int colorBack = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255;
 
-	y = argv[0].toSint16();
-	x = argv[1].toSint16();
-	yl = argv[2].toSint16() - y;
-	xl = argv[3].toSint16() - x;
-
-	y += s->wm_port->_bounds.y;
-
-	if (x + xl > 319)
-		x -= ((x + xl) - 319);
-
-	flags = argv[5 + argextra].toSint16();
-
-	priority = (argc > 6 + argextra) ? argv[6 + argextra].toSint16() : -1;
-	bgcolor.mask = 0;
-
-	int16 bgColor = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255;
-
-	if (bgColor >= 0) {
-		if (!s->resMan->isVGA())
-			bgcolor.visual = get_pic_color(s, MIN<int>(bgColor, 15));
-		else
-			bgcolor.visual = get_pic_color(s, bgColor);
-		bgcolor.mask = GFX_MASK_VISUAL;
-	} else {
-		bgcolor.visual = PaletteEntry(0,0,0);
-	}
-
-	bgcolor.priority = priority;
-	bgcolor.mask |= priority >= 0 ? GFX_MASK_PRIORITY : 0;
-	bgcolor.alpha = 0;
-	bgcolor.control = -1;
-	debugC(2, kDebugLevelGraphics, "New window with params %d, %d, %d, %d\n", argv[0].toSint16(), argv[1].toSint16(), argv[2].toSint16(), argv[3].toSint16());
-
-	int16 visualColor = (argc > 7 + argextra) ? argv[7 + argextra].toSint16() : 0;
-	fgcolor.visual = get_pic_color(s, visualColor);
-	fgcolor.mask = GFX_MASK_VISUAL;
-	fgcolor.control = -1;
-	fgcolor.priority = -1;
-	fgcolor.alpha = 0;
-	black.visual = get_pic_color(s, 0);
-	black.mask = GFX_MASK_VISUAL;
-	black.alpha = 0;
-	black.control = -1;
-	black.priority = -1;
-	lWhite.visual = get_pic_color(s, !s->resMan->isVGA() ? 15 : 255);
-	lWhite.mask = GFX_MASK_VISUAL;
-	lWhite.alpha = 0;
-	lWhite.priority = -1;
-	lWhite.control = -1;
-	Common::String title;
-	if (argv[4 + argextra].segment) {
-		title = s->segMan->getString(argv[4 + argextra]);
-		title = s->strSplit(title.c_str(), NULL);
-	}
-
-	window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
-							s->titlebar_port->_font, lWhite, black, title.c_str(), flags);
-
-	// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
-	if (argextra)
-		gfxw_port_auto_restore_background(s->visual, window, gfx_rect(argv[5].toSint16(), argv[4].toSint16() + s->wm_port->_bounds.y, argv[7].toSint16() - argv[5].toSint16(), argv[6].toSint16() - argv[4].toSint16()));
-
-	ADD_TO_WINDOW_PORT(window);
-	FULL_REDRAW();
-
-	window->draw(gfxw_point_zero);
-	gfxop_update(s->gfx_state);
-
-	s->port = window; // Set active port
+	//	const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL;
+	if (argc==13) {
+		rect2 = Common::Rect (argv[5].toSint16(), argv[4].toSint16(), argv[7].toSint16(), argv[6].toSint16());
+	}
 
-	return make_reg(0, window->_ID);
+	return s->gui->newWindow(rect1, rect2, style, priority, colorPen, colorBack);
 }
 
 #define K_ANIMATE_CENTER_OPEN_H  0 // horizontally open from center
@@ -3130,208 +2847,21 @@ reg_t kShakeScreen(EngineState *s, int argc, reg_t *argv) {
 	return s->r_acc;
 }
 
-#define K_DISPLAY_SET_COORDS 100
-#define K_DISPLAY_SET_ALIGNMENT 101
-#define K_DISPLAY_SET_COLOR 102
-#define K_DISPLAY_SET_BGCOLOR 103
-#define K_DISPLAY_SET_GRAYTEXT 104
-#define K_DISPLAY_SET_FONT 105
-#define K_DISPLAY_WIDTH 106
-#define K_DISPLAY_SAVE_UNDER 107
-#define K_DISPLAY_RESTORE_UNDER 108
-#define K_DONT_UPDATE_IMMEDIATELY 121
-
 reg_t kDisplay(EngineState *s, int argc, reg_t *argv) {
-	int argpt;
 	reg_t textp = argv[0];
 	int index = (argc > 1) ? argv[1].toUint16() : 0;
-	int temp;
-	bool save_under = false;
-	gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
-	Common::String text;
-	GfxPort *port = (s->port) ? s->port : s->picture_port;
-	bool update_immediately = true;
-
-	gfx_color_t color0, *color1, bg_color;
-	gfx_alignment_t halign = ALIGN_LEFT;
-	rect_t area = gfx_rect(port->draw_pos.x, port->draw_pos.y, 320 - port->draw_pos.x, 200 - port->draw_pos.y);
-	int gray = port->gray_text;
-	int font_nr = port->_font;
-	GfxText *text_handle;
 
-	color0 = port->_color;
-	bg_color = port->_bgcolor;
-	// TODO: in SCI1VGA the default colors for text and background are #0 (black)
-	// SCI0 case should be checked
+	Common::String text;
 
 	if (textp.segment) {
-		argpt = 1;
+		argc--; argv++;
 		text = s->segMan->getString(textp);
 	} else {
-		argpt = 2;
+		argc--; argc--; argv++; argv++;
 		text = kernel_lookup_text(s, textp, index);
 	}
 
-#if 0
-	if (!text) {
-		error("Display with invalid reference %04x:%04x", PRINT_REG(textp));
-		return NULL_REG;
-	}
-#endif
-
-	while (argpt < argc) {
-		switch (argv[argpt++].toUint16()) {
-
-		case K_DISPLAY_SET_COORDS:
-
-			area.x = argv[argpt++].toUint16();
-			area.y = argv[argpt++].toUint16();
-			debugC(2, kDebugLevelGraphics, "Display: set_coords(%d, %d)\n", area.x, area.y);
-			break;
-
-		case K_DISPLAY_SET_ALIGNMENT:
-
-			halign = (gfx_alignment_t)argv[argpt++].toSint16();
-			debugC(2, kDebugLevelGraphics, "Display: set_align(%d)\n", halign);
-			break;
-
-		case K_DISPLAY_SET_COLOR:
-
-			temp = argv[argpt++].toSint16();
-			debugC(2, kDebugLevelGraphics, "Display: set_color(%d)\n", temp);
-			if (!s->resMan->isVGA() && temp >= 0 && temp <= 15)
-				color0 = (s->ega_colors[temp]);
-			else
-				if (s->resMan->isVGA() && temp >= 0 && temp < 256) {
-					color0.visual = get_pic_color(s, temp);
-					color0.mask = GFX_MASK_VISUAL;
-				} else
-					if (temp == -1)
-						color0 = transparent;
-					else
-						warning("Display: Attempt to set invalid fg color %d", temp);
-			break;
-
-		case K_DISPLAY_SET_BGCOLOR:
-
-			temp = argv[argpt++].toSint16();
-			debugC(2, kDebugLevelGraphics, "Display: set_bg_color(%d)\n", temp);
-			if (!s->resMan->isVGA() && temp >= 0 && temp <= 15)
-				bg_color = s->ega_colors[temp];
-			else
-				if (s->resMan->isVGA() && temp >= 0 && temp <= 256) {
-					bg_color.visual = get_pic_color(s, temp);
-					bg_color.mask = GFX_MASK_VISUAL;
-				} else
-					if (temp == -1)
-						bg_color = transparent;
-					else
-						warning("Display: Attempt to set invalid fg color %d", temp);
-			break;
-
-		case K_DISPLAY_SET_GRAYTEXT:
-
-			gray = argv[argpt++].toSint16();
-			debugC(2, kDebugLevelGraphics, "Display: set_graytext(%d)\n", gray);
-			break;
-
-		case K_DISPLAY_SET_FONT:
-
-			font_nr = argv[argpt++].toUint16();
-
-			debugC(2, kDebugLevelGraphics, "Display: set_font(\"font.%03d\")\n", font_nr);
-			break;
-
-		case K_DISPLAY_WIDTH:
-
-			area.width = argv[argpt++].toUint16();
-			if (area.width == 0)
-				area.width = MAX_TEXT_WIDTH_MAGIC_VALUE;
-
-			debugC(2, kDebugLevelGraphics, "Display: set_width(%d)\n", area.width);
-			break;
-
-		case K_DISPLAY_SAVE_UNDER:
-
-			save_under = true;
-			debugC(2, kDebugLevelGraphics, "Display: set_save_under()\n");
-			break;
-
-		case K_DISPLAY_RESTORE_UNDER:
-
-			debugC(2, kDebugLevelGraphics, "Display: restore_under(%04x)\n", argv[argpt].toUint16());
-			graph_restore_box(s, argv[argpt++]);
-			update_immediately = true;
-			argpt++;
-			return s->r_acc;
-
-		case K_DONT_UPDATE_IMMEDIATELY:
-
-			update_immediately = false;
-			debugC(2, kDebugLevelGraphics, "Display: set_dont_update()\n");
-			argpt++;
-			break;
-
-		default:
-			debugC(2, kDebugLevelGraphics, "Unknown Display() command %x\n", argv[argpt - 1].toUint16());
-			return NULL_REG;
-		}
-	}
-
-	if (halign == ALIGN_LEFT) {
-		// If the text does not fit on the screen, move it to the left and upwards until it does
-		gfxop_get_text_params(s->gfx_state, font_nr, text.c_str(), area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
-
-		// Make the text fit on the screen
-		if (area.x + area.width > 320)
-			area.x += 320 - area.x - area.width; // Plus negative number = subtraction
-
-		if (area.y + area.height > 200)
-			area.y += 200 - area.y - area.height; // Plus negative number = subtraction
-	} else {
-		// If the text does not fit on the screen, clip it till it does
-		if (area.x + area.width > s->gfx_state->pic_port_bounds.width)
-			area.width = s->gfx_state->pic_port_bounds.width - area.x;
-
-		if (area.y + area.height > s->gfx_state->pic_port_bounds.height)
-			area.height = s->gfx_state->pic_port_bounds.height - area.y;
-	}
-
-	if (gray)
-		color1 = &bg_color;
-	else
-		color1 = &color0;
-
-	assert_primary_widget_lists(s);
-
-	text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text.c_str()).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
-
-	if (!text_handle) {
-		error("Display: Failed to create text widget");
-		return NULL_REG;
-	}
-
-	if (save_under) {    // Backup
-		rect_t save_area = text_handle->_bounds;
-		save_area.x += port->_bounds.x;
-		save_area.y += port->_bounds.y;
-
-		s->r_acc = graph_save_box(s, save_area);
-		text_handle->_serial++; // This is evil!
-
-		debugC(2, kDebugLevelGraphics, "Saving (%d, %d) size (%d, %d) as %04x:%04x\n", save_area.x, save_area.y, save_area.width, save_area.height, PRINT_REG(s->r_acc));
-	}
-
-	debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text.c_str());
-
-	//ADD_TO_CURRENT_PICTURE_PORT(text_handle);
-
-	ADD_TO_CURRENT_PICTURE_PORT(text_handle);
-	if ((!s->pic_not_valid) && update_immediately) { // Refresh if drawn to valid picture
-		FULL_REDRAW();
-		debugC(2, kDebugLevelGraphics, "Refreshing display...\n");
-	}
-
+	s->gui->display(s->strSplit(text.c_str()).c_str(), argc, argv);
 	return s->r_acc;
 }
 
@@ -3488,4 +3018,16 @@ reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) {
 	return s->r_acc;
 }
 
+// New calls for SCI11. Using those is only needed when using text-codes so that one is able to change
+//  font and/or color multiple times during kDisplay and kDrawControl
+reg_t kTextFonts(EngineState *s, int argc, reg_t *argv) {
+	s->gui->textFonts(argc, argv);
+	return s->r_acc;
+}
+
+reg_t kTextColors(EngineState *s, int argc, reg_t *argv) {
+	s->gui->textColors(argc, argv);
+	return s->r_acc;
+}
+
 } // End of namespace Sci
diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp
index 4d0bd8a..e46f707 100644
--- a/engines/sci/engine/kmisc.cpp
+++ b/engines/sci/engine/kmisc.cpp
@@ -131,7 +131,8 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
 
 	switch (mode) {
 	case K_NEW_GETTIME_TICKS :
-		retval = start_time * 60 / 1000;
+		retval = s->gui->getTimeTicks();	// FIXME
+		//retval = start_time * 60 / 1000;
 		debugC(2, kDebugLevelTime, "GetTime(elapsed) returns %d", retval);
 		break;
 	case K_NEW_GETTIME_TIME_12HOUR :
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index cf7e163..a8dbce5 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -44,6 +44,7 @@ namespace Common {
 #include "sci/engine/seg_manager.h"
 #include "sci/gfx/gfx_system.h"
 #include "sci/sfx/core.h"
+#include "sci/gui/gui.h"
 
 namespace Sci {
 
@@ -175,6 +176,8 @@ public:
 
 	/* Non-VM information */
 
+	SciGUI *gui; /* Currently active GUI */
+
 	GfxState *gfx_state; /**< Graphics state and driver */
 	gfx_pixmap_t *old_screen; /**< Old screen content: Stored during kDrawPic() for kAnimate() */
 
@@ -319,6 +322,12 @@ private:
  */
 PaletteEntry get_pic_color(EngineState *s, int color);
 
+/* Functions used in gui32\gui32.cpp */
+reg_t graph_save_box(EngineState *s, rect_t area);
+void graph_restore_box(EngineState *s, reg_t handle);
+void assert_primary_widget_lists(EngineState *s);
+void reparentize_primary_widget_lists(EngineState *s, GfxPort *newport);
+
 } // End of namespace Sci
 
 #endif // SCI_INCLUDE_ENGINE_H
diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp
index 15704b6..ccf15f3 100644
--- a/engines/sci/gfx/gfx_driver.cpp
+++ b/engines/sci/gfx/gfx_driver.cpp
@@ -248,4 +248,19 @@ void GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) {
 	cursorData = 0;
 }
 
+void GfxDriver::animatePalette(int fromColor, int toColor, int stepCount) {
+	int i;
+	PaletteEntry firstColor = _mode->palette->getColor(fromColor);
+	PaletteEntry loopColor;
+	for (i=fromColor+1; i<=toColor; i++) {
+		loopColor = _mode->palette->getColor(i);
+		loopColor.r = 0;
+		loopColor.g = 0;
+		loopColor.b = 0;
+		_mode->palette->makeSystemColor(i-1, loopColor); // loopColor.r, loopColor.g, loopColor.b);
+	}
+//	_mode->palette->setColor(toColor, firstColor.r, firstColor.g, firstColor.b);
+	_mode->palette->makeSystemColor(toColor, firstColor);
+}
+
 } // End of namespace Sci
diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h
index ede48a6..1143d8e 100644
--- a/engines/sci/gfx/gfx_driver.h
+++ b/engines/sci/gfx/gfx_driver.h
@@ -228,6 +228,11 @@ public:
 	gfx_mode_t *getMode() { return _mode; }
 	byte *getVisual0() { return _visual[0]; }
 
+	/**
+	 * Animates palette
+	 */
+	void animatePalette(int fromColor, int toColor, int stepCount);
+
 private:
 	gfx_pixmap_t *_priority[2];
 	byte *_visual[2];
diff --git a/engines/sci/gfx/res_view.cpp b/engines/sci/gfx/res_view.cpp
index 95f6919..cbe26b9 100644
--- a/engines/sci/gfx/res_view.cpp
+++ b/engines/sci/gfx/res_view.cpp
@@ -365,6 +365,12 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso
 	return retval;
 }
 
+// SCI1:
+// [LoopCount:WORD] [MirrorMask:WORD] [??:WORD] [PaletteOffset:WORD] [LoopOffset0:WORD] [LoopOffset1:WORD]...
+// Loop-data:
+// [CellCount:WORD] [Unknown:WORD] [CellOffset0:WORD] [CellOffset1:WORD]...
+// SCI11:
+// [HeaderSize:WORD] [LoopCount:BYTE] [Unknown:BYTE] [??:WORD] [??:WORD] [PaletteOffset:WORD]
 gfxr_view_t *getVGAView(int id, byte *resource, int size, ViewType viewType) {
 	uint16 palOffset = READ_LE_UINT16(resource + V1_PALETTE_OFFSET + ((viewType == kViewVga11) ? 2 : 0));
 	uint16 headerSize = (viewType == kViewVga11) ? READ_LE_UINT16(resource + V2_HEADER_SIZE) : 0;
diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp
new file mode 100644
index 0000000..307aab8
--- /dev/null
+++ b/engines/sci/gui/gui.cpp
@@ -0,0 +1,330 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_screen.h"
+#include "sci/gui/gui_gfx.h"
+#include "sci/gui/gui_windowmgr.h"
+#include "sci/gui/gui_memmgr.h"
+#include "sci/gui/gui_view.h"
+
+#include "sci/gfx/operations.h"
+
+namespace Sci {
+
+SciGUI::SciGUI(OSystem *system, EngineState *state)
+	: _system(system), _s(state) {
+	_screen = new SciGUIscreen(_system, _s);
+	_gfx = new SciGUIgfx(_system, _s, _screen);
+	_windowMgr = new SciGUIwindowMgr(_s, _gfx);
+}
+
+SciGUI::SciGUI() {
+}
+
+SciGUI::~SciGUI() {
+}
+
+void SciGUI::init(bool oldGfxFunctions) {
+	_usesOldGfxFunctions = oldGfxFunctions;
+
+	/* Set default SCI0 palette */
+}
+
+int16 SciGUI::getTimeTicks() {
+	return _gfx->_sysTicks;
+}
+
+void SciGUI::wait(int16 ticks) {
+	uint32 waitto = _gfx->_sysTicks + ticks;
+	do {
+		//eventMgr->pollEvents();
+		_system->delayMillis(_gfx->_sysSpeed >> 11);
+	} while (_gfx->_sysTicks < waitto);
+}
+
+void SciGUI::setPort(uint16 portPtr) {
+	switch (portPtr) {
+		case 0: _gfx->SetPort(_windowMgr->_wmgrPort); break;
+		case 0xFFFF: _gfx->SetPort(_gfx->_menuPort); break;
+		default:
+			_gfx->SetPort((sciPort *)heap2Ptr(portPtr));
+	};
+}
+
+void SciGUI::setPortPic(Common::Rect rect, int16 picTop, int16 picLeft) {
+	_windowMgr->_picWind->rect = rect;
+	_windowMgr->_picWind->top = picTop;
+	_windowMgr->_picWind->left = picLeft;
+	//if (argc >= 7)
+		//InitPri(42,190);
+}
+
+reg_t SciGUI::getPort() {
+	return make_reg(0, ptr2heap((byte *)_gfx->GetPort()));
+}
+
+void SciGUI::globalToLocal(int16 *x, int16 *y) {
+	sciPort *curPort = _gfx->GetPort();
+	*x = *x - curPort->left;
+	*y = *y - curPort->top;
+}
+
+void SciGUI::localToGlobal(int16 *x, int16 *y) {
+	sciPort *curPort = _gfx->GetPort();
+	*x = *x + curPort->left;
+	*y = *y + curPort->top;
+}
+
+reg_t SciGUI::newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack) {
+	sciWnd *wnd = NULL;
+
+	if (rect2.top != 0 && rect2.left != 0 && rect2.height() != 0 && rect2.width() != 0)
+		wnd = _windowMgr->NewWindow(&rect1, &rect2, "", style, priority, 0);
+	else
+		wnd = _windowMgr->NewWindow(&rect1, NULL, "", style, priority, 0);
+	wnd->penClr = colorPen;
+	wnd->backClr = colorBack;
+	_windowMgr->DrawWindow(wnd);
+	return make_reg(0, ptr2heap((byte *)wnd));
+}
+
+void SciGUI::disposeWindow(uint16 windowPtr, int16 arg2) {
+	sciWnd *wnd = (sciWnd *)heap2Ptr(windowPtr);
+	_windowMgr->DisposeWindow(wnd, arg2);
+}
+
+void SciGUI::display(const char *text, int argc, reg_t *argv) {
+	int displayArg;
+	sciPort oldPort;
+	int16 align = 0;
+	int16 bgcolor = -1, width = 0xFFFF, bRedraw = 1;
+	byte bSaveUnder = false;
+	Common::Rect rect, *orect = &((sciWnd *)_gfx->GetPort())->rect0;
+
+	memcpy(&oldPort, _gfx->GetPort(), sizeof(sciPort));
+	// setting defaults
+	_gfx->PenMode(0);
+	_gfx->PenColor(0);
+	_gfx->TextFace(0);
+	// processing codes in argv
+	while (argc > 0) {
+		displayArg = argv[0].toUint16();
+		argc--; argv++;
+		switch (displayArg - 100) {
+		case 0:
+			_gfx->MoveTo(argv[0].toUint16(), argv[1].toUint16());
+			argc -= 2; argv += 2;
+			break;// move pen
+		case 1:
+			align = argv[0].toUint16();
+			argc--; argv++;
+			break;// set alignment
+		case 2:
+			_gfx->PenColor(argv[0].toUint16());
+			argc--; argv++;
+			break;// set pen color
+		case 3:
+			bgcolor = argv[0].toUint16();
+			argc--; argv++;
+			break;
+		case 4:
+			_gfx->TextFace(argv[0].toUint16());
+			argc--; argv++;
+			break;// set text grayout flag
+		case 5:
+			_gfx->SetFont(argv[0].toUint16());
+			argc--; argv++;
+			break;// set font
+		case 6:
+			width = argv[0].toUint16();
+			argc--; argv++;
+			break;
+		case 7:
+			bSaveUnder = 1;
+			break;
+		case 8: // restore under
+//			if (hunk2Ptr(*pArgs)) {
+//				memcpy(&rect, hunk2Ptr(*pArgs), sizeof(Common::Rect));
+//				// rect is now absolute. Have to move it to be port-relative
+//				rect.translate(-_gfx->RGetPort()->left, -_gfx->RGetPort()->top);
+//				_gfx->RestoreBits(*pArgs);
+//				ReAnimate(&rect);
+//			}
+			// finishing loop
+			argc = 0;
+			break;
+		case 0x15:
+			bRedraw = 0;
+			break;
+		default:
+			warning("Unknown kDisplay argument %X", displayArg);
+			break;
+		}
+	}
+	// now drawing the text
+	_gfx->TextSize(rect, text, -1, width);
+	_gfx->Move((orect->left <= 320 ? 0 : 320 - orect->left), (orect->top <= 200 ? 0 : 200 - orect->top)); // move port to (0,0)
+	rect.moveTo(_gfx->GetPort()->curLeft, _gfx->GetPort()->curTop);
+//	if (bSaveUnder)
+//		_acc = _gfx->SaveBits(rect, 1);
+	if (bgcolor != -1)
+		_gfx->FillRect(rect, 1, bgcolor, 0, 0);
+	_gfx->TextBox(text, 0, rect, align, 0xFFFF);
+//	if (_picNotValid == 0 && bRedraw)
+//		_gfx->ShowBits(rect, 1);
+	// restoring port and cursor pos
+	sciPort *currport = _gfx->GetPort();
+	uint16 tTop = currport->curTop;
+	uint16 tLeft = currport->curLeft;
+	memcpy(currport, &oldPort, sizeof(sciPort));
+	currport->curTop = tTop;
+	currport->curLeft = tLeft;
+
+	_screen->UpdateWhole();
+}
+
+void SciGUI::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
+	Common::Rect rect(0, 0, *textWidth, *textHeight);
+	_gfx->TextSize(rect, text, font, maxWidth);
+	*textWidth = rect.width(); *textHeight = rect.height();
+}
+
+// Used SCI1+ for text codes
+void SciGUI::textFonts(int argc, reg_t *argv) {
+}
+
+// Used SCI1+ for text codes
+void SciGUI::textColors(int argc, reg_t *argv) {
+}
+
+void SciGUI::drawPicture(sciResourceId pictureId, uint16 style, uint16 flags, int16 EGApaletteNo) {
+	bool addToFlag = flags ? true : false;
+
+	sciPort *oldPort = _gfx->SetPort((sciPort *)_windowMgr->_picWind);
+
+	if (_windowMgr->isFrontWindow(_windowMgr->_picWind)) {
+		_gfx->drawPicture(pictureId, style, addToFlag, EGApaletteNo);
+	} else {
+		_windowMgr->BeginUpdate(_windowMgr->_picWind);
+		_gfx->drawPicture(pictureId, style, addToFlag, EGApaletteNo);
+		_windowMgr->EndUpdate(_windowMgr->_picWind);
+	}
+	_screen->UpdateWhole();
+
+	_gfx->SetPort(oldPort);
+	_s->pic_not_valid = 1;
+}
+
+void SciGUI::drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo) {
+	_gfx->drawCell(viewId, loopNo, cellNo, leftPos, topPos, priority, paletteNo);
+	_gfx->SetCLUT(&_gfx->_sysPalette);
+	_screen->UpdateWhole();
+}
+
+void SciGUI::drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse) {
+	rect.grow(1);
+	_gfx->EraseRect(rect);
+	_gfx->FrameRect(rect);
+	rect.grow(-2);
+	_gfx->TextFace(style & 1 ? 0 : 1);
+	_gfx->TextBox(text, 0, rect, 1, fontId);
+	_gfx->TextFace(0);
+	if (style & 8) { // selected
+		rect.grow(1);
+		_gfx->FrameRect(rect);
+	}
+	_screen->UpdateWhole();
+}
+
+void SciGUI::drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse) {
+	rect.grow(1);
+	_gfx->EraseRect(rect);
+	rect.grow(-1);
+	_gfx->TextBox(text, 0, rect, mode, fontId);
+	if (style & 8) { // selected
+		_gfx->FrameRect(rect);
+	}
+	_screen->UpdateWhole();
+}
+
+void SciGUI::graphFillBoxForeground(Common::Rect rect) {
+	_gfx->PaintRect(rect);
+	_screen->UpdateWhole();
+}
+
+void SciGUI::graphFillBoxBackground(Common::Rect rect) {
+	_gfx->EraseRect(rect);
+	_screen->UpdateWhole();
+}
+
+void SciGUI::graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) {
+	_gfx->FillRect(rect, colorMask, color, priority, control);
+	_screen->UpdateWhole();
+}
+
+void SciGUI::graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control) {
+	_gfx->Draw_Line(rect.left, rect.top, rect.right, rect.bottom, color, priority, control);
+	_screen->UpdateWhole();
+}
+
+reg_t SciGUI::graphSaveBox(Common::Rect rect, uint16 flags) {
+	return _gfx->SaveBits(rect, flags);
+}
+
+void SciGUI::graphRestoreBox(reg_t handle) {
+	_gfx->RestoreBits(handle);
+	_screen->UpdateWhole();
+}
+
+void SciGUI::paletteSet(int resourceNo, int flags) {
+   _gfx->SetResPalette(resourceNo, flags);
+}
+
+int16 SciGUI::paletteFind(int r, int g, int b) {
+	return _gfx->MatchColor(&_gfx->_sysPalette, r, g, b) & 0xFF;
+}
+
+void SciGUI::paletteAnimate(int fromColor, int toColor, int speed) {
+	_gfx->animatePalette(fromColor, toColor, speed);
+}
+
+void SciGUI::moveCursor(int16 x, int16 y) {
+	Common::Point newPos;
+	sciPort *curPort = _gfx->GetPort();
+	
+	x += _windowMgr->_picWind->rect.left;
+	y += _windowMgr->_picWind->rect.top;
+	newPos.x = CLIP<int16> (x, _windowMgr->_picWind->rect.left, _windowMgr->_picWind->rect.right - 1);
+	newPos.y = CLIP<int16> (y, _windowMgr->_picWind->rect.top, _windowMgr->_picWind->rect.bottom - 1);
+
+	gfxop_set_pointer_position(_s->gfx_state, newPos);
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/gui/gui.h b/engines/sci/gui/gui.h
new file mode 100644
index 0000000..9a16f55
--- /dev/null
+++ b/engines/sci/gui/gui.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/gui/gui_helpers.h"
+
+namespace Sci {
+
+class SciGUIscreen;
+class SciGUIgfx;
+class SciGUIresources;
+class SciGUIwindowMgr;
+class SciGUI {
+public:
+	SciGUI(OSystem *system, EngineState *s);
+	SciGUI();
+	~SciGUI();
+
+	virtual void init(bool oldGfxFunctions);
+
+	virtual int16 getTimeTicks();
+	virtual void wait(int16 ticks);
+	virtual void setPort(uint16 portPtr);
+	virtual void setPortPic(Common::Rect rect, int16 picTop, int16 picLeft);
+	virtual reg_t getPort();
+	virtual void globalToLocal(int16 *x, int16 *y);
+	virtual void localToGlobal(int16 *x, int16 *y);
+	virtual reg_t newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack);
+	virtual void disposeWindow(uint16 windowPtr, int16 arg2);
+
+	virtual void display(const char *text, int argc, reg_t *argv);
+
+	virtual void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+	virtual void textFonts(int argc, reg_t *argv);
+	virtual void textColors(int argc, reg_t *argv);
+
+	virtual void drawPicture(sciResourceId pictureId, uint16 showStyle, uint16 flags, int16 EGApaletteNo);
+	virtual void drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo);
+	virtual void drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse);
+	virtual void drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse);
+
+	virtual void graphFillBoxForeground(Common::Rect rect);
+	virtual void graphFillBoxBackground(Common::Rect rect);
+	virtual void graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control);
+	virtual void graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control);
+	virtual reg_t graphSaveBox(Common::Rect rect, uint16 flags);
+	virtual void graphRestoreBox(reg_t handle);
+
+	virtual void paletteSet(int resourceNo, int flags);
+	virtual int16 paletteFind(int r, int g, int b);
+	virtual void paletteAnimate(int fromColor, int toColor, int speed);
+
+	virtual void moveCursor(int16 x, int16 y);
+
+private:
+	OSystem *_system;
+	EngineState *_s;
+	SciGUIscreen *_screen;
+	SciGUIgfx *_gfx;
+	SciGUIresources *_resources;
+	SciGUIwindowMgr *_windowMgr;
+	bool _usesOldGfxFunctions;
+};
+
+} // End of namespace Sci
diff --git a/engines/sci/gui/gui_dbllist.cpp b/engines/sci/gui/gui_dbllist.cpp
new file mode 100644
index 0000000..c441308
--- /dev/null
+++ b/engines/sci/gui/gui_dbllist.cpp
@@ -0,0 +1,257 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+
+#include "sci/sci.h"
+#include "sci/gui/gui_helpers.h"
+#include "sci/gui/gui_memmgr.h"
+#include "sci/gui/gui_dbllist.h"
+
+namespace Sci {
+
+DblList::DblList() {
+	_hFirst = 0;
+	_hLast = 0;
+}
+
+DblList::DblList(HEAPHANDLE heap) {
+	byte *ptr = heap2Ptr(heap);
+	_hFirst = READ_UINT16(ptr);
+	_hLast = READ_UINT16(ptr + 2);
+}
+
+DblList::~DblList(void) {
+}
+//--------------------------------------
+// Prints all list contents
+void DblList::Dump(char*caption) {
+	debug("DumpList %s:", caption);
+	debug("  First: %04X Last: %04X", _hFirst, _hLast);
+	HEAPHANDLE node = _hFirst;
+	while (node) {
+		sciNode *pNode = (sciNode *)heap2Ptr(node);
+		debug("  %04X key=%04X prev=%04X next=%04X add.data=%db", node,
+				pNode->key, pNode->prev, pNode->next, heapGetDataSize(node) - 6);
+		node = pNode->next;
+	}
+	debug("End of list");
+}
+//--------------------------------------
+// Add a new node to front of the list
+HEAPHANDLE DblList::AddToFront(HEAPHANDLE node, uint16 key) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::AddToFront !",
+				node);
+		return node;
+	}
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	pNode->key = key;
+	if (_hFirst) { // we already have  a 1st node
+		sciNode *pnext = (sciNode *)heap2Ptr(_hFirst);
+		pnext->prev = node;
+		pNode->next = _hFirst;
+	} else { // list is empty, to passed node becames 1st one
+		_hLast = node;
+		pNode->next = 0;
+	}
+	_hFirst = node;
+	pNode->prev = 0;
+	return node;
+}
+
+//-------------------------------------
+//
+HEAPHANDLE DblList::AddToEnd(HEAPHANDLE node, uint16 key) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::AddToEnd !", node);
+		return node;
+	}
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	if (_hFirst) { // list is not empty
+		sciNode *plast = (sciNode *)heap2Ptr(_hLast);
+		plast->next = node;
+		pNode->prev = _hLast;
+	} else { // list is empty, so the node becames 1st one
+		_hFirst = node;
+		pNode->prev = 0;
+	}
+	_hLast = node;
+	pNode->next = 0;
+	pNode->key = key;
+
+	return node;
+}
+
+//------------------------------------------------
+// returns node that contains the key
+HEAPHANDLE DblList::FindKey(uint16 key) {
+	HEAPHANDLE node = _hFirst;
+	while (node) {
+		sciNode *pNode = (sciNode *)heap2Ptr(node);
+		if (pNode->key == key)
+			break;
+		node = pNode->next;
+	}
+	return node;
+}
+//------------------------------------------------
+// detaches node with specified key and returning the node
+HEAPHANDLE DblList::DeleteKey(uint16 key) {
+	HEAPHANDLE node = FindKey(key);
+	if (node)
+		DeleteNode(node);
+	return node;
+}
+//------------------------------------------------
+// detaches specified node from list
+byte DblList::DeleteNode(HEAPHANDLE node) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::AddToEnd !", node);
+		return node;
+	}
+	// updating the links
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	if (pNode->prev) {
+		sciNode *pprev = (sciNode *)heap2Ptr(pNode->prev);
+		pprev->next = pNode->next;
+	}
+	if (pNode->next) {
+		sciNode *pnext = (sciNode *)heap2Ptr(pNode->next);
+		pnext->prev = pNode->prev;
+	}
+	// updating list head if needed
+	if (_hFirst == node)
+		_hFirst = pNode->next;
+	if (_hLast == node)
+		_hLast = pNode->prev;
+	pNode->prev = 0;
+	pNode->next = 0;
+	return 1;
+}
+//------------------------------------------------
+// Moves node to the end of the list
+HEAPHANDLE DblList::MoveToEnd(HEAPHANDLE node) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::MoveToEnd !", node);
+		return node;
+	}
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	if (pNode->next) { // node is not the last one in list
+		DeleteNode(node);
+		AddToEnd(node, pNode->key);
+	}
+	return node;
+}
+//------------------------------------------------
+// Moves node to the front of the list
+HEAPHANDLE DblList::MoveToFront(HEAPHANDLE node) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::MoveToFront !",
+				node);
+		return node;
+	}
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	if (pNode->prev) { // node is not 1st one in list
+		DeleteNode(node);
+		AddToFront(node, pNode->key);
+	}
+	return node;
+}
+//------------------------------------------------
+HEAPHANDLE DblList::AddAfter(HEAPHANDLE ref, HEAPHANDLE node, uint16 key) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::AddAfter !", node);
+		return node;
+	}
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	sciNode *pref = (sciNode *)heap2Ptr(ref);
+	pNode->key = key;
+	if (pref->next == 0) { // ref node is the last one
+		pNode->next = 0;
+		_hLast = node;
+	} else {
+		sciNode *pnext = (sciNode *)heap2Ptr(pref->next);
+		pNode->next = pref->next;
+		pnext->prev = node;
+	}
+	pref->next = node;
+	pNode->prev = ref;
+	return node;
+}
+//------------------------------------------------
+//
+HEAPHANDLE DblList::AddBefore(HEAPHANDLE ref, HEAPHANDLE node, uint16 key) {
+	if (!node) {
+		warning("Bad node handler (%04X) passed to DblList::AddBefore !", node);
+		return node;
+	}
+	sciNode *pNode = (sciNode *)heap2Ptr(node);
+	sciNode *pref = (sciNode *)heap2Ptr(ref);
+	pNode->key = key;
+	if (pref->prev == 0) { // ref node is the 1st one
+		pNode->prev = 0;
+		_hFirst = node;
+	} else {
+		sciNode*pprev = (sciNode *)heap2Ptr(pref->prev);
+		pNode->prev = pref->prev;
+		pprev->next = node;
+	}
+	pref->prev = node;
+	pNode->next = ref;
+	return node;
+}
+//------------------------------------------------
+void DblList::toHeap(HEAPHANDLE heap) {
+	byte *ptr = heap2Ptr(heap);
+	WRITE_UINT16(ptr, _hFirst);
+	WRITE_UINT16(ptr + 2, _hLast);
+}
+//------------------------------------------------
+void DblList::DeleteList() {
+	HEAPHANDLE node = getFirst(), next;
+	sciNode *pNode;
+	while (node) {
+		pNode = (sciNode *)heap2Ptr(node);
+		next = pNode->next;
+		heapDisposePtr(node);
+		node = next;
+	}
+	_hFirst = _hLast = 0;
+}
+//------------------------------------------------
+uint16 DblList::getSize() {
+	uint16 cnt = 0;
+	HEAPHANDLE node = getFirst();
+	sciNode *pNode;
+	while (node) {
+		pNode = (sciNode *)heap2Ptr(node);
+		node = pNode->next;
+		cnt++;
+	}
+	return cnt;
+}
+//------------------------------------------------
+} // end of namespace
diff --git a/engines/sci/gui/gui_dbllist.h b/engines/sci/gui/gui_dbllist.h
new file mode 100644
index 0000000..fe3cd36
--- /dev/null
+++ b/engines/sci/gui/gui_dbllist.h
@@ -0,0 +1,74 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+/*
+ Each node contains handles to next and previous node and an optional key for searching
+ Head node contains handles to first and last node
+ */
+
+namespace Sci {
+
+typedef uint16 HEAPHANDLE;
+
+class DblList {
+public:
+	DblList();
+	DblList(HEAPHANDLE heap);
+	~DblList(void);
+protected:
+	HEAPHANDLE _hFirst, _hLast;
+public:
+	// Add a new node to front of the list
+	HEAPHANDLE AddToFront(HEAPHANDLE node, uint16 key = 0);
+	HEAPHANDLE AddToEnd(HEAPHANDLE node, uint16 key = 0);
+	HEAPHANDLE MoveToEnd(HEAPHANDLE node);
+	HEAPHANDLE MoveToFront(HEAPHANDLE node);
+	HEAPHANDLE AddAfter(HEAPHANDLE ref, HEAPHANDLE node, uint16 key = 0);
+	HEAPHANDLE AddBefore(HEAPHANDLE ref, HEAPHANDLE node, uint16 key = 0);
+
+	HEAPHANDLE FindKey(uint16 key);
+	HEAPHANDLE DeleteKey(uint16 key);
+	byte DeleteNode(HEAPHANDLE node);
+	void DeleteList();
+	void Dump(char*caption = ""); // for debug
+	HEAPHANDLE getFirst() {
+		return _hFirst;
+	}
+	HEAPHANDLE getLast() {
+		return _hLast;
+	}
+	void toHeap(HEAPHANDLE heap);
+	bool isEmpty() {
+		return (_hFirst == 0 && _hLast == 0);
+	}
+	uint16 getSize();
+	void set(HEAPHANDLE first, HEAPHANDLE last){
+		_hFirst = first;
+		_hLast = last;
+	}
+
+};
+
+} // end of namespace
diff --git a/engines/sci/gui/gui_font.cpp b/engines/sci/gui/gui_font.cpp
new file mode 100644
index 0000000..c27ae35
--- /dev/null
+++ b/engines/sci/gui/gui_font.cpp
@@ -0,0 +1,100 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_screen.h"
+#include "sci/gui/gui_font.h"
+
+namespace Sci {
+
+SciGUIfont::SciGUIfont(OSystem *system, EngineState *state, SciGUIscreen *screen, sciResourceId resourceId)
+	: _system(system), _s(state), _screen(screen), _resourceId(resourceId) {
+	assert(resourceId != -1);
+	initData(resourceId);
+}
+
+SciGUIfont::~SciGUIfont() {
+}
+
+void SciGUIfont::initData(sciResourceId resourceId) {
+	Resource *fontResource = _s->resMan->findResource(ResourceId(kResourceTypeFont, resourceId), false);
+	if (!fontResource) {
+		error("font resource %d not found", resourceId);
+	}
+	_resourceData = fontResource->data;
+
+	mCharMax = READ_LE_UINT16(_resourceData + 2);
+	mFontH = READ_LE_UINT16(_resourceData + 4);
+	mChars = new charinfo[mCharMax];
+	// filling info for every char
+	for (int16 i = 0; i < mCharMax; i++) {
+		mChars[i].offset = READ_LE_UINT16(_resourceData + 6 + i * 2);
+		mChars[i].w = _resourceData[mChars[i].offset];
+		mChars[i].h = _resourceData[mChars[i].offset + 1];
+	}
+}
+
+sciResourceId SciGUIfont::getResourceId() {
+	return _resourceId;
+}
+
+byte SciGUIfont::getHeight() {
+	return mFontH;
+}
+byte SciGUIfont::getCharWidth(byte chr) {
+	return chr < mCharMax ? mChars[chr].w : 0;
+}
+byte SciGUIfont::getCharHeight(byte chr) {
+	return chr < mCharMax ? mChars[chr].h : 0;
+}
+byte *SciGUIfont::getCharData(byte chr) {
+	return chr < mCharMax ? _resourceData + mChars[chr].offset + 2 : 0;
+}
+
+void SciGUIfont::draw(int16 chr, int16 top, int16 left, byte color, byte textface) {
+	int charWidth = MIN<int>(getCharWidth(chr), _screen->_width - left);
+	int charHeight = MIN<int>(getCharHeight(chr), 200 - top);
+	byte b = 0, mask = 0xFF;
+	int pitch = _screen->_width;
+	int y = top;
+
+	byte *pIn = getCharData(chr);
+	for (int i = 0; i < charHeight; i++, y++) {
+		if (textface & 1) // "grayed" output
+			mask = top++ % 2 ? 0xAA : 0x55;
+		for (int done = 0; done < charWidth; done++) {
+			if ((done & 7) == 0) // fetching next data byte
+				b = *(pIn++) & mask;
+			if (b & 0x80) // if MSB is set - paint it
+				_screen->Put_Pixel(left + done, y, 1, color, 0, 0);
+			b = b << 1;
+		}
+	}
+
+}
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_font.h b/engines/sci/gui/gui_font.h
new file mode 100644
index 0000000..437a572
--- /dev/null
+++ b/engines/sci/gui/gui_font.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+class SciGUIfont {
+public:
+	SciGUIfont(OSystem *system, EngineState *state, SciGUIscreen *screen, sciResourceId resourceId);
+	~SciGUIfont();
+
+	sciResourceId getResourceId();
+	byte getHeight();
+	byte getCharWidth(byte chr);
+	byte getCharHeight(byte chr);
+	byte *getCharData(byte chr);
+	void draw(int16 chr, int16 top, int16 left, byte color, byte textface);
+
+private:
+	void initData(sciResourceId resourceId);
+
+	OSystem *_system;
+	EngineState *_s;
+	SciGUIscreen *_screen;
+
+	sciResourceId _resourceId;
+	byte *_resourceData;
+
+	struct charinfo {
+		byte w, h;
+		int16 offset;
+	};
+	byte mFontH;
+	uint16 mCharMax;
+	charinfo* mChars;
+};
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_gfx.cpp b/engines/sci/gui/gui_gfx.cpp
new file mode 100644
index 0000000..56ce2ec
--- /dev/null
+++ b/engines/sci/gui/gui_gfx.cpp
@@ -0,0 +1,1194 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/timer.h"
+#include "common/util.h"
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_font.h"
+#include "sci/gui/gui_picture.h"
+#include "sci/gui/gui_view.h"
+#include "sci/gui/gui_screen.h"
+#include "sci/gui/gui_gfx.h"
+
+namespace Sci {
+
+static uint32 _sysTicks;
+
+SciGUIgfx::SciGUIgfx(OSystem *system, EngineState *state, SciGUIscreen *screen)
+	: _system(system), _s(state), _screen(screen) {
+	init();
+	initPalette();
+	initTimer();
+}
+
+SciGUIgfx::~SciGUIgfx() {
+	_system->getTimerManager()->removeTimerProc(&timerHandler);
+}
+
+void SciGUIgfx::init() {
+	uint16 a = 0;
+
+	_font = NULL;
+
+	_mainPort = mallocPort();
+	SetPort(_mainPort);
+	OpenPort(_mainPort);
+
+	_menuPort = mallocPort();
+	OpenPort(_menuPort);
+	SetFont(0);
+	_menuPort->rect = Common::Rect(0, 0, _screen->_width, _screen->_height);
+
+//	HEAPHANDLE theMenuBarH = heapNewPtr(34, kDataPort, "MenuBar");
+//	heapClearPtr(theMenuBarH);
+//	_theMenuBar = (Common::Rect *)heap2Ptr(theMenuBarH);
+//	*_theMenuBar = Common::Rect(_gfx->RGetPort()->rect.right, 10);
+
+	_sysTicks = 0;
+}
+
+void SciGUIgfx::initPalette() {
+	int16 i;
+	for (i = 0; i < 256; i++) {
+		_sysPalette.colors[i].used = 0;
+		_sysPalette.colors[i].r = 0;
+		_sysPalette.colors[i].g = 0;
+		_sysPalette.colors[i].b = 0;
+		_sysPalette.intencity[i] = 100;
+		_sysPalette.mapping[i] = i;
+	}
+	_sysPalette.colors[0].used = 1;
+	_sysPalette.colors[255].used = 1;
+	_sysPalette.colors[255].r = 255;
+	_sysPalette.colors[255].g = 255;
+	_sysPalette.colors[255].b = 255;
+	//if (g_sci->getPlatform() == Common::kPlatformAmiga)
+	//	setAmigaPalette();
+	//else 
+
+	// Load default palette from resource 999
+	if (!SetResPalette(999, 2)) {
+		// if not found, we set EGA palette
+		SetEGApalette();
+	};
+
+	// Init _clrPowers used in MatchColor
+	for(int16 i = 0; i < 256; i++)
+	  _clrPowers[i] = i*i;
+}
+
+void SciGUIgfx::initTimer() {
+	_sysSpeed = 1000000 / 60;
+	Common::TimerManager *tm = _system->getTimerManager();
+	tm->removeTimerProc(&timerHandler);
+	tm->installTimerProc(&timerHandler, _sysSpeed, this);
+}
+
+void SciGUIgfx::timerHandler(void *ref) {
+	((SciGUIgfx *)ref)->_sysTicks++;
+}
+
+sciPort *SciGUIgfx::mallocPort () {
+	sciPort *newPort = (sciPort *)malloc(sizeof(sciPort));
+	assert(newPort);
+	memset(newPort, 0, sizeof(sciPort));
+	return newPort;
+}
+
+#define SCI_PAL_FORMAT_CONSTANT 1
+#define SCI_PAL_FORMAT_VARIABLE 0
+
+void SciGUIgfx::SetEGApalette() {
+	int i;
+	_sysPalette.colors[1].r  = 0x000; _sysPalette.colors[1].g  = 0x000; _sysPalette.colors[1].b  = 0x0AA;
+	_sysPalette.colors[2].r  = 0x000; _sysPalette.colors[2].g  = 0x0AA; _sysPalette.colors[2].b  = 0x000;
+	_sysPalette.colors[3].r  = 0x000; _sysPalette.colors[3].g  = 0x0AA; _sysPalette.colors[3].b  = 0x0AA;
+	_sysPalette.colors[4].r  = 0x0AA; _sysPalette.colors[4].g  = 0x000; _sysPalette.colors[4].b  = 0x000;
+	_sysPalette.colors[5].r  = 0x0AA; _sysPalette.colors[5].g  = 0x000; _sysPalette.colors[5].b  = 0x0AA;
+	_sysPalette.colors[6].r  = 0x0AA; _sysPalette.colors[6].g  = 0x055; _sysPalette.colors[6].b  = 0x000;
+	_sysPalette.colors[7].r  = 0x0AA; _sysPalette.colors[7].g  = 0x0AA; _sysPalette.colors[7].b  = 0x0AA;
+	_sysPalette.colors[8].r  = 0x055; _sysPalette.colors[8].g  = 0x055; _sysPalette.colors[8].b  = 0x055;
+	_sysPalette.colors[9].r  = 0x055; _sysPalette.colors[9].g  = 0x055; _sysPalette.colors[9].b  = 0x0FF;
+	_sysPalette.colors[10].r = 0x055; _sysPalette.colors[10].g = 0x0FF; _sysPalette.colors[10].b = 0x055;
+	_sysPalette.colors[11].r = 0x055; _sysPalette.colors[11].g = 0x0FF; _sysPalette.colors[11].b = 0x0FF;
+	_sysPalette.colors[12].r = 0x0FF; _sysPalette.colors[12].g = 0x055; _sysPalette.colors[12].b = 0x055;
+	_sysPalette.colors[13].r = 0x0FF; _sysPalette.colors[13].g = 0x055; _sysPalette.colors[13].b = 0x0FF;
+	_sysPalette.colors[14].r = 0x0FF; _sysPalette.colors[14].g = 0x0FF; _sysPalette.colors[14].b = 0x055;
+	_sysPalette.colors[15].r = 0x0FF; _sysPalette.colors[15].g = 0x0FF; _sysPalette.colors[15].b = 0x0FF;
+	for (i = 0; i <= 15; i++) {
+		_sysPalette.colors[i].used = 1;
+	}
+	for (i = 16; i <= 254; i++) {
+		_sysPalette.colors[i].r = 200;
+		_sysPalette.colors[i].used = 1;
+	}
+	SetCLUT(&_sysPalette);
+}
+
+void SciGUIgfx::CreatePaletteFromData(byte *data, sciPalette *paletteOut) {
+	int palFormat = 0;
+	int palOffset = 0;
+	int palColorStart = 0;
+	int palColorCount = 0;
+	int colorNo = 0;
+
+	memset(paletteOut, 0, sizeof(sciPalette));
+	if (data[0] == 0 && data[1] == 1) {
+		// SCI0/SCI1 palette
+		palFormat = SCI_PAL_FORMAT_VARIABLE; // CONSTANT;
+		palOffset = 260;
+		palColorStart = 0; palColorCount = 256;
+	} else {
+		// SCI1.1 palette
+		palFormat = data[32];
+		palOffset = 37;
+		palColorStart = READ_LE_UINT16(data + 25); palColorCount = READ_LE_UINT16(data + 29);
+	}
+	switch (palFormat) {
+		case SCI_PAL_FORMAT_CONSTANT:
+			for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
+				paletteOut->colors[colorNo].used = 1;
+				paletteOut->colors[colorNo].r = data[palOffset++];
+				paletteOut->colors[colorNo].g = data[palOffset++];
+				paletteOut->colors[colorNo].b = data[palOffset++];
+			}
+			break;
+		case SCI_PAL_FORMAT_VARIABLE:
+			for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
+				paletteOut->colors[colorNo].used = data[palOffset++];
+				paletteOut->colors[colorNo].r = data[palOffset++];
+				paletteOut->colors[colorNo].g = data[palOffset++];
+				paletteOut->colors[colorNo].b = data[palOffset++];
+			}
+			break;
+	}
+}
+
+bool SciGUIgfx::SetResPalette(int16 resourceNo, int16 flag) {
+	Resource *palResource = _s->resMan->findResource(ResourceId(kResourceTypePalette, resourceNo), 0);
+	int palFormat = 0;
+	int palOffset = 0;
+	int palColorStart = 0;
+	int palColorCount = 0;
+	int colorNo = 0;
+	sciPalette palette = {0};
+
+	if (palResource) {
+		CreatePaletteFromData(palResource->data, &palette);
+		SetPalette(&palette, 2);
+		return true;
+	}
+	return false;
+}
+
+void SciGUIgfx::SetPalette(sciPalette *sciPal, int16 flag) {
+	uint32 systime = _sysPalette.timestamp;
+	if (flag == 2 || sciPal->timestamp != systime) {
+		MergePalettes(sciPal, &_sysPalette, flag);
+		sciPal->timestamp = _sysPalette.timestamp;
+		if (_s->pic_not_valid == 0 && systime != _sysPalette.timestamp)
+			SetCLUT(&_sysPalette);
+	}
+}
+
+void SciGUIgfx::MergePalettes(sciPalette *pFrom, sciPalette *pTo, uint16 flag) {
+	uint16 res;
+	int i,j;
+	// colors 0 (black) and 255 (white) are not affected by merging
+	for (i = 1 ; i < 255; i++) {
+		if (!pFrom->colors[i].used)// color is not used - so skip it
+			continue;
+		// forced palette merging or dest color is not used yet
+		if (flag == 2 || (!pTo->colors[i].used)) { 
+			pTo->colors[i].used = pFrom->colors[i].used;
+			pTo->colors[i].r = pFrom->colors[i].r;
+			pTo->colors[i].g = pFrom->colors[i].g;
+			pTo->colors[i].b = pFrom->colors[i].b;
+			pFrom->mapping[i] = i;
+			continue;
+		}
+		// check if exact color could be matched
+		res = MatchColor(pTo, pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b);
+		if (res & 0x8000) { // exact match was found
+			pFrom->mapping[i] = res & 0xFF;
+			continue;
+		}
+		// no exact match - see if there is an unused color
+		for (j = 1; j < 256; j++)
+			if (!pTo->colors[j].used) {
+				pTo->colors[j].used = pFrom->colors[i].used;
+				pTo->colors[j].r = pFrom->colors[i].r;
+				pTo->colors[j].g = pFrom->colors[i].g;
+				pTo->colors[j].b = pFrom->colors[i].b;
+				pFrom->mapping[i] = j;
+				break;
+			}
+		// if still no luck - set an approximate color
+		if (j == 256) {
+			pFrom->mapping[i] = res & 0xFF;
+			pTo->colors[res & 0xFF].used |= 0x10;
+		}
+	}
+	pTo->timestamp = _sysTicks;
+}
+
+uint16 SciGUIgfx::MatchColor(sciPalette*pPal, byte r, byte g, byte b) {
+	byte found = 0xFF;
+	int diff = 0x2FFFF, cdiff;
+	int16 dr,dg,db;
+
+	for (int i = 0; i < 256; i++) {
+		if ((!pPal->colors[i].used))
+			continue;
+		dr = pPal->colors[i].r - r;
+		dg = pPal->colors[i].g - g;
+		db = pPal->colors[i].b - b;
+//		minimum squares match
+		cdiff = _clrPowers[ABS(dr)] + _clrPowers[ABS(dg)] + _clrPowers[ABS(db)];
+//		minimum sum match (Sierra's)
+//		cdiff = ABS(dr) + ABS(dg) + ABS(db);
+		if (cdiff < diff) {
+			if (cdiff == 0)
+				return i | 0x8000; // setting this flag to indicate exact match
+			found = i;
+			diff = cdiff;
+		}
+	}
+	return found;
+}
+
+void SciGUIgfx::SetCLUT(sciPalette*pal) {
+	if (pal != &_sysPalette)
+		memcpy(&_sysPalette,pal,sizeof(sciPalette));
+	// just copy palette to system
+	byte bpal[4 * 256];
+	// Get current palette, update it and put back
+	_system->grabPalette(bpal, 0, 256);
+	for (int16 i = 0; i < 256; i++) {
+		if (!pal->colors[i].used)
+			continue;
+		bpal[i * 4] = pal->colors[i].r * pal->intencity[i] / 100;
+		bpal[i * 4 + 1] = pal->colors[i].g * pal->intencity[i] / 100;
+		bpal[i * 4 + 2] = pal->colors[i].b * pal->intencity[i] / 100;
+		bpal[i * 4 + 3] = 100;
+	}
+	_system->setPalette(bpal, 0, 256);
+	_system->updateScreen();
+}
+
+void SciGUIgfx::GetCLUT(sciPalette*pal) {
+	if (pal != &_sysPalette)
+		memcpy(pal,&_sysPalette,sizeof(sciPalette));
+}
+
+sciPort *SciGUIgfx::SetPort(sciPort *newPort) {
+	sciPort *oldPort = _curPort;
+	_curPort = newPort;
+	return oldPort;
+}
+
+sciPort *SciGUIgfx::GetPort(void) {
+	return _curPort;
+}
+
+void SciGUIgfx::SetOrigin(int16 left, int16 top) {
+	_curPort->left = left;
+	_curPort->top = top;
+}
+
+void SciGUIgfx::MoveTo(int16 left, int16 top) {
+	_curPort->curTop = top;
+	_curPort->curLeft = left;
+}
+
+void SciGUIgfx::Move(int16 left, int16 top) {
+	_curPort->curTop += top;
+	_curPort->curLeft += left;
+}
+
+int16 SciGUIgfx::GetFontId() {
+	return _curPort->fontId;
+}
+
+SciGUIfont *SciGUIgfx::GetFont() {
+	if ((_font == NULL) || (_font->getResourceId() != _curPort->fontId)) {
+		_font = new SciGUIfont(_system, _s, _screen, _curPort->fontId);
+	}
+	return _font;
+}
+
+void SciGUIgfx::SetFont(int16 fontId) {
+	if ((_font == NULL) || (_font->getResourceId() != fontId)) {
+		_font = new SciGUIfont(_system, _s, _screen, fontId);
+	}
+	_curPort->fontId = fontId;
+	_curPort->fontH = _font->getHeight();
+}
+
+void SciGUIgfx::OpenPort(sciPort *port) {
+	port->fontId = 0;
+	port->fontH = 8;
+
+	sciPort *tmp = _curPort;
+	_curPort = port;
+	SetFont(port->fontId);
+	_curPort = tmp;
+
+	port->top = 0;
+	port->left = 0;
+	port->textFace = 0;
+	port->penClr = 0;
+	port->backClr = 0xFF;
+	port->penMode = 0;
+	memcpy(&port->rect, &_bounds, sizeof(_bounds));
+}
+
+void SciGUIgfx::PenColor(int16 color) {
+	_curPort->penClr = color;
+}
+
+void SciGUIgfx::PenMode(int16 mode) {
+	_curPort->penMode = mode;
+}
+
+void SciGUIgfx::TextFace(int16 textFace) {
+	_curPort->textFace = textFace;
+}
+
+int16 SciGUIgfx::GetPointSize(void) {
+	return _curPort->fontH;
+}
+
+void SciGUIgfx::ClearScreen(byte color) {
+	FillRect(_curPort->rect, SCI_SCREEN_MASK_ALL, color, 0, 0);
+}
+
+void SciGUIgfx::InvertRect(const Common::Rect &rect) {
+	int16 oldpenmode = _curPort->penMode;
+	_curPort->penMode = 2;
+	FillRect(rect, 1, _curPort->penClr, _curPort->backClr);
+	_curPort->penMode = oldpenmode;
+}
+//-----------------------------
+void SciGUIgfx::EraseRect(const Common::Rect &rect) {
+	FillRect(rect, 1, _curPort->backClr);
+}
+//-----------------------------
+void SciGUIgfx::PaintRect(const Common::Rect &rect) {
+	FillRect(rect, 1, _curPort->penClr);
+}
+
+void SciGUIgfx::FillRect(const Common::Rect &rect, int16 drawFlags, byte clrPen, byte clrBack, byte bControl) {
+	Common::Rect r(rect.left, rect.top, rect.right, rect.bottom);
+	r.clip(_curPort->rect);
+	if (r.isEmpty()) // nothing to fill
+		return;
+
+	int16 oldPenMode = _curPort->penMode;
+	OffsetRect(r);
+	int16 w = r.width();
+	int16 h = r.height();
+	int16 x, y;
+	byte curVisual;
+
+	// Doing visual first
+	if (drawFlags & SCI_SCREEN_MASK_VISUAL) {
+		if (oldPenMode == 2) { // invert mode
+			for (y = r.top; y < r.bottom; y++) {
+				for (x = r.left; x < r.right; x++) {
+					curVisual = _screen->Get_Visual(x, y);
+					if (curVisual == clrPen) {
+						_screen->Put_Pixel(x, y, 1, clrBack, 0, 0);
+					} else if (curVisual == clrBack) {
+						_screen->Put_Pixel(x, y, 1, clrPen, 0, 0);
+					}
+				}
+			}
+		} else { // just fill rect with ClrPen
+			for (y = r.top; y < r.bottom; y++) {
+				for (x = r.left; x < r.right; x++) {
+					_screen->Put_Pixel(x, y, 1, clrPen, 0, 0);
+				}
+			}
+		}
+	}
+
+	if (drawFlags < 2)
+		return;
+	drawFlags &= SCI_SCREEN_MASK_PRIORITY|SCI_SCREEN_MASK_CONTROL;
+
+	if (oldPenMode != 2) {
+		for (y = r.top; y < r.bottom; y++) {
+			for (x = r.left; x < r.right; x++) {
+				_screen->Put_Pixel(x, y, drawFlags, 0, clrBack, bControl);
+			}
+		}
+	} else {
+		for (y = r.top; y < r.bottom; y++) {
+			for (x = r.left; x < r.right; x++) {
+				_screen->Put_Pixel(x, y, drawFlags, 0, !_screen->Get_Priority(x, y), !_screen->Get_Control(x, y));
+			}
+		}
+	}
+}
+
+void SciGUIgfx::FrameRect(const Common::Rect &rect) {
+	Common::Rect r;
+	// left
+	r = rect;
+	r.right = rect.left + 1;
+	PaintRect(r);
+	// right
+	r.right = rect.right;
+	r.left = rect.right - 1;
+	PaintRect(r);
+	//top
+	r.left = rect.left;
+	r.bottom = rect.top + 1;
+	PaintRect(r);
+	//bottom
+	r.bottom = rect.bottom;
+	r.top = rect.bottom - 1;
+	PaintRect(r);
+}
+
+void SciGUIgfx::OffsetRect(Common::Rect &r) {
+	r.top += _curPort->top;
+	r.bottom += _curPort->top;
+	r.left += _curPort->left;
+	r.right += _curPort->left;
+}
+
+byte SciGUIgfx::CharHeight(int16 ch) {
+#if 0
+	CResFont *res = getResFont();
+	return res ? res->getCharH(ch) : 0;
+#endif
+	return 0;
+}
+//-----------------------------
+byte SciGUIgfx::CharWidth(int16 ch) {
+	SciGUIfont *font = GetFont();
+	return font ? font->getCharWidth(ch) : 0;
+}
+//-----------------------------
+int16 SciGUIgfx::TextWidth(const char *text, int16 from, int16 len) {
+	SciGUIfont *font = GetFont();
+	if (font) {
+		int16 width = 0;
+		for (int i = from; i < len; i++)
+			width += _font->getCharWidth(text[i]);
+		return width;
+	}
+	return 0;
+}
+//-----------------------------
+void SciGUIgfx::ClearChar(int16 chr) {
+	if (_curPort->penMode != 1)
+		return;
+	Common::Rect rect;
+	rect.top = _curPort->curTop;
+	rect.bottom = rect.top + _curPort->fontH;
+	rect.left = _curPort->curLeft;
+	rect.right = rect.left + CharWidth(chr);
+	EraseRect(rect);
+}
+//-----------------------------
+void SciGUIgfx::DrawChar(int16 chr) {
+	chr = chr & 0xFF;
+	ClearChar(chr);
+	StdChar(chr);
+	_curPort->curLeft += CharWidth(chr);
+}
+//-----------------------------
+void SciGUIgfx::StdChar(int16 chr) {
+#if 0
+	CResFont*res = getResFont();
+	if (res)
+		res->Draw(chr, _curPort->top + _curPort->curTop, _curPort->left
+				+ _curPort->curLeft, _vSeg, 320, _curPort->penClr,
+				_curPort->textFace);
+#endif
+}
+
+SCILanguage SciGUIgfx::getSCILanguage() {
+	return kLangEnglish;
+}
+
+char *SciGUIgfx::StrSplit(char *buff, const char *msg, const char *fmt) {
+	SCILanguage gameLang = getSCILanguage();
+	SCILanguage subtitleLang = kLangNone;
+	char *retval;
+//	if (_theGame.getHandle())
+		//subtitleLang = (SCILanguage)_theGame.getProperty(0x58); // subtitleLang property
+
+	if (buff == msg) {
+		char str[2000];
+		getIntlString(str, msg, fmt, gameLang, subtitleLang);
+		retval = strcpy(buff, str);
+	} else
+		retval = getIntlString(buff, msg, fmt, gameLang, subtitleLang);
+	return retval;
+}
+//--------------------------------
+// In multilanguage game the msg has format ___english_text__#I___italian_text___
+// The function should place in buff a translated part of msg or the 1st one if a translation
+// does not exist
+char *SciGUIgfx::getIntlString(char *buff, const char *msg, const char *fmt, SCILanguage gameLang, SCILanguage subtitleLang) {
+
+	// prefer subtitleLang if set
+	SCILanguage lang = subtitleLang != kLangNone ? subtitleLang : gameLang;
+	const char *ptr = msg, *szFrom;
+	char ch;
+	int nLen = 0;
+	// searching for language code in msg
+	while (*ptr) {
+		ch = *(ptr + 1);
+		if(*ptr == '#' && (ch == 'I' || ch == 'F' || ch == 'G' || ch == 'S')) {
+			ptr +=2;
+			break;
+		}
+	ptr++;
+	}
+	// if a language code was found...
+	if (*ptr) {
+		if ((lang == kLangItalian && ch == 'I') || (lang == kLangFrench && ch == 'F') ||
+				(lang == kLangGerman && ch == 'G') || (lang == kLangSpanish && ch == 'S')) {
+			nLen = (int)strlen(ptr);
+			szFrom = ptr;
+		} else {
+			nLen = ptr - msg - 2;
+			szFrom = msg;
+		}
+	} else {
+		nLen = ptr - msg;
+		szFrom = msg;
+	}
+	if (fmt && subtitleLang != kLangNone) {
+		strcpy(buff, fmt);
+		strncat(buff, szFrom, nLen);
+		buff[nLen + strlen(fmt)] = 0;
+	} else {
+		strncpy(buff, szFrom, nLen);
+		buff[nLen] = 0;
+	}
+	return buff;
+}
+
+// TODO: implement codes
+int16 SciGUIgfx::TextSize(Common::Rect &rect, const char *str, int16 fontId, int16 maxwidth) {
+	char buff[1000] = { 0 };
+	int16 oldfont = GetFontId();
+	if (fontId != -1)
+		SetFont(fontId);
+	rect.top = rect.left = 0;
+
+	if (maxwidth < 0) { // force output as single line
+		rect.bottom = GetPointSize();
+		rect.right = StringWidth(str);
+	} else {
+		// rect.right=found widest line with RTextWidth and GetLongest
+		// rect.bottom=num. lines * GetPointSize
+		rect.right = (maxwidth ? maxwidth : 192);
+		int16 height = 0, maxWidth = 0, width, nc;
+		const char*p = str;
+		while (*p) {
+			if (*p == 0xD || *p == 0xA) {
+				p++;
+				continue;
+			}
+			nc = GetLongest(p, rect.right);
+			if (nc == 0)
+				break;
+			width = TextWidth(p, 0, nc);
+			maxWidth = MAX(width, maxWidth);
+			p += nc;
+			height++;
+		}
+		rect.bottom = height * GetPointSize();
+		rect.right = maxwidth ? maxwidth : MIN(rect.right, maxWidth);
+	}
+	SetFont(oldfont);
+	return rect.right;
+}
+
+// TODO: implement codes
+// return max # of chars to fit maxwidth with full words
+int16 SciGUIgfx::GetLongest(const char *str, int16 maxWidth) {
+	SciGUIfont *font = GetFont();
+	if (!font)
+		return 0;
+
+	int16 chars = 0, to = 0;
+	uint16 width = 0;
+	while (width <= maxWidth) {
+		switch (str[to]) {
+		case ' ':
+			chars = to + 1;
+			break;
+		case 0:
+		case 0xD:
+		case 0xA:
+			return to;
+		}
+		width += font->getCharWidth(str[to]);
+		to++;
+	}
+	return chars;
+}
+
+// TODO: implement codes
+void SciGUIgfx::DrawText(const char *text, int16 from, int16 len) {
+	int16 chr, width;
+	SciGUIfont *font = GetFont();
+	Common::Rect rect;
+
+	if (!font)
+		return;
+
+	text += from;
+	rect.top = _curPort->curTop;
+	rect.bottom = rect.top + _curPort->fontH;
+	while (len--) {
+		chr = (*text++) & 0xFF;
+		width = font->getCharWidth(chr);
+		// clear char
+		if (_curPort->penMode == 1) {
+			rect.left = _curPort->curLeft;
+			rect.right = rect.left + width;
+			EraseRect(rect);
+		}
+		// CharStd
+		font->draw(chr, _curPort->top + _curPort->curTop, _curPort->left + _curPort->curLeft, _curPort->penClr, _curPort->textFace);
+		_curPort->curLeft += width;
+	}
+}
+
+void SciGUIgfx::ShowText(const char *text, int16 from, int16 len) {
+	Common::Rect rect;
+
+	rect.top = _curPort->curTop;
+	rect.bottom = rect.top + GetPointSize();
+	rect.left = _curPort->curLeft;
+	DrawText(text, from, len);
+	rect.right = _curPort->curLeft;
+	ShowBits(rect, 1);
+}
+
+// Draws a text in rect.
+// align : -1-right , 0-left, 1-center
+void SciGUIgfx::TextBox(const char *text, int16 bshow, const Common::Rect &rect, int16 align, int16 fontId) {
+	int16 w, nc, offset;
+	int16 hline = 0;
+	int16 oldfont = GetFontId();
+	int16 rectWidth = rect.width();
+
+	if (fontId != -1)
+		SetFont(fontId);
+
+	while (*text) {
+		if (*text == 0xD || *text == 0xA) {
+			text++;
+			continue;
+		}
+		nc = GetLongest(text, rect.width());
+		if (nc == 0)
+			break;
+		w = TextWidth(text, 0, nc);
+		switch (align) {
+		case -1:
+			offset = rect.width() - w;
+			break;
+		case 1:
+			offset = (rect.width() - w) / 2;
+			break;
+		default:
+			offset = 0;
+		}
+		MoveTo(rect.left + offset, rect.top + hline);
+
+		if (bshow)
+			ShowText(text, 0, nc);
+		else
+			DrawText(text, 0, nc);
+		hline += GetPointSize();
+		text += nc;
+	}
+	SetFont(oldfont);
+}
+
+// Update (part of) screen
+void SciGUIgfx::ShowBits(const Common::Rect &r, uint16 flags) {
+	Common::Rect rect(r.left, r.top, r.right, r.bottom);
+	rect.clip(_curPort->rect);
+	if (rect.isEmpty()) // nothing to show
+		return;
+
+	OffsetRect(rect);
+	uint16 w = rect.width();
+	uint16 h = rect.height();
+	assert((flags&0x8000) == 0);
+	_screen->UpdateWhole();
+//	_system->copyRectToScreen(GetSegment(flags) + _baseTable[rect.top] + rect.left, 320, rect.left, rect.top, w, h);
+//	_system->updateScreen();
+}
+
+sciMemoryHandle SciGUIgfx::SaveBits(const Common::Rect &rect, byte screenMask) {
+	sciMemoryHandle memoryId;
+	byte *memoryPtr;
+	int size;
+	
+	Common::Rect r(rect.left, rect.top, rect.right, rect.bottom);
+	r.clip(_curPort->rect);
+	if (r.isEmpty()) // nothing to save
+		return NULL_REG;
+
+	OffsetRect(r); //local port coords to screen coords
+
+	// now actually ask _screen how much space it will need for saving
+	size = _screen->BitsGetDataSize(r, screenMask);
+
+	memoryId = kalloc(_s->segMan, "SaveBits()", size);
+	memoryPtr = kmem(_s->segMan, memoryId);
+	_screen->BitsSave(r, screenMask, memoryPtr);
+	return memoryId;
+}
+
+void SciGUIgfx::RestoreBits(sciMemoryHandle memoryHandle) {
+	byte *memoryPtr = kmem(_s->segMan, memoryHandle);;
+
+	if (memoryPtr) {
+		_screen->BitsRestore(memoryPtr);
+		kfree(_s->segMan, memoryHandle);
+	}
+}
+
+void SciGUIgfx::Draw_Line(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
+	//set_drawing_flag
+	byte flag = _screen->GetDrawingMask(color, prio, control);
+	prio &= 0xF0;
+	control &= 0x0F;
+
+	// offseting the line
+	left += _curPort->left;
+	right += _curPort->left;
+	top += _curPort->top;
+	bottom += _curPort->top;
+	// horizontal line
+	if (top == bottom) {
+		Draw_Horiz(left, right, top, flag, color, prio, control);
+		return;
+	}
+	// vertical line
+	if (left == right) {
+		Draw_Vert(top, bottom, left, flag, color, prio, control);
+		return;
+	}
+	// sloped line - draw with Bresenham algorithm
+	int dy = bottom - top;
+	int dx = right - left;
+	int stepy = dy < 0 ? -1 : 1;
+	int stepx = dx < 0 ? -1 : 1;
+	dy = ABS(dy) << 1;
+	dx = ABS(dx) << 1;
+
+	// setting the 1st and last pixel
+	_screen->Put_Pixel(left, top, flag, color, prio, control);
+	_screen->Put_Pixel(right, bottom, flag, color, prio, control);
+	// drawing the line
+	if (dx > dy) // going horizontal
+	{
+		int fraction = dy - (dx >> 1);
+		while (left != right) {
+			if (fraction >= 0) {
+				top += stepy;
+				fraction -= dx;
+			}
+			left += stepx;
+			fraction += dy;
+			_screen->Put_Pixel(left, top, flag, color, prio, control);
+		}
+	} else // going vertical
+	{
+		int fraction = dx - (dy >> 1);
+		while (top != bottom) {
+			if (fraction >= 0) {
+				left += stepx;
+				fraction -= dy;
+			}
+			top += stepy;
+			fraction += dx;
+			_screen->Put_Pixel(left, top, flag, color, prio, control);
+		}
+	}
+	//g_sci->eventMgr->waitUntil(5);
+	//ShowBits(&_rThePort->rect,6);
+}
+
+void SciGUIgfx::Draw_Horiz(int16 left, int16 right, int16 top, byte flag, byte color, byte prio, byte control) {
+	if (right < left)
+		SWAP(right, left);
+	for (int i = left; i <= right; i++)
+		_screen->Put_Pixel(i, top, flag, color, prio, control);
+}
+
+//--------------------------------
+void SciGUIgfx::Draw_Vert(int16 top, int16 bottom, int16 left, byte flag, byte color, byte prio, byte control) {
+	if (top > bottom)
+		SWAP(top, bottom);
+	for (int i = top; i <= bottom; i++)
+		_screen->Put_Pixel(left, i, flag, color, prio, control);
+}
+
+// Bitmap for drawing sierra circles
+const byte pattern_Circles[8][15] = {
+	{ 0x01 },
+	{ 0x03, 0x03, 0x03 },
+	{ 0x02, 0x07, 0x07, 0x07, 0x02 },
+	{ 0x06, 0x06, 0x0F, 0x0F, 0x0F, 0x06, 0x06 },
+	{ 0x04, 0x0E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x04 },
+	{ 0x0C, 0x1E, 0x1E, 0x1E, 0x3F, 0x3F, 0x3F, 0x1E, 0x1E, 0x1E, 0x0C },
+	{ 0x1C, 0x3E, 0x3E, 0x3E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3E, 0x3E, 0x3E, 0x1C },
+	{ 0x18, 0x3C, 0x7E, 0x7E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x7E, 0x7E, 0x3C, 0x18 }
+};
+
+const bool pattern_Textures[32 * 8 * 2] = {
+	false, false, false, false, false,  true, false, false, // 0x20
+	false, false,  true, false, true,  false, false,  true, // 0x94
+	false,  true, false, false, false, false, false, false, // 0x02
+	false, false,  true, false, false,  true, false, false, // 0x24
+	false, false, false, false,  true, false, false,  true, // 0x90
+	false,  true, false, false, false, false, false,  true, // 0x82
+	false, false,  true, false, false,  true, false,  true, // 0xA4
+	false,  true, false, false, false,  true, false,  true, // 0xA2
+	false,  true, false, false, false, false, false,  true, // 0x82
+	 true, false, false,  true, false, false, false, false, // 0x09
+	false,  true, false,  true, false, false, false, false, // 0x0A
+	false,  true, false, false, false,  true, false, false, // 0x22
+	false,  true, false, false,  true, false, false, false, // 0x12
+	false, false, false, false,  true, false, false, false, // 0x10
+	false,  true, false, false, false, false,  true, false, // 0x42
+	false, false,  true, false,  true, false, false, false, // 0x14
+	 true, false, false, false,  true, false, false,  true, // 0x91
+	false,  true, false,  true, false, false,  true, false, // 0x4A
+	 true, false, false, false,  true, false, false,  true, // 0x91
+	 true, false, false, false,  true, false, false, false, // 0x11
+	false, false, false,  true, false, false, false, false, // 0x08
+	false,  true, false, false,  true, false, false, false, // 0x12
+	 true, false,  true, false, false,  true, false, false, // 0x25
+	false, false, false, false,  true, false, false, false, // 0x10
+	false,  true, false, false, false,  true, false, false, // 0x22
+	false, false, false,  true, false,  true, false,  true, // 0xA8
+	false, false,  true, false,  true, false, false, false, // 0x14
+	false, false,  true, false, false,  true, false, false, // 0x24
+	false, false, false, false, false, false, false, false, // 0x00
+	false, false, false, false,  true, false,  true, false, // 0x50
+	false, false,  true, false, false,  true, false, false, // 0x24
+	false, false,  true, false, false, false, false,        // 0x04 (last bit is not mentioned cause original interpreter also ignores that bit)
+	// Now the table is actually duplicated, so we won't need to wrap around
+	false, false, false, false, false,  true, false, false, // 0x20
+	false, false,  true, false, true,  false, false,  true, // 0x94
+	false,  true, false, false, false, false, false, false, // 0x02
+	false, false,  true, false, false,  true, false, false, // 0x24
+	false, false, false, false,  true, false, false,  true, // 0x90
+	false,  true, false, false, false, false, false,  true, // 0x82
+	false, false,  true, false, false,  true, false,  true, // 0xA4
+	false,  true, false, false, false,  true, false,  true, // 0xA2
+	false,  true, false, false, false, false, false,  true, // 0x82
+	 true, false, false,  true, false, false, false, false, // 0x09
+	false,  true, false,  true, false, false, false, false, // 0x0A
+	false,  true, false, false, false,  true, false, false, // 0x22
+	false,  true, false, false,  true, false, false, false, // 0x12
+	false, false, false, false,  true, false, false, false, // 0x10
+	false,  true, false, false, false, false,  true, false, // 0x42
+	false, false,  true, false,  true, false, false, false, // 0x14
+	 true, false, false, false,  true, false, false,  true, // 0x91
+	false,  true, false,  true, false, false,  true, false, // 0x4A
+	 true, false, false, false,  true, false, false,  true, // 0x91
+	 true, false, false, false,  true, false, false, false, // 0x11
+	false, false, false,  true, false, false, false, false, // 0x08
+	false,  true, false, false,  true, false, false, false, // 0x12
+	 true, false,  true, false, false,  true, false, false, // 0x25
+	false, false, false, false,  true, false, false, false, // 0x10
+	false,  true, false, false, false,  true, false, false, // 0x22
+	false, false, false,  true, false,  true, false,  true, // 0xA8
+	false, false,  true, false,  true, false, false, false, // 0x14
+	false, false,  true, false, false,  true, false, false, // 0x24
+	false, false, false, false, false, false, false, false, // 0x00
+	false, false, false, false,  true, false,  true, false, // 0x50
+	false, false,  true, false, false,  true, false, false, // 0x24
+	false, false,  true, false, false, false, false,        // 0x04 (last bit is not mentioned cause original interpreter also ignores that bit)
+};
+	
+// Bit offsets into pattern_textures
+const byte pattern_TextureOffset[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 };
+
+void SciGUIgfx::Draw_Box(Common::Rect box, byte color, byte prio, byte control) {
+	byte flag = _screen->GetDrawingMask(color, prio, control);
+	int y, x;
+
+	for (y = box.top; y < box.bottom; y++) {
+		for (x = box.left; x < box.right; x++) {
+			_screen->Put_Pixel(x, y, flag, color, prio, control);
+		}
+	}
+}
+
+void SciGUIgfx::Draw_TexturedBox(Common::Rect box, byte color, byte prio, byte control, byte texture) {
+	byte flag = _screen->GetDrawingMask(color, prio, control);
+	const bool *textureData = &pattern_Textures[pattern_TextureOffset[texture]];
+	int y, x;
+
+	for (y = box.top; y < box.bottom; y++) {
+		for (x = box.left; x < box.right; x++) {
+			if (*textureData) {
+				_screen->Put_Pixel(x, y, flag, color, prio, control);
+			}
+			textureData++;
+		}
+	}
+}
+
+void SciGUIgfx::Draw_Circle(Common::Rect box, byte size, byte color, byte prio, byte control) {
+	byte flag = _screen->GetDrawingMask(color, prio, control);
+	byte *circle = (byte *)&pattern_Circles[size];
+	byte circleBitmap;
+	int y, x;
+
+	for (y = box.top; y < box.bottom; y++) {
+		circleBitmap = *circle;
+		for (x = box.left; x < box.right; x++) {
+			if (circleBitmap & 1) {
+				_screen->Put_Pixel(x, y, flag, color, prio, control);
+			}
+			circleBitmap = circleBitmap >> 1;
+		}
+		circle++;
+	}
+}
+
+void SciGUIgfx::Draw_TexturedCircle(Common::Rect box, byte size, byte color, byte prio, byte control, byte texture) {
+	byte flag = _screen->GetDrawingMask(color, prio, control);
+	byte *circle = (byte *)&pattern_Circles[size];
+	byte circleBitmap;
+	const bool *textureData = &pattern_Textures[pattern_TextureOffset[texture]];
+	int y, x;
+
+	for (y = box.top; y < box.bottom; y++) {
+		circleBitmap = *circle;
+		for (x = box.left; x < box.right; x++) {
+			if (circleBitmap & 1) {
+				if (*textureData) {
+					_screen->Put_Pixel(x, y, flag, color, prio, control);
+				}
+				textureData++;
+			}
+			circleBitmap = circleBitmap >> 1;
+		}
+		circle++;
+	}
+}
+
+void SciGUIgfx::Draw_Pattern(int16 x, int16 y, byte color, byte priority, byte control, byte code, byte texture) {
+	byte size = code & SCI_PATTERN_CODE_PENSIZE;
+	Common::Rect rect;
+
+	// We need to adjust the given coordinates, because the ones given us do not define upper left but somewhat middle
+	y -= size;
+	x -= (size + 1) >> 1;
+
+	rect.top = y; rect.left = x;
+	rect.setHeight((size*2)+1); rect.setWidth(size+1);
+
+	if (code & SCI_PATTERN_CODE_RECTANGLE) {
+		// Rectangle
+		if (code & SCI_PATTERN_CODE_USE_TEXTURE) {
+			Draw_TexturedBox(rect, color, priority, control, texture);
+		} else {
+			Draw_Box(rect, color, priority, control);
+		}
+
+	} else {
+		// Circle
+		if (code & SCI_PATTERN_CODE_USE_TEXTURE) {
+			Draw_TexturedCircle(rect, size, color, priority, control, texture);
+		} else {
+			Draw_Circle(rect, size, color, priority, control);
+		}
+	}
+}
+
+void SciGUIgfx::Pic_Fill(int16 x, int16 y, byte color, byte prio, byte control) {
+	Common::Stack<Common::Point> stack;
+	Common::Point p, p1;
+
+	byte flag = _screen->GetDrawingMask(color, prio, control), fmatch;
+	p.x = x + _curPort->left;
+	p.y = y + _curPort->top;
+	stack.push(p);
+
+	// parameters check
+	if ((flag & 2 && prio == 0) || (flag & 3 && control == 0))
+		return;
+
+	byte t_col = _screen->Get_Visual(p.x, p.y);
+	byte t_pri = _screen->Get_Priority(p.x, p.y);
+	byte t_con = _screen->Get_Control(p.x, p.y);
+	int16 w, e, a_set, b_set;
+	// if in 1st point priority,control or color is already set to target, clear the flag
+	if (!_s->resMan->isVGA()) {
+		// EGA 16 colors
+		if (flag & 1 && ((t_col == (color & 0x0F)) || (t_col == (color >> 4))))
+			flag ^= 1;
+	} else {
+		// VGA 256 colors
+		if (flag & 1 && t_col == color)
+			flag ^= 1;
+	}
+	if (flag & 2 && t_pri == prio)
+		flag ^= 2;
+	if (flag & 4 && t_con == control)
+		flag ^= 4;
+	if (flag == 0)// nothing to fill
+		return;
+
+	// hard borders for filling
+	int l = _curPort->rect.left + _curPort->left;
+	int t = _curPort->rect.top + _curPort->top;
+	int r = _curPort->rect.right + _curPort->left - 1;
+	int b = _curPort->rect.bottom + _curPort->top - 1;
+	while (stack.size()) {
+		p = stack.pop();
+		if ((fmatch = _screen->IsFillMatch(p.x, p.y, flag, t_col, t_pri, t_con)) == 0) // already filled
+			continue;
+		_screen->Put_Pixel(p.x, p.y, flag, color, prio, control);
+		w = p.x;
+		e = p.x;
+		// moving west and east pointers as long as there is a matching color to fill
+		while (w > l && (fmatch = _screen->IsFillMatch(w - 1, p.y, flag, t_col, t_pri, t_con)))
+			_screen->Put_Pixel(--w, p.y, fmatch, color, prio, control);
+		while (e < r && (fmatch = _screen->IsFillMatch(e + 1, p.y, flag, t_col, t_pri, t_con)))
+			_screen->Put_Pixel(++e, p.y, fmatch, color, prio, control);
+		// checking lines above and below for possible flood targets
+		a_set = b_set = 0;
+		while (w <= e) {
+			if (p.y > t && _screen->IsFillMatch(w, p.y - 1, flag, t_col, t_pri, t_con)) { // one line above
+				if (a_set == 0) {
+					p1.x = w;
+					p1.y = p.y - 1;
+					stack.push(p1);
+					a_set = 1;
+				}
+			} else
+				a_set = 0;
+
+			if (p.y < b && _screen->IsFillMatch(w, p.y + 1, flag, t_col, t_pri, t_con)) { // one line below
+				if (b_set == 0) {
+					p1.x = w;
+					p1.y = p.y + 1;
+					stack.push(p1);
+					b_set = 1;
+				}
+			} else
+				b_set = 0;
+			w++;
+		}
+	}
+}
+
+void SciGUIgfx::drawPicture(sciResourceId pictureId, uint16 style, bool addToFlag, sciResourceId paletteId) {
+	SciGUIpicture *picture;
+
+	picture = new SciGUIpicture(_system, _s, this, _screen, pictureId);
+	// do we add to a picture? if not -> clear screen
+	if (!addToFlag) {
+		ClearScreen(0);
+	}
+	picture->draw(style, addToFlag, paletteId);
+}
+
+void SciGUIgfx::drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo) {
+	SciGUIview *view = new SciGUIview(_system, _s, this, _screen, viewId);
+	Common::Rect rect(0, 0);
+	Common::Rect clipRect(0, 0);
+	if (view) {
+		rect.left = leftPos;
+		rect.top = topPos;
+		rect.right = rect.left + view->getWidth(loopNo, cellNo);
+		rect.bottom = rect.top + view->getHeight(loopNo, cellNo);
+		clipRect = rect;
+		clipRect.clip(_curPort->rect);
+		if (clipRect.isEmpty()) // nothing to draw
+			return;
+		view->draw(rect, clipRect, loopNo, cellNo, priority, paletteNo);
+		//if (_picNotValid == 0)
+		//	_gfx->ShowBits(rect, 1);
+	}
+}
+
+void SciGUIgfx::animatePalette(byte fromColor, byte toColor, int speed) {
+	sciColor col;
+	int len = toColor - fromColor - 1;
+	uint32 now = _sysTicks;
+	// search for sheduled animations with the same 'from' value
+	int sz = _palSchedules.size();
+	for (int i = 0; i < sz; i++) {
+		if (_palSchedules[i].from == fromColor) {
+			if (_palSchedules[i].schedule < now) {
+				if (speed > 0) {
+					col = _sysPalette.colors[fromColor];
+					memmove(&_sysPalette.colors[fromColor], &_sysPalette.colors[fromColor + 1], len * sizeof(sciColor));
+					_sysPalette.colors[toColor - 1] = col;
+				} else {
+					col = _sysPalette.colors[toColor - 1];
+					memmove(&_sysPalette.colors[fromColor+1], &_sysPalette.colors[fromColor], len * sizeof(sciColor));
+					_sysPalette.colors[fromColor] = col;
+				}
+				// removing schedule
+				_palSchedules.remove_at(i);
+			}
+			SetCLUT(&_sysPalette);
+			return;
+		}
+	}
+	// adding a new schedule
+	sciPalSched sched;
+	sched.from = fromColor;
+	sched.schedule = now + ABS(speed);
+	_palSchedules.push_back(sched);
+}
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_gfx.h b/engines/sci/gui/gui_gfx.h
new file mode 100644
index 0000000..ac64d71
--- /dev/null
+++ b/engines/sci/gui/gui_gfx.h
@@ -0,0 +1,150 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+#define SCI_PATTERN_CODE_RECTANGLE 0x10
+#define SCI_PATTERN_CODE_USE_TEXTURE 0x20
+#define SCI_PATTERN_CODE_PENSIZE 0x07
+
+class SciGUIscreen;
+class SciGUIfont;
+class SciGUIpicture;
+class SciGUIview;
+class SciGUIgfx {
+public:
+	SciGUIgfx(OSystem *system, EngineState *state, SciGUIscreen *screen);
+	~SciGUIgfx();
+
+	void init(void);
+	void initPalette();
+	virtual void initTimer();
+	static void timerHandler(void*ref);
+
+	sciPort *mallocPort ();
+	byte *GetSegment(byte seg);
+	void ResetScreen();
+	void SetEGApalette();
+	void CreatePaletteFromData(byte *paletteData, sciPalette *paletteOut);
+	bool SetResPalette(int16 resourceNo, int16 flag);
+	void SetPalette(sciPalette *sciPal, int16 flag);
+	void MergePalettes(sciPalette*pFrom, sciPalette*pTo, uint16 flag);
+	uint16 MatchColor(sciPalette*pPal, byte r, byte g, byte b);
+	void SetCLUT(sciPalette*pal);
+	void GetCLUT(sciPalette*pal);
+
+	sciPort *SetPort(sciPort *port);
+	sciPort *GetPort();
+	void SetOrigin(int16 left, int16 top);
+	void MoveTo(int16 left, int16 top);
+	void Move(int16 left, int16 top);
+	void SetFont(int16 fontId);
+	void OpenPort(sciPort *port);
+	void PenColor(int16 color);
+	void PenMode(int16 mode);
+	void TextFace(int16 textFace);
+	int16 GetPointSize(void);
+	int16 GetFontId();
+	SciGUIfont *GetFont();
+
+	void ClearScreen(byte color = 255);
+	void InvertRect(const Common::Rect &rect);
+	void EraseRect(const Common::Rect &rect);
+	void PaintRect(const Common::Rect &rect);
+	void FillRect(const Common::Rect &rect, int16 arg2, byte clrPen, byte clrBack = 0, byte bControl = 0);
+	void FrameRect(const Common::Rect &rect);
+	void OffsetRect(Common::Rect &r);
+
+	byte CharHeight(int16 ch);
+	byte CharWidth(int16 ch);
+	int16 TextWidth(const char*text, int16 from, int16 len);
+	int16 StringWidth(const char*str) {
+		return TextWidth(str, 0, (int16)strlen(str));
+	}
+	void ClearChar(int16 chr);
+	void DrawChar(int16 chr);
+	void StdChar(int16 chr);
+	SCILanguage getSCILanguage();
+	char* StrSplit(char*buff, const char*msg, const char*fmt);
+	char* getIntlString(char*buff, const char*msg, const char*fmt, SCILanguage lang, SCILanguage prop);
+	int16 TextSize(Common::Rect &rect, const char *str, int16 fontId, int16 maxwidth);
+	int16 GetLongest(const char *str, int16 maxwidth);
+	void DrawText(const char *str, int16 from, int16 len);
+	void ShowText(const char *str, int16 from, int16 len);
+	void ShowString(const char *str) {
+		ShowText(str, 0, (int16)strlen(str));
+	}
+	void DrawString(const char *str) {
+		DrawText(str, 0, (int16)strlen(str));
+	}
+	void TextBox(const char *str, int16 bshow, const Common::Rect &rect, int16 align, int16 fontId);
+	void ShowBits(const Common::Rect &r, uint16 flags);
+	sciMemoryHandle SaveBits(const Common::Rect &rect, byte screenFlags);
+	void RestoreBits(sciMemoryHandle memoryHandle);
+
+	void Draw_Line(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control);
+	void Draw_Horiz(int16 left, int16 right, int16 top, byte flag, byte color, byte prio, byte control);
+	void Draw_Vert(int16 top, int16 bottom, int16 left, byte flag, byte color, byte prio, byte control);
+	void Draw_Box(Common::Rect box, byte color, byte prio, byte control);
+	void Draw_TexturedBox(Common::Rect box, byte color, byte prio, byte control, byte texture);
+	void Draw_Circle(Common::Rect box, byte size, byte color, byte prio, byte control);
+	void Draw_TexturedCircle(Common::Rect box, byte size, byte color, byte prio, byte control, byte texture);
+	void Draw_Pattern(int16 x, int16 y, byte pic_color, byte pic_priority, byte pic_control, byte code, byte texture);
+	void Pic_Fill(int16 x, int16 y, byte color, byte prio, byte control);
+	
+	void drawPicture(sciResourceId pictureId, uint16 style, bool addToFlag, sciResourceId paletteId);
+	void drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo);
+
+	void animatePalette(byte fromColor, byte toColor, int speed);
+
+	sciPort *_menuPort;
+	uint32 _sysTicks;
+	int32 _sysSpeed; // ticker timer in ms 
+	sciPalette _sysPalette;
+
+	uint16 _resolutionWidth;
+	uint16 _resolutionHeight;
+	uint _resolutionPixels;
+
+private:
+	OSystem *_system;
+	EngineState *_s;
+	SciGUIscreen *_screen;
+
+	Common::Rect _bounds;
+	sciPort *_mainPort;
+	sciPort *_curPort;
+//	byte *_visualScreen;
+//	byte *_pcSeg;
+	uint16 _clrPowers[256];
+
+	byte bMapColors;
+	sciPalette *pPicPal;
+	Common::Array<sciPalSched> _palSchedules;
+
+	SciGUIfont *_font;
+};
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_helpers.h b/engines/sci/gui/gui_helpers.h
new file mode 100644
index 0000000..3f80d0c
--- /dev/null
+++ b/engines/sci/gui/gui_helpers.h
@@ -0,0 +1,150 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/rect.h"
+#include "sci/engine/vm_types.h"
+
+namespace Sci {
+
+typedef int sciResourceId; // is a resource-number and -1 means no parameter given
+typedef reg_t sciMemoryHandle;
+typedef uint16 SCIHANDLE;
+
+struct sciNode {
+	SCIHANDLE next; // heap handle to next node
+	SCIHANDLE prev; // heap handle to data
+	uint16 key; // maybe also a heap handle
+};
+struct sciNode1 : sciNode {
+	uint16 value;
+};
+
+// sciPort and sciWnd need to be binary identical, so if you change anything in one, you have to change it in the other one
+//  as well!
+struct sciPort {
+	sciNode node; // node struct for list operations
+	int16 top, left;
+	Common::Rect rect;
+	int16 curTop, curLeft;
+	int16 fontH;
+	sciResourceId fontId;
+	int16 textFace, penClr, backClr;
+	int16 penMode;
+};
+
+struct sciWnd {
+	// begins like sciPort (needs to be binary identical!!)
+	sciNode node; // node struct for list operations
+	int16 top, left;
+	Common::Rect rect;
+	int16 curTop, curLeft;
+	int16 fontH;
+	sciResourceId fontId;
+	int16 textFace, penClr, backClr;
+	int16 penMode;
+	// window specific members
+	Common::Rect rect0; // client area of window
+	Common::Rect rect1; // total area of window including borders
+	uint16 wndStyle;
+	uint16 uSaveFlag;
+	reg_t hSaved1;
+	reg_t hSaved2;
+	SCIHANDLE hTitle;
+	bool bDrawed;
+};
+
+struct sciCast {
+	sciNode node;
+	uint16 view;
+	uint16 loop;
+	uint16 cel;
+	uint16 z;
+	uint16 pal;
+	SCIHANDLE hSaved;
+	Common::Rect rect;
+};
+
+struct sciColor {
+	byte used;
+	byte r, g, b;
+};
+
+struct sciPalette {
+	byte mapping[256];
+	uint32 timestamp;
+	sciColor colors[256];
+	byte intencity[256];
+};
+
+struct sciPalSched {
+	byte from;
+	uint32 schedule;
+};
+
+#define STUB(str) debug("STUB: '%s' at file %s line %d",str,__FILE__,__LINE__)
+
+
+// FIXME: The following feature enums and macros should be reconsidered.
+// The way they are done right now is highly error prone.
+
+enum {
+	FTR_WINDOWMGR_SCI0	= (0<<0),	// SCI0 based window manager
+	FTR_WINDOWMGR_SCI1	= (1<<0),	// SCI1 based window manager  
+	FTR_CAN_BEHERE		= (0<<1),	// Kernel77 is kCanBeHere (SCI0)
+	FTR_CANT_BEHERE		= (1<<1),	// Kernel77 is kCantBeHere(SCI1)
+	FTR_SOUND_SCI0		= (0<<2),	// SCI0 Sound functions
+	FTR_SOUND_SCI01		= (1<<2),	// SCI0+ Sound functions
+	FTR_SOUND_SCI1		= (2<<2),	// SCI1 Sound functions
+	FTR_SHOWPIC_SCI0	= (0<<4),	// SCI0 ShowPic (44 effect codes)
+	FTR_SHOWPIC_SCI1	= (1<<4),	// SCI1 ShowPic (15 effect codes)
+	FTR_GL_ANIMATE		= (1<<5)	// Animate can be paused by global flag
+};
+
+#define GETFTR_WINDOWMGR(x) (x & 0x00000001)
+#define GETFTR_CANBEHERE(x) (x & 0x00000002)
+#define GETFTR_SOUND(x)		(x & 0x0000000C)
+#define GETFTR_SHOWPIC(x)	(x & 0x00000010)
+
+enum {
+	GFX_STOPUPDATE = 0x01,
+	GFX_VIEWUPDATED = 0x02,
+	GFX_NOUPDATE = 0x04,
+	GFX_HIDDEN = 0x08,
+	GFX_FIXEDPRIO=0x10,
+	GFX_ALWAYSUPDATE = 0x20,
+	GFX_FORCEUPDATE = 0x40,
+	GFX_REMOVEVIEW = 0x80
+};
+
+enum SCILanguage{
+	kLangNone = 0,
+	kLangEnglish = 1,
+	kLangFrench = 33,
+	kLangSpanish = 34,
+	kLangItalian = 39,
+	kLangGerman = 49
+};
+
+}
diff --git a/engines/sci/gui/gui_memmgr.cpp b/engines/sci/gui/gui_memmgr.cpp
new file mode 100644
index 0000000..3b42da2
--- /dev/null
+++ b/engines/sci/gui/gui_memmgr.cpp
@@ -0,0 +1,373 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/gui/gui_helpers.h"
+#include "sci/gui/gui_memmgr.h"
+
+namespace Sci {
+
+static tagHandle *pHandles = 0;
+static int16 nHandles = 0;
+static byte *_heap = 0;
+SCIHANDLE _firstfree = 0;
+Common::HashMap<HEAPHANDLE, tagHeapInfo> heapInfo;
+#define HEAP_BOTTOM 1000
+
+//----------------------
+void FreeMem(void) {
+	// deleting handles
+	if (pHandles) {
+		for (uint16 i = 0; i < nHandles; i++)
+			hunkDisposeHandle(i);
+		delete[] pHandles;
+		pHandles = 0;
+	}
+	// deleting heap
+	if (_heap) {
+		delete[] _heap;
+		_heap = 0;
+	}
+}
+//----------------------
+bool InitMem(int16 max_handles) {
+	// heap
+	_heap = new byte[HEAP_SIZE];
+	memset(_heap, 0x55, HEAP_SIZE);
+	_firstfree = HEAP_START;
+	heapSetBlockSize(_firstfree, HEAP_SIZE - 1 - HEAP_START);
+	heapSetBlockNext(_firstfree, (SCIHANDLE)(HEAP_SIZE - 1));
+	//hunk
+	pHandles = new tagHandle[max_handles];
+	if (pHandles) {
+		nHandles = max_handles;
+		memset(pHandles, 0, sizeof(tagHandle) * max_handles); // zerofy all
+		return 1;
+	}
+	return 0;
+}
+//----------------------
+SCIHANDLE hunkNeedHandle(uint16 size, uint32 resId) {
+	SCIHANDLE newh = 0;
+	// see if there is an empty handle available
+	for (int16 i = 1; i < nHandles; i++)
+		if (pHandles[i].ptr == 0) {
+			newh = i;
+			break;
+		}
+	// if unused handle was found - allocate memory and return it
+	if (newh == nHandles)
+		return 0;
+	pHandles[newh].ptr = (byte*)malloc(size);
+	assert(pHandles[newh].ptr);
+	if (pHandles[newh].ptr) {
+		pHandles[newh].size = size;
+		pHandles[newh].resId = resId;
+		debug(
+				5,
+				"   MemMgr: Requested %6db for res %08X, allocated handle %04X",
+				size, resId, newh);
+		return newh;
+	}
+	return 0;
+}
+//----------------------
+void hunkDisposeHandle(SCIHANDLE handle) {
+// 	if (handle > 0 && handle < nHandles && pHandles[handle].ptr) {
+// 		debug(
+// 				5,
+// 				"   MemMgr: disposing handle 0x%04X, size=%8db, associated res %08X",
+// 				handle, pHandles[handle].size, pHandles[handle].resId);
+// 		free(pHandles[handle].ptr);
+// 		pHandles[handle].ptr = 0;
+// 		// deleting associated resource handler
+// 		// Check that this don't fail on delete as ResGetLoaded could return 0;
+// 		if (pHandles[handle].resId != 0xFFFFFFFF)
+// 			delete g_sci->ResMgr.ResGetLoaded(pHandles[handle].resId);
+// 	}
+}
+//----------------------
+byte *hunk2Ptr(SCIHANDLE handle) {
+	if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
+		return (byte *)pHandles[handle].ptr;
+	return 0;
+}
+//----------------------
+SCIHANDLE ptr2hunk(byte *ptr) {
+	for (int i = 0; i < nHandles; i++) {
+		if (ptr >= pHandles[i].ptr && ptr <= pHandles[i].ptr + pHandles[i].size)
+			return i;
+	}
+return 0;
+}
+//----------------------
+uint32 hunkHandleSize(SCIHANDLE handle) {
+	if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
+		return pHandles[handle].size;
+	return 0;
+}
+//----------------------
+// int16 hunkResourceNum(SCIHANDLE handle) {
+// 	if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
+// 		return RES_ID2NUM(pHandles[handle].resId);
+// 	return -1;
+// }
+
+//----------------------
+void hunkDump() {
+	debug("\nMemMgr: Hunk dump:");
+	uint32 size = 0;
+	for (int i = 0; i < nHandles; i++)
+		if (pHandles[i].ptr) {
+			debug("  %04X, size=%8db, associated res %08X", i,
+					pHandles[i].size, pHandles[i].resId);
+			size += pHandles[i].size;
+		}
+	debug("Total memory allocated: %db", size);
+	debug("End dump");
+}
+
+uint32 hunkUsed() {
+	uint32 size = 0;
+	for (int i = 0; i < nHandles; i++)
+		if (pHandles[i].ptr)
+			size += pHandles[i].size;
+	return size;
+}
+//----------------------
+// HEAP
+//----------------------
+//---------------------------------------------
+// TODO : make sure that STRING, STACK and SCRIPT DATA is never allocated below HEAP_BOTTOM=1000
+// otherwise it will cause problems with kernel string fuctions that assumes that anything below 1000 is res number
+HEAPHANDLE heapNewPtr(uint16 size, kDataType type, const char *info) {
+	if (size == 0)
+		warning("Zero Heap Allocation Request!");
+
+	HEAPHANDLE ptr, prev, next;
+	ptr = prev = _firstfree;
+	// 2 bytes block header header + block size must be odd
+	size += 2 + (size & 1);
+	// looking for an empty block to use
+	uint16 blocksize;
+	bool bBottomSafe = !(type == kDataString || type == kDataUnknown);
+
+	while (ptr < HEAP_SIZE - 1) {
+		blocksize = heapGetBlockSize(ptr);
+		next = heapGetBlockNext(ptr);
+		if (blocksize >= size) {
+			if (bBottomSafe || (!bBottomSafe && ptr > HEAP_BOTTOM)) {
+				if (blocksize <= size + 4) { // use all block
+					size = blocksize;
+					heapSetBlockNext(prev, next);
+				} else { // split block in 2 blocks
+					HEAPHANDLE newblock = ptr + size;
+					heapSetBlockNext(prev, newblock);
+					heapSetBlockSize(newblock, blocksize - size);
+					heapSetBlockNext(newblock, next);
+					next = newblock;
+				}
+				// setting allocated block
+				heapSetBlockSize(ptr, size);
+				// updating firstfree pointer
+				if (ptr == _firstfree)
+					_firstfree = next;
+				setHeapInfo(ptr, type, info);
+				return ptr;
+			} //if (bBottomSafe || (!bBottomSafe && ptr>HEAP_BOTTOM))
+			else { // !bottomsafe && ptr < HEAP_BOTTOM
+				if (blocksize + ptr - HEAP_BOTTOM >= size) {
+					// splitting the block into 3 parts
+					// [2][ptr...999] [2][1002...1000+size-1] [2][1002+size...ptr+blocksize]
+					//   free              returned              free
+					heapSetBlockSize(ptr, HEAP_BOTTOM-ptr + 2);
+					heapSetBlockSize(HEAP_BOTTOM+2, size);
+					heapSetBlockSize(HEAP_BOTTOM+2 + size, blocksize - size
+							- (HEAP_BOTTOM-ptr + 2));
+
+					heapSetBlockNext(HEAP_BOTTOM+2 + size, next);
+					heapSetBlockNext(ptr, HEAP_BOTTOM+2 + size);
+					setHeapInfo(HEAP_BOTTOM+2, type, info);
+					return HEAP_BOTTOM + 2;
+				}
+			}
+		} // if (blocksize >= size)
+		// block too small - moving to next one
+		prev = ptr;
+		ptr = next;
+	}
+	// allocation error - out of heap
+	warning("Out of heap space");
+	return 0;
+}
+//--------------------------------------------
+void heapDisposePtr(HEAPHANDLE handle) {
+	HEAPHANDLE prev, next;
+	prev = next = _firstfree;
+	// searching for prev and next free blocks (before & after deleted block)
+	while (next < handle) {
+		prev = next;
+		next = heapGetBlockNext(prev);
+	}
+	// if deleted block is before 1st free space then it'll be 1st free space
+	if (handle < _firstfree) {
+		next = _firstfree;
+		_firstfree = handle;
+	} else
+		heapSetBlockNext(prev, handle);
+
+	heapSetBlockNext(handle, next);
+	//Try to merge with previous
+	if (prev + heapGetBlockSize(prev) == handle) {
+		heapSetBlockSize(prev, heapGetBlockSize(prev)
+				+ heapGetBlockSize(handle));
+		heapSetBlockNext(prev, next);
+		handle = prev;
+	}
+	//Try to merge with next
+	if (handle + heapGetBlockSize(handle) == next && next != (HEAP_SIZE - 1)) {
+		heapSetBlockSize(handle, heapGetBlockSize(handle) + heapGetBlockSize(
+				next));
+		heapSetBlockNext(handle, heapGetBlockNext(next));
+	}
+}
+//-------------------------------------
+uint16 heapFreeSize() {
+	HEAPHANDLE free = _firstfree;
+	uint16 szFree = 0;
+	while (free < HEAP_SIZE - 1) {
+		int size = heapGetBlockSize(free);
+		free = heapGetBlockNext(free);
+		szFree += size;
+	}
+	return szFree;
+}
+//-------------------------------------
+uint16 heapLargestFreeSize() {
+	HEAPHANDLE free = _firstfree;
+	uint16 maxFree = 0;
+	while (free < HEAP_SIZE - 1) {
+		int size = heapGetBlockSize(free);
+		free = heapGetBlockNext(free);
+		if (size > maxFree)
+			maxFree = size;
+	}
+	return maxFree ? maxFree - 2 : 0;
+}
+//-------------------------------------
+void heapDump() {
+	debug("\nMemMgr:Heap dump:");
+	HEAPHANDLE ptr = HEAP_START;
+	HEAPHANDLE free = _firstfree;
+
+	uint16 szFree = 0, szUsed = 0;
+	while (ptr < HEAP_SIZE - 1) {
+		int size = heapGetBlockSize(ptr);
+		if (ptr == free) {
+			free = heapGetBlockNext(free);
+			debug("  %04X %6u size:%6d FREE next=%04X", ptr, ptr,
+					heapGetDataSize(ptr), free);
+			szFree += size;
+		} else {
+			debug("  %04X %6u size:%6d USED", ptr, ptr, heapGetDataSize(ptr));
+			szUsed += size;
+		}
+		ptr += size;
+	}
+	debug("Total %db used, %db free\nEnd Dump", szUsed, szFree);
+}
+//----------------------------
+inline byte *heap2Ptr(HEAPHANDLE ptr) {
+	return (ptr >= HEAP_START) ? (byte *)(_heap + ptr) : NULL;
+}
+//----------------------------
+HEAPHANDLE ptr2heap(byte *ptr) {
+	return ptr > _heap && ptr < (_heap + HEAP_SIZE) ? (HEAPHANDLE)(ptr - _heap)
+			: 0;
+}
+//----------------------------
+uint16 heapGetBlockSize(HEAPHANDLE ptr) {
+	return READ_UINT16(_heap + ptr - 2);
+}
+//----------------------------
+uint16 heapGetDataSize(HEAPHANDLE ptr) {
+	return heapGetBlockSize(ptr) - 2;
+}
+//----------------------------
+void heapFillPtr(HEAPHANDLE ptr, byte filler) {
+	memset(heap2Ptr(ptr), filler, heapGetDataSize(ptr));
+}
+//----------------------------
+void heapClearPtr(HEAPHANDLE ptr) {
+	heapFillPtr(ptr, 0);
+}
+//----------------------------
+void heapSetBlockSize(HEAPHANDLE ptr, uint16 nbytes) {
+	WRITE_UINT16(_heap + ptr - 2, nbytes);
+}
+//----------------------------
+HEAPHANDLE heapGetBlockNext(HEAPHANDLE ptr) {
+	return READ_UINT16(_heap + ptr);
+}
+//----------------------------
+void heapSetBlockNext(HEAPHANDLE ptr, SCIHANDLE next) {
+	WRITE_UINT16(_heap + ptr, next);
+}
+//----------------------------
+void heapDisposePtr(byte *ptr) {
+	heapDisposePtr(ptr - _heap);
+}
+//---------------------------------------------
+//
+//
+void setHeapInfo(HEAPHANDLE hnd, kDataType type, const char *szinfo) {
+	tagHeapInfo info = { kDataUnknown, 0 };
+	info.type = type;
+	if (szinfo)
+		strncpy(info.info, szinfo, 20);
+	heapInfo.setVal(hnd, info);
+}
+//--------------------------------
+bool saveMemState(Common::OutSaveFile *pFile) {
+	pFile->writeString("MEMORY\n");
+	// saving heap
+	pFile->write(_heap, HEAP_SIZE);
+	pFile->writeUint16LE(_firstfree);
+	// TODO : process and write hunk handles
+	//pFile->writeString("HUNK\n");
+	return true;
+}
+//--------------------------------
+bool restoreMemState(Common::InSaveFile *pFile) {
+	if (pFile->readLine() != "MEMORY")
+		return false;
+	pFile->read(_heap, HEAP_SIZE);
+	_firstfree = pFile->readUint16LE();
+
+	return true;
+}
+
+//-------------------------------
+}// end of namespace SCI
diff --git a/engines/sci/gui/gui_memmgr.h b/engines/sci/gui/gui_memmgr.h
new file mode 100644
index 0000000..4a1631c
--- /dev/null
+++ b/engines/sci/gui/gui_memmgr.h
@@ -0,0 +1,123 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SCI_MEMMGR_H
+#define SCI_MEMMGR_H
+
+#include "common/savefile.h"
+#include "common/endian.h"
+#include "common/hashmap.h"
+
+/*
+ Memory management functions for SCI engine;
+ All fuctions are simplified as there is no 16-bit limitations as in
+ original SCI. Although it may cause problems.
+
+ SCI Heap functionality.
+ Heap size is limited to 65535 bytes to be consistent with SCI scripts
+ Free block header is [wBlockSize][wNextFree]
+ Used block header is [wBlockSize][data.....]
+ ^-----returned HEAPHANDLE
+ */
+
+namespace Sci {
+
+typedef uint16 SCIHANDLE;
+typedef uint16 HEAPHANDLE;
+
+enum {
+	HEAP_SIZE	= 0x10000l,
+	HEAP_START	= 2
+};
+
+struct tagHandle {
+	byte *ptr; // data pointer
+	uint32 size; // memory block size
+	uint32 resId; // associated resource
+};
+//---------------------------------------------
+// for debugger
+enum kDataType {
+	kDataUnknown = 0,
+	kDataClass,
+	kDataObject,
+	kDataRect,
+	kDataWindow,
+	kDataPort,
+	kDataString,
+	kDataListHdr,
+	kDataListNode,
+	kDataCast,
+	kDataPalette,
+	kDataScript,
+	kDataFile
+};
+
+struct tagHeapInfo {
+	kDataType type;
+	char info[21];
+};
+
+void setHeapInfo(HEAPHANDLE hnd, kDataType type, const char *info = 0);
+
+bool InitMem(int16 max_handles);
+void FreeMem(void);
+
+// hunk functions
+SCIHANDLE hunkNeedHandle(uint16 size, uint32 resId = 0xFFFFFFFF);
+void hunkDisposeHandle(SCIHANDLE handle);
+
+byte *hunk2Ptr(SCIHANDLE handle);
+SCIHANDLE ptr2hunk(byte *ptr);
+uint32 hunkHandleSize(SCIHANDLE handle);
+int16 hunkResourceNum(SCIHANDLE handle);
+void hunkDump();
+uint32 hunkUsed();
+
+// heap functions
+HEAPHANDLE heapNewPtr(uint16 size, kDataType type/*=kDataUnknown*/,
+		const char *info = 0);
+void heapDisposePtr(HEAPHANDLE handle);
+void heapDisposePtr(byte *ptr);
+byte *heap2Ptr(HEAPHANDLE ptr);
+HEAPHANDLE ptr2heap(byte *ptr);
+uint16 heapGetBlockSize(HEAPHANDLE ptr);
+uint16 heapGetDataSize(HEAPHANDLE ptr);
+void heapFillPtr(HEAPHANDLE ptr, byte filler);
+void heapClearPtr(HEAPHANDLE ptr);
+void heapDump();
+uint16 heapFreeSize();
+uint16 heapLargestFreeSize();
+
+void heapSetBlockSize(HEAPHANDLE ptr, uint16 nbytes);
+HEAPHANDLE heapGetBlockNext(HEAPHANDLE ptr);
+void heapSetBlockNext(HEAPHANDLE ptr, SCIHANDLE next);
+
+bool saveMemState(Common::OutSaveFile *pFile);
+bool restoreMemState(Common::InSaveFile *pFile);
+
+} // end of namespace SCI
+
+#endif
diff --git a/engines/sci/gui/gui_picture.cpp b/engines/sci/gui/gui_picture.cpp
new file mode 100644
index 0000000..1f2218a
--- /dev/null
+++ b/engines/sci/gui/gui_picture.cpp
@@ -0,0 +1,592 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_screen.h"
+#include "sci/gui/gui_gfx.h"
+#include "sci/gui/gui_picture.h"
+
+namespace Sci {
+
+SciGUIpicture::SciGUIpicture(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId)
+	: _system(system), _s(state), _gfx(gfx), _screen(screen), _resourceId(resourceId) {
+	assert(resourceId != -1);
+	initData(resourceId);
+}
+
+SciGUIpicture::~SciGUIpicture() {
+}
+
+void SciGUIpicture::initData(sciResourceId resourceId) {
+	_resource = _s->resMan->findResource(ResourceId(kResourceTypePic, resourceId), false);
+	if (!_resource) {
+		error("picture resource %d not found", resourceId);
+	}
+}
+
+sciResourceId SciGUIpicture::getResourceId() {
+	return _resourceId;
+}
+
+#define PALETTE_SIZE 1284
+#define CEL_HEADER_SIZE 7
+#define EXTRA_MAGIC_SIZE 15
+
+void SciGUIpicture::draw(uint16 style, bool addToFlag, int16 EGApaletteNo) {
+	_style = style;
+	_addToFlag = addToFlag;
+	_EGApaletteNo = EGApaletteNo;
+	_curPort = _gfx->GetPort();
+	_priority = 0;
+
+	if (READ_LE_UINT16(_resource->data) == 0x26) {
+		// SCI 1.1 picture
+		draw11();
+	} else {
+		// Just directly draw the vector data
+		_gfx->SetEGApalette();
+		drawVectorData(_resource->data, _resource->size);
+	}
+}
+
+void SciGUIpicture::reset() {
+	int16 x, y;
+	for (y = _curPort->top; y < _screen->_height; y++) {
+		for (x = 0; x < _screen->_width; x++) {
+			_screen->Put_Pixel(x, y, SCI_SCREEN_MASK_ALL, 255, 0, 0);
+		}
+	}
+}
+
+void SciGUIpicture::draw11() {
+	byte *inbuffer = _resource->data;
+	int size = _resource->size;
+	int has_view = READ_LE_UINT16(inbuffer + 4);
+	int vector_data_ptr = READ_LE_UINT16(inbuffer + 16);
+	int vector_size = size - vector_data_ptr;
+	int palette_data_ptr = READ_LE_UINT16(inbuffer + 28);
+	int view_data_ptr = READ_LE_UINT16(inbuffer + 32);
+	int view_size = palette_data_ptr - view_data_ptr;
+	int view_rle_ptr = READ_LE_UINT16(inbuffer + view_data_ptr + 24);
+	int view_pixel_ptr = READ_LE_UINT16(inbuffer + view_data_ptr + 28);
+	byte *view = NULL;
+	sciPalette palette;
+
+	// Create palette and set it
+	_gfx->CreatePaletteFromData(inbuffer + palette_data_ptr, &palette);
+	_gfx->SetPalette(&palette, 2);
+//	drawPalette11(inbuffer + palette_data_ptr);
+
+	// display Cel-data
+	if (has_view) {
+		view = (byte *)malloc(size*2); // is there a way to know how much decoded view-data there will be?
+		if (!view) return;
+		memcpy(view, inbuffer + view_data_ptr, 8);
+		decodeRLE(inbuffer + view_rle_ptr, inbuffer + view_pixel_ptr, view + 8, view_size - 8);
+		drawCel(0, 0, view, size * 2);
+		free(view);
+	}
+
+	// process vector data
+	// ?? if we process vector data first some things in sq4 dont seem right, but this way we wont get _priority set
+	drawVectorData(inbuffer + vector_data_ptr, vector_size);
+}
+
+void SciGUIpicture::drawPalette11(byte *data) {
+	int start_color = data[25];
+	int format = data[32];
+	byte *pal_data = &data[37];
+	int colors_nr = READ_LE_UINT16(data + 29);
+	int i;
+	sciPalette palette = {0};
+
+	switch (format) {
+	case SCI_PAL_FORMAT_VARIABLE_FLAGS:
+		for (i = start_color; i < start_color + colors_nr; i ++) {
+			palette.colors[i].used = pal_data[0];
+			palette.colors[i].r = pal_data[1];
+			palette.colors[i].g = pal_data[2];
+			palette.colors[i].b = pal_data[3];
+			pal_data += 4;
+		}
+		break;
+	case SCI_PAL_FORMAT_CONSTANT_FLAGS:
+		for (i = start_color; i < start_color + colors_nr; i ++) {
+			palette.colors[i].used = 1;
+			palette.colors[i].r = pal_data[0];
+			palette.colors[i].g = pal_data[1];
+			palette.colors[i].b = pal_data[2];
+			pal_data += 3;
+		}
+		break;
+	}
+	_gfx->SetPalette(&palette, 2);
+}
+
+void SciGUIpicture::decodeRLE(byte *rledata, byte *pixeldata, byte *outbuffer, int size) {
+	int pos = 0;
+	byte nextbyte;
+	byte *rd = rledata;
+	byte *ob = outbuffer;
+	byte *pd = pixeldata;
+
+	while (pos < size) {
+		nextbyte = *(rd++);
+		*(ob++) = nextbyte;
+		pos ++;
+		switch (nextbyte&0xC0) {
+		case 0x40 :
+		case 0x00 :
+			memcpy(ob, pd, nextbyte);
+			pd += nextbyte;
+			ob += nextbyte;
+			pos += nextbyte;
+			break;
+		case 0xC0 :
+			break;
+		case 0x80 :
+			nextbyte = *(pd++);
+			*(ob++) = nextbyte;
+			pos ++;
+			break;
+		}
+	}
+}
+
+void SciGUIpicture::drawCel(int16 x, int16 y, byte *pdata, int size) {
+	byte* pend = pdata + size;
+	uint16 width = READ_LE_UINT16(pdata + 0);
+	uint16 height = READ_LE_UINT16(pdata + 2);
+	signed char dx = *(pdata + 4);
+	signed char dy = *(pdata + 5);
+	byte priority = _addToFlag ? _priority : 0;
+	byte clr = *(pdata + 6);
+	if (dx || dy || width != 320)
+		debug("Warning: embedded picture cel has width=%d dx=%d dy=%d", width, dx, dy);
+	byte *ptr = pdata + 8; // offset to data
+
+	y += _curPort->top;
+
+	uint16 j = 0, lasty = MIN<int16>(height + y, _curPort->rect.bottom) + _curPort->top;
+	byte b, brun;
+
+	while (y < lasty && ptr < pend) {
+		b = *ptr++;
+		brun = b & 0x3F; // bytes run length on this step
+		switch (b & 0xC0) {
+		case 0: // copy bytes as-is but skip transparent ones
+			while (brun-- && y < lasty && ptr < pend) {
+				if ((b = *ptr++) != clr && priority >= _screen->Get_Priority(x, y)) {
+					_screen->Put_Pixel(x, y, 3, b, priority, 0);
+				}
+				x++;
+				if (x >= _screen->_width) {
+					x -= _screen->_width; y++;
+				}
+			}
+			break;
+		case 0x80: // fill with color
+			b = *ptr++;
+			while (brun-- && y < lasty) {
+				if (priority >= _screen->Get_Priority(x, y)) {
+					_screen->Put_Pixel(x, y, 3, b, priority, 0);
+				}
+				x++;
+				if (x >= _screen->_width) {
+					x -= _screen->_width; y++;
+				}
+			}
+			break;
+		case 0xC0: // fill with transparent - skip
+			x += brun;
+			if (x >= _screen->_width) {
+				x -= _screen->_width; y++;
+			}
+			break;
+		}
+	}
+}
+
+void SciGUIpicture::drawCelAmiga(int16 x, int16 y, byte *pdata, int size) {
+	byte* pend = pdata + size;
+	uint16 width = READ_LE_UINT16(pdata + 0);
+	uint16 height = READ_LE_UINT16(pdata + 2);
+	signed char dx = *(pdata + 4);
+	signed char dy = *(pdata + 5);
+	byte priority = _addToFlag ? _priority : 0;
+	//byte clr = *(pdata + 8);
+	if (dx || dy || width != 320)
+		debug("Warning : cel have w=%d dx=%d dy=%d", width, dx, dy);
+	byte *ptr = pdata + 8; // offset to data
+
+	y += _curPort->top;
+
+	uint16 j = 0, lasty = MIN<int16>(height + y, _curPort->rect.bottom) + _curPort->top;
+	byte op, col, bytes;
+	while (y < lasty && ptr < pend) {
+		op = *ptr++;
+		if (op & 0x07) {
+			bytes = op & 0x07;
+			col = op >> 3;
+			while (bytes-- && y < lasty) {
+				if (priority >= _screen->Get_Priority(x, y)) {
+					_screen->Put_Pixel(x, y, 3, col, priority, 0);
+				}
+				x++;
+				if (x >= _screen->_width) {
+					x -= _screen->_width; y++;
+				}
+			}
+		} else {
+			bytes = op >> 3;
+			x += bytes;
+			if (x >= _screen->_width) {
+				x -= _screen->_width; y++;
+			}
+		}
+	}
+}
+
+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
+};
+#define PIC_OP_FIRST PIC_OP_SET_COLOR
+
+enum {
+	PIC_OPX_SCI0_SET_PALETTE_ENTRIES = 0,
+	PIC_OPX_SCI0_SET_PALETTE = 1,
+	PIC_OPX_SCI0_MONO0 = 2,
+	PIC_OPX_SCI0_MONO1 = 3,
+	PIC_OPX_SCI0_MONO2 = 4,
+	PIC_OPX_SCI0_MONO3 = 5,
+	PIC_OPX_SCI0_MONO4 = 6,
+	PIC_OPX_SCI0_EMBEDDED_VIEW = 7,
+	PIC_OPX_SCI0_SET_PRIORITY_TABLE = 8
+};
+
+enum {
+	PIC_OPX_SCI1_SET_PALETTE_ENTRIES = 0,
+	PIC_OPX_SCI1_EMBEDDED_VIEW = 1,
+	PIC_OPX_SCI1_SET_PALETTE = 2,
+	PIC_OPX_SCI1_PRIORITY_TABLE_EQDIST = 3,
+	PIC_OPX_SCI1_PRIORITY_TABLE_EXPLICIT = 4
+};
+
+#define PIC_EGAPALETTE_COUNT 4
+#define PIC_EGAPALETTE_SIZE  40
+#define PIC_EGAPALETTE_TOTALSIZE PIC_EGAPALETTE_COUNT*PIC_EGAPALETTE_SIZE
+
+const byte vector_defaultEGApalette[PIC_EGAPALETTE_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
+};
+
+void SciGUIpicture::drawVectorData(byte *data, int dataSize) {
+	byte pic_op;
+	byte pic_color = 0, pic_priority = 0x0F, pic_control = 0x0F;
+	int16 x = 0, y = 0, oldx, oldy;
+	byte EGApalette = 0;
+	byte EGAindex = 0;
+	byte EGApalettes[PIC_EGAPALETTE_TOTALSIZE] = {0};
+	bool EGAmapping = false;
+	int curPos = 0;
+	uint16 size;
+	byte byte;
+	int i;
+	sciPalette palette = {0};
+	int16 pattern_Code = 0, pattern_Texture = 0;
+	bool sci1 = false;
+
+	if (_EGApaletteNo >= PIC_EGAPALETTE_COUNT)
+		_EGApaletteNo = 0;
+
+	if (getSciVersion() >= SCI_VERSION_1_EGA)
+		sci1 = true;
+
+	for (i = 0; i < PIC_EGAPALETTE_TOTALSIZE; i += PIC_EGAPALETTE_SIZE)
+		memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette));
+
+	// Drawing
+	while (curPos < dataSize) {
+		warning("%X at %d", data[curPos], curPos);
+		switch (pic_op = data[curPos++]) {
+		case PIC_OP_SET_COLOR:
+			byte = data[curPos++];
+			pic_color = EGAmapping ? EGApalettes[byte] : byte;
+			break;
+		case PIC_OP_DISABLE_VISUAL:
+			pic_color = 0xFF;
+			break;
+
+		case PIC_OP_SET_PRIORITY:
+			pic_priority = data[curPos++];
+			break;
+		case PIC_OP_DISABLE_PRIORITY:
+			pic_priority = 255;
+			break;
+
+		case PIC_OP_SET_CONTROL:
+			pic_control = data[curPos++];
+			break;
+		case PIC_OP_DISABLE_CONTROL:
+			pic_control = 255;
+			break;
+
+		case PIC_OP_SHORT_LINES: // short line
+			vectorGetAbsCoords(data, curPos, oldx, oldy);
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetRelCoords(data, curPos, oldx, oldy, x, y);
+				warning("line %d %d -> %d %d", oldy, oldx, y, x);
+				_gfx->Draw_Line(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
+				oldx = x; oldy = y;
+			}
+			break;
+		case PIC_OP_MEDIUM_LINES: // medium line
+			vectorGetAbsCoords(data, curPos, oldx, oldy);
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetRelCoordsMed(data, curPos, oldx, oldy, x, y);
+				warning("line %d %d -> %d %d", oldy, oldx, y, x);
+				_gfx->Draw_Line(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
+				oldx = x; oldy = y;
+			}
+			break;
+		case PIC_OP_LONG_LINES: // long line
+			vectorGetAbsCoords(data, curPos, oldx, oldy);
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetAbsCoords(data, curPos, x, y);
+				warning("line %d %d -> %d %d", oldy, oldx, y, x);
+				_gfx->Draw_Line(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
+				oldx = x; oldy = y;
+			}
+			break;
+
+		case PIC_OP_FILL: //fill
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetAbsCoords(data, curPos, x, y);
+				warning("fill %d %d", y, x);
+				_gfx->Pic_Fill(x, y, pic_color, pic_priority, pic_control);
+			}
+			break;
+
+		case PIC_OP_SET_PATTERN:
+			pattern_Code = data[curPos++];
+			break;
+		case PIC_OP_SHORT_PATTERNS:
+			vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
+			vectorGetAbsCoords(data, curPos, x, y);
+			warning("pattern %d %d", y, x);
+			_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
+				vectorGetRelCoords(data, curPos, x, y, x, y);
+				warning("pattern %d %d", y, x);
+				_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
+			}
+			break;
+		case PIC_OP_MEDIUM_PATTERNS:
+			vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
+			vectorGetAbsCoords(data, curPos, x, y);
+			warning("pattern %d %d", y, x);
+			_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
+				vectorGetRelCoordsMed(data, curPos, x, y, x, y);
+				warning("pattern %d %d", y, x);
+				_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
+			}
+			break;
+		case PIC_OP_ABSOLUTE_PATTERN:
+			while (vectorIsNonOpcode(data[curPos])) {
+				vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
+				vectorGetAbsCoords(data, curPos, x, y);
+				warning("pattern %d %d", y, x);
+				//_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
+			}
+			break;
+
+		case PIC_OP_OPX: // Extended functions
+			if (sci1) {
+				warning("OPX SCI1 %X at %d", data[curPos], curPos);
+				switch (pic_op = data[curPos++]) {
+				case PIC_OPX_SCI1_SET_PALETTE_ENTRIES:
+					while (vectorIsNonOpcode(data[curPos])) {
+						curPos++; // skip commands
+					}
+					break;
+				case PIC_OPX_SCI1_SET_PALETTE:
+					curPos += 256 + 4; // Skip over mapping and timestamp
+					for (i = 0; i < 256; i++) {
+						palette.colors[i].used = data[curPos++];
+						palette.colors[i].r = data[curPos++]; palette.colors[i].g = data[curPos++]; palette.colors[i].b = data[curPos++];
+					}
+					_gfx->SetPalette(&palette, 2);
+					break;
+				case PIC_OPX_SCI1_EMBEDDED_VIEW: // draw cel
+					vectorGetAbsCoords(data, curPos, x, y);
+					size = READ_LE_UINT16(data + curPos); curPos += 2;
+					drawCel(x, y, data + curPos, size);
+					curPos += size;
+					break;
+				case PIC_OPX_SCI1_PRIORITY_TABLE_EQDIST:
+					//FIXME
+					//g_sci->InitPri(READ_LE_UINT16(ptr), READ_LE_UINT16(ptr + 2));
+					debug(5, "DrawPic::InitPri %d %d", 
+						READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2));
+					curPos += 4;
+					break;
+				case PIC_OPX_SCI1_PRIORITY_TABLE_EXPLICIT:
+					//FIXME
+					//g_sci->PriBands(ptr);
+					curPos += 14;
+					break;
+				default:
+					error("Unsupported sci1 extended pic-operation %X", pic_op);
+				}
+			} else {
+				switch (pic_op = data[curPos++]) {
+				case PIC_OPX_SCI0_SET_PALETTE_ENTRIES:
+					while (vectorIsNonOpcode(data[curPos])) {
+						byte = data[curPos++];
+						if (byte >= PIC_EGAPALETTE_TOTALSIZE) {
+							error("picture trying to write to invalid EGA-palette");
+						}
+						EGApalettes[byte] = data[curPos++];
+					}
+					break;
+				case PIC_OPX_SCI0_SET_PALETTE:
+					byte = data[curPos++];
+					if (EGApalette >= PIC_EGAPALETTE_COUNT) {
+						error("picture trying to write to invalid palette %d", EGApalette);
+					}
+					byte *= PIC_EGAPALETTE_SIZE;
+					for (i = 0; i < PIC_EGAPALETTE_SIZE; i++) {
+						EGApalettes[byte + i] = data[curPos++];
+					}
+					break;
+				case PIC_OPX_SCI0_MONO0:
+					curPos += 41;
+					break;
+				case PIC_OPX_SCI0_MONO1:
+				case PIC_OPX_SCI0_MONO3:
+					curPos++;
+					break;
+				case PIC_OPX_SCI0_MONO2:
+				case PIC_OPX_SCI0_MONO4:
+					break;
+				case PIC_OPX_SCI0_EMBEDDED_VIEW:
+					vectorGetAbsCoords(data, curPos, x, y);
+					size = READ_LE_UINT16(data + curPos); curPos += 2;
+					drawCel(x, y, data + curPos, size);
+					curPos += size;
+					break;
+				case PIC_OPX_SCI0_SET_PRIORITY_TABLE:
+					//FIXME
+					//g_sci->PriBands(ptr);
+					curPos += 14;
+					break;
+				default:
+					error("Unsupported sci1 extended pic-operation %X", pic_op);
+				}
+			}
+			break;
+		case PIC_OP_TERMINATE:
+			_priority = pic_priority;
+			return;
+		default:
+			error("Unsupported pic-operation %X", pic_op);
+		}
+	}
+	error("picture vector data without terminator");
+}
+
+bool SciGUIpicture::vectorIsNonOpcode(byte byte) {
+	if (byte >= PIC_OP_FIRST)
+		return false;
+	return true;
+}
+
+void SciGUIpicture::vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y) {
+	byte byte = data[curPos++];
+	x = data[curPos++] + ((byte & 0xF0) << 4);
+	y = data[curPos++] + ((byte & 0x0F) << 8);
+	if (_style & PIC_STYLE_MIRRORED) x = 319 - x;
+}
+
+void SciGUIpicture::vectorGetRelCoords(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y) {
+	byte byte = data[curPos++];
+	if (byte & 0x80) {
+		x = oldx - ((byte >> 4) & 7) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
+	} else {
+		x = oldx + (byte >> 4) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
+	}
+	if (byte & 0x08) {
+		y = oldy - (byte & 7);
+	} else {
+		y = oldy + (byte & 7);
+	}
+}
+
+void SciGUIpicture::vectorGetRelCoordsMed(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y) {
+	byte byte = data[curPos++];
+	if (byte & 0x80) {
+		y = oldy - (byte & 0x7F);
+	} else {
+		y = oldy + byte;
+	}
+	byte = data[curPos++];
+	if (byte & 0x80) {
+		x = oldx - (128 - (byte & 0x7F)) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
+	} else {
+		x = oldx + byte * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
+	}
+}
+
+void SciGUIpicture::vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture) {
+	if (pattern_Code & SCI_PATTERN_CODE_USE_TEXTURE) {
+		pattern_Texture = (data[curPos++] >> 1) & 0x7f;
+	}
+}
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_picture.h b/engines/sci/gui/gui_picture.h
new file mode 100644
index 0000000..815172e
--- /dev/null
+++ b/engines/sci/gui/gui_picture.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+#define SCI_PAL_FORMAT_VARIABLE_FLAGS 0
+#define SCI_PAL_FORMAT_CONSTANT_FLAGS 1
+
+#define PIC_STYLE_MIRRORED 0x4000
+
+class SciGUIpicture {
+public:
+	SciGUIpicture(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId);
+	~SciGUIpicture();
+
+	sciResourceId getResourceId();
+	void draw(uint16 style, bool addToFlag, int16 EGApaletteNo);
+
+private:
+	void initData(sciResourceId resourceId);
+	void reset();
+	void draw11();
+	void decodeRLE(byte *rledata, byte *pixeldata, byte *outbuffer, int size);
+	void drawPalette11(byte *data);
+	void drawCel(int16 x, int16 y, byte *pdata, int size);
+	void drawCelAmiga(int16 x, int16 y, byte *pdata, int size);
+	void drawVectorData(byte *data, int size);
+	bool vectorIsNonOpcode(byte byte);
+	void vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y);
+	void vectorGetRelCoords(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y);
+	void vectorGetRelCoordsMed(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y);
+	void vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture);
+
+	OSystem *_system;
+	EngineState *_s;
+	SciGUIgfx *_gfx;
+	SciGUIscreen *_screen;
+
+	int16 _resourceId;
+	Resource *_resource;
+
+	sciPort *_curPort;
+	uint16 _style;
+	bool _addToFlag;
+	int16 _EGApaletteNo;
+	byte _priority;
+};
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_screen.cpp b/engines/sci/gui/gui_screen.cpp
new file mode 100644
index 0000000..9f4a9e6
--- /dev/null
+++ b/engines/sci/gui/gui_screen.cpp
@@ -0,0 +1,209 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/timer.h"
+#include "common/util.h"
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_screen.h"
+
+namespace Sci {
+
+SciGUIscreen::SciGUIscreen(OSystem *system, EngineState *state)
+	: _system(system), _s(state) {
+	init();
+}
+
+SciGUIscreen::~SciGUIscreen() {
+}
+
+void SciGUIscreen::init() {
+	int i;
+	uint16 base = 0;
+
+	_width  = 320;
+	_height = 200;
+	_pixels = _width * _height;
+
+	// if you want to do scaling, adjust Put_Pixel() accordingly
+	_displayWidth = 320;
+	_displayHeight = 200;
+	_displayPixels = _displayWidth * _displayHeight;
+	_bytesPerDisplayPixel = 1;
+
+	_visualScreen = initScreen(_pixels);
+	_priorityScreen = initScreen(_pixels);
+	_controlScreen = initScreen(_pixels);
+	_displayScreen = initScreen(_displayPixels);
+
+	for (i = 0; i < _height; i++) {
+		_baseTable[i] = base; _baseDisplayTable[i] = base;
+		base += _width;
+	}
+}
+
+byte *SciGUIscreen::initScreen(uint16 pixelCount) {
+	byte *screen = (byte *)malloc(pixelCount);
+	memset(screen, 0, pixelCount);
+	return screen;
+}
+
+void SciGUIscreen::UpdateWhole() {
+	_system->copyRectToScreen(_displayScreen, _displayWidth, 0, 0, _displayWidth, _displayHeight);
+	_system->updateScreen();
+}
+
+byte SciGUIscreen::GetDrawingMask(byte color, byte prio, byte control) {
+	byte flag = 0;
+	if (color != 255)
+		flag |= SCI_SCREEN_MASK_VISUAL;
+	if (prio != 255)
+		flag |= SCI_SCREEN_MASK_PRIORITY;
+	if (control != 255)
+		flag |= SCI_SCREEN_MASK_CONTROL;
+	return flag;
+}
+
+void SciGUIscreen::Put_Pixel(int x, int y, byte drawMask, byte color, byte priority, byte control) {
+	int offset = _baseTable[y] + x;
+
+	if (drawMask & SCI_SCREEN_MASK_VISUAL) {
+		if (!_s->resMan->isVGA()) {
+			// EGA output (16 colors, dithered)
+			color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
+		}
+		*(_visualScreen + offset) = color;
+		_displayScreen[_baseDisplayTable[y] + x] = color;
+	}
+	if (drawMask & SCI_SCREEN_MASK_PRIORITY)
+		*(_priorityScreen + offset) = priority;
+	if (drawMask & SCI_SCREEN_MASK_CONTROL)
+		*(_controlScreen + offset) = control;
+}
+
+byte SciGUIscreen::Get_Visual(int x, int y) {
+	return _visualScreen[_baseTable[y] + x];
+}
+
+byte SciGUIscreen::Get_Priority(int x, int y) {
+	return _priorityScreen[_baseTable[y] + x];
+}
+
+byte SciGUIscreen::Get_Control(int x, int y) {
+	return _controlScreen[_baseTable[y] + x];
+}
+
+byte SciGUIscreen::IsFillMatch(int16 x, int16 y, byte flag, byte t_color, byte t_pri, byte t_con) {
+	int offset = _baseTable[y] + x;
+	byte match = 0;
+
+	if (flag & SCI_SCREEN_MASK_VISUAL && *(_visualScreen + offset) == t_color)
+		match |= SCI_SCREEN_MASK_VISUAL;
+	if (flag & SCI_SCREEN_MASK_PRIORITY && *(_priorityScreen + offset) == t_pri)
+		match |= SCI_SCREEN_MASK_PRIORITY;
+	if (flag & SCI_SCREEN_MASK_CONTROL && *(_controlScreen + offset) == t_con)
+		match |= SCI_SCREEN_MASK_CONTROL;
+	return match;
+}
+
+int SciGUIscreen::BitsGetDataSize(Common::Rect rect, byte mask) {
+	int byteCount = sizeof(rect) + sizeof(mask);
+	int pixels = rect.width() * rect.height();
+	if (mask & SCI_SCREEN_MASK_VISUAL) {
+		byteCount += pixels + (pixels * _bytesPerDisplayPixel);
+	}
+	if (mask & SCI_SCREEN_MASK_PRIORITY) {
+		byteCount += pixels;
+	}
+	if (mask & SCI_SCREEN_MASK_CONTROL) {
+		byteCount += pixels;
+	}
+	return byteCount;
+}
+
+void SciGUIscreen::BitsSave(Common::Rect rect, byte mask, byte *memoryPtr) {
+	memcpy(memoryPtr, (void *)&rect, sizeof(rect)); memoryPtr += sizeof(rect);
+	memcpy(memoryPtr, (void *)&mask, sizeof(mask)); memoryPtr += sizeof(mask);
+
+	if (mask & SCI_SCREEN_MASK_VISUAL) {
+		BitsSaveScreen(rect, _visualScreen, memoryPtr);
+		BitsSaveScreen(rect, _displayScreen, memoryPtr);
+	}
+	if (mask & SCI_SCREEN_MASK_PRIORITY) {
+		BitsSaveScreen(rect, _priorityScreen, memoryPtr);
+	}
+	if (mask & SCI_SCREEN_MASK_CONTROL) {
+		BitsSaveScreen(rect, _controlScreen, memoryPtr);
+	}
+}
+
+void SciGUIscreen::BitsSaveScreen(Common::Rect rect, byte *screen, byte *&memoryPtr) {
+	int width = rect.width();
+	int height = rect.height();
+	int y;
+
+	screen += (rect.top * _width) + rect.left;
+
+	for (y=rect.top; y<rect.bottom; y++) {
+		memcpy(memoryPtr, (void*)screen, width); memoryPtr += width;
+		screen += _width;
+	}
+}
+
+void SciGUIscreen::BitsRestore(byte *memoryPtr) {
+	Common::Rect rect;
+	byte mask;
+
+	memcpy((void *)&rect, memoryPtr, sizeof(rect)); memoryPtr += sizeof(rect);
+	memcpy((void *)&mask, memoryPtr, sizeof(mask)); memoryPtr += sizeof(mask);
+
+	if (mask & SCI_SCREEN_MASK_VISUAL) {
+		BitsRestoreScreen(rect, memoryPtr, _visualScreen);
+		BitsRestoreScreen(rect, memoryPtr, _displayScreen);
+	}
+	if (mask & SCI_SCREEN_MASK_PRIORITY) {
+		BitsRestoreScreen(rect, memoryPtr, _priorityScreen);
+	}
+	if (mask & SCI_SCREEN_MASK_CONTROL) {
+		BitsRestoreScreen(rect, memoryPtr, _controlScreen);
+	}
+}
+
+void SciGUIscreen::BitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *screen) {
+	int width = rect.width();
+	int height = rect.height();
+	int y;
+
+	screen += (rect.top * _width) + rect.left;
+
+	for (y=rect.top; y<rect.bottom; y++) {
+		memcpy((void*) screen, memoryPtr, width); memoryPtr += width;
+		screen += _width;
+	}
+}
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_screen.h b/engines/sci/gui/gui_screen.h
new file mode 100644
index 0000000..242948e
--- /dev/null
+++ b/engines/sci/gui/gui_screen.h
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+#define SCI_SCREEN_MAXHEIGHT 400
+
+#define SCI_SCREEN_MASK_VISUAL   1
+#define SCI_SCREEN_MASK_PRIORITY 2
+#define SCI_SCREEN_MASK_CONTROL  4
+#define SCI_SCREEN_MASK_ALL      SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY|SCI_SCREEN_MASK_CONTROL
+#define SCI_SCREEN_MASK_DITHERED 128
+
+class SciGUIscreen {
+public:
+	SciGUIscreen(OSystem *system, EngineState *state);
+	~SciGUIscreen();
+
+	void init(void);
+	byte *initScreen(uint16 pixelCount);
+
+	void UpdateWhole();
+
+	byte GetDrawingMask(byte color, byte prio, byte control);
+	void Put_Pixel(int x, int y, byte drawMask, byte color, byte prio, byte control);
+	byte Get_Visual(int x, int y);
+	byte Get_Priority(int x, int y);
+	byte Get_Control(int x, int y);
+	byte IsFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con);
+
+	int BitsGetDataSize(Common::Rect rect, byte mask);
+	void BitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
+	void BitsRestore(byte *memoryPtr);
+
+	sciPalette _sysPalette;
+
+	uint16 _width;
+	uint16 _height;
+	uint _pixels;
+	uint16 _displayWidth;
+	uint16 _displayHeight;
+	uint _displayPixels;
+	byte _bytesPerDisplayPixel;
+
+private:
+	void BitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *screen);
+	void BitsSaveScreen(Common::Rect rect, byte *screen, byte *&memoryPtr);
+
+	OSystem *_system;
+	EngineState *_s;
+
+	uint16 _baseTable[SCI_SCREEN_MAXHEIGHT];
+	uint16 _baseDisplayTable[SCI_SCREEN_MAXHEIGHT];
+
+	// these screens have the real resolution of the game engine (320x200 for SCI0/SCI1/SCI11 games, 640x480 for SCI2 games)
+	//  SCI0 games will be dithered in here at any time
+	byte *_visualScreen;
+	byte *_priorityScreen;
+	byte *_controlScreen;
+
+	// this screen is the one that is actually displayed to the user. It may be 640x480 for japanese SCI1 games
+	//  SCI0 games may be undithered in here. Only read from this buffer for Save/ShowBits usage.
+	byte *_displayScreen;
+};
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_view.cpp b/engines/sci/gui/gui_view.cpp
new file mode 100644
index 0000000..0dacfb3
--- /dev/null
+++ b/engines/sci/gui/gui_view.cpp
@@ -0,0 +1,296 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_gfx.h"
+#include "sci/gui/gui_screen.h"
+#include "sci/gui/gui_view.h"
+
+namespace Sci {
+
+SciGUIview::SciGUIview(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId)
+	: _system(system), _s(state), _gfx(gfx), _screen(screen), _resourceId(resourceId) {
+	assert(resourceId != -1);
+	initData(resourceId);
+}
+
+SciGUIview::~SciGUIview() {
+}
+
+void SciGUIview::initData(sciResourceId resourceId) {
+	Resource *viewResource = _s->resMan->findResource(ResourceId(kResourceTypeView, resourceId), false);
+	if (!viewResource) {
+		error("view resource %d not found", resourceId);
+	}
+	_resourceData = viewResource->data;
+
+	byte *cellData, *loopData;
+	uint16 cellOffset;
+	sciViewCellInfo *cell;
+	uint16 cellCount = 0;
+	uint16 mirrorBits = 0;
+	uint16 palOffset = 0;
+	uint16 headerSize = 0;
+	uint16 loopSize = 0, cellSize = 0;
+	int loopNo, cellNo;
+	int16 version;
+	byte seekEntry;
+
+	_embeddedPal = false;
+	_loopCount = 0;
+
+	version = READ_LE_UINT16(_resourceData + 4);
+	switch (version) {
+		case 0: // View-format SCI1
+		// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
+		
+		// bit 0x8000 of _resourceData[1] means palette is set
+		_loopCount = _resourceData[0];
+		mirrorBits = READ_LE_UINT16(_resourceData + 2);
+		palOffset = READ_LE_UINT16(_resourceData + 6);
+
+		if (palOffset && palOffset != 0x100) {
+			_gfx->CreatePaletteFromData(_resourceData + palOffset, &_palette);
+			_embeddedPal = true;
+		}
+
+		_loop = new sciViewLoopInfo[_loopCount];
+		for (loopNo = 0; loopNo < _loopCount; loopNo++) {
+			loopData = _resourceData + READ_LE_UINT16(_resourceData + 8 + loopNo * 2);
+			// CellCount:WORD Unknown:WORD CellOffset0:WORD CellOffset1:WORD...
+
+			cellCount = READ_LE_UINT16(loopData);
+			_loop[loopNo].cellCount = cellCount;
+			_loop[loopNo].mirrorFlag = mirrorBits & 1 ? true : false;
+			mirrorBits >>= 1;
+
+			// read cel info
+			_loop[loopNo].cell = new sciViewCellInfo[cellCount];
+			for (cellNo = 0; cellNo < cellCount; cellNo++) {
+				cellOffset = READ_LE_UINT16(loopData + 4 + cellNo * 2);
+				cellData = _resourceData + cellOffset;
+
+				cell = &_loop[loopNo].cell[cellNo];
+				cell->width = READ_LE_UINT16(cellData);
+				cell->height = READ_LE_UINT16(cellData + 2);
+				cell->displaceX = cellData[4];
+				cell->displaceY = cellData[5];
+				cell->clearKey = cellData[6];
+				cell->offsetRLE = cellOffset + 8;
+				cell->offsetLiteral = 0;
+				cell->rawBitmap = 0;
+				if (_loop[loopNo].mirrorFlag)
+					cell->displaceX = -cell->displaceX;
+			}
+		}
+		break;
+
+		case 1: // View-format SCI1.1
+		// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
+		// HeaderSize:WORD LoopCount:WORD Version:WORD Unknown:WORD PaletteOffset:WORD
+		headerSize = READ_LE_UINT16(_resourceData + 0);
+		_loopCount = READ_LE_UINT16(_resourceData + 2);
+		palOffset = READ_LE_UINT16(_resourceData + 8);
+
+		loopData = _resourceData + headerSize;
+		loopSize = _resourceData[12];
+		cellSize = _resourceData[13];
+
+		if (palOffset) {
+			_gfx->CreatePaletteFromData(_resourceData + palOffset, &_palette);
+			_embeddedPal = true;
+		}
+
+		_loop = new sciViewLoopInfo[_loopCount];
+		for (loopNo = 0; loopNo < _loopCount; loopNo++) {
+			loopData = _resourceData + headerSize + (loopNo * loopSize);
+			
+			seekEntry = loopData[2];
+			if (seekEntry != 255) {
+				loopData = _resourceData + headerSize + (seekEntry * loopNo);
+			}
+
+			cellCount = loopData[4];
+			_loop[loopNo].cellCount = cellCount;
+			_loop[loopNo].mirrorFlag = false;
+
+			cellData = _resourceData + READ_LE_UINT16(loopData + 14);
+
+			// read cel info
+			_loop[loopNo].cell = new sciViewCellInfo[cellCount];
+			for (cellNo = 0; cellNo < cellCount; cellNo++) {
+				cell = &_loop[loopNo].cell[cellNo];
+				cell->width = READ_LE_UINT16(cellData);
+				cell->height = READ_LE_UINT16(cellData + 2);
+				cell->displaceX = READ_LE_UINT16(cellData + 4);
+				cell->displaceY = READ_LE_UINT16(cellData + 6);
+				cell->clearKey = cellData[8];
+				cell->offsetRLE = READ_LE_UINT16(cellData + 24);
+				cell->offsetLiteral = READ_LE_UINT16(cellData + 28);
+				cell->rawBitmap = 0;
+				if (_loop[loopNo].mirrorFlag)
+					cell->displaceX = -cell->displaceX;
+
+				cellData += cellSize;
+			}
+		}
+		break;
+	}
+}
+
+sciResourceId SciGUIview::getResourceId() {
+	return _resourceId;
+}
+
+int16 SciGUIview::getWidth(uint16 loopNo, uint16 cellNo) {
+	loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
+	if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
+		cellNo = 0;
+	return _loopCount ? _loop[loopNo].cell[cellNo].width : 0;
+}
+
+int16 SciGUIview::getHeight(uint16 loopNo, uint16 cellNo) {
+	loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
+	if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
+		cellNo = 0;
+	return _loopCount ? _loop[loopNo].cell[cellNo].height : 0;
+}
+
+sciViewCellInfo *SciGUIview::getCellInfo(uint16 loopNo, uint16 cellNo) {
+	loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
+	if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
+		cellNo = 0;
+	return _loopCount ? &_loop[loopNo].cell[cellNo] : NULL;
+}
+
+void SciGUIview::unpackView(uint16 loopNo, uint16 cellNo, byte *outPtr, uint16 pixelCount) {
+	byte *rlePtr = _resourceData + _loop[loopNo].cell[cellNo].offsetRLE;
+	byte *literalPtr = _resourceData + _loop[loopNo].cell[cellNo].offsetLiteral;
+	uint16 pixelNo = 0, brun;
+	byte b;
+
+	if (literalPtr == _resourceData) { // no extra literal data
+		while (pixelNo < pixelCount) {
+			b = *rlePtr++;
+			brun = b & 0x3F; // bytes run length on this step
+			switch (b & 0xC0) {
+			case 0: // copy bytes as-is
+				while (brun-- && pixelNo < pixelCount)
+					outPtr[pixelNo++] = *rlePtr++;
+				break;
+			case 0x80: // fill with color
+				memset(outPtr + pixelNo, *rlePtr++, MIN<uint16>(brun, pixelCount - pixelNo));
+				pixelNo += brun;
+				break;
+			case 0xC0: // fill with transparent
+				pixelNo += brun;
+				break;
+			}
+		}
+	} else {
+		while (pixelNo < pixelCount) {
+			b = *rlePtr++;
+			brun = b & 0x3F; // bytes run length on this step
+			switch (b & 0xC0) {
+			case 0: // copy bytes as-is
+				while (brun-- && pixelNo < pixelCount)
+					outPtr[pixelNo++] = *literalPtr++;
+				break;
+			case 0x80: // fill with color
+				memset(outPtr + pixelNo, *literalPtr++, MIN<uint16>(brun, pixelCount - pixelNo));
+				pixelNo += brun;
+				break;
+			case 0xC0: // fill with transparent
+				pixelNo += brun;
+				break;
+			}
+		}
+	}
+}
+
+byte *SciGUIview::getBitmap(uint16 loopNo, uint16 cellNo) {
+	loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
+	if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
+		cellNo = 0;
+	if (_loop[loopNo].cell[cellNo].rawBitmap)
+		return _loop[loopNo].cell[cellNo].rawBitmap;
+
+	uint16 width = _loop[loopNo].cell[cellNo].width;
+	uint16 height = _loop[loopNo].cell[cellNo].height;
+//	byte *ptr = _resourceData + _loop[loopNo].cell[cellNo].offset;
+	// allocating memory to store cel's bitmap
+	assert(width * height <= 64000);
+	uint16 pixelCount = width * height;
+	_loop[loopNo].cell[cellNo].rawBitmap = new byte[pixelCount];
+	byte *pOut = _loop[loopNo].cell[cellNo].rawBitmap;
+
+	memset(pOut, _loop[loopNo].cell[cellNo].clearKey, pixelCount);
+	//if (g_sci->getPlatform() == Common::kPlatformAmiga)
+	//	unpackViewAmiga(ptr, pOut, pixelCount);
+	//else
+		unpackView(loopNo, cellNo, pOut, pixelCount);
+
+	// mirroring the view if needed
+	if (_loop[loopNo].mirrorFlag) {
+		for (int i = 0; i < height; i++, pOut += width)
+			for (int j = 0; j < width / 2; j++)
+				SWAP(pOut[j], pOut[width - j - 1]);
+	}
+	return _loop[loopNo].cell[cellNo].rawBitmap;
+}
+
+void SciGUIview::draw(Common::Rect rect, Common::Rect clipRect, uint16 loopNo, uint16 cellNo, byte priority, uint16 paletteNo) {
+	sciPalette *palette = _embeddedPal ? &_palette : &_gfx->_sysPalette;
+	sciViewCellInfo *cellInfo = getCellInfo(loopNo, cellNo);
+	byte *bitmap = getBitmap(loopNo, cellNo);
+	int16 cellHeight = cellInfo->height, cellWidth = cellInfo->width;
+	int16 width, height;
+	byte clearKey = cellInfo->clearKey;
+	byte color;
+	byte drawMask = priority == 255 ? SCI_SCREEN_MASK_VISUAL : SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY;
+	int x, y;
+
+	// Merge view palette in...
+	if (_embeddedPal)
+		_gfx->SetPalette(&_palette, 1);
+
+	width = MIN(clipRect.width(), cellWidth);
+	height = MIN(clipRect.height(), cellHeight);
+
+	bitmap += (clipRect.top - rect.top) * cellWidth + (clipRect.left - rect.left);
+	_gfx->OffsetRect(clipRect);
+
+	for (y = clipRect.top; y < clipRect.top + height; y++, bitmap += cellWidth) {
+		for (x = 0; x < width; x++) {
+			color = bitmap[x];
+			if (color != clearKey && priority >= _screen->Get_Priority(clipRect.left + x, y))
+				_screen->Put_Pixel(clipRect.left + x, y, drawMask, palette->mapping[color], priority, 0);
+		}
+	}
+}
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_view.h b/engines/sci/gui/gui_view.h
new file mode 100644
index 0000000..62ac4a7
--- /dev/null
+++ b/engines/sci/gui/gui_view.h
@@ -0,0 +1,77 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+struct sciViewCellInfo {
+	int16 width, height;
+	char displaceX;
+	byte displaceY;
+	byte clearKey;
+	uint16 offsetRLE;
+	uint16 offsetLiteral;
+	byte *rawBitmap;
+};
+
+struct sciViewLoopInfo {
+	bool mirrorFlag;
+	int16 cellCount;
+	sciViewCellInfo *cell;
+};
+
+class SciGUIview {
+public:
+	SciGUIview(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId);
+	~SciGUIview();
+
+	// TODO: Remove gfx reference after putting palette things into SciGUIscreen
+
+	sciResourceId getResourceId();
+	int16 getWidth(uint16 loopNo, uint16 cellNo);
+	int16 getHeight(uint16 loopNo, uint16 cellNo);
+	sciViewCellInfo *getCellInfo(uint16 loop, uint16 cel);
+	sciViewLoopInfo *getLoopInfo(uint16 loop);
+	byte *getBitmap(uint16 loopNo, uint16 cellNo);
+	void draw(Common::Rect rect, Common::Rect clipRect, uint16 loopNo, uint16 cellNo, byte priority, uint16 paletteNo);
+
+private:
+	void initData(sciResourceId resourceId);
+	void unpackView(uint16 loopNo, uint16 cellNo, byte *outPtr, uint16 pixelCount);
+
+	OSystem *_system;
+	EngineState *_s;
+	SciGUIgfx *_gfx;
+	SciGUIscreen *_screen;
+
+	sciResourceId _resourceId;
+	byte *_resourceData;
+
+	uint16 _loopCount;
+	sciViewLoopInfo *_loop;
+	bool _embeddedPal;
+	sciPalette _palette;
+};
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_windowmgr.cpp b/engines/sci/gui/gui_windowmgr.cpp
new file mode 100644
index 0000000..3a474a1
--- /dev/null
+++ b/engines/sci/gui/gui_windowmgr.cpp
@@ -0,0 +1,326 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/gui/gui_gfx.h"
+#include "sci/gui/gui_windowmgr.h"
+#include "sci/gui/gui_memmgr.h"
+
+namespace Sci {
+
+Common::Rect _picRect(0,10,320, 200);
+
+// window styles
+enum {
+	TRANSPARENT = 1,
+	NOFRAME		= 2,
+	TITLE		= 4,
+	TOPMOST		= 8,
+	USER		= 0x80
+};
+
+SciGUIwindowMgr::SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx)
+	: _s(state), _gfx(gfx) {
+
+	// FIXME: remove memmgr
+	InitMem(0x320);
+
+	HEAPHANDLE wmgrPortH = heapNewPtr(sizeof(sciPort), kDataPort, "wmgrPort");
+	heapClearPtr(wmgrPortH);
+	_wmgrPort = (sciPort *)heap2Ptr(wmgrPortH);
+
+	int16 offTop = 20;
+
+	_gfx->OpenPort(_wmgrPort);
+	_gfx->SetPort(_wmgrPort);
+	_gfx->SetOrigin(0, offTop);
+	_wmgrPort->rect.bottom = 200 - offTop;
+	_wmgrPort->rect.right = 320;
+	_wmgrPort->rect.moveTo(0, 0);
+	_wmgrPort->curTop = 0;
+	_wmgrPort->curLeft = 0;
+
+	windowList.AddToFront(wmgrPortH);
+
+	_picWind = NewWindow(&_picRect, 0, 0, TRANSPARENT | NOFRAME, 0, 1);
+}
+
+SciGUIwindowMgr::~SciGUIwindowMgr() {
+}
+
+int16 SciGUIwindowMgr::isFrontWindow(sciWnd *pWnd) {
+	if (heap2Ptr(windowList.getLast()) == (byte *)pWnd)
+		return 1;
+	return 0;
+}
+
+void SciGUIwindowMgr::SelectWindow(HEAPHANDLE hh) {
+	sciPort *port = (sciPort *)heap2Ptr(hh);
+	_gfx->SetPort(port);
+	if (hh != windowList.getLast()) { // selecting not topmost window
+		sciWnd *prevwnd = (sciWnd *)heap2Ptr(port->node.prev);
+		BeginUpdate(prevwnd);
+		windowList.MoveToEnd(hh);
+		EndUpdate(prevwnd);
+	}
+	_gfx->SetPort(port);
+}
+
+void SciGUIwindowMgr::BeginUpdate(sciWnd *wnd) {
+	sciPort *oldPort = _gfx->SetPort(_wmgrPort);
+	sciWnd *node = (sciWnd *)heap2Ptr(windowList.getLast());
+	while (node != wnd) {
+		UpdateWindow(node);
+		node = (sciWnd *)heap2Ptr(node->node.prev);
+	}
+	_gfx->SetPort(oldPort);
+}
+
+void SciGUIwindowMgr::EndUpdate(sciWnd *wnd) {
+	sciPort *oldPort = _gfx->SetPort(_wmgrPort);
+	sciWnd *last = (sciWnd *)heap2Ptr(windowList.getLast());
+	while (wnd != last) {
+		wnd = (sciWnd *)heap2Ptr(wnd->node.next);
+		UpdateWindow(wnd);
+	}
+	_gfx->SetPort(oldPort);
+}
+
+SCILanguage SciGUIwindowMgr::getSCILanguage() {
+	return kLangEnglish;
+}
+
+char *SciGUIwindowMgr::StrSplit(char *buff, const char *msg, const char *fmt) {
+	SCILanguage gameLang = getSCILanguage();
+	SCILanguage subtitleLang = kLangNone;
+	char *retval;
+//	if (_theGame.getHandle())
+		//subtitleLang = (SCILanguage)_theGame.getProperty(0x58); // subtitleLang property
+
+	if (buff == msg) {
+		char str[2000];
+		getIntlString(str, msg, fmt, gameLang, subtitleLang);
+		retval = strcpy(buff, str);
+	} else
+		retval = getIntlString(buff, msg, fmt, gameLang, subtitleLang);
+	return retval;
+}
+//--------------------------------
+// In multilanguage game the msg has format ___english_text__#I___italian_text___
+// The function should place in buff a translated part of msg or the 1st one if a translation
+// does not exist
+char *SciGUIwindowMgr::getIntlString(char *buff, const char *msg, const char *fmt,
+		SCILanguage gameLang, SCILanguage subtitleLang) {
+
+	// prefer subtitleLang if set
+	SCILanguage lang = subtitleLang != kLangNone ? subtitleLang : gameLang;
+	const char *ptr = msg, *szFrom;
+	char ch;
+	int nLen = 0;
+	// searching for language code in msg
+	while (*ptr) {
+		ch = *(ptr + 1);
+		if(*ptr == '#' && (ch == 'I' || ch == 'F' || ch == 'G' || ch == 'S')) {
+			ptr +=2;
+			break;
+		}
+	ptr++;
+	}
+	// if a language code was found...
+	if (*ptr) {
+		if ((lang == kLangItalian && ch == 'I') || (lang == kLangFrench && ch == 'F') ||
+				(lang == kLangGerman && ch == 'G') || (lang == kLangSpanish && ch == 'S')) {
+			nLen = (int)strlen(ptr);
+			szFrom = ptr;
+		} else {
+			nLen = ptr - msg - 2;
+			szFrom = msg;
+		}
+	} else {
+		nLen = ptr - msg;
+		szFrom = msg;
+	}
+	if (fmt && subtitleLang != kLangNone) {
+		strcpy(buff, fmt);
+		strncat(buff, szFrom, nLen);
+		buff[nLen + strlen(fmt)] = 0;
+	} else {
+		strncpy(buff, szFrom, nLen);
+		buff[nLen] = 0;
+	}
+	return buff;
+}
+
+sciWnd *SciGUIwindowMgr::NewWindow(Common::Rect *rect, Common::Rect *rect2, const char *title, uint16 style, uint16 arg8, uint16 argA) {
+	HEAPHANDLE hWnd = heapNewPtr(sizeof(sciWnd), kDataWindow, title);
+	Common::Rect r;
+
+	if (!hWnd) {
+		warning("Can't open window!");
+		return 0;
+	}
+	heapClearPtr(hWnd);
+	if (style & TOPMOST)
+		windowList.AddToFront(hWnd);
+	else
+		windowList.AddToEnd(hWnd);
+	sciWnd *pwnd = (sciWnd *)heap2Ptr(hWnd);
+	_gfx->OpenPort((sciPort *)pwnd);
+	r = *rect;
+	pwnd->rect = *rect;
+	if (rect2)
+		pwnd->rect1 = *rect2;
+	
+	pwnd->wndStyle = style;
+	pwnd->hSaved1 = pwnd->hSaved2 = NULL_REG;
+	pwnd->bDrawed = false;
+	if ((style & TRANSPARENT) == 0)
+		pwnd->uSaveFlag = (arg8 == 0xFFFF ? 1 : 3);
+	
+	if (title && (style & TITLE)) {
+		HEAPHANDLE hTitle = heapNewPtr((uint16)strlen(title) + 1, kDataString, title);
+		if (!hTitle) {
+			warning("Can't open window!");
+			return 0;
+		}
+		pwnd->hTitle = hTitle;
+		StrSplit((char *)heap2Ptr(hTitle), title, NULL);
+	}
+	
+	r = *rect;
+	if (style == USER || (style & NOFRAME) == 0) {
+		r.grow(1);
+		if (style & TITLE) {
+			r.top -= 10;
+			r.bottom++;
+		}
+	}
+	
+	pwnd->rect0 = r;
+	const Common::Rect *wmprect = &_wmgrPort->rect;
+	int16 oldtop = pwnd->rect0.top;
+	int16 oldleft = pwnd->rect0.left;
+	if (wmprect->top > pwnd->rect0.top)
+		pwnd->rect0.moveTo(pwnd->rect0.left, wmprect->top);
+	
+	if (wmprect->bottom < pwnd->rect0.bottom)
+		pwnd->rect0.moveTo(pwnd->rect0.left, wmprect->bottom
+				- pwnd->rect0.bottom + pwnd->rect0.top);
+	
+	if (wmprect->right < pwnd->rect0.right)
+		pwnd->rect0.moveTo(wmprect->right + pwnd->rect0.left
+				- pwnd->rect0.right, pwnd->rect0.top);
+	
+	if (wmprect->left > pwnd->rect0.left)
+		pwnd->rect0.moveTo(wmprect->left, pwnd->rect0.top);
+	
+	pwnd->rect.moveTo(pwnd->rect.left + pwnd->rect0.left - oldleft,
+			pwnd->rect.top + pwnd->rect0.top - oldtop);
+	if (rect2 == 0)
+		pwnd->rect1 = pwnd->rect0;
+	
+	if (argA)
+		DrawWindow(pwnd);
+	_gfx->SetPort((sciPort *)pwnd);
+	_gfx->SetOrigin(pwnd->rect.left, pwnd->rect.top + _wmgrPort->top);
+	pwnd->rect.moveTo(0, 0);
+	return pwnd;
+}
+
+void SciGUIwindowMgr::DrawWindow(sciWnd *pWnd) {
+	if (pWnd->bDrawed)
+		return;
+	Common::Rect r;
+	int16 wndStyle = pWnd->wndStyle;
+
+	pWnd->bDrawed = true;
+	sciPort *oldport = _gfx->SetPort(_wmgrPort);
+	_gfx->PenColor(0);
+	if ((wndStyle & TRANSPARENT) == 0) {
+		pWnd->hSaved1 = _gfx->SaveBits(pWnd->rect1, 1);
+		if (pWnd->uSaveFlag & 2) {
+			pWnd->hSaved2 = _gfx->SaveBits(pWnd->rect1, 2);
+			if ((wndStyle & USER) == 0)
+				_gfx->FillRect(pWnd->rect1, 2, 0, 0xF);
+		}
+	}
+	
+	// drawing frame,shadow and title
+	if ((wndStyle & USER) == 0) {
+		r = pWnd->rect0;
+		if ((wndStyle & NOFRAME) == 0) {
+			r.translate(1, 1);
+			_gfx->FrameRect(r);// shadow
+			r.translate(-1, -1);
+			_gfx->FrameRect(r);// window frame
+			if (wndStyle & TITLE) {
+				_gfx->FrameRect(r);
+				r.grow(-1);
+				_gfx->FillRect(r, 1, 0);
+				if (pWnd->hTitle) {
+					int16 oldcolor = _gfx->GetPort()->penClr;
+					_gfx->PenColor(255);
+					_gfx->TextBox((char *)heap2Ptr(pWnd->hTitle), 1, r, 1, 0);
+					_gfx->PenColor(oldcolor);
+				}
+				
+				r = pWnd->rect0;
+				r.top += 9;
+			}
+			
+			r.grow(-1);
+		}
+		
+		if ((wndStyle & TRANSPARENT) == 0)
+			_gfx->FillRect(r, 1, pWnd->backClr);
+		_gfx->ShowBits(pWnd->rect0, 1);
+	}
+	_gfx->SetPort(oldport);
+}
+
+void SciGUIwindowMgr::DisposeWindow(sciWnd *pWnd, int16 arg2) {
+	_gfx->SetPort(_wmgrPort);
+	_gfx->RestoreBits(pWnd->hSaved1);
+	_gfx->RestoreBits(pWnd->hSaved2);
+	if (arg2)
+		_gfx->ShowBits(pWnd->rect0, 1);
+//	else
+//		g_sci->ReAnimate(&pwnd->rect0);
+	HEAPHANDLE hh = ptr2heap((byte *)pWnd);
+	windowList.DeleteNode(hh);
+	SelectWindow(windowList.getLast());
+	if (pWnd->hTitle)
+		heapDisposePtr(pWnd->hTitle);
+	heapDisposePtr(hh);
+}
+
+void SciGUIwindowMgr::UpdateWindow(sciWnd *wnd) {
+}
+
+} // end of namespace Sci
diff --git a/engines/sci/gui/gui_windowmgr.h b/engines/sci/gui/gui_windowmgr.h
new file mode 100644
index 0000000..bc7ea47
--- /dev/null
+++ b/engines/sci/gui/gui_windowmgr.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/gui/gui_dbllist.h"
+
+namespace Sci {
+
+class SciGUIwindowMgr {
+public:
+	SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx);
+	~SciGUIwindowMgr();
+
+	int16 isFrontWindow(sciWnd *wnd);
+	void SelectWindow(HEAPHANDLE hh);
+	void BeginUpdate(sciWnd *wnd);
+	void EndUpdate(sciWnd *wnd);
+	SCILanguage getSCILanguage();
+	char* StrSplit(char*buff, const char*msg, const char*fmt);
+	char* getIntlString(char*buff, const char*msg, const char*fmt, SCILanguage lang, SCILanguage prop);
+	sciWnd *NewWindow(Common::Rect *rect, Common::Rect *rect2, const char *title, uint16 style, uint16 arg8, uint16 argA);
+	void DrawWindow(sciWnd *wnd);
+	void DisposeWindow(sciWnd *pWnd, int16 arg2);
+	void UpdateWindow(sciWnd *wnd);
+
+	sciPort *_wmgrPort;
+	sciWnd *_picWind;
+
+private:
+	EngineState *_s;
+	SciGUIgfx *_gfx;
+
+	DblList windowList;
+};
+
+} // end of namespace Sci
diff --git a/engines/sci/gui32/gui32.cpp b/engines/sci/gui32/gui32.cpp
new file mode 100644
index 0000000..0f504e8
--- /dev/null
+++ b/engines/sci/gui32/gui32.cpp
@@ -0,0 +1,734 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+#include "sci/tools.h"
+#include "sci/debug.h"	// for g_debug_sleeptime_factor
+#include "sci/resource.h"
+#include "sci/engine/state.h"
+#include "sci/engine/kernel.h"
+#include "sci/gfx/gfx_gui.h"
+#include "sci/gfx/gfx_widgets.h"
+#include "sci/gfx/gfx_state_internal.h"	// required for GfxContainer, GfxPort, GfxVisual
+#include "sci/gui32/gui32.h"
+
+// This is the real width of a text with a specified width of 0
+#define MAX_TEXT_WIDTH_MAGIC_VALUE 192
+
+#define ADD_TO_CURRENT_PORT(widget) \
+	{if (s->port)				   \
+		s->port->add((GfxContainer *)s->port, widget); \
+	else \
+		s->picture_port->add((GfxContainer *)s->visual, widget);}
+
+#define ADD_TO_CURRENT_PICTURE_PORT(widget) \
+	{if (s->port)				   \
+		s->port->add((GfxContainer *)s->port, widget); \
+	else \
+		s->picture_port->add((GfxContainer *)s->picture_port, widget);}
+
+#define ADD_TO_WINDOW_PORT(widget) \
+	s->wm_port->add((GfxContainer *)s->wm_port, widget);
+
+#define FULL_REDRAW()\
+	if (s->visual) \
+		s->visual->draw(gfxw_point_zero); \
+	gfxop_update(s->gfx_state);
+
+#define K_DRAWPIC_FLAG_MIRRORED (1 << 14)
+
+namespace Sci {
+
+SciGUI32::SciGUI32(OSystem *system, EngineState *state)
+	: _system(system), s(state) {
+}
+
+SciGUI32::~SciGUI32() {
+}
+
+void SciGUI32::init(bool oldGfxFunctions) {
+	_usesOldGfxFunctions = oldGfxFunctions;
+	activated_icon_bar = false;
+	port_origin_x = 0;
+	port_origin_y = 0;
+}
+
+int16 SciGUI32::getTimeTicks() {
+	uint32 start_time;
+	start_time = _system->getMillis() - s->game_start_time;
+	return start_time * 60 / 1000;
+}
+
+void SciGUI32::wait(int16 ticks) {
+	uint32 time;
+
+	time = g_system->getMillis();
+	s->r_acc = make_reg(0, ((long)time - (long)s->last_wait_time) * 60 / 1000);
+	s->last_wait_time = time;
+
+	ticks *= g_debug_sleeptime_factor;
+	gfxop_sleep(s->gfx_state, ticks * 1000 / 60);
+
+
+	// Reset speed throttler: Game is playing along nicely anyway
+	if (ticks > 0)
+		s->speedThrottler->reset();
+}
+
+void SciGUI32::setPort(uint16 portPtr) {
+	GfxPort *new_port;
+
+	/* We depart from official semantics here, sorry!
+	   Reasoning: Sierra SCI does not clip ports while we do.
+	   Therefore a draw to the titlebar port (which is the
+	   official semantics) would cut off the lower part of the
+	   icons in an SCI1 icon bar. Instead we have an
+	   iconbar_port that does not exist in SSCI. */
+	if (portPtr == 65535) portPtr = s->iconbar_port->_ID;
+
+	new_port = s->visual->getPort(portPtr);
+
+	if (!new_port) {
+		warning("Invalid port %04x requested", portPtr);
+		return;
+	}
+
+	s->port->draw(gfxw_point_zero); // Update the port we're leaving
+	s->port = new_port;
+}
+
+void SciGUI32::setPortPic(Common::Rect rect, int16 picTop, int16 picLeft) {
+	if (activated_icon_bar) {
+		port_origin_x = port_origin_y = 0;
+		activated_icon_bar = false;
+		return;
+	}
+	port_origin_y = rect.top;
+	port_origin_x = rect.left;
+
+	if (rect.top == -10) {
+		s->port->draw(gfxw_point_zero); // Update the port we're leaving
+		s->port = s->iconbar_port;
+		activated_icon_bar = true;
+		return;
+	}
+
+	// Notify the graphics resource manager that the pic port bounds changed
+	s->gfx_state->gfxResMan->changePortBounds(picLeft, picTop, rect.right + picLeft, rect.bottom + picTop);
+
+	// LSL6 calls kSetPort to extend the screen to draw the GUI. If we free all resources
+	// here, the background picture is freed too, and this makes everything a big mess.
+	// FIXME/TODO: This code really needs to be rewritten to conform to the original behavior
+	if (s->_gameName != "lsl6") {
+		s->gfx_state->pic_port_bounds = gfx_rect(picLeft, picTop, rect.right, rect.bottom);
+
+		// FIXME: Should really only invalidate all loaded pic resources here;
+		// this is overkill
+		s->gfx_state->gfxResMan->freeAllResources();
+	} else {
+		// WORKAROUND for LSL6
+		warning("SetPort case 6 called in LSL6.");
+	}
+}
+
+reg_t SciGUI32::getPort() {
+	return make_reg(0, s->port->_ID);
+}
+
+void SciGUI32::globalToLocal(int16 *x, int16 *y) {
+	*x = *x - s->port->zone.x;
+	*y = *y - s->port->zone.y;
+}
+
+void SciGUI32::localToGlobal(int16 *x, int16 *y) {
+	*x = *x + s->port->zone.x;
+	*y = *y + s->port->zone.y;
+}
+
+reg_t SciGUI32::newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack) {
+	GfxPort *window;
+	int x, y, xl, yl;
+	gfx_color_t bgcolor;
+	gfx_color_t fgcolor;
+	gfx_color_t black;
+	gfx_color_t lWhite;
+
+	y = rect1.top;
+	x = rect1.left;
+	yl = rect1.height();
+	xl = rect1.width();
+
+	y += s->wm_port->_bounds.y;
+
+	if (x + xl > 319)
+		x -= ((x + xl) - 319);
+
+	bgcolor.mask = 0;
+
+	if (colorBack >= 0) {
+		if (!s->resMan->isVGA())
+			bgcolor.visual = get_pic_color(s, MIN<int>(colorBack, 15));
+		else
+			bgcolor.visual = get_pic_color(s, colorBack);
+		bgcolor.mask = GFX_MASK_VISUAL;
+	} else {
+		bgcolor.visual = PaletteEntry(0,0,0);
+	}
+
+	bgcolor.priority = priority;
+	bgcolor.mask |= priority >= 0 ? GFX_MASK_PRIORITY : 0;
+	bgcolor.alpha = 0;
+	bgcolor.control = -1;
+	debugC(2, kDebugLevelGraphics, "New window with params %d, %d, %d, %d\n", rect1.top, rect1.left, rect1.height(), rect1.width());
+
+	fgcolor.visual = get_pic_color(s, colorPen);
+	fgcolor.mask = GFX_MASK_VISUAL;
+	fgcolor.control = -1;
+	fgcolor.priority = -1;
+	fgcolor.alpha = 0;
+	black.visual = get_pic_color(s, 0);
+	black.mask = GFX_MASK_VISUAL;
+	black.alpha = 0;
+	black.control = -1;
+	black.priority = -1;
+	lWhite.visual = get_pic_color(s, !s->resMan->isVGA() ? 15 : 255);
+	lWhite.mask = GFX_MASK_VISUAL;
+	lWhite.alpha = 0;
+	lWhite.priority = -1;
+	lWhite.control = -1;
+//	const char *title = argv[4 + argextra].segment ? kernel_dereference_char_pointer(s, argv[4 + argextra], 0) : NULL;
+	const char *title = NULL;
+
+	window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
+							s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, style);
+
+	// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
+	if (rect2.top != 0 && rect2.left != 0 && rect2.height() != 0 && rect2.width() != 0)
+		gfxw_port_auto_restore_background(s->visual, window, gfx_rect(rect2.left, rect2.top + s->wm_port->_bounds.y, rect2.width(), rect2.height()));
+
+	ADD_TO_WINDOW_PORT(window);
+	FULL_REDRAW();
+
+	window->draw(gfxw_point_zero);
+	gfxop_update(s->gfx_state);
+
+	s->port = window; // Set active port
+
+	return make_reg(0, window->_ID);
+}
+
+void SciGUI32::disposeWindow(uint16 windowPtr, int16 arg2) {
+	GfxPort *goner;
+	GfxPort *pred;
+
+	goner = s->visual->getPort(windowPtr);
+	if ((windowPtr < 3) || (goner == NULL)) {
+		error("Removal of invalid window %04x requested", windowPtr);
+		return;
+	}
+
+	if (s->dyn_views && (GfxContainer *)s->dyn_views->_parent == (GfxContainer *)goner) {
+		reparentize_primary_widget_lists(s, (GfxPort *) goner->_parent);
+	}
+
+	if (s->drop_views && (GfxContainer *)s->drop_views->_parent == (GfxContainer *)goner)
+		s->drop_views = NULL; // Kill it
+
+	pred = gfxw_remove_port(s->visual, goner);
+
+	if (goner == s->port) // Did we kill the active port?
+		s->port = pred;
+
+	// Find the last port that exists and that isn't marked no-switch
+	int id = s->visual->_portRefs.size() - 1;
+	while (id > 0 && (!s->visual->_portRefs[id] || (s->visual->_portRefs[id]->_flags & GFXW_FLAG_NO_IMPLICIT_SWITCH)))
+		id--;
+
+	debugC(2, kDebugLevelGraphics, "Activating port %d after disposing window %d\n", id, windowPtr);
+	s->port = (id >= 0) ? s->visual->_portRefs[id] : 0;
+
+	if (!s->port)
+		s->port = gfxw_find_default_port(s->visual);
+
+	gfxop_update(s->gfx_state);
+}
+
+#define K_DISPLAY_SET_COORDS 100
+#define K_DISPLAY_SET_ALIGNMENT 101
+#define K_DISPLAY_SET_COLOR 102
+#define K_DISPLAY_SET_BGCOLOR 103
+#define K_DISPLAY_SET_GRAYTEXT 104
+#define K_DISPLAY_SET_FONT 105
+#define K_DISPLAY_WIDTH 106
+#define K_DISPLAY_SAVE_UNDER 107
+#define K_DISPLAY_RESTORE_UNDER 108
+#define K_DONT_UPDATE_IMMEDIATELY 121
+
+void SciGUI32::display(const char *text, int argc, reg_t *argv) {
+	int argpt = 0;
+	int temp;
+	bool save_under = false;
+	gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
+	GfxPort *port = (s->port) ? s->port : s->picture_port;
+	bool update_immediately = true;
+
+	gfx_color_t color0, *color1, bg_color;
+	gfx_alignment_t halign = ALIGN_LEFT;
+	rect_t area = gfx_rect(port->draw_pos.x, port->draw_pos.y, 320 - port->draw_pos.x, 200 - port->draw_pos.y);
+	int gray = port->gray_text;
+	int font_nr = port->_font;
+	GfxText *text_handle;
+
+	color0 = port->_color;
+	bg_color = port->_bgcolor;
+	// TODO: in SCI1VGA the default colors for text and background are #0 (black)
+	// SCI0 case should be checked
+	if (s->resMan->isVGA()) {
+		// This priority check fixes the colors in the menus in KQ5
+		// TODO/FIXME: Is this correct?
+		if (color0.priority >= 0)
+			color0.visual = get_pic_color(s, 0);
+		if (bg_color.priority >= 0)
+			bg_color.visual = get_pic_color(s, 0);
+	}
+
+	while (argpt < argc) {
+		switch (argv[argpt++].toUint16()) {
+
+		case K_DISPLAY_SET_COORDS:
+
+			area.x = argv[argpt++].toUint16();
+			area.y = argv[argpt++].toUint16();
+			debugC(2, kDebugLevelGraphics, "Display: set_coords(%d, %d)\n", area.x, area.y);
+			break;
+
+		case K_DISPLAY_SET_ALIGNMENT:
+
+			halign = (gfx_alignment_t)argv[argpt++].toSint16();
+			debugC(2, kDebugLevelGraphics, "Display: set_align(%d)\n", halign);
+			break;
+
+		case K_DISPLAY_SET_COLOR:
+
+			temp = argv[argpt++].toSint16();
+			debugC(2, kDebugLevelGraphics, "Display: set_color(%d)\n", temp);
+			if (!s->resMan->isVGA() && temp >= 0 && temp <= 15)
+				color0 = (s->ega_colors[temp]);
+			else
+				if (s->resMan->isVGA() && temp >= 0 && temp < 256) {
+					color0.visual = get_pic_color(s, temp);
+					color0.mask = GFX_MASK_VISUAL;
+				} else
+					if (temp == -1)
+						color0 = transparent;
+					else
+						warning("Display: Attempt to set invalid fg color %d", temp);
+			break;
+
+		case K_DISPLAY_SET_BGCOLOR:
+
+			temp = argv[argpt++].toSint16();
+			debugC(2, kDebugLevelGraphics, "Display: set_bg_color(%d)\n", temp);
+			if (!s->resMan->isVGA() && temp >= 0 && temp <= 15)
+				bg_color = s->ega_colors[temp];
+			else
+				if (s->resMan->isVGA() && temp >= 0 && temp <= 256) {
+					bg_color.visual = get_pic_color(s, temp);
+					bg_color.mask = GFX_MASK_VISUAL;
+				} else
+					if (temp == -1)
+						bg_color = transparent;
+					else
+						warning("Display: Attempt to set invalid fg color %d", temp);
+			break;
+
+		case K_DISPLAY_SET_GRAYTEXT:
+
+			gray = argv[argpt++].toSint16();
+			debugC(2, kDebugLevelGraphics, "Display: set_graytext(%d)\n", gray);
+			break;
+
+		case K_DISPLAY_SET_FONT:
+
+			font_nr = argv[argpt++].toUint16();
+
+			debugC(2, kDebugLevelGraphics, "Display: set_font(\"font.%03d\")\n", font_nr);
+			break;
+
+		case K_DISPLAY_WIDTH:
+
+			area.width = argv[argpt++].toUint16();
+			if (area.width == 0)
+				area.width = MAX_TEXT_WIDTH_MAGIC_VALUE;
+
+			debugC(2, kDebugLevelGraphics, "Display: set_width(%d)\n", area.width);
+			break;
+
+		case K_DISPLAY_SAVE_UNDER:
+
+			save_under = true;
+			debugC(2, kDebugLevelGraphics, "Display: set_save_under()\n");
+			break;
+
+		case K_DISPLAY_RESTORE_UNDER:
+
+			debugC(2, kDebugLevelGraphics, "Display: restore_under(%04x)\n", argv[argpt].toUint16());
+			graph_restore_box(s, argv[argpt++]);
+			update_immediately = true;
+			argpt++;
+			return;
+
+		case K_DONT_UPDATE_IMMEDIATELY:
+
+			update_immediately = false;
+			debugC(2, kDebugLevelGraphics, "Display: set_dont_update()\n");
+			argpt++;
+			break;
+
+		default:
+			debugC(2, kDebugLevelGraphics, "Unknown Display() command %x\n", argv[argpt - 1].toUint16());
+			return;
+		}
+	}
+
+	if (halign == ALIGN_LEFT) {
+		// If the text does not fit on the screen, move it to the left and upwards until it does
+		gfxop_get_text_params(s->gfx_state, font_nr, text, area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
+
+		// Make the text fit on the screen
+		if (area.x + area.width > 320)
+			area.x += 320 - area.x - area.width; // Plus negative number = subtraction
+
+		if (area.y + area.height > 200)
+			area.y += 200 - area.y - area.height; // Plus negative number = subtraction
+	} else {
+		// If the text does not fit on the screen, clip it till it does
+		if (area.x + area.width > s->gfx_state->pic_port_bounds.width)
+			area.width = s->gfx_state->pic_port_bounds.width - area.x;
+
+		if (area.y + area.height > s->gfx_state->pic_port_bounds.height)
+			area.height = s->gfx_state->pic_port_bounds.height - area.y;
+	}
+
+	if (gray)
+		color1 = &bg_color;
+	else
+		color1 = &color0;
+
+	assert_primary_widget_lists(s);
+
+	text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
+
+	if (!text_handle) {
+		error("Display: Failed to create text widget");
+		return;
+	}
+
+	if (save_under) {    // Backup
+		rect_t save_area = text_handle->_bounds;
+		save_area.x += port->_bounds.x;
+		save_area.y += port->_bounds.y;
+
+		s->r_acc = graph_save_box(s, save_area);
+		text_handle->_serial++; // This is evil!
+
+		debugC(2, kDebugLevelGraphics, "Saving (%d, %d) size (%d, %d) as %04x:%04x\n", save_area.x, save_area.y, save_area.width, save_area.height, PRINT_REG(s->r_acc));
+	}
+
+	debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text);
+
+	//ADD_TO_CURRENT_PICTURE_PORT(text_handle);
+
+	ADD_TO_CURRENT_PICTURE_PORT(text_handle);
+	if ((!s->pic_not_valid) && update_immediately) { // Refresh if drawn to valid picture
+		FULL_REDRAW();
+		debugC(2, kDebugLevelGraphics, "Refreshing display...\n");
+	}
+}
+
+void SciGUI32::textSize(const char *text, int16 fontId, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
+	int width, height;
+	if (maxWidth < 0)
+		maxWidth = 0;
+	gfxop_get_text_params(s->gfx_state, fontId, text, maxWidth ? maxWidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
+	                                 &width, &height, 0, NULL, NULL, NULL);
+	*textWidth = width; *textHeight = height;
+}
+
+void SciGUI32::textFonts(int argc, reg_t *argv) {
+	// stub
+}
+
+void SciGUI32::textColors(int argc, reg_t *argv) {
+	// stub
+}
+
+void SciGUI32::drawPicture(sciResourceId pictureId, uint16 showStyle, uint16 flags, int16 EGApaletteNo) {
+	drawn_pic_t dp;
+	gfx_color_t transparent = s->wm_port->_bgcolor;
+	int picFlags = DRAWPIC01_FLAG_FILL_NORMALLY;
+	bool add_to_pic = flags;
+
+	dp.nr = pictureId;
+	if (EGApaletteNo != -1) {
+		dp.palette = EGApaletteNo;
+	} else {
+		dp.palette = 0;
+	}
+
+	if (showStyle & K_DRAWPIC_FLAG_MIRRORED)
+		picFlags |= DRAWPIC1_FLAG_MIRRORED;
+
+	gfxop_disable_dirty_frames(s->gfx_state);
+
+	if (NULL != s->old_screen) {
+		gfxop_free_pixmap(s->gfx_state, s->old_screen);
+	}
+
+	s->old_screen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 10, 320, 190));
+
+	debugC(2, kDebugLevelGraphics, "Drawing pic.%03d\n", pictureId);
+	if (add_to_pic) {
+		gfxop_add_to_pic(s->gfx_state, dp.nr, picFlags, dp.palette);
+	} else {
+		gfxop_new_pic(s->gfx_state, dp.nr, picFlags, dp.palette);
+	}
+
+	delete s->wm_port;
+	delete s->picture_port;
+	delete s->iconbar_port;
+
+	s->wm_port = new GfxPort(s->visual, s->gfx_state->pic_port_bounds, s->ega_colors[0], transparent);
+	s->picture_port = new GfxPort(s->visual, s->gfx_state->pic_port_bounds, s->ega_colors[0], transparent);
+
+	s->iconbar_port = new GfxPort(s->visual, gfx_rect(0, 0, 320, 200), s->ega_colors[0], transparent);
+	s->iconbar_port->_flags |= GFXW_FLAG_NO_IMPLICIT_SWITCH;
+
+	s->visual->add((GfxContainer *)s->visual, s->picture_port);
+	s->visual->add((GfxContainer *)s->visual, s->wm_port);
+	s->visual->add((GfxContainer *)s->visual, s->iconbar_port);
+
+	s->port = s->picture_port;
+
+	s->pic_priority_table = gfxop_get_pic_metainfo(s->gfx_state);
+
+	s->pic_animate = showStyle & 0xff; // The animation used during kAnimate() later on
+
+	s->dyn_views = NULL;
+	s->drop_views = NULL;
+
+	s->priority_first = 42;
+
+	if (_usesOldGfxFunctions)
+		s->priority_last = 200;
+	else
+		s->priority_last = 190;
+
+	s->pic_not_valid = 1;
+	s->pic_is_new = 1;
+}
+
+void SciGUI32::drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo) {
+	int loop = loopNo;
+	int cel = cellNo;
+	GfxView *new_view;
+
+	gfxop_check_cel(s->gfx_state, viewId, &loop, &cel);
+
+	debugC(2, kDebugLevelGraphics, "DrawCel((%d,%d), (view.%d, %d, %d), p=%d)\n", leftPos, topPos, viewId, loop, cel, priority);
+
+	new_view = gfxw_new_view(s->gfx_state, Common::Point(leftPos, topPos), viewId, loop, cel, 0, priority, -1,
+	                         ALIGN_LEFT, ALIGN_TOP, GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET);
+
+	ADD_TO_CURRENT_PICTURE_PORT(new_view);
+	FULL_REDRAW();
+}
+
+void SciGUI32::drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse) {
+	rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height());
+
+	ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, text, fontId,
+		(int8)(style & kControlStateFramed), (int8)inverse, (int8)(style & kControlStateDisabled)));
+	if (!s->pic_not_valid) FULL_REDRAW();
+}
+
+void SciGUI32::drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse) {
+	rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height());
+
+	ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, text, fontId, (gfx_alignment_t) mode,
+								(int8)(!!(style & kControlStateDitherFramed)), (int8)inverse));
+	if (!s->pic_not_valid) FULL_REDRAW();
+}
+
+static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int control) {
+	gfx_color_t retval;
+
+	if (!s->resMan->isVGA()) {
+		retval = s->ega_colors[(color >=0 && color < 16)? color : 0];
+		gfxop_set_color(s->gfx_state, &retval, (color < 0) ? -1 : retval.visual.r, retval.visual.g, retval.visual.b,
+		                (color == -1) ? 255 : 0, priority, control);
+	} else {
+		retval.visual = get_pic_color(s, color);
+		retval.alpha = 0;
+		retval.priority = priority;
+		retval.control = control;
+		retval.mask = GFX_MASK_VISUAL | ((priority >= 0) ? GFX_MASK_PRIORITY : 0) | ((control >= 0) ? GFX_MASK_CONTROL : 0);
+	};
+
+	return retval;
+}
+
+void _k_graph_rebuild_port_with_color(EngineState *s, gfx_color_t newbgcolor) {
+	GfxPort *port = s->port;
+	GfxPort *newport;
+
+	newport = sciw_new_window(s, port->zone, port->_font, port->_color, newbgcolor,
+	                          s->titlebar_port->_font, s->ega_colors[15], s->ega_colors[8],
+	                          port->_title_text.c_str(), port->port_flags & ~kWindowTransparent);
+
+	if (s->dyn_views) {
+		int found = 0;
+		GfxContainer *parent = s->dyn_views->_parent;
+
+		while (parent && !(found |= (parent == port)))
+			parent = parent->_parent;
+
+		s->dyn_views = NULL;
+	}
+
+	port->_parent->add((GfxContainer *)port->_parent, newport);
+	delete port;
+}
+
+void SciGUI32::graphFillBoxForeground(Common::Rect rect) {
+	_k_graph_rebuild_port_with_color(s, s->port->_color);
+	//port = _s->port;
+
+	FULL_REDRAW();
+}
+
+void SciGUI32::graphFillBoxBackground(Common::Rect rect) {
+	_k_graph_rebuild_port_with_color(s, s->port->_bgcolor);
+	//port = _s->port;
+
+	FULL_REDRAW();
+}
+
+void SciGUI32::graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) {
+	gfx_color_t fillColor = graph_map_color(s, color, priority, control);
+	fillColor.mask = (byte)colorMask;
+	rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height());
+
+	//debugC(2, kDebugLevelGraphics, "fill_box_any((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n",
+	//          argv[2].toSint16(), argv[1].toSint16(), argv[4].toSint16(), argv[3].toSint16(), argv[6].toSint16(), priority, control, argv[5].toUint16());
+
+	// FIXME/TODO: this is not right, as some of the dialogs are drawn *behind* some widgets. But at least it works for now
+	//ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT));	// old code
+
+	// FillBox seems to be meant again s->port instead of s->picture_port, at least in QfG3
+//		warning("Fillbox");
+//		ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT));
+	s->picture_port->add((GfxContainer *)s->picture_port, gfxw_new_box(s->gfx_state, area, fillColor, fillColor, GFX_BOX_SHADE_FLAT));
+}
+
+void SciGUI32::graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control) {
+	gfx_color_t gfxcolor = graph_map_color(s, color, priority, control);
+
+	debugC(2, kDebugLevelGraphics, "draw_line((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n",
+	          rect.left, rect.top, rect.right, rect.bottom, color, priority, control, gfxcolor.mask);
+
+	// Note: it's quite possible that the coordinates of the line will *not* form a valid rectangle (e.g. it might
+	// have negative width/height). The actual dirty rectangle is constructed in gfxdr_add_dirty().
+	// FIXME/TODO: We need to change the semantics of this call, so that no fake rectangles are used. As it is, it's
+	// not possible change rect_t to Common::Rect, as we assume that Common::Rect forms a *valid* rectangle.
+	ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_line(Common::Point(rect.left, rect.top), Common::Point(rect.right, rect.bottom),
+	                               gfxcolor, GFX_LINE_MODE_CORRECT, GFX_LINE_STYLE_NORMAL));
+	FULL_REDRAW();
+}
+
+reg_t SciGUI32::graphSaveBox(Common::Rect rect, uint16 flags) {
+	rect_t area;
+	area.x = rect.left + s->port->zone.x + port_origin_x;
+	area.y = rect.top + s->port->zone.y + port_origin_y;
+	area.width = rect.width() - port_origin_x;
+	area.height = rect.height() - port_origin_y;
+
+	return graph_save_box(s, area);
+}
+
+void SciGUI32::graphRestoreBox(reg_t handle) {
+	graph_restore_box(s, handle);
+}
+
+void SciGUI32::paletteSet(int resourceNo, int flags) {
+	//warning("STUB");
+}
+
+int16 SciGUI32::paletteFind(int r, int g, int b) {
+	int i, delta, bestindex = -1, bestdelta = 200000;
+
+	for (i = 0; i < s->gfx_state->gfxResMan->getColorCount(); i++) {
+		int dr = abs(s->gfx_state->gfxResMan->getColor(i).r - r);
+		int dg = abs(s->gfx_state->gfxResMan->getColor(i).g - g);
+		int db = abs(s->gfx_state->gfxResMan->getColor(i).b - b);
+
+		delta = dr * dr + dg * dg + db * db;
+
+		if (delta < bestdelta) {
+			bestdelta = delta;
+			bestindex = i;
+		}
+	}
+	// Don't warn about inexact mappings -- it's actually the
+	// rule rather than the exception
+	return bestindex;
+}
+
+void SciGUI32::paletteAnimate(int fromColor, int toColor, int speed) {
+	warning("STUB");
+}
+
+void SciGUI32::moveCursor(int16 x, int16 y) {
+	Common::Point newPos;
+
+	// newPos = s->gfx_state->pointer_pos;
+
+	newPos.x = x + s->port->zone.x;
+	newPos.y = y + s->port->zone.y;
+
+	if (newPos.x > s->port->zone.x + s->port->zone.width)
+		newPos.x = s->port->zone.x + s->port->zone.width;
+	if (newPos.y > s->port->zone.y + s->port->zone.height)
+		newPos.y = s->port->zone.y + s->port->zone.height;
+
+	if (newPos.x < 0) newPos.x = 0;
+	if (newPos.y < 0) newPos.y = 0;
+	gfxop_set_pointer_position(s->gfx_state, newPos);
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/gui32/gui32.h b/engines/sci/gui32/gui32.h
new file mode 100644
index 0000000..7c606a8
--- /dev/null
+++ b/engines/sci/gui32/gui32.h
@@ -0,0 +1,79 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+class SciGUI32 : public SciGUI {
+public:
+	SciGUI32(OSystem *system, EngineState *s);
+	~SciGUI32();
+
+	void init(bool oldGfxFunctions);
+
+	int16 getTimeTicks();
+	void wait(int16 ticks);
+	void setPort(uint16 portPtr);
+	void setPortPic(Common::Rect rect, int16 picTop, int16 picLeft);
+	reg_t getPort();
+	void globalToLocal(int16 *x, int16 *y);
+	void localToGlobal(int16 *x, int16 *y);
+	reg_t newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack);
+	void disposeWindow(uint16 windowPtr, int16 arg2);
+
+	void display(const char *text, int argc, reg_t *argv);
+
+	void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+	void textFonts(int argc, reg_t *argv);
+	void textColors(int argc, reg_t *argv);
+
+	void drawPicture(sciResourceId pictureId, uint16 showStyle, uint16 flags, int16 EGApaletteNo);
+	void drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo);
+	void drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse);
+	void drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse);
+
+	void graphFillBoxForeground(Common::Rect rect);
+	void graphFillBoxBackground(Common::Rect rect);	
+	void graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control);
+	void graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control);
+	reg_t graphSaveBox(Common::Rect rect, uint16 flags);
+	void graphRestoreBox(reg_t handle);
+
+	void paletteSet(int resourceNo, int flags);
+	virtual int16 paletteFind(int r, int g, int b);
+	void paletteAnimate(int fromColor, int toColor, int speed);
+
+	void moveCursor(int16 x, int16 y);
+
+private:
+	OSystem *_system;
+	EngineState *s;
+	bool _usesOldGfxFunctions;
+
+	bool activated_icon_bar;	// FIXME: Avoid non-const global vars
+	int port_origin_x;	// FIXME: Avoid non-const global vars
+	int port_origin_y;	// FIXME: Avoid non-const global vars
+};
+
+} // End of namespace Sci
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 88c60b6..fd5b7aa 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -55,6 +55,16 @@ MODULE_OBJS = \
 	gfx/res_pic.o \
 	gfx/res_view.o \
 	gfx/seq_decoder.o \
+	gui/gui.o \
+	gui/gui_dbllist.o \
+	gui/gui_font.o \
+	gui/gui_gfx.o \
+	gui/gui_memmgr.o \
+	gui/gui_picture.o \
+	gui/gui_screen.o \
+	gui/gui_view.o \
+	gui/gui_windowmgr.o \
+	gui32/gui32.o \
 	sfx/core.o \
 	sfx/iterator.o \
 	sfx/songlib.o \
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index a8f130f..11c86d8 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -35,6 +35,8 @@
 #include "sci/engine/state.h"
 #include "sci/engine/kernel.h"
 
+#include "sci/gui32/gui32.h"
+
 #include "sci/gfx/gfx_resource.h"
 #include "sci/gfx/gfx_tools.h"
 #include "sci/gfx/operations.h"
@@ -44,7 +46,7 @@ namespace Sci {
 class GfxDriver;
 
 SciEngine::SciEngine(OSystem *syst, const SciGameDescription *desc)
-		: Engine(syst), _gameDescription(desc) {
+		: Engine(syst), _gameDescription(desc), _system(syst) {
 	// Put your engine in a sane state, but do nothing big yet;
 	// in particular, do not load data from files; rather, if you
 	// need to do such things, do them from init().
@@ -152,6 +154,10 @@ Common::Error SciEngine::run() {
 	GfxState gfx_state;
 	_gamestate->gfx_state = &gfx_state;
 
+	// GUI change
+	//_gamestate->gui = new SciGUI(_system, _gamestate);    // new
+	_gamestate->gui = new SciGUI32(_system, _gamestate);  // old
+
 	// Assign default values to the config manager, in case settings are missing
 	ConfMan.registerDefault("dither_mode", "0");
 
@@ -183,6 +189,8 @@ Common::Error SciEngine::run() {
 		return Common::kUnknownError;
 	}
 
+	_gamestate->gui->init(_kernel->usesOldGfxFunctions());
+
 	printf("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()).c_str());
 
 	game_run(&_gamestate); // Run the game
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 3dbafce..ffcef32 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -132,6 +132,7 @@ private:
 	Kernel *_kernel;
 	Vocabulary *_vocabulary;
 	Console *_console;
+	OSystem *_system;
 };
 
 /**
