[Scummvm-cvs-logs] scummvm master -> 509a00109e79156e91c062f145ac3aa86ec8584e

dreammaster dreammaster at scummvm.org
Sun Mar 20 19:49:37 CET 2016


This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
433a2daa6a GRAPHICS: Added ManagedSurface and Screen classes
9c7569b74b ACCESS: Changed engine to use Graphics::ManagedSurface
b4e3d4abc1 MADS: Changed engine to use Graphics::ManagedSurface
3da3dda187 SHERLOCK: Changed engine to use Graphics::ManagedSurface
077250acfb TSAGE: Changed engine to use Graphics::ManagedSurface
c05a09d337 VOYEUR: Changed engine to use Graphics::ManagedSurface
390487aa43 GRAPHICS: Cleanup of ManagedSurface and Screen classes
509a00109e Merge pull request #652 from dreammaster/screen


Commit: 433a2daa6a42b4cca3a715d4461a893be17ef61a
    https://github.com/scummvm/scummvm/commit/433a2daa6a42b4cca3a715d4461a893be17ef61a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-14T20:56:14-04:00

Commit Message:
GRAPHICS: Added ManagedSurface and Screen classes

Changed paths:
  A graphics/managed_surface.cpp
  A graphics/managed_surface.h
  A graphics/screen.cpp
  A graphics/screen.h
    graphics/font.cpp
    graphics/font.h
    graphics/module.mk



diff --git a/graphics/font.cpp b/graphics/font.cpp
index dba4824..d709758 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "graphics/font.h"
+#include "graphics/managed_surface.h"
 
 #include "common/array.h"
 #include "common/util.h"
@@ -273,6 +274,16 @@ void Font::drawString(Surface *dst, const Common::U32String &str, int x, int y,
 	drawStringImpl(*this, dst, str, x, y, w, color, align, 0);
 }
 
+void Font::drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align, int deltax, bool useEllipsis) const {
+	drawString(&dst->_innerSurface, str, x, y, w, color, align, deltax, useEllipsis);
+	dst->addDirtyRect(Common::Rect(x, y, x + w, y + getFontHeight()));
+}
+
+void Font::drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align) const {
+	drawString(&dst->_innerSurface, str, x, y, w, color, align);
+	dst->addDirtyRect(Common::Rect(x, y, x + w, y + getFontHeight()));
+}
+
 int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines) const {
 	return wordWrapTextImpl(*this, str, maxWidth, lines);
 }
diff --git a/graphics/font.h b/graphics/font.h
index 35f6792..62e71a8 100644
--- a/graphics/font.h
+++ b/graphics/font.h
@@ -34,6 +34,7 @@ template<class T> class Array;
 namespace Graphics {
 
 struct Surface;
+class ManagedSurface;
 
 /** Text alignment modes */
 enum TextAlign {
@@ -145,6 +146,8 @@ public:
 	// TODO: Add doxygen comments to this
 	void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
 	void drawString(Surface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
+	void drawString(ManagedSurface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
+	void drawString(ManagedSurface *dst, const Common::U32String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft) const;
 
 	/**
 	 * Compute and return the width the string str has when rendered using this font.
diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
new file mode 100644
index 0000000..45db0bc
--- /dev/null
+++ b/graphics/managed_surface.cpp
@@ -0,0 +1,258 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "graphics/managed_surface.h"
+#include "common/algorithm.h"
+#include "common/textconsole.h"
+
+namespace Graphics {
+
+const int SCALE_THRESHOLD = 0x100;
+
+ManagedSurface::ManagedSurface() : 
+		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+		_isManaged(false), _owner(nullptr) {
+}
+
+ManagedSurface::ManagedSurface(const ManagedSurface &surf) :
+		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+		_isManaged(false), _owner(nullptr) {
+	*this = surf;
+}
+
+ManagedSurface::ManagedSurface(int width, int height) :
+		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+		_isManaged(false), _owner(nullptr) {
+	create(width, height);
+}
+
+ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) :
+		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+		_isManaged(false), _owner(nullptr) {
+	create(width, height, format);
+}
+
+ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) :
+		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
+		_isManaged(false), _owner(nullptr) {
+	create(surf, bounds);
+}
+
+ManagedSurface::~ManagedSurface() {
+	free();
+}
+
+ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) {
+	if (surf._isManaged) {
+		// Create a new surface and copy the pixels from the source surface
+		create(surf.w, surf.h, surf.format);
+		Common::copy((const byte *)surf.getPixels(), (const byte *)surf.getPixels() +
+			surf.w * surf.h * surf.format.bytesPerPixel, (byte *)this->getPixels());
+	} else {
+		// Source isn't managed, so simply copy it's fields
+		_isManaged = false;
+		_owner = surf._owner;
+		_offsetFromOwner = surf._offsetFromOwner;
+		
+		void *srcPixels = (void *)surf._innerSurface.getPixels();
+		_innerSurface.setPixels(srcPixels);
+		_innerSurface.w = surf.w;
+		_innerSurface.h = surf.h;
+		_innerSurface.pitch = surf.pitch;
+		this->format = surf.format;
+	}
+
+	return *this;
+}
+
+void ManagedSurface::setPixels(void *newPixels) {
+	free();
+	_innerSurface.setPixels(newPixels);
+}
+
+void ManagedSurface::create(uint16 width, uint16 height) {
+	create(width, height, PixelFormat::createFormatCLUT8());
+}
+
+void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixelFormat) {
+	free();
+	_innerSurface.create(width, height, pixelFormat);
+
+	_isManaged = true;
+	markAllDirty();
+}
+
+void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) {
+	free();
+	
+	_offsetFromOwner = Common::Point(bounds.left, bounds.top);
+	_innerSurface.setPixels(surf.getBasePtr(bounds.left, bounds.top));
+	_innerSurface.pitch = surf.pitch;
+	_innerSurface.format = surf.format;
+	_innerSurface.w = bounds.width();
+	_innerSurface.h = bounds.height();
+	_owner = &surf;
+	_isManaged = false;
+}
+
+void ManagedSurface::free() {
+	if (_isManaged)
+		_innerSurface.free();
+
+	_isManaged = false;
+	_owner = nullptr;
+	_offsetFromOwner = Common::Point(0, 0);
+}
+
+bool ManagedSurface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
+	if (destBounds.left >= this->w || destBounds.top >= this->h ||
+			destBounds.right <= 0 || destBounds.bottom <= 0)
+		return false;
+
+	// Clip the bounds if necessary to fit on-screen
+	if (destBounds.right > this->w) {
+		srcBounds.right -= destBounds.right - this->w;
+		destBounds.right = this->w;
+	}
+
+	if (destBounds.bottom > this->h) {
+		srcBounds.bottom -= destBounds.bottom - this->h;
+		destBounds.bottom = this->h;
+	}
+
+	if (destBounds.top < 0) {
+		srcBounds.top += -destBounds.top;
+		destBounds.top = 0;
+	}
+
+	if (destBounds.left < 0) {
+		srcBounds.left += -destBounds.left;
+		destBounds.left = 0;
+	}
+
+	return true;
+}
+
+void ManagedSurface::blitFrom(const Surface &src) {
+	blitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Point(0, 0));
+}
+
+void ManagedSurface::blitFrom(const Surface &src, const Common::Point &destPos) {
+	blitFrom(src, Common::Rect(0, 0, src.w, src.h), destPos);
+}
+
+void ManagedSurface::blitFrom(const Surface &src, const Common::Rect &srcRect,
+		const Common::Point &destPos) {
+	Common::Rect srcBounds = srcRect;
+	Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(), 
+		destPos.y + srcRect.height());
+	assert(src.format.bytesPerPixel == format.bytesPerPixel);
+
+	if (!srcRect.isValidRect() || !clip(srcBounds, destBounds))
+		return;
+
+	for (int y = 0; y < srcBounds.height(); ++y) {
+		const byte *srcP = (const byte *)src.getBasePtr(srcBounds.left, srcBounds.top + y);
+		byte *destP = (byte *)getBasePtr(destBounds.left, destBounds.top + y);
+		Common::copy(srcP, srcP + srcBounds.width() * format.bytesPerPixel, destP);
+	}
+
+	addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, uint transColor, bool flipped, uint overrideColor) {
+	transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(0, 0, this->w, this->h),
+		transColor, false, overrideColor);
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, const Common::Point &destPos,
+		uint transColor, bool flipped, uint overrideColor) {
+	transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(destPos.x, destPos.y,
+		destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor);
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect,
+		const Common::Point &destPos, uint transColor, bool flipped, uint overrideColor) {
+	transBlitFrom(src, srcRect, Common::Rect(destPos.x, destPos.y,
+		destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor);
+}
+
+template<typename T>
+void transBlit(const Surface &src, const Common::Rect &srcRect, const Surface *dest, const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) {
+	int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
+	int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
+
+	// Loop through drawing output lines
+	for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) {
+		if (destY < 0 || destY >= dest->h)
+			continue;
+		const T *srcLine = (const T *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD);
+		T *destLine = (T *)dest->getBasePtr(destRect.left, destY);
+
+		// Loop through drawing the pixels of the row
+		for (int destX = destRect.left, xCtr = 0, scaleXCtr = 0; destX < destRect.right; ++destX, ++xCtr, scaleXCtr += scaleX) {
+			if (destX < 0 || destX >= dest->w)
+				continue;
+
+			T srcVal = srcLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD];
+			if (srcVal != transColor) {
+				destLine[xCtr] = overrideColor ? overrideColor : srcVal;
+			}
+		}
+	}
+}
+
+void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect,
+	const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) {
+	if (src.w == 0 || src.h == 0 || destRect.width() == 0 || destRect.height() == 0)
+		return;
+
+	if (format.bytesPerPixel == 1)
+		transBlit<byte>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
+	else if (format.bytesPerPixel == 2)
+		transBlit<uint16>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
+	else if (format.bytesPerPixel == 4)
+		transBlit<uint32>(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor);
+	else
+		error("Surface::transBlitFrom: bytesPerPixel must be 1, 2, or 4");
+
+	// Mark the affected area
+	addDirtyRect(destRect);
+}
+
+void ManagedSurface::markAllDirty() {
+	addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void ManagedSurface::addDirtyRect(const Common::Rect &r) {
+	if (_owner) {
+		Common::Rect bounds = r;
+		bounds.translate(_offsetFromOwner.x, _offsetFromOwner.y);
+		_owner->addDirtyRect(bounds);
+	}
+}
+
+void ManagedSurface::clear(uint color) {
+	fillRect(getBounds(), color);
+}
+
+} // End of namespace Graphics
diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h
new file mode 100644
index 0000000..1d837fd
--- /dev/null
+++ b/graphics/managed_surface.h
@@ -0,0 +1,355 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GRAPHICS_MANAGED_SURFACE_H
+#define GRAPHICS_MANAGED_SURFACE_H
+
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "common/rect.h"
+
+namespace Graphics {
+
+class Font;
+
+/**
+ * A derived graphics surface, which handles automatically managing the allocated
+ * surface data block, as well as introducing several new blitting methods
+ */
+class ManagedSurface {
+	friend class Font;
+private:
+	Surface _innerSurface;
+	bool _isManaged;
+	ManagedSurface *_owner;
+	Common::Point _offsetFromOwner;
+protected:
+	/**
+	 * Clips the given source bounds so the passed destBounds will be entirely on-screen
+	 */
+	bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
+
+	/**
+	 * Base method that descendent classes can override for recording affected
+	 * dirty areas of the surface
+	 */
+	virtual void addDirtyRect(const Common::Rect &r);
+public:
+	uint16 &w;
+	uint16 &h;
+	uint16 &pitch;
+	PixelFormat &format;
+public:
+	/**
+	 * Create the managed surface
+	 */
+	ManagedSurface();
+
+	/**
+	 * Create a managed surface from another one
+	 * Note that if the source has a managed surface, it will be duplicated
+	 */
+	ManagedSurface(const ManagedSurface &surf);
+
+	/**
+	 * Create the managed surface
+	 */
+	ManagedSurface(int width, int height);
+	
+	/**
+	 * Create the managed surface
+	 */
+	ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat);
+	
+	/**
+	 * Create the managed surface
+	 */
+	ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds);
+
+	/**
+	 * Destroy the managed surface
+	 */
+	virtual ~ManagedSurface();
+
+	/**
+	 * Implements automatic conversion to a Graphics::Surface by
+	 * simply returning the inner surface. This must be const,
+	 * because we don't want changes being done directly to it,
+	 * since it would bypass dirty rect handling
+	 */
+	operator const Surface &() const { return _innerSurface; }
+	const Surface &rawSurface() const { return _innerSurface; }
+
+	/**
+	 * Reassign one managed surface to another one
+	 * Note that if the source has a managed surface, it will be duplicated
+	 */
+	ManagedSurface &operator=(const ManagedSurface &surf);
+
+	/**
+	 * Returns true if the surface has not yet been allocated
+	 */
+	bool empty() const { return w == 0 || h == 0 || _innerSurface.getPixels() == nullptr; }
+
+	/**
+	 * Returns true if the surface is managing it's own pixels
+	 */
+	bool isManaged() const { return _isManaged; }
+
+	/**
+	 * Return a pointer to the pixel at the specified point.
+	 *
+	 * @param x The x coordinate of the pixel.
+	 * @param y The y coordinate of the pixel.
+	 * @return Pointer to the pixel.
+	 */
+	inline const void *getBasePtr(int x, int y) const {
+		return _innerSurface.getBasePtr(x, y);
+	}
+
+	/**
+	 * Return a pointer to the pixel at the specified point.
+	 *
+	 * @param x The x coordinate of the pixel.
+	 * @param y The y coordinate of the pixel.
+	 * @return Pointer to the pixel.
+	 */
+	inline void *getBasePtr(int x, int y) {
+		return _innerSurface.getBasePtr(x, y);
+	}
+
+	/**
+	 * Get a reference to the pixel data
+	 */
+	inline void *getPixels() { return _innerSurface.getPixels(); }
+	inline const void *getPixels() const { return _innerSurface.getPixels(); }
+
+	/**
+	 * Sets the pixel data.
+	 */
+	virtual void setPixels(void *newPixels);
+
+	/**
+	 * Allocate memory for the pixel data of the surface.
+	 */
+	virtual void create(uint16 width, uint16 height);
+
+	/**
+	 * Allocate memory for the pixel data of the surface.
+	 */
+	virtual void create(uint16 width, uint16 height, const PixelFormat &pixelFormat);
+
+	/**
+	 * Sets up the surface as a sub-section of another passed parent surface. This surface
+	 * will not own the pixels, and any dirty rect notifications will automatically be
+	 * passed to the original parent surface.
+	 * @remarks		Note that this differs from Graphics::Surface::getSubArea, in that that
+	 * method only adds a single initial dirty rect for the whole area, and then none further
+	 */
+	virtual void create(ManagedSurface &surf, const Common::Rect &bounds);
+
+	/**
+	 * Release the memory used by the pixels memory of this surface. This is the
+	 * counterpart to create().
+	 */
+	virtual void free();
+
+	/**
+	 * Clears any pending dirty rects that have been generated for the surface
+	 */
+	virtual void clearDirtyRects() {}
+
+	/**
+	 * When the managed surface is a sub-section of a parent surface, returns the
+	 * the offset in the parent surface that the surface starts at
+	 */
+	const Common::Point getOffsetFromOwner() const { return _offsetFromOwner; }
+
+	/**
+	 * Return a rect giving the bounds of the surface
+	 */
+	const Common::Rect getBounds() const {
+		return Common::Rect(0, 0, this->w, this->h);
+	}
+	
+	/**
+	 * Copies another surface into this one
+	 */
+	void blitFrom(const Surface &src);
+
+	/**
+	 * Copies another surface into this one at a given destination position
+	 */
+	void blitFrom(const Surface &src, const Common::Point &destPos);
+
+	/**
+	 * Copies another surface into this one at a given destination position
+	 */
+	void blitFrom(const Surface &src, const Common::Rect &srcRect,
+		const Common::Point &destPos);
+
+	/**
+	 * Copies another surface into this one ignoring pixels of a designated transparent color
+	 * @param src			Source surface
+	 * @param transColor	Transparency color to ignore copying
+	 * @param flipped		Specifies whether to horizontally flip the image
+	 * @param overrideColor	Optional color to use instead of non-transparent pixels from
+	 *						the source surface
+	 */
+	void transBlitFrom(const Surface &src, uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+	/**
+	 * Copies another surface into this one ignoring pixels of a designated transparent color
+	 * @param src			Source surface
+	 * @param destPos		Destination position to draw the surface
+	 * @param transColor	Transparency color to ignore copying
+	 * @param flipped		Specifies whether to horizontally flip the image
+	 * @param overrideColor	Optional color to use instead of non-transparent pixels from
+	 *						the source surface
+	 */
+	void transBlitFrom(const Surface &src, const Common::Point &destPos,
+		uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+	/**
+	 * Copies another surface into this one ignoring pixels of a designated transparent color
+	 * @param src			Source surface
+	 * @param srcRect		Sub-section of source surface to draw
+	 * @param destPos		Destination position to draw the surface
+	 * @param transColor	Transparency color to ignore copying
+	 * @param flipped		Specifies whether to horizontally flip the image
+	 * @param overrideColor	Optional color to use instead of non-transparent pixels from
+	 *						the source surface
+	 */
+	void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Point &destPos,
+		uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+	/**
+	 * Copies another surface into this one ignoring pixels of a designated transparent color
+	 * @param src			Source surface
+	 * @param srcRect		Sub-section of source surface to draw
+	 * @param destRect		Destination area to draw the surface in. This can be sized differently
+	 *						then srcRect, allowing for arbitrary scaling of the image
+	 * @param transColor	Transparency color to ignore copying
+	 * @param flipped		Specifies whether to horizontally flip the image
+	 * @param overrideColor	Optional color to use instead of non-transparent pixels from
+	 *						the source surface
+	 */
+	void transBlitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Rect &destRect,
+		uint transColor = 0, bool flipped = false, uint overrideColor = 0);
+
+	/**
+	 * Clear the entire surface
+	 */
+	void clear(uint color = 0);
+
+	/**
+	 * Mark the entire surface as dirty
+	 */
+	void markAllDirty();
+
+	/**
+	 * Copies a bitmap to the Surface internal buffer. The pixel format
+	 * of buffer must match the pixel format of the Surface.
+	 */
+	void copyRectToSurface(const void *buffer, int srcPitch, int destX, int destY, int width, int height) {
+		_innerSurface.copyRectToSurface(buffer, srcPitch, destX, destY, width, height);
+	}
+
+	/**
+	 * Copies a bitmap to the Surface internal buffer. The pixel format
+	 * of buffer must match the pixel format of the Surface.
+	 */
+	void copyRectToSurface(const Graphics::Surface &srcSurface, int destX, int destY, const Common::Rect subRect) {
+		_innerSurface.copyRectToSurface(srcSurface, destX, destY, subRect);
+	}
+
+	/**
+	 * Copy the data from another Surface, reinitializing the
+	 * surface to match the dimensions of the passed surface
+	 */
+	void copyFrom(const ManagedSurface &surf) {
+		clearDirtyRects();
+		_innerSurface.copyFrom(surf._innerSurface);
+	}
+
+	/**
+	 * Draw a line.
+	 */
+	void drawLine(int x0, int y0, int x1, int y1, uint32 color) {
+		_innerSurface.drawLine(x0, y0, x1, y1, color);
+		addDirtyRect(Common::Rect(x0, y0, x1, y1));
+	}
+
+	/**
+	 * Draw a thick line.
+	 */
+	void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color) {
+		_innerSurface.drawThickLine(x0, y0, x1, y1, penX, penY, color);
+		addDirtyRect(Common::Rect(x0, y0, x1, y1));
+	}
+
+	/**
+	 * Draw a horizontal line.
+	 */
+	void hLine(int x, int y, int x2, uint32 color) {
+		_innerSurface.hLine(x, y, x2, color);
+		addDirtyRect(Common::Rect(x, y, x2 + 1, y + 1));
+	}
+
+	/**
+	 * Draw a vertical line.
+	 */
+	void vLine(int x, int y, int y2, uint32 color) {
+		_innerSurface.vLine(x, y, y2, color);
+		addDirtyRect(Common::Rect(x, y, x + 1, y2 + 1));
+	}
+
+	/**
+	 * Fill a rect with a given color.
+	 */
+	void fillRect(Common::Rect r, uint32 color) {
+		_innerSurface.fillRect(r, color);
+		addDirtyRect(r);
+	}
+
+	/**
+	 * Draw a frame around a specified rect.
+	 */
+	void frameRect(const Common::Rect &r, uint32 color) {
+		_innerSurface.frameRect(r, color);
+		addDirtyRect(r);
+	}
+
+	/**
+	 * Returns a sub-area of the screen, but only adds a single initial dirty rect
+	 * for the retrieved area.
+	 */
+	Surface getSubArea(const Common::Rect &area) {
+		addDirtyRect(area);
+		return _innerSurface.getSubArea(area);
+	}
+};
+
+} // End of namespace Graphics
+
+
+#endif
diff --git a/graphics/module.mk b/graphics/module.mk
index b6919cf..90f6a31 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -12,10 +12,12 @@ MODULE_OBJS := \
 	fonts/ttf.o \
 	fonts/winfont.o \
 	maccursor.o \
+	managed_surface.o \
 	pixelformat.o \
 	primitives.o \
 	scaler.o \
 	scaler/thumbnail_intern.o \
+	screen.o \
 	sjis.o \
 	surface.o \
 	transform_struct.o \
diff --git a/graphics/screen.cpp b/graphics/screen.cpp
new file mode 100644
index 0000000..4169c98
--- /dev/null
+++ b/graphics/screen.cpp
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "common/algorithm.h"
+#include "graphics/screen.h"
+#include "graphics/palette.h"
+
+namespace Graphics {
+
+Screen::Screen(): ManagedSurface() {
+	create(g_system->getWidth(), g_system->getHeight());
+}
+
+Screen::Screen(int width, int height): ManagedSurface() {
+	create(width, height);
+}
+
+Screen::Screen(int width, int height, PixelFormat pixelFormat): ManagedSurface() {
+	create(width, height, pixelFormat);
+}
+
+void Screen::update() {
+	// Merge the dirty rects
+	mergeDirtyRects();
+
+	// Loop through copying dirty areas to the physical screen
+	Common::List<Common::Rect>::iterator i;
+	for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
+		const Common::Rect &r = *i;
+		const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
+		g_system->copyRectToScreen(srcP, pitch, r.left, r.top,
+			r.width(), r.height());
+	}
+
+	// Signal the physical screen to update
+	g_system->updateScreen();
+	_dirtyRects.clear();
+}
+
+
+void Screen::addDirtyRect(const Common::Rect &r) {
+	Common::Rect bounds = r;
+	bounds.clip(getBounds());
+	bounds.translate(getOffsetFromOwner().x, getOffsetFromOwner().y);
+
+	if (bounds.width() > 0 && bounds.height() > 0)
+		_dirtyRects.push_back(bounds);
+}
+
+void Screen::makeAllDirty() {
+	addDirtyRect(Common::Rect(0, 0, this->w, this->h));
+}
+
+void Screen::mergeDirtyRects() {
+	Common::List<Common::Rect>::iterator rOuter, rInner;
+
+	// Process the dirty rect list to find any rects to merge
+	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
+		rInner = rOuter;
+		while (++rInner != _dirtyRects.end()) {
+
+			if ((*rOuter).intersects(*rInner)) {
+				// These two rectangles overlap, so merge them
+				unionRectangle(*rOuter, *rOuter, *rInner);
+
+				// remove the inner rect from the list
+				_dirtyRects.erase(rInner);
+
+				// move back to beginning of list
+				rInner = rOuter;
+			}
+		}
+	}
+}
+
+bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
+	destRect = src1;
+	destRect.extend(src2);
+
+	return !destRect.isEmpty();
+}
+
+void Screen::getPalette(byte palette[PALETTE_SIZE]) {
+	assert(format.bytesPerPixel == 1);
+	g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
+}
+
+void Screen::getPalette(byte *palette, uint start, uint num) {
+	assert(format.bytesPerPixel == 1);
+	g_system->getPaletteManager()->grabPalette(palette, start, num);
+}
+
+void Screen::setPalette(const byte palette[PALETTE_SIZE]) {
+	assert(format.bytesPerPixel == 1);
+	g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT);
+}
+
+void Screen::setPalette(const byte *palette, uint start, uint num) {
+	assert(format.bytesPerPixel == 1);
+	g_system->getPaletteManager()->setPalette(palette, start, num);
+}
+
+void Screen::clearPalette() {
+	byte palette[PALETTE_SIZE];
+	Common::fill(&palette[0], &palette[PALETTE_SIZE], 0);
+	setPalette(palette);
+}
+
+} // End of namespace Graphics
diff --git a/graphics/screen.h b/graphics/screen.h
new file mode 100644
index 0000000..3479ce8
--- /dev/null
+++ b/graphics/screen.h
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GRAPHICS_SCREEN_H
+#define GRAPHICS_SCREEN_H
+
+#include "graphics/managed_surface.h"
+#include "graphics/pixelformat.h"
+#include "common/list.h"
+#include "common/rect.h"
+
+namespace Graphics {
+
+#define PALETTE_COUNT 256
+#define PALETTE_SIZE (256 * 3)
+
+class Screen : virtual public ManagedSurface {
+private:
+	/**
+	 * List of affected areas of the screen
+	 */
+	Common::List<Common::Rect> _dirtyRects;
+private:
+	/**
+	* Merges together overlapping dirty areas of the screen
+	*/
+	void mergeDirtyRects();
+
+	/**
+	* Returns the union of two dirty area rectangles
+	*/
+	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+protected:
+	/**
+	 * Adds a rectangle to the list of modified areas of the screen during the
+	 * current frame
+	 */
+	virtual void addDirtyRect(const Common::Rect &r);
+public:
+	Screen();
+	Screen(int width, int height);
+	Screen(int width, int height, PixelFormat pixelFormat);
+
+	/**
+	 * Returns true if there are any pending screen updates
+	 */
+	bool isDirty() const { return _dirtyRects.empty(); }
+
+	/**
+	 * Makes the whole screen dirty
+	 */
+	void makeAllDirty();
+
+	/**
+	 * Clear the current dirty rects list
+	 */
+	virtual void clearDirtyRects() { _dirtyRects.clear(); }
+
+	/**
+	 * Updates the screen by copying any affected areas to the system
+	 */
+	virtual void update();
+
+	/**
+	 * Return the currently active palette
+	 */
+	void getPalette(byte palette[PALETTE_SIZE]);
+
+	/**
+	 * Return a portion of the currently active palette
+	 */
+	void getPalette(byte *palette, uint start, uint num);
+
+	/**
+	 * Set the palette
+	 */
+	void setPalette(const byte palette[PALETTE_SIZE]);
+
+	/**
+	 * Set a subsection of the palette
+	 */
+	void setPalette(const byte *palette, uint start, uint num);
+
+	/**
+	 * Clears the current palette, setting all entries to black
+	 */
+	void clearPalette();
+};
+
+} // End of namespace Graphics
+
+#endif


Commit: 9c7569b74bf3493f7970a912ae54b87d73e6633e
    https://github.com/scummvm/scummvm/commit/9c7569b74bf3493f7970a912ae54b87d73e6633e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-14T20:56:25-04:00

Commit Message:
ACCESS: Changed engine to use Graphics::ManagedSurface

Changed paths:
    engines/access/access.cpp
    engines/access/asurface.cpp
    engines/access/asurface.h
    engines/access/events.cpp
    engines/access/events.h
    engines/access/files.cpp
    engines/access/files.h
    engines/access/font.cpp
    engines/access/screen.cpp
    engines/access/screen.h
    engines/access/video.cpp
    engines/access/video/movie_decoder.cpp



diff --git a/engines/access/access.cpp b/engines/access/access.cpp
index bc9bcb4..c12761a 100644
--- a/engines/access/access.cpp
+++ b/engines/access/access.cpp
@@ -436,20 +436,9 @@ void AccessEngine::copyBF1BF2() {
 }
 
 void AccessEngine::copyBF2Vid() {
-	const byte *srcP = (const byte *)_buffer2.getPixels();
-	byte *destP = (byte *)_screen->getBasePtr(_screen->_windowXAdd,
-		_screen->_windowYAdd + _screen->_screenYOff);
-
-	for (int yp = 0; yp < _screen->_vWindowLinesTall; ++yp) {
-		Common::copy(srcP, srcP + _screen->_vWindowBytesWide, destP);
-		srcP += _buffer2.pitch;
-		destP += _screen->pitch;
-	}
-
-	// Add dirty rect for affected area
-	Common::Rect r(_screen->_vWindowBytesWide, _screen->_vWindowLinesTall);
-	r.moveTo(_screen->_windowXAdd, _screen->_windowYAdd + _screen->_screenYOff);
-	_screen->addDirtyRect(r);
+	_screen->blitFrom(_buffer2,
+		Common::Rect(0, 0, _screen->_vWindowBytesWide, _screen->_vWindowLinesTall),
+		Common::Point(_screen->_windowXAdd, _screen->_windowYAdd));
 }
 
 void AccessEngine::playVideo(int videoNum, const Common::Point &pt) {
diff --git a/engines/access/asurface.cpp b/engines/access/asurface.cpp
index f693e6a..2518ff6 100644
--- a/engines/access/asurface.cpp
+++ b/engines/access/asurface.cpp
@@ -110,7 +110,7 @@ void ImageEntryList::addToList(ImageEntry &ie) {
 int ASurface::_clipWidth;
 int ASurface::_clipHeight;
 
-ASurface::ASurface(): Graphics::Surface() {
+ASurface::ASurface(): Graphics::ManagedSurface() {
 	_leftSkip = _rightSkip = 0;
 	_topSkip = _bottomSkip = 0;
 	_lastBoundsX = _lastBoundsY = 0;
@@ -122,65 +122,14 @@ ASurface::ASurface(): Graphics::Surface() {
 }
 
 ASurface::~ASurface() {
-	free();
 	_savedBlock.free();
 }
 
-void ASurface::create(uint16 width, uint16 height) {
-	Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-}
-
 void ASurface::clearBuffer() {
 	byte *pSrc = (byte *)getPixels();
 	Common::fill(pSrc, pSrc + w * h, 0);
 }
 
-bool ASurface::clip(Common::Rect &r) {
-	int skip;
-	_leftSkip = _rightSkip = 0;
-	_topSkip = _bottomSkip = 0;
-
-	if (r.left > _clipWidth || r.left < 0) {
-		if (r.left >= 0)
-			return true;
-
-		skip = -r.left;
-		r.setWidth(r.width() - skip);
-		_leftSkip = skip;
-		r.moveTo(0, r.top);
-	}
-
-	int right = r.right - 1;
-	if (right < 0)
-		return true;
-	else if (right > _clipWidth) {
-		skip = right - _clipWidth;
-		r.setWidth(r.width() - skip);
-		_rightSkip = skip;
-	}
-
-	if (r.top > _clipHeight || r.top < 0) {
-		if (r.top >= 0)
-			return true;
-
-		skip = -r.top;
-		r.setHeight(r.height() - skip);
-		_topSkip = skip;
-		r.moveTo(r.left, 0);
-	}
-
-	int bottom = r.bottom - 1;
-	if (bottom < 0)
-		return true;
-	else if (bottom > _clipHeight) {
-		skip = bottom - _clipHeight;
-		_bottomSkip = skip;
-		r.setHeight(r.height() - skip);
-	}
-
-	return false;
-}
-
 void ASurface::plotImage(SpriteResource *sprite, int frameNum, const Common::Point &pt) {
 	SpriteFrame *frame = sprite->getFrame(frameNum);
 	Common::Rect r(pt.x, pt.y, pt.x + frame->w, pt.y + frame->h);
@@ -195,81 +144,7 @@ void ASurface::plotImage(SpriteResource *sprite, int frameNum, const Common::Poi
 	}
 }
 
-void ASurface::transBlitFrom(ASurface *src, const Common::Point &destPos) {
-	if (getPixels() == nullptr)
-		create(w, h);
-
-	for (int yp = 0; yp < src->h; ++yp) {
-		const byte *srcP = (const byte *)src->getBasePtr(0, yp);
-		byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yp);
-
-		for (int xp = 0; xp < this->w; ++xp, ++srcP, ++destP) {
-			if (*srcP != TRANSPARENCY)
-				*destP = *srcP;
-		}
-	}
-}
-
-void ASurface::transBlitFrom(ASurface *src, const Common::Rect &bounds) {
-	const int SCALE_LIMIT = 0x100;
-	int scaleX = SCALE_LIMIT * bounds.width() / src->w;
-	int scaleY = SCALE_LIMIT * bounds.height() / src->h;
-	int scaleXCtr = 0, scaleYCtr = 0;
-
-	for (int yCtr = 0, destY = bounds.top; yCtr < src->h; ++yCtr) {
-		// Handle skipping lines if Y scaling
-		scaleYCtr += scaleY;
-		if (scaleYCtr < SCALE_LIMIT)
-			continue;
-		scaleYCtr -= SCALE_LIMIT;
-
-		// Handle off-screen lines
-		if (destY >= this->h)
-			break;
-
-		if (destY >= 0) {
-			// Handle drawing the line
-			const byte *pSrc = (const byte *)src->getBasePtr(0, yCtr);
-			byte *pDest = (byte *)getBasePtr(bounds.left, destY);
-			scaleXCtr = 0;
-			int x = bounds.left;
-
-			for (int xCtr = 0; xCtr < src->w; ++xCtr, ++pSrc) {
-				// Handle horizontal scaling
-				scaleXCtr += scaleX;
-				if (scaleXCtr < SCALE_LIMIT)
-					continue;
-				scaleXCtr -= SCALE_LIMIT;
-
-				// Only handle on-screen pixels
-				if (x >= this->w)
-					break;
-				if (x >= 0 && *pSrc != 0)
-					*pDest = *pSrc;
-
-				++pDest;
-				++x;
-			}
-		}
-
-		++destY;
-	}
-}
-
-void ASurface::transBlitFrom(ASurface &src) {
-	blitFrom(src);
-}
-
-void ASurface::blitFrom(const Graphics::Surface &src) {
-	assert(w >= src.w && h >= src.h);
-	for (int y = 0; y < src.h; ++y) {
-		const byte *srcP = (const byte *)src.getBasePtr(0, y);
-		byte *destP = (byte *)getBasePtr(0, y);
-		Common::copy(srcP, srcP + src.w, destP);
-	}
-}
-
-void ASurface::copyBuffer(Graphics::Surface *src) {
+void ASurface::copyBuffer(Graphics::ManagedSurface *src) {
 	blitFrom(*src);
 }
 
@@ -282,14 +157,11 @@ void ASurface::plotB(SpriteFrame *frame, const Common::Point &pt) {
 }
 
 void ASurface::sPlotF(SpriteFrame *frame, const Common::Rect &bounds) {
-	transBlitFrom(frame, bounds);
+	transBlitFrom(*frame, Common::Rect(0, 0, frame->w, frame->h), bounds, TRANSPARENCY, false);
 }
 
 void ASurface::sPlotB(SpriteFrame *frame, const Common::Rect &bounds) {
-	ASurface flippedFrame;
-	frame->flipHorizontal(flippedFrame);
-
-	transBlitFrom(&flippedFrame, bounds);
+	transBlitFrom(*frame, Common::Rect(0, 0, frame->w, frame->h), bounds, TRANSPARENCY, true);
 }
 
 void ASurface::copyBlock(ASurface *src, const Common::Rect &bounds) {
@@ -324,22 +196,22 @@ void ASurface::restoreBlock() {
 }
 
 void ASurface::drawRect() {
-	Graphics::Surface::fillRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2), _lColor);
+	Graphics::ManagedSurface::fillRect(Common::Rect(_orgX1, _orgY1, _orgX2, _orgY2), _lColor);
 }
 
 void ASurface::drawLine(int x1, int y1, int x2, int y2, int col) {
-	Graphics::Surface::drawLine(x1, y1, x2, y2, col);
+	Graphics::ManagedSurface::drawLine(x1, y1, x2, y2, col);
 }
 
 void ASurface::drawLine() {
-	Graphics::Surface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
+	Graphics::ManagedSurface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
 }
 
 void ASurface::drawBox() {
-	Graphics::Surface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
-	Graphics::Surface::drawLine(_orgX1, _orgY2, _orgX2, _orgY2, _lColor);
-	Graphics::Surface::drawLine(_orgX2, _orgY1, _orgX2, _orgY1, _lColor);
-	Graphics::Surface::drawLine(_orgX2, _orgY2, _orgX2, _orgY2, _lColor);
+	Graphics::ManagedSurface::drawLine(_orgX1, _orgY1, _orgX2, _orgY1, _lColor);
+	Graphics::ManagedSurface::drawLine(_orgX1, _orgY2, _orgX2, _orgY2, _lColor);
+	Graphics::ManagedSurface::drawLine(_orgX2, _orgY1, _orgX2, _orgY1, _lColor);
+	Graphics::ManagedSurface::drawLine(_orgX2, _orgY2, _orgX2, _orgY2, _lColor);
 }
 
 void ASurface::flipHorizontal(ASurface &dest) {
@@ -373,4 +245,50 @@ void ASurface::moveBufferDown() {
 	Common::copy_backward(p, p + (pitch * (h - TILE_HEIGHT)), p + (pitch * h));
 }
 
+bool ASurface::clip(Common::Rect &r) {
+	int skip;
+	_leftSkip = _rightSkip = 0;
+	_topSkip = _bottomSkip = 0;
+
+	if (r.left > _clipWidth || r.left < 0) {
+		if (r.left >= 0)
+			return true;
+
+		skip = -r.left;
+		r.setWidth(r.width() - skip);
+		_leftSkip = skip;
+		r.moveTo(0, r.top);
+	}
+
+	int right = r.right - 1;
+	if (right < 0)
+		return true;
+	else if (right > _clipWidth) {
+		skip = right - _clipWidth;
+		r.setWidth(r.width() - skip);
+		_rightSkip = skip;
+	}
+
+	if (r.top > _clipHeight || r.top < 0) {
+		if (r.top >= 0)
+			return true;
+
+		skip = -r.top;
+		r.setHeight(r.height() - skip);
+		_topSkip = skip;
+		r.moveTo(r.left, 0);
+	}
+
+	int bottom = r.bottom - 1;
+	if (bottom < 0)
+		return true;
+	else if (bottom > _clipHeight) {
+		skip = bottom - _clipHeight;
+		_bottomSkip = skip;
+		r.setHeight(r.height() - skip);
+	}
+
+	return false;
+}
+
 } // End of namespace Access
diff --git a/engines/access/asurface.h b/engines/access/asurface.h
index dd05c80..ec18ec0 100644
--- a/engines/access/asurface.h
+++ b/engines/access/asurface.h
@@ -27,7 +27,7 @@
 #include "common/array.h"
 #include "common/memstream.h"
 #include "common/rect.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
 #include "access/data.h"
 
 namespace Access {
@@ -35,7 +35,7 @@ namespace Access {
 class SpriteResource;
 class SpriteFrame;
 
-class ASurface : public Graphics::Surface {
+class ASurface : virtual public Graphics::ManagedSurface {
 private:
 	Graphics::Surface _savedBlock;
 
@@ -61,14 +61,8 @@ public:
 
 	virtual ~ASurface();
 
-	void create(uint16 width, uint16 height);
-
-	bool empty() const { return w == 0 || h == 0 || pixels == nullptr; }
-
 	void clearBuffer();
 
-	bool clip(Common::Rect &r);
-
 	void plotImage(SpriteResource *sprite, int frameNum, const Common::Point &pt);
 
 	/**
@@ -102,18 +96,8 @@ public:
 	virtual void drawLine();
 
 	virtual void drawBox();
-	
-	virtual void transBlitFrom(ASurface *src, const Common::Point &destPos);
-
-	virtual void transBlitFrom(ASurface *src, const Common::Rect &bounds);
 
-	virtual void transBlitFrom(ASurface &src);
-
-	virtual void blitFrom(const Graphics::Surface &src);
-
-	virtual void copyBuffer(Graphics::Surface *src);
-
-	virtual void addDirtyRect(const Common::Rect &r) {}
+	virtual void copyBuffer(Graphics::ManagedSurface *src);
 
 	void copyTo(ASurface *dest);
 
@@ -126,6 +110,8 @@ public:
 	void moveBufferUp();
 
 	void moveBufferDown();
+
+	bool clip(Common::Rect &r);
 };
 
 class SpriteFrame : public ASurface {
diff --git a/engines/access/events.cpp b/engines/access/events.cpp
index d62b05c..21ff0d0 100644
--- a/engines/access/events.cpp
+++ b/engines/access/events.cpp
@@ -115,7 +115,7 @@ void EventsManager::setCursor(CursorType cursorId) {
 	}
 }
 
-void EventsManager::setCursorData(Graphics::Surface *src, const Common::Rect &r) {
+void EventsManager::setCursorData(Graphics::ManagedSurface *src, const Common::Rect &r) {
 	_invCursor.create(r.width(), r.height(), Graphics::PixelFormat::createFormatCLUT8());
 	_invCursor.copyRectToSurface(*src, 0, 0, r);
 }
@@ -281,8 +281,7 @@ void EventsManager::nextFrame() {
 	// Give time to the debugger
 	_vm->_debugger->onFrame();
 
-	// TODO: Refactor for dirty rects
-	_vm->_screen->updateScreen();
+	_vm->_screen->update();
 }
 
 void EventsManager::nextTimer() {
diff --git a/engines/access/events.h b/engines/access/events.h
index b8c5f0e..5acbb71 100644
--- a/engines/access/events.h
+++ b/engines/access/events.h
@@ -100,7 +100,7 @@ public:
 	/**
 	 * Set the image for the inventory cursor
 	 */
-	void setCursorData(Graphics::Surface *src, const Common::Rect &r);
+	void setCursorData(Graphics::ManagedSurface *src, const Common::Rect &r);
 
 	/**
 	 * Return the current cursor Id
diff --git a/engines/access/files.cpp b/engines/access/files.cpp
index b9c0f70..48276ee 100644
--- a/engines/access/files.cpp
+++ b/engines/access/files.cpp
@@ -130,13 +130,13 @@ void FileManager::openFile(Resource *res, const Common::String &filename) {
 		error("Could not open file - %s", filename.c_str());
 }
 
-void FileManager::loadScreen(Graphics::Surface *dest, int fileNum, int subfile) {
+void FileManager::loadScreen(Graphics::ManagedSurface *dest, int fileNum, int subfile) {
 	Resource *res = loadFile(fileNum, subfile);
 	handleScreen(dest, res);
 	delete res;
 }
 
-void FileManager::handleScreen(Graphics::Surface *dest, Resource *res) {
+void FileManager::handleScreen(Graphics::ManagedSurface *dest, Resource *res) {
 	_vm->_screen->loadRawPalette(res->_stream);
 	if (_setPaletteFlag)
 		_vm->_screen->setPalette();
@@ -147,20 +147,17 @@ void FileManager::handleScreen(Graphics::Surface *dest, Resource *res) {
 	res->_size -= res->_stream->pos();
 	handleFile(res);
 
-	if (dest != _vm->_screen)
-		dest->w = _vm->_screen->w;
+	Graphics::Surface destSurface = dest->getSubArea(Common::Rect(0, 0,
+		_vm->_screen->w, _vm->_screen->h));
 
-	if (dest->w == dest->pitch) {
-		res->_stream->read((byte *)dest->getPixels(), dest->w * dest->h);
+	if (destSurface.w == destSurface.pitch) {
+		res->_stream->read((byte *)destSurface.getPixels(), destSurface.w * destSurface.h);
 	} else {
-		for (int y = 0; y < dest->h; ++y) {
-			byte *pDest = (byte *)dest->getBasePtr(0, y);
-			res->_stream->read(pDest, dest->w);
+		for (int y = 0; y < destSurface.h; ++y) {
+			byte *pDest = (byte *)destSurface.getBasePtr(0, y);
+			res->_stream->read(pDest, destSurface.w);
 		}
 	}
-
-	if (dest == _vm->_screen)
-		_vm->_screen->addDirtyRect(Common::Rect(0, 0, dest->w, dest->h));
 }
 
 void FileManager::loadScreen(int fileNum, int subfile) {
diff --git a/engines/access/files.h b/engines/access/files.h
index d081934..61fccc2 100644
--- a/engines/access/files.h
+++ b/engines/access/files.h
@@ -26,7 +26,7 @@
 #include "common/scummsys.h"
 #include "common/array.h"
 #include "common/file.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
 #include "access/decompress.h"
 
 namespace Access {
@@ -81,7 +81,7 @@ private:
 	/**
 	 * Handles loading a screen surface and palette with decoded resource
 	 */
-	void handleScreen(Graphics::Surface *dest, Resource *res);
+	void handleScreen(Graphics::ManagedSurface *dest, Resource *res);
 
 	/**
 	* Open up a sub-file container file
@@ -133,7 +133,7 @@ public:
 	/**
 	 * Load a screen resource onto a designated surface
 	 */
-	void loadScreen(Graphics::Surface *dest, int fileNum, int subfile);
+	void loadScreen(Graphics::ManagedSurface *dest, int fileNum, int subfile);
 };
 
 } // End of namespace Access
diff --git a/engines/access/font.cpp b/engines/access/font.cpp
index 8af183f..6ae65e4 100644
--- a/engines/access/font.cpp
+++ b/engines/access/font.cpp
@@ -151,13 +151,12 @@ void Font::drawString(ASurface *s, const Common::String &msg, const Common::Poin
 
 int Font::drawChar(ASurface *s, char c, Common::Point &pt) {
 	Graphics::Surface &ch = _chars[c - ' '];
-
-	s->addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + ch.w, pt.y + ch.h));
+	Graphics::Surface dest = s->getSubArea(Common::Rect(pt.x, pt.y, pt.x + ch.w, pt.y + ch.h));
 
 	// Loop through the lines of the character
 	for (int y = 0; y < ch.h; ++y) {
 		byte *pSrc = (byte *)ch.getBasePtr(0, y);
-		byte *pDest = (byte *)s->getBasePtr(pt.x, pt.y + y);
+		byte *pDest = (byte *)dest.getBasePtr(0, y);
 
 		// Loop through the horizontal pixels of the line
 		for (int x = 0; x < ch.w; ++x, ++pSrc, ++pDest) {
diff --git a/engines/access/screen.cpp b/engines/access/screen.cpp
index aa15abd..9700640 100644
--- a/engines/access/screen.cpp
+++ b/engines/access/screen.cpp
@@ -69,8 +69,6 @@ void Screen::clearScreen() {
 	clearBuffer();
 	if (_vesaMode)
 		_vm->_clearSummaryFlag = true;
-
-	addDirtyRect(Common::Rect(0, 0, this->w, this->h));
 }
 
 void Screen::setDisplayScan() {
@@ -89,28 +87,14 @@ void Screen::setPanel(int num) {
 	_msVirtualOffset = _virtualOffsetsTable[num];
 }
 
-void Screen::updateScreen() {
+void Screen::update() {
 	if (_vm->_startup >= 0) {
 		if (--_vm->_startup == -1)
 			_fadeIn = true;
 		return;
 	}
-
-	// Merge the dirty rects
-	mergeDirtyRects();
-
-	// Loop through copying dirty areas to the physical screen
-	Common::List<Common::Rect>::iterator i;
-	for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
-		const Common::Rect &r = *i;
-		const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
-		g_system->copyRectToScreen(srcP, this->pitch, r.left, r.top,
-			r.width(), r.height());
-	}
-
-	// Signal the physical screen to update
-	g_system->updateScreen();
-	_dirtyRects.clear();
+	markAllDirty();//****DEBUG****
+	Graphics::Screen::update();
 }
 
 void Screen::setInitialPalettte() {
@@ -153,7 +137,7 @@ void Screen::loadRawPalette(Common::SeekableReadStream *stream) {
 
 void Screen::updatePalette() {
 	g_system->getPaletteManager()->setPalette(&_tempPalette[0], 0, PALETTE_COUNT);
-	updateScreen();
+	update();
 }
 
 void Screen::savePalette() {
@@ -293,22 +277,7 @@ void Screen::drawBox() {
 	ASurface::drawBox();
 }
 
-void Screen::transBlitFrom(ASurface *src, const Common::Point &destPos) {
-	addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + src->w, destPos.y + src->h));
-	ASurface::transBlitFrom(src, destPos);
-}
-
-void Screen::transBlitFrom(ASurface *src, const Common::Rect &bounds) {
-	addDirtyRect(bounds);
-	ASurface::transBlitFrom(src, bounds);
-}
-
-void Screen::blitFrom(const Graphics::Surface &src) {
-	addDirtyRect(Common::Rect(0, 0, src.w, src.h));
-	ASurface::blitFrom(src);
-}
-
-void Screen::copyBuffer(Graphics::Surface *src) {
+void Screen::copyBuffer(Graphics::ManagedSurface *src) {
 	addDirtyRect(Common::Rect(0, 0, src->w, src->h));
 	ASurface::copyBuffer(src);
 }
@@ -349,51 +318,7 @@ void Screen::cyclePaletteBackwards() {
 }
 
 void Screen::flashPalette(int count) {
-	warning("TODO: Implement flashPalette");
-}
-
-void Screen::addDirtyRect(const Common::Rect &r) {
-	_dirtyRects.push_back(r);
-	assert(r.isValidRect() && r.width() > 0 && r.height() > 0);
-}
-
-void Screen::mergeDirtyRects() {
-	Common::List<Common::Rect>::iterator rOuter, rInner;
-
-	// Ensure dirty rect list has at least two entries
-	rOuter = _dirtyRects.begin();
-	for (int i = 0; i < 2; ++i, ++rOuter) {
-		if (rOuter == _dirtyRects.end())
-			return;
-	}
-	
-	// Process the dirty rect list to find any rects to merge
-	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
-		rInner = rOuter;
-		while (++rInner != _dirtyRects.end()) {
-
-			if ((*rOuter).intersects(*rInner)) {
-				// these two rectangles overlap or
-				// are next to each other - merge them
-
-				unionRectangle(*rOuter, *rOuter, *rInner);
-
-				// remove the inner rect from the list
-				_dirtyRects.erase(rInner);
-
-				// move back to beginning of list
-				rInner = rOuter;
-			}
-		}
-	}
+	// No implementation needed in ScummVM
 }
 
-bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
-	destRect = src1;
-	destRect.extend(src2);
-
-	return !destRect.isEmpty();
-}
-
-
 } // End of namespace Access
diff --git a/engines/access/screen.h b/engines/access/screen.h
index 6fa0fe3..a022741 100644
--- a/engines/access/screen.h
+++ b/engines/access/screen.h
@@ -26,15 +26,13 @@
 #include "common/scummsys.h"
 #include "common/rect.h"
 #include "common/stream.h"
+#include "graphics/screen.h"
 #include "access/asurface.h"
 
 namespace Access {
 
 class AccessEngine;
 
-#define PALETTE_COUNT 256
-#define PALETTE_SIZE (256 * 3)
-
 struct ScreenSave {
 	int _clipWidth;
 	int _clipHeight;
@@ -47,7 +45,7 @@ struct ScreenSave {
 	int _screenYOff;
 };
 
-class Screen : public ASurface {
+class Screen : public virtual ASurface, public virtual Graphics::Screen {
 private:
 	AccessEngine *_vm;
 	byte _tempPalette[PALETTE_SIZE];
@@ -66,10 +64,6 @@ private:
 	Common::List<Common::Rect> _dirtyRects;
 
 	void updatePalette();
-
-	void mergeDirtyRects();
-
-	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
 public:
 	int _vesaMode;
 	int _startColor, _numColors;
@@ -87,6 +81,11 @@ public:
 	bool _screenChangeFlag;
 	bool _fadeIn;
 public:
+	/**
+	 * Updates the screen
+	 */
+	virtual void update();
+
 	virtual void copyBlock(ASurface *src, const Common::Rect &bounds);
 
 	virtual void restoreBlock();
@@ -95,15 +94,7 @@ public:
 
 	virtual void drawBox();
 
-	virtual void transBlitFrom(ASurface *src, const Common::Point &destPos);
-
-	virtual void transBlitFrom(ASurface *src, const Common::Rect &bounds);
-
-	virtual void blitFrom(const Graphics::Surface &src);
-
-	virtual void copyBuffer(Graphics::Surface *src);
-
-	virtual void addDirtyRect(const Common::Rect &r);
+	virtual void copyBuffer(Graphics::ManagedSurface *src);
 public:
 	Screen(AccessEngine *vm);
 
@@ -114,11 +105,6 @@ public:
 	void setPanel(int num);
 
 	/**
-	 * Update the underlying screen
-	 */
-	void updateScreen();
-
-	/**
 	 * Fade out screen
 	 */
 	void forceFadeOut();
diff --git a/engines/access/video.cpp b/engines/access/video.cpp
index 5fc5f67..e3ff457 100644
--- a/engines/access/video.cpp
+++ b/engines/access/video.cpp
@@ -157,7 +157,7 @@ void VideoPlayer::playVideo() {
 
 	// If the video is playing on the screen surface, add a dirty rect
 	if (_vidSurface == _vm->_screen)
-		_vm->_screen->addDirtyRect(_videoBounds);
+		_vm->_screen->markAllDirty();
 
 	getFrame();
 	if (++_videoFrame == _frameCount) {
diff --git a/engines/access/video/movie_decoder.cpp b/engines/access/video/movie_decoder.cpp
index 05ec25d..1406e54 100644
--- a/engines/access/video/movie_decoder.cpp
+++ b/engines/access/video/movie_decoder.cpp
@@ -719,7 +719,7 @@ bool AccessEngine::playMovie(const Common::String &filename, const Common::Point
 					g_system->getPaletteManager()->setPalette(palette, 0, 256);
 				}
 
-				_screen->updateScreen();
+				_screen->update();
 			}
 		}
 


Commit: b4e3d4abc16d9996651874c8952b1ce846dcb6a1
    https://github.com/scummvm/scummvm/commit/b4e3d4abc16d9996651874c8952b1ce846dcb6a1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-14T20:56:26-04:00

Commit Message:
MADS: Changed engine to use Graphics::ManagedSurface

Changed paths:
    engines/mads/debugger.cpp
    engines/mads/dialogs.cpp
    engines/mads/dragonsphere/dragonsphere_scenes.cpp
    engines/mads/events.cpp
    engines/mads/font.cpp
    engines/mads/game.cpp
    engines/mads/mads.cpp
    engines/mads/mads.h
    engines/mads/menu_views.cpp
    engines/mads/msurface.cpp
    engines/mads/msurface.h
    engines/mads/nebular/dialogs_nebular.cpp
    engines/mads/nebular/menu_nebular.cpp
    engines/mads/nebular/nebular_scenes.cpp
    engines/mads/nebular/nebular_scenes3.cpp
    engines/mads/phantom/phantom_scenes.cpp
    engines/mads/rails.cpp
    engines/mads/scene.cpp
    engines/mads/scene_data.cpp
    engines/mads/screen.cpp
    engines/mads/screen.h
    engines/mads/sequence.cpp
    engines/mads/sprites.cpp
    engines/mads/user_interface.cpp
    engines/mads/user_interface.h



diff --git a/engines/mads/debugger.cpp b/engines/mads/debugger.cpp
index 740c19a..b9731b1 100644
--- a/engines/mads/debugger.cpp
+++ b/engines/mads/debugger.cpp
@@ -158,7 +158,7 @@ bool Debugger::Cmd_ShowCodes(int argc, const char **argv) {
 	Scene &scene = _vm->_game->_scene;
 
 	// Copy the depth/walk surface to the background and flag for screen refresh
-	scene._depthSurface.copyTo(&scene._backgroundSurface);
+	scene._depthSurface.blitFrom(scene._backgroundSurface);
 	scene._spriteSlots.fullRefresh();
 
 	// Draw the locations of scene nodes onto the background
diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp
index d9a1e53..fa656a9 100644
--- a/engines/mads/dialogs.cpp
+++ b/engines/mads/dialogs.cpp
@@ -54,21 +54,19 @@ Dialog::~Dialog() {
 
 void Dialog::save() {
 	_savedSurface = new MSurface(_width, _height);
-	_vm->_screen.copyTo(_savedSurface,
+	_savedSurface->blitFrom(*_vm->_screen,
 		Common::Rect(_position.x, _position.y, _position.x + _width, _position.y + _height),
 		Common::Point());
 
-	_vm->_screen.copyRectToScreen(getBounds());
+//	_vm->_screen->copyRectToScreen(getBounds());
 }
 
 void Dialog::restore() {
 	if (_savedSurface) {
-		_savedSurface->copyTo(&_vm->_screen, _position);
+		_vm->_screen->blitFrom(*_savedSurface, _position);
 		delete _savedSurface;
 		_savedSurface = nullptr;
 
-		_vm->_screen.copyRectToScreen(getBounds());
-
 		Common::copy(&_dialogPalette[0], &_dialogPalette[8 * 3],
 			&_vm->_palette->_mainPalette[248 * 3]);
 		_vm->_palette->setPalette(&_vm->_palette->_mainPalette[248 * 3], 248, 8);
@@ -87,16 +85,16 @@ void Dialog::draw() {
 	// Draw the dialog
 	// Fill entire content of dialog
 	Common::Rect bounds = getBounds();
-	_vm->_screen.fillRect(bounds, TEXTDIALOG_BACKGROUND);
+	_vm->_screen->fillRect(bounds, TEXTDIALOG_BACKGROUND);
 
 	// Draw the outer edge lines
-	_vm->_screen.hLine(_position.x + 1, _position.y + _height - 2,
+	_vm->_screen->hLine(_position.x + 1, _position.y + _height - 2,
 		_position.x + _width - 2, TEXTDIALOG_EDGE);
-	_vm->_screen.hLine(_position.x, _position.y + _height - 1,
+	_vm->_screen->hLine(_position.x, _position.y + _height - 1,
 		_position.x + _width - 1, TEXTDIALOG_EDGE);
-	_vm->_screen.vLine(_position.x + _width - 2, _position.y + 2,
+	_vm->_screen->vLine(_position.x + _width - 2, _position.y + 2,
 		_position.y + _height - 2, TEXTDIALOG_EDGE);
-	_vm->_screen.vLine(_position.x + _width - 1, _position.y + 1,
+	_vm->_screen->vLine(_position.x + _width - 1, _position.y + 1,
 		_position.y + _height - 1, TEXTDIALOG_EDGE);
 
 	// Draw the gravelly dialog content
@@ -125,8 +123,9 @@ void Dialog::calculateBounds() {
 void Dialog::drawContent(const Common::Rect &r, int seed, byte color1, byte color2) {
 	uint16 currSeed = seed ? seed : 0xB78E;
 
+	Graphics::Surface dest = _vm->_screen->getSubArea(r);
 	for (int yp = 0; yp < r.height(); ++yp) {
-		byte *destP = _vm->_screen.getBasePtr(r.left, r.top + yp);
+		byte *destP = (byte *)dest.getBasePtr(0, yp);
 
 		for (int xp = 0; xp < r.width(); ++xp) {
 			uint16 seedAdjust = currSeed;
@@ -326,7 +325,7 @@ void TextDialog::draw() {
 	for (int lineNum = 0; lineNum <= _numLines; ++lineNum) {
 		if (_lineXp[lineNum] == -1) {
 			// Draw a line across the entire dialog
-			_vm->_screen.hLine(_position.x + 2,
+			_vm->_screen->hLine(_position.x + 2,
 				lineYp + (_font->getHeight() + 1)  / 2,
 				_position.x + _width - 4, TEXTDIALOG_BLACK);
 		} else {
@@ -336,21 +335,19 @@ void TextDialog::draw() {
 			if (_lineXp[lineNum] & 0x40)
 				++yp;
 
-			_font->writeString(&_vm->_screen, _lines[lineNum],
+			_font->writeString(_vm->_screen, _lines[lineNum],
 				Common::Point(xp, yp), 1);
 
 			if (_lineXp[lineNum] & 0x80) {
 				// Draw an underline under the text
 				int lineWidth = _font->getWidth(_lines[lineNum], 1);
-				_vm->_screen.hLine(xp, yp + _font->getHeight(), xp + lineWidth,
+				_vm->_screen->hLine(xp, yp + _font->getHeight(), xp + lineWidth,
 					TEXTDIALOG_BLACK);
 			}
 		}
 
 		lineYp += _font->getHeight() + 1;
 	}
-
-	_vm->_screen.copyRectToScreen(getBounds());
 }
 
 void TextDialog::calculateBounds() {
@@ -360,10 +357,10 @@ void TextDialog::calculateBounds() {
 	if (_position.y == -1)
 		_position.y = 100 - (_height / 2);
 
-	if ((_position.x + _width) > _vm->_screen.getWidth())
-		_position.x = _vm->_screen.getWidth() - (_position.x + _width);
-	if ((_position.y + _height) > _vm->_screen.getHeight())
-		_position.y = _vm->_screen.getHeight() - (_position.y + _height);
+	if ((_position.x + _width) > _vm->_screen->w)
+		_position.x = _vm->_screen->w - (_position.x + _width);
+	if ((_position.y + _height) > _vm->_screen->h)
+		_position.y = _vm->_screen->h - (_position.y + _height);
 }
 
 void TextDialog::drawWithInput() {
@@ -452,7 +449,7 @@ FullScreenDialog::FullScreenDialog(MADSEngine *vm) : _vm(vm) {
 }
 
 FullScreenDialog::~FullScreenDialog() {
-	_vm->_screen.resetClipBounds();
+	_vm->_screen->resetClipBounds();
 	_vm->_game->_scene.restrictScene();
 }
 
@@ -491,16 +488,13 @@ void FullScreenDialog::display() {
 	game._trigger = 0;
 
 	// Clear the screen and draw the upper and lower horizontal lines
-	_vm->_screen.empty();
+	_vm->_screen->clear();
 	_vm->_palette->setLowRange();
-	_vm->_screen.hLine(0, 20, MADS_SCREEN_WIDTH, 2);
-	_vm->_screen.hLine(0, 179, MADS_SCREEN_WIDTH, 2);
-	_vm->_screen.resetClipBounds();
-	_vm->_screen.copyRectToScreen(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+	_vm->_screen->hLine(0, 20, MADS_SCREEN_WIDTH, 2);
+	_vm->_screen->hLine(0, 179, MADS_SCREEN_WIDTH, 2);
 
 	// Restrict the screen to the area between the two lines
-	_vm->_screen.setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH,
-		DIALOG_TOP + MADS_SCENE_HEIGHT));
+	_vm->_screen->setClipBounds(Common::Rect(0, DIALOG_TOP, MADS_SCREEN_WIDTH, DIALOG_TOP + MADS_SCENE_HEIGHT));
 	_vm->_game->_scene.restrictScene();
 
 	if (_screenId > 0)
diff --git a/engines/mads/dragonsphere/dragonsphere_scenes.cpp b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
index 938931e..a18d03d 100644
--- a/engines/mads/dragonsphere/dragonsphere_scenes.cpp
+++ b/engines/mads/dragonsphere/dragonsphere_scenes.cpp
@@ -218,7 +218,7 @@ void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, int variant) {
 }
 
 void SceneInfoDragonsphere::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
-	byte *destP = depthSurface.getData();
+	byte *destP = (byte *)depthSurface.getPixels();
 	byte *walkMap = new byte[stream->size()];
 	stream->read(walkMap, stream->size());
 
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
index 7463704..de83260 100644
--- a/engines/mads/events.cpp
+++ b/engines/mads/events.cpp
@@ -98,7 +98,7 @@ void EventsManager::changeCursor() {
 		// Check for hotspot indication pixels along the right-hand and bottom
 		// row. Put together, these give the cursor's hotspot x,y
 		int hotspotX = 0, hotspotY = 0;
-		byte *cursorData = cursor->getData();
+		const byte *cursorData = (const byte *)cursor->getPixels();
 		for (int idx = 0; idx < cursor->w; ++idx) {
 			if (cursorData[(cursor->h - 1) * cursor->w + idx] != transIndex)
 				hotspotX = idx;
@@ -110,7 +110,7 @@ void EventsManager::changeCursor() {
 		// Reduce the cursor data to remove the last column from each row, since
 		// the cursor routines don't have a pitch option
 		byte *destCursor = new byte[(cursor->w - 1) * (cursor->h - 1)];
-		byte *srcP = cursorData;
+		const byte *srcP = cursorData;
 		byte *destP = destCursor;
 
 		for (int idx = 0; idx < (cursor->h - 1); ++idx) {
@@ -217,7 +217,7 @@ bool EventsManager::checkForNextFrameCounter() {
 		_vm->_debugger->onFrame();
 
 		// Display the frame
-		_vm->_screen.updateScreen();
+		_vm->_screen->update();
 
 		// Signal the ScummVM debugger
 		_vm->_debugger->onFrame();
diff --git a/engines/mads/font.cpp b/engines/mads/font.cpp
index 3e6d23f..3828c3d 100644
--- a/engines/mads/font.cpp
+++ b/engines/mads/font.cpp
@@ -167,16 +167,13 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
 		return x;
 
 	int bottom = y + height - 1;
-	if (bottom > surface->getHeight() - 1) {
-		height -= MIN(height, bottom - (surface->getHeight() - 1));
+	if (bottom > surface->h - 1) {
+		height -= MIN(height, bottom - (surface->h - 1));
 	}
 
 	if (height <= 0)
 		return x;
 
-	byte *destPtr = surface->getBasePtr(x, y);
-	uint8 *oldDestPtr = destPtr;
-
 	int xPos = x;
 
 	const char *text = msg.c_str();
@@ -185,10 +182,11 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
 		int charWidth = _charWidths[(byte)theChar];
 
 		if (charWidth > 0) {
-
 			if (xPos + charWidth > xEnd)
 				return xPos;
 
+			Graphics::Surface dest = surface->getSubArea(
+				Common::Rect(xPos, y, xPos + charWidth, y + height));
 			uint8 *charData = &_charData[_charOffs[(byte)theChar]];
 			int bpp = getBpp(charWidth);
 
@@ -196,6 +194,8 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
 				charData += bpp * skipY;
 
 			for (int i = 0; i < height; i++) {
+				byte *destPtr = (byte *)dest.getBasePtr(0, i);
+
 				for (int j = 0; j < bpp; j++) {
 					if (*charData & 0xc0)
 						*destPtr = _fontColors[(*charData & 0xc0) >> 6];
@@ -211,22 +211,13 @@ int Font::writeString(MSurface *surface, const Common::String &msg, const Common
 					destPtr++;
 					charData++;
 				}
-
-				destPtr += surface->getWidth() - bpp * 4;
-
 			}
-
-			destPtr = oldDestPtr + charWidth + spaceWidth;
-			oldDestPtr = destPtr;
-
 		}
 
 		xPos += charWidth + spaceWidth;
-
 	}
 
 	return xPos;
-
 }
 
 int Font::getWidth(const Common::String &msg, int spaceWidth) {
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 8ebea2a..0a6741b 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -498,7 +498,7 @@ void Game::loadGame(int slotNumber) {
 	_scene._currentSceneId = -2;
 	_sectionNumber = _scene._nextSceneId / 100;
 	_scene._frameStartTime = _vm->_events->getFrameCounter();
-	_vm->_screen._shakeCountdown = -1;
+	_vm->_screen->_shakeCountdown = -1;
 
 	// Default the selected inventory item to the first one, if the player has any
 	_scene._userInterface._selectedInvIndex = _objects._inventoryList.size() > 0 ? 0 : -1;
@@ -600,7 +600,8 @@ void Game::createThumbnail() {
 	uint8 thumbPalette[PALETTE_SIZE];
 	_vm->_palette->grabPalette(thumbPalette, 0, PALETTE_COUNT);
 	_saveThumb = new Graphics::Surface();
-	::createThumbnail(_saveThumb, _vm->_screen.getData(), MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette);
+	::createThumbnail(_saveThumb, (const byte *)_vm->_screen->getPixels(),
+		MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT, thumbPalette);
 }
 
 void Game::syncTimers(SyncType slaveType, int slaveId, SyncType masterType, int masterId) {
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index deccb5b..29bcd10 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -94,7 +94,7 @@ void MADSEngine::initialize() {
 	_palette = new Palette(this);
 	Font::init(this);
 	_font = new Font();
-	_screen.init();
+	_screen = new Screen();
 	_sound = new SoundManager(this, _mixer);
 	_audio = new AudioPlayer(_mixer, getGameID());
 	_game = Game::init(this);
@@ -102,7 +102,7 @@ void MADSEngine::initialize() {
 
 	loadOptions();
 
-	_screen.empty();
+	_screen->clear();
 }
 
 void MADSEngine::loadOptions() {
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
index eb808de..52f71f7 100644
--- a/engines/mads/mads.h
+++ b/engines/mads/mads.h
@@ -100,7 +100,7 @@ public:
 	GameConversations * _gameConv;
 	Palette *_palette;
 	Resources *_resources;
-	ScreenSurface _screen;
+	Screen *_screen;
 	SoundManager *_sound;
 	AudioPlayer *_audio;
 	bool _easyMouse;
diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp
index 10d5a21..9050ca6 100644
--- a/engines/mads/menu_views.cpp
+++ b/engines/mads/menu_views.cpp
@@ -253,7 +253,7 @@ void TextView::processCommand() {
 		SceneInfo *sceneInfo = SceneInfo::init(_vm);
 		sceneInfo->_width = MADS_SCREEN_WIDTH;
 		sceneInfo->_height = MADS_SCENE_HEIGHT;
-		_spareScreens[spareIndex].setSize(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+		_spareScreens[spareIndex].create(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
 
 		sceneInfo->loadMadsV1Background(screenId, "", SCENEFLAG_TRANSLATE,
 			_spareScreens[spareIndex]);
@@ -346,9 +346,11 @@ void TextView::doFrame() {
 
 	// If a screen transition is in progress and it's time for another column, handle it
 	if (_spareScreen) {
-		byte *srcP = _spareScreen->getBasePtr(_translationX, 0);
-		byte *bgP = scene._backgroundSurface.getBasePtr(_translationX, 0);
-		byte *screenP = (byte *)_vm->_screen.getBasePtr(_translationX, 0);
+		const byte *srcP = (const byte *)_spareScreen->getBasePtr(_translationX, 0);
+		byte *bgP = (byte *)scene._backgroundSurface.getBasePtr(_translationX, 0);
+
+		Graphics::Surface dest = _vm->_screen->getSubArea(Common::Rect(_translationX, 0, _translationX + 1, 0));
+		byte *screenP = (byte *)dest.getBasePtr(0, 0);
 
 		for (int y = 0; y < MADS_SCENE_HEIGHT; ++y, srcP += MADS_SCREEN_WIDTH,
 			bgP += MADS_SCREEN_WIDTH, screenP += MADS_SCREEN_WIDTH) {
@@ -356,10 +358,6 @@ void TextView::doFrame() {
 			*screenP = *srcP;
 		}
 
-		// Flag the column of the screen is modified
-		_vm->_screen.copyRectToScreen(Common::Rect(_translationX, 0,
-			_translationX + 1, MADS_SCENE_HEIGHT));
-
 		// Keep moving the column to copy to the right
 		if (++_translationX == MADS_SCREEN_WIDTH) {
 			// Surface transition is complete
@@ -571,6 +569,7 @@ void AnimationView::doFrame() {
 void AnimationView::loadNextResource() {
 	Scene &scene = _vm->_game->_scene;
 	Palette &palette = *_vm->_palette;
+	Screen &screen = *_vm->_screen;
 	ResourceEntry &resEntry = _resources[_resourceIndex];
 	Common::Array<PaletteCycle> paletteCycles;
 
@@ -587,12 +586,15 @@ void AnimationView::loadNextResource() {
 	// Handle the bars at the top/bottom
 	if (resEntry._showWhiteBars) {
 		// For animations the screen has been clipped to the middle 156 rows.
-		// So although it's slightly messy, bypass our screen class entirely,
-		// and draw the horizontal lines directly on the physiacl screen surface
-		Graphics::Surface *s = g_system->lockScreen();
-		s->hLine(0, 20, MADS_SCREEN_WIDTH, 253);
-		s->hLine(0, 179, MADS_SCREEN_WIDTH, 253);
-		g_system->unlockScreen();
+		// So although it's slightly messy, temporarily reset clip bounds
+		// so we can redraw the white lines
+		Common::Rect clipBounds = screen.getClipBounds();
+		screen.resetClipBounds();
+
+		screen.hLine(0, 20, MADS_SCREEN_WIDTH, 253);
+		screen.hLine(0, 179, MADS_SCREEN_WIDTH, 253);
+
+		screen.setClipBounds(clipBounds);
 	}
 
 	// Load the new animation
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index f768624..40c69c0 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -32,37 +32,6 @@ namespace MADS {
 
 MADSEngine *MSurface::_vm = nullptr;
 
-MSurface::MSurface() {
-	pixels = nullptr;
-	_freeFlag = false;
-}
-
-MSurface::MSurface(int width, int height) {
-	pixels = nullptr;
-	_freeFlag = false;
-	setSize(width, height);
-}
-
-MSurface::~MSurface() {
-	if (_freeFlag)
-		Graphics::Surface::free();
-}
-
-void MSurface::setSize(int width, int height) {
-	if (_freeFlag)
-		Graphics::Surface::free();
-	Graphics::Surface::create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-	_freeFlag = true;
-}
-
-void MSurface::setPixels(byte *pData, int horizSize, int vertSize) {
-	_freeFlag = false;
-	pixels = pData;
-	w = pitch = horizSize;
-	h = vertSize;
-	format.bytesPerPixel = 1;
-}
-
 int MSurface::scaleValue(int value, int scale, int err) {
 	int scaled = 0;
 	while (value--) {
@@ -76,7 +45,6 @@ int MSurface::scaleValue(int value, int scale, int err) {
 }
 
 void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect) {
-
 	enum {
 		kStatusSkip,
 		kStatusScale,
@@ -116,8 +84,8 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
 		return;
 	int heightAmt = scaledHeight;
 
-	byte *src = info.sprite->getData();
-	byte *dst = getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY);
+	const byte *src = (const byte *)info.sprite->getPixels();
+	byte *dst = (byte *)getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY);
 
 	int status = kStatusSkip;
 	byte *scaledLineBuf = new byte[scaledWidth];
@@ -138,7 +106,7 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
 				byte *lineDst = scaledLineBuf;
 				int curErrX = errX;
 				int width = scaledWidth;
-				byte *tempSrc = src;
+				const byte *tempSrc = src;
 				int startX = clipX;
 				while (width > 0) {
 					byte pixel = *tempSrc++;
@@ -201,63 +169,136 @@ void MSurface::drawSprite(const Common::Point &pt, SpriteInfo &info, const Commo
 	}
 
 	delete[] scaledLineBuf;
-
 }
 
-void MSurface::empty() {
-	Common::fill(getBasePtr(0, 0), getBasePtr(0, h), 0);
+void MSurface::scrollX(int xAmount) {
+	if (xAmount == 0)
+		return;
+
+	byte buffer[80];
+	int direction = (xAmount > 0) ? -1 : 1;
+	int xSize = ABS(xAmount);
+	assert(xSize <= 80);
+
+	byte *srcP = (byte *)getBasePtr(0, 0);
+
+	for (int y = 0; y < this->h; ++y, srcP += pitch) {
+		if (direction < 0) {
+			// Copy area to be overwritten
+			Common::copy(srcP, srcP + xSize, &buffer[0]);
+			// Shift the remainder of the line over the given area
+			Common::copy(srcP + xSize, srcP + this->w, srcP);
+			// Move buffered area to the end of the line
+			Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize);
+		} else {
+			// Copy area to be overwritten
+			Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]);
+			// Shift the remainder of the line over the given area
+			Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w);
+			// Move buffered area to the start of the line
+			Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
+		}
+	}
+
+	markAllDirty();
 }
 
-void MSurface::copyFrom(MSurface *src, const Common::Rect &srcBounds,
-		const Common::Point &destPos, int transparentColor) {
-	// Validation of the rectangle and position
-	int destX = destPos.x, destY = destPos.y;
-	if ((destX >= w) || (destY >= h))
+void MSurface::scrollY(int yAmount) {
+	if (yAmount == 0)
 		return;
 
-	Common::Rect copyRect = srcBounds;
-	if (destX < 0) {
-		copyRect.left += -destX;
-		destX = 0;
-	} else if (destX + copyRect.width() > w) {
-		copyRect.right -= destX + copyRect.width() - w;
-	}
-	if (destY < 0) {
-		copyRect.top += -destY;
-		destY = 0;
-	} else if (destY + copyRect.height() > h) {
-		copyRect.bottom -= destY + copyRect.height() - h;
+	int direction = (yAmount > 0) ? 1 : -1;
+	int ySize = ABS(yAmount);
+	assert(ySize < (this->h / 2));
+	assert(this->w == pitch);
+
+	int blockSize = ySize * this->w;
+	byte *tempData = new byte[blockSize];
+	byte *pixelsP = (byte *)getBasePtr(0, 0);
+
+	if (direction > 0) {
+		// Buffer the lines to be overwritten
+		byte *srcP = (byte *)getBasePtr(0, this->h - ySize);
+		Common::copy(srcP, srcP + (pitch * ySize), tempData);
+		// Vertically shift all the lines
+		Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)),
+			pixelsP + (pitch * this->h));
+		// Transfer the buffered lines top the top of the screen
+		Common::copy(tempData, tempData + blockSize, pixelsP);
+	} else {
+		// Buffer the lines to be overwritten
+		Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
+		// Vertically shift all the lines
+		Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP);
+		// Transfer the buffered lines to the bottom of the screen
+		Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize)));
 	}
 
-	if (!copyRect.isValidRect())
-		return;
+	markAllDirty();
+	delete[] tempData;
+}
 
-	// Copy the specified area
+void MSurface::translate(Common::Array<RGB6> &palette) {
+	for (int y = 0; y < this->h; ++y) {
+		byte *pDest = (byte *)getBasePtr(0, y);
+
+		for (int x = 0; x < this->w; ++x, ++pDest) {
+			if (*pDest < 255)	// scene 752 has some palette indices of 255
+				*pDest = palette[*pDest]._palIndex;
+		}
+	}
 
-	byte *data = src->getData();
-	byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
-	byte *destPtr = (byte *)pixels + (destY * getWidth()) + destX;
+	markAllDirty();
+}
 
-	for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
-		if (transparentColor == -1) {
-			// No transparency, so copy line over
-			Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr);
-		} else {
-			// Copy each byte one at a time checking for the transparency color
-			for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr)
-				if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr];
+void MSurface::translate(byte map[PALETTE_COUNT]) {
+	for (int y = 0; y < this->h; ++y) {
+		byte *pDest = (byte *)getBasePtr(0, y);
+
+		for (int x = 0; x < this->w; ++x, ++pDest) {
+				*pDest = map[*pDest];
 		}
+	}
+
+	markAllDirty();
+}
+
+MSurface *MSurface::flipHorizontal() const {
+	MSurface *dest = new MSurface(this->w, this->h);
+
+	for (int y = 0; y < this->h; ++y) {
+		const byte *srcP = getBasePtr(this->w - 1, y);
+		byte *destP = dest->getBasePtr(0, y);
 
-		srcPtr += src->getWidth();
-		destPtr += getWidth();
+		for (int x = 0; x < this->w; ++x)
+			*destP++ = *srcP--;
+	}
+
+	return dest;
+}
+
+void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
+		const Common::Point &destPos, const Common::Rect &srcRect) {
+	// Loop through the lines
+	for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
+		const byte *srcP = (const byte *)srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr);
+		byte *destP = (byte *)getBasePtr(destPos.x, destPos.y + yCtr);
+
+		// Copy the line over
+		for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) {
+			*destP = paletteMap[*srcP];
+		}
 	}
+
+	addDirtyRect(Common::Rect(destPos.x, destPos.y, destPos.x + srcRect.width(),
+		destPos.y + srcRect.height()));
 }
 
-void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
+void MSurface::copyFrom(MSurface &src, const Common::Point &destPos, int depth,
 	DepthSurface *depthSurface, int scale, bool flipped, int transparentColor) {
 	int destX = destPos.x, destY = destPos.y;
-	int frameWidth = src->getWidth();
-	int frameHeight = src->getHeight();
+	int frameWidth = src.w;
+	int frameHeight = src.h;
 	int direction = flipped ? -1 : 1;
 
 	int highestDim = MAX(frameWidth, frameHeight);
@@ -271,7 +312,8 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 			distCtr += scale;
 			if (distCtr < 100) {
 				lineDist[distIndex] = false;
-			} else {
+			}
+			else {
 				lineDist[distIndex] = true;
 				distCtr -= 100;
 
@@ -290,18 +332,20 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 	// Special case for quicker drawing of non-scaled images
 	if (scale == 100 || scale == -1) {
 		// Copy the specified area
-		Common::Rect copyRect(0, 0, src->getWidth(), src->getHeight());
+		Common::Rect copyRect(0, 0, src.w, src.h);
 
 		if (destX < 0) {
 			copyRect.left += -destX;
 			destX = 0;
-		} else if (destX + copyRect.width() > w) {
+		}
+		else if (destX + copyRect.width() > w) {
 			copyRect.right -= destX + copyRect.width() - w;
 		}
 		if (destY < 0) {
 			copyRect.top += -destY;
 			destY = 0;
-		} else if (destY + copyRect.height() > h) {
+		}
+		else if (destY + copyRect.height() > h) {
 			copyRect.bottom -= destY + copyRect.height() - h;
 		}
 
@@ -311,9 +355,9 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 		if (flipped)
 			copyRect.moveTo(0, copyRect.top);
 
-		byte *data = src->getData();
-		byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
-		byte *destPtr = (byte *)pixels + (destY * pitch) + destX;
+		byte *data = src.getPixels();
+		byte *srcPtr = data + (src.w * copyRect.top + copyRect.left);
+		byte *destPtr = (byte *)getPixels() + (destY * pitch) + destX;
 		if (flipped)
 			srcPtr += copyRect.width() - 1;
 
@@ -329,18 +373,18 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 					destPtr[xCtr] = *srcP;
 			}
 
-			srcPtr += src->getWidth();
-			destPtr += getWidth();
+			srcPtr += src.w;
+			destPtr += this->w;
 		}
 
 		return;
 	}
 
 	// Start of draw logic for scaled sprites
-	const byte *srcPixelsP = src->getData();
+	const byte *srcPixelsP = src.getPixels();
 
-	int destRight = this->getWidth() - 1;
-	int destBottom = this->getHeight() - 1;
+	int destRight = this->w - 1;
+	int destBottom = this->h - 1;
 
 	// Check x bounding area
 	int spriteLeft = 0;
@@ -387,7 +431,7 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 	spriteLeft = spriteLeft * direction;
 
 	// Loop through the lines of the sprite
-	for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) {
+	for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src.pitch) {
 		if (!lineDist[yp])
 			// Not a display line, so skip it
 			continue;
@@ -411,8 +455,8 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 				continue;
 
 			// Get depth of current output pixel in depth surface
-			Common::Point pt((destP - (byte *)this->pixels) % this->pitch,
-				(destP - (byte *)this->pixels) / this->pitch);
+			Common::Point pt((destP - (byte *)getPixels()) % this->pitch,
+				(destP - (byte *)getPixels()) / this->pitch);
 			int pixelDepth = (depthSurface == nullptr) ? 15 : depthSurface->getDepth(pt);
 
 			if ((*srcP != transparentColor) && (depth <= pixelDepth))
@@ -424,119 +468,8 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
 		// Move to the next destination line
 		destPixelsP += this->pitch;
 	}
-}
-
-void MSurface::scrollX(int xAmount) {
-	if (xAmount == 0)
-		return;
-
-	byte buffer[80];
-	int direction = (xAmount > 0) ? -1 : 1;
-	int xSize = ABS(xAmount);
-	assert(xSize <= 80);
-
-	byte *srcP = getBasePtr(0, 0);
-
-	for (int y = 0; y < this->h; ++y, srcP += pitch) {
-		if (direction < 0) {
-			// Copy area to be overwritten
-			Common::copy(srcP, srcP + xSize, &buffer[0]);
-			// Shift the remainder of the line over the given area
-			Common::copy(srcP + xSize, srcP + this->w, srcP);
-			// Move buffered area to the end of the line
-			Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize);
-		} else {
-			// Copy area to be overwritten
-			Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]);
-			// Shift the remainder of the line over the given area
-			Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w);
-			// Move buffered area to the start of the line
-			Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
-		}
-	}
-}
-
-void MSurface::scrollY(int yAmount) {
-	if (yAmount == 0)
-		return;
-
-	int direction = (yAmount > 0) ? 1 : -1;
-	int ySize = ABS(yAmount);
-	assert(ySize < (this->h / 2));
-	assert(this->w == pitch);
-
-	int blockSize = ySize * this->w;
-	byte *tempData = new byte[blockSize];
-	byte *pixelsP = getBasePtr(0, 0);
-
-	if (direction > 0) {
-		// Buffer the lines to be overwritten
-		byte *srcP = (byte *)getBasePtr(0, this->h - ySize);
-		Common::copy(srcP, srcP + (pitch * ySize), tempData);
-		// Vertically shift all the lines
-		Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)),
-			pixelsP + (pitch * this->h));
-		// Transfer the buffered lines top the top of the screen
-		Common::copy(tempData, tempData + blockSize, pixelsP);
-	} else {
-		// Buffer the lines to be overwritten
-		Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
-		// Vertically shift all the lines
-		Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP);
-		// Transfer the buffered lines to the bottom of the screen
-		Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize)));
-	}
-
-	delete[] tempData;
-}
-
-void MSurface::translate(Common::Array<RGB6> &palette) {
-	for (int y = 0; y < this->h; ++y) {
-		byte *pDest = getBasePtr(0, y);
-
-		for (int x = 0; x < this->w; ++x, ++pDest) {
-			if (*pDest < 255)	// scene 752 has some palette indices of 255
-				*pDest = palette[*pDest]._palIndex;
-		}
-	}
-}
-
-void MSurface::translate(byte map[PALETTE_COUNT]) {
-	for (int y = 0; y < this->h; ++y) {
-		byte *pDest = getBasePtr(0, y);
-
-		for (int x = 0; x < this->w; ++x, ++pDest) {
-				*pDest = map[*pDest];
-		}
-	}
-}
-
-MSurface *MSurface::flipHorizontal() const {
-	MSurface *dest = new MSurface(this->w, this->h);
-
-	for (int y = 0; y < this->h; ++y) {
-		const byte *srcP = getBasePtr(this->w - 1, y);
-		byte *destP = dest->getBasePtr(0, y);
-
-		for (int x = 0; x < this->w; ++x)
-			*destP++ = *srcP--;
-	}
-
-	return dest;
-}
-
-void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
-		const Common::Point &destPos, const Common::Rect &srcRect) {
-	// Loop through the lines
-	for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) {
-		const byte *srcP = srcSurface.getBasePtr(srcRect.left, srcRect.top + yCtr);
-		byte *destP = getBasePtr(destPos.x, destPos.y + yCtr);
 
-		// Copy the line over
-		for (int xCtr = 0; xCtr < srcRect.width(); ++xCtr, ++srcP, ++destP) {
-			*destP = paletteMap[*srcP];
-		}
-	}
+	addDirtyRect(Common::Rect(destX, destY, destX + frameWidth, destY + frameHeight));
 }
 
 /*------------------------------------------------------------------------*/
@@ -544,26 +477,26 @@ void MSurface::copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
 int DepthSurface::getDepth(const Common::Point &pt) {
 	if (_depthStyle == 2) {
 		int bits = (3 - (pt.x % 4)) * 2;
-		byte v = *getBasePtr(pt.x >> 2, pt.y);
+		byte v = *(const byte *)getBasePtr(pt.x >> 2, pt.y);
 		return v >> bits;
 	} else {
 		if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h)
 			return 0;
 
-		return *getBasePtr(pt.x, pt.y) & 0xF;
+		return *(const byte *)getBasePtr(pt.x, pt.y) & 0xF;
 	}
 }
 
 int DepthSurface::getDepthHighBit(const Common::Point &pt) {
 	if (_depthStyle == 2) {
 		int bits = (3 - (pt.x % 4)) * 2;
-		byte v = *getBasePtr(pt.x >> 2, pt.y);
+		byte v = *(const byte *)getBasePtr(pt.x >> 2, pt.y);
 		return (v >> bits) & 2;
 	} else {
 		if (pt.x < 0 || pt.y < 0 || pt.x >= this->w || pt.y >= this->h)
 			return 0;
 
-		return *getBasePtr(pt.x, pt.y) & 0x80;
+		return *(const byte *)getBasePtr(pt.x, pt.y) & 0x80;
 	}
 }
 
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index 8930737..e927709 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -25,7 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/rect.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
 #include "mads/palette.h"
 
 namespace MADS {
@@ -50,10 +50,14 @@ struct SpriteInfo {
 /*
  * MADS graphics surface
  */
-class MSurface : public Graphics::Surface {
+class MSurface : virtual public Graphics::ManagedSurface {
+private:
+	/**
+	 * Helper method for calculating new dimensions when scaling a sprite
+	 */
+	int scaleValue(int value, int scale, int err);
 protected:
 	static MADSEngine *_vm;
-	bool _freeFlag;
 public:
 	/**
 	 * Sets the engine reference used all surfaces
@@ -61,11 +65,6 @@ public:
 	static void setVm(MADSEngine *vm) { _vm = vm; }
 
 	/**
-	 * Helper method for calculating new dimensions when scaling a sprite
-	 */
-	static int scaleValue(int value, int scale, int err);
-
-	/**
 	* Base method for descendents to load their contents
 	*/
 	virtual void load(const Common::String &resName) {}
@@ -73,126 +72,50 @@ public:
 	/**
 	 * Basic constructor
 	 */
-	MSurface();
+	MSurface() : Graphics::ManagedSurface() {}
 
 	/**
 	 * Constructor for a surface with fixed dimensions
 	 */
-	MSurface(int width, int height);
+	MSurface(int width, int height) : Graphics::ManagedSurface(width, height) {}
 
 	/**
 	 * Destructor
 	 */
-	virtual ~MSurface();
-
-	/**
-	 * Reinitializes a surface to have a given set of dimensions
-	 */
-	void setSize(int width, int height);
-
-	/**
-	 * Sets the pixels the surface is associated with
-	 * @remarks		The surface will not free the data block
-	 */
-	void setPixels(byte *pData, int horizSize, int vertSize);
-
-	/**
-	 * Draws an arbitrary line on the screen using a specified color
-	 * @param startPos		Starting position
-	 * @param endPos		Ending position
-	 * @param color			Color to use
-	 */
-	void line(const Common::Point &startPos, const Common::Point &endPos, byte color);
-
-	/**
-	 * Draws a sprite
-	 * @param pt		Position to draw sprite at
-	 * @param info		General sprite details
-	 * @param clipRect	Clipping rectangle to constrain sprite drawing within
-	 */
-	void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect);
-
-	/**
-	 * Returns the width of the surface
-	 */
-	int getWidth() const { return w; }
-
-	/**
-	 * Returns the height of the surface
-	 */
-	int getHeight() const { return h; }
+	virtual ~MSurface() {}
 
 	/**
-	 * Returns the size of the surface as a Rect
+	 * Return a rect containing the bounds of the surface
 	 */
-	Common::Rect getBounds() const {
-		return Common::Rect(0, 0, w, h);
-	}
+	Common::Rect getBounds() { return Common::Rect(0, 0, this->w, this->h); }
 
 	/**
-	 * Returns a pointer to the surface data
+	 * Return the pixels for the surface
 	 */
-	byte *getData() { return (byte *)Graphics::Surface::getPixels(); }
+	inline byte *getPixels() { return (byte *)Graphics::ManagedSurface::getPixels(); }
 
 	/**
-	 * Returns a pointer to a given position within the surface
+	 * Return the pixels for the surface
 	 */
-	byte *getBasePtr(int x, int y) { return (byte *)Graphics::Surface::getBasePtr(x, y); }
+	inline const void *getPixels() const { return (const byte *)Graphics::ManagedSurface::getPixels(); }
 
 	/**
-	* Returns a pointer to a given position within the surface
-	*/
-	const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::Surface::getBasePtr(x, y); }
-
-	/**
-	 * Clears the surface
-	 */
-	void empty();
-
-	/**
-	 * Copys a sub-section of another surface into the current one.
-	 * @param src			Source surface
-	 * @param srcBounds		Area of source surface to copy
-	 * @param destPos		Destination position to draw in current surface
-	 * @param transparentColor	Transparency palette index
-	 */
-	void copyFrom(MSurface *src, const Common::Rect &srcBounds, const Common::Point &destPos,
-		int transparentColor = -1);
-
-	/**
-	* Copys a sub-section of another surface into the current one.
-	* @param src			Source surface
-	* @param destPos		Destination position to draw in current surface
-	* @param depth			Depth of sprite
-	* @param depthSurface	Depth surface to use with sprite depth
-	* @param scale			Scale for image
-	* @param flipped		Flag for whether image is to be flipped
-	* @param transparentColor	Transparency palette index
-	*/
-	void copyFrom(MSurface *src, const Common::Point &destPos, int depth, DepthSurface *depthSurface,
-		int scale, bool flipped, int transparentColor = -1);
-
-	/**
-	 * Copies the surface to a given destination surface
+	 * Return a pointer to a given position on the surface
 	 */
-	void copyTo(MSurface *dest, int transparentColor = -1) {
-		dest->copyFrom(this, Common::Rect(w, h), Common::Point(), transparentColor);
-	}
+	byte *getBasePtr(int x, int y) { return (byte *)Graphics::ManagedSurface::getBasePtr(x, y); }
 
 	/**
-	 * Copies the surface to a given destination surface
+	 * Return a pointer to a given position on the surface
 	 */
-	void copyTo(MSurface *dest, const Common::Point &pt, int transparentColor = -1) {
-		dest->copyFrom(this, Common::Rect(w, h), pt, transparentColor);
-	}
+	inline const byte *getBasePtr(int x, int y) const { return (const byte *)Graphics::ManagedSurface::getBasePtr(x, y); }
 
 	/**
-	 * Copies the surface to a given destination surface
+	 * Draws a sprite
+	 * @param pt		Position to draw sprite at
+	 * @param info		General sprite details
+	 * @param clipRect	Clipping rectangle to constrain sprite drawing within
 	 */
-	void copyTo(MSurface *dest, const Common::Rect &srcBounds, const Common::Point &destPos,
-				int transparentColor = -1) {
-		dest->copyFrom(this, srcBounds, destPos, transparentColor);
-	}
+	void drawSprite(const Common::Point &pt, SpriteInfo &info, const Common::Rect &clipRect);
 
 	/**
 	 * Scroll the screen horizontally by a given amount
@@ -227,6 +150,19 @@ public:
 	 */
 	void copyRectTranslate(MSurface &srcSurface, const byte *paletteMap,
 		const Common::Point &destPos, const Common::Rect &srcRect);
+
+	/**
+	 * Copys a sub-section of another surface into the current one.
+	 * @param src			Source surface
+	 * @param destPos		Destination position to draw in current surface
+	 * @param depth			Depth of sprite
+	 * @param depthSurface	Depth surface to use with sprite depth
+	 * @param scale			Scale for image
+	 * @param flipped		Flag for whether image is to be flipped
+	 * @param transparentColor	Transparency palette index
+	 */
+	void copyFrom(MSurface &src, const Common::Point &destPos, int depth, DepthSurface *depthSurface,
+		int scale, bool flipped, int transparentColor = -1);
 };
 
 class DepthSurface : public MSurface {
@@ -239,7 +175,7 @@ public:
 	/**
 	 * Constructor
 	 */
-	DepthSurface() : _depthStyle(0) {}
+	DepthSurface() : MSurface(), _depthStyle(0) {}
 
 	/**
 	 * Returns the depth at a given position
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
index 58e60fe..2af80f5 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -438,11 +438,10 @@ void CopyProtectionDialog::show() {
 	Common::KeyState curKey;
 	const Common::Rect inputArea(110, 165, 210, 175);
 	MSurface *origInput = new MSurface(inputArea.width(), inputArea.height());
-	_vm->_screen.frameRect(inputArea, TEXTDIALOG_BLACK);
-	_vm->_screen.copyTo(origInput, inputArea, Common::Point(0, 0));
-	_font->setColors(TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE);
-	_vm->_screen.copyRectToScreen(inputArea);
-	_vm->_screen.updateScreen();
+	_vm->_screen->frameRect(inputArea, TEXTDIALOG_BLACK);
+	origInput->blitFrom(*_vm->_screen, inputArea, Common::Point(0, 0));
+		_font->setColors(TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE);
+	_vm->_screen->update();
 
 	bool firstTime = true;
 
@@ -470,11 +469,10 @@ void CopyProtectionDialog::show() {
 			_textInput = _hogEntry._word[0];
 		}
 
-		_vm->_screen.copyFrom(origInput, Common::Rect(0, 0, inputArea.width(), inputArea.height()), Common::Point(inputArea.left, inputArea.top));
-		_font->writeString(&_vm->_screen, _textInput,
+		_vm->_screen->blitFrom(*origInput, Common::Point(inputArea.left, inputArea.top));
+		_font->writeString(_vm->_screen, _textInput,
 			Common::Point(inputArea.left + 2, inputArea.top + 1), 1);
-		_vm->_screen.copyRectToScreen(inputArea);
-		_vm->_screen.updateScreen();
+		_vm->_screen->update();
 	}
 
 	origInput->free();
@@ -537,7 +535,7 @@ void PictureDialog::save() {
 
 	// Save the entire screen
 	_savedSurface = new MSurface(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
-	_vm->_screen.copyTo(_savedSurface);
+	_savedSurface->blitFrom(*_vm->_screen);
 
 	// Save palette information
 	Common::copy(&palette._mainPalette[0], &palette._mainPalette[PALETTE_SIZE], &_palette[0]);
@@ -568,7 +566,7 @@ void PictureDialog::save() {
 
 	// Remap the greyed out screen to use the small greyscale range
 	// at the top end of the palette
-	_vm->_screen.translate(map);
+	_vm->_screen->translate(map);
 
 	// Load the inventory picture
 	Common::String setName = Common::String::format("*OB%.3d.SS", _objectId);
@@ -578,13 +576,12 @@ void PictureDialog::save() {
 	// Get the inventory frame, and adjust the dialog position to allow for it
 	MSprite *frame = asset->getFrame(0);
 	_position.y = frame->h + 12;
-	if ((_position.y + _height) > _vm->_screen.getHeight())
-		_position.y -= (_position.y + _height) - _vm->_screen.getHeight();
+	if ((_position.y + _height) > _vm->_screen->h)
+		_position.y -= (_position.y + _height) - _vm->_screen->h;
 
 	// Draw the inventory picture
-	frame->copyTo(&_vm->_screen, Common::Point(160 - frame->w / 2, 6),
+	_vm->_screen->transBlitFrom(*frame, Common::Point(160 - frame->w / 2, 6),
 		frame->getTransparencyIndex());
-	_vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
 
 	// Adjust the dialog colors to use
 	TEXTDIALOG_CONTENT1 -= 10;
@@ -598,13 +595,11 @@ void PictureDialog::save() {
 
 void PictureDialog::restore() {
 	if (_savedSurface) {
-		_savedSurface->copyTo(&_vm->_screen);
+		_vm->_screen->blitFrom(*_savedSurface);
 		_savedSurface->free();
 		delete _savedSurface;
 		_savedSurface = nullptr;
 
-		_vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
-
 		// Restore palette information
 		Palette &palette = *_vm->_palette;
 		Common::copy(&_palette[0], &_palette[PALETTE_SIZE], &palette._mainPalette[0]);
@@ -691,7 +686,6 @@ void GameDialog::display() {
 }
 
 GameDialog::~GameDialog() {
-	_vm->_screen.resetClipBounds();
 	_vm->_game->_scene._currentSceneId = RETURNING_FROM_DIALOG;
 }
 
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index 0520294..cd81efe 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -384,8 +384,8 @@ void AdvertView::show() {
 	// Load the advert background onto the screen
 	SceneInfo *sceneInfo = SceneInfo::init(_vm);
 	sceneInfo->load(screenId, 0, Common::String(), 0, _vm->_game->_scene._depthSurface,
-		_vm->_screen);
-	_vm->_screen.copyRectToScreen(_vm->_screen.getBounds());
+		*_vm->_screen);
+	_vm->_screen->markAllDirty();
 	_vm->_palette->setFullPalette(_vm->_palette->_mainPalette);
 
 	delete sceneInfo;
diff --git a/engines/mads/nebular/nebular_scenes.cpp b/engines/mads/nebular/nebular_scenes.cpp
index da419a7..40228b4 100644
--- a/engines/mads/nebular/nebular_scenes.cpp
+++ b/engines/mads/nebular/nebular_scenes.cpp
@@ -323,8 +323,8 @@ void SceneInfoNebular::loadCodes(MSurface &depthSurface, int variant) {
 }
 
 void SceneInfoNebular::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
-	byte *destP = depthSurface.getData();
-	byte *endP = depthSurface.getBasePtr(0, depthSurface.h);
+	byte *destP = (byte *)depthSurface.getPixels();
+	byte *endP = (byte *)depthSurface.getBasePtr(0, depthSurface.h);
 
 	byte runLength = stream->readByte();
 	while (destP < endP && runLength > 0) {
diff --git a/engines/mads/nebular/nebular_scenes3.cpp b/engines/mads/nebular/nebular_scenes3.cpp
index 0fb13a7..7323ee8 100644
--- a/engines/mads/nebular/nebular_scenes3.cpp
+++ b/engines/mads/nebular/nebular_scenes3.cpp
@@ -2818,7 +2818,7 @@ void Scene318::step() {
 
 		if (_internCounter >= 3600) {
 			_vm->_sound->command(59);
-			_vm->_screen._shakeCountdown = 20;
+			_vm->_screen->_shakeCountdown = 20;
 			_internWalkingFl = true;
 		}
 	}
@@ -3288,22 +3288,22 @@ void Scene319::step() {
 
 		if (_animMode == 2) {
 			if (_animFrame == 13)
-				_vm->_screen._shakeCountdown = 40;
+				_vm->_screen->_shakeCountdown = 40;
 
 			if (_animFrame == 16)
-				_vm->_screen._shakeCountdown = 1;
+				_vm->_screen->_shakeCountdown = 1;
 		}
 
 		if (_animMode == 3) {
 			if (_animFrame == 11)
-				_vm->_screen._shakeCountdown = 60;
+				_vm->_screen->_shakeCountdown = 60;
 
 			if (_animFrame == 18)
-				_vm->_screen._shakeCountdown = 1;
+				_vm->_screen->_shakeCountdown = 1;
 		}
 
 		if ((_animMode == 4) && (_animFrame == 16))
-			_vm->_screen._shakeCountdown = 80;
+			_vm->_screen->_shakeCountdown = 80;
 
 		if ((nextFrame >= 0) && (nextFrame != _scene->_animation[0]->getCurrentFrame())) {
 			_scene->_animation[0]->setCurrentFrame(nextFrame);
@@ -3326,7 +3326,7 @@ void Scene319::step() {
 
 		_animFrame = _scene->_animation[0]->getCurrentFrame();
 		_slacheTalkingFl = true;
-		_vm->_screen._shakeCountdown = 1;
+		_vm->_screen->_shakeCountdown = 1;
 
 		for (int i = 0; i <= 1; i++) {
 			int oldIdx = _globals._sequenceIndexes[i];
@@ -3350,7 +3350,7 @@ void Scene319::step() {
 		_vm->_palette->setColorValues(0, 0, 0);
 		_vm->_palette->fadeOut(_vm->_palette->_mainPalette, nullptr, 18, 228,
 			248, 0, 1, 16);
-		_vm->_screen._shakeCountdown = 1;
+		_vm->_screen->_shakeCountdown = 1;
 		_scene->_reloadSceneFlag = true;
 		break;
 
@@ -3731,7 +3731,7 @@ void Scene320::step() {
 
 			case 417:
 			case 457:
-				_vm->_screen._shakeCountdown = 40;
+				_vm->_screen->_shakeCountdown = 40;
 				_vm->_sound->command(59);
 				break;
 
diff --git a/engines/mads/phantom/phantom_scenes.cpp b/engines/mads/phantom/phantom_scenes.cpp
index f7a7153..7ef627c 100644
--- a/engines/mads/phantom/phantom_scenes.cpp
+++ b/engines/mads/phantom/phantom_scenes.cpp
@@ -191,7 +191,7 @@ void SceneInfoPhantom::loadCodes(MSurface &depthSurface, int variant) {
 }
 
 void SceneInfoPhantom::loadCodes(MSurface &depthSurface, Common::SeekableReadStream *stream) {
-	byte *destP = depthSurface.getData();
+	byte *destP = (byte *)depthSurface.getPixels();
 	byte *walkMap = new byte[stream->size()];
 	stream->read(walkMap, stream->size());
 
diff --git a/engines/mads/rails.cpp b/engines/mads/rails.cpp
index ee0ca98..46d9e0e 100644
--- a/engines/mads/rails.cpp
+++ b/engines/mads/rails.cpp
@@ -149,7 +149,7 @@ int Rails::scanPath(const Common::Point &srcPos, const Common::Point &destPos) {
 	++xDiff;
 	++yDiff;
 
-	const byte *srcP = _depthSurface->getBasePtr(srcPos.x, srcPos.y);
+	const byte *srcP = (const byte *)_depthSurface->getBasePtr(srcPos.x, srcPos.y);
 	int index = xAmount;
 
 	// Outer loop
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index 83ab115..66f56f9 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -89,8 +89,7 @@ Scene::~Scene() {
 }
 
 void Scene::restrictScene() {
-	_sceneSurface.init(MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT, MADS_SCREEN_WIDTH,
-		_vm->_screen.getPixels(), Graphics::PixelFormat::createFormatCLUT8());
+	_sceneSurface.create(*_vm->_screen, Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT));
 }
 
 void Scene::clearVocab() {
@@ -517,7 +516,7 @@ void  Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
 	if (_posAdjust != Common::Point(0, 0))
 		warning("Adjust used %d %d", _posAdjust.x, _posAdjust.y);
 	// Copy background for the dirty areas to the screen
-	_dirtyAreas.copy(&_backgroundSurface, &_vm->_screen, _posAdjust);
+	_dirtyAreas.copy(&_backgroundSurface, _vm->_screen, _posAdjust);
 
 	// Handle dirty areas for foreground objects
 	_spriteSlots.setDirtyAreas();
@@ -528,11 +527,11 @@ void  Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
 	_spriteSlots.drawSprites(&_sceneSurface);
 
 	// Draw text elements onto the view
-	_textDisplay.draw(&_vm->_screen);
+	_textDisplay.draw(_vm->_screen);
 
 	if (transitionType) {
 		// Fading in the screen
-		_vm->_screen.transition(transitionType, surfaceFlag);
+		_vm->_screen->transition(transitionType, surfaceFlag);
 		_vm->_sound->startQueuedCommands();
 	} else {
 		// Copy dirty areas to the screen
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
index 7b0e64c..5323178 100644
--- a/engines/mads/scene_data.cpp
+++ b/engines/mads/scene_data.cpp
@@ -242,13 +242,13 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
 	int height = _height;
 
 	if (!bgSurface.getPixels() || (bgSurface.w != width) || (bgSurface.h != height)) {
-		bgSurface.setSize(width, height);
+		bgSurface.create(width, height);
 	}
 
 	if (_depthStyle == 2)
 		width >>= 2;
 	if (!depthSurface.getPixels()) {
-		depthSurface.setSize(width, height);
+		depthSurface.create(width, height);
 	}
 
 	loadCodes(depthSurface, variant);
@@ -288,7 +288,7 @@ void SceneInfo::load(int sceneId, int variant, const Common::String &resName,
 		assert(asset && _depthStyle != 2);
 
 		MSprite *spr = asset->getFrame(si._frameNumber);
-		bgSurface.copyFrom(spr, si._position, si._depth, &depthSurface,
+		bgSurface.copyFrom(*spr, si._position, si._depth, &depthSurface,
 			si._scale, false, spr->getTransparencyIndex());
 	}
 
@@ -455,7 +455,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
 		newHeight = tileCount * tileHeight;
 
 	if (bgSurface.w != newWidth || bgSurface.h != newHeight)
-		bgSurface.setSize(newWidth, newHeight);
+		bgSurface.create(newWidth, newHeight);
 
 	// --------------------------------------------------------------------------------
 
@@ -477,7 +477,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
 
 		//debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize);
 
-		newTile->empty();
+		newTile->clear();
 
 		byte *compressedTileData = new byte[compressedTileDataSize];
 
@@ -503,7 +503,8 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName,
 			TileSetIterator tile = tileSet.begin();
 			for (int i = 0; i < tileIndex; i++)
 				++tile;
-			((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight));
+
+			bgSurface.blitFrom(*(*tile).get(), Common::Point(x * tileWidth, y * tileHeight));
 			((*tile).get())->free();
 		}
 	}
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
index 90fbbe7..05f9de6 100644
--- a/engines/mads/screen.cpp
+++ b/engines/mads/screen.cpp
@@ -69,7 +69,6 @@ void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) {
 	_active = true;
 }
 
-
 void DirtyArea::setSpriteSlot(const SpriteSlot *spriteSlot) {
 	int width, height;
 	Scene &scene = _vm->_game->_scene;
@@ -215,12 +214,13 @@ void DirtyAreas::copy(MSurface *srcSurface, MSurface *destSurface, const Common:
 		Common::Point destPos(srcBounds.left, srcBounds.top);
 
 		if ((*this)[i]._active && bounds.isValidRect()) {
-			srcSurface->copyTo(destSurface, bounds, destPos);
+			destSurface->blitFrom(*srcSurface, bounds, destPos);
 		}
 	}
 }
 
 void DirtyAreas::copyToScreen() {
+/*
 	for (uint i = 0; i < size(); ++i) {
 		const Common::Rect &bounds = (*this)[i]._bounds;
 
@@ -229,9 +229,10 @@ void DirtyAreas::copyToScreen() {
 			continue;
 
 		if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) {
-			_vm->_screen.copyRectToScreen(bounds);
+			_vm->_screen->copyRectToScreen(bounds);
 		}
 	}
+	*/
 }
 
 void DirtyAreas::reset() {
@@ -554,38 +555,17 @@ void ScreenObjects::synchronize(Common::Serializer &s) {
 
 /*------------------------------------------------------------------------*/
 
-ScreenSurface::ScreenSurface() {
+Screen::Screen(): Graphics::Screen(), MSurface() {
+	// Create the screen surface separately on another surface, since the screen
+	// surface will be subject to change as the clipping area is altered
+	_rawSurface.create(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
+	resetClipBounds();
+
 	_shakeCountdown = -1;
 	_random = 0x4D2;
-	_surfacePixels = nullptr;
-}
-
-void ScreenSurface::init() {
-	// Set the size for the screen
-	setSize(MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT);
-
-	// Store a copy of the raw pixels pointer for the screen, since the surface
-	// itself may be later changed to only a subset of the screen
-	_surfacePixels = (byte *)getPixels();
-	_freeFlag = false;
-}
-
-ScreenSurface::~ScreenSurface() {
-	::free(_surfacePixels);
 }
 
-void ScreenSurface::copyRectToScreen(const Common::Rect &bounds) {
-	const byte *buf = getBasePtr(bounds.left, bounds.top);
-
-	Common::Rect destBounds = bounds;
-	destBounds.translate(_clipBounds.left, _clipBounds.top);
-
-	if (bounds.width() != 0 && bounds.height() != 0)
-		g_system->copyRectToScreen(buf, this->pitch, destBounds.left, destBounds.top,
-		destBounds.width(), destBounds.height());
-}
-
-void ScreenSurface::updateScreen() {
+void Screen::update() {
 	if (_shakeCountdown >= 0) {
 		_random = _random * 5 + 1;
 		int offset = (_random >> 8) & 3;
@@ -596,27 +576,42 @@ void ScreenSurface::updateScreen() {
 		// offset width shown at the very right. The offset changes to give
 		// an effect of shaking the screen
 		offset *= 4;
-		const byte *buf = getBasePtr(offset, 0);
-		g_system->copyRectToScreen(buf, this->pitch, 0, 0,
-			this->pitch - offset, this->h);
+		const byte *buf = (const byte *)getBasePtr(offset, 0);
+		g_system->copyRectToScreen(buf, this->pitch, 0, 0, this->pitch - offset, this->h);
 		if (offset > 0)
-			g_system->copyRectToScreen(this->pixels, this->pitch,
+			g_system->copyRectToScreen(getPixels(), this->pitch,
 				this->pitch - offset, 0, offset, this->h);
+		return;
 	}
 
-	g_system->updateScreen();
+	// Reset any clip bounds if active whilst the screen is updated
+	Common::Rect clipBounds = getClipBounds();
+	resetClipBounds();
+
+	// Update the screen
+	Graphics::Screen::update();
+
+	// Revert back to whatever clipping is active
+	setClipBounds(clipBounds);
 }
 
-void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) {
+void Screen::transition(ScreenTransition transitionType, bool surfaceFlag) {
 	Palette &pal = *_vm->_palette;
 	Scene &scene = _vm->_game->_scene;
 	byte palData[PALETTE_SIZE];
 
+	// The original loads the new scene to the screen surface for some of the
+	// transition types like fade out/in, so we need to clear the dirty rects so
+	// it doesn't prematurely get blitted to the physical screen before fade out
+	Common::Rect clipBounds = getClipBounds();
+	clearDirtyRects();
+
  	switch (transitionType) {
 	case kTransitionFadeIn:
-	case kTransitionFadeOutIn:
+	case kTransitionFadeOutIn: {
 		Common::fill(&pal._colorValues[0], &pal._colorValues[3], 0);
 		Common::fill(&pal._colorFlags[0], &pal._colorFlags[3], false);
+		resetClipBounds();
 
 		if (transitionType == kTransitionFadeOutIn) {
 			// Fade out
@@ -628,9 +623,11 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
 		Common::fill(&palData[0], &palData[PALETTE_SIZE], 0);
 		pal.setFullPalette(palData);
 
-		copyRectToScreen(getBounds());
+		markAllDirty();
+		update();
 		pal.fadeIn(palData, pal._mainPalette, 0, 256, 0, 1, 1, 16);
 		break;
+	}
 
 	case kTransitionBoxInBottomLeft:
 	case kTransitionBoxInBottomRight:
@@ -666,19 +663,13 @@ void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag
 		// Quick transitions
 		break;
 	}
-}
 
-void ScreenSurface::setClipBounds(const Common::Rect &r) {
-	_clipBounds = r;
-	setPixels(_surfacePixels + pitch * r.top + r.left, r.width(), r.height());
-	this->pitch = MADS_SCREEN_WIDTH;
+	// Reset clipping
+	markAllDirty();
+	setClipBounds(clipBounds);
 }
 
-void ScreenSurface::resetClipBounds() {
-	setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
-}
-
-void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entrySide,
+void Screen::panTransition(MSurface &newScreen, byte *palData, int entrySide,
 		const Common::Point &srcPos, const Common::Point &destPos,
 		ThroughBlack throughBlack, bool setPalette, int numTicks) {
 	EventsManager &events = *_vm->_events;
@@ -735,8 +726,6 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS
 					srcPos.x + xAt + 1, srcPos.y + size.y));
 			}
 
-			copyRectToScreen(Common::Rect(xAt, destPos.y, xAt + 1, destPos.y + size.y));
-
 			// Slight delay
 			events.pollEvents();
 			g_system->delayMillis(1);
@@ -747,16 +736,18 @@ void ScreenSurface::panTransition(MSurface &newScreen, byte *palData, int entryS
 	}
 
 	if (throughBlack == THROUGH_BLACK2) {
+		/*
 		Common::Rect r(srcPos.x, srcPos.y, srcPos.x + size.x, srcPos.y + size.y);
 		copyRectToSurface(newScreen, destPos.x, destPos.y, r);
 		copyRectToScreen(r);
+		*/
 	}
 }
 
 /**
  * Translates the current screen from the old palette to the new palette
  */
-void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteMap) {
+void Screen::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteMap) {
 	Palette &palette = *_vm->_palette;
 	byte oldPalette[PALETTE_SIZE];
 	byte oldMap[PALETTE_COUNT];
@@ -775,7 +766,7 @@ void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteM
 		destP += 2 * RGB_SIZE;
 	}
 
-	Common::Rect oldClip = _clipBounds;
+	Common::Rect oldClip = getClipBounds();
 	resetClipBounds();
 
 	copyRectTranslate(*this, oldMap, Common::Point(0, 0),
@@ -790,7 +781,7 @@ void ScreenSurface::swapForeground(byte newPalette[PALETTE_SIZE], byte *paletteM
  * Palettes consist of 128 RGB entries for the foreground and background
  * respectively, with the two interleaved together. So the start
  */
-void ScreenSurface::swapPalette(const byte *palData, byte swapTable[PALETTE_COUNT],
+void Screen::swapPalette(const byte *palData, byte swapTable[PALETTE_COUNT],
 		bool foreground) {
 	int start = foreground ? 1 : 0;
 	const byte *dynamicList = &palData[start * RGB_SIZE];
@@ -815,5 +806,12 @@ void ScreenSurface::swapPalette(const byte *palData, byte swapTable[PALETTE_COUN
 	}
 }
 
+void Screen::setClipBounds(const Common::Rect &r) {
+	create(_rawSurface, r);
+}
+
+void Screen::resetClipBounds() {
+	setClipBounds(Common::Rect(0, 0, MADS_SCREEN_WIDTH, MADS_SCREEN_HEIGHT));
+}
 
 } // End of namespace MADS
diff --git a/engines/mads/screen.h b/engines/mads/screen.h
index d910e88..6260805 100644
--- a/engines/mads/screen.h
+++ b/engines/mads/screen.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/array.h"
+#include "graphics/screen.h"
 #include "mads/msurface.h"
 #include "mads/action.h"
 
@@ -207,11 +208,10 @@ public:
 	void synchronize(Common::Serializer &s);
 };
 
-class ScreenSurface : public MSurface {
+class Screen : virtual public Graphics::Screen, virtual public MSurface {
 private:
 	uint16 _random;
-	byte *_surfacePixels;
-	Common::Rect _clipBounds;
+	MSurface _rawSurface;
 
 	void panTransition(MSurface &newScreen, byte *palData, int entrySide,
 		const Common::Point &srcPos, const Common::Point &destPos,
@@ -226,36 +226,40 @@ public:
 	/**
 	 * Constructor
 	 */
-	ScreenSurface();
+	Screen();
 
 	/**
 	 * Destructor
 	 */
-	~ScreenSurface();
+	virtual ~Screen() {}
 
 	/**
-	 * Initialize the surface
+	 * Updates the physical screen with contents of the internal surface
 	 */
-	void init();
+	virtual void update();
 
 	/**
-	 * Copys an area of the screen surface to the ScmmVM physical screen buffer
-	 * @param bounds	Area of screen surface to copy
+	 * Transition to a new screen with a given effect
 	 */
-	void copyRectToScreen(const Common::Rect &bounds);
+	void transition(ScreenTransition transitionType, bool surfaceFlag);
 
 	/**
-	 * Updates the screen with the contents of the surface
+	 * Set the screen drawing area to a sub-section of the real screen
 	 */
-	void updateScreen();
-
-	void transition(ScreenTransition transitionType, bool surfaceFlag);
-
 	void setClipBounds(const Common::Rect &r);
 
+	/**
+	 * Reset back to drawing on the entirety of the screen
+	 */
 	void resetClipBounds();
 
-	const Common::Rect &getClipBounds() { return _clipBounds; }
+	/**
+	 * Return the current drawing/clip area
+	 */
+	const Common::Rect getClipBounds() const { 
+		const Common::Point pt = getOffsetFromOwner();
+		return Common::Rect(pt.x, pt.y, pt.x + this->w, pt.y + this->h);
+	}
 };
 
 } // End of namespace MADS
diff --git a/engines/mads/sequence.cpp b/engines/mads/sequence.cpp
index 50b37de..2afe089 100644
--- a/engines/mads/sequence.cpp
+++ b/engines/mads/sequence.cpp
@@ -237,8 +237,8 @@ bool SequenceList::loadSprites(int seqIndex) {
 		if ((seqEntry._flags != 0) || (seqEntry._dynamicHotspotIndex >= 0)) {
 			SpriteAsset &spriteSet = *scene._sprites[seqEntry._spritesIndex];
 			MSprite *frame = spriteSet.getFrame(seqEntry._frameIndex - 1);
-			int width = frame->getWidth() * seqEntry._scale / 200;
-			int height = frame->getHeight() * seqEntry._scale / 100;
+			int width = frame->w * seqEntry._scale / 200;
+			int height = frame->h * seqEntry._scale / 100;
 			Common::Point pt = spriteSlot._position;
 
 			// Handle sprite movement, if present
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
index 0a1c0b7..fc8ddf2 100644
--- a/engines/mads/sprites.cpp
+++ b/engines/mads/sprites.cpp
@@ -59,10 +59,10 @@ MSprite::MSprite() : MSurface() {
 }
 
 MSprite::MSprite(Common::SeekableReadStream *source, const Common::Array<RGB6> &palette,
-		const Common::Rect &bounds)
-	: MSurface(bounds.width(), bounds.height()),
-	  _offset(Common::Point(bounds.left, bounds.top)), _transparencyIndex(TRANSPARENT_COLOR_INDEX) {
+		const Common::Rect &bounds): MSurface(), _transparencyIndex(TRANSPARENT_COLOR_INDEX),
+	  _offset(Common::Point(bounds.left, bounds.top)) {
 	// Load the sprite data
+	create(bounds.width(), bounds.height());
 	loadSprite(source, palette);
 }
 
@@ -74,8 +74,8 @@ void MSprite::loadSprite(Common::SeekableReadStream *source,
 	byte *outp, *lineStart;
 	bool newLine = false;
 
-	outp = getData();
-	lineStart = getData();
+	outp = getPixels();
+	lineStart = getPixels();
 	int spriteSize = this->w * this->h;
 	byte transIndex = getTransparencyIndex();
 	Common::fill(outp, outp + spriteSize, transIndex);
@@ -84,7 +84,7 @@ void MSprite::loadSprite(Common::SeekableReadStream *source,
 		byte cmd1, cmd2, count, pixel;
 
 		if (newLine) {
-			outp = lineStart + getWidth();
+			outp = lineStart + this->w;
 			lineStart = outp;
 			newLine = false;
 		}
@@ -126,7 +126,7 @@ void MSprite::loadSprite(Common::SeekableReadStream *source,
 	// Do a final iteration over the sprite to convert it's pixels to
 	// the final positions in the main palette
 	spriteSize = this->w * this->h;
-	for (outp = getData(); spriteSize > 0; --spriteSize, ++outp) {
+	for (outp = getPixels(); spriteSize > 0; --spriteSize, ++outp) {
 		if (*outp != transIndex)
 			*outp = palette[*outp]._palIndex;
 	}
@@ -257,12 +257,12 @@ void SpriteSlots::drawBackground() {
 				}
 
 				if (spriteSlot._depth <= 1) {
-					frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex());
+					scene._backgroundSurface.transBlitFrom(*frame, pt, frame->getTransparencyIndex());
 				} else if (scene._depthStyle == 0) {
-					scene._backgroundSurface.copyFrom(frame, pt, spriteSlot._depth, &scene._depthSurface,
+					scene._backgroundSurface.copyFrom(*frame, pt, spriteSlot._depth, &scene._depthSurface,
 						-1, false, frame->getTransparencyIndex());
 				} else {
-					frame->copyTo(&scene._backgroundSurface, pt, frame->getTransparencyIndex());
+					scene._backgroundSurface.transBlitFrom(*frame, pt, frame->getTransparencyIndex());
 				}
 			}
 		}
@@ -319,7 +319,7 @@ void SpriteSlots::drawSprites(MSurface *s) {
 
 		if ((slot._scale < 100) && (slot._scale != -1)) {
 			// Scaled drawing
-			s->copyFrom(sprite, slot._position, slot._depth, &scene._depthSurface,
+			s->copyFrom(*sprite, slot._position, slot._depth, &scene._depthSurface,
 				slot._scale, flipped, sprite->getTransparencyIndex());
 		} else {
 			int xp, yp;
@@ -334,7 +334,7 @@ void SpriteSlots::drawSprites(MSurface *s) {
 
 			if (slot._depth > 1) {
 				// Draw the frame with depth processing
-				s->copyFrom(sprite, Common::Point(xp, yp), slot._depth, &scene._depthSurface,
+				s->copyFrom(*sprite, Common::Point(xp, yp), slot._depth, &scene._depthSurface,
 					-1, flipped, sprite->getTransparencyIndex());
 			} else {
 				MSurface *spr = sprite;
@@ -344,7 +344,7 @@ void SpriteSlots::drawSprites(MSurface *s) {
 				}
 
 				// No depth, so simply draw the image
-				spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex());
+				s->transBlitFrom(*spr, Common::Point(xp, yp), sprite->getTransparencyIndex());
 
 				// Free sprite if it was a flipped one
 				if (flipped) {
diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp
index e4b09ff..8f7cb0a 100644
--- a/engines/mads/user_interface.cpp
+++ b/engines/mads/user_interface.cpp
@@ -112,7 +112,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) {
 					Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top));
 			} else {
 				// Copy area
-				userInterface._surface.copyTo(&userInterface, dirtyArea._bounds,
+				userInterface.blitFrom(userInterface._surface, dirtyArea._bounds,
 					Common::Point(dirtyArea._bounds.left, dirtyArea._bounds.top));
 			}
 		}
@@ -155,7 +155,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) {
 
 				if (slot._segmentId == IMG_SPINNING_OBJECT) {
 					MSprite *sprite = asset->getFrame(frameNumber - 1);
-					sprite->copyTo(&userInterface, slot._position,
+					userInterface.transBlitFrom(*sprite, slot._position,
 						sprite->getTransparencyIndex());
 				} else {
 					MSprite *sprite = asset->getFrame(frameNumber - 1);
@@ -185,7 +185,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) {
 				// Flag area of screen as needing update
 				Common::Rect r = dirtyArea._bounds;
 				r.translate(0, scene._interfaceY);
-				_vm->_screen.copyRectToScreen(r);
+				//_vm->_screen->copyRectToScreen(r);
 			}
 		}
 	}
@@ -339,10 +339,10 @@ UserInterface::UserInterface(MADSEngine *vm) : _vm(vm), _dirtyAreas(vm),
 	Common::fill(&_categoryIndexes[0], &_categoryIndexes[7], 0);
 
 	// Map the user interface to the bottom of the game's screen surface
-	byte *pData = _vm->_screen.getBasePtr(0, MADS_SCENE_HEIGHT);
-	setPixels(pData, MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
+	create(*_vm->_screen, Common::Rect(0, MADS_SCENE_HEIGHT,  MADS_SCREEN_WIDTH, 
+		MADS_SCREEN_HEIGHT));
 
-	_surface.setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
+	_surface.create(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
 }
 
 void UserInterface::load(const Common::String &resName) {
@@ -367,7 +367,7 @@ void UserInterface::load(const Common::String &resName) {
 
 	// Read in the surface data
 	Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1);
-	pixelsStream->read(_surface.getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT);
+	pixelsStream->read(_surface.getPixels(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT);
 	delete pixelsStream;
 }
 
@@ -390,7 +390,7 @@ void UserInterface::setup(InputMode inputMode) {
 		resName += ".INT";
 
 		load(resName);
-		_surface.copyTo(this);
+		blitFrom(_surface);
 	}
 	_vm->_game->_screenObjects._inputMode = inputMode;
 
@@ -455,9 +455,9 @@ void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds,
 
 	// Copy the specified area
 
-	byte *data = src->getData();
-	byte *srcPtr = data + (src->getWidth() * copyRect.top + copyRect.left);
-	byte *destPtr = (byte *)this->pixels + (destY * getWidth()) + destX;
+	byte *data = src->getPixels();
+	byte *srcPtr = data + (src->w * copyRect.top + copyRect.left);
+	byte *destPtr = (byte *)getPixels() + (destY * this->w) + destX;
 
 	for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
 		// Process each line of the area
@@ -468,8 +468,8 @@ void UserInterface::mergeFrom(MSurface *src, const Common::Rect &srcBounds,
 				destPtr[xCtr] = srcPtr[xCtr];
 		}
 
-		srcPtr += src->getWidth();
-		destPtr += getWidth();
+		srcPtr += src->w;
+		destPtr += this->w;
 	}
 }
 
@@ -593,7 +593,7 @@ void UserInterface::scrollbarChanged() {
 	_uiSlots.add(r);
 	_uiSlots.draw(false, false);
 	drawScroller();
-	updateRect(r);
+//	updateRect(r);
 }
 
 void UserInterface::writeVocab(ScrCategory category, int id) {
@@ -1012,7 +1012,7 @@ void UserInterface::selectObject(int invIndex) {
 			_uiSlots.add(bounds);
 			_uiSlots.draw(false, false);
 			drawItemVocabList();
-			updateRect(bounds);
+			//updateRect(bounds);
 		}
 	}
 
@@ -1036,7 +1036,7 @@ void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx
 		_uiSlots.add(bounds);
 		_uiSlots.draw(false, false);
 		drawInventoryList();
-		updateRect(bounds);
+		//updateRect(bounds);
 		_inventoryChanged = false;
 
 		if (invList.size() < 2) {
@@ -1052,25 +1052,19 @@ void UserInterface::updateSelection(ScrCategory category, int newIndex, int *idx
 		if (oldIndex >= 0) {
 			writeVocab(category, oldIndex);
 
-			if (getBounds(category, oldIndex, bounds))
-				updateRect(bounds);
+/*			if (getBounds(category, oldIndex, bounds))
+				updateRect(bounds); */
 		}
 
 		if (newIndex >= 0) {
 			writeVocab(category, newIndex);
 
-			if (getBounds(category, newIndex, bounds))
-				updateRect(bounds);
+/*			if (getBounds(category, newIndex, bounds))
+				updateRect(bounds); */
 		}
 	}
 }
 
-void UserInterface::updateRect(const Common::Rect &bounds) {
-	Common::Rect r = bounds;
-	r.translate(0, MADS_SCENE_HEIGHT);
-	_vm->_screen.copyRectToScreen(r);
-}
-
 void UserInterface::scrollerChanged() {
 	warning("TODO: scrollerChanged");
 }
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
index 60cc1f7..9232dc1 100644
--- a/engines/mads/user_interface.h
+++ b/engines/mads/user_interface.h
@@ -190,8 +190,6 @@ private:
 	 * Draw a UI textual element
 	 */
 	void writeVocab(ScrCategory category, int id);
-
-	void updateRect(const Common::Rect &bounds);
 public:
 	MSurface _surface;
 	UISlots _uiSlots;


Commit: 3da3dda187b4f88b21c3c7015c953fe0b30b2a50
    https://github.com/scummvm/scummvm/commit/3da3dda187b4f88b21c3c7015c953fe0b30b2a50
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-14T20:56:27-04:00

Commit Message:
SHERLOCK: Changed engine to use Graphics::ManagedSurface

Changed paths:
  A engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
  A engines/sherlock/scalpel/3do/scalpel_3do_screen.h
  A engines/sherlock/tattoo/tattoo_screen.cpp
  A engines/sherlock/tattoo/tattoo_screen.h
    engines/sherlock/animation.cpp
    engines/sherlock/events.cpp
    engines/sherlock/fonts.cpp
    engines/sherlock/fonts.h
    engines/sherlock/image_file.h
    engines/sherlock/module.mk
    engines/sherlock/objects.cpp
    engines/sherlock/scalpel/scalpel.cpp
    engines/sherlock/scalpel/scalpel_darts.cpp
    engines/sherlock/scalpel/scalpel_inventory.cpp
    engines/sherlock/scalpel/scalpel_map.cpp
    engines/sherlock/scalpel/scalpel_scene.cpp
    engines/sherlock/scalpel/scalpel_screen.cpp
    engines/sherlock/scalpel/scalpel_screen.h
    engines/sherlock/scalpel/scalpel_user_interface.cpp
    engines/sherlock/scalpel/tsage/logo.cpp
    engines/sherlock/scene.cpp
    engines/sherlock/screen.cpp
    engines/sherlock/screen.h
    engines/sherlock/sherlock.h
    engines/sherlock/surface.cpp
    engines/sherlock/surface.h
    engines/sherlock/tattoo/tattoo_darts.cpp
    engines/sherlock/tattoo/tattoo_journal.cpp
    engines/sherlock/tattoo/tattoo_map.cpp
    engines/sherlock/tattoo/tattoo_people.cpp
    engines/sherlock/tattoo/tattoo_scene.cpp
    engines/sherlock/tattoo/tattoo_user_interface.cpp
    engines/sherlock/tattoo/widget_base.cpp
    engines/sherlock/tattoo/widget_credits.cpp
    engines/sherlock/tattoo/widget_files.cpp
    engines/sherlock/tattoo/widget_foolscap.cpp
    engines/sherlock/tattoo/widget_inventory.cpp
    engines/sherlock/tattoo/widget_options.cpp
    engines/sherlock/tattoo/widget_password.cpp
    engines/sherlock/tattoo/widget_quit.cpp
    engines/sherlock/tattoo/widget_talk.cpp
    engines/sherlock/tattoo/widget_text.cpp
    engines/sherlock/tattoo/widget_tooltip.cpp
    engines/sherlock/tattoo/widget_verbs.cpp



diff --git a/engines/sherlock/animation.cpp b/engines/sherlock/animation.cpp
index 681e71d..4442c1d 100644
--- a/engines/sherlock/animation.cpp
+++ b/engines/sherlock/animation.cpp
@@ -23,6 +23,8 @@
 #include "sherlock/animation.h"
 #include "sherlock/sherlock.h"
 #include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
+
 #include "common/algorithm.h"
 
 namespace Sherlock {
@@ -89,7 +91,7 @@ bool Animation::play(const Common::String &filename, bool intro, int minDelay, i
 
 			// Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame,
 			// since we don't want the offsets in the image file to be used, just the explicit position we specify
-			screen.transBlitFrom(images[imageFrame]._frame, pt);
+			screen.SHtransBlitFrom(images[imageFrame]._frame, pt);
 		} else {
 			// At this point, either the sprites for the frame has been complete, or there weren't any sprites
 			// at all to draw for the frame
@@ -201,7 +203,7 @@ bool Animation::play3DO(const Common::String &filename, bool intro, int minDelay
 
 			// Draw the sprite. Note that we explicitly use the raw frame below, rather than the ImageFrame,
 			// since we don't want the offsets in the image file to be used, just the explicit position we specify
-			screen._backBuffer1.transBlitFrom(images[imageFrame]._frame, pt);
+			screen._backBuffer1.SHtransBlitFrom(images[imageFrame]._frame, pt);
 			if (!fadeActive)
 				screen.slamArea(pt.x, pt.y, images[imageFrame]._frame.w, images[imageFrame]._frame.h);
 		} else {
diff --git a/engines/sherlock/events.cpp b/engines/sherlock/events.cpp
index 4b0b7df..6cfee5d 100644
--- a/engines/sherlock/events.cpp
+++ b/engines/sherlock/events.cpp
@@ -143,7 +143,7 @@ void Events::setCursor(CursorId cursorId, const Common::Point &cursorPos, const
 
 	// Form a single surface containing both frames
 	Surface s(r.width(), r.height());
-	s.fill(TRANSPARENCY);
+	s.clear(TRANSPARENCY);
 
 	// Draw the passed image
 	Common::Point drawPos;
@@ -151,11 +151,11 @@ void Events::setCursor(CursorId cursorId, const Common::Point &cursorPos, const
 		drawPos.x = -cursorPt.x;
 	if (cursorPt.y < 0)
 		drawPos.y = -cursorPt.y;
-	s.blitFrom(surface, Common::Point(drawPos.x, drawPos.y));
+	s.SHblitFrom(surface, Common::Point(drawPos.x, drawPos.y));
 
 	// Draw the cursor image
 	drawPos = Common::Point(MAX(cursorPt.x, (int16)0), MAX(cursorPt.y, (int16)0));
-	s.transBlitFrom(cursorImg, Common::Point(drawPos.x, drawPos.y));
+	s.SHtransBlitFrom(cursorImg, Common::Point(drawPos.x, drawPos.y));
 
 	// Set up hotspot position for cursor, adjusting for cursor image's position within the surface
 	Common::Point hotspot;
@@ -163,7 +163,7 @@ void Events::setCursor(CursorId cursorId, const Common::Point &cursorPos, const
 		hotspot = Common::Point(8, 8);
 	hotspot += drawPos;
 	// Set the cursor
-	setCursor(s.getRawSurface(), hotspot.x, hotspot.y);
+	setCursor(s, hotspot.x, hotspot.y);
 }
 
 void Events::animateCursorIfNeeded() {
diff --git a/engines/sherlock/fonts.cpp b/engines/sherlock/fonts.cpp
index 8e36c39..5a14881 100644
--- a/engines/sherlock/fonts.cpp
+++ b/engines/sherlock/fonts.cpp
@@ -43,7 +43,7 @@ void Fonts::setVm(SherlockEngine *vm) {
 	_charCount = 0;
 }
 
-void Fonts::free() {
+void Fonts::freeFont() {
 	delete _font;
 }
 
@@ -213,7 +213,7 @@ void Fonts::writeString(Surface *surface, const Common::String &str,
 
 		if (curChar < _charCount) {
 			ImageFrame &frame = (*_font)[curChar];
-			surface->transBlitFrom(frame, Common::Point(charPos.x, charPos.y + _yOffsets[curChar]), false, overrideColor);
+			surface->SHtransBlitFrom(frame, Common::Point(charPos.x, charPos.y + _yOffsets[curChar]), false, overrideColor);
 			charPos.x += frame._frame.w + 1;
 		} else {
 			warning("Invalid character encountered - %d", (int)curChar);
diff --git a/engines/sherlock/fonts.h b/engines/sherlock/fonts.h
index a527cc7..3594d46 100644
--- a/engines/sherlock/fonts.h
+++ b/engines/sherlock/fonts.h
@@ -57,7 +57,7 @@ public:
 	/**
 	 * Frees the font manager
 	 */
-	static void free();
+	static void freeFont();
 
 	/**
 	 * Set the font to use for writing text on the screen
diff --git a/engines/sherlock/image_file.h b/engines/sherlock/image_file.h
index da260ab..778332b 100644
--- a/engines/sherlock/image_file.h
+++ b/engines/sherlock/image_file.h
@@ -46,6 +46,11 @@ struct ImageFrame {
 	Graphics::Surface _frame;
 
 	/**
+	 * Converts an ImageFrame record to a surface for convenience in passing to drawing methods
+	 */
+	operator const Graphics::Surface &() { return _frame; }
+
+	/**
 	 * Decompress a single frame for the sprite
 	 */
 	void decompressFrame(const byte *src, bool isRoseTattoo);
diff --git a/engines/sherlock/module.mk b/engines/sherlock/module.mk
index 7fa7896..0d17d0b 100644
--- a/engines/sherlock/module.mk
+++ b/engines/sherlock/module.mk
@@ -3,6 +3,7 @@ MODULE := engines/sherlock
 MODULE_OBJS = \
 	scalpel/scalpel.o \
 	scalpel/3do/movie_decoder.o \
+	scalpel/3do/scalpel_3do_screen.o \
 	scalpel/drivers/adlib.o \
 	scalpel/drivers/mt32.o \
 	scalpel/tsage/logo.o \
@@ -30,6 +31,7 @@ MODULE_OBJS = \
 	tattoo/tattoo_people.o \
 	tattoo/tattoo_resources.o \
 	tattoo/tattoo_scene.o \
+	tattoo/tattoo_screen.o \
 	tattoo/tattoo_talk.o \
 	tattoo/tattoo_user_interface.o \
 	tattoo/widget_base.o \
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index a89b8dc..644c0c7 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -365,8 +365,8 @@ bool BaseObject::checkEndOfSequence() {
 
 			if (seq == 99) {
 				--_frameNumber;
-				screen._backBuffer1.transBlitFrom(*_imageFrame, _position);
-				screen._backBuffer2.transBlitFrom(*_imageFrame, _position);
+				screen._backBuffer1.SHtransBlitFrom(*_imageFrame, _position);
+				screen._backBuffer2.SHtransBlitFrom(*_imageFrame, _position);
 				_type = INVALID;
 			} else if (IS_ROSE_TATTOO && _talkSeq && seq == 0) {
 				setObjTalkSequence(_talkSeq);
diff --git a/engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp b/engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
new file mode 100644
index 0000000..f848394
--- /dev/null
+++ b/engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
@@ -0,0 +1,286 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/scalpel.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
+
+namespace Sherlock {
+
+namespace Scalpel {
+
+Scalpel3DOScreen::Scalpel3DOScreen(SherlockEngine *vm): ScalpelScreen(vm) {
+}
+
+void Scalpel3DOScreen::SHblitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
+	if (!_vm->_isScreenDoubled) {
+		ScalpelScreen::SHblitFrom(src, pt, srcBounds);
+		return;
+	}
+
+	Common::Rect srcRect = srcBounds;
+	Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
+
+	if (!srcRect.isValidRect() || !clip(srcRect, destRect))
+		return;
+
+	// Add dirty area remapped to the 640x200 surface
+	addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2));
+
+	// Transfer the area, doubling each pixel
+	for (int yp = 0; yp < srcRect.height(); ++yp) {
+		const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp);
+		uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2);
+
+		for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) {
+			*destP = *srcP;
+			*(destP + 1) = *srcP;
+			*(destP + 640) = *srcP;
+			*(destP + 640 + 1) = *srcP;
+		}
+	}
+}
+
+void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
+		bool flipped, int overrideColor) {
+	error("TODO: Refactor");
+#if 0
+	if (!_vm->_isScreenDoubled) {
+		ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor);
+		return;
+	}
+
+	Common::Rect drawRect(0, 0, src.w, src.h);
+	Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
+
+	// Clip the display area to on-screen
+	if (!clip(drawRect, destRect))
+		// It's completely off-screen
+		return;
+
+	if (flipped)
+		drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom,
+		src.w - drawRect.left, src.h - drawRect.top);
+
+	Common::Point destPt(destRect.left, destRect.top);
+	addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2,
+		(destPt.y + drawRect.height()) * 2));
+
+	assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2);
+
+	for (int yp = 0; yp < drawRect.height(); ++yp) {
+		const uint16 *srcP = (const uint16 *)src.getBasePtr(
+			flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
+		uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2);
+
+		for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) {
+			// RGB 0, 0, 0 -> transparent on 3DO
+			if (*srcP) {
+				*destP = *srcP;
+				*(destP + 1) = *srcP;
+				*(destP + 640) = *srcP;
+				*(destP + 640 + 1) = *srcP;
+			}
+
+			srcP = flipped ? srcP - 1 : srcP + 1;
+		}
+	}
+#endif
+}
+
+void Scalpel3DOScreen::fillRect(const Common::Rect &r, uint color) {
+	if (_vm->_isScreenDoubled)
+		ScalpelScreen::fillRect(Common::Rect(r.left * 2, r.top * 2, r.right * 2, r.bottom * 2), color);
+	else
+		ScalpelScreen::fillRect(r, color);
+}
+
+void Scalpel3DOScreen::fadeIntoScreen3DO(int speed) {
+	Events &events = *_vm->_events;
+	uint16 *currentScreenBasePtr = (uint16 *)getPixels();
+	uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels();
+	uint16  currentScreenPixel = 0;
+	uint16  targetScreenPixel = 0;
+
+	uint16  currentScreenPixelRed = 0;
+	uint16  currentScreenPixelGreen = 0;
+	uint16  currentScreenPixelBlue = 0;
+
+	uint16  targetScreenPixelRed = 0;
+	uint16  targetScreenPixelGreen = 0;
+	uint16  targetScreenPixelBlue = 0;
+
+	uint16  screenWidth = SHERLOCK_SCREEN_WIDTH;
+	uint16  screenHeight = SHERLOCK_SCREEN_HEIGHT;
+	uint16  screenX = 0;
+	uint16  screenY = 0;
+	uint16  pixelsChanged = 0;
+
+	clearDirtyRects();
+
+	do {
+		pixelsChanged = 0;
+		uint16 *currentScreenPtr = currentScreenBasePtr;
+		uint16 *targetScreenPtr = targetScreenBasePtr;
+
+		for (screenY = 0; screenY < screenHeight; screenY++) {
+			for (screenX = 0; screenX < screenWidth; screenX++) {
+				currentScreenPixel = *currentScreenPtr;
+				targetScreenPixel = *targetScreenPtr;
+
+				if (currentScreenPixel != targetScreenPixel) {
+					// pixel doesn't match, adjust accordingly
+					currentScreenPixelRed = currentScreenPixel & 0xF800;
+					currentScreenPixelGreen = currentScreenPixel & 0x07E0;
+					currentScreenPixelBlue = currentScreenPixel & 0x001F;
+					targetScreenPixelRed = targetScreenPixel & 0xF800;
+					targetScreenPixelGreen = targetScreenPixel & 0x07E0;
+					targetScreenPixelBlue = targetScreenPixel & 0x001F;
+
+					if (currentScreenPixelRed != targetScreenPixelRed) {
+						if (currentScreenPixelRed < targetScreenPixelRed) {
+							currentScreenPixelRed += 0x0800;
+						} else {
+							currentScreenPixelRed -= 0x0800;
+						}
+					}
+					if (currentScreenPixelGreen != targetScreenPixelGreen) {
+						// Adjust +2/-2 because we are running RGB555 at RGB565
+						if (currentScreenPixelGreen < targetScreenPixelGreen) {
+							currentScreenPixelGreen += 0x0040;
+						} else {
+							currentScreenPixelGreen -= 0x0040;
+						}
+					}
+					if (currentScreenPixelBlue != targetScreenPixelBlue) {
+						if (currentScreenPixelBlue < targetScreenPixelBlue) {
+							currentScreenPixelBlue += 0x0001;
+						} else {
+							currentScreenPixelBlue -= 0x0001;
+						}
+					}
+
+					uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
+					*currentScreenPtr = v;
+					if (_vm->_isScreenDoubled) {
+						*(currentScreenPtr + 1) = v;
+						*(currentScreenPtr + 640) = v;
+						*(currentScreenPtr + 640 + 1) = v;
+					}
+
+					pixelsChanged++;
+				}
+
+				currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
+				targetScreenPtr++;
+			}
+
+			if (_vm->_isScreenDoubled)
+				currentScreenPtr += 640;
+		}
+
+		// Too much considered dirty at the moment
+		if (_vm->_isScreenDoubled)
+			addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
+		else
+			addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
+
+		events.pollEvents();
+		events.delay(10 * speed);
+	} while ((pixelsChanged) && (!_vm->shouldQuit()));
+}
+
+void Scalpel3DOScreen::blitFrom3DOcolorLimit(uint16 limitColor) {
+	uint16 *currentScreenPtr = (uint16 *)getPixels();
+	uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels();
+	uint16  currentScreenPixel = 0;
+
+	uint16  screenWidth = SHERLOCK_SCREEN_WIDTH;
+	uint16  screenHeight = SHERLOCK_SCREEN_HEIGHT;
+	uint16  screenX = 0;
+	uint16  screenY = 0;
+
+	uint16  currentScreenPixelRed = 0;
+	uint16  currentScreenPixelGreen = 0;
+	uint16  currentScreenPixelBlue = 0;
+
+	uint16  limitPixelRed = limitColor & 0xF800;
+	uint16  limitPixelGreen = limitColor & 0x07E0;
+	uint16  limitPixelBlue = limitColor & 0x001F;
+
+	for (screenY = 0; screenY < screenHeight; screenY++) {
+		for (screenX = 0; screenX < screenWidth; screenX++) {
+			currentScreenPixel = *targetScreenPtr;
+
+			currentScreenPixelRed = currentScreenPixel & 0xF800;
+			currentScreenPixelGreen = currentScreenPixel & 0x07E0;
+			currentScreenPixelBlue = currentScreenPixel & 0x001F;
+
+			if (currentScreenPixelRed < limitPixelRed)
+				currentScreenPixelRed = limitPixelRed;
+			if (currentScreenPixelGreen < limitPixelGreen)
+				currentScreenPixelGreen = limitPixelGreen;
+			if (currentScreenPixelBlue < limitPixelBlue)
+				currentScreenPixelBlue = limitPixelBlue;
+
+			uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
+			*currentScreenPtr = v;
+			if (_vm->_isScreenDoubled) {
+				*(currentScreenPtr + 1) = v;
+				*(currentScreenPtr + 640) = v;
+				*(currentScreenPtr + 640 + 1) = v;
+			}
+
+			currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
+			targetScreenPtr++;
+		}
+
+		if (_vm->_isScreenDoubled)
+			currentScreenPtr += 640;
+	}
+
+	// Too much considered dirty at the moment
+	if (_vm->_isScreenDoubled)
+		addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
+	else
+		addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
+}
+
+uint16 Scalpel3DOScreen::width() const {
+	return _vm->_isScreenDoubled ? this->w / 2 : this->w;
+}
+
+uint16 Scalpel3DOScreen::height() const {
+	return _vm->_isScreenDoubled ? this->h / 2 : this->h;
+}
+
+void Scalpel3DOScreen::rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt) {
+	Common::Rect srcRect(0, 0, src.w, src.h);
+	Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
+
+	addDirtyRect(destRect);
+	copyRectToSurface(src, destRect.left, destRect.top, srcRect);
+}
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/3do/scalpel_3do_screen.h b/engines/sherlock/scalpel/3do/scalpel_3do_screen.h
new file mode 100644
index 0000000..422f588
--- /dev/null
+++ b/engines/sherlock/scalpel/3do/scalpel_3do_screen.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SHERLOCK_SCALPEL_3DO_SCREEN_H
+#define SHERLOCK_SCALPEL_3DO_SCREEN_H
+
+#include "sherlock/scalpel/scalpel_screen.h"
+
+namespace Sherlock {
+
+class SherlockEngine;
+
+namespace Scalpel {
+
+class Scalpel3DOScreen : public ScalpelScreen {
+protected:
+	/**
+	 * Draws a sub-section of a surface at a given position within this surface
+	 * Overriden for the 3DO to automatically double the size of everything to the underlying 640x400 surface
+	 */
+	virtual void SHblitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
+
+	/**
+	 * Draws a surface at a given position within this surface with transparency
+	 */
+	virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped, 
+		int overrideColor);
+public:
+	Scalpel3DOScreen(SherlockEngine *vm);
+	virtual ~Scalpel3DOScreen() {}
+
+	/**
+	 * Draws a sub-section of a surface at a given position within this surface
+	 */
+	void rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt);
+
+	/**
+	 * Fade backbuffer 1 into screen (3DO RGB!)
+	 */
+	void fadeIntoScreen3DO(int speed);
+
+	void blitFrom3DOcolorLimit(uint16 color);
+
+	/**
+	 * Fill a given area of the surface with a given color
+	 */
+	virtual void fillRect(const Common::Rect &r, uint color);
+
+	virtual uint16 width() const;
+	virtual uint16 height() const;
+};
+
+} // End of namespace Scalpel
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index b17f38b..cbb2020 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -29,6 +29,7 @@
 #include "sherlock/scalpel/scalpel_people.h"
 #include "sherlock/scalpel/scalpel_scene.h"
 #include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
 #include "sherlock/scalpel/tsage/logo.h"
 #include "sherlock/sherlock.h"
 #include "sherlock/music.h"
@@ -371,8 +372,8 @@ bool ScalpelEngine::showCityCutscene() {
 
 	if (finished) {
 		ImageFile titleImages_LondonNovember("title2.vgs", true);
-		_screen->_backBuffer1.blitFrom(*_screen);
-		_screen->_backBuffer2.blitFrom(*_screen);
+		_screen->_backBuffer1.SHblitFrom(*_screen);
+		_screen->_backBuffer2.SHblitFrom(*_screen);
 
 		Common::Point londonPosition;
 
@@ -386,19 +387,19 @@ bool ScalpelEngine::showCityCutscene() {
 		}
 
 		// London, England
-		_screen->_backBuffer1.transBlitFrom(titleImages_LondonNovember[0], londonPosition);
+		_screen->_backBuffer1.SHtransBlitFrom(titleImages_LondonNovember[0], londonPosition);
 		_screen->randomTransition();
 		finished = _events->delay(1000, true);
 
 		// November, 1888
 		if (finished) {
-			_screen->_backBuffer1.transBlitFrom(titleImages_LondonNovember[1], Common::Point(100, 100));
+			_screen->_backBuffer1.SHtransBlitFrom(titleImages_LondonNovember[1], Common::Point(100, 100));
 			_screen->randomTransition();
 			finished = _events->delay(5000, true);
 		}
 
 		// Transition out the title
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2);
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2);
 		_screen->randomTransition();
 	}
 
@@ -407,8 +408,8 @@ bool ScalpelEngine::showCityCutscene() {
 
 	if (finished) {
 		ImageFile titleImages_SherlockHolmesTitle("title.vgs", true);
-		_screen->_backBuffer1.blitFrom(*_screen);
-		_screen->_backBuffer2.blitFrom(*_screen);
+		_screen->_backBuffer1.SHblitFrom(*_screen);
+		_screen->_backBuffer2.SHblitFrom(*_screen);
 
 		Common::Point lostFilesPosition;
 		Common::Point sherlockHolmesPosition;
@@ -427,17 +428,17 @@ bool ScalpelEngine::showCityCutscene() {
 		}
 
 		// The Lost Files of
-		_screen->_backBuffer1.transBlitFrom(titleImages_SherlockHolmesTitle[0], lostFilesPosition);
+		_screen->_backBuffer1.SHtransBlitFrom(titleImages_SherlockHolmesTitle[0], lostFilesPosition);
 		// Sherlock Holmes
-		_screen->_backBuffer1.transBlitFrom(titleImages_SherlockHolmesTitle[1], sherlockHolmesPosition);
+		_screen->_backBuffer1.SHtransBlitFrom(titleImages_SherlockHolmesTitle[1], sherlockHolmesPosition);
 		// copyright
-		_screen->_backBuffer1.transBlitFrom(titleImages_SherlockHolmesTitle[2], copyrightPosition);
+		_screen->_backBuffer1.SHtransBlitFrom(titleImages_SherlockHolmesTitle[2], copyrightPosition);
 
 		_screen->verticalTransition();
 		finished = _events->delay(4000, true);
 
 		if (finished) {
-			_screen->_backBuffer1.blitFrom(_screen->_backBuffer2);
+			_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2);
 			_screen->randomTransition();
 			finished = _events->delay(2000);
 		}
@@ -461,7 +462,7 @@ bool ScalpelEngine::showCityCutscene() {
 				// English, width 175, height 38
 				alleyPosition = Common::Point(72, 51);
 			}
-			_screen->transBlitFrom(titleImages_SherlockHolmesTitle[3], alleyPosition);
+			_screen->SHtransBlitFrom(titleImages_SherlockHolmesTitle[3], alleyPosition);
 			_screen->fadeIn(palette, 3);
 
 			// Wait until the track got looped and the first few notes were played
@@ -537,7 +538,7 @@ bool ScalpelEngine::showAlleyCutscene() {
 			earlyTheFollowingMorningPosition = Common::Point(35, 52);
 		}
 
-		_screen->transBlitFrom(titleImages_EarlyTheFollowingMorning[0], earlyTheFollowingMorningPosition);
+		_screen->SHtransBlitFrom(titleImages_EarlyTheFollowingMorning[0], earlyTheFollowingMorningPosition);
 
 		// fast fade-in
 		_screen->fadeIn(palette, 1);
@@ -641,23 +642,23 @@ bool ScalpelEngine::scrollCredits() {
 	delete stream;
 
 	// Save a copy of the screen background for use in drawing each credit frame
-	_screen->_backBuffer1.blitFrom(*_screen);
+	_screen->_backBuffer1.SHblitFrom(*_screen);
 
 	// Loop for showing the credits
 	for(int idx = 0; idx < 600 && !_events->kbHit() && !shouldQuit(); ++idx) {
 		// Copy the entire screen background before writing text
-		_screen->blitFrom(_screen->_backBuffer1);
+		_screen->SHblitFrom(_screen->_backBuffer1);
 
 		// Write the text appropriate for the next frame
 		if (idx < 400)
-			_screen->transBlitFrom(creditsImages[0], Common::Point(10, 200 - idx), false, 0);
+			_screen->SHtransBlitFrom(creditsImages[0], Common::Point(10, 200 - idx), false, 0);
 		if (idx > 200)
-			_screen->transBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0);
+			_screen->SHtransBlitFrom(creditsImages[1], Common::Point(10, 400 - idx), false, 0);
 
 		// Don't show credit text on the top and bottom ten rows of the screen
-		_screen->blitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->w(), 10));
-		_screen->blitFrom(_screen->_backBuffer1, Common::Point(0, _screen->h() - 10),
-			Common::Rect(0, _screen->h() - 10, _screen->w(), _screen->h()));
+		_screen->SHblitFrom(_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, _screen->width(), 10));
+		_screen->SHblitFrom(_screen->_backBuffer1, Common::Point(0, _screen->height() - 10),
+			Common::Rect(0, _screen->height() - 10, _screen->width(), _screen->height()));
 
 		_events->delay(100);
 	}
@@ -670,7 +671,7 @@ bool ScalpelEngine::show3DOSplash() {
 	// 3DO EA Splash screen
 	ImageFile3DO titleImage_3DOSplash("3DOSplash.cel", kImageFile3DOType_Cel);
 
-	_screen->transBlitFrom(titleImage_3DOSplash[0]._frame, Common::Point(0, -20));
+	_screen->SHtransBlitFrom(titleImage_3DOSplash[0]._frame, Common::Point(0, -20));
 	bool finished = _events->delay(3000, true);
 
 	if (finished) {
@@ -706,7 +707,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
 		_sound->playAiff("prologue/sounds/rain.aiff", 15, true);
 
 		// Fade screen to grey
-		screen._backBuffer1.fill(0xCE59); // RGB565: 25, 50, 25 (grey)
+		screen._backBuffer1.clear(0xCE59); // RGB565: 25, 50, 25 (grey)
 		screen.fadeIntoScreen3DO(2);
 	}
 
@@ -715,16 +716,16 @@ bool ScalpelEngine::showCityCutscene3DO() {
 	}
 
 	if (finished) {
-		screen._backBuffer1.fill(0); // fill backbuffer with black to avoid issues during fade from white
+		screen._backBuffer1.clear(0); // fill backbuffer with black to avoid issues during fade from white
 		finished = _animation->play3DO("26open1", true, 1, true, 2);
 	}
 
 	if (finished) {
-		screen._backBuffer2.blitFrom(screen._backBuffer1);
+		screen._backBuffer2.SHblitFrom(screen._backBuffer1);
 
 		// "London, England"
 		ImageFile3DO titleImage_London("title2a.cel", kImageFile3DOType_Cel);
-		screen._backBuffer1.transBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
+		screen._backBuffer1.SHtransBlitFrom(titleImage_London[0]._frame, Common::Point(30, 50));
 
 		screen.fadeIntoScreen3DO(1);
 		finished = _events->delay(1500, true);
@@ -732,7 +733,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
 		if (finished) {
 			// "November, 1888"
 			ImageFile3DO titleImage_November("title2b.cel", kImageFile3DOType_Cel);
-			screen._backBuffer1.transBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
+			screen._backBuffer1.SHtransBlitFrom(titleImage_November[0]._frame, Common::Point(100, 100));
 
 			screen.fadeIntoScreen3DO(1);
 			finished = _music->waitUntilMSec(14700, 0, 0, 5000);
@@ -740,8 +741,8 @@ bool ScalpelEngine::showCityCutscene3DO() {
 
 		if (finished) {
 			// Restore screen
-			_screen->_backBuffer1.blitFrom(screen._backBuffer2);
-			_screen->blitFrom(screen._backBuffer1);
+			_screen->_backBuffer1.SHblitFrom(screen._backBuffer2);
+			_screen->SHblitFrom(screen._backBuffer1);
 		}
 	}
 
@@ -751,7 +752,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
 	if (finished) {
 		// "Sherlock Holmes" (title)
 		ImageFile3DO titleImage_SherlockHolmesTitle("title1ab.cel", kImageFile3DOType_Cel);
-		screen._backBuffer1.transBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
+		screen._backBuffer1.SHtransBlitFrom(titleImage_SherlockHolmesTitle[0]._frame, Common::Point(34, 5));
 
 		// Blend in
 		screen.fadeIntoScreen3DO(2);
@@ -761,7 +762,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
 		if (finished) {
 			ImageFile3DO titleImage_Copyright("title1c.cel", kImageFile3DOType_Cel);
 
-			screen.transBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
+			screen.SHtransBlitFrom(titleImage_Copyright[0]._frame, Common::Point(20, 190));
 			finished = _events->delay(3500, true);
 		}
 	}
@@ -780,7 +781,7 @@ bool ScalpelEngine::showCityCutscene3DO() {
 	if (finished) {
 		// "In the alley behind the Regency Theatre..."
 		ImageFile3DO titleImage_InTheAlley("title1d.cel", kImageFile3DOType_Cel);
-		screen._backBuffer1.transBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
+		screen._backBuffer1.SHtransBlitFrom(titleImage_InTheAlley[0]._frame, Common::Point(72, 51));
 
 		// Fade in
 		screen.fadeIntoScreen3DO(4);
@@ -819,7 +820,7 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
 		ImageFile3DO titleImage_ScreamingVictim("scream.cel", kImageFile3DOType_Cel);
 
 		screen.clear();
-		screen.transBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
+		screen.SHtransBlitFrom(titleImage_ScreamingVictim[0]._frame, Common::Point(0, 0));
 
 		// Play "scream.aiff"
 		if (_sound->_voices)
@@ -848,7 +849,7 @@ bool ScalpelEngine::showAlleyCutscene3DO() {
 	if (finished) {
 		// "Early the following morning on Baker Street..."
 		ImageFile3DO titleImage_EarlyTheFollowingMorning("title3.cel", kImageFile3DOType_Cel);
-		screen._backBuffer1.transBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
+		screen._backBuffer1.SHtransBlitFrom(titleImage_EarlyTheFollowingMorning[0]._frame, Common::Point(35, 51));
 
 		// Fade in
 		screen.fadeIntoScreen3DO(4);
@@ -908,7 +909,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
 		ImageFile3DO titleImage_CoffeeNote("note.cel", kImageFile3DOType_Cel);
 
 		_screen->clear();
-		_screen->transBlitFrom(titleImage_CoffeeNote[0]._frame, Common::Point(0, 0));
+		_screen->SHtransBlitFrom(titleImage_CoffeeNote[0]._frame, Common::Point(0, 0));
 
 		if (_sound->_voices) {
 			finished = _sound->playSound("prologue/sounds/note.aiff", WAIT_KBD_OR_FINISH);
@@ -937,7 +938,7 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
 		// TODO: Brighten the image, possibly by doing a partial fade
 		// to white.
 
-		_screen->_backBuffer2.blitFrom(_screen->_backBuffer1);
+		_screen->_backBuffer2.SHblitFrom(_screen->_backBuffer1);
 
 		for (int nr = 1; finished && nr <= 4; nr++) {
 			char filename[15];
@@ -945,8 +946,8 @@ bool ScalpelEngine::showOfficeCutscene3DO() {
 			ImageFile3DO *creditsImage = new ImageFile3DO(filename, kImageFile3DOType_Cel);
 			ImageFrame *creditsFrame = &(*creditsImage)[0];
 			for (int i = 0; finished && i < 200 + creditsFrame->_height; i++) {
-				_screen->blitFrom(_screen->_backBuffer2);
-				_screen->transBlitFrom(creditsFrame->_frame, Common::Point((320 - creditsFrame->_width) / 2, 200 - i));
+				_screen->SHblitFrom(_screen->_backBuffer2);
+				_screen->SHtransBlitFrom(creditsFrame->_frame, Common::Point((320 - creditsFrame->_width) / 2, 200 - i));
 				if (!_events->delay(70, true))
 					finished = false;
 			}
@@ -998,7 +999,7 @@ void ScalpelEngine::showLBV(const Common::String &filename) {
 	delete stream;
 
 	_screen->setPalette(images._palette);
-	_screen->_backBuffer1.blitFrom(images[0]);
+	_screen->_backBuffer1.SHblitFrom(images[0]);
 	_screen->verticalTransition();
 }
 
@@ -1156,7 +1157,7 @@ void ScalpelEngine::eraseBrumwellMirror() {
 
 	// If player is in range of the mirror, then restore background from the secondary back buffer
 	if (Common::Rect(70, 100, 200, 200).contains(pt)) {
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(137, 18),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(137, 18),
 			Common::Rect(137, 18, 184, 74));
 	}
 }
@@ -1218,20 +1219,20 @@ void ScalpelEngine::doBrumwellMirror() {
 		bool flipped = people[HOLMES]._sequenceNumber == WALK_LEFT || people[HOLMES]._sequenceNumber == STOP_LEFT
 			|| people[HOLMES]._sequenceNumber == WALK_UPRIGHT || people[HOLMES]._sequenceNumber == STOP_UPRIGHT
 			|| people[HOLMES]._sequenceNumber == WALK_DOWNLEFT || people[HOLMES]._sequenceNumber == STOP_DOWNLEFT;
-		_screen->_backBuffer1.transBlitFrom(imageFrame, pt + Common::Point(38, -imageFrame._frame.h - 25), flipped);
+		_screen->_backBuffer1.SHtransBlitFrom(imageFrame, pt + Common::Point(38, -imageFrame._frame.h - 25), flipped);
 
 		// Redraw the mirror borders to prevent the drawn image of Holmes from appearing outside of the mirror
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(114, 18),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(114, 18),
 			Common::Rect(114, 18, 137, 114));
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(137, 70),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(137, 70),
 			Common::Rect(137, 70, 142, 114));
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(142, 71),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(142, 71),
 			Common::Rect(142, 71, 159, 114));
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(159, 72),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(159, 72),
 			Common::Rect(159, 72, 170, 116));
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(170, 73),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(170, 73),
 			Common::Rect(170, 73, 184, 114));
-		_screen->_backBuffer1.blitFrom(_screen->_backBuffer2, Common::Point(184, 18),
+		_screen->_backBuffer1.SHblitFrom(_screen->_backBuffer2, Common::Point(184, 18),
 			Common::Rect(184, 18, 212, 114));
 	}
 }
@@ -1272,7 +1273,7 @@ void ScalpelEngine::showScummVMRestoreDialog() {
 bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::Point &pos, bool isPortrait) {
 	Scalpel3DOScreen &screen = *(Scalpel3DOScreen *)_screen;
 	Scalpel3DOMovieDecoder *videoDecoder = new Scalpel3DOMovieDecoder();
-	Graphics::Surface tempSurface;
+	Graphics::ManagedSurface tempSurface;
 
 	Common::Point framePos(pos.x, pos.y);
 	ImageFile3DO *frameImageFile = nullptr;
@@ -1307,7 +1308,7 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
 
 	// If we're to show the movie at half-size, we'll need a temporary intermediate surface
 	if (halfSize)
-		tempSurface.create(width / 2, height / 2, _screen->getPixelFormat());
+		tempSurface.create(width / 2, height / 2);
 
 	while (!shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
 		if (videoDecoder->needsUpdate()) {
@@ -1371,19 +1372,19 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
 					}
 
 					// Point the drawing frame to the temporary surface
-					frame = &tempSurface;
+					frame = &tempSurface.rawSurface();
 				}
 
 				if (isPortrait && !frameShown) {
 					// Draw the frame (not the frame of the video, but a frame around the video) itself
-					_screen->transBlitFrom(frameImage->_frame, framePos);
+					_screen->SHtransBlitFrom(frameImage->_frame, framePos);
 					frameShown = true;
 				}
 
 				if (isPortrait && !halfSize) {
 					screen.rawBlitFrom(*frame, Common::Point(pos.x * 2, pos.y * 2));
 				} else {
-					_screen->blitFrom(*frame, pos);
+					_screen->SHblitFrom(*frame, pos);
 				}
 
 				_screen->update();
@@ -1413,9 +1414,9 @@ bool ScalpelEngine::play3doMovie(const Common::String &filename, const Common::P
 	}
 
 	// Restore scene
-	screen._backBuffer1.blitFrom(screen._backBuffer2);
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2);
 	_scene->updateBackground();
-	screen.slamArea(0, 0, screen.w(), CONTROLS_Y);
+	screen.slamArea(0, 0, screen.width(), CONTROLS_Y);
 
 	return !skipVideo;
 }
diff --git a/engines/sherlock/scalpel/scalpel_darts.cpp b/engines/sherlock/scalpel/scalpel_darts.cpp
index 87f4566..c5ba803 100644
--- a/engines/sherlock/scalpel/scalpel_darts.cpp
+++ b/engines/sherlock/scalpel/scalpel_darts.cpp
@@ -102,7 +102,7 @@ void Darts::playDarts() {
 			score -= lastDart;
 			_roundScore += lastDart;
 
-			screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
 				Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 			screen.print(Common::Point(DART_INFO_X, DART_INFO_Y), DART_COL_FORE, "Dart # %d", idx + 1);
 			screen.print(Common::Point(DART_INFO_X, DART_INFO_Y + 10), DART_COL_FORE, "Scored %d points", lastDart);
@@ -154,7 +154,7 @@ void Darts::playDarts() {
 				events.wait(20);
 			}
 
-			screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
 				Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 			screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
 		}
@@ -166,8 +166,8 @@ void Darts::playDarts() {
 		done |= _vm->shouldQuit();
 
 		if (!done) {
-			screen._backBuffer2.blitFrom((*_dartImages)[0], Common::Point(0, 0));
-			screen._backBuffer1.blitFrom(screen._backBuffer2);
+			screen._backBuffer2.SHblitFrom((*_dartImages)[0], Common::Point(0, 0));
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2);
 			screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
 		}
 	} while (!done);
@@ -185,7 +185,7 @@ void Darts::loadDarts() {
 	_dartImages = new ImageFile("darts.vgs");
 	screen.setPalette(_dartImages->_palette);
 
-	screen._backBuffer1.blitFrom((*_dartImages)[0], Common::Point(0, 0));
+	screen._backBuffer1.SHblitFrom((*_dartImages)[0], Common::Point(0, 0));
 	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
 }
 
@@ -245,7 +245,7 @@ void Darts::showNames(int playerNum) {
 	screen.slamArea(STATUS_INFO_X + 50, STATUS_INFO_Y + 10, 81, 12);
 
 	// Make a copy of the back buffer to the secondary one
-	screen._backBuffer2.blitFrom(screen._backBuffer1);
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1);
 }
 
 void Darts::showStatus(int playerNum) {
@@ -253,7 +253,7 @@ void Darts::showStatus(int playerNum) {
 	byte color;
 
 	// Copy scoring screen from secondary back buffer. This will erase any previously displayed status/score info
-	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
 		Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, SHERLOCK_SCREEN_WIDTH, STATUS_INFO_Y + 48));
 
 	color = (playerNum == 0) ? PLAYER_COLOR : DART_COL_FORE;
@@ -292,7 +292,7 @@ int Darts::throwDart(int dartNum, int computer) {
 	if (_vm->shouldQuit())
 		return 0;
 
-	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_INFO_X, DART_INFO_Y - 1),
 		Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 	screen.slamRect(Common::Rect(DART_INFO_X, DART_INFO_Y - 1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 
@@ -309,9 +309,9 @@ int Darts::throwDart(int dartNum, int computer) {
 
 	// Copy the bars to the secondary back buffer so that they remain fixed at their selected values
 	// whilst the dart is being animated at being thrown at the board
-	screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1),
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DARTBARHX - 1, DARTHORIZY - 1),
 		Common::Rect(DARTBARHX - 1, DARTHORIZY - 1, DARTBARHX + DARTBARSIZE + 3, DARTHORIZY + 10));
-	screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1),
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1),
 		Common::Rect(DARTBARVX - 1, DARTHEIGHTY - 1, DARTBARVX + 11, DARTHEIGHTY + DARTBARSIZE + 3));
 
 	// Convert height and width to relative range of -50 to 50, where 0,0 is the exact centre of the board
@@ -344,7 +344,7 @@ void Darts::drawDartThrow(const Common::Point &pt) {
 
 		// Draw the dart
 		Common::Point drawPos(pos.x - frame._width / 2, pos.y - frame._height);
-		screen._backBuffer1.transBlitFrom(frame, drawPos);
+		screen._backBuffer1.SHtransBlitFrom(frame, drawPos);
 		screen.slamArea(drawPos.x, drawPos.y, frame._width, frame._height);
 
 		// Handle erasing old dart frame area
@@ -352,14 +352,14 @@ void Darts::drawDartThrow(const Common::Point &pt) {
 			screen.slamRect(oldDrawBounds);
 
 		oldDrawBounds = Common::Rect(drawPos.x, drawPos.y, drawPos.x + frame._width, drawPos.y + frame._height);
-		screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, oldDrawBounds);
+		screen._backBuffer1.SHblitFrom(screen._backBuffer2, drawPos, oldDrawBounds);
 
 		events.wait(2);
 	}
 
 	// Draw dart in final "stuck to board" form
-	screen._backBuffer1.transBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
-	screen._backBuffer2.transBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
+	screen._backBuffer1.SHtransBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
+	screen._backBuffer2.SHtransBlitFrom((*_dartImages)[22], Common::Point(oldDrawBounds.left, oldDrawBounds.top));
 	screen.slamRect(oldDrawBounds);
 }
 
@@ -368,8 +368,8 @@ void Darts::erasePowerBars() {
 
 	screen._backBuffer1.fillRect(Common::Rect(DARTBARHX, DARTHORIZY, DARTBARHX + DARTBARSIZE, DARTHORIZY + 10), BLACK);
 	screen._backBuffer1.fillRect(Common::Rect(DARTBARVX, DARTHEIGHTY, DARTBARVX + 10, DARTHEIGHTY + DARTBARSIZE), BLACK);
-	screen._backBuffer1.transBlitFrom((*_dartImages)[2], Common::Point(DARTBARHX - 1, DARTHORIZY - 1));
-	screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1));
+	screen._backBuffer1.SHtransBlitFrom((*_dartImages)[2], Common::Point(DARTBARHX - 1, DARTHORIZY - 1));
+	screen._backBuffer1.SHtransBlitFrom((*_dartImages)[3], Common::Point(DARTBARVX - 1, DARTHEIGHTY - 1));
 	screen.slamArea(DARTBARHX - 1, DARTHORIZY - 1, DARTBARSIZE + 3, 11);
 	screen.slamArea(DARTBARVX - 1, DARTHEIGHTY - 1, 11, DARTBARSIZE + 3);
 }
@@ -398,11 +398,11 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, bool i
 
 		if (isVertical) {
 			screen._backBuffer1.hLine(pt.x, pt.y + DARTBARSIZE - 1 - idx, pt.x + 8, color);
-			screen._backBuffer1.transBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1));
+			screen._backBuffer1.SHtransBlitFrom((*_dartImages)[3], Common::Point(pt.x - 1, pt.y - 1));
 			screen.slamArea(pt.x, pt.y + DARTBARSIZE - 1 - idx, 8, 2);
 		} else {
 			screen._backBuffer1.vLine(pt.x + idx, pt.y, pt.y + 8, color);
-			screen._backBuffer1.transBlitFrom((*_dartImages)[2], Common::Point(pt.x - 1, pt.y - 1));
+			screen._backBuffer1.SHtransBlitFrom((*_dartImages)[2], Common::Point(pt.x - 1, pt.y - 1));
 			screen.slamArea(pt.x + idx, pt.y, 1, 8);
 		}
 
diff --git a/engines/sherlock/scalpel/scalpel_inventory.cpp b/engines/sherlock/scalpel/scalpel_inventory.cpp
index c3e2029..e8d4d3b 100644
--- a/engines/sherlock/scalpel/scalpel_inventory.cpp
+++ b/engines/sherlock/scalpel/scalpel_inventory.cpp
@@ -201,7 +201,7 @@ void ScalpelInventory::highlight(int index, byte color) {
 	ImageFrame &frame = (*_invShapes[slot])[0];
 
 	bb.fillRect(Common::Rect(8 + slot * 52, 165, (slot + 1) * 52, 194), color);
-	bb.transBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2),
+	bb.SHtransBlitFrom(frame, Common::Point(6 + slot * 52 + ((47 - frame._width) / 2),
 		163 + ((33 - frame._height) / 2)));
 	screen.slamArea(8 + slot * 52, 165, 44, 30);
 }
@@ -217,12 +217,12 @@ void ScalpelInventory::refreshInv() {
 	ui._infoFlag = true;
 	ui.clearInfo();
 
-	screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(0, CONTROLS_Y),
 		Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 	ui.examine();
 
 	if (!talk._talkToAbort) {
-		screen._backBuffer2.blitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
+		screen._backBuffer2.SHblitFrom((*ui._controlPanel)[0], Common::Point(0, CONTROLS_Y));
 		loadInv();
 	}
 }
@@ -264,7 +264,7 @@ void ScalpelInventory::putInv(InvSlamMode slamIt) {
 
 		// Draw the item image
 		ImageFrame &frame = (*_invShapes[itemNum])[0];
-		bb.transBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2),
+		bb.SHtransBlitFrom(frame, Common::Point(6 + itemNum * 52 + ((47 - frame._width) / 2),
 			163 + ((33 - frame._height) / 2)));
 	}
 
diff --git a/engines/sherlock/scalpel/scalpel_map.cpp b/engines/sherlock/scalpel/scalpel_map.cpp
index 0924581..ba14b5b 100644
--- a/engines/sherlock/scalpel/scalpel_map.cpp
+++ b/engines/sherlock/scalpel/scalpel_map.cpp
@@ -167,13 +167,13 @@ int ScalpelMap::show() {
 	setupSprites();
 
 	if (!IS_3DO) {
-		screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
-		screen._backBuffer1.blitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-		screen._backBuffer1.blitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
-		screen._backBuffer1.blitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+		screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+		screen._backBuffer1.SHblitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+		screen._backBuffer1.SHblitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+		screen._backBuffer1.SHblitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
 	} else {
-		screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
-		screen.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+		screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+		screen.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
 	}
 
 	_drawMap = true;
@@ -238,12 +238,12 @@ int ScalpelMap::show() {
 			changed = false;
 
 			if (!IS_3DO) {
-				screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
-				screen._backBuffer1.blitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-				screen._backBuffer1.blitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
-				screen._backBuffer1.blitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+				screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+				screen._backBuffer1.SHblitFrom((*bigMap)[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+				screen._backBuffer1.SHblitFrom((*bigMap)[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+				screen._backBuffer1.SHblitFrom((*bigMap)[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
 			} else {
-				screen._backBuffer1.blitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
+				screen._backBuffer1.SHblitFrom((*bigMap)[0], Common::Point(-_bigPos.x, -_bigPos.y));
 			}
 
 			showPlaces();
@@ -359,7 +359,6 @@ void ScalpelMap::freeSprites() {
 	delete _mapCursors;
 	delete _shapes;
 	delete _iconShapes;
-	_iconSave.free();
 }
 
 void ScalpelMap::showPlaces() {
@@ -376,7 +375,7 @@ void ScalpelMap::showPlaces() {
 			if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH
 					&& pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) {
 				if (_vm->readFlags(idx)) {
-					screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate],
+					screen._backBuffer1.SHtransBlitFrom((*_iconShapes)[pt._translate],
 						Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12));
 				}
 			}
@@ -388,13 +387,13 @@ void ScalpelMap::showPlaces() {
 }
 
 void ScalpelMap::saveTopLine() {
-	_topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
+	_topLine.SHblitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
 }
 
 void ScalpelMap::eraseTopLine() {
 	Screen &screen = *_vm->_screen;
-	screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
-	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
+	screen._backBuffer1.SHblitFrom(_topLine, Common::Point(0, 0));
+	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.height());
 }
 
 void ScalpelMap::showPlaceName(int idx, bool highlighted) {
@@ -409,7 +408,7 @@ void ScalpelMap::showPlaceName(int idx, bool highlighted) {
 
 		bool flipped = people[HOLMES]._sequenceNumber == MAP_DOWNLEFT || people[HOLMES]._sequenceNumber == MAP_LEFT
 			|| people[HOLMES]._sequenceNumber == MAP_UPLEFT;
-		screen._backBuffer1.transBlitFrom(*people[HOLMES]._imageFrame, _lDrawnPos, flipped);
+		screen._backBuffer1.SHtransBlitFrom(*people[HOLMES]._imageFrame, _lDrawnPos, flipped);
 	}
 
 	if (highlighted) {
@@ -451,9 +450,9 @@ void ScalpelMap::updateMap(bool flushScreen) {
 	saveIcon(people[HOLMES]._imageFrame, hPos);
 	if (people[HOLMES]._sequenceNumber == MAP_DOWNLEFT || people[HOLMES]._sequenceNumber == MAP_LEFT
 			|| people[HOLMES]._sequenceNumber == MAP_UPLEFT)
-		screen._backBuffer1.transBlitFrom(*people[HOLMES]._imageFrame, hPos, true);
+		screen._backBuffer1.SHtransBlitFrom(*people[HOLMES]._imageFrame, hPos, true);
 	else
-		screen._backBuffer1.transBlitFrom(*people[HOLMES]._imageFrame, hPos, false);
+		screen._backBuffer1.SHtransBlitFrom(*people[HOLMES]._imageFrame, hPos, false);
 
 	if (flushScreen) {
 		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@@ -553,8 +552,8 @@ void ScalpelMap::saveIcon(ImageFrame *src, const Common::Point &pt) {
 		return;
 	}
 
-	assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
-	_iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
+	assert(size.x <= _iconSave.width() && size.y <= _iconSave.height());
+	_iconSave.SHblitFrom(screen._backBuffer1, Common::Point(0, 0),
 		Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
 	_savedPos = pos;
 	_savedSize = size;
@@ -565,7 +564,7 @@ void ScalpelMap::restoreIcon() {
 
 	if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH
 			&& _savedPos.y < SHERLOCK_SCREEN_HEIGHT)
-		screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
+		screen._backBuffer1.SHblitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
 }
 
 void ScalpelMap::highlightIcon(const Common::Point &pt) {
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
index b62703e..83e49bb 100644
--- a/engines/sherlock/scalpel/scalpel_scene.cpp
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -71,26 +71,26 @@ void ScalpelScene::drawAllShapes() {
 	// Draw all active shapes which are behind the person
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == BEHIND)
-			screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
 	}
 
 	// Draw all canimations which are behind the person
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		if (_canimShapes[idx]->_type == ACTIVE_BG_SHAPE && _canimShapes[idx]->_misc == BEHIND)
-			screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame,
+			screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame,
 			_canimShapes[idx]->_position, _canimShapes[idx]->_flags & OBJ_FLIPPED);
 	}
 
 	// Draw all active shapes which are normal and behind the person
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		if (_bgShapes[idx]._type == ACTIVE_BG_SHAPE && _bgShapes[idx]._misc == NORMAL_BEHIND)
-			screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position, _bgShapes[idx]._flags & OBJ_FLIPPED);
 	}
 
 	// Draw all canimations which are normal and behind the person
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		if (_canimShapes[idx]->_type == ACTIVE_BG_SHAPE && _canimShapes[idx]->_misc == NORMAL_BEHIND)
-			screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+			screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
 			_canimShapes[idx]->_flags & OBJ_FLIPPED);
 	}
 
@@ -103,7 +103,7 @@ void ScalpelScene::drawAllShapes() {
 				p._sequenceNumber == WALK_UPLEFT || p._sequenceNumber == STOP_UPLEFT ||
 				p._sequenceNumber == WALK_DOWNRIGHT || p._sequenceNumber == STOP_DOWNRIGHT);
 
-			screen._backBuffer->transBlitFrom(*p._imageFrame, Common::Point(p._position.x / FIXED_INT_MULTIPLIER,
+			screen._backBuffer->SHtransBlitFrom(*p._imageFrame, Common::Point(p._position.x / FIXED_INT_MULTIPLIER,
 				p._position.y / FIXED_INT_MULTIPLIER - p.frameHeight()), flipped);
 		}
 	}
@@ -112,7 +112,7 @@ void ScalpelScene::drawAllShapes() {
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
 			_bgShapes[idx]._misc == NORMAL_FORWARD)
-			screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
+			screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
 			_bgShapes[idx]._flags & OBJ_FLIPPED);
 	}
 
@@ -120,7 +120,7 @@ void ScalpelScene::drawAllShapes() {
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		if ((_canimShapes[idx]->_type == ACTIVE_BG_SHAPE || _canimShapes[idx]->_type == STATIC_BG_SHAPE) &&
 			_canimShapes[idx]->_misc == NORMAL_FORWARD)
-			screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+			screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
 			_canimShapes[idx]->_flags & OBJ_FLIPPED);
 	}
 
@@ -132,7 +132,7 @@ void ScalpelScene::drawAllShapes() {
 
 		if ((_bgShapes[idx]._type == ACTIVE_BG_SHAPE || _bgShapes[idx]._type == STATIC_BG_SHAPE) &&
 			_bgShapes[idx]._misc == FORWARD)
-			screen._backBuffer->transBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
+			screen._backBuffer->SHtransBlitFrom(*_bgShapes[idx]._imageFrame, _bgShapes[idx]._position,
 			_bgShapes[idx]._flags & OBJ_FLIPPED);
 	}
 
@@ -140,7 +140,7 @@ void ScalpelScene::drawAllShapes() {
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		if ((_canimShapes[idx]->_type == ACTIVE_BG_SHAPE || _canimShapes[idx]->_type == STATIC_BG_SHAPE) &&
 			_canimShapes[idx]->_misc == FORWARD)
-			screen._backBuffer->transBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
+			screen._backBuffer->SHtransBlitFrom(*_canimShapes[idx]->_imageFrame, _canimShapes[idx]->_position,
 			_canimShapes[idx]->_flags & OBJ_FLIPPED);
 	}
 
@@ -242,7 +242,7 @@ void ScalpelScene::doBgAnim() {
 		if (people[HOLMES]._type == CHARACTER)
 			screen.restoreBackground(bounds);
 		else if (people[HOLMES]._type == REMOVE)
-			screen._backBuffer->blitFrom(screen._backBuffer2, pt, bounds);
+			screen._backBuffer->SHblitFrom(screen._backBuffer2, pt, bounds);
 
 		for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 			Object &o = _bgShapes[idx];
@@ -261,7 +261,7 @@ void ScalpelScene::doBgAnim() {
 			Object &o = _bgShapes[idx];
 			if (o._type == NO_SHAPE && ((o._flags & OBJ_BEHIND) == 0)) {
 				// Restore screen area
-				screen._backBuffer->blitFrom(screen._backBuffer2, o._position,
+				screen._backBuffer->SHblitFrom(screen._backBuffer2, o._position,
 					Common::Rect(o._position.x, o._position.y,
 					o._position.x + o._noShapeSize.x, o._position.y + o._noShapeSize.y));
 
@@ -309,14 +309,14 @@ void ScalpelScene::doBgAnim() {
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		Object &o = _bgShapes[idx];
 		if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND)
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 	}
 
 	// Draw all canimations which are behind the person
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		Object &o = *_canimShapes[idx];
 		if (o._type == ACTIVE_BG_SHAPE && o._misc == BEHIND) {
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 		}
 	}
 
@@ -324,14 +324,14 @@ void ScalpelScene::doBgAnim() {
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		Object &o = _bgShapes[idx];
 		if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND)
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 	}
 
 	// Draw all canimations which are NORMAL and behind the person
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		Object &o = *_canimShapes[idx];
 		if (o._type == ACTIVE_BG_SHAPE && o._misc == NORMAL_BEHIND) {
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 		}
 	}
 
@@ -344,7 +344,7 @@ void ScalpelScene::doBgAnim() {
 		bool flipped = people[HOLMES]._sequenceNumber == WALK_LEFT || people[HOLMES]._sequenceNumber == STOP_LEFT ||
 			people[HOLMES]._sequenceNumber == WALK_UPLEFT || people[HOLMES]._sequenceNumber == STOP_UPLEFT ||
 			people[HOLMES]._sequenceNumber == WALK_DOWNRIGHT || people[HOLMES]._sequenceNumber == STOP_DOWNRIGHT;
-		screen._backBuffer->transBlitFrom(*people[HOLMES]._imageFrame,
+		screen._backBuffer->SHtransBlitFrom(*people[HOLMES]._imageFrame,
 			Common::Point(tempX, people[HOLMES]._position.y / FIXED_INT_MULTIPLIER - people[HOLMES]._imageFrame->_frame.h), flipped);
 	}
 
@@ -352,14 +352,14 @@ void ScalpelScene::doBgAnim() {
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		Object &o = _bgShapes[idx];
 		if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD)
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 	}
 
 	// Draw all static and active canimations that are NORMAL and are in front of the person
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		Object &o = *_canimShapes[idx];
 		if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == NORMAL_FORWARD) {
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 		}
 	}
 
@@ -367,19 +367,19 @@ void ScalpelScene::doBgAnim() {
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		Object &o = _bgShapes[idx];
 		if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD)
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 	}
 
 	// Draw any active portrait
 	if (people._portraitLoaded && people._portrait._type == ACTIVE_BG_SHAPE)
-		screen._backBuffer->transBlitFrom(*people._portrait._imageFrame,
+		screen._backBuffer->SHtransBlitFrom(*people._portrait._imageFrame,
 			people._portrait._position, people._portrait._flags & OBJ_FLIPPED);
 
 	// Draw all static and active canimations that are in front of the person
 	for (uint idx = 0; idx < _canimShapes.size(); ++idx) {
 		Object &o = *_canimShapes[idx];
 		if ((o._type == ACTIVE_BG_SHAPE || o._type == STATIC_BG_SHAPE) && o._misc == FORWARD) {
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 		}
 	}
 
@@ -387,7 +387,7 @@ void ScalpelScene::doBgAnim() {
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
 		Object &o = _bgShapes[idx];
 		if (o._type == NO_SHAPE && (o._flags & OBJ_BEHIND) == 0)
-			screen._backBuffer->transBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
+			screen._backBuffer->SHtransBlitFrom(*o._imageFrame, o._position, o._flags & OBJ_FLIPPED);
 	}
 
 	// Bring the newly built picture to the screen
diff --git a/engines/sherlock/scalpel/scalpel_screen.cpp b/engines/sherlock/scalpel/scalpel_screen.cpp
index 197a2a2..37e5294 100644
--- a/engines/sherlock/scalpel/scalpel_screen.cpp
+++ b/engines/sherlock/scalpel/scalpel_screen.cpp
@@ -28,6 +28,8 @@ namespace Sherlock {
 namespace Scalpel {
 
 ScalpelScreen::ScalpelScreen(SherlockEngine *vm) : Screen(vm) {
+	_backBuffer1.create(320, 200);
+	_backBuffer2.create(320, 200);
 }
 
 void ScalpelScreen::makeButton(const Common::Rect &bounds, int textX,
@@ -123,255 +125,6 @@ void ScalpelScreen::makeField(const Common::Rect &r) {
 	_backBuffer->vLine(r.right - 1, r.top + 1, r.bottom - 2, BUTTON_TOP);
 }
 
-/*----------------------------------------------------------------*/
-
-void Scalpel3DOScreen::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
-	if (!_vm->_isScreenDoubled) {
-		ScalpelScreen::blitFrom(src, pt, srcBounds);
-		return;
-	}
-
-	Common::Rect srcRect = srcBounds;
-	Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
-
-	if (!srcRect.isValidRect() || !clip(srcRect, destRect))
-		return;
-
-	// Add dirty area remapped to the 640x200 surface
-	addDirtyRect(Common::Rect(destRect.left * 2, destRect.top * 2, destRect.right * 2, destRect.bottom * 2));
-
-	// Transfer the area, doubling each pixel
-	for (int yp = 0; yp < srcRect.height(); ++yp) {
-		const uint16 *srcP = (const uint16 *)src.getBasePtr(srcRect.left, srcRect.top + yp);
-		uint16 *destP = (uint16 *)getBasePtr(destRect.left * 2, (destRect.top + yp) * 2);
-
-		for (int xp = srcRect.left; xp < srcRect.right; ++xp, ++srcP, destP += 2) {
-			*destP = *srcP;
-			*(destP + 1) = *srcP;
-			*(destP + 640) = *srcP;
-			*(destP + 640 + 1) = *srcP;
-		}
-	}
-}
-
-void Scalpel3DOScreen::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
-		bool flipped, int overrideColor) {
-	if (!_vm->_isScreenDoubled) {
-		ScalpelScreen::transBlitFromUnscaled(src, pt, flipped, overrideColor);
-		return;
-	}
-
-	Common::Rect drawRect(0, 0, src.w, src.h);
-	Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
-
-	// Clip the display area to on-screen
-	if (!clip(drawRect, destRect))
-		// It's completely off-screen
-		return;
-
-	if (flipped)
-		drawRect = Common::Rect(src.w - drawRect.right, src.h - drawRect.bottom,
-		src.w - drawRect.left, src.h - drawRect.top);
-
-	Common::Point destPt(destRect.left, destRect.top);
-	addDirtyRect(Common::Rect(destPt.x * 2, destPt.y * 2, (destPt.x + drawRect.width()) * 2,
-		(destPt.y + drawRect.height()) * 2));
-
-	assert(src.format.bytesPerPixel == 2 && _surface.format.bytesPerPixel == 2);
-
-	for (int yp = 0; yp < drawRect.height(); ++yp) {
-		const uint16 *srcP = (const uint16 *)src.getBasePtr(
-			flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
-		uint16 *destP = (uint16 *)getBasePtr(destPt.x * 2, (destPt.y + yp) * 2);
-
-		for (int xp = 0; xp < drawRect.width(); ++xp, destP += 2) {
-			// RGB 0, 0, 0 -> transparent on 3DO
-			if (*srcP) {
-				*destP = *srcP;
-				*(destP + 1) = *srcP;
-				*(destP + 640) = *srcP;
-				*(destP + 640 + 1) = *srcP;
-			}
-
-			srcP = flipped ? srcP - 1 : srcP + 1;
-		}
-	}
-}
-
-void Scalpel3DOScreen::fillRect(const Common::Rect &r, uint color) {
-	if (_vm->_isScreenDoubled)
-		ScalpelScreen::fillRect(Common::Rect(r.left * 2, r.top * 2, r.right * 2, r.bottom * 2), color);
-	else
-		ScalpelScreen::fillRect(r, color);
-}
-
-void Scalpel3DOScreen::fadeIntoScreen3DO(int speed) {
-	Events &events = *_vm->_events;
-	uint16 *currentScreenBasePtr = (uint16 *)getPixels();
-	uint16 *targetScreenBasePtr = (uint16 *)_backBuffer->getPixels();
-	uint16  currentScreenPixel = 0;
-	uint16  targetScreenPixel = 0;
-
-	uint16  currentScreenPixelRed = 0;
-	uint16  currentScreenPixelGreen = 0;
-	uint16  currentScreenPixelBlue = 0;
-
-	uint16  targetScreenPixelRed = 0;
-	uint16  targetScreenPixelGreen = 0;
-	uint16  targetScreenPixelBlue = 0;
-
-	uint16  screenWidth = SHERLOCK_SCREEN_WIDTH;
-	uint16  screenHeight = SHERLOCK_SCREEN_HEIGHT;
-	uint16  screenX = 0;
-	uint16  screenY = 0;
-	uint16  pixelsChanged = 0;
-
-	clearDirtyRects();
-
-	do {
-		pixelsChanged = 0;
-		uint16 *currentScreenPtr = currentScreenBasePtr;
-		uint16 *targetScreenPtr = targetScreenBasePtr;
-
-		for (screenY = 0; screenY < screenHeight; screenY++) {
-			for (screenX = 0; screenX < screenWidth; screenX++) {
-				currentScreenPixel = *currentScreenPtr;
-				targetScreenPixel = *targetScreenPtr;
-
-				if (currentScreenPixel != targetScreenPixel) {
-					// pixel doesn't match, adjust accordingly
-					currentScreenPixelRed = currentScreenPixel & 0xF800;
-					currentScreenPixelGreen = currentScreenPixel & 0x07E0;
-					currentScreenPixelBlue = currentScreenPixel & 0x001F;
-					targetScreenPixelRed = targetScreenPixel & 0xF800;
-					targetScreenPixelGreen = targetScreenPixel & 0x07E0;
-					targetScreenPixelBlue = targetScreenPixel & 0x001F;
-
-					if (currentScreenPixelRed != targetScreenPixelRed) {
-						if (currentScreenPixelRed < targetScreenPixelRed) {
-							currentScreenPixelRed += 0x0800;
-						} else {
-							currentScreenPixelRed -= 0x0800;
-						}
-					}
-					if (currentScreenPixelGreen != targetScreenPixelGreen) {
-						// Adjust +2/-2 because we are running RGB555 at RGB565
-						if (currentScreenPixelGreen < targetScreenPixelGreen) {
-							currentScreenPixelGreen += 0x0040;
-						} else {
-							currentScreenPixelGreen -= 0x0040;
-						}
-					}
-					if (currentScreenPixelBlue != targetScreenPixelBlue) {
-						if (currentScreenPixelBlue < targetScreenPixelBlue) {
-							currentScreenPixelBlue += 0x0001;
-						} else {
-							currentScreenPixelBlue -= 0x0001;
-						}
-					}
-
-					uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
-					*currentScreenPtr = v;
-					if (_vm->_isScreenDoubled) {
-						*(currentScreenPtr + 1) = v;
-						*(currentScreenPtr + 640) = v;
-						*(currentScreenPtr + 640 + 1) = v;
-					}
-
-					pixelsChanged++;
-				}
-
-				currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
-				targetScreenPtr++;
-			}
-
-			if (_vm->_isScreenDoubled)
-				currentScreenPtr += 640;
-		}
-
-		// Too much considered dirty at the moment
-		if (_vm->_isScreenDoubled)
-			addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
-		else
-			addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
-
-		events.pollEvents();
-		events.delay(10 * speed);
-	} while ((pixelsChanged) && (!_vm->shouldQuit()));
-}
-
-void Scalpel3DOScreen::blitFrom3DOcolorLimit(uint16 limitColor) {
-	uint16 *currentScreenPtr = (uint16 *)getPixels();
-	uint16 *targetScreenPtr = (uint16 *)_backBuffer->getPixels();
-	uint16  currentScreenPixel = 0;
-
-	uint16  screenWidth = SHERLOCK_SCREEN_WIDTH;
-	uint16  screenHeight = SHERLOCK_SCREEN_HEIGHT;
-	uint16  screenX = 0;
-	uint16  screenY = 0;
-
-	uint16  currentScreenPixelRed = 0;
-	uint16  currentScreenPixelGreen = 0;
-	uint16  currentScreenPixelBlue = 0;
-
-	uint16  limitPixelRed = limitColor & 0xF800;
-	uint16  limitPixelGreen = limitColor & 0x07E0;
-	uint16  limitPixelBlue = limitColor & 0x001F;
-
-	for (screenY = 0; screenY < screenHeight; screenY++) {
-		for (screenX = 0; screenX < screenWidth; screenX++) {
-			currentScreenPixel = *targetScreenPtr;
-
-			currentScreenPixelRed = currentScreenPixel & 0xF800;
-			currentScreenPixelGreen = currentScreenPixel & 0x07E0;
-			currentScreenPixelBlue = currentScreenPixel & 0x001F;
-
-			if (currentScreenPixelRed < limitPixelRed)
-				currentScreenPixelRed = limitPixelRed;
-			if (currentScreenPixelGreen < limitPixelGreen)
-				currentScreenPixelGreen = limitPixelGreen;
-			if (currentScreenPixelBlue < limitPixelBlue)
-				currentScreenPixelBlue = limitPixelBlue;
-
-			uint16 v = currentScreenPixelRed | currentScreenPixelGreen | currentScreenPixelBlue;
-			*currentScreenPtr = v;
-			if (_vm->_isScreenDoubled) {
-				*(currentScreenPtr + 1) = v;
-				*(currentScreenPtr + 640) = v;
-				*(currentScreenPtr + 640 + 1) = v;
-			}
-
-			currentScreenPtr += _vm->_isScreenDoubled ? 2 : 1;
-			targetScreenPtr++;
-		}
-
-		if (_vm->_isScreenDoubled)
-			currentScreenPtr += 640;
-	}
-
-	// Too much considered dirty at the moment
-	if (_vm->_isScreenDoubled)
-		addDirtyRect(Common::Rect(0, 0, screenWidth * 2, screenHeight * 2));
-	else
-		addDirtyRect(Common::Rect(0, 0, screenWidth, screenHeight));
-}
-
-uint16 Scalpel3DOScreen::w() const {
-	return _vm->_isScreenDoubled ? _surface.w / 2 : _surface.w;
-}
-
-uint16 Scalpel3DOScreen::h() const {
-	return _vm->_isScreenDoubled ? _surface.h / 2 : _surface.h;
-}
-
-void Scalpel3DOScreen::rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt) {
-	Common::Rect srcRect(0, 0, src.w, src.h);
-	Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
-
-	addDirtyRect(destRect);
-	_surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
-}
-
 } // End of namespace Scalpel
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_screen.h b/engines/sherlock/scalpel/scalpel_screen.h
index cee33b8..d9be29c 100644
--- a/engines/sherlock/scalpel/scalpel_screen.h
+++ b/engines/sherlock/scalpel/scalpel_screen.h
@@ -61,44 +61,6 @@ public:
 	void makeField(const Common::Rect &r);
 };
 
-class Scalpel3DOScreen : public ScalpelScreen {
-protected:
-	/**
-	 * Draws a sub-section of a surface at a given position within this surface
-	 * Overriden for the 3DO to automatically double the size of everything to the underlying 640x400 surface
-	 */
-	virtual void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
-	/**
-	 * Draws a surface at a given position within this surface with transparency
-	 */
-	virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped, 
-		int overrideColor);
-public:
-	Scalpel3DOScreen(SherlockEngine *vm) : ScalpelScreen(vm) {}
-	virtual ~Scalpel3DOScreen() {}
-
-	/**
-	 * Draws a sub-section of a surface at a given position within this surface
-	 */
-	void rawBlitFrom(const Graphics::Surface &src, const Common::Point &pt);
-
-	/**
-	 * Fade backbuffer 1 into screen (3DO RGB!)
-	 */
-	void fadeIntoScreen3DO(int speed);
-
-	void blitFrom3DOcolorLimit(uint16 color);
-
-	/**
-	 * Fill a given area of the surface with a given color
-	 */
-	virtual void fillRect(const Common::Rect &r, uint color);
-
-	virtual uint16 w() const;
-	virtual uint16 h() const;
-};
-
 } // End of namespace Scalpel
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_user_interface.cpp b/engines/sherlock/scalpel/scalpel_user_interface.cpp
index 7ac8d0d..6534f61 100644
--- a/engines/sherlock/scalpel/scalpel_user_interface.cpp
+++ b/engines/sherlock/scalpel/scalpel_user_interface.cpp
@@ -148,23 +148,24 @@ void ScalpelUserInterface::reset() {
 void ScalpelUserInterface::drawInterface(int bufferNum) {
 	Screen &screen = *_vm->_screen;
 
-	const ImageFrame &src = (*_controlPanel)[0];
+	const Graphics::Surface &src = (*_controlPanel)[0]._frame;
 	int16 x = (!IS_3DO) ? 0 : UI_OFFSET_3DO;
 
 	if (bufferNum & 1) {
 		if (IS_3DO)
 			screen._backBuffer1.fillRect(Common::Rect(0, CONTROLS_Y,
 				SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BLACK);
-		screen._backBuffer1.transBlitFrom(src, Common::Point(x, CONTROLS_Y));
+		screen._backBuffer1.SHtransBlitFrom(src, Common::Point(x, CONTROLS_Y));
 	}
 	if (bufferNum & 2) {
 		if (IS_3DO)
 			screen._backBuffer2.fillRect(Common::Rect(0, CONTROLS_Y,
 				SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT), BLACK);
-		screen._backBuffer2.transBlitFrom(src, Common::Point(x, CONTROLS_Y));
+		screen._backBuffer2.SHtransBlitFrom(src, Common::Point(x, CONTROLS_Y));
 	}
 	if (bufferNum == 3)
-		screen._backBuffer2.fillRect(0, INFO_LINE, SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10, INFO_BLACK);
+		screen._backBuffer2.SHfillRect(Common::Rect(0, INFO_LINE,
+			SHERLOCK_SCREEN_WIDTH, INFO_LINE + 10), INFO_BLACK);
 }
 
 void ScalpelUserInterface::handleInput() {
@@ -426,7 +427,7 @@ void ScalpelUserInterface::depressButton(int num) {
 	offsetButton3DO(pt, num);
 
 	ImageFrame &frame = (*_controls)[num];
-	screen._backBuffer1.transBlitFrom(frame, pt);
+	screen._backBuffer1.SHtransBlitFrom(frame, pt);
 	screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
 }
 
@@ -442,7 +443,7 @@ void ScalpelUserInterface::restoreButton(int num) {
 	events.setCursor(ARROW);
 
 	// Restore the UI on the back buffer
-	screen._backBuffer1.blitFrom(screen._backBuffer2, pt,
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, pt,
 		Common::Rect(pt.x, pt.y, pt.x + 90, pt.y + 19));
 	screen.slamArea(pt.x, pt.y, pt.x + frame.w, pt.y + frame.h);
 
@@ -489,7 +490,7 @@ void ScalpelUserInterface::toggleButton(uint16 num) {
 			ImageFrame &frame = (*_controls)[num];
 			Common::Point pt(MENU_POINTS[num][0], MENU_POINTS[num][1]);
 			offsetButton3DO(pt, num);
-			screen._backBuffer1.transBlitFrom(frame, pt);
+			screen._backBuffer1.SHtransBlitFrom(frame, pt);
 			screen.slamArea(pt.x, pt.y, pt.x + frame._width, pt.y + frame._height);
 		}
 	} else {
@@ -1272,7 +1273,7 @@ void ScalpelUserInterface::doLookControl() {
 				// Need to close the window and depress the Look button
 				Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
 				offsetButton3DO(pt, 0);
-				screen._backBuffer2.blitFrom((*_controls)[0], pt);
+				screen._backBuffer2.SHblitFrom((*_controls)[0], pt);
 				banishWindow(true);
 
 				_windowBounds.top = CONTROLS_Y1;
@@ -1296,14 +1297,14 @@ void ScalpelUserInterface::doLookControl() {
 			// Looking at an inventory object
 			// Backup the user interface
 			Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - CONTROLS_Y1);
-			tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
+			tempSurface.SHblitFrom(screen._backBuffer2, Common::Point(0, 0),
 				Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 
 			inv.drawInventory(INVENTORY_DONT_DISPLAY);
 			banishWindow(true);
 
 			// Restore the ui
-			screen._backBuffer2.blitFrom(tempSurface, Common::Point(0, CONTROLS_Y1));
+			screen._backBuffer2.SHblitFrom(tempSurface, Common::Point(0, CONTROLS_Y1));
 
 			_windowBounds.top = CONTROLS_Y1;
 			_key = _oldKey = _hotkeyLook;
@@ -1887,7 +1888,7 @@ void ScalpelUserInterface::journalControl() {
 	// Reset the palette
 	screen.setPalette(screen._cMap);
 
-	screen._backBuffer1.blitFrom(screen._backBuffer2);
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2);
 	scene.updateBackground();
 	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
 }
@@ -1921,9 +1922,9 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
 				Common::Point pt(MENU_POINTS[0][0], MENU_POINTS[0][1]);
 				offsetButton3DO(pt, 0);
 
-				tempSurface.blitFrom(screen._backBuffer2, Common::Point(0, 0),
-					Common::Rect(pt.x, pt.y, pt.x + tempSurface.w(), pt.y + tempSurface.h()));
-				screen._backBuffer2.transBlitFrom((*_controls)[0], pt);
+				tempSurface.SHblitFrom(screen._backBuffer2, Common::Point(0, 0),
+					Common::Rect(pt.x, pt.y, pt.x + tempSurface.width(), pt.y + tempSurface.height()));
+				screen._backBuffer2.SHtransBlitFrom((*_controls)[0], pt);
 
 				banishWindow(1);
 				events.setCursor(MAGNIFY);
@@ -1933,7 +1934,7 @@ void ScalpelUserInterface::printObjectDesc(const Common::String &str, bool first
 				_menuMode = LOOK_MODE;
 				events.clearEvents();
 
-				screen._backBuffer2.blitFrom(tempSurface, pt);
+				screen._backBuffer2.SHblitFrom(tempSurface, pt);
 			} else {
 				events.setCursor(ARROW);
 				banishWindow(true);
@@ -2071,9 +2072,9 @@ void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp)
 
 	if (slideUp) {
 		// Gradually slide up the display of the window
-		for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
-			screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
-				Common::Rect(0, 0, bgSurface.w(), idx));
+		for (int idx = 1; idx <= bgSurface.height(); idx += 2) {
+			screen._backBuffer->SHblitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - idx),
+				Common::Rect(0, 0, bgSurface.width(), idx));
 			screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - idx,
 				SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 
@@ -2081,21 +2082,21 @@ void ScalpelUserInterface::summonWindow(const Surface &bgSurface, bool slideUp)
 		}
 	} else {
 		// Gradually slide down the display of the window
-		for (int idx = 1; idx <= bgSurface.h(); idx += 2) {
-			screen._backBuffer->blitFrom(bgSurface,
-				Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
-				Common::Rect(0, bgSurface.h() - idx, bgSurface.w(), bgSurface.h()));
-			screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(),
-				SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.h() + idx));
+		for (int idx = 1; idx <= bgSurface.height(); idx += 2) {
+			screen._backBuffer->SHblitFrom(bgSurface,
+				Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height()),
+				Common::Rect(0, bgSurface.height() - idx, bgSurface.width(), bgSurface.height()));
+			screen.slamRect(Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height(),
+				SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - bgSurface.height() + idx));
 
 			events.delay(10);
 		}
 	}
 
 	// Final display of the entire window
-	screen._backBuffer->blitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h()),
-		Common::Rect(0, 0, bgSurface.w(), bgSurface.h()));
-	screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.h(), bgSurface.w(), bgSurface.h());
+	screen._backBuffer->SHblitFrom(bgSurface, Common::Point(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height()),
+		Common::Rect(0, 0, bgSurface.width(), bgSurface.height()));
+	screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - bgSurface.height(), bgSurface.width(), bgSurface.height());
 
 	_windowOpen = true;
 }
@@ -2106,10 +2107,10 @@ void ScalpelUserInterface::summonWindow(bool slideUp, int height) {
 	// Extract the window that's been drawn on the back buffer
 	Surface tempSurface(SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT - height);
 	Common::Rect r(0, height, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
-	tempSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), r);
+	tempSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), r);
 
 	// Remove drawn window with original user interface
-	screen._backBuffer1.blitFrom(screen._backBuffer2,
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2,
 		Common::Point(0, height), r);
 
 	// Display the window gradually on-screen
@@ -2133,7 +2134,7 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
 					Common::copy_backward(pSrc, pSrcEnd, pDest);
 
 					// Restore lines from the ui in the secondary back buffer
-					screen._backBuffer1.blitFrom(screen._backBuffer2,
+					screen._backBuffer1.SHblitFrom(screen._backBuffer2,
 						Common::Point(0, CONTROLS_Y),
 						Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, CONTROLS_Y + idx));
 
@@ -2143,14 +2144,14 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
 				}
 
 				// Restore final two old lines
-				screen._backBuffer1.blitFrom(screen._backBuffer2,
+				screen._backBuffer1.SHblitFrom(screen._backBuffer2,
 					Common::Point(0, SHERLOCK_SCREEN_HEIGHT - 2),
 					Common::Rect(0, SHERLOCK_SCREEN_HEIGHT - 2,
 						SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 				screen.slamArea(0, SHERLOCK_SCREEN_HEIGHT - 2, SHERLOCK_SCREEN_WIDTH, 2);
 			} else {
 				// Restore old area to completely erase window
-				screen._backBuffer1.blitFrom(screen._backBuffer2,
+				screen._backBuffer1.SHblitFrom(screen._backBuffer2,
 					Common::Point(0, CONTROLS_Y),
 					Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 				screen.slamRect(Common::Rect(0, CONTROLS_Y, SHERLOCK_SCREEN_WIDTH,
@@ -2170,7 +2171,7 @@ void ScalpelUserInterface::banishWindow(bool slideUp) {
 			}
 
 			// Show entire final area
-			screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1),
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(0, CONTROLS_Y1),
 				Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 			screen.slamRect(Common::Rect(0, CONTROLS_Y1, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 		}
diff --git a/engines/sherlock/scalpel/tsage/logo.cpp b/engines/sherlock/scalpel/tsage/logo.cpp
index 273d26d..a885057 100644
--- a/engines/sherlock/scalpel/tsage/logo.cpp
+++ b/engines/sherlock/scalpel/tsage/logo.cpp
@@ -217,7 +217,7 @@ void Object::erase() {
 	Screen &screen = *_vm->_screen;
 	
 	if (_visage.isLoaded() && !_oldBounds.isEmpty())
-		screen.blitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
+		screen.SHblitFrom(screen._backBuffer1, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
 }
 
 void Object::update() {
@@ -246,9 +246,9 @@ void Object::update() {
 		_visage.getFrame(s, _frame);
 
 		// Display the frame
-		_oldBounds = Common::Rect(_position.x, _position.y, _position.x + s.w(), _position.y + s.h());
+		_oldBounds = Common::Rect(_position.x, _position.y, _position.x + s.width(), _position.y + s.height());
 		_oldBounds.translate(-s._centroid.x, -s._centroid.y);
-		screen.transBlitFrom(s, Common::Point(_oldBounds.left, _oldBounds.top));
+		screen.SHtransBlitFrom(s, Common::Point(_oldBounds.left, _oldBounds.top));
 	}
 }
 
@@ -652,7 +652,7 @@ void Logo::loadBackground() {
 	screen.setPalette(palette);
 
 	// Copy the surface to the screen
-	screen.blitFrom(screen._backBuffer1);
+	screen.SHblitFrom(screen._backBuffer1);
 }
 
 void Logo::fade(const byte palette[PALETTE_SIZE], int step) {
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index 6f9ef17..78d0cd8 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -27,6 +27,7 @@
 #include "sherlock/scalpel/scalpel_people.h"
 #include "sherlock/scalpel/scalpel_scene.h"
 #include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
 #include "sherlock/tattoo/tattoo.h"
 #include "sherlock/tattoo/tattoo_scene.h"
 #include "sherlock/tattoo/tattoo_user_interface.h"
@@ -356,7 +357,7 @@ bool Scene::loadScene(const Common::String &filename) {
 			if (IS_ROSE_TATTOO) {
 				// Resize the screen if necessary
 				int fullWidth = SHERLOCK_SCREEN_WIDTH + bgHeader._scrollSize;
-				if (screen._backBuffer1.w() != fullWidth) {
+				if (screen._backBuffer1.width() != fullWidth) {
 					screen._backBuffer1.create(fullWidth, SHERLOCK_SCREEN_HEIGHT);
 					screen._backBuffer2.create(fullWidth, SHERLOCK_SCREEN_HEIGHT);
 				}
@@ -649,7 +650,7 @@ bool Scene::loadScene(const Common::String &filename) {
 			}
 
 			// Backup the image and set the palette
-			screen._backBuffer2.blitFrom(screen._backBuffer1);
+			screen._backBuffer2.SHblitFrom(screen._backBuffer1);
 			screen.setPalette(screen._cMap);
 
 			delete rrmStream;
@@ -996,12 +997,12 @@ bool Scene::loadScene(const Common::String &filename) {
 
 #if 0
 		// code to show the background
-		screen.blitFrom(screen._backBuffer1);
+		screen.SHblitFrom(screen._backBuffer1);
 		_vm->_events->wait(10000);
 #endif
 
 		// Backup the image
-		screen._backBuffer2.blitFrom(screen._backBuffer1);
+		screen._backBuffer2.SHblitFrom(screen._backBuffer1);
 	}
 
 	// Handle drawing any on-screen interface
@@ -1236,7 +1237,7 @@ void Scene::transitionToScene() {
 
 	// If the scene is capable of scrolling, set the current scroll so that whoever has control 
 	// of the scroll code is in the middle of the screen
-	if (screen._backBuffer1.w() > SHERLOCK_SCREEN_WIDTH)
+	if (screen._backBuffer1.width() > SHERLOCK_SCREEN_WIDTH)
 		people[people._walkControl].centerScreenOnPerson();
 
 	for (uint objIdx = 0; objIdx < _bgShapes.size(); ++objIdx) {
diff --git a/engines/sherlock/screen.cpp b/engines/sherlock/screen.cpp
index 74da2a8..85d47c8 100644
--- a/engines/sherlock/screen.cpp
+++ b/engines/sherlock/screen.cpp
@@ -23,6 +23,8 @@
 #include "sherlock/screen.h"
 #include "sherlock/sherlock.h"
 #include "sherlock/scalpel/scalpel_screen.h"
+#include "sherlock/scalpel/3do/scalpel_3do_screen.h"
+#include "sherlock/tattoo/tattoo_screen.h"
 #include "common/system.h"
 #include "common/util.h"
 #include "graphics/palette.h"
@@ -31,17 +33,14 @@ namespace Sherlock {
 
 Screen *Screen::init(SherlockEngine *vm) {
 	if (vm->getGameID() == GType_RoseTattoo)
-		return new Screen(vm);
+		return new Tattoo::TattooScreen(vm);
 	else if (vm->getPlatform() == Common::kPlatform3DO)
 		return new Scalpel::Scalpel3DOScreen(vm);
 	else
 		return new Scalpel::ScalpelScreen(vm);
 }
 
-Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->getHeight()), _vm(vm),
-		_backBuffer1(vm->getGameID() == GType_RoseTattoo ? 640 : 320, vm->getGameID() == GType_RoseTattoo ? 480 : 200),
-		_backBuffer2(vm->getGameID() == GType_RoseTattoo ? 640 : 320, vm->getGameID() == GType_RoseTattoo ? 480 : 200),
-		_backBuffer(&_backBuffer1) {
+Screen::Screen(SherlockEngine *vm) : Graphics::Screen(), _vm(vm), _backBuffer(&_backBuffer1) {
 	_transitionSeed = 1;
 	_fadeStyle = false;
 	Common::fill(&_cMap[0], &_cMap[PALETTE_SIZE], 0);
@@ -58,37 +57,7 @@ Screen::Screen(SherlockEngine *vm) : Surface(g_system->getWidth(), g_system->get
 }
 
 Screen::~Screen() {
-	Fonts::free();
-}
-
-void Screen::update() {
-	// Merge the dirty rects
-	mergeDirtyRects();
-
-	// Loop through copying dirty areas to the physical screen
-	Common::List<Common::Rect>::iterator i;
-	for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
-		const Common::Rect &r = *i;
-		const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
-		g_system->copyRectToScreen(srcP, _surface.pitch, r.left, r.top,
-			r.width(), r.height());
-	}
-
-	// Signal the physical screen to update
-	g_system->updateScreen();
-	_dirtyRects.clear();
-}
-
-void Screen::makeAllDirty() {
-	addDirtyRect(Common::Rect(0, 0, this->w(), this->h()));
-}
-
-void Screen::getPalette(byte palette[PALETTE_SIZE]) {
-	g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
-}
-
-void Screen::setPalette(const byte palette[PALETTE_SIZE]) {
-	g_system->getPaletteManager()->setPalette(palette, 0, PALETTE_COUNT);
+	Fonts::freeFont();
 }
 
 int Screen::equalizePalette(const byte palette[PALETTE_SIZE]) {
@@ -124,7 +93,7 @@ void Screen::fadeToBlack(int speed) {
 	}
 
 	setPalette(tempPalette);
-	fillRect(Common::Rect(0, 0, _surface.w, _surface.h), 0);
+	fillRect(Common::Rect(0, 0, this->w, this->h), 0);
 }
 
 void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) {
@@ -136,59 +105,23 @@ void Screen::fadeIn(const byte palette[PALETTE_SIZE], int speed) {
 	setPalette(palette);
 }
 
-void Screen::addDirtyRect(const Common::Rect &r) {
-	_dirtyRects.push_back(r);
-	assert(r.width() > 0 && r.height() > 0);
-}
-
-void Screen::mergeDirtyRects() {
-	Common::List<Common::Rect>::iterator rOuter, rInner;
-
-	// Process the dirty rect list to find any rects to merge
-	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
-		rInner = rOuter;
-		while (++rInner != _dirtyRects.end()) {
-
-			if ((*rOuter).intersects(*rInner)) {
-				// these two rectangles overlap or
-				// are next to each other - merge them
-
-				unionRectangle(*rOuter, *rOuter, *rInner);
-
-				// remove the inner rect from the list
-				_dirtyRects.erase(rInner);
-
-				// move back to beginning of list
-				rInner = rOuter;
-			}
-		}
-	}
-}
-
-bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
-	destRect = src1;
-	destRect.extend(src2);
-
-	return !destRect.isEmpty();
-}
-
 void Screen::randomTransition() {
 	Events &events = *_vm->_events;
 	const int TRANSITION_MULTIPLIER = 0x15a4e35;
-	_dirtyRects.clear();
+	clearDirtyRects();
 	assert(IS_SERRATED_SCALPEL);
 
 	for (int idx = 0; idx <= 65535 && !_vm->shouldQuit(); ++idx) {
 		_transitionSeed = _transitionSeed * TRANSITION_MULTIPLIER + 1;
 		int offset = _transitionSeed & 0xFFFF;
 
-		if (offset < (this->w() * this->h()))
+		if (offset < (this->width() * this->height()))
 			*((byte *)getPixels() + offset) = *((const byte *)_backBuffer->getPixels() + offset);
 
 		if (idx != 0 && (idx % 300) == 0) {
 			// Ensure there's a full screen dirty rect for the next frame update
-			if (_dirtyRects.empty())
-				addDirtyRect(Common::Rect(0, 0, _surface.w, _surface.h));
+			if (!isDirty())
+				addDirtyRect(Common::Rect(0, 0, this->w, this->h));
 
 			events.pollEvents();
 			events.delay(1);
@@ -196,7 +129,7 @@ void Screen::randomTransition() {
 	}
 
 	// Make sure everything has been transferred
-	blitFrom(*_backBuffer);
+	SHblitFrom(*_backBuffer);
 }
 
 void Screen::verticalTransition() {
@@ -205,13 +138,13 @@ void Screen::verticalTransition() {
 	byte table[640];
 	Common::fill(&table[0], &table[640], 0);
 
-	for (int yp = 0; yp < this->h(); ++yp) {
-		for (int xp = 0; xp < this->w(); ++xp) {
-			int temp = (table[xp] >= (this->h() - 3)) ? this->h() - table[xp] :
+	for (int yp = 0; yp < this->height(); ++yp) {
+		for (int xp = 0; xp < this->width(); ++xp) {
+			int temp = (table[xp] >= (this->height() - 3)) ? this->height() - table[xp] :
 				_vm->getRandomNumber(3) + 1;
 
 			if (temp) {
-				blitFrom(_backBuffer1, Common::Point(xp, table[xp]),
+				SHblitFrom(_backBuffer1, Common::Point(xp, table[xp]),
 					Common::Rect(xp, table[xp], xp + 1, table[xp] + temp));
 				table[xp] += temp;
 			}
@@ -223,7 +156,7 @@ void Screen::verticalTransition() {
 
 void Screen::restoreBackground(const Common::Rect &r) {
 	if (r.width() > 0 && r.height() > 0)
-		_backBuffer->blitFrom(_backBuffer2, Common::Point(r.left, r.top), r);
+		_backBuffer->SHblitFrom(_backBuffer2, Common::Point(r.left, r.top), r);
 }
 
 void Screen::slamArea(int16 xp, int16 yp, int16 width, int16 height) {
@@ -254,11 +187,10 @@ void Screen::slamRect(const Common::Rect &r) {
 		}
 
 		if (srcRect.isValidRect())
-			blitFrom(*_backBuffer, Common::Point(destRect.left, destRect.top), srcRect);
+			SHblitFrom(*_backBuffer, Common::Point(destRect.left, destRect.top), srcRect);
 	}
 }
 
-
 void Screen::flushImage(ImageFrame *frame, const Common::Point &pt, int16 *xp, int16 *yp, 
 		int16 *width, int16 *height) {
 	Common::Point imgPos = pt + frame->_offset;
@@ -335,7 +267,7 @@ void Screen::blockMove(const Common::Rect &r) {
 }
 
 void Screen::blockMove() {
-	blockMove(Common::Rect(0, 0, w(), h()));
+	blockMove(Common::Rect(0, 0, width(), height()));
 }
 
 void Screen::print(const Common::Point &pt, uint color, const char *formatStr, ...) {
@@ -351,13 +283,13 @@ void Screen::print(const Common::Point &pt, uint color, const char *formatStr, .
 	pos.y--;		// Font is always drawing one line higher
 	if (!pos.x)
 		// Center text horizontally
-		pos.x = (this->w() - width) / 2;
+		pos.x = (this->width() - width) / 2;
 
 	Common::Rect textBounds(pos.x, pos.y, pos.x + width, pos.y + _fontHeight);
-	if (textBounds.right > this->w())
-		textBounds.moveTo(this->w() - width, textBounds.top);
-	if (textBounds.bottom > this->h())
-		textBounds.moveTo(textBounds.left, this->h() - _fontHeight);
+	if (textBounds.right > this->width())
+		textBounds.moveTo(this->width() - width, textBounds.top);
+	if (textBounds.bottom > this->height())
+		textBounds.moveTo(textBounds.left, this->height() - _fontHeight);
 
 	// Write out the string at the given position
 	writeString(str, Common::Point(textBounds.left, textBounds.top), color);
@@ -387,7 +319,8 @@ void Screen::vgaBar(const Common::Rect &r, int color) {
 }
 
 void Screen::setDisplayBounds(const Common::Rect &r) {
-	_sceneSurface.setPixels(_backBuffer1.getBasePtr(r.left, r.top), r.width(), r.height(), _backBuffer1.getPixelFormat());
+	_sceneSurface.setPixels((byte *)_backBuffer1.getBasePtr(r.left, r.top),
+		r.width(), r.height(), _backBuffer1.format);
 
 	_backBuffer = &_sceneSurface;
 }
@@ -397,8 +330,8 @@ void Screen::resetDisplayBounds() {
 }
 
 Common::Rect Screen::getDisplayBounds() {
-	return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.w(), _sceneSurface.h()) :
-		Common::Rect(0, 0, this->w(), this->h());
+	return (_backBuffer == &_sceneSurface) ? Common::Rect(0, 0, _sceneSurface.width(), _sceneSurface.height()) :
+		Common::Rect(0, 0, this->width(), this->height());
 }
 
 void Screen::synchronize(Serializer &s) {
diff --git a/engines/sherlock/screen.h b/engines/sherlock/screen.h
index 04a0c1e..ceeb129 100644
--- a/engines/sherlock/screen.h
+++ b/engines/sherlock/screen.h
@@ -25,52 +25,30 @@
 
 #include "common/list.h"
 #include "common/rect.h"
+#include "graphics/screen.h"
+#include "sherlock/image_file.h"
 #include "sherlock/surface.h"
 #include "sherlock/resources.h"
 #include "sherlock/saveload.h"
 
 namespace Sherlock {
 
-#define PALETTE_SIZE 768
-#define PALETTE_COUNT 256
 #define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
 #define BG_GREYSCALE_RANGE_END 229
 #define BLACK 0
 
 class SherlockEngine;
 
-class Screen : public Surface {
+class Screen : virtual public Graphics::Screen, virtual public Surface {
 private:
-	Common::List<Common::Rect> _dirtyRects;
 	uint32 _transitionSeed;
 	Surface _sceneSurface;
 
 	// Rose Tattoo fields
 	int _fadeBytesRead, _fadeBytesToRead;
 	int _oldFadePercent;
-private:
-	/**
-	 * Merges together overlapping dirty areas of the screen
-	 */
-	void mergeDirtyRects();
-
-	/**
-	 * Returns the union of two dirty area rectangles
-	 */
-	bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
 protected:
 	SherlockEngine *_vm;
-
-	/**
-	 * Clear the current dirty rects list
-	 */
-	void clearDirtyRects() { _dirtyRects.clear(); }
-
-	/**
-	 * Adds a rectangle to the list of modified areas of the screen during the
-	 * current frame
-	 */
-	virtual void addDirtyRect(const Common::Rect &r);
 public:
 	Surface _backBuffer1, _backBuffer2;
 	Surface *_backBuffer;
@@ -86,26 +64,6 @@ public:
 	virtual ~Screen();
 
 	/**
-	 * Handles updating any dirty areas of the screen Surface object to the physical screen
-	 */
-	void update();
-
-	/**
-	 * Makes the whole screen dirty
-	 */
-	void makeAllDirty();
-
-	/**
-	 * Return the currently active palette
-	 */
-	void getPalette(byte palette[PALETTE_SIZE]);
-
-	/**
-	 * Set the palette
-	 */
-	void setPalette(const byte palette[PALETTE_SIZE]);
-
-	/**
 	 * Fades from the currently active palette to the passed palette
 	 */
 	int equalizePalette(const byte palette[PALETTE_SIZE]);
diff --git a/engines/sherlock/sherlock.h b/engines/sherlock/sherlock.h
index b85321c..d3b2d0c 100644
--- a/engines/sherlock/sherlock.h
+++ b/engines/sherlock/sherlock.h
@@ -63,9 +63,9 @@ enum GameType {
 	GType_RoseTattoo = 1
 };
 
-#define SHERLOCK_SCREEN_WIDTH _vm->_screen->w()
-#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->h()
-#define SHERLOCK_SCENE_WIDTH _vm->_screen->_backBuffer1.w()
+#define SHERLOCK_SCREEN_WIDTH _vm->_screen->width()
+#define SHERLOCK_SCREEN_HEIGHT _vm->_screen->height()
+#define SHERLOCK_SCENE_WIDTH _vm->_screen->_backBuffer1.width()
 #define SHERLOCK_SCENE_HEIGHT (IS_SERRATED_SCALPEL ? 138 : 480)
 #define SCENES_COUNT (IS_SERRATED_SCALPEL ? 63 : 101)
 #define MAX_BGSHAPES (IS_SERRATED_SCALPEL ? 64 : 150)
diff --git a/engines/sherlock/surface.cpp b/engines/sherlock/surface.cpp
index b7fc763..46304e1 100644
--- a/engines/sherlock/surface.cpp
+++ b/engines/sherlock/surface.cpp
@@ -21,245 +21,24 @@
  */
 
 #include "sherlock/surface.h"
-#include "sherlock/sherlock.h"
-#include "sherlock/resources.h"
-#include "common/system.h"
-#include "graphics/palette.h"
+#include "sherlock/fonts.h"
 
 namespace Sherlock {
 
-Surface::Surface(uint16 width, uint16 height) : Fonts(), _freePixels(true) {
-	create(width, height);
-}
-
-Surface::Surface() : Fonts(), _freePixels(false) {
-}
-
-Surface::~Surface() {
-	if (_freePixels)
-		_surface.free();
-}
-
-void Surface::create(uint16 width, uint16 height) {
-	if (_freePixels)
-		_surface.free();
-
-	if (_vm->getPlatform() == Common::kPlatform3DO) {
-		_surface.create(width, height, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
-	} else {
-		_surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-	}
-	_freePixels = true;
-}
-
-Graphics::PixelFormat Surface::getPixelFormat() {
-	return _surface.format;
-}
-
-void Surface::blitFrom(const Surface &src) {
-	blitFrom(src, Common::Point(0, 0));
-}
-
-void Surface::blitFrom(const ImageFrame &src) {
-	blitFrom(src._frame, Common::Point(0, 0));
-}
-
-void Surface::blitFrom(const Graphics::Surface &src) {
-	blitFrom(src, Common::Point(0, 0));
-}
-
-void Surface::blitFrom(const Surface &src, const Common::Point &pt) {
-	blitFrom(src, pt, Common::Rect(0, 0, src._surface.w, src._surface.h));
-}
-
-void Surface::blitFrom(const ImageFrame &src, const Common::Point &pt) {
-	blitFrom(src._frame, pt, Common::Rect(0, 0, src._frame.w, src._frame.h));
-}
-
-void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt) {
-	blitFrom(src, pt, Common::Rect(0, 0, src.w, src.h));
-}
-
-void Surface::blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
-	Common::Rect srcRect = srcBounds;
-	Common::Rect destRect(pt.x, pt.y, pt.x + srcRect.width(), pt.y + srcRect.height());
-
-	if (srcRect.isValidRect() && clip(srcRect, destRect)) {
-		// Surface is at least partially or completely on-screen
-		addDirtyRect(destRect);
-		_surface.copyRectToSurface(src, destRect.left, destRect.top, srcRect);
-	}
-}
-
-void Surface::blitFrom(const ImageFrame &src, const Common::Point &pt, const Common::Rect &srcBounds) {
-	blitFrom(src._frame, pt, srcBounds);
-}
-
-void Surface::blitFrom(const Surface &src, const Common::Point &pt, const Common::Rect &srcBounds) {
-	blitFrom(src._surface, pt, srcBounds);
-}
-
-void Surface::transBlitFrom(const ImageFrame &src, const Common::Point &pt,
-		bool flipped, int overrideColor, int scaleVal) {
-	Common::Point drawPt(pt.x + src.sDrawXOffset(scaleVal), pt.y + src.sDrawYOffset(scaleVal));
-	transBlitFrom(src._frame, drawPt, flipped, overrideColor, scaleVal);
-}
-
-void Surface::transBlitFrom(const Surface &src, const Common::Point &pt,
-		bool flipped, int overrideColor, int scaleVal) {
-	const Graphics::Surface &s = src._surface;
-	transBlitFrom(s, pt, flipped, overrideColor, scaleVal);
-}
-
-void Surface::transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
-		bool flipped, int overrideColor, int scaleVal) {
-	if (scaleVal == SCALE_THRESHOLD) {
-		transBlitFromUnscaled(src, pt, flipped, overrideColor);
-		return;
-	}
-
-	int destWidth = src.w * SCALE_THRESHOLD / scaleVal;
-	int destHeight = src.h * SCALE_THRESHOLD / scaleVal;
-
-	// Loop through drawing output lines
-	for (int destY = pt.y, scaleYCtr = 0; destY < (pt.y + destHeight); ++destY, scaleYCtr += scaleVal) {
-		if (destY < 0 || destY >= this->h())
-			continue;
-		const byte *srcLine = (const byte *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD);
-		byte *destLine = (byte *)getBasePtr(pt.x, destY);
-
-		// Loop through drawing individual rows
-		for (int xCtr = 0, scaleXCtr = 0; xCtr < destWidth; ++xCtr, scaleXCtr += scaleVal) {
-			int destX = pt.x + xCtr;
-			if (destX < 0 || destX >= this->w())
-				continue;
-
-			byte srcVal = srcLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD];
-			if (srcVal != TRANSPARENCY)
-				destLine[xCtr] = srcVal;
-		}
-	}
-
-	// Mark the affected area
-	addDirtyRect(Common::Rect(pt.x, pt.y, pt.x + destWidth, pt.y + destHeight));
-}
-
-void Surface::transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt,
-		bool flipped, int overrideColor) {
-	Common::Rect drawRect(0, 0, src.w, src.h);
-	Common::Rect destRect(pt.x, pt.y, pt.x + src.w, pt.y + src.h);
-
-	// Clip the display area to on-screen
-	if (!clip(drawRect, destRect))
-		// It's completely off-screen
-		return;
-
-	if (flipped)
-		drawRect = Common::Rect(src.w - drawRect.right, drawRect.top,
-			src.w - drawRect.left, drawRect.bottom);
-
-	Common::Point destPt(destRect.left, destRect.top);
-	addDirtyRect(Common::Rect(destPt.x, destPt.y, destPt.x + drawRect.width(),
-		destPt.y + drawRect.height()));
-
-	switch (src.format.bytesPerPixel) {
-	case 1:
-		// 8-bit palettized: Draw loop
-		assert(_surface.format.bytesPerPixel == 1); // Security check
-		for (int yp = 0; yp < drawRect.height(); ++yp) {
-			const byte *srcP = (const byte *)src.getBasePtr(
-				flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
-			byte *destP = (byte *)getBasePtr(destPt.x, destPt.y + yp);
-
-			for (int xp = 0; xp < drawRect.width(); ++xp, ++destP) {
-				if (*srcP != TRANSPARENCY)
-					*destP = overrideColor ? overrideColor : *srcP;
-
-				srcP = flipped ? srcP - 1 : srcP + 1;
-			}
-		}
-		break;
-	case 2:
-		// 3DO 15-bit RGB565: Draw loop
-		assert(_surface.format.bytesPerPixel == 2); // Security check
-		for (int yp = 0; yp < drawRect.height(); ++yp) {
-			const uint16 *srcP = (const uint16 *)src.getBasePtr(
-				flipped ? drawRect.right - 1 : drawRect.left, drawRect.top + yp);
-			uint16 *destP = (uint16 *)getBasePtr(destPt.x, destPt.y + yp);
-
-			for (int xp = 0; xp < drawRect.width(); ++xp, ++destP) {
-				if (*srcP) // RGB 0, 0, 0 -> transparent on 3DO
-					*destP = *srcP; // overrideColor ? overrideColor : *srcP;
-
-				srcP = flipped ? srcP - 1 : srcP + 1;
-			}
-		}
-		break;
-	default:
-		error("Surface: unsupported bytesperpixel");
-		break;
-	}
+Surface::Surface() : Graphics::ManagedSurface(), Fonts() {
 }
 
-void Surface::fillRect(int x1, int y1, int x2, int y2, uint color) {
-	fillRect(Common::Rect(x1, y1, x2, y2), color);
-}
-
-void Surface::fillRect(const Common::Rect &r, uint color) {
-	_surface.fillRect(r, color);
-	addDirtyRect(r);
-}
-
-void Surface::fill(uint color) {
-	fillRect(Common::Rect(_surface.w, _surface.h), color);
-}
-
-bool Surface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) {
-	if (destBounds.left >= w() || destBounds.top >= h() ||
-			destBounds.right <= 0 || destBounds.bottom <= 0)
-		return false;
-
-	// Clip the bounds if necessary to fit on-screen
-	if (destBounds.right > w()) {
-		srcBounds.right -= destBounds.right - w();
-		destBounds.right = w();
-	}
-
-	if (destBounds.bottom > h()) {
-		srcBounds.bottom -= destBounds.bottom - h();
-		destBounds.bottom = h();
-	}
-
-	if (destBounds.top < 0) {
-		srcBounds.top += -destBounds.top;
-		destBounds.top = 0;
-	}
-
-	if (destBounds.left < 0) {
-		srcBounds.left += -destBounds.left;
-		destBounds.left = 0;
-	}
-
-	return true;
-}
-
-void Surface::clear() {
-	fillRect(Common::Rect(0, 0, w(), h()), 0);
-}
-
-void Surface::free() {
-	if (_freePixels) {
-		_surface.free();
-		_freePixels = false;
-	}
+Surface::Surface(int width, int height) : Graphics::ManagedSurface(width, height),
+		Fonts() {
+	create(width, height);
 }
 
-void Surface::setPixels(byte *pixels, int width, int height, Graphics::PixelFormat pixelFormat) {
-	_surface.format = pixelFormat;
-	_surface.w = width;
-	_surface.h = height;
-	_surface.pitch = width * pixelFormat.bytesPerPixel;
-	_surface.setPixels(pixels);
+void Surface::setPixels(byte *pixelsPtr, int sizeX, int sizeY, const Graphics::PixelFormat &pixFormat) {
+	Graphics::ManagedSurface::setPixels(pixelsPtr);
+	this->format = pixFormat;
+	this->w = sizeX;
+	this->h = sizeY;
+	this->pitch = sizeX * pixFormat.bytesPerPixel;
 }
 
 void Surface::writeString(const Common::String &str, const Common::Point &pt, uint overrideColor) {
@@ -278,4 +57,21 @@ void Surface::writeFancyString(const Common::String &str, const Common::Point &p
 	writeString(str, Common::Point(pt.x + 1, pt.y + 1), overrideColor2);
 }
 
+void Surface::SHtransBlitFrom(const ImageFrame &src, const Common::Point &pt,
+		bool flipped, int overrideColor, int scaleVal) {
+	Common::Point drawPt(pt.x + src.sDrawXOffset(scaleVal), pt.y + src.sDrawYOffset(scaleVal));
+	SHtransBlitFrom(src._frame, drawPt, flipped, overrideColor, scaleVal);
+}
+
+void Surface::SHtransBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
+		bool flipped, int overrideColor, int scaleVal) {
+	Common::Rect srcRect(0, 0, src.w, src.h);
+	Common::Rect destRect(pt.x, pt.y, pt.x + src.w * SCALE_THRESHOLD / scaleVal,
+		pt.y + src.h * SCALE_THRESHOLD / scaleVal);
+	
+	Graphics::ManagedSurface::transBlitFrom(src, srcRect, destRect, TRANSPARENCY,
+		flipped, overrideColor);
+}
+
+
 } // End of namespace Sherlock
diff --git a/engines/sherlock/surface.h b/engines/sherlock/surface.h
index 378c9be..648b121 100644
--- a/engines/sherlock/surface.h
+++ b/engines/sherlock/surface.h
@@ -20,165 +20,101 @@
  *
  */
 
-#ifndef SHERLOCK_GRAPHICS_H
-#define SHERLOCK_GRAPHICS_H
+#ifndef SHERLOCK_SURFACE_H
+#define SHERLOCK_SURFACE_H
 
 #include "common/rect.h"
 #include "common/platform.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
 #include "sherlock/fonts.h"
+#include "sherlock/image_file.h"
 
 namespace Sherlock {
 
 #define SCALE_THRESHOLD 0x100
 #define TRANSPARENCY 255
 
-struct ImageFrame;
-
-class Surface: public Fonts {
-private:
-	bool _freePixels;
-
-	/**
-	 * Copy a surface into this one
-	 */
-	void blitFrom(const Graphics::Surface &src);
-protected:
-	Graphics::Surface _surface;
-
-	/**
-	 * Clips the given source bounds so the passed destBounds will be entirely on-screen
-	 */
-	bool clip(Common::Rect &srcBounds, Common::Rect &destBounds);
-
-	/**
-	 * Base method stub for signalling dirty rect areas
-	 */
-	virtual void addDirtyRect(const Common::Rect &r) {}
-
-	/**
-	 * Draws a sub-section of a surface at a given position within this surface
-	 */
-	virtual void blitFrom(const Graphics::Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
+/**
+ * Implements a descendent surface that combines both a managed surface and the font
+ * drawing code. It also introduces a series of drawing method stubs that the 3DO
+ * Serrated Scalpel screen overrides to implement sprite doubling
+ */
+class Surface: virtual public Graphics::ManagedSurface, public Fonts {
+public:
 	/**
-	 * Draws a surface at a given position within this surface with transparency
+	 * Constructor
 	 */
-	virtual void transBlitFromUnscaled(const Graphics::Surface &src, const Common::Point &pt, bool flipped, 
-		int overrideColor);
-public:
-	Surface(uint16 width, uint16 height);
 	Surface();
-	virtual ~Surface();
-
+	
 	/**
-	 * Sets up an internal surface with the specified dimensions that will be automatically freed
-	 * when the surface object is destroyed
+	 * Constructor
 	 */
-	void create(uint16 width, uint16 height);
-
-	Graphics::PixelFormat getPixelFormat();
+	Surface(int width, int height);
 
 	/**
-	 * Copy a surface into this one
+	 * Set the surface details
 	 */
-	void blitFrom(const Surface &src);
+	void setPixels(byte *pixelsPtr, int sizeX, int sizeY, const Graphics::PixelFormat &pixFormat);
 
 	/**
-	 * Copy an image frame into this surface
+	 * Draws a surface on this surface
 	 */
-	void blitFrom(const ImageFrame &src);
+	virtual void SHblitFrom(const Graphics::Surface &src) {
+		Graphics::ManagedSurface::blitFrom(src);
+	}
 
 	/**
 	 * Draws a surface at a given position within this surface
 	 */
-	void blitFrom(const Surface &src, const Common::Point &pt);
-
-	/**
-	 * Copy an image frame onto this surface at a given position
-	 */
-	void blitFrom(const ImageFrame &src, const Common::Point &pt);
+	virtual void SHblitFrom(const Graphics::Surface &src, const Common::Point &destPos) {
+		Graphics::ManagedSurface::blitFrom(src, destPos);
+	}
 
 	/**
 	 * Draws a sub-section of a surface at a given position within this surface
 	 */
-	void blitFrom(const Surface &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
-	/**
-	 * Copy a sub-area of a source image frame into this surface at a given position
-	 */
-	void blitFrom(const ImageFrame &src, const Common::Point &pt, const Common::Rect &srcBounds);
-
-	/**
-	 * Draws a surface at a given position within this surface
-	 */
-	void blitFrom(const Graphics::Surface &src, const Common::Point &pt);
+	virtual void SHblitFrom(const Graphics::Surface &src, const Common::Point &destPos, const Common::Rect &srcBounds) {
+		Graphics::ManagedSurface::blitFrom(src, srcBounds, destPos);
+	}
 
 	/**
 	 * Draws an image frame at a given position within this surface with transparency
 	 */
-	void transBlitFrom(const ImageFrame &src, const Common::Point &pt,
-		bool flipped = false, int overrideColor = 0, int scaleVal = 256);
-	
-	/**
-	* Draws a surface at a given position within this surface with transparency
-	*/
-	void transBlitFrom(const Surface &src, const Common::Point &pt,
-		bool flipped = false, int overrideColor = 0, int scaleVal = 256);
+	void SHtransBlitFrom(const ImageFrame &src, const Common::Point &pt,
+		bool flipped = false, int overrideColor = 0, int scaleVal = SCALE_THRESHOLD);
 
 	/**
-	 * Draws a surface at a given position within this surface with transparency
+	 * Draws an image frame at a given position within this surface with transparency
 	 */
-	void transBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
-		bool flipped = false, int overrideColor = 0, int scaleVal = 256);
+	void SHtransBlitFrom(const Graphics::Surface &src, const Common::Point &pt,
+		bool flipped = false, int overrideColor = 0, int scaleVal = SCALE_THRESHOLD);
 
 	/**
 	 * Fill a given area of the surface with a given color
 	 */
-	void fillRect(int x1, int y1, int x2, int y2, uint color);
-	
-	/**
-	 * Fill a given area of the surface with a given color
-	 */
-	virtual void fillRect(const Common::Rect &r, uint color);
-
-	void fill(uint color);
-
-	/**
-	 * Clear the surface
-	 */
-	void clear();
+	virtual void SHfillRect(const Common::Rect &r, uint color) {
+		Graphics::ManagedSurface::fillRect(r, color);
+	}
 
 	/**
-	 * Free the underlying surface
+	 * Return the width of the surface
 	 */
-	void free();
-
+	virtual uint16 width() const { return this->w; }
+	
 	/**
-	 * Returns true if the surface is empty
+	 * Return the height of the surface
 	 */
-	bool empty() const { return _surface.getPixels() == nullptr; }
+	virtual uint16 height() const { return this->h; }
 
 	/**
-	 * Set the pixels for the surface to an existing data block
+	 * Draws the given string into the back buffer using the images stored in _font
 	 */
-	void setPixels(byte *pixels, int width, int height, Graphics::PixelFormat format);
-
+	void writeString(const Common::String &str, const Common::Point &pt, uint overrideColor);
+	
 	/**
-	 * Draws the given string into the back buffer using the images stored in _font
+	 * Draws a fancy version of the given string at the given position
 	 */
-	virtual void writeString(const Common::String &str, const Common::Point &pt, uint overrideColor);
 	void writeFancyString(const Common::String &str, const Common::Point &pt, uint overrideColor1, uint overrideColor2);
-
-	inline virtual uint16 w() const { return _surface.w; }
-	inline virtual uint16 h() const { return _surface.h; }
-	inline const byte *getPixels() const { return (const byte *)_surface.getPixels(); }
-	inline byte *getPixels() { return (byte *)_surface.getPixels(); }
-	inline byte *getBasePtr(int x, int y) { return (byte *)_surface.getBasePtr(x, y); }
-	inline const byte *getBasePtr(int x, int y) const { return (const byte *)_surface.getBasePtr(x, y); }
-	inline Graphics::Surface &getRawSurface() { return _surface; }
-	inline void hLine(int x, int y, int x2, uint color) { _surface.hLine(x, y, x2, color); }
-	inline void vLine(int x, int y, int y2, uint color) { _surface.vLine(x, y, y2, color); }
 };
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_darts.cpp b/engines/sherlock/tattoo/tattoo_darts.cpp
index 0a815af..cbc3ea1 100644
--- a/engines/sherlock/tattoo/tattoo_darts.cpp
+++ b/engines/sherlock/tattoo/tattoo_darts.cpp
@@ -163,7 +163,7 @@ void Darts::playDarts(GameType gameType) {
 
 			// Show scores
 			showStatus(playerNum);
-			screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+			screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
 				Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
 			screen.print(Common::Point(_dartInfo.left, _dartInfo.top), 0, FIXED(DartsCurrentDart), idx + 1);
 
@@ -267,10 +267,11 @@ void Darts::playDarts(GameType gameType) {
 			} else {
 				events.wait(40);
 			}
+
 			// Clears the status part of the board
-			screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
 				Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
-			screen.blitFrom(screen._backBuffer1);
+			screen.SHblitFrom(screen._backBuffer1);
 		}
 
 		playerNum ^= 1;
@@ -278,9 +279,9 @@ void Darts::playDarts(GameType gameType) {
 			++_roundNum;
 
 		if (!done) {
-			screen._backBuffer2.blitFrom((*_dartBoard)[0], Common::Point(0, 0));
-			screen._backBuffer1.blitFrom(screen._backBuffer2);
-			screen.blitFrom(screen._backBuffer2);
+			screen._backBuffer2.SHblitFrom((*_dartBoard)[0], Common::Point(0, 0));
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2);
+			screen.SHblitFrom(screen._backBuffer2);
 		}
 	}
 
@@ -367,9 +368,9 @@ void Darts::loadDarts() {
 	delete stream;
 
 	// Load the initial background
-	screen._backBuffer1.blitFrom((*_dartBoard)[0], Common::Point(0, 0));
-	screen._backBuffer2.blitFrom(screen._backBuffer1);
-	screen.blitFrom(screen._backBuffer1);
+	screen._backBuffer1.SHblitFrom((*_dartBoard)[0], Common::Point(0, 0));
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1);
+	screen.SHblitFrom(screen._backBuffer1);
 }
 
 void Darts::closeDarts() {
@@ -399,14 +400,14 @@ void Darts::showNames(int playerNum) {
 	screen.fillRect(Common::Rect(STATUS2_INFO_X, STATUS_INFO_Y + _spacing + 1,
 		STATUS2_INFO_X + 50, STATUS_INFO_Y + _spacing + 3), color);
 
-	screen._backBuffer2.blitFrom(screen._backBuffer1);
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1);
 }
 
 void Darts::showStatus(int playerNum) {
 	Screen &screen = *_vm->_screen;
 	const char *const CRICKET_SCORE_NAME[7] = { "20", "19", "18", "17", "16", "15", FIXED(DartsBull) };
 
-	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
 		Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, STATUS_INFO_X + STATUS_INFO_WIDTH,
 		STATUS_INFO_Y + STATUS_INFO_HEIGHT - 10));
 	screen.print(Common::Point(STATUS_INFO_X + 30, STATUS_INFO_Y + _spacing + 4), 0, "%d", _score1);
@@ -447,7 +448,7 @@ void Darts::showStatus(int playerNum) {
 		}
 	}
 
-	screen.blitFrom(screen._backBuffer1, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
+	screen.SHblitFrom(screen._backBuffer1, Common::Point(STATUS_INFO_X, STATUS_INFO_Y + 10),
 		Common::Rect(STATUS_INFO_X, STATUS_INFO_Y + 10, STATUS_INFO_X + STATUS_INFO_WIDTH, 
 			STATUS_INFO_Y + STATUS_INFO_HEIGHT - 10));
 }
@@ -457,7 +458,7 @@ void Darts::erasePowerBars() {
 
 	// Erase the old power bars and replace them with empty ones
 	screen._backBuffer1.fillRect(Common::Rect(DART_BAR_VX, DART_HEIGHT_Y, DART_BAR_VX + 9, DART_HEIGHT_Y + DART_BAR_SIZE), 0);
-	screen._backBuffer1.transBlitFrom((*_dartGraphics)[0], Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1));
+	screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[0], Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1));
 	screen.slamArea(DART_BAR_VX - 1, DART_HEIGHT_Y - 1, 10, DART_BAR_SIZE + 2);
 }
 
@@ -497,7 +498,7 @@ int Darts::doPowerBar(const Common::Point &pt, byte color, int goToPower, int or
 		}
 
 		screen._backBuffer1.hLine(pt.x, pt.y + DART_BAR_SIZE- 1 - idx, pt.x + 8, color);
-		screen._backBuffer1.transBlitFrom((*_dartGraphics)[0], Common::Point(pt.x - 1, pt.y - 1));
+		screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[0], Common::Point(pt.x - 1, pt.y - 1));
 		screen.slamArea(pt.x, pt.y + DART_BAR_SIZE - 1 - idx, 8, 2);
 
 		if (!(idx % 8))
@@ -544,7 +545,7 @@ int Darts::drawHand(int goToPower, int computer) {
 				break;
 		}
 
-		screen._backBuffer1.transBlitFrom((*hands)[0], pt);
+		screen._backBuffer1.SHtransBlitFrom((*hands)[0], pt);
 		screen.slamArea(pt.x - 1, pt.y, _handSize.x + 1, _handSize.y);
 		screen.restoreBackground(Common::Rect(pt.x, pt.y, pt.x + _handSize.x, pt.y + _handSize.y));
 
@@ -631,7 +632,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 		_handSize.y = hands[idx]._offset.y + hands[idx]._height;
 		int handCy = SHERLOCK_SCREEN_HEIGHT - _handSize.y;
 
-		screen._backBuffer1.transBlitFrom(hands[idx], Common::Point(_handX, handCy));
+		screen._backBuffer1.SHtransBlitFrom(hands[idx], Common::Point(_handX, handCy));
 		screen.slamArea(_handX, handCy, _handSize.x + 1, _handSize.y);
 		screen.slamArea(handOCx, handOCy, handOldxSize, handOldySize);
 		screen.restoreBackground(Common::Rect(_handX, handCy, _handX + _handSize.x, handCy + _handSize.y));
@@ -653,7 +654,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 			ocy = drawPos.y = cy - (*_dartGraphics)[dartNum]._height;
 
 			// Draw dart
-			screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], drawPos);
+			screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[dartNum], drawPos);
 
 			if (drawPos.x < 0) {
 				xSize += drawPos.x;
@@ -675,7 +676,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 				// Flush the erased dart area
 				screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize); 
 
-			screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y), 
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y), 
 				Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize));
 
 			oldDrawPos.x = drawPos.x;
@@ -696,7 +697,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 	if (oldDrawPos.x != -1)
 		screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
 
-	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(drawPos.x, drawPos.y),
 		Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize));
 
 	cx = dartPos.x;
@@ -722,7 +723,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 		ocx = drawPos.x = cx - (*_dartGraphics)[dartNum]._width / 2;
 		ocy = drawPos.y = cy - (*_dartGraphics)[dartNum]._height;
 
-		screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawPos.x, drawPos.y));
+		screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[dartNum], Common::Point(drawPos.x, drawPos.y));
 
 		if (drawPos.x < 0) {
 			xSize += drawPos.x;
@@ -744,7 +745,7 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 			screen.slamArea(oldDrawPos.x, oldDrawPos.y, oldxSize, oldySize);
 
 		if (idx != 23)
-			screen._backBuffer1.blitFrom(screen._backBuffer2, drawPos, 
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, drawPos, 
 				Common::Rect(drawPos.x, drawPos.y, drawPos.x + xSize, drawPos.y + ySize)); // erase dart
 
 		events.wait(1);
@@ -761,8 +762,8 @@ void Darts::drawDartThrow(const Common::Point &dartPos, int computer) {
 	ySize = (*_dartGraphics)[dartNum]._height;
 
 	// Draw final dart on the board
-	screen._backBuffer1.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
-	screen._backBuffer2.transBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
+	screen._backBuffer1.SHtransBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
+	screen._backBuffer2.SHtransBlitFrom((*_dartGraphics)[dartNum], Common::Point(ocx, ocy));
 	screen.slamArea(ocx, ocy, xSize, ySize);
 }
 
@@ -955,9 +956,9 @@ int Darts::throwDart(int dartNum, int computer) {
 	}
 
 	drawDartsLeft(dartNum + 1, computer);
-	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(_dartInfo.left, _dartInfo.top - 1),
 		Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
-	screen.blitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
+	screen.SHblitFrom(screen._backBuffer1, Common::Point(_dartInfo.left, _dartInfo.top - 1),
 		Common::Rect(_dartInfo.left, _dartInfo.top - 1, _dartInfo.right, _dartInfo.bottom - 1));
 
 	if (computer) {
@@ -979,7 +980,7 @@ int Darts::throwDart(int dartNum, int computer) {
 	height = 101 - height;
 
 	// Copy power bars to the secondary back buffer
-	screen._backBuffer2.blitFrom(screen._backBuffer1, Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1),
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1, Common::Point(DART_BAR_VX - 1, DART_HEIGHT_Y - 1),
 		Common::Rect(DART_BAR_VX - 1, DART_HEIGHT_Y - 1, DART_BAR_VX - 1 + 10, 
 		DART_HEIGHT_Y - 1 + DART_BAR_SIZE + 2));
 
@@ -1023,14 +1024,14 @@ void Darts::drawDartsLeft(int dartNum, int computer) {
 	const int DART_X2[3] = { 393, 441, 502 };
 	const int DART_Y2[3] = { 373, 373, 373 };
 
-	screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(DART_X1[0], DART_Y1[0]),
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(DART_X1[0], DART_Y1[0]),
 		Common::Rect(DART_X1[0], DART_Y1[0], SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 
 	for (int idx = 2; idx >= dartNum - 1; --idx) {
 		if (computer)
-			screen._backBuffer1.transBlitFrom((*_dartsLeft)[idx + 3], Common::Point(DART_X2[idx], DART_Y2[idx]));
+			screen._backBuffer1.SHtransBlitFrom((*_dartsLeft)[idx + 3], Common::Point(DART_X2[idx], DART_Y2[idx]));
 		else
-			screen._backBuffer1.transBlitFrom((*_dartsLeft)[idx], Common::Point(DART_X1[idx], DART_Y1[idx]));
+			screen._backBuffer1.SHtransBlitFrom((*_dartsLeft)[idx], Common::Point(DART_X1[idx], DART_Y1[idx]));
 	}
 
 	screen.slamArea(DART_X1[0], DART_Y1[0], SHERLOCK_SCREEN_WIDTH - DART_X1[0], SHERLOCK_SCREEN_HEIGHT - DART_Y1[0]);
diff --git a/engines/sherlock/tattoo/tattoo_journal.cpp b/engines/sherlock/tattoo/tattoo_journal.cpp
index dac0760..918887f 100644
--- a/engines/sherlock/tattoo/tattoo_journal.cpp
+++ b/engines/sherlock/tattoo/tattoo_journal.cpp
@@ -65,7 +65,7 @@ void TattooJournal::show() {
 	delete stream;
 
 	// Set screen to black, and set background
-	screen._backBuffer1.blitFrom((*_journalImages)[0], Common::Point(0, 0));
+	screen._backBuffer1.SHblitFrom((*_journalImages)[0], Common::Point(0, 0));
 	screen.empty();
 	screen.setPalette(palette);
 
@@ -461,7 +461,7 @@ void TattooJournal::loadLocations() {
 void TattooJournal::drawFrame() {
 	Screen &screen = *_vm->_screen;
 
-	screen._backBuffer1.blitFrom((*_journalImages)[0], Common::Point(0, 0));
+	screen._backBuffer1.SHblitFrom((*_journalImages)[0], Common::Point(0, 0));
 	drawControls(0);
 
 }
@@ -486,10 +486,10 @@ void TattooJournal::drawControls(int mode) {
 		screen._backBuffer1.fillRect(inner, MENU_BACKGROUND);
 
 	// Draw the four corners of the info box
-	screen._backBuffer1.transBlitFrom(images[0], Common::Point(r.left, r.top));
-	screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.top));
-	screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.left, r.bottom - images[1]._height));
-	screen._backBuffer1.transBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.bottom - images[1]._height));
+	screen._backBuffer1.SHtransBlitFrom(images[0], Common::Point(r.left, r.top));
+	screen._backBuffer1.SHtransBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.top));
+	screen._backBuffer1.SHtransBlitFrom(images[1], Common::Point(r.left, r.bottom - images[1]._height));
+	screen._backBuffer1.SHtransBlitFrom(images[1], Common::Point(r.right - images[1]._width, r.bottom - images[1]._height));
 
 	// Draw the top of the info box
 	screen._backBuffer1.hLine(r.left + images[0]._width, r.top, r.right - images[0]._height, INFO_TOP);
@@ -513,8 +513,8 @@ void TattooJournal::drawControls(int mode) {
 
 	// Draw the sides of the separator bar above the scroll bar
 	int yp = r.top + screen.fontHeight() + 7;
-	screen._backBuffer1.transBlitFrom(images[4], Common::Point(r.left, yp - 1));
-	screen._backBuffer1.transBlitFrom(images[5], Common::Point(r.right - images[5]._width, yp - 1));
+	screen._backBuffer1.SHtransBlitFrom(images[4], Common::Point(r.left, yp - 1));
+	screen._backBuffer1.SHtransBlitFrom(images[5], Common::Point(r.right - images[5]._width, yp - 1));
 
 	// Draw the bar above the scroll bar
 	screen._backBuffer1.hLine(r.left + images[4]._width, yp, r.right - images[5]._width, INFO_TOP);
@@ -525,8 +525,8 @@ void TattooJournal::drawControls(int mode) {
 		// Draw the Bars separating the Journal Commands
 		int xp = r.right / 3;
 		for (int idx = 0; idx < 2; ++idx) {
-			screen._backBuffer1.transBlitFrom(images[6], Common::Point(xp - 2, r.top + 1));
-			screen._backBuffer1.transBlitFrom(images[7], Common::Point(xp - 2, yp - 1));
+			screen._backBuffer1.SHtransBlitFrom(images[6], Common::Point(xp - 2, r.top + 1));
+			screen._backBuffer1.SHtransBlitFrom(images[7], Common::Point(xp - 2, yp - 1));
 
 			screen._backBuffer1.hLine(xp - 1, r.top + 4, yp - 2, INFO_TOP);
 			screen._backBuffer1.hLine(xp, r.top + 4, yp - 2, INFO_MIDDLE);
@@ -779,7 +779,7 @@ int TattooJournal::getFindName(bool printError) {
 	
 	// Backup the area under the text entry
 	Surface bgSurface(r.width() - 6, screen.fontHeight());
-	bgSurface.blitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY, 
+	bgSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY, 
 		r.right - 3, cursorY + screen.fontHeight()));
 
 	if (printError) {
@@ -810,7 +810,7 @@ int TattooJournal::getFindName(bool printError) {
 		events.clearEvents();
 
 		// Restore the text background
-		screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left, cursorY));
+		screen._backBuffer1.SHblitFrom(bgSurface, Common::Point(r.left, cursorY));
 
 		// If there was a name already entered, copy it to name and display it
 		if (!_find.empty()) {
@@ -846,7 +846,7 @@ int TattooJournal::getFindName(bool printError) {
 				}
 				else {
 					// Erase cursor by restoring background and writing current text
-					screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
+					screen._backBuffer1.SHblitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
 					screen.gPrint(Common::Point(r.left + screen.widestChar() + 3, cursorY), COMMAND_HIGHLIGHTED, "%s", name.c_str());
 					screen.slamArea(r.left + 3, cursorY, r.width() - 3, screen.fontHeight());
 				}
@@ -912,7 +912,7 @@ int TattooJournal::getFindName(bool printError) {
 			}
 
 			// Redraw the text
-			screen._backBuffer1.blitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
+			screen._backBuffer1.SHblitFrom(bgSurface, Common::Point(r.left + 3, cursorY));
 			screen.gPrint(Common::Point(r.left + screen.widestChar() + 3, cursorY), COMMAND_HIGHLIGHTED,
 				"%s", name.c_str());
 			screen.slamArea(r.left + 3, cursorY, r.right - 3, screen.fontHeight());
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index 4c7e8c8..0839e46 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -105,7 +105,7 @@ int TattooMap::show() {
 	// Load the map image and draw it to the back buffer
 	ImageFile *map = new ImageFile("map.vgs");
 	screen._backBuffer1.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2);
-	screen._backBuffer1.blitFrom((*map)[0], Common::Point(0, 0));
+	screen._backBuffer1.SHblitFrom((*map)[0], Common::Point(0, 0));
 	delete map;
 
 	screen.clear();
@@ -114,7 +114,7 @@ int TattooMap::show() {
 
 	// Copy the map drawn in the back buffer to the secondary back buffer
 	screen._backBuffer2.create(SHERLOCK_SCREEN_WIDTH * 2, SHERLOCK_SCREEN_HEIGHT * 2);
-	screen._backBuffer2.blitFrom(screen._backBuffer1);
+	screen._backBuffer2.SHblitFrom(screen._backBuffer1);
 
 	// Display the built map to the screen
 	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
@@ -148,12 +148,12 @@ int TattooMap::show() {
 
 		if (_targetScroll.x < 0)
 			_targetScroll.x = 0;
-		if ((_targetScroll.x + SHERLOCK_SCREEN_WIDTH) > screen._backBuffer1.w())
-			_targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
+		if ((_targetScroll.x + SHERLOCK_SCREEN_WIDTH) > screen._backBuffer1.width())
+			_targetScroll.x = screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH;
 		if (_targetScroll.y < 0)
 			_targetScroll.y = 0;
-		if ((_targetScroll.y + SHERLOCK_SCREEN_HEIGHT) > screen._backBuffer1.h())
-			_targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
+		if ((_targetScroll.y + SHERLOCK_SCREEN_HEIGHT) > screen._backBuffer1.height())
+			_targetScroll.y = screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT;
 
 		// Check the keyboard
 		if (events.kbHit()) {
@@ -166,8 +166,8 @@ int TattooMap::show() {
 				break;
 
 			case Common::KEYCODE_END:
-				_targetScroll.x = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
-				_targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
+				_targetScroll.x = screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH;
+				_targetScroll.y = screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT;
 				break;
 
 			case Common::KEYCODE_PAGEUP:
@@ -178,8 +178,8 @@ int TattooMap::show() {
 
 			case Common::KEYCODE_PAGEDOWN:
 				_targetScroll.y += SHERLOCK_SCREEN_HEIGHT;
-				if (_targetScroll.y > (screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT))
-					_targetScroll.y = screen._backBuffer1.h() - SHERLOCK_SCREEN_HEIGHT;
+				if (_targetScroll.y > (screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT))
+					_targetScroll.y = screen._backBuffer1.height() - SHERLOCK_SCREEN_HEIGHT;
 				break;
 
 			case Common::KEYCODE_SPACE:
@@ -304,7 +304,7 @@ void TattooMap::drawMapIcons() {
 		if (_data[idx]._iconNum != -1 && _vm->readFlags(idx + 1)) {
 			MapEntry &mapEntry = _data[idx];
 			ImageFrame &img = (*_iconImages)[mapEntry._iconNum];
-			screen._backBuffer1.transBlitFrom(img._frame, Common::Point(mapEntry.x - img._width / 2,
+			screen._backBuffer1.SHtransBlitFrom(img._frame, Common::Point(mapEntry.x - img._width / 2,
 				mapEntry.y - img._height / 2));
 		}
 	}
@@ -355,10 +355,10 @@ void TattooMap::restoreArea(const Common::Rect &bounds) {
 	Screen &screen = *_vm->_screen;
 
 	Common::Rect r = bounds;
-	r.clip(Common::Rect(0, 0, screen._backBuffer1.w(), screen._backBuffer1.h()));
+	r.clip(Common::Rect(0, 0, screen._backBuffer1.width(), screen._backBuffer1.height()));
 
 	if (!r.isEmpty())
-		screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(r.left, r.top), r);
+		screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(r.left, r.top), r);
 }
 
 void TattooMap::showCloseUp(int closeUpNum) {
@@ -407,7 +407,7 @@ void TattooMap::showCloseUp(int closeUpNum) {
 			screen._currentScroll.y + closeUp.y / 100 - picSize.y / 2);
 
 		restoreArea(oldBounds);
-		screen._backBuffer1.transBlitFrom(pic[0], pt, false, 0, scaleVal);
+		screen._backBuffer1.SHtransBlitFrom(pic[0], pt, false, 0, scaleVal);
 
 		screen.slamRect(oldBounds);
 		screen.slamArea(pt.x, pt.y, picSize.x, picSize.y);
@@ -426,7 +426,7 @@ void TattooMap::showCloseUp(int closeUpNum) {
 		screen._currentScroll.y + SHERLOCK_SCREEN_HEIGHT / 2 - pic[0]._height / 2 + pic[0]._height);
 
 	restoreArea(oldBounds);
-	screen._backBuffer1.transBlitFrom(pic[0], Common::Point(r.left, r.top));
+	screen._backBuffer1.SHtransBlitFrom(pic[0], Common::Point(r.left, r.top));
 	screen.slamRect(oldBounds);
 	screen.slamRect(r);
 
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index b83a977..65cc283 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -1042,7 +1042,7 @@ void TattooPerson::walkHolmesToNPC() {
 		holmes._walkDest.x = MAX(_position.x / FIXED_INT_MULTIPLIER - imgFrame.sDrawXSize(scaleVal), 0);
 	} else {
 		holmes._walkDest.x = MIN(_position.x / FIXED_INT_MULTIPLIER + imgFrame.sDrawXSize(scaleVal) * 2,
-			screen._backBuffer1.w() - 1);
+			screen._backBuffer1.width() - 1);
 	}
 
 	// See where Holmes is with respect to the NPC (y coords)
@@ -1168,7 +1168,7 @@ void TattooPerson::centerScreenOnPerson() {
 	TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
 
 	ui._targetScroll.x = CLIP(_position.x / FIXED_INT_MULTIPLIER - SHERLOCK_SCREEN_WIDTH / 2,
-		0, screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH);
+		0, screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH);
 	screen._currentScroll = ui._targetScroll;
 
 	// Reset the default look position to the center of the screen
@@ -1478,7 +1478,7 @@ const Common::Point TattooPeople::restrictToZone(int zoneId, const Common::Point
 	Screen &screen = *_vm->_screen;
 	Common::Rect &r = scene._zones[zoneId];
 
-	if (destPos.x < 0 || destPos.x > screen._backBuffer1.w())
+	if (destPos.x < 0 || destPos.x > screen._backBuffer1.width())
 		return destPos;
 	else if (destPos.y < r.top && r.left < destPos.x && destPos.x < r.right)
 		return Common::Point(destPos.x, r.top);
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 27f3766..00015cb 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -141,15 +141,15 @@ void TattooScene::drawAllShapes() {
 
 		if (obj._type == ACTIVE_BG_SHAPE && obj._misc == BEHIND) {
 			if (obj._quickDraw && obj._scaleVal == SCALE_THRESHOLD)
-				screen._backBuffer1.blitFrom(*obj._imageFrame, obj._position);
+				screen._backBuffer1.SHblitFrom(*obj._imageFrame, obj._position);
 			else
-				screen._backBuffer1.transBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
+				screen._backBuffer1.SHtransBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
 		}
 	}
 
 	// Draw the animation if it is behind the person
 	if (_activeCAnim.active() && _activeCAnim._zPlacement == BEHIND)
-		screen._backBuffer1.transBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
+		screen._backBuffer1.SHtransBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
 			(_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
 
 	screen.resetDisplayBounds();
@@ -194,13 +194,13 @@ void TattooScene::drawAllShapes() {
 		if (se._shape) {
 			// it's a bg shape
 			if (se._shape->_quickDraw && se._shape->_scaleVal == SCALE_THRESHOLD)
-				screen._backBuffer1.blitFrom(*se._shape->_imageFrame, se._shape->_position);
+				screen._backBuffer1.SHblitFrom(*se._shape->_imageFrame, se._shape->_position);
 			else
-				screen._backBuffer1.transBlitFrom(*se._shape->_imageFrame, se._shape->_position,
+				screen._backBuffer1.SHtransBlitFrom(*se._shape->_imageFrame, se._shape->_position,
 					se._shape->_flags & OBJ_FLIPPED, 0, se._shape->_scaleVal);
 		} else if (se._isAnimation) {
 			// It's an active animation
-			screen._backBuffer1.transBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
+			screen._backBuffer1.SHtransBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position,
 				(_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
 		} else {
 			// Drawing person
@@ -212,7 +212,7 @@ void TattooScene::drawAllShapes() {
 
 			if (p._tempScaleVal == SCALE_THRESHOLD) {
 				p._tempX += adjust.x;
-				screen._backBuffer1.transBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
+				screen._backBuffer1.SHtransBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
 					- p.frameHeight() - adjust.y), p._walkSequences[p._sequenceNumber]._horizFlip, 0, p._tempScaleVal);
 			} else {
 				if (adjust.x) {
@@ -242,7 +242,7 @@ void TattooScene::drawAllShapes() {
 						++adjust.y;
 				}
 
-				screen._backBuffer1.transBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
+				screen._backBuffer1.SHtransBlitFrom(*p._imageFrame, Common::Point(p._tempX, p._position.y / FIXED_INT_MULTIPLIER
 					- p._imageFrame->sDrawYSize(p._tempScaleVal) - adjust.y), p._walkSequences[p._sequenceNumber]._horizFlip, 0, p._tempScaleVal);
 			}
 		}
@@ -255,15 +255,15 @@ void TattooScene::drawAllShapes() {
 
 		if (obj._type == ACTIVE_BG_SHAPE && obj._misc == FORWARD) {
 			if (obj._quickDraw && obj._scaleVal == SCALE_THRESHOLD)
-				screen._backBuffer1.blitFrom(*obj._imageFrame, obj._position);
+				screen._backBuffer1.SHblitFrom(*obj._imageFrame, obj._position);
 			else
-				screen._backBuffer1.transBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
+				screen._backBuffer1.SHtransBlitFrom(*obj._imageFrame, obj._position, obj._flags & OBJ_FLIPPED, 0, obj._scaleVal);
 		}
 	}
 
 	// Draw the canimation if it is set as FORWARD
 	if (_activeCAnim.active() && _activeCAnim._zPlacement == FORWARD)
-		screen._backBuffer1.transBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position, (_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
+		screen._backBuffer1.SHtransBlitFrom(_activeCAnim._imageFrame, _activeCAnim._position, (_activeCAnim._flags & 4) >> 1, 0, _activeCAnim._scaleVal);
 
 	// Draw all NO_SHAPE shapes which have their flag bits clear
 	for (uint idx = 0; idx < _bgShapes.size(); ++idx) {
diff --git a/engines/sherlock/tattoo/tattoo_screen.cpp b/engines/sherlock/tattoo/tattoo_screen.cpp
new file mode 100644
index 0000000..c98ae26
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_screen.cpp
@@ -0,0 +1,37 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sherlock/tattoo/tattoo_screen.h"
+#include "sherlock/tattoo/tattoo.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+TattooScreen::TattooScreen(SherlockEngine *vm) : Screen(vm) {
+	_backBuffer1.create(640, 480);
+	_backBuffer2.create(640, 480);
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_screen.h b/engines/sherlock/tattoo/tattoo_screen.h
new file mode 100644
index 0000000..b55e9bb
--- /dev/null
+++ b/engines/sherlock/tattoo/tattoo_screen.h
@@ -0,0 +1,44 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SHERLOCK_TATTOO_SCREEN_H
+#define SHERLOCK_TATTOO_SCREEN_H
+
+#include "sherlock/screen.h"
+
+namespace Sherlock {
+
+class SherlockEngine;
+
+namespace Tattoo {
+
+class TattooScreen : public Screen {
+public:
+	TattooScreen(SherlockEngine *vm);
+	virtual ~TattooScreen() {}
+};
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock
+
+#endif
diff --git a/engines/sherlock/tattoo/tattoo_user_interface.cpp b/engines/sherlock/tattoo/tattoo_user_interface.cpp
index ee028f8..677a662 100644
--- a/engines/sherlock/tattoo/tattoo_user_interface.cpp
+++ b/engines/sherlock/tattoo/tattoo_user_interface.cpp
@@ -72,7 +72,7 @@ TattooUserInterface::~TattooUserInterface() {
 
 void TattooUserInterface::initScrollVars() {
 	Screen &screen = *_vm->_screen;
-	_scrollSize = screen._backBuffer1.w() - SHERLOCK_SCREEN_WIDTH;
+	_scrollSize = screen._backBuffer1.width() - SHERLOCK_SCREEN_WIDTH;
 	_targetScroll = Common::Point(0, 0);
 	screen._currentScroll = Common::Point(0, 0);
 }
@@ -233,7 +233,7 @@ void TattooUserInterface::doJournal() {
 	Common::copy(&lookupTable1[0], &lookupTable1[PALETTE_COUNT], &_lookupTable1[0]);
 
 	// Restore the scene
-	screen._backBuffer1.blitFrom(screen._backBuffer2);
+	screen._backBuffer1.SHblitFrom(screen._backBuffer2);
 	scene.updateBackground();
 	screen.slamArea(screen._currentScroll.x, screen._currentScroll.y, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
 }
@@ -727,7 +727,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
 
 	if (_mask != nullptr) {
 		// Since a mask is active, restore the screen from the secondary back buffer prior to applying the mask
-		screen._backBuffer1.blitFrom(screen._backBuffer2, screen._currentScroll, Common::Rect(screen._currentScroll.x, 0, 
+		screen._backBuffer1.SHblitFrom(screen._backBuffer2, screen._currentScroll, Common::Rect(screen._currentScroll.x, 0, 
 			screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT));
 
 		switch (scene._currentScene) {
@@ -757,7 +757,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
 		case 53:
 			if (++_maskCounter == 2) {
 				_maskCounter = 0;
-				if (++_maskOffset.x == screen._backBuffer1.w())
+				if (++_maskOffset.x == screen._backBuffer1.width())
 					_maskOffset.x = 0;
 			}
 			break;
@@ -779,7 +779,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
 						
 			if ((obj._type == ACTIVE_BG_SHAPE && (obj._maxFrames > 1 || obj._delta.x != 0 || obj._delta.y != 0)) || 
 					obj._type == HIDE_SHAPE || obj._type == REMOVE)
-				screen._backBuffer1.blitFrom(screen._backBuffer2, obj._oldPosition, 
+				screen._backBuffer1.SHblitFrom(screen._backBuffer2, obj._oldPosition, 
 					Common::Rect(obj._oldPosition.x, obj._oldPosition.y, obj._oldPosition.x + obj._oldSize.x,
 						obj._oldPosition.y + obj._oldSize.y));
 		}
@@ -793,7 +793,7 @@ void TattooUserInterface::doBgAnimEraseBackground() {
 		Object &obj = scene._bgShapes[idx];
 
 		if (obj._type == NO_SHAPE && (obj._flags & 1) == 0) {
-			screen._backBuffer1.blitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
+			screen._backBuffer1.SHblitFrom(screen._backBuffer2, obj._position, obj.getNoShapeBounds());
 
 			obj._oldPosition = obj._position;
 			obj._oldSize = obj._noShapeSize;
@@ -870,7 +870,7 @@ void TattooUserInterface::maskArea(Common::SeekableReadStream &mask, const Commo
 	int pixel, len, xp, yp;
 
 	for (yp = 0; yp < ySize; ++yp) {
-		byte *ptr = bb1.getBasePtr(pt.x, pt.y + yp);
+		byte *ptr = (byte *)bb1.getBasePtr(pt.x, pt.y + yp);
 
 		for (xp = 0; xp < xSize;) {
 			// The mask data consists of pairs of pixel/lengths, where all non-zero pixels means that the
@@ -893,7 +893,7 @@ void TattooUserInterface::makeBGArea(const Common::Rect &r) {
 	Screen &screen = *_vm->_screen;
 
 	for (int yp = r.top; yp < r.bottom; ++yp) {
-		byte *ptr = screen._backBuffer1.getBasePtr(r.left, yp);
+		byte *ptr = (byte *)screen._backBuffer1.getBasePtr(r.left, yp);
 
 		for (int xp = r.left; xp < r.right; ++xp, ++ptr)
 			*ptr = _lookupTable[*ptr];
diff --git a/engines/sherlock/tattoo/widget_base.cpp b/engines/sherlock/tattoo/widget_base.cpp
index 8f06491..a35f4e5 100644
--- a/engines/sherlock/tattoo/widget_base.cpp
+++ b/engines/sherlock/tattoo/widget_base.cpp
@@ -88,7 +88,7 @@ void WidgetBase::erase() {
 
 	if (_oldBounds.width() > 0) {
 		// Restore the affected area from the secondary back buffer into the first one, and then copy to screen
-		screen._backBuffer1.blitFrom(screen._backBuffer2, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
+		screen._backBuffer1.SHblitFrom(screen._backBuffer2, Common::Point(_oldBounds.left, _oldBounds.top), _oldBounds);
 		screen.slamRect(_oldBounds);
 
 		// Reset the old bounds so it won't be erased again
@@ -111,7 +111,7 @@ void WidgetBase::draw() {
 		drawBackground();
 
 		// Draw the widget onto the back buffer and then slam it to the screen
-		screen._backBuffer1.transBlitFrom(_surface, Common::Point(_bounds.left, _bounds.top));
+		screen._backBuffer1.SHtransBlitFrom(_surface, Common::Point(_bounds.left, _bounds.top));
 		screen.slamRect(_bounds);
 
 		// Store a copy of the drawn area for later erasing
@@ -183,8 +183,8 @@ void WidgetBase::restrictToScreen() {
 		_bounds.moveTo(_bounds.left, 0);
 	if (_bounds.right > (screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH))
 		_bounds.moveTo(screen._currentScroll.x + SHERLOCK_SCREEN_WIDTH - _bounds.width(), _bounds.top);
-	if (_bounds.bottom > screen._backBuffer1.h())
-		_bounds.moveTo(_bounds.left, screen._backBuffer1.h() - _bounds.height());
+	if (_bounds.bottom > screen._backBuffer1.height())
+		_bounds.moveTo(_bounds.left, screen._backBuffer1.height() - _bounds.height());
 }
 
 void WidgetBase::makeInfoArea(Surface &s) {
@@ -192,30 +192,30 @@ void WidgetBase::makeInfoArea(Surface &s) {
 	ImageFile &images = *ui._interfaceImages;
 
 	// Draw the four corners of the Info Box
-	s.transBlitFrom(images[0], Common::Point(0, 0));
-	s.transBlitFrom(images[1], Common::Point(s.w() - images[1]._width, 0));
-	s.transBlitFrom(images[2], Common::Point(0, s.h() - images[2]._height));
-	s.transBlitFrom(images[3], Common::Point(s.w() - images[3]._width, s.h()));
+	s.SHtransBlitFrom(images[0], Common::Point(0, 0));
+	s.SHtransBlitFrom(images[1], Common::Point(s.width() - images[1]._width, 0));
+	s.SHtransBlitFrom(images[2], Common::Point(0, s.height() - images[2]._height));
+	s.SHtransBlitFrom(images[3], Common::Point(s.width() - images[3]._width, s.height()));
 
 	// Draw the top of the Info Box
-	s.hLine(images[0]._width, 0, s.w() - images[1]._width, INFO_TOP);
-	s.hLine(images[0]._width, 1, s.w() - images[1]._width, INFO_MIDDLE);
-	s.hLine(images[0]._width, 2, s.w() - images[1]._width, INFO_BOTTOM);
+	s.hLine(images[0]._width, 0, s.width() - images[1]._width, INFO_TOP);
+	s.hLine(images[0]._width, 1, s.width() - images[1]._width, INFO_MIDDLE);
+	s.hLine(images[0]._width, 2, s.width() - images[1]._width, INFO_BOTTOM);
 
 	// Draw the bottom of the Info Box
-	s.hLine(images[0]._width, s.h()- 3, s.w() - images[1]._width, INFO_TOP);
-	s.hLine(images[0]._width, s.h()- 2, s.w() - images[1]._width, INFO_MIDDLE);
-	s.hLine(images[0]._width, s.h()- 1, s.w() - images[1]._width, INFO_BOTTOM);
+	s.hLine(images[0]._width, s.height()- 3, s.width() - images[1]._width, INFO_TOP);
+	s.hLine(images[0]._width, s.height()- 2, s.width() - images[1]._width, INFO_MIDDLE);
+	s.hLine(images[0]._width, s.height()- 1, s.width() - images[1]._width, INFO_BOTTOM);
 
 	// Draw the left Side of the Info Box
-	s.vLine(0, images[0]._height, s.h()- images[2]._height, INFO_TOP);
-	s.vLine(1, images[0]._height, s.h()- images[2]._height, INFO_MIDDLE);
-	s.vLine(2, images[0]._height, s.h()- images[2]._height, INFO_BOTTOM);
+	s.vLine(0, images[0]._height, s.height()- images[2]._height, INFO_TOP);
+	s.vLine(1, images[0]._height, s.height()- images[2]._height, INFO_MIDDLE);
+	s.vLine(2, images[0]._height, s.height()- images[2]._height, INFO_BOTTOM);
 
 	// Draw the right Side of the Info Box
-	s.vLine(s.w() - 3, images[0]._height, s.h()- images[2]._height, INFO_TOP);
-	s.vLine(s.w() - 2, images[0]._height, s.h()- images[2]._height, INFO_MIDDLE);
-	s.vLine(s.w() - 1, images[0]._height, s.h()- images[2]._height, INFO_BOTTOM);
+	s.vLine(s.width() - 3, images[0]._height, s.height()- images[2]._height, INFO_TOP);
+	s.vLine(s.width() - 2, images[0]._height, s.height()- images[2]._height, INFO_MIDDLE);
+	s.vLine(s.width() - 1, images[0]._height, s.height()- images[2]._height, INFO_BOTTOM);
 }
 
 void WidgetBase::makeInfoArea() {
diff --git a/engines/sherlock/tattoo/widget_credits.cpp b/engines/sherlock/tattoo/widget_credits.cpp
index 2b37dd3..1c878da 100644
--- a/engines/sherlock/tattoo/widget_credits.cpp
+++ b/engines/sherlock/tattoo/widget_credits.cpp
@@ -37,7 +37,7 @@ void WidgetCredits::initCredits() {
 	Screen &screen = *_vm->_screen;
 	Common::SeekableReadStream *stream = res.load("credits.txt");
 	int spacing = screen.fontHeight() * 2;
-	int yp = screen.h();
+	int yp = screen.height();
 
 	_creditsActive = true;
 	_creditLines.clear();
@@ -60,7 +60,7 @@ void WidgetCredits::initCredits() {
 		} else {
 			int width = screen.stringWidth(line) + 2;
 
-			_creditLines.push_back(CreditLine(line, Common::Point((screen.w() - width) / 2 + 1, yp), width));
+			_creditLines.push_back(CreditLine(line, Common::Point((screen.width() - width) / 2 + 1, yp), width));
 			yp += spacing;
 		}
 	}
@@ -120,10 +120,10 @@ void WidgetCredits::close() {
 
 void WidgetCredits::drawCredits() {
 	Screen &screen = *_vm->_screen;
-	Common::Rect screenRect(0, 0, screen.w(), screen.h());
+	Common::Rect screenRect(0, 0, screen.width(), screen.height());
 	Surface &bb1 = screen._backBuffer1;
 
-	for (uint idx = 0; idx < _creditLines.size() && _creditLines[idx]._position.y < screen.h(); ++idx) {
+	for (uint idx = 0; idx < _creditLines.size() && _creditLines[idx]._position.y < screen.height(); ++idx) {
 		if (screenRect.contains(_creditLines[idx]._position)) {
 			if (!_creditLines[idx]._line2.empty()) {
 				int x1 = _creditLines[idx]._position.x;
@@ -176,7 +176,7 @@ void WidgetCredits::drawCredits() {
 
 void WidgetCredits::blitCredits() {
 	Screen &screen = *_vm->_screen;
-	Common::Rect screenRect(0, -_creditSpeed, screen.w(), screen.h() + _creditSpeed);
+	Common::Rect screenRect(0, -_creditSpeed, screen.width(), screen.height() + _creditSpeed);
 
 	for (uint idx = 0; idx < _creditLines.size(); ++idx) {
 		if (screenRect.contains(_creditLines[idx]._position)) {
@@ -190,7 +190,7 @@ void WidgetCredits::blitCredits() {
 
 void WidgetCredits::eraseCredits() {
 	Screen &screen = *_vm->_screen;
-	Common::Rect screenRect(0, -_creditSpeed, screen.w(), screen.h() + _creditSpeed);
+	Common::Rect screenRect(0, -_creditSpeed, screen.width(), screen.height() + _creditSpeed);
 
 	for (uint idx = 0; idx < _creditLines.size(); ++idx) {
 		if (screenRect.contains(_creditLines[idx]._position)) {
diff --git a/engines/sherlock/tattoo/widget_files.cpp b/engines/sherlock/tattoo/widget_files.cpp
index ff8cb83..7666e81 100644
--- a/engines/sherlock/tattoo/widget_files.cpp
+++ b/engines/sherlock/tattoo/widget_files.cpp
@@ -107,36 +107,36 @@ void WidgetFiles::render(FilesRenderMode mode) {
 	byte color;
 
 	if (mode == RENDER_ALL) {
-		_surface.fill(TRANSPARENCY);
+		_surface.clear(TRANSPARENCY);
 		makeInfoArea();
 
 		switch (_fileMode) {
 		case SAVEMODE_LOAD:
 			_surface.writeString(FIXED(LoadGame),
-				Common::Point((_surface.w() - _surface.stringWidth(FIXED(LoadGame))) / 2, 5), INFO_TOP);
+				Common::Point((_surface.width() - _surface.stringWidth(FIXED(LoadGame))) / 2, 5), INFO_TOP);
 			break;
 
 		case SAVEMODE_SAVE:
 			_surface.writeString(FIXED(SaveGame),
-				Common::Point((_surface.w() - _surface.stringWidth(FIXED(SaveGame))) / 2, 5), INFO_TOP);
+				Common::Point((_surface.width() - _surface.stringWidth(FIXED(SaveGame))) / 2, 5), INFO_TOP);
 			break;
 
 		default:
 			break;
 		}
 
-		_surface.hLine(3, _surface.fontHeight() + 7, _surface.w() - 4, INFO_TOP);
-		_surface.hLine(3, _surface.fontHeight() + 8, _surface.w() - 4, INFO_MIDDLE);
-		_surface.hLine(3, _surface.fontHeight() + 9, _surface.w() - 4, INFO_BOTTOM);
-		_surface.transBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 6));
-		_surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, _surface.fontHeight() + 6));
+		_surface.hLine(3, _surface.fontHeight() + 7, _surface.width() - 4, INFO_TOP);
+		_surface.hLine(3, _surface.fontHeight() + 8, _surface.width() - 4, INFO_MIDDLE);
+		_surface.hLine(3, _surface.fontHeight() + 9, _surface.width() - 4, INFO_BOTTOM);
+		_surface.SHtransBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 6));
+		_surface.SHtransBlitFrom(images[5], Common::Point(_surface.width() - images[5]._width, _surface.fontHeight() + 6));
 
-		int xp = _surface.w() - BUTTON_SIZE - 6;
+		int xp = _surface.width() - BUTTON_SIZE - 6;
 		_surface.vLine(xp, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_TOP);
 		_surface.vLine(xp + 1, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_MIDDLE);
 		_surface.vLine(xp + 2, _surface.fontHeight() + 10, _bounds.height() - 4, INFO_BOTTOM);
-		_surface.transBlitFrom(images[6], Common::Point(xp - 1, _surface.fontHeight() + 8));
-		_surface.transBlitFrom(images[7], Common::Point(xp - 1, _bounds.height() - 4));
+		_surface.SHtransBlitFrom(images[6], Common::Point(xp - 1, _surface.fontHeight() + 8));
+		_surface.SHtransBlitFrom(images[7], Common::Point(xp - 1, _bounds.height() - 4));
 	}
 
 	int xp = _surface.stringWidth("00.") + _surface.widestChar() + 5;
@@ -149,7 +149,7 @@ void WidgetFiles::render(FilesRenderMode mode) {
 			color = INFO_TOP;
 
 		if (mode == RENDER_NAMES_AND_SCROLLBAR)
-			_surface.fillRect(Common::Rect(4, yp, _surface.w() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
+			_surface.fillRect(Common::Rect(4, yp, _surface.width() - BUTTON_SIZE - 9, yp + _surface.fontHeight()), TRANSPARENCY);
 			
 		Common::String numStr = Common::String::format("%d.", idx + 1);
 		_surface.writeString(numStr, Common::Point(_surface.widestChar(), yp), color);
@@ -324,7 +324,7 @@ bool WidgetFiles::getFilename() {
 				filename.setChar(' ', index);
 			}
 
-			_surface.fillRect(Common::Rect(pt.x, pt.y, _surface.w() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
+			_surface.fillRect(Common::Rect(pt.x, pt.y, _surface.width() - BUTTON_SIZE - 9, pt.y + _surface.fontHeight() - 1), TRANSPARENCY);
 			_surface.writeString(filename.c_str() + index, pt, COMMAND_HIGHLIGHTED);
 
 		} else if ((keyState.keycode == Common::KEYCODE_LEFT && index > 0)
@@ -387,7 +387,7 @@ bool WidgetFiles::getFilename() {
 		}
 
 		if ((keyState.ascii >= ' ') && (keyState.ascii <= 'z') && (index < 50)) {
-			if (pt.x + _surface.charWidth(keyState.ascii) < _surface.w() - BUTTON_SIZE - 20) {
+			if (pt.x + _surface.charWidth(keyState.ascii) < _surface.w - BUTTON_SIZE - 20) {
 				if (insert)
 					filename.insertChar(keyState.ascii, index);
 				else
diff --git a/engines/sherlock/tattoo/widget_foolscap.cpp b/engines/sherlock/tattoo/widget_foolscap.cpp
index c8df71e..8225946 100644
--- a/engines/sherlock/tattoo/widget_foolscap.cpp
+++ b/engines/sherlock/tattoo/widget_foolscap.cpp
@@ -103,7 +103,7 @@ void WidgetFoolscap::show() {
 
 	// Set up the window background
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.blitFrom(paperFrame, Common::Point(0, 0));
+	_surface.SHblitFrom(paperFrame, Common::Point(0, 0));
 
 	// If they have already solved the puzzle, put the answer on the graphic
 	if (_vm->readFlags(299)) {
@@ -265,7 +265,7 @@ void WidgetFoolscap::handleKeyboardEvents() {
 void WidgetFoolscap::restoreChar() {
 	Screen &screen = *_vm->_screen;
 	ImageFrame &bgFrame = (*_images)[0];
-	_surface.blitFrom(bgFrame, _cursorPos, Common::Rect(_cursorPos.x, _cursorPos.y,
+	_surface.SHblitFrom(bgFrame, _cursorPos, Common::Rect(_cursorPos.x, _cursorPos.y,
 		_cursorPos.x + screen.widestChar(), _cursorPos.y + screen.fontHeight()));
 }
 
diff --git a/engines/sherlock/tattoo/widget_inventory.cpp b/engines/sherlock/tattoo/widget_inventory.cpp
index b49e30b..34331f0 100644
--- a/engines/sherlock/tattoo/widget_inventory.cpp
+++ b/engines/sherlock/tattoo/widget_inventory.cpp
@@ -94,7 +94,7 @@ void WidgetInventoryTooltip::setText(const Common::String &str) {
 	// Allocate a fresh surface for the new string
 	_bounds = Common::Rect(width, height);
 	_surface.create(width, height);
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 
 	if (line2.empty()) {
 		_surface.writeFancyString(str, Common::Point(0, 0), BLACK, INFO_TOP);
@@ -338,7 +338,7 @@ void WidgetInventoryVerbs::load() {
 
 	// Create the surface
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 	makeInfoArea();
 
 	// Draw the Verb commands and the lines separating them
@@ -352,8 +352,8 @@ void WidgetInventoryVerbs::load() {
 			_surface.vLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 1, _bounds.right - 4, INFO_MIDDLE);
 			_surface.vLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 2, _bounds.right - 4, INFO_BOTTOM);
 
-			_surface.transBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1)));
-			_surface.transBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width,
+			_surface.SHtransBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1)));
+			_surface.SHtransBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width,
 				(_surface.fontHeight() + 7) * (idx + 1) - 1));
 		}
 	}
@@ -515,7 +515,7 @@ void WidgetInventory::load(int mode) {
 
 	// Redraw the inventory menu on the widget surface
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 
 	// Draw the window background and then the inventory on top of it
 	makeInfoArea(_surface);
@@ -531,7 +531,7 @@ void WidgetInventory::drawBars() {
 	_surface.hLine(3, INVENTORY_YSIZE + 3, _bounds.width() - 4, INFO_TOP);
 	_surface.hLine(3, INVENTORY_YSIZE + 4, _bounds.width() - 4, INFO_MIDDLE);
 	_surface.hLine(3, INVENTORY_YSIZE + 5, _bounds.width() - 4, INFO_BOTTOM);
-	_surface.transBlitFrom(images[4], Common::Point(0, INVENTORY_YSIZE + 2));
+	_surface.SHtransBlitFrom(images[4], Common::Point(0, INVENTORY_YSIZE + 2));
 
 	for (int idx = 1; idx <= NUM_INVENTORY_SHOWN / 2; ++idx) {
 		x = idx * (INVENTORY_XSIZE + 3);
@@ -540,10 +540,10 @@ void WidgetInventory::drawBars() {
 		_surface.vLine(x + 1, 3, _bounds.height() - 4, INFO_MIDDLE);
 		_surface.vLine(x + 2, 3, _bounds.height() - 4, INFO_BOTTOM);
 
-		_surface.transBlitFrom(images[6], Common::Point(x - 1, 1));
-		_surface.transBlitFrom(images[7], Common::Point(x - 1, _bounds.height() - 4));
-		_surface.transBlitFrom(images[6], Common::Point(x - 1, INVENTORY_YSIZE + 5));
-		_surface.transBlitFrom(images[7], Common::Point(x - 1, INVENTORY_YSIZE + 2));
+		_surface.SHtransBlitFrom(images[6], Common::Point(x - 1, 1));
+		_surface.SHtransBlitFrom(images[7], Common::Point(x - 1, _bounds.height() - 4));
+		_surface.SHtransBlitFrom(images[6], Common::Point(x - 1, INVENTORY_YSIZE + 5));
+		_surface.SHtransBlitFrom(images[7], Common::Point(x - 1, INVENTORY_YSIZE + 2));
 	}
 
 	_surface.hLine(x + 2, INVENTORY_YSIZE + 2, INVENTORY_YSIZE + 8, INFO_BOTTOM);
@@ -566,7 +566,7 @@ void WidgetInventory::drawInventory() {
 		// Draw the item
 		if (itemId < inv._holdings) {
 			ImageFrame &img = (*inv._invShapes[idx])[0];
-			_surface.transBlitFrom(img, Common::Point(pt.x + (INVENTORY_XSIZE - img._width) / 2,
+			_surface.SHtransBlitFrom(img, Common::Point(pt.x + (INVENTORY_XSIZE - img._width) / 2,
 				pt.y + (INVENTORY_YSIZE - img._height) / 2));
 		}
 	}
diff --git a/engines/sherlock/tattoo/widget_options.cpp b/engines/sherlock/tattoo/widget_options.cpp
index 92bd10b..81f50f3 100644
--- a/engines/sherlock/tattoo/widget_options.cpp
+++ b/engines/sherlock/tattoo/widget_options.cpp
@@ -257,17 +257,17 @@ void WidgetOptions::render(OptionRenderMode mode) {
 
 		// Setup the dialog
 		_surface.create(_bounds.width(), _bounds.height());
-		_surface.fill(TRANSPARENCY);
+		_surface.clear(TRANSPARENCY);
 		makeInfoArea();
 
 		// Draw the lines separating options in the dialog
 		int yp = _surface.fontHeight() + 7;
 		for (int idx = 0; idx < 7; ++idx) {
-			_surface.transBlitFrom(images[4], Common::Point(0, yp - 1));
-			_surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, yp - 1));
-			_surface.hLine(3, yp, _surface.w() - 4, INFO_TOP);
-			_surface.hLine(3, yp + 1, _surface.w() - 4, INFO_MIDDLE);
-			_surface.hLine(3, yp + 2, _surface.w() - 4, INFO_BOTTOM);
+			_surface.SHtransBlitFrom(images[4], Common::Point(0, yp - 1));
+			_surface.SHtransBlitFrom(images[5], Common::Point(_surface.width() - images[5]._width, yp - 1));
+			_surface.hLine(3, yp, _surface.width() - 4, INFO_TOP);
+			_surface.hLine(3, yp + 1, _surface.width() - 4, INFO_MIDDLE);
+			_surface.hLine(3, yp + 2, _surface.width() - 4, INFO_BOTTOM);
 
 			yp += _surface.fontHeight() + 7;
 			if (idx == 1)
@@ -281,7 +281,7 @@ void WidgetOptions::render(OptionRenderMode mode) {
 	for (int idx = 0, yp = 5; idx < 11; ++idx, yp += _surface.fontHeight() + 7) {
 		if (mode == OP_ALL || idx == _selector || idx == _oldSelector) {
 			if (mode == OP_NAMES)
-				_surface.fillRect(Common::Rect(4, yp, _surface.w() - 5, yp + _surface.fontHeight() - 1), TRANSPARENCY);
+				_surface.fillRect(Common::Rect(4, yp, _surface.width() - 5, yp + _surface.fontHeight() - 1), TRANSPARENCY);
 			byte color = (idx == _selector) ? COMMAND_HIGHLIGHTED : INFO_TOP;
 			Common::String str;
 
@@ -302,11 +302,11 @@ void WidgetOptions::render(OptionRenderMode mode) {
 				int num = (_surface.fontHeight() + 4) & 0xfe;
 				int sliderY = yp + num / 2 - 8;
 
-				_surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.w() - 5, 
+				_surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.width() - 5, 
 					sliderY - (num - 6) / 2 + num - 1), TRANSPARENCY);
 				_surface.fillRect(Common::Rect(_surface.widestChar(), sliderY + 2, 
-					_surface.w() - _surface.widestChar() - 1, sliderY + 3), INFO_MIDDLE);
-				drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.w() - _surface.widestChar(), sliderY + 6));
+					_surface.width() - _surface.widestChar() - 1, sliderY + 3), INFO_MIDDLE);
+				drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.width() - _surface.widestChar(), sliderY + 6));
 				
 				_surface.fillRect(Common::Rect(_midiSliderX - 1, sliderY - (num - 6) / 2 + 2, 
 					_midiSliderX + 1, sliderY - (num - 6) / 2 + num - 3), INFO_MIDDLE);
@@ -315,7 +315,7 @@ void WidgetOptions::render(OptionRenderMode mode) {
 	
 				if (_midiSliderX - 4 > _surface.widestChar())
 					_surface.fillRect(Common::Rect(_midiSliderX - 4, sliderY, _midiSliderX - 4, sliderY + 4), INFO_BOTTOM);
-				if (_midiSliderX + 4 < _surface.w() - _surface.widestChar())
+				if (_midiSliderX + 4 < _surface.width() - _surface.widestChar())
 					_surface.fillRect(Common::Rect(_midiSliderX + 4, sliderY, _midiSliderX + 4, sliderY + 4), INFO_BOTTOM);
 				break;
 			}
@@ -332,18 +332,18 @@ void WidgetOptions::render(OptionRenderMode mode) {
 				int num = (_surface.fontHeight() + 4) & 0xfe;
 				int sliderY = yp + num / 2 - 8;
 
-				_surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.w() - 5, 
+				_surface.fillRect(Common::Rect(4, sliderY - (num - 6) / 2, _surface.width() - 5, 
 					sliderY - (num - 6) / 2 + num - 1), TRANSPARENCY);
-				_surface.fillRect(Common::Rect(_surface.widestChar(), sliderY + 2, _surface.w() - _surface.widestChar() - 1, 
+				_surface.fillRect(Common::Rect(_surface.widestChar(), sliderY + 2, _surface.width() - _surface.widestChar() - 1, 
 					sliderY + 3), INFO_MIDDLE);
-				drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.w() - _surface.widestChar(), sliderY + 6));
+				drawDialogRect(Common::Rect(_surface.widestChar(), sliderY, _surface.width() - _surface.widestChar(), sliderY + 6));
 				_surface.fillRect(Common::Rect(_digiSliderX - 1, sliderY - (num - 6) / 2 + 2, _digiSliderX + 1, 
 					sliderY - (num - 6) / 2 + num - 3), INFO_MIDDLE);
 				drawDialogRect(Common::Rect(_digiSliderX - 3, sliderY - (num - 6) / 2, _digiSliderX + 4, 
 					sliderY - (num - 6) / 2 + num));
 				if (_digiSliderX - 4 > _surface.widestChar())
 					_surface.fillRect(Common::Rect(_digiSliderX - 4, sliderY, _digiSliderX - 4, sliderY + 4), INFO_BOTTOM);
-				if (_digiSliderX + 4 < _surface.w() - _surface.widestChar())
+				if (_digiSliderX + 4 < _surface.width() - _surface.widestChar())
 					_surface.fillRect(Common::Rect(_digiSliderX + 4, sliderY, _digiSliderX + 4, sliderY + 4), INFO_BOTTOM);
 				break;
 			}
@@ -375,7 +375,7 @@ void WidgetOptions::render(OptionRenderMode mode) {
 
 			// Unless we're doing one of the Slider Controls, print the text for the line
 			if (idx != 3 && idx != 6) {
-				int xp = (_surface.w() - _surface.stringWidth(str)) / 2;
+				int xp = (_surface.width() - _surface.stringWidth(str)) / 2;
 				_surface.writeString(str, Common::Point(xp, yp), color);
 			}
 		}
diff --git a/engines/sherlock/tattoo/widget_password.cpp b/engines/sherlock/tattoo/widget_password.cpp
index 57a5e02..2a29210 100644
--- a/engines/sherlock/tattoo/widget_password.cpp
+++ b/engines/sherlock/tattoo/widget_password.cpp
@@ -47,7 +47,7 @@ void WidgetPassword::show() {
 
 	// Create the surface
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 	makeInfoArea();
 
 	// Draw the header area
@@ -55,8 +55,8 @@ void WidgetPassword::show() {
 	_surface.hLine(3, _surface.fontHeight() + 7, _bounds.width() - 4, INFO_TOP);
 	_surface.hLine(3, _surface.fontHeight() + 8, _bounds.width() - 4, INFO_MIDDLE);
 	_surface.hLine(3, _surface.fontHeight() + 9, _bounds.width() - 4, INFO_BOTTOM);
-	_surface.transBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 7 - 1));
-	_surface.transBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width, _surface.fontHeight() + 7 - 1));
+	_surface.SHtransBlitFrom(images[4], Common::Point(0, _surface.fontHeight() + 7 - 1));
+	_surface.SHtransBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width, _surface.fontHeight() + 7 - 1));
 
 	// Set the password entry data
 	_cursorPos = Common::Point(_surface.widestChar(), _surface.fontHeight() + 12);
diff --git a/engines/sherlock/tattoo/widget_quit.cpp b/engines/sherlock/tattoo/widget_quit.cpp
index f853e7f..ea8f2e0 100644
--- a/engines/sherlock/tattoo/widget_quit.cpp
+++ b/engines/sherlock/tattoo/widget_quit.cpp
@@ -48,22 +48,22 @@ void WidgetQuit::show() {
 
 	// Create the surface
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 	makeInfoArea();
 
 	// Draw the message text
-	_surface.writeString(FIXED(AreYouSureYou), Common::Point((_surface.w() - _surface.stringWidth(FIXED(AreYouSureYou))) / 2, 5), INFO_TOP);
-	_surface.writeString(FIXED(WishToQuit), Common::Point((_surface.w() - _surface.stringWidth(FIXED(WishToQuit))) / 2,
+	_surface.writeString(FIXED(AreYouSureYou), Common::Point((_surface.width() - _surface.stringWidth(FIXED(AreYouSureYou))) / 2, 5), INFO_TOP);
+	_surface.writeString(FIXED(WishToQuit), Common::Point((_surface.width() - _surface.stringWidth(FIXED(WishToQuit))) / 2,
 		_surface.fontHeight() + 9), INFO_TOP);
 
 	// Draw the horizontal bars seperating the commands and the message
 	int yp = (_surface.fontHeight() + 4) * 2 + 3;
 	for (int idx = 0; idx < 2; ++idx) {
-		_surface.transBlitFrom(images[4], Common::Point(0, yp - 1));
-		_surface.transBlitFrom(images[5], Common::Point(_surface.w() - images[5]._width, yp - 1));
-		_surface.hLine(3, yp, _surface.w() - 4, INFO_TOP);
-		_surface.hLine(3, yp + 1, _surface.w() - 4, INFO_MIDDLE);
-		_surface.hLine(3, yp + 2, _surface.w() - 4, INFO_BOTTOM);
+		_surface.SHtransBlitFrom(images[4], Common::Point(0, yp - 1));
+		_surface.SHtransBlitFrom(images[5], Common::Point(_surface.width() - images[5]._width, yp - 1));
+		_surface.hLine(3, yp, _surface.width() - 4, INFO_TOP);
+		_surface.hLine(3, yp + 1, _surface.width() - 4, INFO_MIDDLE);
+		_surface.hLine(3, yp + 2, _surface.width() - 4, INFO_BOTTOM);
 
 		const char *btn = (idx == 0) ? YES : NO;
 		_surface.writeString(btn, Common::Point((_bounds.width() - _surface.stringWidth(btn)) / 2, yp + 5), INFO_TOP);
@@ -129,11 +129,11 @@ void WidgetQuit::handleEvents() {
 	if (_select != _oldSelect) {
 		byte color = (_select == 1) ? COMMAND_HIGHLIGHTED : INFO_TOP;
 		int yp = (_surface.fontHeight() + 4) * 2 + 8;
-		_surface.writeString(FIXED(Yes), Common::Point((_surface.w() - _surface.stringWidth(FIXED(Yes))) / 2, yp), color);
+		_surface.writeString(FIXED(Yes), Common::Point((_surface.width() - _surface.stringWidth(FIXED(Yes))) / 2, yp), color);
 		
 		color = (_select == 0) ? COMMAND_HIGHLIGHTED : INFO_TOP;
 		yp += (_surface.fontHeight() + 7);
-		_surface.writeString(FIXED(No), Common::Point((_surface.w() - _surface.stringWidth(FIXED(No))) / 2, yp), color);
+		_surface.writeString(FIXED(No), Common::Point((_surface.width() - _surface.stringWidth(FIXED(No))) / 2, yp), color);
 	}
 	_oldSelect = _select;
 
diff --git a/engines/sherlock/tattoo/widget_talk.cpp b/engines/sherlock/tattoo/widget_talk.cpp
index 6e7bde2..b673f32 100644
--- a/engines/sherlock/tattoo/widget_talk.cpp
+++ b/engines/sherlock/tattoo/widget_talk.cpp
@@ -100,7 +100,7 @@ void WidgetTalk::load() {
 
 	// Set up the surface
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 
 	// Form the background for the new window
 	makeInfoArea();
@@ -389,7 +389,7 @@ void WidgetTalk::render(Highlight highlightMode) {
 			if (highlightMode == HL_NO_HIGHLIGHTING || _statementLines[idx]._num == _selector ||
 					_statementLines[idx]._num == _oldSelector) {
 				// Erase the line contents
-				_surface.fillRect(Common::Rect(3, yp, _surface.w() - BUTTON_SIZE - 3, yp + _surface.fontHeight()), TRANSPARENCY);
+				_surface.fillRect(Common::Rect(3, yp, _surface.width() - BUTTON_SIZE - 3, yp + _surface.fontHeight()), TRANSPARENCY);
 
 				// Different coloring based on whether the option has been previously chosen or not
 				byte color = (!talk._talkHistory[talk._converseNum][_statementLines[idx]._num]) ?
diff --git a/engines/sherlock/tattoo/widget_text.cpp b/engines/sherlock/tattoo/widget_text.cpp
index d8d229d..a29cd27 100644
--- a/engines/sherlock/tattoo/widget_text.cpp
+++ b/engines/sherlock/tattoo/widget_text.cpp
@@ -166,7 +166,7 @@ void WidgetText::render(const Common::String &str) {
 
 	// Allocate a surface for the window
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 
 	// Form the background for the new window
 	makeInfoArea();
@@ -195,7 +195,7 @@ void WidgetMessage::load(const Common::String &str, int time) {
 
 	// Allocate a surface for the window
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 
 	// Form the background for the new window and write the line of text
 	makeInfoArea();
diff --git a/engines/sherlock/tattoo/widget_tooltip.cpp b/engines/sherlock/tattoo/widget_tooltip.cpp
index b29f45f..1560cb9 100644
--- a/engines/sherlock/tattoo/widget_tooltip.cpp
+++ b/engines/sherlock/tattoo/widget_tooltip.cpp
@@ -47,7 +47,7 @@ void WidgetTooltipBase::draw() {
 		
 		// Draw the widget directly onto the screen. Unlike other widgets, we don't draw to the back buffer,
 		// since nothing should be drawing on top of tooltips, so there's no need to store in the back buffer
-		screen.transBlitFrom(_surface, Common::Point(_bounds.left - screen._currentScroll.x, 
+		screen.SHtransBlitFrom(_surface, Common::Point(_bounds.left - screen._currentScroll.x, 
 			_bounds.top - screen._currentScroll.y));
 
 		// Store a copy of the drawn area for later erasing
@@ -126,7 +126,7 @@ void WidgetTooltip::setText(const Common::String &str) {
 
 		// Reallocate the text surface with the new size
 		_surface.create(width, height);
-		_surface.fill(TRANSPARENCY);
+		_surface.clear(TRANSPARENCY);
 
 		if (line2.empty()) {
 			// Only a single line
diff --git a/engines/sherlock/tattoo/widget_verbs.cpp b/engines/sherlock/tattoo/widget_verbs.cpp
index 499afb2..5041888 100644
--- a/engines/sherlock/tattoo/widget_verbs.cpp
+++ b/engines/sherlock/tattoo/widget_verbs.cpp
@@ -127,7 +127,7 @@ void WidgetVerbs::render() {
 
 	// Create the drawing surface
 	_surface.create(_bounds.width(), _bounds.height());
-	_surface.fill(TRANSPARENCY);
+	_surface.clear(TRANSPARENCY);
 
 	// Draw basic background
 	makeInfoArea();
@@ -142,8 +142,8 @@ void WidgetVerbs::render() {
 			_surface.hLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 1, _bounds.width() - 4, INFO_MIDDLE);
 			_surface.hLine(3, (_surface.fontHeight() + 7) * (idx + 1) + 2, _bounds.width() - 4, INFO_BOTTOM);
 
-			_surface.transBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1) - 1));
-			_surface.transBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width, 
+			_surface.SHtransBlitFrom(images[4], Common::Point(0, (_surface.fontHeight() + 7) * (idx + 1) - 1));
+			_surface.SHtransBlitFrom(images[5], Common::Point(_bounds.width() - images[5]._width, 
 				(_surface.fontHeight() + 7) * (idx + 1) - 1));
 		}
 	}


Commit: 077250acfb09afb67a445fad30aef6af2e2af014
    https://github.com/scummvm/scummvm/commit/077250acfb09afb67a445fad30aef6af2e2af014
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-14T20:56:28-04:00

Commit Message:
TSAGE: Changed engine to use Graphics::ManagedSurface

Changed paths:
  A engines/tsage/screen.cpp
  A engines/tsage/screen.h
    engines/tsage/blue_force/blueforce_dialogs.cpp
    engines/tsage/blue_force/blueforce_logic.cpp
    engines/tsage/blue_force/blueforce_scenes6.cpp
    engines/tsage/converse.cpp
    engines/tsage/core.cpp
    engines/tsage/events.cpp
    engines/tsage/globals.cpp
    engines/tsage/globals.h
    engines/tsage/graphics.cpp
    engines/tsage/graphics.h
    engines/tsage/module.mk
    engines/tsage/ringworld/ringworld_dialogs.cpp
    engines/tsage/ringworld/ringworld_logic.cpp
    engines/tsage/ringworld/ringworld_scenes3.cpp
    engines/tsage/ringworld/ringworld_scenes5.cpp
    engines/tsage/ringworld2/ringworld2_dialogs.cpp
    engines/tsage/ringworld2/ringworld2_logic.cpp
    engines/tsage/ringworld2/ringworld2_outpost.cpp
    engines/tsage/ringworld2/ringworld2_scenes0.cpp
    engines/tsage/saveload.cpp
    engines/tsage/scenes.cpp
    engines/tsage/tsage.h
    engines/tsage/user_interface.cpp



diff --git a/engines/tsage/blue_force/blueforce_dialogs.cpp b/engines/tsage/blue_force/blueforce_dialogs.cpp
index 5be27c9..3697ca7 100644
--- a/engines/tsage/blue_force/blueforce_dialogs.cpp
+++ b/engines/tsage/blue_force/blueforce_dialogs.cpp
@@ -161,7 +161,7 @@ void RightClickDialog::execute() {
 		}
 
 		g_system->delayMillis(10);
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	// Deactivate the graphics manager used for the dialog
@@ -242,7 +242,7 @@ void AmmoBeltDialog::execute() {
 		}
 
 		g_system->delayMillis(10);
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	_gfxManager.deactivate();
diff --git a/engines/tsage/blue_force/blueforce_logic.cpp b/engines/tsage/blue_force/blueforce_logic.cpp
index e6e7139..2c5f9bd 100644
--- a/engines/tsage/blue_force/blueforce_logic.cpp
+++ b/engines/tsage/blue_force/blueforce_logic.cpp
@@ -859,7 +859,7 @@ void SceneExt::endStrip() {
 }
 
 void SceneExt::clearScreen() {
-	BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+	BF_GLOBALS._screen.clear();
 }
 
 /*--------------------------------------------------------------------------*/
@@ -1411,7 +1411,7 @@ void SceneMessage::process(Event &event) {
 
 
 void SceneMessage::draw() {
-	GfxSurface &surface = BF_GLOBALS._screenSurface;
+	GfxSurface &surface = BF_GLOBALS._screen;
 
 	// Clear the game area
 	surface.fillRect(Rect(0, 0, SCREEN_WIDTH, UI_INTERFACE_Y), 0);
diff --git a/engines/tsage/blue_force/blueforce_scenes6.cpp b/engines/tsage/blue_force/blueforce_scenes6.cpp
index 92534d3..0d6b5c2 100644
--- a/engines/tsage/blue_force/blueforce_scenes6.cpp
+++ b/engines/tsage/blue_force/blueforce_scenes6.cpp
@@ -78,7 +78,7 @@ void Scene600::Action1::signal() {
 			pObj->animate(ANIM_MODE_NONE, NULL);
 		}
 
-		BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+		BF_GLOBALS._screen.fillRect(BF_GLOBALS._screen.getBounds(), 0);
 		scene->loadScene(999);
 		setDelay(5);
 		break;
@@ -275,7 +275,7 @@ void Scene666::postInit(SceneObjectList *OwnerList) {
 	SceneExt::postInit();
 	BF_GLOBALS._interfaceY = SCREEN_HEIGHT;
 	loadScene(999);
-	BF_GLOBALS._screenSurface.fillRect(BF_GLOBALS._screenSurface.getBounds(), 0);
+	BF_GLOBALS._screen.fillRect(BF_GLOBALS._screen.getBounds(), 0);
 
 	if (BF_GLOBALS._dayNumber == 0) {
 		BF_GLOBALS._dayNumber = 1;
diff --git a/engines/tsage/converse.cpp b/engines/tsage/converse.cpp
index d1faca5..7240c91 100644
--- a/engines/tsage/converse.cpp
+++ b/engines/tsage/converse.cpp
@@ -469,7 +469,7 @@ int ConversationChoiceDialog::execute(const Common::StringArray &choiceList) {
 		while (!g_globals->_events.getEvent(event, EVENT_KEYPRESS | EVENT_BUTTON_DOWN | EVENT_MOUSE_MOVE) &&
 				!g_vm->shouldQuit()) {
 			g_system->delayMillis(10);
-			GLOBALS._screenSurface.updateScreen();
+			GLOBALS._screen.update();
 		}
 		if (g_vm->shouldQuit())
 			break;
diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp
index d4068c2..985d16b 100644
--- a/engines/tsage/core.cpp
+++ b/engines/tsage/core.cpp
@@ -1467,7 +1467,7 @@ void ScenePalette::fade(const byte *adjustData, bool fullAdjust, int percent) {
 
 	// Set the altered palette
 	g_system->getPaletteManager()->setPalette((const byte *)&tempPalette[0], 0, 256);
-	GLOBALS._screenSurface.updateScreen();
+	GLOBALS._screen.update();
 }
 
 PaletteRotation *ScenePalette::addRotation(int start, int end, int rotationMode, int duration, Action *action) {
@@ -1524,11 +1524,11 @@ void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) {
 	if (g_vm->getGameID() != GType_Ringworld && g_vm->getGameID() != GType_Sherlock1)
 		tempRect.setHeight(T2_GLOBALS._interfaceY);
 
-	g_globals->_screenSurface.copyFrom(g_globals->_sceneManager._scene->_backSurface,
+	g_globals->_screen.copyFrom(g_globals->_sceneManager._scene->_backSurface,
 		tempRect, Rect(0, 0, tempRect.width(), tempRect.height()), NULL);
 	if (g_vm->getGameID() == GType_Ringworld2 && !GLOBALS._player._uiEnabled
 			&& T2_GLOBALS._interfaceY == UI_INTERFACE_Y) {
-		g_globals->_screenSurface.fillRect(Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT - 1), 0);
+		g_globals->_screen.fillRect(Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT - 1), 0);
 	}
 
 	for (SynchronizedList<PaletteModifier *>::iterator i = tempPalette._listeners.begin(); i != tempPalette._listeners.end(); ++i)
@@ -1796,7 +1796,7 @@ void SceneItem::display(int resNum, int lineNum, ...) {
 		// Keep event on-screen until a mouse or keypress
 		while (!g_vm->shouldQuit() && !g_globals->_events.getEvent(event,
 				EVENT_BUTTON_DOWN | EVENT_KEYPRESS)) {
-			GLOBALS._screenSurface.updateScreen();
+			GLOBALS._screen.update();
 			g_system->delayMillis(10);
 
 			if ((g_vm->getGameID() == GType_Ringworld2) && (R2_GLOBALS._speechSubtitles & SPEECH_VOICE)) {
@@ -2816,7 +2816,7 @@ void SceneObject::updateScreen() {
 		destRect.translate(-sceneBounds.left, -sceneBounds.top);
 		srcRect.translate(-g_globals->_sceneOffset.x, -g_globals->_sceneOffset.y);
 
-		g_globals->_screenSurface.copyFrom(g_globals->_sceneManager._scene->_backSurface, srcRect, destRect);
+		g_globals->_screen.copyFrom(g_globals->_sceneManager._scene->_backSurface, srcRect, destRect);
 	}
 }
 
diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp
index 0491c04..1fa1702 100644
--- a/engines/tsage/events.cpp
+++ b/engines/tsage/events.cpp
@@ -50,7 +50,7 @@ bool EventsClass::pollEvent() {
 		++_frameNumber;
 
 		// Update screen
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	if (!g_system->getEventManager()->pollEvent(_event)) return false;
@@ -400,7 +400,7 @@ void EventsClass::delay(int numFrames) {
 		_priorFrameTime = g_system->getMillis();
 	}
 
-	GLOBALS._screenSurface.updateScreen();
+	GLOBALS._screen.update();
 	_prevDelayFrame = _frameNumber;
 	_priorFrameTime = g_system->getMillis();
 }
diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp
index b880f35..b95bea3 100644
--- a/engines/tsage/globals.cpp
+++ b/engines/tsage/globals.cpp
@@ -59,7 +59,7 @@ static SavedObject *classFactoryProc(const Common::String &className) {
 
 /*--------------------------------------------------------------------------*/
 
-Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface),
+Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screen),
 		_randomSource("tsage"), _color1(0), _color2(255), _color3(255) {
 	reset();
 	_stripNum = 0;
@@ -119,7 +119,7 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface
 		_color3 = 4;
 		_dialogCenter.y = 100;
 	}
-	_screenSurface.setScreenSurface();
+
 	_gfxManagers.push_back(&_gfxManagerInstance);
 
 	_sceneObjects = &_sceneObjectsInstance;
diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h
index 1194fe8..e1ebe26 100644
--- a/engines/tsage/globals.h
+++ b/engines/tsage/globals.h
@@ -30,6 +30,7 @@
 #include "tsage/events.h"
 #include "tsage/sound.h"
 #include "tsage/saveload.h"
+#include "tsage/screen.h"
 #include "tsage/user_interface.h"
 
 namespace TsAGE {
@@ -38,7 +39,7 @@ class Globals : public SavedObject {
 private:
 	static void dispatchSound(ASound *obj);
 public:
-	GfxSurface _screenSurface;
+	Screen _screen;
 	GfxManager _gfxManagerInstance;
 	Common::List<GfxManager *> _gfxManagers;
 	SceneHandler *_sceneHandler;
diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index 156503f..8620498 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -229,123 +229,43 @@ void Rect::synchronize(Serializer &s) {
 
 /*--------------------------------------------------------------------------*/
 
-GfxSurface::GfxSurface() : _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
+GfxSurface::GfxSurface() : Graphics::ManagedSurface(), _bounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) {
 	_disableUpdates = false;
 	_lockSurfaceCtr = 0;
-	_customSurface = NULL;
 	_transColor = -1;
-	_trackDirtyRects = false;
 	_flags = 0;
 }
 
-GfxSurface::GfxSurface(const GfxSurface &s) {
+GfxSurface::GfxSurface(const GfxSurface &s): Graphics::ManagedSurface() {
 	_lockSurfaceCtr = 0;
-	_customSurface = NULL;
-	_trackDirtyRects = false;
-	*this = s;
+	
+	operator=(s);
 }
 
 GfxSurface::~GfxSurface() {
-	clear();
+	// Sanity check.. GfxSurface should always be just referencing _rawSurface,
+	// and not directly managing it's own surface
+	assert(!isManaged());
 }
 
-void GfxSurface::clear() {
-	if (_customSurface) {
-		_customSurface->free();
-		delete _customSurface;
-		_customSurface = NULL;
-	}
-}
-
-/**
- * Specifies that the surface will encapsulate the ScummVM screen surface
- */
-void GfxSurface::setScreenSurface() {
-	_trackDirtyRects = true;
-	create(SCREEN_WIDTH, SCREEN_HEIGHT);
-}
-
-/**
- * Updates the physical screen with the screen surface buffer
- */
-void GfxSurface::updateScreen() {
-	assert(_trackDirtyRects);
-
-	// Merge any overlapping dirty rects
-	mergeDirtyRects();
-
-	// Loop through the dirty rect list to copy the affected areas to the sc
-	for (Common::List<Rect>::iterator i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
-		Rect r = *i;
-
-		// Make sure that there is something to update. If not, skip this
-		// rectangle. An example case is the speedbike closeup at the beginning
-		// of Ringworld (third screen).
-		if (r.isEmpty())
-			continue;
-
-		const byte *srcP = (const byte *)_customSurface->getBasePtr(r.left, r.top);
-		g_system->copyRectToScreen(srcP, _customSurface->pitch, r.left, r.top,
-			r.width(), r.height());
-	}
-
-	// Update the physical screen
-	g_system->updateScreen();
-
-	// Now that the dirty rects have been copied, clear the dirty rect list
-	_dirtyRects.clear();
-}
+void GfxSurface::create(uint16 width, uint16 height) {
+	free();
 
-/**
- * Adds a rect to the dirty rect list
- */
-void GfxSurface::addDirtyRect(const Rect &r) {
-	if (_trackDirtyRects) {
-		// Get the bounds and adjust to allow for sub-screen areas
-		Rect r2 = r;
-		r2.translate(_bounds.left, _bounds.top);
-
-		// Add to the dirty rect list
-		r2.right = MIN(r2.right + 1, SCREEN_WIDTH);
-		r2.bottom = MIN(r2.bottom + 1, SCREEN_HEIGHT);
-
-		if (r2.isValidRect())
-			_dirtyRects.push_back(r2);
-	}
+	_rawSurface.create(width, height);
+	setBounds(Rect(0, 0, width, height));
 }
 
-
-
-/**
- * Specifies that the surface should maintain it's own internal surface
- */
-void GfxSurface::create(int width, int height) {
-	assert((width >= 0) && (height >= 0));
-
-	if (_customSurface) {
-		_customSurface->free();
-		delete _customSurface;
-	}
-	_customSurface = new Graphics::Surface();
-	_customSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
-	Common::fill((byte *)_customSurface->getPixels(), (byte *)_customSurface->getBasePtr(0, height), 0);
-	_bounds = Rect(0, 0, width, height);
+void GfxSurface::setBounds(const Rect &bounds) {
+	_bounds = bounds;
+	Graphics::ManagedSurface::create(_rawSurface, bounds);
 }
 
 /**
  * Locks the surface for access, and returns a raw ScummVM surface to manipulate it
  */
-Graphics::Surface GfxSurface::lockSurface() {
+Graphics::ManagedSurface &GfxSurface::lockSurface() {
 	++_lockSurfaceCtr;
-
-	Graphics::Surface *src = _customSurface;
-	assert(src);
-
-	// Setup the returned surface either as one pointing to the same pixels as the source, or
-	// as a subset of the source one based on the currently set bounds
-	Graphics::Surface result;
-	result.init(_bounds.width(), _bounds.height(), src->pitch, src->getBasePtr(_bounds.left, _bounds.top), src->format);
-	return result;
+	return *this;
 }
 
 /**
@@ -367,69 +287,43 @@ void GfxSurface::synchronize(Serializer &s) {
 
 	if (s.isSaving()) {
 		// Save contents of the surface
-		if (_customSurface) {
-			s.syncAsSint16LE(_customSurface->w);
-			s.syncAsSint16LE(_customSurface->h);
-			s.syncBytes((byte *)_customSurface->getPixels(), _customSurface->w * _customSurface->h);
+		if (isManaged()) {
+			s.syncAsSint16LE(this->w);
+			s.syncAsSint16LE(this->h);
+			s.syncBytes((byte *)getPixels(), this->w * this->h);
 		} else {
 			int zero = 0;
 			s.syncAsSint16LE(zero);
 			s.syncAsSint16LE(zero);
 		}
 	} else {
-		int w = 0, h = 0;
-		s.syncAsSint16LE(w);
-		s.syncAsSint16LE(h);
-
-		if ((w == 0) || (h == 0)) {
-			if (_customSurface)
-				delete _customSurface;
-			_customSurface = NULL;
+		int xSize = 0, ySize = 0;
+		s.syncAsSint16LE(xSize);
+		s.syncAsSint16LE(ySize);
+
+		if (xSize == 0 || ySize == 0) {
+			free();
 		} else {
-			create(w, h);
-			s.syncBytes((byte *)_customSurface->getPixels(), w * h);
+			create(xSize, ySize);
+			s.syncBytes((byte *)getPixels(), xSize * ySize);
 		}
 	}
 }
 
-/**
- * Fills a specified rectangle on the surface with the specified color
- *
- * @bounds Area to fill
- * @color Color to use
- */
-void GfxSurface::fillRect(const Rect &bounds, int color) {
-	Graphics::Surface surface = lockSurface();
-	surface.fillRect(bounds, color);
-	unlockSurface();
-	addDirtyRect(bounds);
-}
-
 GfxSurface &GfxSurface::operator=(const GfxSurface &s) {
 	assert(_lockSurfaceCtr == 0);
 	assert(s._lockSurfaceCtr == 0);
 
-	if (_customSurface) {
-		_customSurface->free();
-		delete _customSurface;
-	}
-
-	_customSurface = s._customSurface;
 	_disableUpdates = s._disableUpdates;
 	_bounds = s._bounds;
 	_centroid = s._centroid;
 	_transColor = s._transColor;
 	_flags = s._flags;
 
-	if (_customSurface) {
-		// Surface owns the internal data, so replicate it so new surface owns it's own
-		_customSurface = new Graphics::Surface();
-		_customSurface->create(s._customSurface->w, s._customSurface->h, Graphics::PixelFormat::createFormatCLUT8());
-		const byte *srcP = (const byte *)s._customSurface->getPixels();
-		byte *destP = (byte *)_customSurface->getPixels();
-
-		Common::copy(srcP, srcP + (_bounds.width() * _bounds.height()), destP);
-	}
+	// Copy the source's surface
+	create(s.w, s.h);
+	blitFrom(s);
+	setBounds(s.getBounds());
 
 	return *this;
 }
@@ -474,7 +368,7 @@ bool GfxSurface::displayText(const Common::String &msg, const Common::Point &pt)
 /**
  * Loads a quarter of a screen from a resource
  */
-void GfxSurface::loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection) {
+void GfxSurface::loadScreenSection(Graphics::ManagedSurface &dest, int xHalf, int yHalf, int xSection, int ySection) {
 	int screenNum = g_globals->_sceneManager._scene->_activeScreenNumber;
 	Rect updateRect(0, 0, 160, 100);
 	updateRect.translate(xHalf * 160, yHalf * 100);
@@ -682,50 +576,6 @@ void GfxSurface::draw(const Common::Point &pt, Rect *rect) {
 	}
 }
 
-/**
- * Merges any clipping rectangles that overlap to try and reduce
- * the total number of clip rectangles.
- */
-void GfxSurface::mergeDirtyRects() {
-	if (_dirtyRects.size() <= 1)
-		return;
-
-	Common::List<Rect>::iterator rOuter, rInner;
-
-	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
-		rInner = rOuter;
-		while (++rInner != _dirtyRects.end()) {
-
-			if ((*rOuter).intersects(*rInner)) {
-				// these two rectangles overlap or
-				// are next to each other - merge them
-
-				unionRectangle(*rOuter, *rOuter, *rInner);
-
-				// remove the inner rect from the list
-				_dirtyRects.erase(rInner);
-
-				// move back to beginning of list
-				rInner = rOuter;
-			}
-		}
-	}
-}
-
-/**
- * Creates the union of two rectangles.
- * Returns True if there is a union.
- * @param pDest			destination rectangle that is to receive the new union
- * @param pSrc1			a source rectangle
- * @param pSrc2			a source rectangle
- */
-bool GfxSurface::unionRectangle(Common::Rect &destRect, const Rect &src1, const Rect &src2) {
-	destRect = src1;
-	destRect.extend(src2);
-
-	return !destRect.isEmpty();
-}
-
 /*--------------------------------------------------------------------------*/
 
 GfxElement::GfxElement() {
@@ -762,17 +612,16 @@ void GfxElement::highlight() {
 	Rect tempRect(_bounds);
 	tempRect.collapse(g_globals->_gfxEdgeAdjust - 1, g_globals->_gfxEdgeAdjust - 1);
 
-	for (int yp = tempRect.top; yp < tempRect.bottom; ++yp) {
-		byte *lineP = (byte *)surface.getBasePtr(tempRect.left, yp);
-		for (int xp = tempRect.left; xp < tempRect.right; ++xp, ++lineP) {
+	Graphics::Surface dest = surface.getSubArea(tempRect);
+
+	for (int yp = 0; yp < dest.h; ++yp) {
+		byte *lineP = (byte *)dest.getBasePtr(0, yp);
+		for (int xp = 0; xp < tempRect.right; ++xp, ++lineP) {
 			if (*lineP == _colors.background) *lineP = _colors.foreground;
 			else if (*lineP == _colors.foreground) *lineP = _colors.background;
 		}
 	}
 
-	// Mark the affected area as dirty
-	gfxManager.getSurface().addDirtyRect(tempRect);
-
 	// Release the surface
 	gfxManager.unlockSurface();
 }
@@ -816,10 +665,11 @@ void GfxElement::drawFrame() {
 
 		// Loop through the surface area to replace each pixel
 		// with its proper shaded replacement
-		Graphics::Surface surface = gfxManager.lockSurface();
-		for (int y = tempRect.top; y < tempRect.bottom; ++y) {
-			byte *lineP = (byte *)surface.getBasePtr(tempRect.left, y);
-			for (int x = 0; x < tempRect.width(); ++x) {
+		Graphics::Surface dest = gfxManager.getSurface().getSubArea(tempRect);
+
+		for (int y = 0; y < dest.h; ++y) {
+			byte *lineP = (byte *)dest.getBasePtr(0, y);
+			for (int x = 0; x < dest.w; ++x) {
 				*lineP = transList[*lineP];
 				lineP++;
 			}
@@ -827,27 +677,24 @@ void GfxElement::drawFrame() {
 
 		// Draw the edge frame
 		// Outer frame border
-		surface.hLine(tempRect.left + 2, tempRect.top, tempRect.right - 2, 0);
-		surface.hLine(tempRect.left + 2, tempRect.bottom, tempRect.right - 2, 0);
-		surface.vLine(tempRect.left, tempRect.top + 2, tempRect.bottom - 2, 0);
-		surface.vLine(tempRect.right, tempRect.top + 2, tempRect.bottom - 2, 0);
-		*((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.top + 1)) = 0;
-		*((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.top + 1)) = 0;
-		*((byte *)surface.getBasePtr(tempRect.left + 1, tempRect.bottom - 1)) = 0;
-		*((byte *)surface.getBasePtr(tempRect.right - 1, tempRect.bottom - 1)) = 0;
+		dest.hLine(2, 0, dest.w - 2, 0);
+		dest.hLine(2, dest.h - 1, dest.w - 2, 0);
+		dest.vLine(0, 2, dest.h - 2, 0);
+		dest.vLine(tempRect.right, 2, dest.h - 2, 0);
+		*((byte *)dest.getBasePtr(1, 1)) = 0;
+		*((byte *)dest.getBasePtr(dest.w - 1, 1)) = 0;
+		*((byte *)dest.getBasePtr(1, dest.h - 1)) = 0;
+		*((byte *)dest.getBasePtr(dest.w - 1, dest.h - 1)) = 0;
 
 		// Inner frame border
-		surface.hLine(tempRect.left + 2, tempRect.top + 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColor);
-		surface.hLine(tempRect.left + 2, tempRect.bottom - 1, tempRect.right - 2, R2_GLOBALS._frameEdgeColor);
-		surface.vLine(tempRect.left + 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColor);
-		surface.vLine(tempRect.right - 1, tempRect.top + 2, tempRect.bottom - 2, R2_GLOBALS._frameEdgeColor);
-		*((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColor;
-		*((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.top + 2)) = R2_GLOBALS._frameEdgeColor;
-		*((byte *)surface.getBasePtr(tempRect.left + 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColor;
-		*((byte *)surface.getBasePtr(tempRect.right - 2, tempRect.bottom - 2)) = R2_GLOBALS._frameEdgeColor;
-
-		gfxManager.unlockSurface();
-		gfxManager.getSurface().addDirtyRect(tempRect);
+		dest.hLine(2, 1, dest.w - 2, R2_GLOBALS._frameEdgeColor);
+		dest.hLine(2, dest.h - 1, dest.w - 2, R2_GLOBALS._frameEdgeColor);
+		dest.vLine(1, 2, dest.h - 2, R2_GLOBALS._frameEdgeColor);
+		dest.vLine(dest.w - 1, 2, dest.h - 2, R2_GLOBALS._frameEdgeColor);
+		*((byte *)dest.getBasePtr(2, 2)) = R2_GLOBALS._frameEdgeColor;
+		*((byte *)dest.getBasePtr(dest.w - 2, 2)) = R2_GLOBALS._frameEdgeColor;
+		*((byte *)dest.getBasePtr(2, dest.h - 2)) = R2_GLOBALS._frameEdgeColor;
+		*((byte *)dest.getBasePtr(dest.w - 2, dest.h - 2)) = R2_GLOBALS._frameEdgeColor;
 
 	} else {
 		// Fill dialog content with specified background color
@@ -1236,7 +1083,7 @@ GfxButton *GfxDialog::execute(GfxButton *defaultButton) {
 		}
 
 		g_system->delayMillis(10);
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	_gfxManager.deactivate();
@@ -1269,7 +1116,7 @@ void GfxDialog::setPalette() {
 
 /*--------------------------------------------------------------------------*/
 
-GfxManager::GfxManager() : _surface(g_globals->_screenSurface), _oldManager(NULL) {
+GfxManager::GfxManager() : _surface(g_globals->_screen), _oldManager(NULL) {
 	_font.setOwner(this);
 	_font._fillFlag = false;
 	_bounds = Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
@@ -1563,23 +1410,24 @@ int GfxFont::writeChar(const char ch) {
 	int yOffset = (_fontData[charOffset + 1] >> 3) & 0x1f;
 	const uint8 *dataP = &_fontData[charOffset + 2];
 
-	// Lock the surface for access
-	Graphics::Surface surfacePtr = _gfxManager->lockSurface();
-
 	Rect charRect;
 	charRect.set(0, 0, charWidth, _fontSize.y);
 	charRect.translate(_topLeft.x + _position.x, _topLeft.y + _position.y + yOffset);
 
+	// Get the sub-section of the screen to update
+	Graphics::Surface dest = _gfxManager->getSurface().getSubArea(charRect);
+
 	if (_fillFlag)
-		surfacePtr.fillRect(charRect, _colors.background);
+		dest.fillRect(charRect, _colors.background);
 
 	charRect.bottom = charRect.top + charHeight;
+	assert(charRect.height() <= dest.h);
 
 	// Display the character
 	int bitCtr = 0;
 	uint8 v = 0;
-	for (int yp = charRect.top; yp < charRect.bottom; ++yp) {
-		byte *destP = (byte *)surfacePtr.getBasePtr(charRect.left, yp);
+	for (int yp = 0; yp < charHeight; ++yp) {
+		byte *destP = (byte *)dest.getBasePtr(0, yp);
 
 		for (int xs = 0; xs < charRect.width(); ++xs, ++destP) {
 			// Get the next color index to use
@@ -1599,13 +1447,9 @@ int GfxFont::writeChar(const char ch) {
 		}
 	}
 
-	// Mark the affected area as dirty
-	_gfxManager->getSurface().addDirtyRect(charRect);
-
 	// Move the text writing position
 	_position.x += charWidth;
 
-	_gfxManager->unlockSurface();
 	return charWidth;
 }
 
diff --git a/engines/tsage/graphics.h b/engines/tsage/graphics.h
index 25f7aea..3b395b7 100644
--- a/engines/tsage/graphics.h
+++ b/engines/tsage/graphics.h
@@ -28,7 +28,7 @@
 #include "common/list.h"
 #include "common/rect.h"
 #include "common/system.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
 
 namespace TsAGE {
 
@@ -73,20 +73,13 @@ public:
 
 enum FrameFlag { FRAME_FLIP_CENTROID_X = 4, FRAME_FLIP_CENTROID_Y = 8 };
 
-class GfxSurface {
+class GfxSurface: virtual public Graphics::ManagedSurface {
 private:
-	Graphics::Surface *_customSurface;
 	int _lockSurfaceCtr;
+	Graphics::ManagedSurface _rawSurface;
 
 	bool _disableUpdates;
 	Rect _bounds;
-
-	bool _trackDirtyRects;
-	Common::List<Rect> _dirtyRects;
-
-	void mergeDirtyRects();
-	bool unionRectangle(Common::Rect &destRect, const Rect &src1, const Rect &src2);
-
 public:
 	Common::Point _centroid;
 	int _transColor;
@@ -95,17 +88,13 @@ public:
 public:
 	GfxSurface();
 	GfxSurface(const GfxSurface &s);
-	~GfxSurface();
+	virtual ~GfxSurface();
 
-	void setScreenSurface();
-	void updateScreen();
-	void addDirtyRect(const Rect &r);
-	Graphics::Surface lockSurface();
+	Graphics::ManagedSurface &lockSurface();
 	void unlockSurface();
 	void synchronize(Serializer &s);
-	void create(int width, int height);
-	void clear();
-	void setBounds(const Rect &bounds) { _bounds = bounds; }
+	virtual void create(uint16 width, uint16 height);
+	void setBounds(const Rect &bounds);
 	const Rect &getBounds() const { return _bounds; }
 
 	void copyFrom(GfxSurface &src, Rect srcBounds, Rect destBounds,
@@ -119,10 +108,9 @@ public:
 		copyFrom(src, tempRect, priorityRegion);
 	}
 	void draw(const Common::Point &pt, Rect *rect = NULL);
-	void fillRect(const Rect &bounds, int color);
 	GfxSurface &operator=(const GfxSurface &s);
 
-	static void loadScreenSection(Graphics::Surface &dest, int xHalf, int yHalf, int xSection, int ySection);
+	static void loadScreenSection(Graphics::ManagedSurface &dest, int xHalf, int yHalf, int xSection, int ySection);
 	static bool displayText(const Common::String &msg, const Common::Point &pt = Common::Point(160, 100));
 };
 
@@ -281,7 +269,7 @@ public:
 	void getStringBounds(const char *s, Rect &bounds, int maxWidth);
 
 	void setDialogPalette();
-	Graphics::Surface lockSurface() {
+	Graphics::ManagedSurface lockSurface() {
 		_surface.setBounds(_bounds);
 		return _surface.lockSurface();
 	}
diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk
index e23b157..b58c748 100644
--- a/engines/tsage/module.mk
+++ b/engines/tsage/module.mk
@@ -47,6 +47,7 @@ MODULE_OBJS := \
 	ringworld2/ringworld2_vampire.o \
 	saveload.o \
 	scenes.o \
+	screen.o \
 	sherlock/sherlock_logo.o \
 	sound.o \
 	staticres.o \
diff --git a/engines/tsage/ringworld/ringworld_dialogs.cpp b/engines/tsage/ringworld/ringworld_dialogs.cpp
index 1dd3bc1..9fa17f3 100644
--- a/engines/tsage/ringworld/ringworld_dialogs.cpp
+++ b/engines/tsage/ringworld/ringworld_dialogs.cpp
@@ -181,7 +181,7 @@ void RightClickDialog::execute() {
 		}
 
 		g_system->delayMillis(10);
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	_gfxManager.deactivate();
@@ -391,7 +391,7 @@ void InventoryDialog::execute() {
 		Event event;
 		while (!g_globals->_events.getEvent(event) && !g_vm->shouldQuit()) {
 			g_system->delayMillis(10);
-			GLOBALS._screenSurface.updateScreen();
+			GLOBALS._screen.update();
 		}
 		if (g_vm->shouldQuit())
 			break;
@@ -439,7 +439,7 @@ void InventoryDialog::execute() {
 			// Inventory item selected
 			InvObject *invObject = static_cast<GfxInvImage *>(hiliteObj)->_invObject;
 			if (lookFlag) {
-				g_globals->_screenSurface.displayText(invObject->_description);
+				g_globals->_screen.displayText(invObject->_description);
 			} else {
 				RING_INVENTORY._selectedItem = invObject;
 				invObject->setCursor();
diff --git a/engines/tsage/ringworld/ringworld_logic.cpp b/engines/tsage/ringworld/ringworld_logic.cpp
index 1d8293c..354c86a 100644
--- a/engines/tsage/ringworld/ringworld_logic.cpp
+++ b/engines/tsage/ringworld/ringworld_logic.cpp
@@ -320,7 +320,7 @@ void SceneArea::wait() {
 	// Wait until a mouse or keypress
 	Event event;
 	while (!g_vm->shouldQuit() && !g_globals->_events.getEvent(event)) {
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 		g_system->delayMillis(10);
 	}
 
diff --git a/engines/tsage/ringworld/ringworld_scenes3.cpp b/engines/tsage/ringworld/ringworld_scenes3.cpp
index a515224..a9ed7af 100644
--- a/engines/tsage/ringworld/ringworld_scenes3.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes3.cpp
@@ -532,7 +532,7 @@ void Scene2100::Action1::signal() {
 			// Wait for an event
 			Event event;
 			if (!g_globals->_events.getEvent(event)) {
-				GLOBALS._screenSurface.updateScreen();
+				GLOBALS._screen.update();
 				g_system->delayMillis(10);
 				continue;
 			}
@@ -2265,7 +2265,7 @@ void Scene2150::Action1::signal() {
 			// Wait for an event
 			Event event;
 			if (!g_globals->_events.getEvent(event)) {
-				GLOBALS._screenSurface.updateScreen();
+				GLOBALS._screen.update();
 				g_system->delayMillis(10);
 				continue;
 			}
@@ -5119,7 +5119,7 @@ void Scene2320::Action3::signal() {
 			// Wait for an event
 			Event event;
 			if (!g_globals->_events.getEvent(event)) {
-				GLOBALS._screenSurface.updateScreen();
+				GLOBALS._screen.update();
 				g_system->delayMillis(10);
 				continue;
 			}
diff --git a/engines/tsage/ringworld/ringworld_scenes5.cpp b/engines/tsage/ringworld/ringworld_scenes5.cpp
index cb8a89d..98859f3 100644
--- a/engines/tsage/ringworld/ringworld_scenes5.cpp
+++ b/engines/tsage/ringworld/ringworld_scenes5.cpp
@@ -2813,7 +2813,7 @@ void Scene4150::Action1::signal() {
 	case 4: {
 		for (int idx = 100; idx >= 0; idx -= 5) {
 			g_globals->_scenePalette.fade(adjustData, false, idx);
-			GLOBALS._screenSurface.updateScreen();
+			GLOBALS._screen.update();
 			g_system->delayMillis(10);
 		}
 
@@ -2841,7 +2841,7 @@ void Scene4150::Action1::signal() {
 	case 7:
 		for (int idx = 100; idx >= 0; idx -= 5) {
 			g_globals->_scenePalette.fade(adjustData, false, idx);
-			GLOBALS._screenSurface.updateScreen();
+			GLOBALS._screen.update();
 			g_system->delayMillis(10);
 		}
 
diff --git a/engines/tsage/ringworld2/ringworld2_dialogs.cpp b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
index 99f88a1..027fb55 100644
--- a/engines/tsage/ringworld2/ringworld2_dialogs.cpp
+++ b/engines/tsage/ringworld2/ringworld2_dialogs.cpp
@@ -154,7 +154,7 @@ int RightClickDialog::execute() {
 		}
 
 		g_system->delayMillis(10);
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	// Execute the specified action
diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp
index d245419..ecaa671 100644
--- a/engines/tsage/ringworld2/ringworld2_logic.cpp
+++ b/engines/tsage/ringworld2/ringworld2_logic.cpp
@@ -351,7 +351,7 @@ SceneExt::SceneExt(): Scene() {
 	_preventSaving = false;
 
 	// Reset screen clipping area
-	R2_GLOBALS._screenSurface._clipRect = Rect();
+	R2_GLOBALS._screen._clipRect = Rect();
 
 	// WORKAROUND: In the original, playing animations don't reset the global _animationCtr
 	// counter as scene changes unless the playing animation explicitly finishes. For now,
@@ -513,7 +513,7 @@ void SceneExt::endStrip() {
 }
 
 void SceneExt::clearScreen() {
-	R2_GLOBALS._screenSurface.fillRect(R2_GLOBALS._screenSurface.getBounds(), 0);
+	R2_GLOBALS._screen.fillRect(R2_GLOBALS._screen.getBounds(), 0);
 }
 
 void SceneExt::refreshBackground(int xAmount, int yAmount) {
@@ -543,15 +543,12 @@ void SceneExt::refreshBackground(int xAmount, int yAmount) {
 	int screenSize = g_vm->_memoryManager.getSize(dataP);
 
 	// Lock the background for update
-	Graphics::Surface s = _backSurface.lockSurface();
-	assert(screenSize == (s.w * s.h));
+	assert(screenSize == (_backSurface.w * _backSurface.h));
+	Graphics::Surface s = _backSurface.getSubArea(Common::Rect(0, 0, _backSurface.w, _backSurface.h));
 
-	// Copy the data
+	// Copy the data into the surface
 	byte *destP = (byte *)s.getPixels();
 	Common::copy(dataP, dataP + (s.w * s.h), destP);
-	_backSurface.unlockSurface();
-
-	R2_GLOBALS._screenSurface.addDirtyRect(_backSurface.getBounds());
 
 	// Free the resource data
 	DEALLOCATE(dataP);
@@ -601,7 +598,7 @@ void SceneExt::loadBlankScene() {
 	_backSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT * 3 / 2);
 	_backSurface.fillRect(_backSurface.getBounds(), 0);
 
-	R2_GLOBALS._screenSurface.fillRect(R2_GLOBALS._screenSurface.getBounds(), 0);
+	R2_GLOBALS._screen.fillRect(R2_GLOBALS._screen.getBounds(), 0);
 }
 
 /*--------------------------------------------------------------------------*/
@@ -1966,10 +1963,9 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
 	byte *sliceData1 = sliceDataStart;
 
 	Rect playerBounds = _screenBounds;
-	int y = _screenBounds.top;
-	R2_GLOBALS._screenSurface.addDirtyRect(playerBounds);
 
-	Graphics::Surface surface = R2_GLOBALS._screenSurface.lockSurface();
+	Graphics::Surface dest = R2_GLOBALS._screen.getSubArea(playerBounds);
+	int y = 0;
 
 	// Handle different drawing modes
 	switch (slice._drawMode) {
@@ -1980,7 +1976,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
 				// TODO: Check of _subData._drawType was done for two different kinds of
 				// line slice drawing in original
 				const byte *pSrc = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
-				byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, y++);
+				byte *pDest = (byte *)dest.getBasePtr(0, y++);
 
 				Common::copy(pSrc, pSrc + _subData._sliceSize, pDest);
 			}
@@ -1997,7 +1993,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
 
 					if (offset) {
 						const byte *pSrc = (const byte *)sliceDataStart + offset;
-						byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, playerBounds.top);
+						byte *pDest = (byte *)dest.getBasePtr(0, 0);
 
 						//Common::copy(pSrc, pSrc + playerBounds.width(), pDest);
 						rleDecode(pSrc, pDest, playerBounds.width());
@@ -2012,7 +2008,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
 					// TODO: Check of _subData._drawType was done for two different kinds of
 					// line slice drawing in original
 					const byte *pSrc = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
-					byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, playerBounds.top);
+					byte *pDest = (byte *)dest.getBasePtr(0, 0);
 
 					rleDecode(pSrc, pDest, _subData._sliceSize);
 				}
@@ -2027,7 +2023,7 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
 				for (int yIndex = 0; yIndex < _sliceHeight; ++yIndex) {
 					const byte *pSrc1 = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData2 + sliceNum * 2);
 					const byte *pSrc2 = (const byte *)sliceDataStart + READ_LE_UINT16(sliceData1 + sliceNum * 2);
-					byte *pDest = (byte *)surface.getBasePtr(playerBounds.left, y++);
+					byte *pDest = (byte *)dest.getBasePtr(0, y++);
 
 					if (slice2._drawMode == 0) {
 						// Uncompressed background, foreground compressed
@@ -2047,17 +2043,14 @@ void AnimationPlayer::drawFrame(int sliceIndex) {
 		break;
 	}
 
-	// Unlock the screen surface
-	R2_GLOBALS._screenSurface.unlockSurface();
-
 	if (_objectMode == ANIMOBJMODE_42) {
 		_screenBounds.expandPanes();
 
 		// Copy the drawn frame to the back surface
-		Rect srcRect = R2_GLOBALS._screenSurface.getBounds();
+		Rect srcRect = R2_GLOBALS._screen.getBounds();
 		Rect destRect = srcRect;
 		destRect.translate(-g_globals->_sceneOffset.x, -g_globals->_sceneOffset.y);
-		R2_GLOBALS._sceneManager._scene->_backSurface.copyFrom(R2_GLOBALS._screenSurface,
+		R2_GLOBALS._sceneManager._scene->_backSurface.copyFrom(R2_GLOBALS._screen,
 			srcRect, destRect);
 
 		// Draw any objects into the scene
diff --git a/engines/tsage/ringworld2/ringworld2_outpost.cpp b/engines/tsage/ringworld2/ringworld2_outpost.cpp
index cad21b4..8c64970 100644
--- a/engines/tsage/ringworld2/ringworld2_outpost.cpp
+++ b/engines/tsage/ringworld2/ringworld2_outpost.cpp
@@ -4689,7 +4689,7 @@ GfxButton *Scene1337::OptionsDialog::execute(GfxButton *defaultButton) {
 		}
 
 		g_system->delayMillis(10);
-		GLOBALS._screenSurface.updateScreen();
+		GLOBALS._screen.update();
 	}
 
 	_gfxManager.deactivate();
diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
index 573cbbb..63879b0 100644
--- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp
+++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp
@@ -1613,7 +1613,7 @@ void Scene180::signal() {
 	case 43:
 	case 47:
 		_helpEnabled = false;
-		R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		R2_GLOBALS._screen.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
 		_palette.loadPalette(0);
 		_palette.loadPalette(9998);
 		R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 8, this);
@@ -1815,7 +1815,7 @@ void Scene180::signal() {
 		_shipDisplay.remove();
 
 		_backSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
-		R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		R2_GLOBALS._screen.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
 		R2_GLOBALS._sound2.fadeOut2(NULL);
 		R2_GLOBALS._sound1.fadeOut2(this);
 		break;
@@ -1880,7 +1880,7 @@ void Scene180::signal() {
 		R2_GLOBALS._paneRefreshFlag[0] = 3;
 
 		_backSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
-		R2_GLOBALS._screenSurface.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+		R2_GLOBALS._screen.fillRect(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
 
 		setSceneDelay(1);
 		break;
diff --git a/engines/tsage/saveload.cpp b/engines/tsage/saveload.cpp
index 9954b92..3cb8e52 100644
--- a/engines/tsage/saveload.cpp
+++ b/engines/tsage/saveload.cpp
@@ -289,10 +289,10 @@ void Saver::writeSavegameHeader(Common::OutSaveFile *out, tSageSavegameHeader &h
 
 	// Create a thumbnail and save it
 	Graphics::Surface *thumb = new Graphics::Surface();
-	Graphics::Surface s = g_globals->_screenSurface.lockSurface();
+	Graphics::Surface s = g_globals->_screen.lockSurface();
 	::createThumbnail(thumb, (const byte *)s.getPixels(), SCREEN_WIDTH, SCREEN_HEIGHT, thumbPalette);
 	Graphics::saveThumbnail(*out, *thumb);
-	g_globals->_screenSurface.unlockSurface();
+	g_globals->_screen.unlockSurface();
 	thumb->free();
 	delete thumb;
 
diff --git a/engines/tsage/scenes.cpp b/engines/tsage/scenes.cpp
index 80ce1e3..095c0d7 100644
--- a/engines/tsage/scenes.cpp
+++ b/engines/tsage/scenes.cpp
@@ -139,7 +139,7 @@ void SceneManager::fadeInIfNecessary() {
 				percent = 100;
 
 			g_globals->_scenePalette.fade((const byte *)&adjustData, false, percent);
-			GLOBALS._screenSurface.updateScreen();
+			GLOBALS._screen.update();
 			g_system->delayMillis(10);
 		}
 
@@ -175,7 +175,7 @@ void SceneManager::changeScene(int newSceneNumber) {
 	}
 
 	// Blank out the screen
-	g_globals->_screenSurface.fillRect(g_globals->_screenSurface.getBounds(), 0);
+	g_globals->_screen.fillRect(g_globals->_screen.getBounds(), 0);
 
 	// If there are any fading sounds, wait until fading is complete
 	while (g_globals->_soundManager.isFading()) {
@@ -463,7 +463,7 @@ void Scene::refreshBackground(int xAmount, int yAmount) {
 				// Check if the section is already loaded
 				if ((_enabledSections[xp * 16 + yp] == 0xffff) || ((xAmount == 0) && (yAmount == 0))) {
 					// Chunk isn't loaded, so load it in
-					Graphics::Surface s = _backSurface.lockSurface();
+					Graphics::ManagedSurface s = _backSurface.lockSurface();
 					GfxSurface::loadScreenSection(s, xp - xHalfOffset, yp - yHalfOffset, xp, yp);
 					_backSurface.unlockSurface();
 					changedFlag = true;
diff --git a/engines/tsage/screen.cpp b/engines/tsage/screen.cpp
new file mode 100644
index 0000000..f11c384
--- /dev/null
+++ b/engines/tsage/screen.cpp
@@ -0,0 +1,46 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "tsage/screen.h"
+
+namespace TsAGE {
+
+Screen::Screen(): GfxSurface(), Graphics::Screen() {
+	create(SCREEN_WIDTH, SCREEN_HEIGHT);
+}
+
+void Screen::update() {
+	// When dialogs are active, the screen surface may be remapped to
+	// sub-sections of the screen. But for drawing we'll need to temporarily
+	// remove any such remappings and use the entirety of the screen
+	Rect clipBounds = getBounds();
+	setBounds(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
+
+	// Update the screen
+	Graphics::Screen::update();
+
+	// Reset the clipping
+	setBounds(clipBounds);
+}
+
+} // End of namespace TsAGE
diff --git a/engines/tsage/screen.h b/engines/tsage/screen.h
new file mode 100644
index 0000000..bf5057e
--- /dev/null
+++ b/engines/tsage/screen.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.
+ *
+ */
+
+#ifndef TSAGE_SCREEN_H
+#define TSAGE_SCREEN_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "graphics/screen.h"
+#include "tsage/graphics.h"
+
+namespace TsAGE {
+
+#define SCREEN_WIDTH 320
+#define SCREEN_HEIGHT 200
+#define SCREEN_CENTER_X 160
+#define SCREEN_CENTER_Y 100
+#define UI_INTERFACE_Y 168
+
+class Screen : virtual public Graphics::Screen, virtual public GfxSurface {
+public:
+	/**
+	 * Constructor
+	 */
+	Screen();
+
+	/**
+	 * Destructor
+	 */
+	virtual ~Screen() {}
+
+	/**
+	 * Update the screen
+	 */
+	virtual void update();
+};
+
+} // End of namespace TsAGE
+
+#endif /* MADS_SCREEN_H */
diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h
index 667a8da..1a29700 100644
--- a/engines/tsage/tsage.h
+++ b/engines/tsage/tsage.h
@@ -62,12 +62,6 @@ enum {
 
 struct tSageGameDescription;
 
-#define SCREEN_WIDTH 320
-#define SCREEN_HEIGHT 200
-#define SCREEN_CENTER_X 160
-#define SCREEN_CENTER_Y 100
-#define UI_INTERFACE_Y 168
-
 class TSageEngine : public Engine {
 private:
 	const tSageGameDescription *_gameDescription;
diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp
index 3ee585d..fffc0dc 100644
--- a/engines/tsage/user_interface.cpp
+++ b/engines/tsage/user_interface.cpp
@@ -253,7 +253,7 @@ void UICollection::show() {
 void UICollection::erase() {
 	if (_clearScreen) {
 		Rect tempRect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT);
-		GLOBALS._screenSurface.fillRect(tempRect, 0);
+		GLOBALS._screen.fillRect(tempRect, 0);
 		GLOBALS._sceneManager._scene->_backSurface.fillRect(tempRect, 0);
 		_clearScreen = false;
 	}
@@ -274,7 +274,7 @@ void UICollection::draw() {
 			_objList[idx]->draw();
 
 		// Draw the resulting UI onto the screen
-		GLOBALS._screenSurface.copyFrom(GLOBALS._sceneManager._scene->_backSurface,
+		GLOBALS._screen.copyFrom(GLOBALS._sceneManager._scene->_backSurface,
 			Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT),
 			Rect(0, UI_INTERFACE_Y, SCREEN_WIDTH, SCREEN_HEIGHT));
 
@@ -293,12 +293,12 @@ void UICollection::r2rDrawFrame() {
 	GfxSurface vertLineRight = visage.getFrame(3);
 	GfxSurface horizLine = visage.getFrame(2);
 
-	GLOBALS._screenSurface.copyFrom(horizLine, 0, 0);
-	GLOBALS._screenSurface.copyFrom(vertLineLeft, 0, 3);
-	GLOBALS._screenSurface.copyFrom(vertLineRight, SCREEN_WIDTH - 4, 3);
+	GLOBALS._screen.copyFrom(horizLine, 0, 0);
+	GLOBALS._screen.copyFrom(vertLineLeft, 0, 3);
+	GLOBALS._screen.copyFrom(vertLineRight, SCREEN_WIDTH - 4, 3);
 
 	// Restrict drawing area to exclude the borders at the edge of the screen
-	R2_GLOBALS._screenSurface._clipRect = Rect(4, 3, SCREEN_WIDTH - 4,
+	R2_GLOBALS._screen._clipRect = Rect(4, 3, SCREEN_WIDTH - 4,
 		SCREEN_HEIGHT - 3);
 }
 


Commit: c05a09d33717d1b2c41b258013be589fa63a7097
    https://github.com/scummvm/scummvm/commit/c05a09d33717d1b2c41b258013be589fa63a7097
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-14T20:56:30-04:00

Commit Message:
VOYEUR: Changed engine to use Graphics::ManagedSurface

Changed paths:
  A engines/voyeur/screen.cpp
  A engines/voyeur/screen.h
  R engines/voyeur/graphics.cpp
  R engines/voyeur/graphics.h
    engines/voyeur/animation.cpp
    engines/voyeur/data.cpp
    engines/voyeur/debugger.cpp
    engines/voyeur/events.cpp
    engines/voyeur/files.cpp
    engines/voyeur/files.h
    engines/voyeur/files_threads.cpp
    engines/voyeur/module.mk
    engines/voyeur/voyeur.cpp
    engines/voyeur/voyeur.h
    engines/voyeur/voyeur_game.cpp



diff --git a/engines/voyeur/animation.cpp b/engines/voyeur/animation.cpp
index 62b3734..d5d58a2 100644
--- a/engines/voyeur/animation.cpp
+++ b/engines/voyeur/animation.cpp
@@ -470,7 +470,7 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
 		if (hasDirtyPalette()) {
 			const byte *palette = getPalette();
 
-			vm->_graphicsManager->setPalette128(palette, paletteStart, paletteCount);
+			vm->_screen->setPalette128(palette, paletteStart, paletteCount);
 		}
 
 		if (needsUpdate()) {
@@ -482,15 +482,14 @@ void RL2Decoder::play(VoyeurEngine *vm, int resourceOffset,
 					Common::Point pt(READ_LE_UINT16(imgPos + 4 * picCtr) - 32,
 						READ_LE_UINT16(imgPos + 4 * picCtr + 2) - 20);
 
-					vm->_graphicsManager->sDrawPic(newPic, &videoFrame, pt);
+					vm->_screen->sDrawPic(newPic, &videoFrame, pt);
 					++picCtr;
 				}
 			}
 
 			// Decode the next frame and display
 			const Graphics::Surface *frame = decodeNextFrame();
-			Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
-				(byte *)vm->_graphicsManager->_screenSurface.getPixels());
+			vm->_screen->blitFrom(*frame);
 		}
 
 		vm->_eventsManager->getMouseInfo();
diff --git a/engines/voyeur/data.cpp b/engines/voyeur/data.cpp
index b8c987f..4d6e324 100644
--- a/engines/voyeur/data.cpp
+++ b/engines/voyeur/data.cpp
@@ -240,10 +240,10 @@ void SVoy::reviewAnEvidEvent(int eventIndex) {
 	int frameOff = e._computerOff;
 
 	if (_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId)) {
-		_vm->_graphicsManager->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
-		_vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
-		_vm->_graphicsManager->_vPort->setupViewPort(_vm->_graphicsManager->_backgroundPage);
-		_vm->_graphicsManager->_backColors->startFade();
+		_vm->_screen->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
+		_vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
+		_vm->_screen->_vPort->setupViewPort(_vm->_screen->_backgroundPage);
+		_vm->_screen->_backColors->startFade();
 
 		_vm->doEvidDisplay(frameOff, e._dead);
 		_vm->_bVoy->freeBoltGroup(_vm->_playStampGroupId);
@@ -262,10 +262,10 @@ void SVoy::reviewComputerEvent(int eventIndex) {
 	_computerTextId = e._computerOn;
 
 	if (_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId)) {
-		_vm->_graphicsManager->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
-		_vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
-		_vm->_graphicsManager->_vPort->setupViewPort(_vm->_graphicsManager->_backgroundPage);
-		_vm->_graphicsManager->_backColors->startFade();
+		_vm->_screen->_backColors = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 1)._cMapResource;
+		_vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(_vm->_playStampGroupId)._picResource;
+		_vm->_screen->_vPort->setupViewPort(_vm->_screen->_backgroundPage);
+		_vm->_screen->_backColors->startFade();
 		_vm->flipPageAndWaitForFade();
 
 		_vm->getComputerBrush();
diff --git a/engines/voyeur/debugger.cpp b/engines/voyeur/debugger.cpp
index e9a1218..ebfa123 100644
--- a/engines/voyeur/debugger.cpp
+++ b/engines/voyeur/debugger.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "voyeur/debugger.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
 #include "voyeur/voyeur.h"
 #include "voyeur/staticres.h"
 
diff --git a/engines/voyeur/events.cpp b/engines/voyeur/events.cpp
index 34ef507..020fe4b 100644
--- a/engines/voyeur/events.cpp
+++ b/engines/voyeur/events.cpp
@@ -111,18 +111,18 @@ void EventsManager::mainVoyeurIntFunc() {
 }
 
 void EventsManager::sWaitFlip() {
-	Common::Array<ViewPortResource *> &viewPorts = _vm->_graphicsManager->_viewPortListPtr->_entries;
+	Common::Array<ViewPortResource *> &viewPorts = _vm->_screen->_viewPortListPtr->_entries;
 	for (uint idx = 0; idx < viewPorts.size(); ++idx) {
 		ViewPortResource &viewPort = *viewPorts[idx];
 
-		if (_vm->_graphicsManager->_saveBack && (viewPort._flags & DISPFLAG_40)) {
-			Common::Rect *clipPtr = _vm->_graphicsManager->_clipPtr;
-			_vm->_graphicsManager->_clipPtr = &viewPort._clipRect;
+		if (_vm->_screen->_saveBack && (viewPort._flags & DISPFLAG_40)) {
+			Common::Rect *clipPtr = _vm->_screen->_clipPtr;
+			_vm->_screen->_clipPtr = &viewPort._clipRect;
 
 			if (viewPort._restoreFn)
-				(_vm->_graphicsManager->*viewPort._restoreFn)(&viewPort);
+				(_vm->_screen->*viewPort._restoreFn)(&viewPort);
 
-			_vm->_graphicsManager->_clipPtr = clipPtr;
+			_vm->_screen->_clipPtr = clipPtr;
 			viewPort._rectListCount[viewPort._pageIndex] = 0;
 			viewPort._rectListPtr[viewPort._pageIndex]->clear();
 			viewPort._flags &= ~DISPFLAG_40;
@@ -158,9 +158,7 @@ void EventsManager::checkForNextFrameCounter() {
 			showMousePosition();
 
 		// Display the frame
-		g_system->copyRectToScreen((byte *)_vm->_graphicsManager->_screenSurface.getPixels(),
-			SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
-		g_system->updateScreen();
+		_vm->_screen->update();
 
 		// Signal the ScummVM debugger
 		_vm->_debugger->onFrame();
@@ -178,10 +176,8 @@ void EventsManager::showMousePosition() {
 		mousePos += Common::String::format(" - (%d,%d)", pt.x, pt.y);
 	}
 
-	_vm->_graphicsManager->_screenSurface.fillRect(
-		Common::Rect(0, 0, 110, font.getFontHeight()), 0);
-	font.drawString(&_vm->_graphicsManager->_screenSurface, mousePos,
-		0, 0, 110, 63);
+	_vm->_screen->fillRect(Common::Rect(0, 0, 110, font.getFontHeight()), 0);
+	font.drawString(_vm->_screen, mousePos, 0, 0, 110, 63);
 }
 
 void EventsManager::voyeurTimer() {
@@ -299,11 +295,11 @@ void EventsManager::startFade(CMapResource *cMap) {
 
 	if (cMap->_steps > 0) {
 		_fadeStatus = cMap->_fadeStatus | 1;
-		byte *vgaP = &_vm->_graphicsManager->_VGAColors[_fadeFirstCol * 3];
+		byte *vgaP = &_vm->_screen->_VGAColors[_fadeFirstCol * 3];
 		int mapIndex = 0;
 
 		for (int idx = _fadeFirstCol; idx <= _fadeLastCol; ++idx, vgaP += 3) {
-			ViewPortPalEntry &palEntry = _vm->_graphicsManager->_viewPortListPtr->_palette[idx];
+			ViewPortPalEntry &palEntry = _vm->_screen->_viewPortListPtr->_palette[idx];
 			palEntry._rEntry = vgaP[0] << 8;
 			int rDiff = (cMap->_entries[mapIndex * 3] << 8) - palEntry._rEntry;
 			palEntry._rChange = rDiff / cMap->_steps;
@@ -325,7 +321,7 @@ void EventsManager::startFade(CMapResource *cMap) {
 			_intPtr._skipFading = true;
 		_fadeIntNode._flags &= ~1;
 	} else {
-		byte *vgaP = &_vm->_graphicsManager->_VGAColors[_fadeFirstCol * 3];
+		byte *vgaP = &_vm->_screen->_VGAColors[_fadeFirstCol * 3];
 		int mapIndex = 0;
 
 		for (int idx = _fadeFirstCol; idx <= _fadeLastCol; ++idx, vgaP += 3) {
@@ -371,8 +367,8 @@ void EventsManager::vDoFadeInt() {
 	}
 
 	for (int i = _fadeFirstCol; i <= _fadeLastCol; ++i) {
-		ViewPortPalEntry &palEntry = _vm->_graphicsManager->_viewPortListPtr->_palette[i];
-		byte *vgaP = &_vm->_graphicsManager->_VGAColors[palEntry._palIndex * 3];
+		ViewPortPalEntry &palEntry = _vm->_screen->_viewPortListPtr->_palette[i];
+		byte *vgaP = &_vm->_screen->_VGAColors[palEntry._palIndex * 3];
 
 		palEntry._rEntry += palEntry._rChange;
 		palEntry._gEntry += palEntry._gChange;
@@ -395,7 +391,7 @@ void EventsManager::vDoCycleInt() {
 	for (int idx = 3; idx >= 0; --idx) {
 		if (_cyclePtr->_type[idx] && --_cycleTime[idx] <= 0) {
 			byte *pSrc = _cycleNext[idx];
-			byte *pPal = _vm->_graphicsManager->_VGAColors;
+			byte *pPal = _vm->_screen->_VGAColors;
 
 			if (_cyclePtr->_type[idx] != 1) {
 				// New palette data being specified - loop to set entries
@@ -521,7 +517,7 @@ void EventsManager::setCursor(PictureResource *pic) {
 	cursor._bounds = pic->_bounds;
 	cursor._flags = DISPFLAG_CURSOR;
 
-	_vm->_graphicsManager->sDrawPic(pic, &cursor, Common::Point());
+	_vm->_screen->sDrawPic(pic, &cursor, Common::Point());
 }
 
 void EventsManager::setCursor(byte *cursorData, int width, int height, int keyColor) {
@@ -531,16 +527,16 @@ void EventsManager::setCursor(byte *cursorData, int width, int height, int keyCo
 void EventsManager::setCursorColor(int idx, int mode) {
 	switch (mode) {
 	case 0:
-		_vm->_graphicsManager->setColor(idx, 90, 90, 232);
+		_vm->_screen->setColor(idx, 90, 90, 232);
 		break;
 	case 1:
-		_vm->_graphicsManager->setColor(idx, 232, 90, 90);
+		_vm->_screen->setColor(idx, 232, 90, 90);
 		break;
 	case 2:
-		_vm->_graphicsManager->setColor(idx, 90, 232, 90);
+		_vm->_screen->setColor(idx, 90, 232, 90);
 		break;
 	case 3:
-		_vm->_graphicsManager->setColor(idx, 90, 232, 232);
+		_vm->_screen->setColor(idx, 90, 232, 232);
 		break;
 	default:
 		break;
@@ -564,12 +560,12 @@ void EventsManager::getMouseInfo() {
 
 			if (_cursorBlinked) {
 				_cursorBlinked = false;
-				_vm->_graphicsManager->setOneColor(128, 220, 20, 20);
-				_vm->_graphicsManager->setColor(128, 220, 20, 20);
+				_vm->_screen->setOneColor(128, 220, 20, 20);
+				_vm->_screen->setColor(128, 220, 20, 20);
 			} else {
 				_cursorBlinked = true;
-				_vm->_graphicsManager->setOneColor(128, 220, 220, 220);
-				_vm->_graphicsManager->setColor(128, 220, 220, 220);
+				_vm->_screen->setOneColor(128, 220, 220, 220);
+				_vm->_screen->setColor(128, 220, 220, 220);
 			}
 		}
 	}
@@ -585,11 +581,11 @@ void EventsManager::getMouseInfo() {
 
 void EventsManager::startCursorBlink() {
 	if (_vm->_voy->_eventFlags & EVTFLAG_RECORDING) {
-		_vm->_graphicsManager->setOneColor(128, 55, 5, 5);
-		_vm->_graphicsManager->setColor(128, 220, 20, 20);
+		_vm->_screen->setOneColor(128, 55, 5, 5);
+		_vm->_screen->setColor(128, 220, 20, 20);
 		_intPtr._hasPalette = true;
 
-		_vm->_graphicsManager->drawDot();
+		_vm->_screen->drawDot();
 		//copySection();
 	}
 }
diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp
index 300e086..46b195e 100644
--- a/engines/voyeur/files.cpp
+++ b/engines/voyeur/files.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "voyeur/files.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
 #include "voyeur/voyeur.h"
 #include "voyeur/staticres.h"
 
@@ -359,7 +359,7 @@ void BoltFile::resolveIt(uint32 id, byte **p) {
 	}
 }
 
-void BoltFile::resolveFunction(uint32 id, GraphicMethodPtr *fn) {
+void BoltFile::resolveFunction(uint32 id, ScreenMethodPtr *fn) {
 	if ((int32)id == -1)
 		*fn = NULL;
 	else
@@ -485,8 +485,8 @@ void BVoyBoltFile::initViewPortList() {
 	_state._curMemberPtr->_viewPortListResource = res = new ViewPortListResource(
 		_state, _state._curMemberPtr->_data);
 
-	_state._vm->_graphicsManager->_viewPortListPtr = res;
-	_state._vm->_graphicsManager->_vPort = res->_entries[0];
+	_state._vm->_screen->_viewPortListPtr = res;
+	_state._vm->_screen->_vPort = res->_entries[0];
 }
 
 void BVoyBoltFile::initFontInfo() {
@@ -752,24 +752,24 @@ DisplayResource::DisplayResource(VoyeurEngine *vm) {
 
 void DisplayResource::sFillBox(int width, int height) {
 	assert(_vm);
-	bool saveBack = _vm->_graphicsManager->_saveBack;
-	_vm->_graphicsManager->_saveBack = false;
+	bool saveBack = _vm->_screen->_saveBack;
+	_vm->_screen->_saveBack = false;
 
 	PictureResource pr;
 	pr._flags = DISPFLAG_1;
 	pr._select = 0xff;
 	pr._pick = 0;
-	pr._onOff = _vm->_graphicsManager->_drawPtr->_penColor;
+	pr._onOff = _vm->_screen->_drawPtr->_penColor;
 	pr._bounds = Common::Rect(0, 0, width, height);
 
-	_vm->_graphicsManager->sDrawPic(&pr, this, _vm->_graphicsManager->_drawPtr->_pos);
-	_vm->_graphicsManager->_saveBack = saveBack;
+	_vm->_screen->sDrawPic(&pr, this, _vm->_screen->_drawPtr->_pos);
+	_vm->_screen->_saveBack = saveBack;
 }
 
 bool DisplayResource::clipRect(Common::Rect &rect) {
 	Common::Rect clippingRect;
-	if (_vm->_graphicsManager->_clipPtr) {
-		clippingRect = *_vm->_graphicsManager->_clipPtr;
+	if (_vm->_screen->_clipPtr) {
+		clippingRect = *_vm->_screen->_clipPtr;
 	} else if (_flags & DISPFLAG_VIEWPORT) {
 		clippingRect = ((ViewPortResource *)this)->_clipRect;
 	} else {
@@ -804,18 +804,18 @@ bool DisplayResource::clipRect(Common::Rect &rect) {
 }
 
 int DisplayResource::drawText(const Common::String &msg) {
-	GraphicsManager &gfxManager = *_vm->_graphicsManager;
-	assert(gfxManager._fontPtr);
-	assert(gfxManager._fontPtr->_curFont);
-	FontInfoResource &fontInfo = *gfxManager._fontPtr;
-	PictureResource &fontChar = *_vm->_graphicsManager->_fontChar;
+	Screen &screen = *_vm->_screen;
+	assert(screen._fontPtr);
+	assert(screen._fontPtr->_curFont);
+	FontInfoResource &fontInfo = *screen._fontPtr;
+	PictureResource &fontChar = *_vm->_screen->_fontChar;
 	FontResource &fontData = *fontInfo._curFont;
 	int xShadows[9] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
 	int yShadows[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
 
-	Common::Rect *clipPtr = gfxManager._clipPtr;
+	Common::Rect *clipPtr = screen._clipPtr;
 	if (!(fontInfo._picFlags & DISPFLAG_1))
-		gfxManager._clipPtr = NULL;
+		screen._clipPtr = NULL;
 
 	int minChar = fontData._minChar;
 	int padding = fontData._padding;
@@ -834,7 +834,7 @@ int DisplayResource::drawText(const Common::String &msg) {
 		(ViewPortResource *)this;
 
 	if ((fontInfo._fontFlags & DISPFLAG_1) || fontInfo._justify ||
-			(gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT))) {
+			(screen._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT))) {
 		msgWidth = viewPort->textWidth(msg);
 		yp = pos.y;
 		xp = pos.x;
@@ -898,18 +898,18 @@ int DisplayResource::drawText(const Common::String &msg) {
 		}
 	}
 
-	if (gfxManager._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) {
+	if (screen._saveBack && fontInfo._fontSaveBack && (_flags & DISPFLAG_VIEWPORT)) {
 		viewPort->addSaveRect(viewPort->_pageIndex, viewPort->_fontRect);
 	}
 
 	if (fontInfo._fontFlags & DISPFLAG_1) {
-		gfxManager._drawPtr->_pos = Common::Point(viewPort->_fontRect.left, viewPort->_fontRect.top);
-		gfxManager._drawPtr->_penColor = fontInfo._backColor;
+		screen._drawPtr->_pos = Common::Point(viewPort->_fontRect.left, viewPort->_fontRect.top);
+		screen._drawPtr->_penColor = fontInfo._backColor;
 		sFillBox(viewPort->_fontRect.width(), viewPort->_fontRect.height());
 	}
 
-	bool saveBack = gfxManager._saveBack;
-	gfxManager._saveBack = false;
+	bool saveBack = screen._saveBack;
+	screen._saveBack = false;
 
 	int count = 0;
 	if (fontInfo._fontFlags & DISPFLAG_4)
@@ -970,7 +970,7 @@ int DisplayResource::drawText(const Common::String &msg) {
 			uint16 offset = READ_LE_UINT16(fontData._charOffsets + charValue * 2);
 			fontChar._imgData = fontData._charImages + offset * 2;
 
-			gfxManager.sDrawPic(&fontChar, this, Common::Point(xp, yp));
+			screen.sDrawPic(&fontChar, this, Common::Point(xp, yp));
 
 			fontChar._imgData = NULL;
 			xp += charWidth + padding;
@@ -982,8 +982,8 @@ int DisplayResource::drawText(const Common::String &msg) {
 	if (fontInfo._justify == ALIGN_LEFT)
 		fontInfo._pos.x = xp;
 
-	gfxManager._saveBack = saveBack;
-	gfxManager._clipPtr = clipPtr;
+	screen._saveBack = saveBack;
+	screen._clipPtr = clipPtr;
 
 	return msgWidth;
 }
@@ -993,7 +993,7 @@ int DisplayResource::textWidth(const Common::String &msg) {
 		return 0;
 
 	const char *msgP = msg.c_str();
-	FontResource &fontData = *_vm->_graphicsManager->_fontPtr->_curFont;
+	FontResource &fontData = *_vm->_screen->_fontPtr->_curFont;
 	int minChar = fontData._minChar;
 	int maxChar = fontData._maxChar;
 	int padding = fontData._padding;
@@ -1085,9 +1085,9 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
 				mode = 226;
 		}
 
-		if (mode != state._vm->_graphicsManager->_SVGAMode) {
-			state._vm->_graphicsManager->_SVGAMode = mode;
-			state._vm->_graphicsManager->clearPalette();
+		if (mode != state._vm->_screen->_SVGAMode) {
+			state._vm->_screen->_SVGAMode = mode;
+			state._vm->_screen->clearPalette();
 		}
 
 		int screenOffset = READ_LE_UINT32(&src[18]) & 0xffff;
@@ -1096,13 +1096,14 @@ PictureResource::PictureResource(BoltFilesState &state, const byte *src):
 		if (_flags & PICFLAG_CLEAR_SCREEN) {
 			// Clear screen picture. That's right. This game actually has a picture
 			// resource flag to clear the screen! Bizarre.
-			Graphics::Surface &s = state._vm->_graphicsManager->_screenSurface;
-			s.fillRect(Common::Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+			state._vm->_screen->clear();
 		} else {
 			// Direct screen loading picture. In this case, the raw data of the resource
 			// is directly decompressed into the screen surface. Again, bizarre.
-			byte *pDest = (byte *)state._vm->_graphicsManager->_screenSurface.getPixels();
+			Screen &screen = *state._vm->_screen;
+			byte *pDest = (byte *)screen.getPixels();
 			state.decompress(pDest, SCREEN_WIDTH * SCREEN_HEIGHT, state._curMemberPtr->_mode);
+			screen.markAllDirty();
 		}
 	} else {
 		if (_flags & PICFLAG_CLEAR_SCREEN00) {
@@ -1249,13 +1250,13 @@ ViewPortResource::ViewPortResource(BoltFilesState &state, const byte *src):
 		ys + READ_LE_UINT16(src + 0x4C));
 
 	state._curLibPtr->resolveIt(READ_LE_UINT32(src + 0x7A), &dummy);
-	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x7E), (GraphicMethodPtr *)&_fn1);
-	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x82), (GraphicMethodPtr *)&_setupFn);
-	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x86), (GraphicMethodPtr *)&_addFn);
-	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x8A), (GraphicMethodPtr *)&_restoreFn);
+	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x7E), (ScreenMethodPtr *)&_fn1);
+	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x82), (ScreenMethodPtr *)&_setupFn);
+	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x86), (ScreenMethodPtr *)&_addFn);
+	state._curLibPtr->resolveFunction(READ_LE_UINT32(src + 0x8A), (ScreenMethodPtr *)&_restoreFn);
 
 	if (!_restoreFn && _addFn)
-		_addFn = &GraphicsManager::addRectNoSaveBack;
+		_addFn = &Screen::addRectNoSaveBack;
 }
 
 ViewPortResource::~ViewPortResource() {
@@ -1327,19 +1328,19 @@ void ViewPortResource::setupViewPort(PictureResource *page, Common::Rect *clippi
 	_restoreFn = restoreFn;
 
 	if (setupFn)
-		(_state._vm->_graphicsManager->*setupFn)(this);
+		(_state._vm->_screen->*setupFn)(this);
 }
 
 void ViewPortResource::setupViewPort() {
-	setupViewPort(_state._vm->_graphicsManager->_backgroundPage, NULL,
-		&GraphicsManager::setupMCGASaveRect, &GraphicsManager::addRectOptSaveRect,
-		&GraphicsManager::restoreMCGASaveRect);
+	setupViewPort(_state._vm->_screen->_backgroundPage, NULL,
+		&Screen::setupMCGASaveRect, &Screen::addRectOptSaveRect,
+		&Screen::restoreMCGASaveRect);
 }
 
 void ViewPortResource::setupViewPort(PictureResource *pic, Common::Rect *clippingRect) {
 	setupViewPort(pic, clippingRect,
-		&GraphicsManager::setupMCGASaveRect, &GraphicsManager::addRectOptSaveRect,
-		&GraphicsManager::restoreMCGASaveRect);
+		&Screen::setupMCGASaveRect, &Screen::addRectOptSaveRect,
+		&Screen::restoreMCGASaveRect);
 }
 
 void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
@@ -1347,7 +1348,7 @@ void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
 
 	if (clipRect(rect)) {
 		if (_addFn) {
-			(_state._vm->_graphicsManager->*_addFn)(this, pageIndex, rect);
+			(_state._vm->_screen->*_addFn)(this, pageIndex, rect);
 		} else if (_rectListCount[pageIndex] != -1) {
 			_rectListPtr[pageIndex]->push_back(rect);
 		}
@@ -1355,26 +1356,26 @@ void ViewPortResource::addSaveRect(int pageIndex, const Common::Rect &r) {
 }
 
 void ViewPortResource::fillPic(byte onOff) {
-	_state._vm->_graphicsManager->fillPic(this, onOff);
+	_state._vm->_screen->fillPic(this, onOff);
 }
 
 void ViewPortResource::drawIfaceTime() {
 	// Hour display
-	_state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+	_state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
 		(_state._vm->_gameHour / 10) == 0 ? 10 : _state._vm->_gameHour / 10,
 		Common::Point(161, 25));
-	_state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+	_state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
 		_state._vm->_gameHour % 10, Common::Point(172, 25));
 
 	// Minute display
-	_state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+	_state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
 		_state._vm->_gameMinute / 10, Common::Point(190, 25));
-	_state._vm->_graphicsManager->drawANumber(_state._vm->_graphicsManager->_vPort,
+	_state._vm->_screen->drawANumber(_state._vm->_screen->_vPort,
 		_state._vm->_gameMinute % 10, Common::Point(201, 25));
 
 	// AM/PM indicator
 	PictureResource *pic = _state._vm->_bVoy->boltEntry(_state._vm->_voy->_isAM ? 272 : 273)._picResource;
-	_state._vm->_graphicsManager->sDrawPic(pic, _state._vm->_graphicsManager->_vPort,
+	_state._vm->_screen->sDrawPic(pic, _state._vm->_screen->_vPort,
 		Common::Point(215, 27));
 }
 
@@ -1382,9 +1383,9 @@ void ViewPortResource::drawPicPerm(PictureResource *pic, const Common::Point &pt
 	Common::Rect bounds = pic->_bounds;
 	bounds.translate(pt.x, pt.y);
 
-	bool saveBack = _state._vm->_graphicsManager->_saveBack;
-	_state._vm->_graphicsManager->_saveBack = false;
-	_state._vm->_graphicsManager->sDrawPic(pic, this, pt);
+	bool saveBack = _state._vm->_screen->_saveBack;
+	_state._vm->_screen->_saveBack = false;
+	_state._vm->_screen->sDrawPic(pic, this, pt);
 	clipRect(bounds);
 
 	for (int pageIndex = 0; pageIndex < _pageCount; ++pageIndex) {
@@ -1393,7 +1394,7 @@ void ViewPortResource::drawPicPerm(PictureResource *pic, const Common::Point &pt
 		}
 	}
 
-	_state._vm->_graphicsManager->_saveBack = saveBack;
+	_state._vm->_screen->_saveBack = saveBack;
 }
 /*------------------------------------------------------------------------*/
 
@@ -1526,7 +1527,7 @@ CMapResource::CMapResource(BoltFilesState &state, const byte *src): _vm(state._v
 	_entries = new byte[count * 3];
 	Common::copy(src + 6, src + 6 + 3 * count, _entries);
 
-	int palIndex = state._vm->_graphicsManager->_viewPortListPtr->_palIndex;
+	int palIndex = state._vm->_screen->_viewPortListPtr->_palIndex;
 	if (_end > palIndex)
 		_end = palIndex;
 	if (_start > palIndex)
diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h
index eef5df4..8726b38 100644
--- a/engines/voyeur/files.h
+++ b/engines/voyeur/files.h
@@ -27,7 +27,7 @@
 #include "common/file.h"
 #include "common/rect.h"
 #include "common/str.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
 
 namespace Voyeur {
 
@@ -112,7 +112,7 @@ public:
 	byte *memberAddr(uint32 id);
 	byte *memberAddrOffset(uint32 id);
 	void resolveIt(uint32 id, byte **p);
-	void resolveFunction(uint32 id, GraphicMethodPtr *fn);
+	void resolveFunction(uint32 id, ScreenMethodPtr *fn);
 
 	BoltEntry &boltEntry(uint16 id);
 	BoltEntry &getBoltEntryFromLong(uint32 id);
@@ -340,7 +340,7 @@ public:
 	int _rectListCount[3];
 
 	Common::Rect _clipRect;
-	GraphicMethodPtr _fn1;
+	ScreenMethodPtr _fn1;
 	ViewPortSetupPtr _setupFn;
 	ViewPortAddPtr _addFn;
 	ViewPortRestorePtr _restoreFn;
diff --git a/engines/voyeur/files_threads.cpp b/engines/voyeur/files_threads.cpp
index 9908324..bbd3dfe 100644
--- a/engines/voyeur/files_threads.cpp
+++ b/engines/voyeur/files_threads.cpp
@@ -21,7 +21,7 @@
  */
 
 #include "voyeur/files.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
 #include "voyeur/voyeur.h"
 #include "voyeur/staticres.h"
 
@@ -461,7 +461,7 @@ void ThreadResource::parsePlayCommands() {
 					pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + i * 2)._picResource;
 					pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + i * 2 + 1)._cMapResource;
 
-					_vm->_graphicsManager->_vPort->setupViewPort(pic);
+					_vm->_screen->_vPort->setupViewPort(pic);
 					pal->startFade();
 
 					_vm->flipPageAndWaitForFade();
@@ -980,10 +980,10 @@ int ThreadResource::doApt() {
 	_vm->_soundManager->startVOCPlay(_vm->_soundManager->getVOCFileName(_vm->_currentVocId));
 	_vm->_currentVocId = 151;
 
-	_vm->_graphicsManager->setColor(129, 82, 82, 82);
-	_vm->_graphicsManager->setColor(130, 112, 112, 112);
-	_vm->_graphicsManager->setColor(131, 215, 215, 215);
-	_vm->_graphicsManager->setColor(132, 235, 235, 235);
+	_vm->_screen->setColor(129, 82, 82, 82);
+	_vm->_screen->setColor(130, 112, 112, 112);
+	_vm->_screen->setColor(131, 215, 215, 215);
+	_vm->_screen->setColor(132, 235, 235, 235);
 
 	_vm->_eventsManager->_intPtr._hasPalette = true;
 
@@ -1044,7 +1044,7 @@ int ThreadResource::doApt() {
 					// Draw the text description for the highlighted hotspot
 					pic = _vm->_bVoy->boltEntry(_vm->_playStampGroupId +
 						hotspotId + 6)._picResource;
-					_vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
+					_vm->_screen->sDrawPic(pic, _vm->_screen->_vPort,
 						Common::Point(106, 200));
 				}
 
@@ -1112,10 +1112,10 @@ void ThreadResource::doRoom() {
 	if (!vm._bVoy->getBoltGroup(vm._playStampGroupId))
 		return;
 
-	vm._graphicsManager->_backColors = vm._bVoy->boltEntry(vm._playStampGroupId + 1)._cMapResource;
-	vm._graphicsManager->_backgroundPage = vm._bVoy->boltEntry(vm._playStampGroupId)._picResource;
-	vm._graphicsManager->_vPort->setupViewPort(vm._graphicsManager->_backgroundPage);
-	vm._graphicsManager->_backColors->startFade();
+	vm._screen->_backColors = vm._bVoy->boltEntry(vm._playStampGroupId + 1)._cMapResource;
+	vm._screen->_backgroundPage = vm._bVoy->boltEntry(vm._playStampGroupId)._picResource;
+	vm._screen->_vPort->setupViewPort(vm._screen->_backgroundPage);
+	vm._screen->_backColors->startFade();
 
 	voy._fadingStep1 = 2;
 	voy._fadingStep2 = 0;
@@ -1144,7 +1144,7 @@ void ThreadResource::doRoom() {
 	bool breakFlag = false;
 	while (!vm.shouldQuit() && !breakFlag) {
 		_vm->_voyeurArea = AREA_ROOM;
-		vm._graphicsManager->setColor(128, 0, 255, 0);
+		vm._screen->setColor(128, 0, 255, 0);
 		vm._eventsManager->_intPtr._hasPalette = true;
 
 		do {
@@ -1186,7 +1186,7 @@ void ThreadResource::doRoom() {
 			}
 
 			vm._eventsManager->_intPtr._hasPalette = true;
-			vm._graphicsManager->flipPage();
+			vm._screen->flipPage();
 			vm._eventsManager->sWaitFlip();
 		} while (!vm.shouldQuit() && !vm._eventsManager->_mouseClicked);
 
@@ -1234,13 +1234,13 @@ void ThreadResource::doRoom() {
 			// WORKAROUND: Skipped code from the original, that freed the group,
 			// reloaded it, and reloaded the cursors
 
-			vm._graphicsManager->_backColors = vm._bVoy->boltEntry(
+			vm._screen->_backColors = vm._bVoy->boltEntry(
 				vm._playStampGroupId + 1)._cMapResource;
-			vm._graphicsManager->_backgroundPage = vm._bVoy->boltEntry(
+			vm._screen->_backgroundPage = vm._bVoy->boltEntry(
 				vm._playStampGroupId)._picResource;
 
-			vm._graphicsManager->_vPort->setupViewPort();
-			vm._graphicsManager->_backColors->startFade();
+			vm._screen->_vPort->setupViewPort();
+			vm._screen->_backColors->startFade();
 			_vm->flipPageAndWait();
 
 			while (!vm.shouldQuit() && (vm._eventsManager->_fadeStatus & 1))
@@ -1265,7 +1265,7 @@ void ThreadResource::doRoom() {
 
 			_vm->flipPageAndWait();
 
-			vm._graphicsManager->fadeUpICF1();
+			vm._screen->fadeUpICF1();
 			voy._eventFlags &= EVTFLAG_RECORDING;
 			vm._eventsManager->showCursor();
 		}
@@ -1350,7 +1350,7 @@ int ThreadResource::doInterface() {
 	_vm->_soundManager->startVOCPlay(fname);
 	_vm->_eventsManager->getMouseInfo();
 
-	_vm->_graphicsManager->setColor(240, 220, 220, 220);
+	_vm->_screen->setColor(240, 220, 220, 220);
 	_vm->_eventsManager->_intPtr._hasPalette = true;
 	_vm->_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
 
@@ -1424,20 +1424,20 @@ int ThreadResource::doInterface() {
 
 		// Regularly update the time display
 		if (_vm->_voy->_RTANum & 2) {
-			_vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+			_vm->_screen->drawANumber(_vm->_screen->_vPort,
 				_vm->_gameMinute / 10, Common::Point(190, 25));
-			_vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+			_vm->_screen->drawANumber(_vm->_screen->_vPort,
 				_vm->_gameMinute % 10, Common::Point(201, 25));
 
 			if (_vm->_voy->_RTANum & 4) {
 				int v = _vm->_gameHour / 10;
-				_vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+				_vm->_screen->drawANumber(_vm->_screen->_vPort,
 					v == 0 ? 10 : v, Common::Point(161, 25));
-				_vm->_graphicsManager->drawANumber(_vm->_graphicsManager->_vPort,
+				_vm->_screen->drawANumber(_vm->_screen->_vPort,
 					_vm->_gameHour % 10, Common::Point(172, 25));
 
 				pic = _vm->_bVoy->boltEntry(_vm->_voy->_isAM ? 272 : 273)._picResource;
-				_vm->_graphicsManager->sDrawPic(pic, _vm->_graphicsManager->_vPort,
+				_vm->_screen->sDrawPic(pic, _vm->_screen->_vPort,
 					Common::Point(215, 27));
 			}
 		}
@@ -1605,16 +1605,16 @@ void ThreadResource::loadTheApt() {
 
 		_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId);
 		_vm->_voy->_aptLoadMode = -1;
-		_vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(
+		_vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(
 			_vm->_playStampGroupId + 5)._picResource;
-		_vm->_graphicsManager->_vPort->setupViewPort(
-			_vm->_graphicsManager->_backgroundPage);
+		_vm->_screen->_vPort->setupViewPort(
+			_vm->_screen->_backgroundPage);
 	} else {
 		_vm->_bVoy->getBoltGroup(_vm->_playStampGroupId);
-		_vm->_graphicsManager->_backgroundPage = _vm->_bVoy->boltEntry(
+		_vm->_screen->_backgroundPage = _vm->_bVoy->boltEntry(
 			_vm->_playStampGroupId + 5)._picResource;
-		_vm->_graphicsManager->_vPort->setupViewPort(
-			_vm->_graphicsManager->_backgroundPage);
+		_vm->_screen->_vPort->setupViewPort(
+			_vm->_screen->_backgroundPage);
 	}
 
 	CMapResource *pal = _vm->_bVoy->boltEntry(_vm->_playStampGroupId + 4)._cMapResource;
@@ -1624,10 +1624,10 @@ void ThreadResource::loadTheApt() {
 }
 
 void ThreadResource::freeTheApt() {
-	_vm->_graphicsManager->fadeDownICF1(5);
+	_vm->_screen->fadeDownICF1(5);
 	_vm->flipPageAndWaitForFade();
 
-	_vm->_graphicsManager->fadeUpICF1();
+	_vm->_screen->fadeUpICF1();
 
 	if (_vm->_currentVocId != -1) {
 		_vm->_soundManager->stopVOCPlay();
@@ -1635,17 +1635,17 @@ void ThreadResource::freeTheApt() {
 	}
 
 	if (_vm->_voy->_aptLoadMode == -1) {
-		_vm->_graphicsManager->fadeDownICF(6);
+		_vm->_screen->fadeDownICF(6);
 	} else {
 		doAptAnim(2);
 	}
 
 	if (_vm->_voy->_aptLoadMode == 140) {
-		_vm->_graphicsManager->screenReset();
-		_vm->_graphicsManager->resetPalette();
+		_vm->_screen->screenReset();
+		_vm->_screen->resetPalette();
 	}
 
-	_vm->_graphicsManager->_vPort->setupViewPort(nullptr);
+	_vm->_screen->_vPort->setupViewPort(nullptr);
 	_vm->_bVoy->freeBoltGroup(_vm->_playStampGroupId);
 	_vm->_playStampGroupId = -1;
 	_vm->_voy->_viewBounds = nullptr;
@@ -1705,7 +1705,7 @@ void ThreadResource::doAptAnim(int mode) {
 
 		for (int idx = 0; (idx < 6) && !_vm->shouldQuit(); ++idx) {
 			PictureResource *pic = _vm->_bVoy->boltEntry(id + idx + 1)._picResource;
-			_vm->_graphicsManager->_vPort->setupViewPort(pic);
+			_vm->_screen->_vPort->setupViewPort(pic);
 			pal->startFade();
 
 			_vm->flipPageAndWait();
diff --git a/engines/voyeur/graphics.cpp b/engines/voyeur/graphics.cpp
deleted file mode 100644
index a20e9f6..0000000
--- a/engines/voyeur/graphics.cpp
+++ /dev/null
@@ -1,1051 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "voyeur/graphics.h"
-#include "voyeur/voyeur.h"
-#include "voyeur/staticres.h"
-#include "engines/util.h"
-#include "graphics/palette.h"
-#include "graphics/surface.h"
-
-namespace Voyeur {
-
-/*------------------------------------------------------------------------*/
-
-DrawInfo::DrawInfo(int penColor, const Common::Point &pos) {
-	_penColor = penColor;
-	_pos = pos;
-}
-
-/*------------------------------------------------------------------------*/
-
-GraphicsManager::GraphicsManager(VoyeurEngine *vm) : _defaultDrawInfo(1, Common::Point()), _drawPtr(&_defaultDrawInfo), _vm(vm) {
-	_SVGAMode = 0;
-	_planeSelect = 0;
-	_saveBack = true;
-	_clipPtr = NULL;
-	_viewPortListPtr = NULL;
-	_backgroundPage = NULL;
-	_vPort = NULL;
-	_fontPtr = NULL;
-	Common::fill(&_VGAColors[0], &_VGAColors[PALETTE_SIZE], 0);
-	_fontChar = new PictureResource(DISPFLAG_NONE, 0xff, 0xff, 0, Common::Rect(), 0, NULL, 0);
-	_backColors = nullptr;
-}
-
-void GraphicsManager::sInitGraphics() {
-	initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false);
-	_screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
-	clearPalette();
-}
-
-GraphicsManager::~GraphicsManager() {
-	_screenSurface.free();
-	delete _fontChar;
-}
-
-void GraphicsManager::setupMCGASaveRect(ViewPortResource *viewPort) {
-	if (viewPort->_activePage) {
-		viewPort->_activePage->_flags |= DISPFLAG_1;
-		Common::Rect *clipRect = _clipPtr;
-		_clipPtr = &viewPort->_clipRect;
-
-		sDrawPic(viewPort->_activePage, viewPort->_currentPic, Common::Point());
-
-		_clipPtr = clipRect;
-	}
-
-	viewPort->_rectListCount[1] = -1;
-}
-
-void GraphicsManager::addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
-	if (viewPort->_rectListCount[idx] == -1)
-		return;
-
-	// TODO: Lots of code in original, which I suspect may be overlapping rect merging
-	viewPort->_rectListPtr[idx]->push_back(bounds);
-	++viewPort->_rectListCount[idx];
-}
-
-void GraphicsManager::restoreMCGASaveRect(ViewPortResource *viewPort) {
-	if (viewPort->_rectListCount[0] != -1) {
-		for (int i = 0; i < viewPort->_rectListCount[0]; ++i) {
-			addRectOptSaveRect(viewPort, 1, (*viewPort->_rectListPtr[0])[i]);
-		}
-	} else {
-		viewPort->_rectListCount[1] = -1;
-	}
-
-	restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0],
-		viewPort->_pages[1]);
-
-	int count = viewPort->_rectListCount[0];
-	restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0],
-		viewPort->_activePage, viewPort->_currentPic);
-
-	SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]);
-	viewPort->_rectListCount[1] = count;
-}
-
-void GraphicsManager::addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
-	// Stubbed/dummy method in the original.
-}
-
-void GraphicsManager::sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay,
-		const Common::Point &initialOffset) {
-	int width1, width2;
-	int widthDiff, widthDiff2;
-	int height1;
-	int srcOffset;
-	int screenOffset;
-	int srcFlags, destFlags;
-	ViewPortResource *destViewPort = NULL;
-	Common::Rect newBounds;
-	Common::Rect backBounds;
-	int tmpWidth = 0;
-	int tmpHeight = 0;
-	bool isClipped = false;
-	byte pixel = 0;
-	int runLength;
-
-	byte *srcImgData, *destImgData;
-	byte *srcP, *destP;
-	byte byteVal, byteVal2;
-
-	PictureResource *srcPic;
-	PictureResource *destPic;
-
-	// Get the picture parameters, or deference viewport pointers to get their pictures
-	if (srcDisplay->_flags & DISPFLAG_VIEWPORT) {
-		// A viewport was passed, not a picture
-		srcPic = ((ViewPortResource *)srcDisplay)->_currentPic;
-	} else {
-		srcPic = (PictureResource *)srcDisplay;
-	}
-
-	if (destDisplay->_flags & DISPFLAG_VIEWPORT) {
-		// A viewport was passed, not a picture
-		destViewPort = (ViewPortResource *)destDisplay;
-		destPic = destViewPort->_currentPic;
-	} else {
-		destPic = (PictureResource *)destDisplay;
-	}
-
-	Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left,
-		initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top);
-	width1 = width2 = srcPic->_bounds.width();
-	height1 = srcPic->_bounds.height();
-	srcOffset = 0;
-	srcFlags = srcPic->_flags;
-	destFlags = destPic->_flags;
-	byte *cursorData = NULL;
-
-	if (srcFlags & DISPFLAG_1) {
-		if (_clipPtr) {
-			int xs = _clipPtr->left - destPic->_bounds.left;
-			int ys = _clipPtr->top - destPic->_bounds.top;
-			newBounds = Common::Rect(xs, ys, xs + _clipPtr->width(), ys + _clipPtr->height());
-		} else if (destViewPort) {
-			int xs = destViewPort->_clipRect.left - destPic->_bounds.left;
-			int ys = destViewPort->_clipRect.top - destPic->_bounds.top;
-			newBounds = Common::Rect(xs, ys, xs + destViewPort->_clipRect.width(),
-				ys + destViewPort->_clipRect.height());
-		} else {
-			newBounds = Common::Rect(0, 0, destPic->_bounds.width(), destPic->_bounds.height());
-		}
-
-		tmpHeight = offset.y - newBounds.top;
-		if (tmpHeight < 0) {
-			srcOffset -= tmpHeight * width2;
-			height1 += tmpHeight;
-			offset.y = newBounds.top;
-
-			if (height1 <= 0)
-				return;
-
-			isClipped = true;
-		}
-
-		int yMin = newBounds.bottom - (offset.y + height1);
-		if (yMin < 0) {
-			height1 += yMin;
-			if (height1 <= 0)
-				return;
-		}
-
-		tmpWidth = offset.x - newBounds.left;
-		if (tmpWidth < 0) {
-			srcOffset -= tmpWidth;
-			width2 += tmpWidth;
-			offset.x = newBounds.left;
-
-			if (width2 <= 0)
-				return;
-
-			isClipped = true;
-		}
-
-		int xMin = newBounds.right - (offset.x + width2);
-		if (xMin < 0) {
-			width2 += xMin;
-			if (width2 <= 0)
-				return;
-
-			isClipped = true;
-		}
-	}
-
-	screenOffset = offset.y * destPic->_bounds.width() + offset.x;
-	widthDiff = width1 - width2;
-	widthDiff2 = destPic->_bounds.width() - width2;
-
-	if (destViewPort) {
-		if (!_saveBack || (srcPic->_flags & DISPFLAG_800)) {
-			backBounds.left = destPic->_bounds.left + offset.x;
-			backBounds.top = destPic->_bounds.top + offset.y;
-			backBounds.setWidth(width2);
-			backBounds.setHeight(height1);
-			addRectOptSaveRect(destViewPort, 1, backBounds);
-
-		} else if (!destViewPort->_addFn) {
-			if (destViewPort->_rectListCount[destViewPort->_pageIndex] < -1) {
-				Common::Rect r;
-				r.left = destPic->_bounds.left + offset.x;
-				r.top = destPic->_bounds.top + offset.y;
-				r.setWidth(width2);
-				r.setHeight(height1);
-
-				(*destViewPort->_rectListPtr[destViewPort->_pageIndex]).push_back(r);
-				++destViewPort->_rectListCount[destViewPort->_pageIndex];
-			}
-		} else {
-			int xs = offset.x + destPic->_bounds.left;
-			int ys = offset.y + destPic->_bounds.top;
-			backBounds = Common::Rect(xs, ys, xs + width2, ys + height1);
-
-			(this->*destViewPort->_addFn)(destViewPort, destViewPort->_bounds.top, backBounds);
-		}
-	}
-
-	if (srcFlags & DISPFLAG_1000) {
-		int imageDataShift = 0;
-		srcImgData = srcPic->_imgData + (imageDataShift << 14);
-		for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
-			if (imageDataShift < 4)
-				++imageDataShift;
-		}
-
-		destImgData = destPic->_imgData + (imageDataShift << 14);
-		for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
-			if (imageDataShift < 4)
-				++imageDataShift;
-		}
-	} else {
-		srcImgData = srcPic->_imgData;
-		destImgData = destPic->_imgData;
-	}
-
-	if (srcPic->_select != 0xff)
-		return;
-
-	if (destFlags & DISPFLAG_CURSOR) {
-		cursorData = new byte[width2 * height1];
-		Common::fill(cursorData, cursorData + width2 * height1, 0);
-		destImgData = cursorData;
-	}
-
-	if (srcPic->_pick == 0xff) {
-		if (srcFlags & DISPFLAG_8) {
-			error("TODO: sDrawPic variation");
-		} else {
-			// loc_258B8
-			srcP = srcImgData + srcOffset;
-
-			if (destFlags & DISPFLAG_8) {
-				// loc_258D8
-				destP = destImgData + screenOffset;
-
-				if (srcFlags & DISPFLAG_2) {
-					// loc_25652
-					srcP = srcImgData + srcOffset;
-
-					if (destFlags & DISPFLAG_8) {
-						// loc_2566F
-						if (srcFlags & DISPFLAG_2) {
-							// loc_256FA
-							srcP = (byte *)_screenSurface.getPixels() + srcOffset;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
-									pixel = *srcP;
-									if (pixel)
-										*destP = pixel;
-								}
-
-								srcP += widthDiff;
-								destP += widthDiff2;
-							}
-						} else {
-							// loc_25706
-							for (int yp = 0; yp < height1; ++yp) {
-								Common::copy(srcP, srcP + width2, destP);
-								srcP += width2 + widthDiff;
-								destP += width2 + widthDiff2;
-							}
-						}
-					} else {
-						// loc_25773
-						destP = destImgData + screenOffset;
-
-						if (srcFlags & DISPFLAG_2) {
-							// loc_25793
-							for (int yp = 0; yp < height1; ++yp) {
-								Common::copy(srcP, srcP + width2, destP);
-								srcP += width2 + widthDiff;
-								destP += width2 + widthDiff2;
-							}
-						} else {
-							// loc_25829
-							destP = (byte *)_screenSurface.getPixels() + screenOffset;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								Common::copy(srcP, srcP + width2, destP);
-								srcP += width2 + widthDiff;
-								destP += width2 + widthDiff2;
-							}
-						}
-					}
-				} else {
-					// loc_25D40
-					if (srcFlags & DISPFLAG_100) {
-						// loc_25D4A
-						error("TODO: sDrawPic variation");
-					} else {
-						// loc_2606D
-						destP = (byte *)_screenSurface.getPixels() + screenOffset;
-
-						for (int yp = 0; yp < height1; ++yp) {
-							Common::copy(srcP, srcP + width2, destP);
-							destP += width2 + widthDiff2;
-							srcP += width2 + widthDiff;
-						}
-					}
-				}
-			} else {
-				// loc_2615E
-				destP = destImgData + screenOffset;
-
-				if (srcFlags & DISPFLAG_2) {
-					// loc_2617e
-					if (srcFlags & DISPFLAG_100) {
-						// loc_26188
-						srcP = srcImgData;
-						if (isClipped) {
-							// loc_26199
-							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
-							int xMax = tmpWidth + width2;
-							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
-
-							width2 = srcPic->_bounds.width();
-							height1 = tmpHeight + height1;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								runLength = 0;
-
-								for (int xp = 0; xp < width2; ++xp, --runLength) {
-									if (runLength <= 0) {
-										pixel = *srcP++;
-										if (pixel & 0x80) {
-											pixel &= 0x7f;
-											runLength = *srcP++;
-											if (!runLength)
-												runLength = width2;
-										}
-									}
-
-									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
-										if (pixel > 0)
-											*destP = pixel;
-										++destP;
-									}
-								}
-
-								if (yp >= tmpHeight)
-									destP += widthDiff2;
-							}
-						} else {
-							// loc_262BE
-							byteVal = 0;
-							for (int yp = 0; yp < height1; ++yp) {
-								for (int xp = 0; xp < width2; ++xp) {
-									byteVal2 = 0;
-									if (!byteVal2) {
-										byteVal = *++srcP;
-										if (byteVal & 0x80) {
-											byteVal &= 0x7f;
-											byteVal2 = *srcP++;
-
-											if (!byteVal2)
-												byteVal2 = width2;
-										}
-									}
-
-									if (byteVal > 0)
-										*destP = byteVal;
-
-									++destP;
-									--byteVal2;
-								}
-
-								destP += widthDiff2;
-							}
-						}
-					} else {
-						// loc_2637F
-						// Copy with transparency
-						for (int yp = 0; yp < height1; ++yp) {
-							for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
-								if (*srcP != 0)
-									*destP = *srcP;
-							}
-
-							destP += widthDiff2;
-							srcP += widthDiff;
-						}
-					}
-				} else {
-					if (srcFlags & DISPFLAG_100) {
-						// Simple run-length encoded image
-						srcP = srcImgData;
-
-						if (isClipped) {
-							// loc_26424
-							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
-							int xMax = tmpWidth + width2;
-							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
-							width2 = srcPic->_bounds.width();
-							height1 = tmpHeight + height1;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								runLength = 0;
-								for (int xp = 0; xp < width2; ++xp, --runLength) {
-									if (runLength <= 0) {
-										pixel = *srcP++;
-										if (pixel & 0x80) {
-											pixel &= 0x7F;
-											runLength = *srcP++;
-
-											if (!runLength)
-												runLength = width2;
-										}
-									}
-
-									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
-										*destP++ = pixel;
-									}
-								}
-
-								if (yp >= tmpHeight)
-									destP += widthDiff2;
-							}
-						} else {
-							// loc_26543
-							for (int yp = 0; yp < height1; ++yp) {
-								int runLen = 0;
-								for (int xp = 0; xp < width2; ++xp, --runLen) {
-									if (runLen <= 0) {
-										// Start of run length, so get pixel and repeat length
-										pixel = *srcP++;
-										if (pixel & 0x80) {
-											pixel &= 0x7f;
-											runLen = *srcP++;
-											if (runLen == 0)
-												runLen = width2;
-										}
-									}
-
-									// Copy pixel to output
-									*destP++ = pixel;
-								}
-
-								destP += widthDiff2;
-							}
-						}
-					} else {
-						for (int yp = 0; yp < height1; ++yp) {
-							Common::copy(srcP, srcP + width2, destP);
-							destP += width2 + widthDiff2;
-							srcP += width2 + widthDiff;
-						}
-					}
-				}
-			}
-		}
-	} else {
-		// loc_26666
-		if (srcPic->_pick == 0) {
-			// loc_2727A
-			byte onOff = srcPic->_onOff;
-
-			if (srcFlags & DISPFLAG_2) {
-				if (!(srcFlags & DISPFLAG_8)) {
-					srcP = srcImgData + srcOffset;
-
-					if (destFlags & DISPFLAG_8) {
-						// loc_272C3
-						error("TODO: sDrawPic variation");
-					} else {
-						destP = destImgData + screenOffset;
-						for (int yp = 0; yp < height1; ++yp) {
-							for (int xp = 0; xp < width2; ++xp, ++destP) {
-								if ((int8)*srcP++ < 0)
-									*destP = onOff;
-							}
-
-							destP += widthDiff2;
-							srcP += widthDiff;
-						}
-					}
-				}
-			} else {
-				// loc_27477
-				if (destFlags & DISPFLAG_8) {
-					// loc_27481
-					destP = (byte *)_screenSurface.getPixels() + screenOffset;
-					for (int yp = 0; yp < height1; ++yp) {
-						Common::fill(destP, destP + width2, onOff);
-						destP += width2 + widthDiff2;
-					}
-				} else {
-					// loc_2753C
-					destP = destImgData + screenOffset;
-
-					for (int yp = 0; yp < height1; ++yp) {
-						Common::fill(destP, destP + width2, onOff);
-						destP += width2 + widthDiff2;
-					}
-				}
-			}
-
-		} else {
-			// loc_26673
-			byte pick = srcPic->_pick;
-			byte onOff = srcPic->_onOff;
-
-			if (!(srcFlags & PICFLAG_PIC_OFFSET)) {
-				srcP = srcImgData += srcOffset;
-				pixel = 0;
-
-				if (destFlags & PICFLAG_PIC_OFFSET) {
-					destP = destImgData + screenOffset;
-					if (srcFlags & PICFLAG_2) {
-						if (srcFlags & PICFLAG_100) {
-							if (isClipped) {
-								// loc_266E3
-								destP = (byte *)_screenSurface.getPixels() + screenOffset;
-								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
-								int xMax = tmpWidth + width2;
-								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
-								pick = 0x7F;
-								width2 = srcPic->_bounds.width();
-								height1 = tmpHeight + height1;
-
-								for (int yp = 0; yp < height1; ++yp) {
-									int runLen = 0;
-									for (int xp = 0; xp < width2; ++xp, --runLen) {
-										if (runLen <= 0) {
-											pixel = *srcP++;
-											if (pixel & 0x80) {
-												pixel &= 0x7F;
-												runLen = *srcP++;
-												if (!runLen)
-													runLen = width2;
-											}
-										}
-
-										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
-											if (pixel) {
-												*destP = (pixel & pick) ^ onOff;
-											}
-											++destP;
-										}
-									}
-									if (yp >= tmpHeight)
-										destP += widthDiff2;
-								}
-							} else {
-								// loc_26815
-								destP = (byte *)_screenSurface.getPixels() + screenOffset;
-
-								for (int yp = 0; yp < height1; ++yp) {
-									for (int xi = 0; xi < width2; ++xi, ++destP) {
-										byteVal2 = 0;
-										for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
-											if (!byteVal2) {
-												pixel = *srcP++;
-												if (pixel & 0x80) {
-													pixel &= 0x7F;
-													byteVal2 = *srcP++;
-													if (!byteVal2) {
-														byteVal2 = width2;
-													}
-												}
-											}
-
-											if (pixel)
-												*destP = (pixel & pick) ^ onOff;
-										}
-									}
-
-									destP += widthDiff2;
-								}
-							}
-						} else {
-							// Direct screen write
-							destP = (byte *)_screenSurface.getPixels() + screenOffset;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
-									if (*srcP)
-										*destP = (*srcP & pick) ^ onOff;
-								}
-								destP += widthDiff2;
-								srcP += widthDiff;
-							}
-						}
-					} else if (srcFlags & PICFLAG_100) {
-						srcP = srcImgData;
-						if (isClipped) {
-							// loc_269FD
-							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
-							int xMax = tmpWidth + width2;
-							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
-							width2 = srcPic->_bounds.width();
-							height1 = tmpHeight + height1;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								runLength = 0;
-								for (int xp = 0; xp < width2; ++xp, --runLength) {
-									if (runLength <= 0) {
-										pixel = *srcP++;
-										if (pixel & 0x80) {
-											pixel &= 0x7F;
-											runLength = *srcP++;
-
-											if (!runLength)
-												runLength = width2;
-										}
-									}
-
-									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
-										*destP++ = (pixel & 0x80) ^ onOff;
-									}
-								}
-							}
-						} else {
-							// loc_26BD5
-							destP = (byte *)_screenSurface.getPixels() + screenOffset;
-
-							for (int yp = 0; yp < height1; ++yp) {
-								byteVal2 = 0;
-
-								for (int xp = 0; xp < width2; ++xp, ++destP) {
-									if (!byteVal2) {
-										pixel = *srcP++;
-										if (pixel & 0x80) {
-											pixel &= 0x7F;
-											byteVal2 = *srcP++;
-											if (!byteVal2)
-												byteVal2 = width2;
-										}
-									}
-
-									*destP = (pixel & pick) ^ onOff;
-								}
-
-								destP += widthDiff2;
-							}
-						}
-					} else {
-						// loc_26C9A
-						destP = (byte *)_screenSurface.getPixels() + screenOffset;
-
-						for (int yp = 0; yp < height1; ++yp) {
-							for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
-								*destP = (*srcP & pick) ^ onOff;
-							}
-							destP += widthDiff2;
-							srcP += widthDiff;
-						}
-					}
-				} else {
-					// loc_26D2F
-					destP = destImgData + screenOffset;
-
-					if (srcFlags & PICFLAG_2) {
-						// loc_26D4F
-						if (srcFlags & PICFLAG_100) {
-							srcP = srcImgData;
-
-							if (isClipped) {
-								// loc_26D6A
-								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
-								int xMax = tmpWidth + width2;
-								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
-								width2 = srcPic->_bounds.width();
-								height1 = tmpHeight + height1;
-
-								for (int yp = 0; yp < height1; ++yp) {
-									runLength = 0;
-
-									for (int xp = 0; xp < width2; ++xp, --runLength) {
-										if (runLength <= 0) {
-											pixel = *srcP++;
-											if (pixel & 0x80) {
-												pixel &= 0x7F;
-												runLength = *srcP++;
-												if (!runLength)
-													runLength = width2;
-											}
-										}
-
-										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
-											if (pixel)
-												*destP = (pixel & pick) ^ onOff;
-
-											++destP;
-										}
-									}
-
-									if (yp >= tmpHeight)
-										destP += widthDiff2;
-								}
-							} else {
-								// loc_26E95
-								for (int yp = 0; yp < height1; ++yp) {
-									byteVal2 = 0;
-									for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
-										if (!byteVal2) {
-											pixel = *srcP++;
-											if (pixel & 0x80) {
-												pixel &= 0x7F;
-												byteVal2 = *srcP++;
-												if (!byteVal2)
-													byteVal2 = width2;
-											}
-										}
-
-										if (pixel)
-											*destP = (pixel & pick) ^ onOff;
-									}
-
-									destP += widthDiff2;
-								}
-							}
-						} else {
-							// loc_26F5D
-							for (int yp = 0; yp < height1; ++yp) {
-								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
-									if (*srcP)
-										*destP = (*srcP & pick) ^ onOff;
-								}
-								destP += widthDiff2;
-								srcP += widthDiff;
-							}
-						}
-					} else {
-						// loc_26FEF
-						if (srcFlags & PICFLAG_100) {
-							// loc_26FF9
-							for (int yp = 0; yp < height1; ++yp) {
-								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
-									*destP = (*srcP & pick) ^ onOff;
-								}
-								destP += widthDiff2;
-								srcP += widthDiff;
-							}
-						} else {
-							// loc_271F0
-							srcP = srcImgData;
-
-							if (isClipped) {
-								// loc_2700A
-								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
-								int xMax = tmpWidth + width2;
-								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
-								width2 = srcPic->_bounds.width();
-								height1 = tmpHeight + height1;
-
-								for (int yp = 0; yp < height1; ++yp) {
-									runLength = 0;
-
-									for (int xp = 0; xp < width2; ++xp, --runLength) {
-										if (runLength <= 0) {
-											pixel = *srcP++;
-											if (pixel & 0x80) {
-												pixel &= 0x7F;
-												runLength = *srcP++;
-												if (!runLength)
-													runLength = width2;
-											}
-										}
-
-										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
-											*destP++ = (pixel & pick) ^ onOff;
-										}
-									}
-
-									if (yp >= tmpHeight)
-										destP += widthDiff2;
-								}
-							} else {
-								// loc_2712F
-								for (int yp = 0; yp < height1; ++yp) {
-									byteVal2 = 0;
-									for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
-										if (!byteVal2) {
-											pixel = *srcP++;
-											if (pixel & 0x80) {
-												pixel &= 0x7F;
-												byteVal2 = *srcP++;
-												if (!byteVal2)
-													byteVal2 = width2;
-											}
-										}
-
-										*destP = (*srcP & pick) ^ onOff;
-									}
-									destP += widthDiff2;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-
-	if (cursorData) {
-		_vm->_eventsManager->setCursor(cursorData, width2, height1, srcPic->_keyColor);
-		delete[] cursorData;
-	}
-}
-
-void GraphicsManager::drawANumber(DisplayResource *display, int num, const Common::Point &pt) {
-	PictureResource *pic = _vm->_bVoy->boltEntry(num + 261)._picResource;
-	sDrawPic(pic, display, pt);
-}
-
-void GraphicsManager::fillPic(DisplayResource *display, byte onOff) {
-	PictureResource *pic;
-	if (display->_flags & DISPFLAG_VIEWPORT) {
-		pic = ((ViewPortResource *)display)->_currentPic;
-	} else {
-		pic = (PictureResource *)display;
-	}
-
-	PictureResource picResource;
-	picResource._flags = DISPFLAG_NONE;
-	picResource._select = 0xff;
-	picResource._pick = 0;
-	picResource._onOff = onOff;
-	picResource._bounds = pic->_bounds;
-
-	sDrawPic(&picResource, display, Common::Point());
-}
-
-/**
- * Queues the given picture for display
- */
-void GraphicsManager::sDisplayPic(PictureResource *pic) {
-	_vm->_eventsManager->_intPtr._flipWait = true;
-}
-
-void GraphicsManager::flipPage() {
-	Common::Array<ViewPortResource *> &viewPorts = _viewPortListPtr->_entries;
-	bool flipFlag = false;
-
-	for (uint idx = 0; idx < viewPorts.size(); ++idx) {
-		if ((viewPorts[idx]->_flags & (DISPFLAG_20 | DISPFLAG_8 | DISPFLAG_1)) == (DISPFLAG_20 | DISPFLAG_8 | DISPFLAG_1)) {
-			if (_planeSelect == idx)
-				sDisplayPic(viewPorts[idx]->_currentPic);
-			flipFlag = true;
-		}
-
-		if (flipFlag) {
-			ViewPortResource &viewPort = *viewPorts[idx];
-
-			viewPort._lastPage = viewPort._pageIndex;
-			++viewPort._pageIndex;
-
-			if (viewPort._pageIndex >= viewPort._pageCount)
-				viewPort._pageIndex = 0;
-
-			assert(viewPort._pageIndex < 2);
-			viewPort._currentPic = viewPort._pages[viewPort._pageIndex];
-			viewPort._flags = (viewPort._flags & ~DISPFLAG_8) | DISPFLAG_40;
-		}
-	}
-}
-
-void GraphicsManager::restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
-		PictureResource *srcPic, PictureResource *destPic) {
-	// WORKAROUND: Since _backgroundPage can point to a resource freed at the end of display methods,
-	// I'm now explicitly resetting it to null in screenReset(), so at this point it can be null
-	if (!srcPic)
-		return;
-
-	bool saveBack = _saveBack;
-	_saveBack = false;
-
-	if (rectListCount == -1) {
-		sDrawPic(srcPic, destPic, Common::Point());
-	} else {
-		for (int i = rectListCount - 1; i >= 0; --i) {
-			_clipPtr = &rectList[i];
-			sDrawPic(srcPic, destPic, Common::Point());
-		}
-	}
-
-	_saveBack = saveBack;
-}
-
-void GraphicsManager::clearPalette() {
-	byte palette[768];
-	Common::fill(&palette[0], &palette[768], 0);
-	g_system->getPaletteManager()->setPalette(&palette[0], 0, 256);
-}
-
-void GraphicsManager::setPalette(const byte *palette, int start, int count) {
-	g_system->getPaletteManager()->setPalette(palette, start, count);
-	_vm->_eventsManager->_gameData._hasPalette = false;
-}
-
-void GraphicsManager::setPalette128(const byte *palette, int start, int count) {
-	byte rgb[3];
-	g_system->getPaletteManager()->grabPalette(&rgb[0], 128, 1);
-	g_system->getPaletteManager()->setPalette(palette, start, count);
-	g_system->getPaletteManager()->setPalette(&rgb[0], 128, 1);
-}
-
-
-void GraphicsManager::resetPalette() {
-	for (int i = 0; i < 256; ++i)
-		setColor(i, 0, 0, 0);
-
-	_vm->_eventsManager->_intPtr._hasPalette = true;
-}
-
-void GraphicsManager::setColor(int idx, byte r, byte g, byte b) {
-	byte *vgaP = &_VGAColors[idx * 3];
-	vgaP[0] = r;
-	vgaP[1] = g;
-	vgaP[2] = b;
-
-	_vm->_eventsManager->_intPtr._palStartIndex = MIN(_vm->_eventsManager->_intPtr._palStartIndex, idx);
-	_vm->_eventsManager->_intPtr._palEndIndex = MAX(_vm->_eventsManager->_intPtr._palEndIndex, idx);
-}
-
-void GraphicsManager::setOneColor(int idx, byte r, byte g, byte b) {
-	byte palEntry[3];
-	palEntry[0] = r;
-	palEntry[1] = g;
-	palEntry[2] = b;
-	g_system->getPaletteManager()->setPalette(&palEntry[0], idx, 1);
-}
-
-void GraphicsManager::setColors(int start, int count, const byte *pal) {
-	for (int i = 0; i < count; ++i) {
-		if ((i + start) != 128) {
-			const byte *rgb = pal + i * 3;
-			setColor(i + start, rgb[0], rgb[1], rgb[2]);
-		}
-	}
-
-	_vm->_eventsManager->_intPtr._hasPalette = true;
-}
-
-void GraphicsManager::screenReset() {
-	resetPalette();
-
-	_backgroundPage = NULL;
-	_vPort->setupViewPort(NULL);
-	fillPic(_vPort, 0);
-
-	_vm->flipPageAndWait();
-}
-
-void GraphicsManager::fadeDownICF1(int steps) {
-	if (steps > 0) {
-		int stepAmount = _vm->_voy->_fadingAmount2 / steps;
-
-		for (int idx = 0; idx < steps; ++idx) {
-			_vm->_voy->_fadingAmount2 -= stepAmount;
-			_vm->_eventsManager->delay(1);
-		}
-	}
-
-	_vm->_voy->_fadingAmount2 = 0;
-}
-
-void GraphicsManager::fadeUpICF1(int steps) {
-	if (steps > 0) {
-		int stepAmount = (63 - _vm->_voy->_fadingAmount2) / steps;
-
-		for (int idx = 0; idx < steps; ++idx) {
-			_vm->_voy->_fadingAmount2 += stepAmount;
-			_vm->_eventsManager->delay(1);
-		}
-	}
-
-	_vm->_voy->_fadingAmount2 = 63;
-}
-
-void GraphicsManager::fadeDownICF(int steps) {
-	if (steps > 0) {
-		_vm->_eventsManager->hideCursor();
-		int stepAmount1 = _vm->_voy->_fadingAmount1 / steps;
-		int stepAmount2 = _vm->_voy->_fadingAmount2 / steps;
-
-		for (int idx = 0; idx < steps; ++idx) {
-			_vm->_voy->_fadingAmount1 -= stepAmount1;
-			_vm->_voy->_fadingAmount2 -= stepAmount2;
-			_vm->_eventsManager->delay(1);
-		}
-	}
-
-	_vm->_voy->_fadingAmount1 = 0;
-	_vm->_voy->_fadingAmount2 = 0;
-}
-
-void GraphicsManager::drawDot() {
-	for (int y = 0; y < 9; ++y) {
-		byte *pDest = (byte *)_screenSurface.getPixels() + DOT_LINE_START[y] + DOT_LINE_OFFSET[y];
-		Common::fill(pDest, pDest + DOT_LINE_LENGTH[y], 0x80);
-	}
-}
-
-void GraphicsManager::synchronize(Common::Serializer &s) {
-	s.syncBytes(&_VGAColors[0], PALETTE_SIZE);
-}
-
-} // End of namespace Voyeur
diff --git a/engines/voyeur/graphics.h b/engines/voyeur/graphics.h
deleted file mode 100644
index e4d0b38..0000000
--- a/engines/voyeur/graphics.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef VOYEUR_GRAPHICS_H
-#define VOYEUR_GRAPHICS_H
-
-#include "common/scummsys.h"
-#include "common/array.h"
-#include "common/rect.h"
-#include "common/serializer.h"
-#include "graphics/surface.h"
-
-namespace Voyeur {
-
-#define SCREEN_WIDTH 320
-#define SCREEN_HEIGHT 200
-#define PALETTE_COUNT 256
-#define PALETTE_SIZE (256 * 3)
-
-class VoyeurEngine;
-class GraphicsManager;
-class DisplayResource;
-class PictureResource;
-class ViewPortResource;
-class ViewPortListResource;
-class FontResource;
-class FontInfoResource;
-class CMapResource;
-
-class DrawInfo {
-public:
-	int _penColor;
-	Common::Point _pos;
-public:
-	DrawInfo(int penColor, const Common::Point &pos);
-};
-
-typedef void (GraphicsManager::*GraphicMethodPtr)();
-typedef void (GraphicsManager::*ViewPortSetupPtr)(ViewPortResource *);
-typedef void (GraphicsManager::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds);
-typedef void (GraphicsManager::*ViewPortRestorePtr)(ViewPortResource *);
-
-class GraphicsManager {
-public:
-	byte _VGAColors[PALETTE_SIZE];
-	PictureResource *_backgroundPage;
-	int _SVGAMode;
-	ViewPortListResource *_viewPortListPtr;
-	ViewPortResource *_vPort;
-	bool _saveBack;
-	Common::Rect *_clipPtr;
-	uint _planeSelect;
-	Graphics::Surface _screenSurface;
-	CMapResource *_backColors;
-	FontInfoResource *_fontPtr;
-	PictureResource *_fontChar;
-	DrawInfo *_drawPtr;
-	DrawInfo _defaultDrawInfo;
-private:
-	VoyeurEngine *_vm;
-
-	void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
-		PictureResource *srcPic, PictureResource *destPic);
-public:
-	GraphicsManager(VoyeurEngine *vm);
-	~GraphicsManager();
-
-	void sInitGraphics();
-
-	void setupMCGASaveRect(ViewPortResource *viewPort);
-	void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
-	void restoreMCGASaveRect(ViewPortResource *viewPort);
-	void addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
-
-	void sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay, const Common::Point &initialOffset);
-	void fillPic(DisplayResource *display, byte onOff);
-	void sDisplayPic(PictureResource *pic);
-	void drawANumber(DisplayResource *display, int num, const Common::Point &pt);
-	void flipPage();
-	void clearPalette();
-	void setPalette(const byte *palette, int start, int count);
-	void setPalette128(const byte *palette, int start, int count);
-	void resetPalette();
-	void setColor(int idx, byte r, byte g, byte b);
-	void setOneColor(int idx, byte r, byte g, byte b);
-	void setColors(int start, int count, const byte *pal);
-	void screenReset();
-	void fadeDownICF1(int steps);
-	void fadeUpICF1(int steps = 0);
-	void fadeDownICF(int steps);
-	void drawDot();
-
-	/**
-	 * Synchronizes the game data
-	 */
-	void synchronize(Common::Serializer &s);
-};
-
-} // End of namespace Voyeur
-
-#endif /* VOYEUR_GRAPHICS_H */
diff --git a/engines/voyeur/module.mk b/engines/voyeur/module.mk
index aab254c..a38bdd9 100644
--- a/engines/voyeur/module.mk
+++ b/engines/voyeur/module.mk
@@ -8,7 +8,7 @@ MODULE_OBJS := \
 	events.o \
 	files.o \
 	files_threads.o \
-	graphics.o \
+	screen.o \
 	sound.o \
 	staticres.o \
 	voyeur.o \
diff --git a/engines/voyeur/screen.cpp b/engines/voyeur/screen.cpp
new file mode 100644
index 0000000..62f609c
--- /dev/null
+++ b/engines/voyeur/screen.cpp
@@ -0,0 +1,1074 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "voyeur/screen.h"
+#include "voyeur/voyeur.h"
+#include "voyeur/staticres.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+namespace Voyeur {
+
+/*------------------------------------------------------------------------*/
+
+DrawInfo::DrawInfo(int penColor, const Common::Point &pos) {
+	_penColor = penColor;
+	_pos = pos;
+}
+
+/*------------------------------------------------------------------------*/
+
+Screen::Screen(VoyeurEngine *vm) : Graphics::Screen(), _vm(vm), _drawPtr(&_defaultDrawInfo),
+		_defaultDrawInfo(1, Common::Point()) {
+	_SVGAMode = 0;
+	_planeSelect = 0;
+	_saveBack = true;
+	_clipPtr = NULL;
+	_viewPortListPtr = NULL;
+	_backgroundPage = NULL;
+	_vPort = NULL;
+	_fontPtr = NULL;
+	Common::fill(&_VGAColors[0], &_VGAColors[PALETTE_SIZE], 0);
+	_fontChar = new PictureResource(DISPFLAG_NONE, 0xff, 0xff, 0, Common::Rect(), 0, NULL, 0);
+	_backColors = nullptr;
+}
+
+void Screen::sInitGraphics() {
+	initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false);
+	create(SCREEN_WIDTH, SCREEN_HEIGHT);
+	clearPalette();
+}
+
+Screen::~Screen() {
+	delete _fontChar;
+}
+
+void Screen::setupMCGASaveRect(ViewPortResource *viewPort) {
+	if (viewPort->_activePage) {
+		viewPort->_activePage->_flags |= DISPFLAG_1;
+		Common::Rect *clipRect = _clipPtr;
+		_clipPtr = &viewPort->_clipRect;
+
+		sDrawPic(viewPort->_activePage, viewPort->_currentPic, Common::Point());
+
+		_clipPtr = clipRect;
+	}
+
+	viewPort->_rectListCount[1] = -1;
+}
+
+void Screen::addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
+	if (viewPort->_rectListCount[idx] == -1)
+		return;
+
+	// TODO: Lots of code in original, which I suspect may be overlapping rect merging
+	viewPort->_rectListPtr[idx]->push_back(bounds);
+	++viewPort->_rectListCount[idx];
+}
+
+void Screen::restoreMCGASaveRect(ViewPortResource *viewPort) {
+	if (viewPort->_rectListCount[0] != -1) {
+		for (int i = 0; i < viewPort->_rectListCount[0]; ++i) {
+			addRectOptSaveRect(viewPort, 1, (*viewPort->_rectListPtr[0])[i]);
+		}
+	} else {
+		viewPort->_rectListCount[1] = -1;
+	}
+
+	restoreBack(*viewPort->_rectListPtr[1], viewPort->_rectListCount[1], viewPort->_pages[0],
+		viewPort->_pages[1]);
+
+	int count = viewPort->_rectListCount[0];
+	restoreBack(*viewPort->_rectListPtr[0], viewPort->_rectListCount[0],
+		viewPort->_activePage, viewPort->_currentPic);
+
+	SWAP(viewPort->_rectListPtr[0], viewPort->_rectListPtr[1]);
+	viewPort->_rectListCount[1] = count;
+}
+
+void Screen::addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds) {
+	// Stubbed/dummy method in the original.
+}
+
+void Screen::sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay,
+		const Common::Point &initialOffset) {
+	int width1, width2;
+	int widthDiff, widthDiff2;
+	int height1;
+	int srcOffset;
+	int screenOffset;
+	int srcFlags, destFlags;
+	ViewPortResource *destViewPort = NULL;
+	Common::Rect newBounds;
+	Common::Rect backBounds;
+	int tmpWidth = 0;
+	int tmpHeight = 0;
+	bool isClipped = false;
+	byte pixel = 0;
+	int runLength;
+
+	byte *srcImgData, *destImgData;
+	const byte *srcP;
+	byte *destP;
+	byte byteVal, byteVal2;
+
+	PictureResource *srcPic;
+	PictureResource *destPic;
+
+	// Get the picture parameters, or deference viewport pointers to get their pictures
+	if (srcDisplay->_flags & DISPFLAG_VIEWPORT) {
+		// A viewport was passed, not a picture
+		srcPic = ((ViewPortResource *)srcDisplay)->_currentPic;
+	} else {
+		srcPic = (PictureResource *)srcDisplay;
+	}
+
+	if (destDisplay->_flags & DISPFLAG_VIEWPORT) {
+		// A viewport was passed, not a picture
+		destViewPort = (ViewPortResource *)destDisplay;
+		destPic = destViewPort->_currentPic;
+	} else {
+		destPic = (PictureResource *)destDisplay;
+	}
+
+	Common::Point offset = Common::Point(initialOffset.x + srcPic->_bounds.left - destPic->_bounds.left,
+		initialOffset.y + srcPic->_bounds.top - destPic->_bounds.top);
+	width1 = width2 = srcPic->_bounds.width();
+	height1 = srcPic->_bounds.height();
+	srcOffset = 0;
+	srcFlags = srcPic->_flags;
+	destFlags = destPic->_flags;
+	byte *cursorData = NULL;
+
+	if (srcFlags & DISPFLAG_1) {
+		if (_clipPtr) {
+			int xs = _clipPtr->left - destPic->_bounds.left;
+			int ys = _clipPtr->top - destPic->_bounds.top;
+			newBounds = Common::Rect(xs, ys, xs + _clipPtr->width(), ys + _clipPtr->height());
+		} else if (destViewPort) {
+			int xs = destViewPort->_clipRect.left - destPic->_bounds.left;
+			int ys = destViewPort->_clipRect.top - destPic->_bounds.top;
+			newBounds = Common::Rect(xs, ys, xs + destViewPort->_clipRect.width(),
+				ys + destViewPort->_clipRect.height());
+		} else {
+			newBounds = Common::Rect(0, 0, destPic->_bounds.width(), destPic->_bounds.height());
+		}
+
+		tmpHeight = offset.y - newBounds.top;
+		if (tmpHeight < 0) {
+			srcOffset -= tmpHeight * width2;
+			height1 += tmpHeight;
+			offset.y = newBounds.top;
+
+			if (height1 <= 0)
+				return;
+
+			isClipped = true;
+		}
+
+		int yMin = newBounds.bottom - (offset.y + height1);
+		if (yMin < 0) {
+			height1 += yMin;
+			if (height1 <= 0)
+				return;
+		}
+
+		tmpWidth = offset.x - newBounds.left;
+		if (tmpWidth < 0) {
+			srcOffset -= tmpWidth;
+			width2 += tmpWidth;
+			offset.x = newBounds.left;
+
+			if (width2 <= 0)
+				return;
+
+			isClipped = true;
+		}
+
+		int xMin = newBounds.right - (offset.x + width2);
+		if (xMin < 0) {
+			width2 += xMin;
+			if (width2 <= 0)
+				return;
+
+			isClipped = true;
+		}
+	}
+
+	screenOffset = offset.y * destPic->_bounds.width() + offset.x;
+	widthDiff = width1 - width2;
+	widthDiff2 = destPic->_bounds.width() - width2;
+
+	if (destViewPort) {
+		if (!_saveBack || (srcPic->_flags & DISPFLAG_800)) {
+			backBounds.left = destPic->_bounds.left + offset.x;
+			backBounds.top = destPic->_bounds.top + offset.y;
+			backBounds.setWidth(width2);
+			backBounds.setHeight(height1);
+			addRectOptSaveRect(destViewPort, 1, backBounds);
+
+		} else if (!destViewPort->_addFn) {
+			if (destViewPort->_rectListCount[destViewPort->_pageIndex] < -1) {
+				Common::Rect r;
+				r.left = destPic->_bounds.left + offset.x;
+				r.top = destPic->_bounds.top + offset.y;
+				r.setWidth(width2);
+				r.setHeight(height1);
+
+				(*destViewPort->_rectListPtr[destViewPort->_pageIndex]).push_back(r);
+				++destViewPort->_rectListCount[destViewPort->_pageIndex];
+			}
+		} else {
+			int xs = offset.x + destPic->_bounds.left;
+			int ys = offset.y + destPic->_bounds.top;
+			backBounds = Common::Rect(xs, ys, xs + width2, ys + height1);
+
+			(this->*destViewPort->_addFn)(destViewPort, destViewPort->_bounds.top, backBounds);
+		}
+	}
+
+	if (srcFlags & DISPFLAG_1000) {
+		int imageDataShift = 0;
+		srcImgData = srcPic->_imgData + (imageDataShift << 14);
+		for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
+			if (imageDataShift < 4)
+				++imageDataShift;
+		}
+
+		destImgData = destPic->_imgData + (imageDataShift << 14);
+		for (uint idx = 0; idx < srcPic->_maskData; ++idx) {
+			if (imageDataShift < 4)
+				++imageDataShift;
+		}
+	} else {
+		srcImgData = srcPic->_imgData;
+		destImgData = destPic->_imgData;
+	}
+
+	if (srcPic->_select != 0xff)
+		return;
+
+	if (destFlags & DISPFLAG_CURSOR) {
+		cursorData = new byte[width2 * height1];
+		Common::fill(cursorData, cursorData + width2 * height1, 0);
+		destImgData = cursorData;
+	}
+
+	if (srcPic->_pick == 0xff) {
+		if (srcFlags & DISPFLAG_8) {
+			error("TODO: sDrawPic variation");
+		} else {
+			// loc_258B8
+			srcP = srcImgData + srcOffset;
+
+			if (destFlags & DISPFLAG_8) {
+				// loc_258D8
+				destP = destImgData + screenOffset;
+
+				if (srcFlags & DISPFLAG_2) {
+					// loc_25652
+					srcP = srcImgData + srcOffset;
+
+					if (destFlags & DISPFLAG_8) {
+						// loc_2566F
+						if (srcFlags & DISPFLAG_2) {
+							// loc_256FA
+							srcP = (const byte *)getPixels() + srcOffset;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
+									pixel = *srcP;
+									if (pixel)
+										*destP = pixel;
+								}
+
+								srcP += widthDiff;
+								destP += widthDiff2;
+							}
+						} else {
+							// loc_25706
+							for (int yp = 0; yp < height1; ++yp) {
+								Common::copy(srcP, srcP + width2, destP);
+								srcP += width2 + widthDiff;
+								destP += width2 + widthDiff2;
+							}
+						}
+					} else {
+						// loc_25773
+						destP = destImgData + screenOffset;
+
+						if (srcFlags & DISPFLAG_2) {
+							// loc_25793
+							for (int yp = 0; yp < height1; ++yp) {
+								Common::copy(srcP, srcP + width2, destP);
+								srcP += width2 + widthDiff;
+								destP += width2 + widthDiff2;
+							}
+						} else {
+							// loc_25829
+							destP = (byte *)getPixels() + screenOffset;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								Common::copy(srcP, srcP + width2, destP);
+								srcP += width2 + widthDiff;
+								destP += width2 + widthDiff2;
+							}
+
+							addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2, 
+								offset.y + height1));
+						}
+					}
+				} else {
+					// loc_25D40
+					if (srcFlags & DISPFLAG_100) {
+						// loc_25D4A
+						error("TODO: sDrawPic variation");
+					} else {
+						// loc_2606D
+						destP = (byte *)getPixels() + screenOffset;
+
+						for (int yp = 0; yp < height1; ++yp) {
+							Common::copy(srcP, srcP + width2, destP);
+							destP += width2 + widthDiff2;
+							srcP += width2 + widthDiff;
+						}
+
+						addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+							offset.y + height1));
+					}
+				}
+			} else {
+				// loc_2615E
+				destP = destImgData + screenOffset;
+
+				if (srcFlags & DISPFLAG_2) {
+					// loc_2617e
+					if (srcFlags & DISPFLAG_100) {
+						// loc_26188
+						srcP = srcImgData;
+						if (isClipped) {
+							// loc_26199
+							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
+							int xMax = tmpWidth + width2;
+							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
+
+							width2 = srcPic->_bounds.width();
+							height1 = tmpHeight + height1;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								runLength = 0;
+
+								for (int xp = 0; xp < width2; ++xp, --runLength) {
+									if (runLength <= 0) {
+										pixel = *srcP++;
+										if (pixel & 0x80) {
+											pixel &= 0x7f;
+											runLength = *srcP++;
+											if (!runLength)
+												runLength = width2;
+										}
+									}
+
+									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
+										if (pixel > 0)
+											*destP = pixel;
+										++destP;
+									}
+								}
+
+								if (yp >= tmpHeight)
+									destP += widthDiff2;
+							}
+						} else {
+							// loc_262BE
+							byteVal = 0;
+							for (int yp = 0; yp < height1; ++yp) {
+								for (int xp = 0; xp < width2; ++xp) {
+									byteVal2 = 0;
+									if (!byteVal2) {
+										byteVal = *++srcP;
+										if (byteVal & 0x80) {
+											byteVal &= 0x7f;
+											byteVal2 = *srcP++;
+
+											if (!byteVal2)
+												byteVal2 = width2;
+										}
+									}
+
+									if (byteVal > 0)
+										*destP = byteVal;
+
+									++destP;
+									--byteVal2;
+								}
+
+								destP += widthDiff2;
+							}
+						}
+					} else {
+						// loc_2637F
+						// Copy with transparency
+						for (int yp = 0; yp < height1; ++yp) {
+							for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
+								if (*srcP != 0)
+									*destP = *srcP;
+							}
+
+							destP += widthDiff2;
+							srcP += widthDiff;
+						}
+					}
+				} else {
+					if (srcFlags & DISPFLAG_100) {
+						// Simple run-length encoded image
+						srcP = srcImgData;
+
+						if (isClipped) {
+							// loc_26424
+							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
+							int xMax = tmpWidth + width2;
+							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
+							width2 = srcPic->_bounds.width();
+							height1 = tmpHeight + height1;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								runLength = 0;
+								for (int xp = 0; xp < width2; ++xp, --runLength) {
+									if (runLength <= 0) {
+										pixel = *srcP++;
+										if (pixel & 0x80) {
+											pixel &= 0x7F;
+											runLength = *srcP++;
+
+											if (!runLength)
+												runLength = width2;
+										}
+									}
+
+									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
+										*destP++ = pixel;
+									}
+								}
+
+								if (yp >= tmpHeight)
+									destP += widthDiff2;
+							}
+						} else {
+							// loc_26543
+							for (int yp = 0; yp < height1; ++yp) {
+								int runLen = 0;
+								for (int xp = 0; xp < width2; ++xp, --runLen) {
+									if (runLen <= 0) {
+										// Start of run length, so get pixel and repeat length
+										pixel = *srcP++;
+										if (pixel & 0x80) {
+											pixel &= 0x7f;
+											runLen = *srcP++;
+											if (runLen == 0)
+												runLen = width2;
+										}
+									}
+
+									// Copy pixel to output
+									*destP++ = pixel;
+								}
+
+								destP += widthDiff2;
+							}
+						}
+					} else {
+						for (int yp = 0; yp < height1; ++yp) {
+							Common::copy(srcP, srcP + width2, destP);
+							destP += width2 + widthDiff2;
+							srcP += width2 + widthDiff;
+						}
+					}
+				}
+			}
+		}
+	} else {
+		// loc_26666
+		if (srcPic->_pick == 0) {
+			// loc_2727A
+			byte onOff = srcPic->_onOff;
+
+			if (srcFlags & DISPFLAG_2) {
+				if (!(srcFlags & DISPFLAG_8)) {
+					srcP = srcImgData + srcOffset;
+
+					if (destFlags & DISPFLAG_8) {
+						// loc_272C3
+						error("TODO: sDrawPic variation");
+					} else {
+						destP = destImgData + screenOffset;
+						for (int yp = 0; yp < height1; ++yp) {
+							for (int xp = 0; xp < width2; ++xp, ++destP) {
+								if ((int8)*srcP++ < 0)
+									*destP = onOff;
+							}
+
+							destP += widthDiff2;
+							srcP += widthDiff;
+						}
+					}
+				}
+			} else {
+				// loc_27477
+				if (destFlags & DISPFLAG_8) {
+					// loc_27481
+					destP = (byte *)getPixels() + screenOffset;
+					for (int yp = 0; yp < height1; ++yp) {
+						Common::fill(destP, destP + width2, onOff);
+						destP += width2 + widthDiff2;
+					}
+
+					addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+						offset.y + height1));
+				} else {
+					// loc_2753C
+					destP = destImgData + screenOffset;
+
+					for (int yp = 0; yp < height1; ++yp) {
+						Common::fill(destP, destP + width2, onOff);
+						destP += width2 + widthDiff2;
+					}
+				}
+			}
+
+		} else {
+			// loc_26673
+			byte pick = srcPic->_pick;
+			byte onOff = srcPic->_onOff;
+
+			if (!(srcFlags & PICFLAG_PIC_OFFSET)) {
+				srcP = srcImgData += srcOffset;
+				pixel = 0;
+
+				if (destFlags & PICFLAG_PIC_OFFSET) {
+					destP = destImgData + screenOffset;
+					if (srcFlags & PICFLAG_2) {
+						if (srcFlags & PICFLAG_100) {
+							if (isClipped) {
+								// loc_266E3
+								destP = (byte *)getPixels() + screenOffset;
+								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
+								int xMax = tmpWidth + width2;
+								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
+								pick = 0x7F;
+								width2 = srcPic->_bounds.width();
+								height1 = tmpHeight + height1;
+
+								for (int yp = 0; yp < height1; ++yp) {
+									int runLen = 0;
+									for (int xp = 0; xp < width2; ++xp, --runLen) {
+										if (runLen <= 0) {
+											pixel = *srcP++;
+											if (pixel & 0x80) {
+												pixel &= 0x7F;
+												runLen = *srcP++;
+												if (!runLen)
+													runLen = width2;
+											}
+										}
+
+										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
+											if (pixel) {
+												*destP = (pixel & pick) ^ onOff;
+											}
+											++destP;
+										}
+									}
+									if (yp >= tmpHeight)
+										destP += widthDiff2;
+								}
+
+								addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+									offset.y + height1));
+							} else {
+								// loc_26815
+								destP = (byte *)getPixels() + screenOffset;
+
+								for (int yp = 0; yp < height1; ++yp) {
+									for (int xi = 0; xi < width2; ++xi, ++destP) {
+										byteVal2 = 0;
+										for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
+											if (!byteVal2) {
+												pixel = *srcP++;
+												if (pixel & 0x80) {
+													pixel &= 0x7F;
+													byteVal2 = *srcP++;
+													if (!byteVal2) {
+														byteVal2 = width2;
+													}
+												}
+											}
+
+											if (pixel)
+												*destP = (pixel & pick) ^ onOff;
+										}
+									}
+
+									destP += widthDiff2;
+								}
+
+								addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+									offset.y + height1));
+							}
+						} else {
+							// Direct screen write
+							destP = (byte *)getPixels() + screenOffset;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
+									if (*srcP)
+										*destP = (*srcP & pick) ^ onOff;
+								}
+								destP += widthDiff2;
+								srcP += widthDiff;
+							}
+
+							addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+								offset.y + height1));
+						}
+					} else if (srcFlags & PICFLAG_100) {
+						srcP = srcImgData;
+						if (isClipped) {
+							// loc_269FD
+							tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
+							int xMax = tmpWidth + width2;
+							tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
+							width2 = srcPic->_bounds.width();
+							height1 = tmpHeight + height1;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								runLength = 0;
+								for (int xp = 0; xp < width2; ++xp, --runLength) {
+									if (runLength <= 0) {
+										pixel = *srcP++;
+										if (pixel & 0x80) {
+											pixel &= 0x7F;
+											runLength = *srcP++;
+
+											if (!runLength)
+												runLength = width2;
+										}
+									}
+
+									if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
+										*destP++ = (pixel & 0x80) ^ onOff;
+									}
+								}
+							}
+						} else {
+							// loc_26BD5
+							destP = (byte *)getPixels() + screenOffset;
+
+							for (int yp = 0; yp < height1; ++yp) {
+								byteVal2 = 0;
+
+								for (int xp = 0; xp < width2; ++xp, ++destP) {
+									if (!byteVal2) {
+										pixel = *srcP++;
+										if (pixel & 0x80) {
+											pixel &= 0x7F;
+											byteVal2 = *srcP++;
+											if (!byteVal2)
+												byteVal2 = width2;
+										}
+									}
+
+									*destP = (pixel & pick) ^ onOff;
+								}
+
+								destP += widthDiff2;
+							}
+
+							addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+								offset.y + height1));
+						}
+					} else {
+						// loc_26C9A
+						destP = (byte *)getPixels() + screenOffset;
+
+						for (int yp = 0; yp < height1; ++yp) {
+							for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
+								*destP = (*srcP & pick) ^ onOff;
+							}
+							destP += widthDiff2;
+							srcP += widthDiff;
+						}
+
+						addDirtyRect(Common::Rect(offset.x, offset.y, offset.x + width2,
+							offset.y + height1));
+					}
+				} else {
+					// loc_26D2F
+					destP = destImgData + screenOffset;
+
+					if (srcFlags & PICFLAG_2) {
+						// loc_26D4F
+						if (srcFlags & PICFLAG_100) {
+							srcP = srcImgData;
+
+							if (isClipped) {
+								// loc_26D6A
+								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
+								int xMax = tmpWidth + width2;
+								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
+								width2 = srcPic->_bounds.width();
+								height1 = tmpHeight + height1;
+
+								for (int yp = 0; yp < height1; ++yp) {
+									runLength = 0;
+
+									for (int xp = 0; xp < width2; ++xp, --runLength) {
+										if (runLength <= 0) {
+											pixel = *srcP++;
+											if (pixel & 0x80) {
+												pixel &= 0x7F;
+												runLength = *srcP++;
+												if (!runLength)
+													runLength = width2;
+											}
+										}
+
+										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
+											if (pixel)
+												*destP = (pixel & pick) ^ onOff;
+
+											++destP;
+										}
+									}
+
+									if (yp >= tmpHeight)
+										destP += widthDiff2;
+								}
+							} else {
+								// loc_26E95
+								for (int yp = 0; yp < height1; ++yp) {
+									byteVal2 = 0;
+									for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
+										if (!byteVal2) {
+											pixel = *srcP++;
+											if (pixel & 0x80) {
+												pixel &= 0x7F;
+												byteVal2 = *srcP++;
+												if (!byteVal2)
+													byteVal2 = width2;
+											}
+										}
+
+										if (pixel)
+											*destP = (pixel & pick) ^ onOff;
+									}
+
+									destP += widthDiff2;
+								}
+							}
+						} else {
+							// loc_26F5D
+							for (int yp = 0; yp < height1; ++yp) {
+								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
+									if (*srcP)
+										*destP = (*srcP & pick) ^ onOff;
+								}
+								destP += widthDiff2;
+								srcP += widthDiff;
+							}
+						}
+					} else {
+						// loc_26FEF
+						if (srcFlags & PICFLAG_100) {
+							// loc_26FF9
+							for (int yp = 0; yp < height1; ++yp) {
+								for (int xp = 0; xp < width2; ++xp, ++srcP, ++destP) {
+									*destP = (*srcP & pick) ^ onOff;
+								}
+								destP += widthDiff2;
+								srcP += widthDiff;
+							}
+						} else {
+							// loc_271F0
+							srcP = srcImgData;
+
+							if (isClipped) {
+								// loc_2700A
+								tmpWidth = (tmpWidth < 0) ? -tmpWidth : 0;
+								int xMax = tmpWidth + width2;
+								tmpHeight = (tmpHeight < 0) ? -tmpHeight : 0;
+								width2 = srcPic->_bounds.width();
+								height1 = tmpHeight + height1;
+
+								for (int yp = 0; yp < height1; ++yp) {
+									runLength = 0;
+
+									for (int xp = 0; xp < width2; ++xp, --runLength) {
+										if (runLength <= 0) {
+											pixel = *srcP++;
+											if (pixel & 0x80) {
+												pixel &= 0x7F;
+												runLength = *srcP++;
+												if (!runLength)
+													runLength = width2;
+											}
+										}
+
+										if (yp >= tmpHeight && xp >= tmpWidth && xp < xMax) {
+											*destP++ = (pixel & pick) ^ onOff;
+										}
+									}
+
+									if (yp >= tmpHeight)
+										destP += widthDiff2;
+								}
+							} else {
+								// loc_2712F
+								for (int yp = 0; yp < height1; ++yp) {
+									byteVal2 = 0;
+									for (int xp = 0; xp < width2; ++xp, ++destP, --byteVal2) {
+										if (!byteVal2) {
+											pixel = *srcP++;
+											if (pixel & 0x80) {
+												pixel &= 0x7F;
+												byteVal2 = *srcP++;
+												if (!byteVal2)
+													byteVal2 = width2;
+											}
+										}
+
+										*destP = (*srcP & pick) ^ onOff;
+									}
+									destP += widthDiff2;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if (cursorData) {
+		_vm->_eventsManager->setCursor(cursorData, width2, height1, srcPic->_keyColor);
+		delete[] cursorData;
+	}
+}
+
+void Screen::drawANumber(DisplayResource *display, int num, const Common::Point &pt) {
+	PictureResource *pic = _vm->_bVoy->boltEntry(num + 261)._picResource;
+	sDrawPic(pic, display, pt);
+}
+
+void Screen::fillPic(DisplayResource *display, byte onOff) {
+	PictureResource *pic;
+	if (display->_flags & DISPFLAG_VIEWPORT) {
+		pic = ((ViewPortResource *)display)->_currentPic;
+	} else {
+		pic = (PictureResource *)display;
+	}
+
+	PictureResource picResource;
+	picResource._flags = DISPFLAG_NONE;
+	picResource._select = 0xff;
+	picResource._pick = 0;
+	picResource._onOff = onOff;
+	picResource._bounds = pic->_bounds;
+
+	sDrawPic(&picResource, display, Common::Point());
+}
+
+/**
+ * Queues the given picture for display
+ */
+void Screen::sDisplayPic(PictureResource *pic) {
+	_vm->_eventsManager->_intPtr._flipWait = true;
+}
+
+void Screen::flipPage() {
+	Common::Array<ViewPortResource *> &viewPorts = _viewPortListPtr->_entries;
+	bool flipFlag = false;
+
+	for (uint idx = 0; idx < viewPorts.size(); ++idx) {
+		if ((viewPorts[idx]->_flags & (DISPFLAG_20 | DISPFLAG_8 | DISPFLAG_1)) == (DISPFLAG_20 | DISPFLAG_8 | DISPFLAG_1)) {
+			if (_planeSelect == idx)
+				sDisplayPic(viewPorts[idx]->_currentPic);
+			flipFlag = true;
+		}
+
+		if (flipFlag) {
+			ViewPortResource &viewPort = *viewPorts[idx];
+
+			viewPort._lastPage = viewPort._pageIndex;
+			++viewPort._pageIndex;
+
+			if (viewPort._pageIndex >= viewPort._pageCount)
+				viewPort._pageIndex = 0;
+
+			assert(viewPort._pageIndex < 2);
+			viewPort._currentPic = viewPort._pages[viewPort._pageIndex];
+			viewPort._flags = (viewPort._flags & ~DISPFLAG_8) | DISPFLAG_40;
+		}
+	}
+}
+
+void Screen::restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
+		PictureResource *srcPic, PictureResource *destPic) {
+	// WORKAROUND: Since _backgroundPage can point to a resource freed at the end of display methods,
+	// I'm now explicitly resetting it to null in screenReset(), so at this point it can be null
+	if (!srcPic)
+		return;
+
+	bool saveBack = _saveBack;
+	_saveBack = false;
+
+	if (rectListCount == -1) {
+		sDrawPic(srcPic, destPic, Common::Point());
+	} else {
+		for (int i = rectListCount - 1; i >= 0; --i) {
+			_clipPtr = &rectList[i];
+			sDrawPic(srcPic, destPic, Common::Point());
+		}
+	}
+
+	_saveBack = saveBack;
+}
+
+void Screen::setPalette(const byte *palette, int start, int count) {
+	Graphics::Screen::setPalette(palette, start, count);
+	_vm->_eventsManager->_gameData._hasPalette = false;
+}
+
+void Screen::setPalette128(const byte *palette, int start, int count) {
+	byte rgb[3];
+	getPalette(&rgb[0], 128, 1);
+	Graphics::Screen::setPalette(palette, start, count);
+	Graphics::Screen::setPalette(&rgb[0], 128, 1);
+}
+
+void Screen::resetPalette() {
+	for (int i = 0; i < 256; ++i)
+		setColor(i, 0, 0, 0);
+
+	_vm->_eventsManager->_intPtr._hasPalette = true;
+}
+
+void Screen::setColor(int idx, byte r, byte g, byte b) {
+	byte *vgaP = &_VGAColors[idx * 3];
+	vgaP[0] = r;
+	vgaP[1] = g;
+	vgaP[2] = b;
+
+	_vm->_eventsManager->_intPtr._palStartIndex = MIN(_vm->_eventsManager->_intPtr._palStartIndex, idx);
+	_vm->_eventsManager->_intPtr._palEndIndex = MAX(_vm->_eventsManager->_intPtr._palEndIndex, idx);
+}
+
+void Screen::setOneColor(int idx, byte r, byte g, byte b) {
+	byte palEntry[3];
+	palEntry[0] = r;
+	palEntry[1] = g;
+	palEntry[2] = b;
+	g_system->getPaletteManager()->setPalette(&palEntry[0], idx, 1);
+}
+
+void Screen::setColors(int start, int count, const byte *pal) {
+	for (int i = 0; i < count; ++i) {
+		if ((i + start) != 128) {
+			const byte *rgb = pal + i * 3;
+			setColor(i + start, rgb[0], rgb[1], rgb[2]);
+		}
+	}
+
+	_vm->_eventsManager->_intPtr._hasPalette = true;
+}
+
+void Screen::screenReset() {
+	resetPalette();
+
+	_backgroundPage = NULL;
+	_vPort->setupViewPort(NULL);
+	fillPic(_vPort, 0);
+
+	_vm->flipPageAndWait();
+}
+
+void Screen::fadeDownICF1(int steps) {
+	if (steps > 0) {
+		int stepAmount = _vm->_voy->_fadingAmount2 / steps;
+
+		for (int idx = 0; idx < steps; ++idx) {
+			_vm->_voy->_fadingAmount2 -= stepAmount;
+			_vm->_eventsManager->delay(1);
+		}
+	}
+
+	_vm->_voy->_fadingAmount2 = 0;
+}
+
+void Screen::fadeUpICF1(int steps) {
+	if (steps > 0) {
+		int stepAmount = (63 - _vm->_voy->_fadingAmount2) / steps;
+
+		for (int idx = 0; idx < steps; ++idx) {
+			_vm->_voy->_fadingAmount2 += stepAmount;
+			_vm->_eventsManager->delay(1);
+		}
+	}
+
+	_vm->_voy->_fadingAmount2 = 63;
+}
+
+void Screen::fadeDownICF(int steps) {
+	if (steps > 0) {
+		_vm->_eventsManager->hideCursor();
+		int stepAmount1 = _vm->_voy->_fadingAmount1 / steps;
+		int stepAmount2 = _vm->_voy->_fadingAmount2 / steps;
+
+		for (int idx = 0; idx < steps; ++idx) {
+			_vm->_voy->_fadingAmount1 -= stepAmount1;
+			_vm->_voy->_fadingAmount2 -= stepAmount2;
+			_vm->_eventsManager->delay(1);
+		}
+	}
+
+	_vm->_voy->_fadingAmount1 = 0;
+	_vm->_voy->_fadingAmount2 = 0;
+}
+
+void Screen::drawDot() {
+	for (int idx = 0; idx < 9; ++idx) {
+		uint offset = DOT_LINE_START[idx] + DOT_LINE_OFFSET[idx];
+		int xp = offset % SCREEN_WIDTH;
+		int yp = offset / SCREEN_WIDTH;
+
+		byte *pDest = (byte *)getPixels() + offset;
+		Common::fill(pDest, pDest + DOT_LINE_LENGTH[idx], 0x80);
+		addDirtyRect(Common::Rect(xp, yp, xp + DOT_LINE_LENGTH[idx], yp + 1));
+	}
+}
+
+void Screen::synchronize(Common::Serializer &s) {
+	s.syncBytes(&_VGAColors[0], PALETTE_SIZE);
+}
+
+} // End of namespace Voyeur
diff --git a/engines/voyeur/screen.h b/engines/voyeur/screen.h
new file mode 100644
index 0000000..aaf6174
--- /dev/null
+++ b/engines/voyeur/screen.h
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef VOYEUR_GRAPHICS_H
+#define VOYEUR_GRAPHICS_H
+
+#include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/serializer.h"
+#include "graphics/screen.h"
+
+namespace Voyeur {
+
+#define SCREEN_WIDTH 320
+#define SCREEN_HEIGHT 200
+
+class VoyeurEngine;
+class Screen;
+class DisplayResource;
+class PictureResource;
+class ViewPortResource;
+class ViewPortListResource;
+class FontResource;
+class FontInfoResource;
+class CMapResource;
+
+class DrawInfo {
+public:
+	int _penColor;
+	Common::Point _pos;
+public:
+	DrawInfo(int penColor, const Common::Point &pos);
+};
+
+typedef void (Screen::*ScreenMethodPtr)();
+typedef void (Screen::*ViewPortSetupPtr)(ViewPortResource *);
+typedef void (Screen::*ViewPortAddPtr)(ViewPortResource *, int idx, const Common::Rect &bounds);
+typedef void (Screen::*ViewPortRestorePtr)(ViewPortResource *);
+
+class Screen: public Graphics::Screen {
+public:
+	byte _VGAColors[PALETTE_SIZE];
+	PictureResource *_backgroundPage;
+	int _SVGAMode;
+	ViewPortListResource *_viewPortListPtr;
+	ViewPortResource *_vPort;
+	bool _saveBack;
+	Common::Rect *_clipPtr;
+	uint _planeSelect;
+	CMapResource *_backColors;
+	FontInfoResource *_fontPtr;
+	PictureResource *_fontChar;
+	DrawInfo *_drawPtr;
+	DrawInfo _defaultDrawInfo;
+private:
+	VoyeurEngine *_vm;
+
+	void restoreBack(Common::Array<Common::Rect> &rectList, int rectListCount,
+		PictureResource *srcPic, PictureResource *destPic);
+public:
+	Screen(VoyeurEngine *vm);
+	virtual ~Screen();
+
+	void sInitGraphics();
+
+	void setupMCGASaveRect(ViewPortResource *viewPort);
+	void addRectOptSaveRect(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
+	void restoreMCGASaveRect(ViewPortResource *viewPort);
+	void addRectNoSaveBack(ViewPortResource *viewPort, int idx, const Common::Rect &bounds);
+
+	void sDrawPic(DisplayResource *srcDisplay, DisplayResource *destDisplay, const Common::Point &initialOffset);
+	void fillPic(DisplayResource *display, byte onOff);
+	void sDisplayPic(PictureResource *pic);
+	void drawANumber(DisplayResource *display, int num, const Common::Point &pt);
+	void flipPage();
+	void setPalette(const byte *palette, int start, int count);
+	void setPalette128(const byte *palette, int start, int count);
+	void resetPalette();
+	void setColor(int idx, byte r, byte g, byte b);
+	void setOneColor(int idx, byte r, byte g, byte b);
+	void setColors(int start, int count, const byte *pal);
+	void screenReset();
+	void fadeDownICF1(int steps);
+	void fadeUpICF1(int steps = 0);
+	void fadeDownICF(int steps);
+	void drawDot();
+
+	/**
+	 * Synchronizes the game data
+	 */
+	void synchronize(Common::Serializer &s);
+};
+
+} // End of namespace Voyeur
+
+#endif /* VOYEUR_GRAPHICS_H */
diff --git a/engines/voyeur/voyeur.cpp b/engines/voyeur/voyeur.cpp
index cbb6846..01b76a7 100644
--- a/engines/voyeur/voyeur.cpp
+++ b/engines/voyeur/voyeur.cpp
@@ -22,7 +22,7 @@
 
 #include "voyeur/voyeur.h"
 #include "voyeur/animation.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
 #include "voyeur/staticres.h"
 #include "common/scummsys.h"
 #include "common/config-manager.h"
@@ -40,7 +40,7 @@ VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc)
 	_debugger = nullptr;
 	_eventsManager = nullptr;
 	_filesManager = nullptr;
-	_graphicsManager = nullptr;
+	_screen = nullptr;
 	_soundManager = nullptr;
 	_voy = nullptr;
 	_bVoy = NULL;
@@ -65,13 +65,6 @@ VoyeurEngine::VoyeurEngine(OSystem *syst, const VoyeurGameDescription *gameDesc)
 
 	DebugMan.addDebugChannel(kDebugScripts, "scripts", "Game scripts");
 
-	_debugger = new Debugger(this);
-	_eventsManager = new EventsManager(this);
-	_filesManager = new FilesManager(this);
-	_graphicsManager = new GraphicsManager(this);
-	_soundManager = new SoundManager(_mixer);
-	_voy = new SVoy(this);
-
 	_stampLibPtr = nullptr;
 	_controlGroupPtr = nullptr;
 	_stampData = nullptr;
@@ -88,7 +81,7 @@ VoyeurEngine::~VoyeurEngine() {
 	delete _bVoy;
 	delete _voy;
 	delete _soundManager;
-	delete _graphicsManager;
+	delete _screen;
 	delete _filesManager;
 	delete _eventsManager;
 	delete _debugger;
@@ -126,15 +119,22 @@ void VoyeurEngine::ESP_Init() {
 }
 
 void VoyeurEngine::globalInitBolt() {
+	_debugger = new Debugger(this);
+	_eventsManager = new EventsManager(this);
+	_filesManager = new FilesManager(this);
+	_screen = new Screen(this);
+	_soundManager = new SoundManager(_mixer);
+	_voy = new SVoy(this);
+
 	initBolt();
 
 	_filesManager->openBoltLib("bvoy.blt", _bVoy);
 	_bVoy->getBoltGroup(0x000);
 	_bVoy->getBoltGroup(0x100);
 
-	_graphicsManager->_fontPtr = &_defaultFontInfo;
-	_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
-	assert(_graphicsManager->_fontPtr->_curFont);
+	_screen->_fontPtr = &_defaultFontInfo;
+	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+	assert(_screen->_fontPtr->_curFont);
 
 	// Setup default flags
 	_voy->_viewBounds = nullptr;
@@ -144,13 +144,13 @@ void VoyeurEngine::globalInitBolt() {
 
 void VoyeurEngine::initBolt() {
 	vInitInterrupts();
-	_graphicsManager->sInitGraphics();
+	_screen->sInitGraphics();
 	_eventsManager->vInitColor();
 	initInput();
 }
 
 void VoyeurEngine::vInitInterrupts() {
-	_eventsManager->_intPtr._palette = &_graphicsManager->_VGAColors[0];
+	_eventsManager->_intPtr._palette = &_screen->_VGAColors[0];
 }
 
 void VoyeurEngine::initInput() {
@@ -213,8 +213,8 @@ bool VoyeurEngine::doHeadTitle() {
 }
 
 void VoyeurEngine::showConversionScreen() {
-	_graphicsManager->_backgroundPage = _bVoy->boltEntry(0x502)._picResource;
-	_graphicsManager->_vPort->setupViewPort();
+	_screen->_backgroundPage = _bVoy->boltEntry(0x502)._picResource;
+	_screen->_vPort->setupViewPort();
 	flipPageAndWait();
 
 	// Immediate palette load to show the initial screen
@@ -237,7 +237,7 @@ void VoyeurEngine::showConversionScreen() {
 
 	flipPageAndWaitForFade();
 
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 }
 
 bool VoyeurEngine::doLock() {
@@ -249,28 +249,28 @@ bool VoyeurEngine::doLock() {
 	if (_bVoy->getBoltGroup(0x700)) {
 		Common::String password = "3333";
 
-		_graphicsManager->_backgroundPage = _bVoy->getPictureResource(0x700);
-		_graphicsManager->_backColors = _bVoy->getCMapResource(0x701);
+		_screen->_backgroundPage = _bVoy->getPictureResource(0x700);
+		_screen->_backColors = _bVoy->getCMapResource(0x701);
 		PictureResource *cursorPic = _bVoy->getPictureResource(0x702);
 		_voy->_viewBounds = _bVoy->boltEntry(0x704)._rectResource;
 		Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(0x705)._rectResource->_entries;
 
 		assert(cursorPic);
-		_graphicsManager->_vPort->setupViewPort();
+		_screen->_vPort->setupViewPort();
 
-		_graphicsManager->_backColors->startFade();
-		_graphicsManager->_vPort->_parent->_flags |= DISPFLAG_8;
-		_graphicsManager->flipPage();
+		_screen->_backColors->startFade();
+		_screen->_vPort->_parent->_flags |= DISPFLAG_8;
+		_screen->flipPage();
 		_eventsManager->sWaitFlip();
 
 		while (!shouldQuit() && (_eventsManager->_fadeStatus & 1))
 			_eventsManager->delay(1);
 
 		_eventsManager->setCursorColor(127, 0);
-		_graphicsManager->setColor(1, 64, 64, 64);
-		_graphicsManager->setColor(2, 96, 96, 96);
-		_graphicsManager->setColor(3, 160, 160, 160);
-		_graphicsManager->setColor(4, 224, 224, 224);
+		_screen->setColor(1, 64, 64, 64);
+		_screen->setColor(2, 96, 96, 96);
+		_screen->setColor(3, 160, 160, 160);
+		_screen->setColor(4, 224, 224, 224);
 
 		// Set up the cursor
 		_eventsManager->setCursor(cursorPic);
@@ -278,9 +278,9 @@ bool VoyeurEngine::doLock() {
 
 		_eventsManager->_intPtr._hasPalette = true;
 
-		_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x708)._fontResource;
-		_graphicsManager->_fontPtr->_fontSaveBack = 0;
-		_graphicsManager->_fontPtr->_fontFlags = DISPFLAG_NONE;
+		_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x708)._fontResource;
+		_screen->_fontPtr->_fontSaveBack = 0;
+		_screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
 
 		Common::String dateString = "ScummVM";
  		Common::String displayString = Common::String::format("Last Play %s", dateString.c_str());
@@ -288,16 +288,16 @@ bool VoyeurEngine::doLock() {
 		bool firstLoop = true;
 		bool breakFlag = false;
 		while (!breakFlag && !shouldQuit()) {
-			_graphicsManager->_vPort->setupViewPort();
+			_screen->_vPort->setupViewPort();
 			flipPageAndWait();
 
 			// Display the last play time
-			_graphicsManager->_fontPtr->_pos = Common::Point(0, 97);
-			_graphicsManager->_fontPtr->_justify = ALIGN_CENTER;
-			_graphicsManager->_fontPtr->_justifyWidth = 384;
-			_graphicsManager->_fontPtr->_justifyHeight = 97;
+			_screen->_fontPtr->_pos = Common::Point(0, 97);
+			_screen->_fontPtr->_justify = ALIGN_CENTER;
+			_screen->_fontPtr->_justifyWidth = 384;
+			_screen->_fontPtr->_justifyHeight = 97;
 
-			_graphicsManager->_vPort->drawText(displayString);
+			_screen->_vPort->drawText(displayString);
 			flipPageAndWait();
 
 			if (firstLoop) {
@@ -356,7 +356,7 @@ bool VoyeurEngine::doLock() {
 			} else if (key == 11) {
 				// New code
 				if ((password.empty() && displayString.empty()) || (password != displayString)) {
-					_graphicsManager->_vPort->setupViewPort();
+					_screen->_vPort->setupViewPort();
 					password = displayString;
 					displayString = "";
 					continue;
@@ -373,9 +373,9 @@ bool VoyeurEngine::doLock() {
 			_soundManager->playVOCMap(wrongVoc, wrongVocSize);
 		}
 
-		_graphicsManager->fillPic(_graphicsManager->_vPort, 0);
+		_screen->fillPic(_screen->_vPort, 0);
 		flipPageAndWait();
-		_graphicsManager->resetPalette();
+		_screen->resetPalette();
 
 		_voy->_viewBounds = nullptr;
 		_bVoy->freeBoltGroup(0x700);
@@ -393,9 +393,9 @@ void VoyeurEngine::showTitleScreen() {
 	if (!_bVoy->getBoltGroup(0x500))
 		return;
 
-	_graphicsManager->_backgroundPage = _bVoy->getPictureResource(0x500);
+	_screen->_backgroundPage = _bVoy->getPictureResource(0x500);
 
-	_graphicsManager->_vPort->setupViewPort();
+	_screen->_vPort->setupViewPort();
 	flipPageAndWait();
 
 	// Immediate palette load to show the initial screen
@@ -422,18 +422,18 @@ void VoyeurEngine::showTitleScreen() {
 		return;
 	}
 
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 	_eventsManager->delayClick(200);
 
 	// Voyeur title
 	playRL2Video("a1100100.rl2");
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 
 	_bVoy->freeBoltGroup(0x500);
 }
 
 void VoyeurEngine::doOpening() {
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 
 	if (!_bVoy->getBoltGroup(0x200))
 		return;
@@ -459,10 +459,10 @@ void VoyeurEngine::doOpening() {
 	_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
 
 	for (int i = 0; i < 256; ++i)
-		_graphicsManager->setColor(i, 8, 8, 8);
+		_screen->setColor(i, 8, 8, 8);
 
 	_eventsManager->_intPtr._hasPalette = true;
-	_graphicsManager->_vPort->setupViewPort();
+	_screen->_vPort->setupViewPort();
 	flipPageAndWait();
 
 	RL2Decoder decoder;
@@ -472,14 +472,12 @@ void VoyeurEngine::doOpening() {
 	while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) {
 		if (decoder.hasDirtyPalette()) {
 			const byte *palette = decoder.getPalette();
-			_graphicsManager->setPalette(palette, 0, 256);
+			_screen->setPalette(palette, 0, 256);
 		}
 
 		if (decoder.needsUpdate()) {
 			const Graphics::Surface *frame = decoder.decodeNextFrame();
-
-			Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
-				(byte *)_graphicsManager->_screenSurface.getPixels());
+			_screen->blitFrom(*frame);
 
 			if (decoder.getCurFrame() >= (int32)READ_LE_UINT32(frameTable + frameIndex * 4)) {
 				if (creditShow) {
@@ -499,7 +497,7 @@ void VoyeurEngine::doOpening() {
 			}
 
 			if (textPic) {
-				_graphicsManager->sDrawPic(textPic, _graphicsManager->_vPort, textPos);
+				_screen->sDrawPic(textPic, _screen->_vPort, textPos);
 			}
 
 			flipPageAndWait();
@@ -527,14 +525,12 @@ void VoyeurEngine::playRL2Video(const Common::String &filename) {
 	while (!shouldQuit() && !decoder.endOfVideo() && !_eventsManager->_mouseClicked) {
 		if (decoder.hasDirtyPalette()) {
 			const byte *palette = decoder.getPalette();
-			_graphicsManager->setPalette(palette, 0, 256);
+			_screen->setPalette(palette, 0, 256);
 		}
 
 		if (decoder.needsUpdate()) {
 			const Graphics::Surface *frame = decoder.decodeNextFrame();
-
-			Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
-				(byte *)_graphicsManager->_screenSurface.getPixels());
+			_screen->blitFrom(*frame);
 		}
 
 		_eventsManager->getMouseInfo();
@@ -573,17 +569,16 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
 			(decoder.getCurFrame() < endFrame)) {
 		if (decoder.needsUpdate()) {
 			const Graphics::Surface *frame = decoder.decodeNextFrame();
+			_screen->blitFrom(*frame);
 
-			Common::copy((const byte *)frame->getPixels(), (const byte *)frame->getPixels() + 320 * 200,
-				(byte *)_graphicsManager->_screenSurface.getPixels());
 			if (_voy->_eventFlags & EVTFLAG_RECORDING)
-				_graphicsManager->drawDot();
+				_screen->drawDot();
 		}
 
 		if (decoder.hasDirtyPalette()) {
 			const byte *palette = decoder.getPalette();
-			_graphicsManager->setPalette(palette, 0, decoder.getPaletteCount());
-			_graphicsManager->setOneColor(128, 220, 20, 20);
+			_screen->setPalette(palette, 0, decoder.getPaletteCount());
+			_screen->setOneColor(128, 220, 20, 20);
 		}
 
 		_eventsManager->getMouseInfo();
@@ -591,13 +586,13 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
 	}
 
 	// RL2 finished
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 	_voy->_eventFlags &= ~EVTFLAG_RECORDING;
 
 	if (_voy->_eventFlags & EVTFLAG_8) {
 		assert(pic);
-		byte *imgData = _graphicsManager->_vPort->_currentPic->_imgData;
-		_graphicsManager->_vPort->_currentPic->_imgData = pic->_imgData;
+		byte *imgData = _screen->_vPort->_currentPic->_imgData;
+		_screen->_vPort->_currentPic->_imgData = pic->_imgData;
 		pic->_imgData = imgData;
 		_voy->_eventFlags &= ~EVTFLAG_8;
 	}
@@ -608,13 +603,13 @@ void VoyeurEngine::playAVideoDuration(int videoId, int duration) {
 
 void VoyeurEngine::playAudio(int audioId) {
 	_bVoy->getBoltGroup(0x7F00);
-	_graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 +
+	_screen->_backgroundPage = _bVoy->boltEntry(0x7F00 +
 		BLIND_TABLE[audioId] * 2)._picResource;
-	_graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 +
+	_screen->_backColors = _bVoy->boltEntry(0x7F01 +
 		BLIND_TABLE[audioId] * 2)._cMapResource;
 
-	_graphicsManager->_vPort->setupViewPort();
-	_graphicsManager->_backColors->startFade();
+	_screen->_vPort->setupViewPort();
+	_screen->_backColors->startFade();
 	flipPageAndWaitForFade();
 
 	_voy->_eventFlags &= ~EVTFLAG_TIME_DISABLED;
@@ -633,26 +628,26 @@ void VoyeurEngine::playAudio(int audioId) {
 	_soundManager->stopVOCPlay();
 
 	_bVoy->freeBoltGroup(0x7F00);
-	_graphicsManager->_vPort->setupViewPort(NULL);
+	_screen->_vPort->setupViewPort(NULL);
 
 	_voy->_eventFlags &= ~EVTFLAG_RECORDING;
 	_voy->_playStampMode = 129;
 }
 
 void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::String &location) {
-	_graphicsManager->setColor(128, 16, 16, 16);
-	_graphicsManager->setColor(224, 220, 220, 220);
+	_screen->setColor(128, 16, 16, 16);
+	_screen->setColor(224, 220, 220, 220);
 	_eventsManager->_intPtr._hasPalette = true;
 
-	_graphicsManager->_vPort->setupViewPort(NULL);
-	_graphicsManager->_vPort->fillPic(0x80);
-	_graphicsManager->flipPage();
+	_screen->_vPort->setupViewPort(NULL);
+	_screen->_vPort->fillPic(0x80);
+	_screen->flipPage();
 	_eventsManager->sWaitFlip();
 
 	flipPageAndWait();
-	_graphicsManager->_vPort->fillPic(0x80);
+	_screen->_vPort->fillPic(0x80);
 
-	FontInfoResource &fi = *_graphicsManager->_fontPtr;
+	FontInfoResource &fi = *_screen->_fontPtr;
 	fi._curFont = _bVoy->boltEntry(257)._fontResource;
 	fi._foreColor = 224;
 	fi._fontSaveBack = 0;
@@ -661,7 +656,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St
 	fi._justifyWidth = 384;
 	fi._justifyHeight = 120;
 
-	_graphicsManager->_vPort->drawText(time);
+	_screen->_vPort->drawText(time);
 
 	if (!location.empty()) {
 		fi._pos = Common::Point(0, 138);
@@ -669,7 +664,7 @@ void VoyeurEngine::doTransitionCard(const Common::String &time, const Common::St
 		fi._justifyWidth = 384;
 		fi._justifyHeight = 140;
 
-		_graphicsManager->_vPort->drawText(location);
+		_screen->_vPort->drawText(location);
 	}
 
 	flipPageAndWait();
@@ -680,8 +675,8 @@ void VoyeurEngine::saveLastInplay() {
 }
 
 void VoyeurEngine::flipPageAndWait() {
-	_graphicsManager->_vPort->_flags |= DISPFLAG_8;
-	_graphicsManager->flipPage();
+	_screen->_vPort->_flags |= DISPFLAG_8;
+	_screen->flipPage();
 	_eventsManager->sWaitFlip();
 }
 
@@ -702,7 +697,7 @@ void VoyeurEngine::showEndingNews() {
 	PictureResource *pic = _bVoy->boltEntry(_playStampGroupId)._picResource;
 	CMapResource *pal = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
 
-	_graphicsManager->_vPort->setupViewPort(pic);
+	_screen->_vPort->setupViewPort(pic);
 	pal->startFade();
 	flipPageAndWaitForFade();
 
@@ -717,7 +712,7 @@ void VoyeurEngine::showEndingNews() {
 			pal = _bVoy->boltEntry(_playStampGroupId + idx * 2 + 1)._cMapResource;
 		}
 
-		_graphicsManager->_vPort->setupViewPort(pic);
+		_screen->_vPort->setupViewPort(pic);
 		pal->startFade();
 		flipPageAndWaitForFade();
 
@@ -852,7 +847,7 @@ void VoyeurEngine::synchronize(Common::Serializer &s) {
 
 	// Sub-systems
 	_voy->synchronize(s);
-	_graphicsManager->synchronize(s);
+	_screen->synchronize(s);
 	_mainThread->synchronize(s);
 	_controlPtr->_state->synchronize(s);
 }
@@ -906,8 +901,8 @@ void VoyeurSavegameHeader::write(Common::OutSaveFile *f, VoyeurEngine *vm, const
 
 	// Create a thumbnail and save it
 	Graphics::Surface *thumb = new Graphics::Surface();
-	::createThumbnail(thumb, (byte *)vm->_graphicsManager->_screenSurface.getPixels(),
-		SCREEN_WIDTH, SCREEN_HEIGHT, vm->_graphicsManager->_VGAColors);
+	::createThumbnail(thumb, (const byte *)vm->_screen->getPixels(),
+		SCREEN_WIDTH, SCREEN_HEIGHT, vm->_screen->_VGAColors);
 	Graphics::saveThumbnail(*f, *thumb);
 	thumb->free();
 	delete thumb;
diff --git a/engines/voyeur/voyeur.h b/engines/voyeur/voyeur.h
index e0bb734..9cda85f 100644
--- a/engines/voyeur/voyeur.h
+++ b/engines/voyeur/voyeur.h
@@ -27,7 +27,7 @@
 #include "voyeur/data.h"
 #include "voyeur/events.h"
 #include "voyeur/files.h"
-#include "voyeur/graphics.h"
+#include "voyeur/screen.h"
 #include "voyeur/sound.h"
 #include "common/scummsys.h"
 #include "common/system.h"
@@ -164,7 +164,7 @@ public:
 	Debugger *_debugger;
 	EventsManager *_eventsManager;
 	FilesManager *_filesManager;
-	GraphicsManager *_graphicsManager;
+	Screen *_screen;
 	SoundManager *_soundManager;
 	SVoy *_voy;
 
diff --git a/engines/voyeur/voyeur_game.cpp b/engines/voyeur/voyeur_game.cpp
index 13ef318..e959195 100644
--- a/engines/voyeur/voyeur_game.cpp
+++ b/engines/voyeur/voyeur_game.cpp
@@ -149,8 +149,8 @@ void VoyeurEngine::playStamp() {
 		case 130: {
 			// user selected to send the tape
 			if (_bVoy->getBoltGroup(_playStampGroupId)) {
-				_graphicsManager->_backgroundPage = _bVoy->boltEntry(_playStampGroupId)._picResource;
-				_graphicsManager->_backColors = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
+				_screen->_backgroundPage = _bVoy->boltEntry(_playStampGroupId)._picResource;
+				_screen->_backColors = _bVoy->boltEntry(_playStampGroupId + 1)._cMapResource;
 
 				buttonId = getChooseButton();
 				if (_eventsManager->_rightClick)
@@ -158,7 +158,7 @@ void VoyeurEngine::playStamp() {
 					buttonId = 4;
 
 				_bVoy->freeBoltGroup(_playStampGroupId);
-				_graphicsManager->screenReset();
+				_screen->screenReset();
 				_playStampGroupId = -1;
 				flag = true;
 
@@ -232,8 +232,8 @@ void VoyeurEngine::closeStamp() {
 }
 
 void VoyeurEngine::doTailTitle() {
-	_graphicsManager->_vPort->setupViewPort(NULL);
-	_graphicsManager->screenReset();
+	_screen->_vPort->setupViewPort(NULL);
+	_screen->screenReset();
 
 	if (_bVoy->getBoltGroup(0x600)) {
 		RL2Decoder decoder;
@@ -245,12 +245,12 @@ void VoyeurEngine::doTailTitle() {
 			doClosingCredits();
 
 			if (!shouldQuit() && !_eventsManager->_mouseClicked) {
-				_graphicsManager->screenReset();
+				_screen->screenReset();
 
 				PictureResource *pic = _bVoy->boltEntry(0x602)._picResource;
 				CMapResource *pal = _bVoy->boltEntry(0x603)._cMapResource;
 
-				_graphicsManager->_vPort->setupViewPort(pic);
+				_screen->_vPort->setupViewPort(pic);
 				pal->startFade();
 				flipPageAndWaitForFade();
 				_eventsManager->delayClick(300);
@@ -258,7 +258,7 @@ void VoyeurEngine::doTailTitle() {
 				pic = _bVoy->boltEntry(0x604)._picResource;
 				pal = _bVoy->boltEntry(0x605)._cMapResource;
 
-				_graphicsManager->_vPort->setupViewPort(pic);
+				_screen->_vPort->setupViewPort(pic);
 				pal->startFade();
 				flipPageAndWaitForFade();
 				_eventsManager->delayClick(120);
@@ -283,26 +283,26 @@ void VoyeurEngine::doClosingCredits() {
 	const char *msg = (const char *)_bVoy->memberAddr(0x404);
 	const byte *creditList = (const byte *)_bVoy->memberAddr(0x405);
 
-	_graphicsManager->_vPort->setupViewPort(NULL);
-	_graphicsManager->setColor(1, 180, 180, 180);
-	_graphicsManager->setColor(2, 200, 200, 200);
+	_screen->_vPort->setupViewPort(NULL);
+	_screen->setColor(1, 180, 180, 180);
+	_screen->setColor(2, 200, 200, 200);
 	_eventsManager->_intPtr._hasPalette = true;
 
-	_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x402)._fontResource;
-	_graphicsManager->_fontPtr->_foreColor = 2;
-	_graphicsManager->_fontPtr->_backColor = 2;
-	_graphicsManager->_fontPtr->_fontSaveBack = false;
-	_graphicsManager->_fontPtr->_fontFlags = DISPFLAG_NONE;
+	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x402)._fontResource;
+	_screen->_fontPtr->_foreColor = 2;
+	_screen->_fontPtr->_backColor = 2;
+	_screen->_fontPtr->_fontSaveBack = false;
+	_screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
 
 	_soundManager->startVOCPlay(152);
-	FontInfoResource &fi = *_graphicsManager->_fontPtr;
+	FontInfoResource &fi = *_screen->_fontPtr;
 
 	for (int idx = 0; idx < 78; ++idx) {
 		const byte *entry = creditList + idx * 6;
 		int flags = READ_LE_UINT16(entry + 4);
 
 		if (flags & 0x10)
-			_graphicsManager->_vPort->fillPic(0);
+			_screen->_vPort->fillPic(0);
 
 		if (flags & 1) {
 			fi._foreColor = 1;
@@ -312,7 +312,7 @@ void VoyeurEngine::doClosingCredits() {
 			fi._justifyHeight = 240;
 			fi._pos = Common::Point(0, READ_LE_UINT16(entry));
 
-			_graphicsManager->_vPort->drawText(msg);
+			_screen->_vPort->drawText(msg);
 			msg += strlen(msg) + 1;
 		}
 
@@ -324,7 +324,7 @@ void VoyeurEngine::doClosingCredits() {
 			fi._justifyHeight = 240;
 			fi._pos = Common::Point(0, READ_LE_UINT16(entry));
 
-			_graphicsManager->_vPort->drawText(msg);
+			_screen->_vPort->drawText(msg);
 			msg += strlen(msg) + 1;
 		}
 
@@ -336,7 +336,7 @@ void VoyeurEngine::doClosingCredits() {
 			fi._justifyHeight = 240;
 			fi._pos = Common::Point(38, READ_LE_UINT16(entry));
 
-			_graphicsManager->_vPort->drawText(msg);
+			_screen->_vPort->drawText(msg);
 			msg += strlen(msg) + 1;
 
 			fi._foreColor = 2;
@@ -345,7 +345,7 @@ void VoyeurEngine::doClosingCredits() {
 			fi._justifyHeight = 240;
 			fi._pos = Common::Point(198, READ_LE_UINT16(entry));
 
-			_graphicsManager->_vPort->drawText(msg);
+			_screen->_vPort->drawText(msg);
 			msg += strlen(msg) + 1;
 		}
 
@@ -357,7 +357,7 @@ void VoyeurEngine::doClosingCredits() {
 			fi._justifyHeight = 240;
 			fi._pos = Common::Point(0, READ_LE_UINT16(entry));
 
-			_graphicsManager->_vPort->drawText(msg);
+			_screen->_vPort->drawText(msg);
 			msg += strlen(msg) + 1;
 
 			fi._foreColor = 2;
@@ -367,7 +367,7 @@ void VoyeurEngine::doClosingCredits() {
 			fi._justifyHeight = 240;
 			fi._pos = Common::Point(0, READ_LE_UINT16(entry) + 13);
 
-			_graphicsManager->_vPort->drawText(msg);
+			_screen->_vPort->drawText(msg);
 			msg += strlen(msg) + 1;
 		}
 
@@ -381,19 +381,19 @@ void VoyeurEngine::doClosingCredits() {
 	}
 
 	_soundManager->stopVOCPlay();
-	_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
 	_bVoy->freeBoltGroup(0x400);
 }
 
 void VoyeurEngine::doPiracy() {
-	_graphicsManager->screenReset();
-	_graphicsManager->setColor(1, 0, 0, 0);
-	_graphicsManager->setColor(2, 255, 255, 255);
+	_screen->screenReset();
+	_screen->setColor(1, 0, 0, 0);
+	_screen->setColor(2, 255, 255, 255);
 	_eventsManager->_intPtr._hasPalette = true;
-	_graphicsManager->_vPort->setupViewPort(NULL);
-	_graphicsManager->_vPort->fillPic(1);
+	_screen->_vPort->setupViewPort(NULL);
+	_screen->_vPort->fillPic(1);
 
-	FontInfoResource &fi = *_graphicsManager->_fontPtr;
+	FontInfoResource &fi = *_screen->_fontPtr;
 	fi._curFont = _bVoy->boltEntry(0x101)._fontResource;
 	fi._foreColor = 2;
 	fi._backColor = 2;
@@ -406,7 +406,7 @@ void VoyeurEngine::doPiracy() {
 	// Loop through the piracy message array to draw each line
 	for (int idx = 0, yp = 33; idx < 10; ++idx) {
 		fi._pos = Common::Point(0, yp);
-		_graphicsManager->_vPort->drawText(PIRACY_MESSAGE[idx]);
+		_screen->_vPort->drawText(PIRACY_MESSAGE[idx]);
 
 		yp += fi._curFont->_fontHeight + 4;
 	}
@@ -439,27 +439,27 @@ void VoyeurEngine::reviewTape() {
 		_voy->_viewBounds = _bVoy->boltEntry(0x907)._rectResource;
 		Common::Array<RectEntry> &hotspots = _bVoy->boltEntry(0x906)._rectResource->_entries;
 
-		_graphicsManager->_backColors = _bVoy->boltEntry(0x902)._cMapResource;
-		_graphicsManager->_backgroundPage = _bVoy->boltEntry(0x901)._picResource;
-		_graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
-		_graphicsManager->_backColors->startFade();
+		_screen->_backColors = _bVoy->boltEntry(0x902)._cMapResource;
+		_screen->_backgroundPage = _bVoy->boltEntry(0x901)._picResource;
+		_screen->_vPort->setupViewPort(_screen->_backgroundPage);
+		_screen->_backColors->startFade();
 
 		flipPageAndWaitForFade();
 
-		_graphicsManager->setColor(1, 32, 32, 32);
-		_graphicsManager->setColor(2, 96, 96, 96);
-		_graphicsManager->setColor(3, 160, 160, 160);
-		_graphicsManager->setColor(4, 224, 224, 224);
-		_graphicsManager->setColor(9, 24, 64, 24);
-		_graphicsManager->setColor(10, 64, 132, 64);
-		_graphicsManager->setColor(11, 100, 192, 100);
-		_graphicsManager->setColor(12, 120, 248, 120);
+		_screen->setColor(1, 32, 32, 32);
+		_screen->setColor(2, 96, 96, 96);
+		_screen->setColor(3, 160, 160, 160);
+		_screen->setColor(4, 224, 224, 224);
+		_screen->setColor(9, 24, 64, 24);
+		_screen->setColor(10, 64, 132, 64);
+		_screen->setColor(11, 100, 192, 100);
+		_screen->setColor(12, 120, 248, 120);
 		_eventsManager->setCursorColor(128, 1);
 
 		_eventsManager->_intPtr._hasPalette = true;
-		_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x909)._fontResource;
-		_graphicsManager->_fontPtr->_fontSaveBack = false;
-		_graphicsManager->_fontPtr->_fontFlags = DISPFLAG_NONE;
+		_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x909)._fontResource;
+		_screen->_fontPtr->_fontSaveBack = false;
+		_screen->_fontPtr->_fontFlags = DISPFLAG_NONE;
 
 		_eventsManager->getMouseInfo();
 		if (newX == -1) {
@@ -481,37 +481,37 @@ void VoyeurEngine::reviewTape() {
 				needRedraw = false;
 				flipPageAndWait();
 
-				_graphicsManager->_drawPtr->_penColor = 0;
-				_graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
-				_graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
+				_screen->_drawPtr->_penColor = 0;
+				_screen->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
+				_screen->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
 
 				int yp = 45;
 				int eventNum = eventStart;
 				for (int lineNum = 0; lineNum < 8 && eventNum < _voy->_eventCount; ++lineNum, ++eventNum) {
-					_graphicsManager->_fontPtr->_picFlags = DISPFLAG_NONE;
-					_graphicsManager->_fontPtr->_picSelect = 0xff;
-					_graphicsManager->_fontPtr->_picPick = 7;
-					_graphicsManager->_fontPtr->_picOnOff = (lineNum == eventLine) ? 8 : 0;
-					_graphicsManager->_fontPtr->_pos = Common::Point(68, yp);
-					_graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
-					_graphicsManager->_fontPtr->_justifyWidth = 0;
-					_graphicsManager->_fontPtr->_justifyHeight = 0;
+					_screen->_fontPtr->_picFlags = DISPFLAG_NONE;
+					_screen->_fontPtr->_picSelect = 0xff;
+					_screen->_fontPtr->_picPick = 7;
+					_screen->_fontPtr->_picOnOff = (lineNum == eventLine) ? 8 : 0;
+					_screen->_fontPtr->_pos = Common::Point(68, yp);
+					_screen->_fontPtr->_justify = ALIGN_LEFT;
+					_screen->_fontPtr->_justifyWidth = 0;
+					_screen->_fontPtr->_justifyHeight = 0;
 
 					Common::String msg = _eventsManager->getEvidString(eventNum);
-					_graphicsManager->_backgroundPage->drawText(msg);
+					_screen->_backgroundPage->drawText(msg);
 
 					yp += 15;
 				}
 
-				_graphicsManager->_vPort->addSaveRect(
-					_graphicsManager->_vPort->_lastPage, tempRect);
+				_screen->_vPort->addSaveRect(
+					_screen->_vPort->_lastPage, tempRect);
 				flipPageAndWait();
 
-				_graphicsManager->_vPort->addSaveRect(
-					_graphicsManager->_vPort->_lastPage, tempRect);
+				_screen->_vPort->addSaveRect(
+					_screen->_vPort->_lastPage, tempRect);
 			}
 
-			_graphicsManager->sDrawPic(cursor, _graphicsManager->_vPort,
+			_screen->sDrawPic(cursor, _screen->_vPort,
 				_eventsManager->getMousePos());
 			flipPageAndWait();
 
@@ -543,34 +543,34 @@ void VoyeurEngine::reviewTape() {
 
 					flipPageAndWait();
 
-					_graphicsManager->_drawPtr->_penColor = 0;
-					_graphicsManager->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
-					_graphicsManager->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
+					_screen->_drawPtr->_penColor = 0;
+					_screen->_drawPtr->_pos = Common::Point(tempRect.left, tempRect.top);
+					_screen->_backgroundPage->sFillBox(tempRect.width(), tempRect.height());
 
 					int yp = 45;
 					int eventNum = eventStart;
 					for (int idx = 0; idx < 8 && eventNum < _voy->_eventCount; ++idx, ++eventNum) {
-						_graphicsManager->_fontPtr->_picFlags = DISPFLAG_NONE;
-						_graphicsManager->_fontPtr->_picSelect = 0xff;
-						_graphicsManager->_fontPtr->_picPick = 7;
-						_graphicsManager->_fontPtr->_picOnOff = (idx == eventLine) ? 8 : 0;
-						_graphicsManager->_fontPtr->_pos = Common::Point(68, yp);
-						_graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
-						_graphicsManager->_fontPtr->_justifyWidth = 0;
-						_graphicsManager->_fontPtr->_justifyHeight = 0;
+						_screen->_fontPtr->_picFlags = DISPFLAG_NONE;
+						_screen->_fontPtr->_picSelect = 0xff;
+						_screen->_fontPtr->_picPick = 7;
+						_screen->_fontPtr->_picOnOff = (idx == eventLine) ? 8 : 0;
+						_screen->_fontPtr->_pos = Common::Point(68, yp);
+						_screen->_fontPtr->_justify = ALIGN_LEFT;
+						_screen->_fontPtr->_justifyWidth = 0;
+						_screen->_fontPtr->_justifyHeight = 0;
 
 						Common::String msg = _eventsManager->getEvidString(eventNum);
-						_graphicsManager->_backgroundPage->drawText(msg);
+						_screen->_backgroundPage->drawText(msg);
 
 						yp += 15;
 					}
 
-					_graphicsManager->_vPort->addSaveRect(
-						_graphicsManager->_vPort->_lastPage, tempRect);
+					_screen->_vPort->addSaveRect(
+						_screen->_vPort->_lastPage, tempRect);
 					flipPageAndWait();
 
-					_graphicsManager->_vPort->addSaveRect(
-						_graphicsManager->_vPort->_lastPage, tempRect);
+					_screen->_vPort->addSaveRect(
+						_screen->_vPort->_lastPage, tempRect);
 					flipPageAndWait();
 
 					_eventsManager->getMouseInfo();
@@ -650,7 +650,7 @@ void VoyeurEngine::reviewTape() {
 		newY = _eventsManager->getMousePos().y;
 		_voy->_fadingType = 0;
 		_voy->_viewBounds = nullptr;
-		_graphicsManager->_vPort->setupViewPort(NULL);
+		_screen->_vPort->setupViewPort(NULL);
 
 		if (_currentVocId != -1) {
 			_voy->_vocSecondsOffset = _voy->_RTVNum - _voy->_musicStartTime;
@@ -673,13 +673,13 @@ void VoyeurEngine::reviewTape() {
 			_voy->_vocSecondsOffset = e._computerOn;
 
 			_bVoy->getBoltGroup(0x7F00);
-			_graphicsManager->_backgroundPage = _bVoy->boltEntry(0x7F00 +
+			_screen->_backgroundPage = _bVoy->boltEntry(0x7F00 +
 				BLIND_TABLE[_audioVideoId])._picResource;
-			_graphicsManager->_backColors = _bVoy->boltEntry(0x7F01 +
+			_screen->_backColors = _bVoy->boltEntry(0x7F01 +
 				BLIND_TABLE[_audioVideoId])._cMapResource;
 
-			_graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
-			_graphicsManager->_backColors->startFade();
+			_screen->_vPort->setupViewPort(_screen->_backgroundPage);
+			_screen->_backColors->startFade();
 			flipPageAndWaitForFade();
 
 			_eventsManager->_intPtr._flashStep = 1;
@@ -725,16 +725,16 @@ void VoyeurEngine::reviewTape() {
 		}
 	}
 
-	_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
 
-	_graphicsManager->_vPort->fillPic(0);
+	_screen->_vPort->fillPic(0);
 	flipPageAndWait();
 	_bVoy->freeBoltGroup(0x900);
 }
 
 void VoyeurEngine::doGossip() {
-	_graphicsManager->resetPalette();
-	_graphicsManager->screenReset();
+	_screen->resetPalette();
+	_screen->screenReset();
 
 	if (!_bVoy->getBoltGroup(0x300))
 		return;
@@ -752,7 +752,7 @@ void VoyeurEngine::doGossip() {
 	// Transfer initial background to video decoder
 	PictureResource videoFrame(decoder.getRL2VideoTrack()->getBackSurface());
 	bgPic->_bounds.moveTo(0, 0);
-	_graphicsManager->sDrawPic(bgPic, &videoFrame, Common::Point(0, 0));
+	_screen->sDrawPic(bgPic, &videoFrame, Common::Point(0, 0));
 
 	byte *frameNumsP = _bVoy->memberAddr(0x309);
 	byte *posP = _bVoy->boltEntry(0x30A)._data;
@@ -762,8 +762,8 @@ void VoyeurEngine::doGossip() {
 	decoder.close();
 
 	// Reset the palette and clear the screen
-	_graphicsManager->resetPalette();
-	_graphicsManager->screenReset();
+	_screen->resetPalette();
+	_screen->screenReset();
 
 	// Play interview video
 	RL2Decoder decoder2;
@@ -775,7 +775,7 @@ void VoyeurEngine::doGossip() {
 	decoder2.close();
 
 	_bVoy->freeBoltGroup(0x300);
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 }
 
 void VoyeurEngine::doTapePlaying() {
@@ -783,14 +783,14 @@ void VoyeurEngine::doTapePlaying() {
 		return;
 
 	_eventsManager->getMouseInfo();
-	_graphicsManager->_backColors = _bVoy->boltEntry(0xA01)._cMapResource;
-	_graphicsManager->_backgroundPage = _bVoy->boltEntry(0xA00)._picResource;
+	_screen->_backColors = _bVoy->boltEntry(0xA01)._cMapResource;
+	_screen->_backgroundPage = _bVoy->boltEntry(0xA00)._picResource;
 	PictureResource *pic = _bVoy->boltEntry(0xA02)._picResource;
 	VInitCycleResource *cycle = _bVoy->boltEntry(0xA05)._vInitCycleResource;
 
-	_graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
-	_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(57, 30));
-	_graphicsManager->_backColors->startFade();
+	_screen->_vPort->setupViewPort(_screen->_backgroundPage);
+	_screen->sDrawPic(pic, _screen->_vPort, Common::Point(57, 30));
+	_screen->_backColors->startFade();
 	flipPageAndWaitForFade();
 
 	cycle->vStartCycle();
@@ -932,9 +932,9 @@ int VoyeurEngine::getChooseButton()  {
 		+ 6)._rectResource->_entries;
 	int selectedIndex = -1;
 
-	_graphicsManager->_vPort->setupViewPort(_graphicsManager->_backgroundPage);
-	_graphicsManager->_backColors->_steps = 0;
-	_graphicsManager->_backColors->startFade();
+	_screen->_vPort->setupViewPort(_screen->_backgroundPage);
+	_screen->_backColors->_steps = 0;
+	_screen->_backColors->startFade();
 	flipPageAndWait();
 
 	_voy->_viewBounds = _bVoy->boltEntry(_playStampGroupId + 7)._rectResource;
@@ -955,7 +955,7 @@ int VoyeurEngine::getChooseButton()  {
 						selectedIndex = idx;
 						if (selectedIndex != prevIndex) {
 							PictureResource *btnPic = _bVoy->boltEntry(_playStampGroupId + 8 + idx)._picResource;
-							_graphicsManager->sDrawPic(btnPic, _graphicsManager->_vPort,
+							_screen->sDrawPic(btnPic, _screen->_vPort,
 								Common::Point(106, 200));
 
 							cursorPic = _bVoy->boltEntry(_playStampGroupId + 4)._picResource;
@@ -967,11 +967,11 @@ int VoyeurEngine::getChooseButton()  {
 			if (selectedIndex == -1) {
 				cursorPic = _bVoy->boltEntry(_playStampGroupId + 2)._picResource;
 				PictureResource *btnPic = _bVoy->boltEntry(_playStampGroupId + 12)._picResource;
-				_graphicsManager->sDrawPic(btnPic, _graphicsManager->_vPort,
+				_screen->sDrawPic(btnPic, _screen->_vPort,
 					Common::Point(106, 200));
 			}
 
-			_graphicsManager->sDrawPic(cursorPic, _graphicsManager->_vPort,
+			_screen->sDrawPic(cursorPic, _screen->_vPort,
 				Common::Point(pt.x + 13, pt.y - 12));
 
 			flipPageAndWait();
@@ -982,9 +982,9 @@ int VoyeurEngine::getChooseButton()  {
 }
 
 void VoyeurEngine::makeViewFinder() {
-	_graphicsManager->_backgroundPage = _bVoy->boltEntry(0x103)._picResource;
-	_graphicsManager->sDrawPic(_graphicsManager->_backgroundPage,
-		_graphicsManager->_vPort, Common::Point(0, 0));
+	_screen->_backgroundPage = _bVoy->boltEntry(0x103)._picResource;
+	_screen->sDrawPic(_screen->_backgroundPage,
+		_screen->_vPort, Common::Point(0, 0));
 	CMapResource *pal = _bVoy->boltEntry(0x104)._cMapResource;
 
 	int palOffset = 0;
@@ -1016,22 +1016,22 @@ void VoyeurEngine::makeViewFinder() {
 		break;
 	}
 
-	_graphicsManager->_vPort->drawIfaceTime();
+	_screen->_vPort->drawIfaceTime();
 	doTimeBar();
 	pal->startFade();
 
 	flipPageAndWaitForFade();
 
-	_graphicsManager->setColor(241, 105, 105, 105);
-	_graphicsManager->setColor(242, 105, 105, 105);
-	_graphicsManager->setColor(243, 105, 105, 105);
-	_graphicsManager->setColor(palOffset + 241, 219, 235, 235);
+	_screen->setColor(241, 105, 105, 105);
+	_screen->setColor(242, 105, 105, 105);
+	_screen->setColor(243, 105, 105, 105);
+	_screen->setColor(palOffset + 241, 219, 235, 235);
 
 	_eventsManager->_intPtr._hasPalette = true;
 }
 
 void VoyeurEngine::makeViewFinderP() {
-	_graphicsManager->screenReset();
+	_screen->screenReset();
 }
 
 void VoyeurEngine::initIFace() {
@@ -1077,7 +1077,7 @@ void VoyeurEngine::initIFace() {
 
 void VoyeurEngine::doScroll(const Common::Point &pt) {
 	Common::Rect clipRect(72, 47, 72 + 240, 47 + 148);
-	_graphicsManager->_vPort->setupViewPort(NULL, &clipRect);
+	_screen->_vPort->setupViewPort(NULL, &clipRect);
 
 	int base = 0;
 	switch (_voy->_transitionId) {
@@ -1101,18 +1101,18 @@ void VoyeurEngine::doScroll(const Common::Point &pt) {
 
 	if (base) {
 		PictureResource *pic = _bVoy->boltEntry(base + 3)._picResource;
- 		_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 104));
+ 		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 104));
 		pic = _bVoy->boltEntry(base + 4)._picResource;
-		_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 44));
+		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y - 44));
 		pic = _bVoy->boltEntry(base + 5)._picResource;
-		_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 16));
+		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 16));
 		pic = _bVoy->boltEntry(base + 6)._picResource;
-		_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 76));
+		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 76));
 		pic = _bVoy->boltEntry(base + 7)._picResource;
-		_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 136));
+		_screen->sDrawPic(pic, _screen->_vPort, Common::Point(784 - pt.x - 712, 150 - pt.y + 136));
 	}
 
-	_graphicsManager->_vPort->setupViewPort(NULL);
+	_screen->_vPort->setupViewPort(NULL);
 }
 
 void VoyeurEngine::checkTransition() {
@@ -1124,7 +1124,7 @@ void VoyeurEngine::checkTransition() {
 
 		// Only proceed if a valid day string was returned
 		if (!day.empty()) {
-			_graphicsManager->fadeDownICF(6);
+			_screen->fadeDownICF(6);
 
 			// Get the time of day string
 			time = getTimeOfDay();
@@ -1163,7 +1163,7 @@ Common::String VoyeurEngine::getTimeOfDay() {
 }
 
 int VoyeurEngine::doComputerText(int maxLen) {
-	FontInfoResource &font = *_graphicsManager->_fontPtr;
+	FontInfoResource &font = *_screen->_fontPtr;
 	int totalChars = 0;
 
 	font._curFont = _bVoy->boltEntry(0x4910)._fontResource;
@@ -1180,7 +1180,7 @@ int VoyeurEngine::doComputerText(int maxLen) {
 		font._justifyWidth = 384;
 		font._justifyHeight = 100;
 		font._pos = Common::Point(128, 100);
-		_graphicsManager->_vPort->drawText(END_OF_MESSAGE);
+		_screen->_vPort->drawText(END_OF_MESSAGE);
 	} else if (_voy->_RTVNum < _voy->_computerTimeMin && maxLen == 9999) {
 		if (_currentVocId != -1)
 			_soundManager->startVOCPlay(_currentVocId);
@@ -1188,7 +1188,7 @@ int VoyeurEngine::doComputerText(int maxLen) {
 		font._justifyWidth = 384;
 		font._justifyHeight = 100;
 		font._pos = Common::Point(120, 100);
-		_graphicsManager->_vPort->drawText(START_OF_MESSAGE);
+		_screen->_vPort->drawText(START_OF_MESSAGE);
 	} else {
 		char *msg = (char *)_bVoy->memberAddr(0x4900 + _voy->_computerTextId);
 		font._pos = Common::Point(96, 60);
@@ -1206,14 +1206,14 @@ int VoyeurEngine::doComputerText(int maxLen) {
 			if (c == '\0') {
 				if (showEnd) {
 					_eventsManager->delay(90);
-					_graphicsManager->_drawPtr->_pos = Common::Point(96, 54);
-					_graphicsManager->_drawPtr->_penColor = 254;
-					_graphicsManager->_vPort->sFillBox(196, 124);
-					_graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
-					_graphicsManager->_fontPtr->_justifyWidth = 384;
-					_graphicsManager->_fontPtr->_justifyHeight = 100;
-					_graphicsManager->_fontPtr->_pos = Common::Point(128, 100);
-					_graphicsManager->_vPort->drawText(END_OF_MESSAGE);
+					_screen->_drawPtr->_pos = Common::Point(96, 54);
+					_screen->_drawPtr->_penColor = 254;
+					_screen->_vPort->sFillBox(196, 124);
+					_screen->_fontPtr->_justify = ALIGN_LEFT;
+					_screen->_fontPtr->_justifyWidth = 384;
+					_screen->_fontPtr->_justifyHeight = 100;
+					_screen->_fontPtr->_pos = Common::Point(128, 100);
+					_screen->_vPort->drawText(END_OF_MESSAGE);
 				}
 				break;
 			}
@@ -1223,20 +1223,20 @@ int VoyeurEngine::doComputerText(int maxLen) {
 					yp += 10;
 				} else {
 					_eventsManager->delay(90);
-					_graphicsManager->_drawPtr->_pos = Common::Point(96, 54);
-					_graphicsManager->_drawPtr->_penColor = 255;
-					_graphicsManager->_vPort->sFillBox(196, 124);
+					_screen->_drawPtr->_pos = Common::Point(96, 54);
+					_screen->_drawPtr->_penColor = 255;
+					_screen->_vPort->sFillBox(196, 124);
 					yp = 60;
 				}
 
-				_graphicsManager->_fontPtr->_pos = Common::Point(96, yp);
+				_screen->_fontPtr->_pos = Common::Point(96, yp);
 			} else if (c == '_') {
 				showEnd = false;
 			} else {
-				_graphicsManager->_fontPtr->_justify = ALIGN_LEFT;
-				_graphicsManager->_fontPtr->_justifyWidth = 0;
-				_graphicsManager->_fontPtr->_justifyHeight = 0;
-				_graphicsManager->_vPort->drawText(Common::String(c));
+				_screen->_fontPtr->_justify = ALIGN_LEFT;
+				_screen->_fontPtr->_justifyWidth = 0;
+				_screen->_fontPtr->_justifyHeight = 0;
+				_screen->_vPort->drawText(Common::String(c));
 				_eventsManager->delay(4);
 			}
 
@@ -1251,7 +1251,7 @@ int VoyeurEngine::doComputerText(int maxLen) {
 
 	flipPageAndWait();
 
-	_graphicsManager->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
+	_screen->_fontPtr->_curFont = _bVoy->boltEntry(0x101)._fontResource;
 	return totalChars;
 }
 
@@ -1263,7 +1263,7 @@ void VoyeurEngine::getComputerBrush() {
 	int xp = (384 - pic->_bounds.width()) / 2;
 	int yp = (240 - pic->_bounds.height()) / 2 - 4;
 
-	_graphicsManager->_vPort->drawPicPerm(pic, Common::Point(xp, yp));
+	_screen->_vPort->drawPicPerm(pic, Common::Point(xp, yp));
 
 	CMapResource *pal = _bVoy->boltEntry(0x490F)._cMapResource;
 	pal->startFade();
@@ -1280,17 +1280,17 @@ void VoyeurEngine::doTimeBar() {
 		int height = ((_voy->_RTVLimit - _voy->_RTVNum) * 59) / _voy->_RTVLimit;
 		int fullHeight = MAX(151 - height, 93);
 
-		_graphicsManager->_drawPtr->_penColor = 134;
-		_graphicsManager->_drawPtr->_pos = Common::Point(39, 92);
+		_screen->_drawPtr->_penColor = 134;
+		_screen->_drawPtr->_pos = Common::Point(39, 92);
 
-		_graphicsManager->_vPort->sFillBox(6, fullHeight - 92);
+		_screen->_vPort->sFillBox(6, fullHeight - 92);
 		if (height > 0) {
-			_graphicsManager->setColor(215, 238, 238, 238);
+			_screen->setColor(215, 238, 238, 238);
 			_eventsManager->_intPtr._hasPalette = true;
 
-			_graphicsManager->_drawPtr->_penColor = 215;
-			_graphicsManager->_drawPtr->_pos = Common::Point(39, fullHeight);
-			_graphicsManager->_vPort->sFillBox(6, height);
+			_screen->_drawPtr->_penColor = 215;
+			_screen->_drawPtr->_pos = Common::Point(39, fullHeight);
+			_screen->_vPort->sFillBox(6, height);
 		}
 	}
 }
@@ -1303,9 +1303,9 @@ void VoyeurEngine::flashTimeBar() {
 		_flashTimeVal = _eventsManager->_intPtr._flashTimer;
 
 		if (_flashTimeFlag)
-			_graphicsManager->setColor(240, 220, 20, 20);
+			_screen->setColor(240, 220, 20, 20);
 		else
-			_graphicsManager->setColor(240, 220, 220, 220);
+			_screen->setColor(240, 220, 220, 220);
 
 		_eventsManager->_intPtr._hasPalette = true;
 		_flashTimeFlag = !_flashTimeFlag;
@@ -1343,7 +1343,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
 
 	_bVoy->getBoltGroup(_voy->_boltGroupId2);
 	PictureResource *pic = _bVoy->boltEntry(_voy->_boltGroupId2 + evidId * 2)._picResource;
-	_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort, Common::Point(
+	_screen->sDrawPic(pic, _screen->_vPort, Common::Point(
 		(384 - pic->_bounds.width()) / 2, (240 - pic->_bounds.height()) / 2));
 	_bVoy->freeBoltMember(_voy->_boltGroupId2 + evidId * 2);
 
@@ -1394,7 +1394,7 @@ void VoyeurEngine::doEvidDisplay(int evidId, int eventId) {
 			continue;
 
 		pic = _voy->_evPicPtrs[arrIndex];
-		_graphicsManager->sDrawPic(pic, _graphicsManager->_vPort,
+		_screen->sDrawPic(pic, _screen->_vPort,
 			Common::Point((384 - pic->_bounds.width()) / 2,
 			(240 - pic->_bounds.height()) / 2));
 		_voy->_evCmPtrs[arrIndex]->startFade();


Commit: 390487aa43e5507d4d0fb4ae57e7cf726a94f4c1
    https://github.com/scummvm/scummvm/commit/390487aa43e5507d4d0fb4ae57e7cf726a94f4c1
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-17T18:35:17-04:00

Commit Message:
GRAPHICS: Cleanup of ManagedSurface and Screen classes

Changed paths:
    engines/tsage/graphics.cpp
    graphics/managed_surface.cpp
    graphics/managed_surface.h
    graphics/screen.h



diff --git a/engines/tsage/graphics.cpp b/engines/tsage/graphics.cpp
index 8620498..58fa5b8 100644
--- a/engines/tsage/graphics.cpp
+++ b/engines/tsage/graphics.cpp
@@ -245,7 +245,7 @@ GfxSurface::GfxSurface(const GfxSurface &s): Graphics::ManagedSurface() {
 GfxSurface::~GfxSurface() {
 	// Sanity check.. GfxSurface should always be just referencing _rawSurface,
 	// and not directly managing it's own surface
-	assert(!isManaged());
+	assert(disposeAfterUse() == DisposeAfterUse::NO);
 }
 
 void GfxSurface::create(uint16 width, uint16 height) {
@@ -287,7 +287,7 @@ void GfxSurface::synchronize(Serializer &s) {
 
 	if (s.isSaving()) {
 		// Save contents of the surface
-		if (isManaged()) {
+		if (disposeAfterUse() == DisposeAfterUse::YES) {
 			s.syncAsSint16LE(this->w);
 			s.syncAsSint16LE(this->h);
 			s.syncBytes((byte *)getPixels(), this->w * this->h);
diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
index 45db0bc..e493ab9 100644
--- a/graphics/managed_surface.cpp
+++ b/graphics/managed_surface.cpp
@@ -30,30 +30,30 @@ const int SCALE_THRESHOLD = 0x100;
 
 ManagedSurface::ManagedSurface() : 
 		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
-		_isManaged(false), _owner(nullptr) {
+		_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
 }
 
 ManagedSurface::ManagedSurface(const ManagedSurface &surf) :
 		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
-		_isManaged(false), _owner(nullptr) {
+		_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
 	*this = surf;
 }
 
 ManagedSurface::ManagedSurface(int width, int height) :
 		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
-		_isManaged(false), _owner(nullptr) {
+		_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
 	create(width, height);
 }
 
 ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) :
 		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
-		_isManaged(false), _owner(nullptr) {
+		_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
 	create(width, height, format);
 }
 
 ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) :
 		w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format),
-		_isManaged(false), _owner(nullptr) {
+		_disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) {
 	create(surf, bounds);
 }
 
@@ -62,17 +62,18 @@ ManagedSurface::~ManagedSurface() {
 }
 
 ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) {
-	if (surf._isManaged) {
+	// Free any current surface
+	free();
+
+	if (surf._disposeAfterUse == DisposeAfterUse::YES) {
 		// Create a new surface and copy the pixels from the source surface
 		create(surf.w, surf.h, surf.format);
 		Common::copy((const byte *)surf.getPixels(), (const byte *)surf.getPixels() +
 			surf.w * surf.h * surf.format.bytesPerPixel, (byte *)this->getPixels());
 	} else {
-		// Source isn't managed, so simply copy it's fields
-		_isManaged = false;
+		// Source isn't managed, so simply copy its fields
 		_owner = surf._owner;
 		_offsetFromOwner = surf._offsetFromOwner;
-		
 		void *srcPixels = (void *)surf._innerSurface.getPixels();
 		_innerSurface.setPixels(srcPixels);
 		_innerSurface.w = surf.w;
@@ -97,7 +98,7 @@ void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixe
 	free();
 	_innerSurface.create(width, height, pixelFormat);
 
-	_isManaged = true;
+	_disposeAfterUse = DisposeAfterUse::YES;
 	markAllDirty();
 }
 
@@ -111,14 +112,14 @@ void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) {
 	_innerSurface.w = bounds.width();
 	_innerSurface.h = bounds.height();
 	_owner = &surf;
-	_isManaged = false;
+	_disposeAfterUse = DisposeAfterUse::NO;
 }
 
 void ManagedSurface::free() {
-	if (_isManaged)
+	if (_disposeAfterUse == DisposeAfterUse::YES)
 		_innerSurface.free();
 
-	_isManaged = false;
+	_disposeAfterUse = DisposeAfterUse::NO;
 	_owner = nullptr;
 	_offsetFromOwner = Common::Point(0, 0);
 }
@@ -246,6 +247,7 @@ void ManagedSurface::markAllDirty() {
 void ManagedSurface::addDirtyRect(const Common::Rect &r) {
 	if (_owner) {
 		Common::Rect bounds = r;
+		bounds.clip(Common::Rect(0, 0, this->w, this->h));
 		bounds.translate(_offsetFromOwner.x, _offsetFromOwner.y);
 		_owner->addDirtyRect(bounds);
 	}
diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h
index 1d837fd..bd0632a 100644
--- a/graphics/managed_surface.h
+++ b/graphics/managed_surface.h
@@ -26,6 +26,7 @@
 #include "graphics/pixelformat.h"
 #include "graphics/surface.h"
 #include "common/rect.h"
+#include "common/types.h"
 
 namespace Graphics {
 
@@ -38,9 +39,27 @@ class Font;
 class ManagedSurface {
 	friend class Font;
 private:
+	/**
+	 * The Graphics::Surface that the managed surface encapsulates
+	 */
 	Surface _innerSurface;
-	bool _isManaged;
+
+	/**
+	 * If set, the inner surface will be freed when the surface is recreated,
+	 * as well as when the surface is destroyed
+	 */
+	DisposeAfterUse::Flag _disposeAfterUse;
+
+	/**
+	 * Stores the owning surface if this If this managed surface represents
+	 * a sub-section of another
+	 */
 	ManagedSurface *_owner;
+
+	/**
+	 * For sub-section areas of an owning parent managed surface, this represents
+	 * the offset from the parent's top-left corner this sub-surface starts at
+	 */
 	Common::Point _offsetFromOwner;
 protected:
 	/**
@@ -65,8 +84,10 @@ public:
 	ManagedSurface();
 
 	/**
-	 * Create a managed surface from another one
-	 * Note that if the source has a managed surface, it will be duplicated
+	 * Create a managed surface from another one.
+	 * If the source surface is maintaining it's own surface data, then
+	 * this surface will create it's own surface of the same size and copy
+	 * the contents from the source surface
 	 */
 	ManagedSurface(const ManagedSurface &surf);
 
@@ -111,9 +132,9 @@ public:
 	bool empty() const { return w == 0 || h == 0 || _innerSurface.getPixels() == nullptr; }
 
 	/**
-	 * Returns true if the surface is managing it's own pixels
+	 * Returns true if the surface is managing its own pixels
 	 */
-	bool isManaged() const { return _isManaged; }
+	DisposeAfterUse::Flag disposeAfterUse() const { return _disposeAfterUse; }
 
 	/**
 	 * Return a pointer to the pixel at the specified point.
@@ -304,7 +325,7 @@ public:
 	 */
 	void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, uint32 color) {
 		_innerSurface.drawThickLine(x0, y0, x1, y1, penX, penY, color);
-		addDirtyRect(Common::Rect(x0, y0, x1, y1));
+		addDirtyRect(Common::Rect(x0, y0, x1 + penX, y1 + penY));
 	}
 
 	/**
diff --git a/graphics/screen.h b/graphics/screen.h
index 3479ce8..2981612 100644
--- a/graphics/screen.h
+++ b/graphics/screen.h
@@ -33,6 +33,12 @@ namespace Graphics {
 #define PALETTE_COUNT 256
 #define PALETTE_SIZE (256 * 3)
 
+/**
+ * Implements a specialised surface that represents the screen.
+ * It keeps track of any areas of itself that are updated by drawing
+ * calls, and provides an update that method that blits the affected 
+ * areas to the physical screen
+ */
 class Screen : virtual public ManagedSurface {
 private:
 	/**
@@ -61,12 +67,13 @@ public:
 	Screen(int width, int height, PixelFormat pixelFormat);
 
 	/**
-	 * Returns true if there are any pending screen updates
+	 * Returns true if there are any pending screen updates (dirty areas)
 	 */
-	bool isDirty() const { return _dirtyRects.empty(); }
+	bool isDirty() const { return !_dirtyRects.empty(); }
 
 	/**
-	 * Makes the whole screen dirty
+	 * Marks the whole screen as dirty. This forces the next call to update 
+	 * to copy the entire screen contents
 	 */
 	void makeAllDirty();
 


Commit: 509a00109e79156e91c062f145ac3aa86ec8584e
    https://github.com/scummvm/scummvm/commit/509a00109e79156e91c062f145ac3aa86ec8584e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-03-20T14:49:30-04:00

Commit Message:
Merge pull request #652 from dreammaster/screen

ALL: Removing code duplication via new managed surface & screen classes

Changed paths:
  A engines/sherlock/scalpel/3do/scalpel_3do_screen.cpp
  A engines/sherlock/scalpel/3do/scalpel_3do_screen.h
  A engines/sherlock/tattoo/tattoo_screen.cpp
  A engines/sherlock/tattoo/tattoo_screen.h
  A engines/tsage/screen.cpp
  A engines/tsage/screen.h
  A engines/voyeur/screen.cpp
  A engines/voyeur/screen.h
  A graphics/managed_surface.cpp
  A graphics/managed_surface.h
  A graphics/screen.cpp
  A graphics/screen.h
  R engines/voyeur/graphics.cpp
  R engines/voyeur/graphics.h
    engines/access/access.cpp
    engines/access/asurface.cpp
    engines/access/asurface.h
    engines/access/events.cpp
    engines/access/events.h
    engines/access/files.cpp
    engines/access/files.h
    engines/access/font.cpp
    engines/access/screen.cpp
    engines/access/screen.h
    engines/access/video.cpp
    engines/access/video/movie_decoder.cpp
    engines/mads/debugger.cpp
    engines/mads/dialogs.cpp
    engines/mads/dragonsphere/dragonsphere_scenes.cpp
    engines/mads/events.cpp
    engines/mads/font.cpp
    engines/mads/game.cpp
    engines/mads/mads.cpp
    engines/mads/mads.h
    engines/mads/menu_views.cpp
    engines/mads/msurface.cpp
    engines/mads/msurface.h
    engines/mads/nebular/dialogs_nebular.cpp
    engines/mads/nebular/menu_nebular.cpp
    engines/mads/nebular/nebular_scenes.cpp
    engines/mads/nebular/nebular_scenes3.cpp
    engines/mads/phantom/phantom_scenes.cpp
    engines/mads/rails.cpp
    engines/mads/scene.cpp
    engines/mads/scene_data.cpp
    engines/mads/screen.cpp
    engines/mads/screen.h
    engines/mads/sequence.cpp
    engines/mads/sprites.cpp
    engines/mads/user_interface.cpp
    engines/mads/user_interface.h
    engines/sherlock/animation.cpp
    engines/sherlock/events.cpp
    engines/sherlock/fonts.cpp
    engines/sherlock/fonts.h
    engines/sherlock/image_file.h
    engines/sherlock/module.mk
    engines/sherlock/objects.cpp
    engines/sherlock/scalpel/scalpel.cpp
    engines/sherlock/scalpel/scalpel_darts.cpp
    engines/sherlock/scalpel/scalpel_inventory.cpp
    engines/sherlock/scalpel/scalpel_map.cpp
    engines/sherlock/scalpel/scalpel_scene.cpp
    engines/sherlock/scalpel/scalpel_screen.cpp
    engines/sherlock/scalpel/scalpel_screen.h
    engines/sherlock/scalpel/scalpel_user_interface.cpp
    engines/sherlock/scalpel/tsage/logo.cpp
    engines/sherlock/scene.cpp
    engines/sherlock/screen.cpp
    engines/sherlock/screen.h
    engines/sherlock/sherlock.h
    engines/sherlock/surface.cpp
    engines/sherlock/surface.h
    engines/sherlock/tattoo/tattoo_darts.cpp
    engines/sherlock/tattoo/tattoo_journal.cpp
    engines/sherlock/tattoo/tattoo_map.cpp
    engines/sherlock/tattoo/tattoo_people.cpp
    engines/sherlock/tattoo/tattoo_scene.cpp
    engines/sherlock/tattoo/tattoo_user_interface.cpp
    engines/sherlock/tattoo/widget_base.cpp
    engines/sherlock/tattoo/widget_credits.cpp
    engines/sherlock/tattoo/widget_files.cpp
    engines/sherlock/tattoo/widget_foolscap.cpp
    engines/sherlock/tattoo/widget_inventory.cpp
    engines/sherlock/tattoo/widget_options.cpp
    engines/sherlock/tattoo/widget_password.cpp
    engines/sherlock/tattoo/widget_quit.cpp
    engines/sherlock/tattoo/widget_talk.cpp
    engines/sherlock/tattoo/widget_text.cpp
    engines/sherlock/tattoo/widget_tooltip.cpp
    engines/sherlock/tattoo/widget_verbs.cpp
    engines/tsage/blue_force/blueforce_dialogs.cpp
    engines/tsage/blue_force/blueforce_logic.cpp
    engines/tsage/blue_force/blueforce_scenes6.cpp
    engines/tsage/converse.cpp
    engines/tsage/core.cpp
    engines/tsage/events.cpp
    engines/tsage/globals.cpp
    engines/tsage/globals.h
    engines/tsage/graphics.cpp
    engines/tsage/graphics.h
    engines/tsage/module.mk
    engines/tsage/ringworld/ringworld_dialogs.cpp
    engines/tsage/ringworld/ringworld_logic.cpp
    engines/tsage/ringworld/ringworld_scenes3.cpp
    engines/tsage/ringworld/ringworld_scenes5.cpp
    engines/tsage/ringworld2/ringworld2_dialogs.cpp
    engines/tsage/ringworld2/ringworld2_logic.cpp
    engines/tsage/ringworld2/ringworld2_outpost.cpp
    engines/tsage/ringworld2/ringworld2_scenes0.cpp
    engines/tsage/saveload.cpp
    engines/tsage/scenes.cpp
    engines/tsage/tsage.h
    engines/tsage/user_interface.cpp
    engines/voyeur/animation.cpp
    engines/voyeur/data.cpp
    engines/voyeur/debugger.cpp
    engines/voyeur/events.cpp
    engines/voyeur/files.cpp
    engines/voyeur/files.h
    engines/voyeur/files_threads.cpp
    engines/voyeur/module.mk
    engines/voyeur/voyeur.cpp
    engines/voyeur/voyeur.h
    engines/voyeur/voyeur_game.cpp
    graphics/font.cpp
    graphics/font.h
    graphics/module.mk









More information about the Scummvm-git-logs mailing list