[Scummvm-git-logs] scummvm master -> 9c7ed5c0da84030467b61bb6a252544c98daada5

waltervn walter at vanniftrik-it.nl
Tue Jul 16 16:27:28 CEST 2019


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

Summary:
0cd761086a ADL: Refactor graphics code
ce8a840933 ADL: Remove APPLECHAR macro
39acda0c9f ADL: Clean up usage of override specifier
338baf827c ADL: Fix debug mode hang in hires5 animation
9c7ed5c0da ADL: Silence MSVC warnings


Commit: 0cd761086a72e9fd83c23f1c6267fe79829f3f07
    https://github.com/scummvm/scummvm/commit/0cd761086a72e9fd83c23f1c6267fe79829f3f07
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2019-07-16T16:24:19+02:00

Commit Message:
ADL: Refactor graphics code

Changed paths:
  A engines/adl/display_a2.cpp
  A engines/adl/display_a2.h
  R engines/adl/graphics.cpp
    engines/adl/adl.cpp
    engines/adl/adl_v2.cpp
    engines/adl/adl_v5.cpp
    engines/adl/console.cpp
    engines/adl/display.cpp
    engines/adl/display.h
    engines/adl/graphics.h
    engines/adl/hires1.cpp
    engines/adl/hires2.cpp
    engines/adl/hires4.cpp
    engines/adl/hires5.cpp
    engines/adl/hires6.cpp
    engines/adl/module.mk


diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 17fdd28..5da587f 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -37,7 +37,7 @@
 #include "graphics/thumbnail.h"
 
 #include "adl/adl.h"
-#include "adl/display.h"
+#include "adl/display_a2.h"
 #include "adl/detection.h"
 #include "adl/graphics.h"
 #include "adl/sound.h"
@@ -259,7 +259,7 @@ byte AdlEngine::inputKey(bool showCursor) const {
 		if (_inputScript && !_scriptPaused)
 			return APPLECHAR('\r');
 
-		_display->updateTextScreen();
+		_display->copyTextSurface();
 		g_system->delayMillis(16);
 	}
 
@@ -703,10 +703,9 @@ void AdlEngine::gameLoop() {
 }
 
 Common::Error AdlEngine::run() {
-	initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2);
-
+	_display = new Display_A2();
 	_console = new Console(this);
-	_display = new Display();
+	_display->init();
 
 	setupOpcodeTables();
 
@@ -724,7 +723,7 @@ Common::Error AdlEngine::run() {
 		_display->printAsciiString(_strings.lineFeeds);
 	}
 
-	_display->setMode(DISPLAY_MODE_MIXED);
+	_display->setMode(Display::kModeMixed);
 
 	while (!(_isQuitting || shouldQuit()))
 		gameLoop();
@@ -999,7 +998,7 @@ Common::String AdlEngine::getLine() {
 
 		if ((byte)line[0] == ('\r' | 0x80)) {
 			_textMode = !_textMode;
-			_display->setMode(_textMode ? DISPLAY_MODE_TEXT : DISPLAY_MODE_MIXED);
+			_display->setMode(_textMode ? Display::kModeText : Display::kModeMixed);
 			continue;
 		}
 
@@ -1252,8 +1251,8 @@ int AdlEngine::o_restart(ScriptEnv &e) {
 
 	if (input.size() == 0 || input[0] != APPLECHAR('N')) {
 		_isRestarting = true;
-		_display->clear(0x00);
-		_display->updateHiResScreen();
+		_graphics->clearScreen();
+		_display->copyGfxSurface();
 		_display->printString(_strings.pressReturn);
 		initState();
 		_display->printAsciiString(_strings.lineFeeds);
diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp
index 84829a7..aed38be 100644
--- a/engines/adl/adl_v2.cpp
+++ b/engines/adl/adl_v2.cpp
@@ -112,7 +112,7 @@ void AdlEngine_v2::checkTextOverflow(char c) {
 
 void AdlEngine_v2::handleTextOverflow() {
 	_linesPrinted = 0;
-	_display->updateTextScreen();
+	_display->copyTextSurface();
 
 	if (_inputScript) {
 		// Set pause flag to activate regular behaviour of delay and inputKey
@@ -153,7 +153,8 @@ Common::String AdlEngine_v2::loadMessage(uint idx) const {
 
 void AdlEngine_v2::printString(const Common::String &str) {
 	Common::String s(str);
-	uint endPos = TEXT_WIDTH - 1;
+	const uint textWidth = _display->getTextWidth();
+	uint endPos = textWidth - 1;
 	uint startPos = 0;
 	uint pos = 0;
 
@@ -167,7 +168,7 @@ void AdlEngine_v2::printString(const Common::String &str) {
 			}
 
 			s.setChar(APPLECHAR('\r'), pos);
-			endPos = pos + TEXT_WIDTH;
+			endPos = pos + textWidth;
 			startPos = pos + 1;
 		}
 
@@ -181,7 +182,7 @@ void AdlEngine_v2::printString(const Common::String &str) {
 
 	checkTextOverflow(APPLECHAR('\r'));
 	_display->printChar(APPLECHAR('\r'));
-	_display->updateTextScreen();
+	_display->copyTextSurface();
 }
 
 void AdlEngine_v2::drawItem(Item &item, const Common::Point &pos) {
@@ -259,7 +260,7 @@ void AdlEngine_v2::showRoom() {
 	if (!_state.isDark)
 		drawItems();
 
-	_display->updateHiResScreen();
+	_display->copyGfxSurface();
 	printString(_roomData.description);
 }
 
diff --git a/engines/adl/adl_v5.cpp b/engines/adl/adl_v5.cpp
index b797e73..9a970d9 100644
--- a/engines/adl/adl_v5.cpp
+++ b/engines/adl/adl_v5.cpp
@@ -123,7 +123,7 @@ int AdlEngine_v5::o_setTextMode(ScriptEnv &e) {
 		return 1;
 	case 2:
 		_textMode = true;
-		_display->setMode(DISPLAY_MODE_TEXT);
+		_display->setMode(Display::kModeText);
 		_display->home();
 		_maxLines = 24;
 		_linesPrinted = 0;
diff --git a/engines/adl/console.cpp b/engines/adl/console.cpp
index 527a575..777c0a9 100644
--- a/engines/adl/console.cpp
+++ b/engines/adl/console.cpp
@@ -182,8 +182,8 @@ void Console::prepareGame() {
 	_engine->_graphics->clearScreen();
 	_engine->loadRoom(_engine->_state.room);
 	_engine->showRoom();
-	_engine->_display->updateTextScreen();
-	_engine->_display->updateHiResScreen();
+	_engine->_display->copyTextSurface();
+	_engine->_display->copyGfxSurface();
 }
 
 bool Console::Cmd_Region(int argc, const char **argv) {
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index 52fb1b4..f2285a7 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -20,276 +20,82 @@
  *
  */
 
-#include "common/stream.h"
+#include "common/debug.h"
 #include "common/rect.h"
-#include "common/system.h"
 #include "common/str.h"
-#include "common/config-manager.h"
+#include "common/system.h"
 
 #include "graphics/surface.h"
-#include "graphics/palette.h"
-#include "graphics/thumbnail.h"
-
-#include "engines/util.h"
 
 #include "adl/display.h"
-#include "adl/adl.h"
 
 namespace Adl {
 
-// This implements the Apple II "Hi-Res" display mode
-
-#define TEXT_BUF_SIZE (TEXT_WIDTH * TEXT_HEIGHT)
-
-#define COLOR_PALETTE_ENTRIES 8
-static const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
-	0x00, 0x00, 0x00,
-	0xff, 0xff, 0xff,
-	0xc7, 0x34, 0xff,
-	0x38, 0xcb, 0x00,
-	0x00, 0x00, 0x00,
-	0xff, 0xff, 0xff,
-	0x0d, 0xa1, 0xff,
-	0xf2, 0x5e, 0x00
-};
-
-// Opacity of the optional scanlines (percentage)
-#define SCANLINE_OPACITY 75
-
-// Corresponding color in second palette
-#define PAL2(X) ((X) | 0x04)
-
-// Alternate color for odd pixel rows (for scanlines)
-#define ALTCOL(X) ((X) | 0x08)
-
-// Green monochrome palette
-#define MONO_PALETTE_ENTRIES 2
-static const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
-	0x00, 0x00, 0x00,
-	0x00, 0xc0, 0x01
-};
-
-// Uppercase-only Apple II font (manually created).
-static const byte font[64][5] = {
-	{ 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A
-	{ 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC
-	{ 0xfe, 0x82, 0x82, 0x82, 0x7c }, { 0xfe, 0x92, 0x92, 0x92, 0x82 }, // DE
-	{ 0xfe, 0x12, 0x12, 0x12, 0x02 }, { 0x7c, 0x82, 0x82, 0xa2, 0xe2 }, // FG
-	{ 0xfe, 0x10, 0x10, 0x10, 0xfe }, { 0x00, 0x82, 0xfe, 0x82, 0x00 }, // HI
-	{ 0x40, 0x80, 0x80, 0x80, 0x7e }, { 0xfe, 0x10, 0x28, 0x44, 0x82 }, // JK
-	{ 0xfe, 0x80, 0x80, 0x80, 0x80 }, { 0xfe, 0x04, 0x18, 0x04, 0xfe }, // LM
-	{ 0xfe, 0x08, 0x10, 0x20, 0xfe }, { 0x7c, 0x82, 0x82, 0x82, 0x7c }, // NO
-	{ 0xfe, 0x12, 0x12, 0x12, 0x0c }, { 0x7c, 0x82, 0xa2, 0x42, 0xbc }, // PQ
-	{ 0xfe, 0x12, 0x32, 0x52, 0x8c }, { 0x4c, 0x92, 0x92, 0x92, 0x64 }, // RS
-	{ 0x02, 0x02, 0xfe, 0x02, 0x02 }, { 0x7e, 0x80, 0x80, 0x80, 0x7e }, // TU
-	{ 0x3e, 0x40, 0x80, 0x40, 0x3e }, { 0xfe, 0x40, 0x30, 0x40, 0xfe }, // VW
-	{ 0xc6, 0x28, 0x10, 0x28, 0xc6 }, { 0x06, 0x08, 0xf0, 0x08, 0x06 }, // XY
-	{ 0xc2, 0xa2, 0x92, 0x8a, 0x86 }, { 0xfe, 0xfe, 0x82, 0x82, 0x82 }, // Z[
-	{ 0x04, 0x08, 0x10, 0x20, 0x40 }, { 0x82, 0x82, 0x82, 0xfe, 0xfe }, // \]
-	{ 0x20, 0x10, 0x08, 0x10, 0x20 }, { 0x80, 0x80, 0x80, 0x80, 0x80 }, // ^_
-	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0xbe, 0x00, 0x00 }, //  !
-	{ 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x28, 0xfe, 0x28, 0xfe, 0x28 }, // "#
-	{ 0x48, 0x54, 0xfe, 0x54, 0x24 }, { 0x46, 0x26, 0x10, 0xc8, 0xc4 }, // $%
-	{ 0x6c, 0x92, 0xac, 0x40, 0xa0 }, { 0x00, 0x00, 0x0e, 0x00, 0x00 }, // &'
-	{ 0x38, 0x44, 0x82, 0x00, 0x00 }, { 0x00, 0x00, 0x82, 0x44, 0x38 }, // ()
-	{ 0x44, 0x28, 0xfe, 0x28, 0x44 }, { 0x10, 0x10, 0x7c, 0x10, 0x10 }, // *+
-	{ 0x00, 0x80, 0x60, 0x00, 0x00 }, { 0x10, 0x10, 0x10, 0x10, 0x10 }, // ,-
-	{ 0x00, 0x00, 0x80, 0x00, 0x00 }, { 0x40, 0x20, 0x10, 0x08, 0x04 }, // ./
-	{ 0x7c, 0xa2, 0x92, 0x8a, 0x7c }, { 0x00, 0x84, 0xfe, 0x80, 0x00 }, // 01
-	{ 0xc4, 0xa2, 0x92, 0x92, 0x8c }, { 0x42, 0x82, 0x92, 0x9a, 0x66 }, // 23
-	{ 0x30, 0x28, 0x24, 0xfe, 0x20 }, { 0x4e, 0x8a, 0x8a, 0x8a, 0x72 }, // 45
-	{ 0x78, 0x94, 0x92, 0x92, 0x62 }, { 0x02, 0xe2, 0x12, 0x0a, 0x06 }, // 67
-	{ 0x6c, 0x92, 0x92, 0x92, 0x6c }, { 0x8c, 0x92, 0x92, 0x52, 0x3c }, // 89
-	{ 0x00, 0x00, 0x28, 0x00, 0x00 }, { 0x00, 0x80, 0x68, 0x00, 0x00 }, // :;
-	{ 0x10, 0x28, 0x44, 0x82, 0x00 }, { 0x28, 0x28, 0x28, 0x28, 0x28 }, // <=
-	{ 0x00, 0x82, 0x44, 0x28, 0x10 }, { 0x04, 0x02, 0xb2, 0x0a, 0x04 }  // >?
-};
-
-Display::Display() :
-		_mode(DISPLAY_MODE_TEXT),
-		_cursorPos(0),
-		_showCursor(false) {
-
-	_monochrome = !ConfMan.getBool("color");
-	_scanlines = ConfMan.getBool("scanlines");
-
-	if (_monochrome)
-		g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_ENTRIES);
-	else
-		g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES);
-
-	showScanlines(_scanlines);
-
-	_frameBuf = new byte[DISPLAY_SIZE];
-	memset(_frameBuf, 0, DISPLAY_SIZE);
-	_frameBufSurface = new Graphics::Surface;
-	// We need 2x scaling to properly render the half-pixel shift
-	// of the second palette
-	_frameBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8());
-
-	_textBuf = new byte[TEXT_BUF_SIZE];
-	memset(_textBuf, (byte)APPLECHAR(' '), TEXT_BUF_SIZE);
-	_textBufSurface = new Graphics::Surface;
-	// For ease of copying, also use 2x scaling here
-	_textBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8());
-
-	createFont();
+Display::~Display() {
+	delete[] _textBuf;
+	_textSurface->free();
+	delete _textSurface;
 
-	_startMillis = g_system->getMillis();
+	_gfxSurface->free();
+	delete _gfxSurface;
 }
 
-Display::~Display() {
-	delete[] _frameBuf;
-	_frameBufSurface->free();
-	delete _frameBufSurface;
+void Display::createSurfaces(uint gfxWidth, uint gfxHeight, uint splitHeight) {
+	_gfxSurface = new Graphics::Surface;
+	_gfxSurface->create(gfxWidth, gfxHeight, Graphics::PixelFormat::createFormatCLUT8());
+	_textSurface = new Graphics::Surface;
+	_textSurface->create(gfxWidth, gfxHeight, Graphics::PixelFormat::createFormatCLUT8());
+	_splitHeight = splitHeight;
+}
 
-	delete[] _textBuf;
-	_textBufSurface->free();
-	delete _textBufSurface;
+void Display::createTextBuffer(uint textWidth, uint textHeight) {
+	_textWidth = textWidth;
+	_textHeight = textHeight;
 
-	_font->free();
-	delete _font;
+	_textBuf = new byte[textWidth * textHeight];
+	memset(_textBuf, asciiToNative(' '), textWidth * textHeight);
 }
 
-void Display::setMode(DisplayMode mode) {
+void Display::setMode(Display::Mode mode) {
 	_mode = mode;
 
-	if (_mode == DISPLAY_MODE_TEXT || _mode == DISPLAY_MODE_MIXED)
-		updateTextScreen();
-	if (_mode == DISPLAY_MODE_HIRES || _mode == DISPLAY_MODE_MIXED)
-		updateHiResScreen();
+	if (_mode == Display::kModeText || _mode == Display::kModeMixed)
+		copyTextSurface();
+	if (_mode == Display::kModeGraphics || _mode == Display::kModeMixed)
+		copyGfxSurface();
 }
 
-void Display::updateTextScreen() {
+void Display::copyTextSurface() {
 	updateTextSurface();
 
-	if (_mode == DISPLAY_MODE_TEXT)
-		g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h);
-	else if (_mode == DISPLAY_MODE_MIXED)
-		g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2);
+	if (_mode == Display::kModeText)
+		g_system->copyRectToScreen(_textSurface->getPixels(), _textSurface->pitch, 0, 0, _textSurface->w, _textSurface->h);
+	else if (_mode == Display::kModeMixed)
+		g_system->copyRectToScreen(_textSurface->getBasePtr(0, _textSurface->h - _splitHeight), _textSurface->pitch, 0, _textSurface->h - _splitHeight, _textSurface->w, _splitHeight);
 
 	g_system->updateScreen();
 }
 
-void Display::updateHiResScreen() {
-	updateHiResSurface();
+void Display::copyGfxSurface() {
+	updateGfxSurface();
 
-	if (_mode == DISPLAY_MODE_HIRES)
-		g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h);
-	else if (_mode == DISPLAY_MODE_MIXED)
-		g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2);
+	if (_mode == kModeGraphics)
+		g_system->copyRectToScreen(_gfxSurface->getPixels(), _gfxSurface->pitch, 0, 0, _gfxSurface->w, _gfxSurface->h);
+	else if (_mode == kModeMixed)
+		g_system->copyRectToScreen(_gfxSurface->getPixels(), _gfxSurface->pitch, 0, 0, _gfxSurface->w, _gfxSurface->h - _splitHeight);
 
 	g_system->updateScreen();
 }
 
-bool Display::saveThumbnail(Common::WriteStream &out) {
-	if (_scanlines) {
-		showScanlines(false);
-		g_system->updateScreen();
-	}
-
-	bool retval = Graphics::saveThumbnail(out);
-
-	if (_scanlines) {
-		showScanlines(true);
-		g_system->updateScreen();
-	}
-
-	return retval;
-}
-
-void Display::loadFrameBuffer(Common::ReadStream &stream, byte *dst) {
-	for (uint j = 0; j < 8; ++j) {
-		for (uint i = 0; i < 8; ++i) {
-			stream.read(dst, DISPLAY_PITCH);
-			dst += DISPLAY_PITCH * 64;
-			stream.read(dst, DISPLAY_PITCH);
-			dst += DISPLAY_PITCH * 64;
-			stream.read(dst, DISPLAY_PITCH);
-			stream.readUint32LE();
-			stream.readUint32LE();
-			dst -= DISPLAY_PITCH * 120;
-		}
-		dst -= DISPLAY_PITCH * 63;
-	}
-
-	if (stream.eos() || stream.err())
-		error("Failed to read frame buffer");
-}
-
-void Display::loadFrameBuffer(Common::ReadStream &stream) {
-	loadFrameBuffer(stream, _frameBuf);
-}
-
-void Display::putPixel(const Common::Point &p, byte color) {
-	byte offset = p.x / 7;
-	byte mask = 0x80 | (1 << (p.x % 7));
-
-	// Since white and black are in both palettes, we leave
-	// the palette bit alone
-	if ((color & 0x7f) == 0x7f || (color & 0x7f) == 0)
-		mask &= 0x7f;
-
-	// Adjust colors starting with bits '01' or '10' for
-	// odd offsets
-	if (offset & 1) {
-		byte c = color << 1;
-		if (c >= 0x40 && c < 0xc0)
-			color ^= 0x7f;
-	}
-
-	writeFrameBuffer(p, color, mask);
-}
-
-void Display::setPixelByte(const Common::Point &p, byte color) {
-	assert(p.x >= 0 && p.x < DISPLAY_WIDTH && p.y >= 0 && p.y < DISPLAY_HEIGHT);
-
-	_frameBuf[p.y * DISPLAY_PITCH + p.x / 7] = color;
-}
-
-void Display::setPixelBit(const Common::Point &p, byte color) {
-	writeFrameBuffer(p, color, 1 << (p.x % 7));
-}
-
-void Display::setPixelPalette(const Common::Point &p, byte color) {
-	writeFrameBuffer(p, color, 0x80);
-}
-
-byte Display::getPixelByte(const Common::Point &p) const {
-	assert(p.x >= 0 && p.x < DISPLAY_WIDTH && p.y >= 0 && p.y < DISPLAY_HEIGHT);
-
-	return _frameBuf[p.y * DISPLAY_PITCH + p.x / 7];
-}
-
-bool Display::getPixelBit(const Common::Point &p) const {
-	assert(p.x >= 0 && p.x < DISPLAY_WIDTH && p.y >= 0 && p.y < DISPLAY_HEIGHT);
-
-	byte *b = _frameBuf + p.y * DISPLAY_PITCH + p.x / 7;
-	return *b & (1 << (p.x % 7));
-}
-
-void Display::clear(byte color) {
-	byte val = 0;
-
-	byte c = color << 1;
-	if (c >= 0x40 && c < 0xc0)
-		val = 0x7f;
-
-	for (uint i = 0; i < DISPLAY_SIZE; ++i) {
-		_frameBuf[i] = color;
-		color ^= val;
-	}
-}
-
 void Display::home() {
-	memset(_textBuf, (byte)APPLECHAR(' '), TEXT_BUF_SIZE);
+	memset(_textBuf, asciiToNative(' '), _textWidth * _textHeight);
 	_cursorPos = 0;
 }
 
 void Display::moveCursorForward() {
 	++_cursorPos;
 
-	if (_cursorPos >= TEXT_BUF_SIZE)
+	if (_cursorPos >= _textWidth * _textHeight)
 		scrollUp();
 }
 
@@ -299,276 +105,37 @@ void Display::moveCursorBackward() {
 }
 
 void Display::moveCursorTo(const Common::Point &pos) {
-	_cursorPos = pos.y * TEXT_WIDTH + pos.x;
+	_cursorPos = pos.y * _textWidth + pos.x;
 
-	if (_cursorPos >= TEXT_BUF_SIZE)
+	if (_cursorPos >= _textWidth * _textHeight)
 		error("Cursor position (%i, %i) out of bounds", pos.x, pos.y);
 }
 
-// FIXME: This does not currently update the surfaces
-void Display::printChar(char c) {
-	if (c == APPLECHAR('\r'))
-		_cursorPos = (_cursorPos / TEXT_WIDTH + 1) * TEXT_WIDTH;
-	else if (c == APPLECHAR('\a')) {
-		updateTextScreen();
-		static_cast<AdlEngine *>(g_engine)->bell();
-	} else if ((byte)c < 0x80 || (byte)c >= 0xa0) {
-		setCharAtCursor(c);
-		++_cursorPos;
-	}
-
-	if (_cursorPos == TEXT_BUF_SIZE)
-		scrollUp();
-}
-
 void Display::printString(const Common::String &str) {
 	Common::String::const_iterator c;
 	for (c = str.begin(); c != str.end(); ++c)
 		printChar(*c);
 
-	updateTextScreen();
+	copyTextSurface();
 }
 
 void Display::printAsciiString(const Common::String &str) {
-	Common::String aStr;
-
-	Common::String::const_iterator it;
-	for (it = str.begin(); it != str.end(); ++it)
-			aStr += APPLECHAR(*it);
+	Common::String::const_iterator c;
+	for (c = str.begin(); c != str.end(); ++c)
+		printChar(asciiToNative(*c));
 
-	printString(aStr);
+	copyTextSurface();
 }
 
 void Display::setCharAtCursor(byte c) {
 	_textBuf[_cursorPos] = c;
 }
 
-void Display::showCursor(bool enable) {
-	_showCursor = enable;
-}
-
-void Display::writeFrameBuffer(const Common::Point &p, byte color, byte mask) {
-	assert(p.x >= 0 && p.x < DISPLAY_WIDTH && p.y >= 0 && p.y < DISPLAY_HEIGHT);
-
-	byte *b = _frameBuf + p.y * DISPLAY_PITCH + p.x / 7;
-	color ^= *b;
-	color &= mask;
-	*b ^= color;
-}
-
-void Display::showScanlines(bool enable) {
-	byte pal[COLOR_PALETTE_ENTRIES * 3];
-
-	g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES);
-
-	if (enable) {
-		for (uint i = 0; i < ARRAYSIZE(pal); ++i)
-			pal[i] = pal[i] * (100 - SCANLINE_OPACITY) / 100;
-	}
-
-	g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES);
-}
-
-static byte processColorBits(uint16 &bits, bool &odd, bool secondPal) {
-	byte color = 0;
-
-	switch (bits & 0x7) {
-	case 0x3: // 011 (white)
-	case 0x6: // 110
-	case 0x7: // 111
-		color = 1;
-		break;
-	case 0x2: // 010 (color)
-		color = 2 + odd;
-		break;
-	case 0x5: // 101 (color)
-		color = 2 + !odd;
-	}
-
-	if (secondPal)
-		color = PAL2(color);
-
-	odd = !odd;
-	bits >>= 1;
-
-	return color;
-}
-
-static void renderPixelRowColor(byte *dst, byte *src) {
-	uint16 bits = (src[0] & 0x7f) << 1;
-	byte pal = src[0] >> 7;
-
-	if (pal != 0)
-		*dst++ = 0;
-
-	bool odd = false;
-
-	for (uint i = 0; i < DISPLAY_PITCH; ++i) {
-		if (i != DISPLAY_PITCH - 1) {
-			bits |= (src[i + 1] & 0x7f) << 8;
-			pal |= (src[i + 1] >> 7) << 1;
-		}
-
-		// For the first 6 bits in the block we draw two pixels
-		for (uint j = 0; j < 6; ++j) {
-			byte color = processColorBits(bits, odd, pal & 1);
-			*dst++ = color;
-			*dst++ = color;
-		}
-
-		// Last bit of the block, draw one, two or three pixels
-		byte color = processColorBits(bits, odd, pal & 1);
-
-		// Draw the first pixel
-		*dst++ = color;
-
-		switch (pal) {
-			case 0x0:
-			case 0x3:
-				// If palette stays the same, draw a second pixel
-				*dst++ = color;
-				break;
-			case 0x2:
-				// If we're moving from first to second palette,
-				// draw a second pixel, and a third in the second
-				// palette.
-				*dst++ = color;
-				*dst++ = PAL2(color);
-		}
-
-		pal >>= 1;
-	}
-}
-
-static void renderPixelRowMono(byte *dst, byte *src) {
-	byte pal = src[0] >> 7;
-
-	if (pal != 0)
-		*dst++ = 0;
-
-	for (uint i = 0; i < DISPLAY_PITCH; ++i) {
-		if (i != DISPLAY_PITCH - 1)
-			pal |= (src[i + 1] >> 7) << 1;
-
-		for (uint j = 0; j < 6; ++j) {
-			bool color = src[i] & (1 << j);
-			*dst++ = color;
-			*dst++ = color;
-		}
-
-		bool color = src[i] & (1 << 6);
-
-		*dst++ = color;
-
-		switch (pal) {
-			case 0x0:
-			case 0x3:
-				*dst++ = color;
-				break;
-			case 0x2:
-				*dst++ = color;
-				*dst++ = color;
-		}
-
-		pal >>= 1;
-	}
-}
-
-static void copyEvenSurfaceRows(Graphics::Surface &surf) {
-	byte *src = (byte *)surf.getPixels();
-
-	for (uint y = 0; y < surf.h / 2; ++y) {
-		byte *dst = src + surf.pitch;
-		for (uint x = 0; x < surf.w; ++x)
-			dst[x] = ALTCOL(src[x]);
-		src += surf.pitch * 2;
-	}
-}
-
-void Display::updateHiResSurface() {
-	byte *src = _frameBuf;
-	byte *dst = (byte *)_frameBufSurface->getPixels();
-
-	for (uint i = 0; i < DISPLAY_HEIGHT; ++i) {
-		if (_monochrome)
-			renderPixelRowMono(dst, src);
-		else
-			renderPixelRowColor(dst, src);
-		src += DISPLAY_PITCH;
-		dst += _frameBufSurface->pitch * 2;
-	}
-
-	copyEvenSurfaceRows(*_frameBufSurface);
-}
-
-void Display::updateTextSurface() {
-	for (uint row = 0; row < 24; ++row)
-		for (uint col = 0; col < TEXT_WIDTH; ++col) {
-			uint charPos = row * TEXT_WIDTH + col;
-			char c = _textBuf[row * TEXT_WIDTH + col];
-
-			if (charPos == _cursorPos && _showCursor)
-				c = (c & 0x3f) | 0x40;
-
-			Common::Rect r(7 * 2, 8 * 2);
-			r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
-
-			if (!(c & 0x80)) {
-				// Blink text. We subtract _startMillis to make this compatible
-				// with the event recorder, which returns offsetted values on
-				// playback.
-				const uint32 millisPassed = g_system->getMillis() - _startMillis;
-				if (!(c & 0x40) || ((millisPassed / 270) & 1))
-					r.translate(0, 4 * 8 * 2);
-			}
-
-			_textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
-		}
-}
-
-void Display::drawChar(byte c, int x, int y) {
-	byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
-
-	for (uint row = 0; row < 8; ++row) {
-		for (uint col = 1; col < 6; ++col) {
-			if (font[c][col - 1] & (1 << row)) {
-				buf[col * 2] = 1;
-				buf[col * 2 + 1] = 1;
-			}
-		}
-
-		buf += 2 * _font->pitch;
-	}
-}
-
-void Display::createFont() {
-	_font = new Graphics::Surface;
-	_font->create(16 * 7 * 2, 4 * 8 * 2 * 2, Graphics::PixelFormat::createFormatCLUT8());
-
-	for (uint i = 0; i < 4; ++i)
-		for (uint j = 0; j < 16; ++j)
-			drawChar(i * 16 + j, j * 7 * 2, i * 8 * 2);
-
-	// Create inverted font
-	byte *buf = (byte *)_font->getPixels();
-	byte *bufInv = buf + (_font->h / 2) * _font->pitch;
-
-	for (uint row = 0; row < _font->h / 2; row += 2) {
-		for (uint col = 0; col < _font->w; ++col)
-			bufInv[col] = (buf[col] ? 0 : 1);
-
-		buf += _font->pitch * 2;
-		bufInv += _font->pitch * 2;
-	}
-
-	copyEvenSurfaceRows(*_font);
-}
-
 void Display::scrollUp() {
-	memmove(_textBuf, _textBuf + TEXT_WIDTH, TEXT_BUF_SIZE - TEXT_WIDTH);
-	memset(_textBuf + TEXT_BUF_SIZE - TEXT_WIDTH, (byte)APPLECHAR(' '), TEXT_WIDTH);
-	if (_cursorPos >= TEXT_WIDTH)
-		_cursorPos -= TEXT_WIDTH;
+	memmove(_textBuf, _textBuf + _textWidth, (_textHeight - 1) * _textWidth);
+	memset(_textBuf + (_textHeight - 1) * _textWidth, asciiToNative(' '), _textWidth);
+	if (_cursorPos >= _textWidth)
+		_cursorPos -= _textWidth;
 }
 
 } // End of namespace Adl
diff --git a/engines/adl/display.h b/engines/adl/display.h
index c1c0f41..d4a30cf 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -23,10 +23,12 @@
 #ifndef ADL_DISPLAY_H
 #define ADL_DISPLAY_H
 
+// REMOVE
+#define APPLECHAR(C) (char)(C | 0x80)
+
 #include "common/types.h"
 
 namespace Common {
-class ReadStream;
 class WriteStream;
 class String;
 struct Point;
@@ -38,76 +40,56 @@ struct Surface;
 
 namespace Adl {
 
-#define DISPLAY_WIDTH 280
-#define DISPLAY_HEIGHT 192
-#define DISPLAY_PITCH (DISPLAY_WIDTH / 7)
-#define DISPLAY_SIZE (DISPLAY_PITCH * DISPLAY_HEIGHT)
-#define TEXT_WIDTH 40
-#define TEXT_HEIGHT 24
-
-enum DisplayMode {
-	DISPLAY_MODE_HIRES,
-	DISPLAY_MODE_TEXT,
-	DISPLAY_MODE_MIXED
-};
-
-#define APPLECHAR(C) ((char)((C) | 0x80))
-
 class Display {
 public:
-	Display();
-	~Display();
-
-	void setMode(DisplayMode mode);
-	void updateTextScreen();
-	void updateHiResScreen();
-	bool saveThumbnail(Common::WriteStream &out);
-
-	// Graphics
-	static void loadFrameBuffer(Common::ReadStream &stream, byte *dst);
-	void loadFrameBuffer(Common::ReadStream &stream);
-	void putPixel(const Common::Point &p, byte color);
-	void setPixelByte(const Common::Point &p, byte color);
-	void setPixelBit(const Common::Point &p, byte color);
-	void setPixelPalette(const Common::Point &p, byte color);
-	byte getPixelByte(const Common::Point &p) const;
-	bool getPixelBit(const Common::Point &p) const;
-	void clear(byte color);
-
-	// Text
+	enum Mode {
+		kModeGraphics,
+		kModeText,
+		kModeMixed
+	};
+
+	virtual ~Display();
+
+	virtual void init() = 0;
+	virtual bool saveThumbnail(Common::WriteStream &out) = 0;
+	void setMode(Mode mode);
+	void copyTextSurface();
+	void copyGfxSurface();
+
+	virtual char asciiToNative(char c) const = 0;
+	virtual void printChar(char c) = 0;
+	virtual void showCursor(bool enable) = 0;
 	void home();
 	void moveCursorTo(const Common::Point &pos);
 	void moveCursorForward();
 	void moveCursorBackward();
-	void printChar(char c);
 	void printString(const Common::String &str);
 	void printAsciiString(const Common::String &str);
 	void setCharAtCursor(byte c);
-	void showCursor(bool enable);
-
-private:
-	void writeFrameBuffer(const Common::Point &p, byte color, byte mask);
-	void updateHiResSurface();
-	void showScanlines(bool enable);
-
-	void updateTextSurface();
-	void drawChar(byte c, int x, int y);
-	void createFont();
+	uint getTextWidth() const { return _textWidth; }
+	uint getTextHeight() const { return _textHeight; }
 	void scrollUp();
 
-	DisplayMode _mode;
+protected:
+	Display() :	_textBuf(nullptr), _textSurface(nullptr), _gfxSurface(nullptr), _cursorPos(0),
+	            _mode(kModeText), _splitHeight(0), _textWidth(0), _textHeight(0) { }
 
-	byte *_frameBuf;
-	Graphics::Surface *_frameBufSurface;
-	bool _scanlines;
-	bool _monochrome;
+	void createSurfaces(uint gfxWidth, uint gfxHeight, uint splitHeight);
+	void createTextBuffer(uint textWidth, uint textHeight);
 
 	byte *_textBuf;
-	Graphics::Surface *_textBufSurface;
-	Graphics::Surface *_font;
+	Graphics::Surface *_textSurface;
+	Graphics::Surface *_gfxSurface;
 	uint _cursorPos;
-	bool _showCursor;
-	uint32 _startMillis;
+
+private:
+	virtual void updateTextSurface() = 0;
+	virtual void updateGfxSurface() = 0;
+
+	Mode _mode;
+	uint _splitHeight;
+	uint _textWidth;
+	uint _textHeight;
 };
 
 } // End of namespace Adl
diff --git a/engines/adl/display_a2.cpp b/engines/adl/display_a2.cpp
new file mode 100644
index 0000000..393e38b
--- /dev/null
+++ b/engines/adl/display_a2.cpp
@@ -0,0 +1,477 @@
+/* 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/stream.h"
+#include "common/rect.h"
+#include "common/system.h"
+#include "common/str.h"
+#include "common/config-manager.h"
+
+#include "graphics/surface.h"
+#include "graphics/palette.h"
+#include "graphics/thumbnail.h"
+
+#include "engines/util.h"
+
+#include "adl/display_a2.h"
+#include "adl/adl.h"
+
+namespace Adl {
+
+#define COLOR_PALETTE_ENTRIES 8
+static const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = {
+	0x00, 0x00, 0x00,
+	0xff, 0xff, 0xff,
+	0xc7, 0x34, 0xff,
+	0x38, 0xcb, 0x00,
+	0x00, 0x00, 0x00,
+	0xff, 0xff, 0xff,
+	0x0d, 0xa1, 0xff,
+	0xf2, 0x5e, 0x00
+};
+
+// Opacity of the optional scanlines (percentage)
+#define SCANLINE_OPACITY 75
+
+// Corresponding color in second palette
+#define PAL2(X) ((X) | 0x04)
+
+// Alternate color for odd pixel rows (for scanlines)
+#define ALTCOL(X) ((X) | 0x08)
+
+// Green monochrome palette
+#define MONO_PALETTE_ENTRIES 2
+static const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = {
+	0x00, 0x00, 0x00,
+	0x00, 0xc0, 0x01
+};
+
+// Uppercase-only Apple II font (manually created).
+static const byte font[64][5] = {
+	{ 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A
+	{ 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC
+	{ 0xfe, 0x82, 0x82, 0x82, 0x7c }, { 0xfe, 0x92, 0x92, 0x92, 0x82 }, // DE
+	{ 0xfe, 0x12, 0x12, 0x12, 0x02 }, { 0x7c, 0x82, 0x82, 0xa2, 0xe2 }, // FG
+	{ 0xfe, 0x10, 0x10, 0x10, 0xfe }, { 0x00, 0x82, 0xfe, 0x82, 0x00 }, // HI
+	{ 0x40, 0x80, 0x80, 0x80, 0x7e }, { 0xfe, 0x10, 0x28, 0x44, 0x82 }, // JK
+	{ 0xfe, 0x80, 0x80, 0x80, 0x80 }, { 0xfe, 0x04, 0x18, 0x04, 0xfe }, // LM
+	{ 0xfe, 0x08, 0x10, 0x20, 0xfe }, { 0x7c, 0x82, 0x82, 0x82, 0x7c }, // NO
+	{ 0xfe, 0x12, 0x12, 0x12, 0x0c }, { 0x7c, 0x82, 0xa2, 0x42, 0xbc }, // PQ
+	{ 0xfe, 0x12, 0x32, 0x52, 0x8c }, { 0x4c, 0x92, 0x92, 0x92, 0x64 }, // RS
+	{ 0x02, 0x02, 0xfe, 0x02, 0x02 }, { 0x7e, 0x80, 0x80, 0x80, 0x7e }, // TU
+	{ 0x3e, 0x40, 0x80, 0x40, 0x3e }, { 0xfe, 0x40, 0x30, 0x40, 0xfe }, // VW
+	{ 0xc6, 0x28, 0x10, 0x28, 0xc6 }, { 0x06, 0x08, 0xf0, 0x08, 0x06 }, // XY
+	{ 0xc2, 0xa2, 0x92, 0x8a, 0x86 }, { 0xfe, 0xfe, 0x82, 0x82, 0x82 }, // Z[
+	{ 0x04, 0x08, 0x10, 0x20, 0x40 }, { 0x82, 0x82, 0x82, 0xfe, 0xfe }, // \]
+	{ 0x20, 0x10, 0x08, 0x10, 0x20 }, { 0x80, 0x80, 0x80, 0x80, 0x80 }, // ^_
+	{ 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0xbe, 0x00, 0x00 }, //  !
+	{ 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x28, 0xfe, 0x28, 0xfe, 0x28 }, // "#
+	{ 0x48, 0x54, 0xfe, 0x54, 0x24 }, { 0x46, 0x26, 0x10, 0xc8, 0xc4 }, // $%
+	{ 0x6c, 0x92, 0xac, 0x40, 0xa0 }, { 0x00, 0x00, 0x0e, 0x00, 0x00 }, // &'
+	{ 0x38, 0x44, 0x82, 0x00, 0x00 }, { 0x00, 0x00, 0x82, 0x44, 0x38 }, // ()
+	{ 0x44, 0x28, 0xfe, 0x28, 0x44 }, { 0x10, 0x10, 0x7c, 0x10, 0x10 }, // *+
+	{ 0x00, 0x80, 0x60, 0x00, 0x00 }, { 0x10, 0x10, 0x10, 0x10, 0x10 }, // ,-
+	{ 0x00, 0x00, 0x80, 0x00, 0x00 }, { 0x40, 0x20, 0x10, 0x08, 0x04 }, // ./
+	{ 0x7c, 0xa2, 0x92, 0x8a, 0x7c }, { 0x00, 0x84, 0xfe, 0x80, 0x00 }, // 01
+	{ 0xc4, 0xa2, 0x92, 0x92, 0x8c }, { 0x42, 0x82, 0x92, 0x9a, 0x66 }, // 23
+	{ 0x30, 0x28, 0x24, 0xfe, 0x20 }, { 0x4e, 0x8a, 0x8a, 0x8a, 0x72 }, // 45
+	{ 0x78, 0x94, 0x92, 0x92, 0x62 }, { 0x02, 0xe2, 0x12, 0x0a, 0x06 }, // 67
+	{ 0x6c, 0x92, 0x92, 0x92, 0x6c }, { 0x8c, 0x92, 0x92, 0x52, 0x3c }, // 89
+	{ 0x00, 0x00, 0x28, 0x00, 0x00 }, { 0x00, 0x80, 0x68, 0x00, 0x00 }, // :;
+	{ 0x10, 0x28, 0x44, 0x82, 0x00 }, { 0x28, 0x28, 0x28, 0x28, 0x28 }, // <=
+	{ 0x00, 0x82, 0x44, 0x28, 0x10 }, { 0x04, 0x02, 0xb2, 0x0a, 0x04 }  // >?
+};
+
+Display_A2::Display_A2() : _showCursor(false) {
+	initGraphics(Display_A2::kGfxWidth * 2, Display_A2::kGfxHeight * 2);
+}
+
+Display_A2::~Display_A2() {
+	delete[] _frameBuf;
+
+	if (_font) {
+		_font->free();
+		delete _font;
+	}
+}
+
+void Display_A2::init() {
+	_monochrome = !ConfMan.getBool("color");
+	_scanlines = ConfMan.getBool("scanlines");
+
+	if (_monochrome)
+		g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_ENTRIES);
+	else
+		g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES);
+
+	showScanlines(_scanlines);
+
+	// We need 2x scaling to properly render the half-pixel shift
+	// of the second palette
+	createSurfaces(Display_A2::kGfxWidth * 2, Display_A2::kGfxHeight * 2, 64);
+	createTextBuffer(Display_A2::kTextWidth, Display_A2::kTextHeight);
+
+	_frameBuf = new byte[Display_A2::kGfxSize];
+	memset(_frameBuf, 0, Display_A2::kGfxSize);
+
+	createFont();
+
+	_startMillis = g_system->getMillis();
+}
+
+bool Display_A2::saveThumbnail(Common::WriteStream &out) {
+	if (_scanlines) {
+		showScanlines(false);
+		g_system->updateScreen();
+	}
+
+	bool retval = Graphics::saveThumbnail(out);
+
+	if (_scanlines) {
+		showScanlines(true);
+		g_system->updateScreen();
+	}
+
+	return retval;
+}
+
+void Display_A2::loadFrameBuffer(Common::ReadStream &stream, byte *dst) {
+	for (uint j = 0; j < 8; ++j) {
+		for (uint i = 0; i < 8; ++i) {
+			stream.read(dst, Display_A2::kGfxPitch);
+			dst += Display_A2::kGfxPitch * 64;
+			stream.read(dst, Display_A2::kGfxPitch);
+			dst += Display_A2::kGfxPitch * 64;
+			stream.read(dst, Display_A2::kGfxPitch);
+			stream.readUint32LE();
+			stream.readUint32LE();
+			dst -= Display_A2::kGfxPitch * 120;
+		}
+		dst -= Display_A2::kGfxPitch * 63;
+	}
+
+	if (stream.eos() || stream.err())
+		error("Failed to read frame buffer");
+}
+
+void Display_A2::loadFrameBuffer(Common::ReadStream &stream) {
+	loadFrameBuffer(stream, _frameBuf);
+}
+
+void Display_A2::putPixel(const Common::Point &p, byte color) {
+	byte offset = p.x / 7;
+	byte mask = 0x80 | (1 << (p.x % 7));
+
+	// Since white and black are in both palettes, we leave
+	// the palette bit alone
+	if ((color & 0x7f) == 0x7f || (color & 0x7f) == 0)
+		mask &= 0x7f;
+
+	// Adjust colors starting with bits '01' or '10' for
+	// odd offsets
+	if (offset & 1) {
+		byte c = color << 1;
+		if (c >= 0x40 && c < 0xc0)
+			color ^= 0x7f;
+	}
+
+	writeFrameBuffer(p, color, mask);
+}
+
+void Display_A2::setPixelByte(const Common::Point &p, byte color) {
+	assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight);
+
+	_frameBuf[p.y * Display_A2::kGfxPitch + p.x / 7] = color;
+}
+
+void Display_A2::setPixelBit(const Common::Point &p, byte color) {
+	writeFrameBuffer(p, color, 1 << (p.x % 7));
+}
+
+void Display_A2::setPixelPalette(const Common::Point &p, byte color) {
+	writeFrameBuffer(p, color, 0x80);
+}
+
+byte Display_A2::getPixelByte(const Common::Point &p) const {
+	assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight);
+
+	return _frameBuf[p.y * Display_A2::kGfxPitch + p.x / 7];
+}
+
+bool Display_A2::getPixelBit(const Common::Point &p) const {
+	assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight);
+
+	byte *b = _frameBuf + p.y * Display_A2::kGfxPitch + p.x / 7;
+	return *b & (1 << (p.x % 7));
+}
+
+void Display_A2::clear(byte color) {
+	byte val = 0;
+
+	byte c = color << 1;
+	if (c >= 0x40 && c < 0xc0)
+		val = 0x7f;
+
+	for (uint i = 0; i < Display_A2::kGfxSize; ++i) {
+		_frameBuf[i] = color;
+		color ^= val;
+	}
+}
+
+// FIXME: This does not currently update the surfaces
+void Display_A2::printChar(char c) {
+	if (c == APPLECHAR('\r'))
+		_cursorPos = (_cursorPos / Display_A2::kTextWidth + 1) * Display_A2::kTextWidth;
+	else if (c == APPLECHAR('\a')) {
+		copyTextSurface();
+		static_cast<AdlEngine *>(g_engine)->bell();
+	} else if ((byte)c < 0x80 || (byte)c >= 0xa0) {
+		setCharAtCursor(c);
+		++_cursorPos;
+	}
+
+	if (_cursorPos == Display_A2::kTextWidth * Display_A2::kTextHeight)
+		scrollUp();
+}
+
+void Display_A2::showCursor(bool enable) {
+	_showCursor = enable;
+}
+
+void Display_A2::writeFrameBuffer(const Common::Point &p, byte color, byte mask) {
+	assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight);
+
+	byte *b = _frameBuf + p.y * Display_A2::kGfxPitch + p.x / 7;
+	color ^= *b;
+	color &= mask;
+	*b ^= color;
+}
+
+void Display_A2::showScanlines(bool enable) {
+	byte pal[COLOR_PALETTE_ENTRIES * 3];
+
+	g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES);
+
+	if (enable) {
+		for (uint i = 0; i < ARRAYSIZE(pal); ++i)
+			pal[i] = pal[i] * (100 - SCANLINE_OPACITY) / 100;
+	}
+
+	g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES);
+}
+
+static byte processColorBits(uint16 &bits, bool &odd, bool secondPal) {
+	byte color = 0;
+
+	switch (bits & 0x7) {
+	case 0x3: // 011 (white)
+	case 0x6: // 110
+	case 0x7: // 111
+		color = 1;
+		break;
+	case 0x2: // 010 (color)
+		color = 2 + odd;
+		break;
+	case 0x5: // 101 (color)
+		color = 2 + !odd;
+	}
+
+	if (secondPal)
+		color = PAL2(color);
+
+	odd = !odd;
+	bits >>= 1;
+
+	return color;
+}
+
+static void renderPixelRowColor(byte *dst, byte *src) {
+	uint16 bits = (src[0] & 0x7f) << 1;
+	byte pal = src[0] >> 7;
+
+	if (pal != 0)
+		*dst++ = 0;
+
+	bool odd = false;
+
+	for (uint i = 0; i < Display_A2::kGfxPitch; ++i) {
+		if (i != Display_A2::kGfxPitch - 1) {
+			bits |= (src[i + 1] & 0x7f) << 8;
+			pal |= (src[i + 1] >> 7) << 1;
+		}
+
+		// For the first 6 bits in the block we draw two pixels
+		for (uint j = 0; j < 6; ++j) {
+			byte color = processColorBits(bits, odd, pal & 1);
+			*dst++ = color;
+			*dst++ = color;
+		}
+
+		// Last bit of the block, draw one, two or three pixels
+		byte color = processColorBits(bits, odd, pal & 1);
+
+		// Draw the first pixel
+		*dst++ = color;
+
+		switch (pal) {
+			case 0x0:
+			case 0x3:
+				// If palette stays the same, draw a second pixel
+				*dst++ = color;
+				break;
+			case 0x2:
+				// If we're moving from first to second palette,
+				// draw a second pixel, and a third in the second
+				// palette.
+				*dst++ = color;
+				*dst++ = PAL2(color);
+		}
+
+		pal >>= 1;
+	}
+}
+
+static void renderPixelRowMono(byte *dst, byte *src) {
+	byte pal = src[0] >> 7;
+
+	if (pal != 0)
+		*dst++ = 0;
+
+	for (uint i = 0; i < Display_A2::kGfxPitch; ++i) {
+		if (i != Display_A2::kGfxPitch - 1)
+			pal |= (src[i + 1] >> 7) << 1;
+
+		for (uint j = 0; j < 6; ++j) {
+			bool color = src[i] & (1 << j);
+			*dst++ = color;
+			*dst++ = color;
+		}
+
+		bool color = src[i] & (1 << 6);
+
+		*dst++ = color;
+
+		switch (pal) {
+			case 0x0:
+			case 0x3:
+				*dst++ = color;
+				break;
+			case 0x2:
+				*dst++ = color;
+				*dst++ = color;
+		}
+
+		pal >>= 1;
+	}
+}
+
+static void copyEvenSurfaceRows(Graphics::Surface &surf) {
+	byte *src = (byte *)surf.getPixels();
+
+	for (uint y = 0; y < surf.h / 2; ++y) {
+		byte *dst = src + surf.pitch;
+		for (uint x = 0; x < surf.w; ++x)
+			dst[x] = ALTCOL(src[x]);
+		src += surf.pitch * 2;
+	}
+}
+
+void Display_A2::updateGfxSurface() {
+	byte *src = _frameBuf;
+	byte *dst = (byte *)_gfxSurface->getPixels();
+
+	for (uint i = 0; i < Display_A2::kGfxHeight; ++i) {
+		if (_monochrome)
+			renderPixelRowMono(dst, src);
+		else
+			renderPixelRowColor(dst, src);
+		src += Display_A2::kGfxPitch;
+		dst += _gfxSurface->pitch * 2;
+	}
+
+	copyEvenSurfaceRows(*_gfxSurface);
+}
+
+void Display_A2::updateTextSurface() {
+	for (uint row = 0; row < 24; ++row)
+		for (uint col = 0; col < Display_A2::kTextWidth; ++col) {
+			uint charPos = row * Display_A2::kTextWidth + col;
+			char c = _textBuf[row * Display_A2::kTextWidth + col];
+
+			if (charPos == _cursorPos && _showCursor)
+				c = (c & 0x3f) | 0x40;
+
+			Common::Rect r(7 * 2, 8 * 2);
+			r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2);
+
+			if (!(c & 0x80)) {
+				// Blink text. We subtract _startMillis to make this compatible
+				// with the event recorder, which returns offsetted values on
+				// playback.
+				const uint32 millisPassed = g_system->getMillis() - _startMillis;
+				if (!(c & 0x40) || ((millisPassed / 270) & 1))
+					r.translate(0, 4 * 8 * 2);
+			}
+
+			_textSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r);
+		}
+}
+
+void Display_A2::drawChar(byte c, int x, int y) {
+	byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x;
+
+	for (uint row = 0; row < 8; ++row) {
+		for (uint col = 1; col < 6; ++col) {
+			if (font[c][col - 1] & (1 << row)) {
+				buf[col * 2] = 1;
+				buf[col * 2 + 1] = 1;
+			}
+		}
+
+		buf += 2 * _font->pitch;
+	}
+}
+
+void Display_A2::createFont() {
+	_font = new Graphics::Surface;
+	_font->create(16 * 7 * 2, 4 * 8 * 2 * 2, Graphics::PixelFormat::createFormatCLUT8());
+
+	for (uint i = 0; i < 4; ++i)
+		for (uint j = 0; j < 16; ++j)
+			drawChar(i * 16 + j, j * 7 * 2, i * 8 * 2);
+
+	// Create inverted font
+	byte *buf = (byte *)_font->getPixels();
+	byte *bufInv = buf + (_font->h / 2) * _font->pitch;
+
+	for (uint row = 0; row < _font->h / 2; row += 2) {
+		for (uint col = 0; col < _font->w; ++col)
+			bufInv[col] = (buf[col] ? 0 : 1);
+
+		buf += _font->pitch * 2;
+		bufInv += _font->pitch * 2;
+	}
+
+	copyEvenSurfaceRows(*_font);
+}
+
+} // End of namespace Adl
diff --git a/engines/adl/display_a2.h b/engines/adl/display_a2.h
new file mode 100644
index 0000000..5823c24
--- /dev/null
+++ b/engines/adl/display_a2.h
@@ -0,0 +1,85 @@
+/* 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 "adl/display.h"
+
+#ifndef ADL_DISPLAY_A2_H
+#define ADL_DISPLAY_A2_H
+
+namespace Adl {
+
+class Display_A2 : public Display {
+public:
+	Display_A2();
+	virtual ~Display_A2();
+
+	enum {
+		kGfxWidth = 280,
+		kGfxHeight = 192,
+		kGfxPitch = kGfxWidth / 7,
+		kGfxSize = kGfxWidth * kGfxHeight,
+		kTextWidth = 40,
+		kTextHeight = 24
+	};
+
+	virtual void init() override;
+	virtual bool saveThumbnail(Common::WriteStream &out) override;
+
+	// Graphics
+	uint getGfxWidth() const { return kGfxWidth; }
+	uint getGfxHeight() const { return kGfxHeight; }
+	uint getGfxPitch() const { return kGfxPitch; }
+	void loadFrameBuffer(Common::ReadStream &stream, byte *dst);
+	void loadFrameBuffer(Common::ReadStream &stream);
+	void putPixel(const Common::Point &p, byte color);
+	void setPixelByte(const Common::Point &p, byte color);
+	void setPixelBit(const Common::Point &p, byte color);
+	void setPixelPalette(const Common::Point &p, byte color);
+	byte getPixelByte(const Common::Point &p) const;
+	bool getPixelBit(const Common::Point &p) const;
+	void clear(byte color);
+
+	// Text
+	virtual char asciiToNative(char c) const override { return c | 0x80; }
+	virtual void printChar(char c) override;
+	virtual void showCursor(bool enable);
+
+private:
+	void writeFrameBuffer(const Common::Point &p, byte color, byte mask);
+	virtual void updateTextSurface() override;
+	virtual void updateGfxSurface() override;
+
+	void showScanlines(bool enable);
+	void drawChar(byte c, int x, int y);
+	void createFont();
+
+	byte *_frameBuf;
+	bool _scanlines;
+	bool _monochrome;
+	Graphics::Surface *_font;
+	bool _showCursor;
+	uint32 _startMillis;
+};
+
+} // End of namespace Adl
+
+#endif
diff --git a/engines/adl/graphics.cpp b/engines/adl/graphics.cpp
deleted file mode 100644
index 2fcd147..0000000
--- a/engines/adl/graphics.cpp
+++ /dev/null
@@ -1,475 +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 "common/stream.h"
-#include "common/rect.h"
-#include "common/textconsole.h"
-
-#include "adl/display.h"
-#include "adl/graphics.h"
-
-namespace Adl {
-
-void GraphicsMan::clearScreen() const {
-	_display.setMode(DISPLAY_MODE_MIXED);
-	_display.clear(getClearColor());
-}
-
-// Draws a four-connected line
-void GraphicsMan::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const {
-	int16 deltaX = p2.x - p1.x;
-	int8 xStep = 1;
-
-	if (deltaX < 0) {
-		deltaX = -deltaX;
-		xStep = -1;
-	}
-
-	int16 deltaY = p2.y - p1.y;
-	int8 yStep = -1;
-
-	if (deltaY > 0) {
-		deltaY = -deltaY;
-		yStep = 1;
-	}
-
-	Common::Point p(p1);
-	int16 steps = deltaX - deltaY + 1;
-	int16 err = deltaX + deltaY;
-
-	while (true) {
-		putPixel(p, color);
-
-		if (--steps == 0)
-			return;
-
-		if (err < 0) {
-			p.y += yStep;
-			err += deltaX;
-		} else {
-			p.x += xStep;
-			err += deltaY;
-		}
-	}
-}
-
-void GraphicsMan::putPixel(const Common::Point &p, byte color) const {
-	if (_bounds.contains(p))
-		_display.putPixel(p, color);
-}
-
-void GraphicsMan::drawShapePixel(Common::Point &p, byte color, byte bits, byte quadrant) const {
-	if (bits & 4)
-		putPixel(p, color);
-
-	bits += quadrant;
-
-	if (bits & 1)
-		p.x += (bits & 2 ? -1 : 1);
-	else
-		p.y += (bits & 2 ? 1 : -1);
-}
-
-void GraphicsMan::drawShape(Common::ReadStream &corners, Common::Point &pos, byte rotation, byte scaling, byte color) const {
-	const byte stepping[] = {
-		0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
-		0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
-		0xff
-	};
-
-	byte quadrant = rotation >> 4;
-	rotation &= 0xf;
-	byte xStep = stepping[rotation];
-	byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
-
-	while (true) {
-		byte b = corners.readByte();
-
-		if (corners.eos() || corners.err())
-			error("Error reading corners");
-
-		if (b == 0)
-			return;
-
-		do {
-			byte xFrac = 0x80;
-			byte yFrac = 0x80;
-			for (uint j = 0; j < scaling; ++j) {
-				if (xFrac + xStep + 1 > 255)
-					drawShapePixel(pos, color, b, quadrant);
-				xFrac += xStep + 1;
-				if (yFrac + yStep > 255)
-					drawShapePixel(pos, color, b, quadrant + 1);
-				yFrac += yStep;
-			}
-			b >>= 3;
-		} while (b != 0);
-	}
-}
-
-void GraphicsMan::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) {
-	byte x, y;
-	bool bNewLine = false;
-	byte oldX = 0, oldY = 0;
-	while (1) {
-		x = pic.readByte();
-		y = pic.readByte();
-
-		if (pic.err() || pic.eos())
-			error("Error reading picture");
-
-		if (x == 0xff && y == 0xff)
-			return;
-
-		if (x == 0 && y == 0) {
-			bNewLine = true;
-			continue;
-		}
-
-		x += pos.x;
-		y += pos.y;
-
-		if (y > 160)
-			y = 160;
-
-		if (bNewLine) {
-			putPixel(Common::Point(x, y), 0x7f);
-			bNewLine = false;
-		} else {
-			drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
-		}
-
-		oldX = x;
-		oldY = y;
-	}
-}
-
-#define NUM_PATTERNS 22
-#define PATTERN_LEN 4
-static const byte fillPatterns[NUM_PATTERNS][PATTERN_LEN] = {
-	{ 0x00, 0x00, 0x00, 0x00 },
-	{ 0x80, 0x80, 0x80, 0x80 },
-	{ 0xff, 0xff, 0xff, 0xff },
-	{ 0x7f, 0x7f, 0x7f, 0x7f },
-	{ 0x2a, 0x55, 0x2a, 0x55 },
-	{ 0xaa, 0xd5, 0xaa, 0xd5 },
-	{ 0x55, 0x2a, 0x55, 0x2a },
-	{ 0xd5, 0xaa, 0xd5, 0xaa },
-	{ 0x33, 0x66, 0x4c, 0x19 },
-	{ 0xb3, 0xe6, 0xcc, 0x99 },
-	{ 0x22, 0x44, 0x08, 0x11 },
-	{ 0xa2, 0xc4, 0x88, 0x91 },
-	{ 0x11, 0x22, 0x44, 0x08 },
-	{ 0x91, 0xa2, 0xc4, 0x88 },
-	{ 0x6e, 0x5d, 0x3b, 0x77 },
-	{ 0xee, 0xdd, 0xbb, 0xf7 },
-	{ 0x5d, 0x3b, 0x77, 0x6e },
-	{ 0xdd, 0xbb, 0xf7, 0xee },
-	{ 0x66, 0x4c, 0x19, 0x33 },
-	{ 0xe6, 0xcc, 0x99, 0xb3 },
-	{ 0x33, 0x66, 0x4c, 0x19 },
-	{ 0xb3, 0xe6, 0xcc, 0x99 }
-};
-
-#define MIN_COMMAND 0xe0
-
-#define CHECK_COMMAND(X) \
-	do { \
-		if ((X) >= MIN_COMMAND) { \
-			pic.seek(-1, SEEK_CUR); \
-			return; \
-		} \
-	} while (0)
-
-#define READ_BYTE(b) \
-	do { \
-		b = pic.readByte(); \
-		if (pic.eos() || pic.err()) \
-			error("Error reading picture"); \
-		CHECK_COMMAND(b); \
-	} while (0)
-
-#define READ_POINT(p) \
-	do { \
-		READ_BYTE(p.x); \
-		p.x += _offset.x; \
-		p.x <<= 1; \
-		READ_BYTE(p.y); \
-		p.y += _offset.y; \
-	} while (0)
-
-void GraphicsMan_v2::drawCorners(Common::SeekableReadStream &pic, bool yFirst) {
-	Common::Point p;
-
-	READ_POINT(p);
-
-	if (yFirst)
-		goto doYStep;
-
-	while (true) {
-		int16 n;
-
-		READ_BYTE(n);
-		n += _offset.x;
-
-		putPixel(p, _color);
-
-		n <<= 1;
-		drawLine(p, Common::Point(n, p.y), _color);
-		p.x = n;
-
-doYStep:
-		READ_BYTE(n);
-		n += _offset.y;
-
-		putPixel(p, _color);
-		drawLine(p, Common::Point(p.x, n), _color);
-
-		putPixel(Common::Point(p.x + 1, p.y), _color);
-		drawLine(Common::Point(p.x + 1, p.y), Common::Point(p.x + 1, n), _color);
-
-		p.y = n;
-	}
-}
-
-void GraphicsMan_v2::drawRelativeLines(Common::SeekableReadStream &pic) {
-	Common::Point p1;
-
-	READ_POINT(p1);
-	putPixel(p1, _color);
-
-	while (true) {
-		Common::Point p2(p1);
-
-		byte n;
-		READ_BYTE(n);
-
-		byte h = (n & 0x70) >> 4;
-		byte l = n & 7;
-
-		if (n & 0x80)
-			p2.x -= (h << 1);
-		else
-			p2.x += (h << 1);
-
-		if (n & 8)
-			p2.y -= l;
-		else
-			p2.y += l;
-
-		drawLine(p1, p2, _color);
-		p1 = p2;
-	}
-}
-
-void GraphicsMan_v2::drawAbsoluteLines(Common::SeekableReadStream &pic) {
-	Common::Point p1;
-
-	READ_POINT(p1);
-	putPixel(p1, _color);
-
-	while (true) {
-		Common::Point p2;
-
-		READ_POINT(p2);
-		drawLine(p1, p2, _color);
-		p1 = p2;
-	}
-}
-
-static byte getPatternColor(const Common::Point &p, byte pattern) {
-	if (pattern >= NUM_PATTERNS)
-		error("Invalid fill pattern %i encountered in picture", pattern);
-
-	byte offset = (p.y & 1) << 1;
-	offset += (p.x / 7) & 3;
-
-	return fillPatterns[pattern][offset % PATTERN_LEN];
-}
-
-bool GraphicsMan_v2::canFillAt(const Common::Point &p, const bool stopBit) {
-	return _display.getPixelBit(p) != stopBit && _display.getPixelBit(Common::Point(p.x + 1, p.y)) != stopBit;
-}
-
-void GraphicsMan_v2::fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) {
-	byte color = getPatternColor(p, pattern);
-
-	while (--p.x >= _bounds.left) {
-		if ((p.x % 7) == 6) {
-			color = getPatternColor(p, pattern);
-			_display.setPixelPalette(p, color);
-		}
-		if (_display.getPixelBit(p) == stopBit)
-			break;
-		_display.setPixelBit(p, color);
-	}
-}
-
-void GraphicsMan_v2::fillRow(Common::Point p, const byte pattern, const bool stopBit) {
-	// Set pixel at p and palette
-	byte color = getPatternColor(p, pattern);
-	_display.setPixelPalette(p, color);
-	_display.setPixelBit(p, color);
-
-	// Fill left of p
-	fillRowLeft(p, pattern, stopBit);
-
-	// Fill right of p
-	while (++p.x < _bounds.right) {
-		if ((p.x % 7) == 0) {
-			color = getPatternColor(p, pattern);
-			// Palette is set before the first bit is tested
-			_display.setPixelPalette(p, color);
-		}
-		if (_display.getPixelBit(p) == stopBit)
-			break;
-		_display.setPixelBit(p, color);
-	}
-}
-
-void GraphicsMan_v2::fillAt(Common::Point p, const byte pattern) {
-	const bool stopBit = !_display.getPixelBit(p);
-
-	// Move up into the open space above p
-	while (--p.y >= _bounds.top && canFillAt(p, stopBit)) {}
-
-	// Then fill by moving down
-	while (++p.y < _bounds.bottom && canFillAt(p, stopBit))
-		fillRow(p, pattern, stopBit);
-}
-
-void GraphicsMan_v2::fill(Common::SeekableReadStream &pic) {
-	byte pattern;
-	READ_BYTE(pattern);
-
-	while (true) {
-		Common::Point p;
-		READ_POINT(p);
-
-		if (_bounds.contains(p))
-			fillAt(p, pattern);
-	}
-}
-
-void GraphicsMan_v2::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) {
-	// NOTE: The original engine only resets the color for overlays. As a result, room
-	// pictures that draw without setting a color or clearing the screen, will use the
-	// last color set by the previous picture. We assume this is unintentional and do
-	// not copy this behavior.
-	_color = 0;
-	_offset = pos;
-
-	while (true) {
-		byte opcode = pic.readByte();
-
-		if (pic.eos() || pic.err())
-			error("Error reading picture");
-
-		switch (opcode) {
-		case 0xe0:
-			drawCorners(pic, false);
-			break;
-		case 0xe1:
-			drawCorners(pic, true);
-			break;
-		case 0xe2:
-			drawRelativeLines(pic);
-			break;
-		case 0xe3:
-			drawAbsoluteLines(pic);
-			break;
-		case 0xe4:
-			fill(pic);
-			break;
-		case 0xe5:
-			clearScreen();
-			_color = 0x00;
-			break;
-		case 0xf0:
-			_color = 0x00;
-			break;
-		case 0xf1:
-			_color = 0x2a;
-			break;
-		case 0xf2:
-			_color = 0x55;
-			break;
-		case 0xf3:
-			_color = 0x7f;
-			break;
-		case 0xf4:
-			_color = 0x80;
-			break;
-		case 0xf5:
-			_color = 0xaa;
-			break;
-		case 0xf6:
-			_color = 0xd5;
-			break;
-		case 0xf7:
-			_color = 0xff;
-			break;
-		case 0xff:
-			return;
-		default:
-			if (opcode >= 0xe0)
-				error("Invalid pic opcode %02x", opcode);
-			else
-				warning("Expected pic opcode, but found data byte %02x", opcode);
-		}
-	}
-}
-
-void GraphicsMan_v3::fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) {
-	byte color = getPatternColor(p, pattern);
-
-	while (--p.x >= _bounds.left) {
-		// In this version, when moving left, it no longer sets the palette first
-		if (!_display.getPixelBit(p))
-			return;
-		if ((p.x % 7) == 6) {
-			color = getPatternColor(p, pattern);
-			_display.setPixelPalette(p, color);
-		}
-		_display.setPixelBit(p, color);
-	}
-}
-
-void GraphicsMan_v3::fillAt(Common::Point p, const byte pattern) {
-	// If the row at p cannot be filled, we do nothing
-	if (!canFillAt(p))
-			return;
-
-	fillRow(p, pattern);
-
-	Common::Point q(p);
-
-	// Fill up from p
-	while (--q.y >= _bounds.top && canFillAt(q))
-		fillRow(q, pattern);
-
-	// Fill down from p
-	while (++p.y < _bounds.bottom && canFillAt(p))
-		fillRow(p, pattern);
-}
-
-} // End of namespace Adl
diff --git a/engines/adl/graphics.h b/engines/adl/graphics.h
index 38dc2b2..ad56281 100644
--- a/engines/adl/graphics.h
+++ b/engines/adl/graphics.h
@@ -24,34 +24,44 @@
 #define ADL_GRAPHICS_H
 
 #include "common/rect.h"
+#include "common/stream.h"
 
-namespace Common {
-class SeekableReadStream;
-}
+#include "adl/display.h"
 
 namespace Adl {
 
-class Display;
-
-// Used in hires1
 class GraphicsMan {
 public:
-	GraphicsMan(Display &display) : _bounds(280, 160), _display(display) { }
 	virtual ~GraphicsMan() { }
 
 	// Applesoft BASIC HLINE
-	void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const;
+	virtual void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const = 0;
 	// Applesoft BASIC DRAW
-	void drawShape(Common::ReadStream &shape, Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const;
-
-	virtual void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos);
-	void clearScreen() const;
-	void putPixel(const Common::Point &p, byte color) const;
+	virtual void drawShape(Common::ReadStream &shape, Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const = 0;
+	virtual void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) = 0;
+	virtual void clearScreen() const = 0;
 	void setBounds(const Common::Rect &r) { _bounds = r; }
 
 protected:
-	Display &_display;
 	Common::Rect _bounds;
+};
+
+// Used in hires1
+template <class T>
+class GraphicsMan_v1 : public GraphicsMan {
+public:
+	using GraphicsMan::_bounds;
+
+	GraphicsMan_v1<T>(T &display) : _display(display) { this->setBounds(Common::Rect(280, 160)); }
+
+	virtual void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const override;
+	virtual void drawShape(Common::ReadStream &shape, Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const override;
+	virtual void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) override;
+	virtual void clearScreen() const override;
+
+protected:
+	T &_display;
+	void putPixel(const Common::Point &p, byte color) const;
 
 private:
 	void drawShapePixel(Common::Point &p, byte color, byte bits, byte quadrant) const;
@@ -59,38 +69,537 @@ private:
 };
 
 // Used in hires0 and hires2-hires4
-class GraphicsMan_v2 : public GraphicsMan {
+template <class T>
+class GraphicsMan_v2 : public GraphicsMan_v1<T> {
 public:
-	GraphicsMan_v2(Display &display) : GraphicsMan(display), _color(0) { }
+	using GraphicsMan::_bounds;
+	using GraphicsMan_v1<T>::_display;
+	using GraphicsMan_v1<T>::drawLine;
+	using GraphicsMan_v1<T>::putPixel;
+
+	GraphicsMan_v2<T>(T &display) : GraphicsMan_v1<T>(display), _color(0) { }
 	void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos);
 
 protected:
 	bool canFillAt(const Common::Point &p, const bool stopBit = false);
 	void fillRow(Common::Point p, const byte pattern, const bool stopBit = false);
+	byte getPatternColor(const Common::Point &p, byte pattern);
 
 private:
+	static bool readByte(Common::SeekableReadStream &pic, byte &b);
+	bool readPoint(Common::SeekableReadStream &pic, Common::Point &p);
 	void drawCorners(Common::SeekableReadStream &pic, bool yFirst);
 	void drawRelativeLines(Common::SeekableReadStream &pic);
 	void drawAbsoluteLines(Common::SeekableReadStream &pic);
+	void fill(Common::SeekableReadStream &pic);
 	virtual void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit);
 	virtual void fillAt(Common::Point p, const byte pattern);
-	void fill(Common::SeekableReadStream &pic);
-	byte getClearColor() const { return 0xff; }
+	virtual byte getClearColor() const override { return 0xff; }
 
 	byte _color;
 	Common::Point _offset;
 };
 
 // Used in hires5, hires6 and gelfling (possibly others as well)
-class GraphicsMan_v3 : public GraphicsMan_v2 {
+template <class T>
+class GraphicsMan_v3 : public GraphicsMan_v2<T> {
 public:
-	GraphicsMan_v3(Display &display) : GraphicsMan_v2(display) { }
+	using GraphicsMan::_bounds;
+	using GraphicsMan_v1<T>::_display;
+	using GraphicsMan_v2<T>::canFillAt;
+	using GraphicsMan_v2<T>::fillRow;
+	using GraphicsMan_v2<T>::getPatternColor;
+
+	GraphicsMan_v3<T>(T &display) : GraphicsMan_v2<T>(display) { }
 
 private:
-	void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit);
-	void fillAt(Common::Point p, const byte pattern);
+	virtual void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) override;
+	virtual void fillAt(Common::Point p, const byte pattern) override;
 };
 
+template <class T>
+void GraphicsMan_v1<T>::clearScreen() const {
+	_display.setMode(Display::kModeMixed);
+	_display.clear(getClearColor());
+}
+
+// Draws a four-connected line
+template <class T>
+void GraphicsMan_v1<T>::drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const {
+	int16 deltaX = p2.x - p1.x;
+	int8 xStep = 1;
+
+	if (deltaX < 0) {
+		deltaX = -deltaX;
+		xStep = -1;
+	}
+
+	int16 deltaY = p2.y - p1.y;
+	int8 yStep = -1;
+
+	if (deltaY > 0) {
+		deltaY = -deltaY;
+		yStep = 1;
+	}
+
+	Common::Point p(p1);
+	int16 steps = deltaX - deltaY + 1;
+	int16 err = deltaX + deltaY;
+
+	while (true) {
+		putPixel(p, color);
+
+		if (--steps == 0)
+			return;
+
+		if (err < 0) {
+			p.y += yStep;
+			err += deltaX;
+		} else {
+			p.x += xStep;
+			err += deltaY;
+		}
+	}
+}
+
+template <class T>
+void GraphicsMan_v1<T>::putPixel(const Common::Point &p, byte color) const {
+	if (_bounds.contains(p))
+		_display.putPixel(p, color);
+}
+
+template <class T>
+void GraphicsMan_v1<T>::drawShapePixel(Common::Point &p, byte color, byte bits, byte quadrant) const {
+	if (bits & 4)
+		putPixel(p, color);
+
+	bits += quadrant;
+
+	if (bits & 1)
+		p.x += (bits & 2 ? -1 : 1);
+	else
+		p.y += (bits & 2 ? 1 : -1);
+}
+
+template <class T>
+void GraphicsMan_v1<T>::drawShape(Common::ReadStream &corners, Common::Point &pos, byte rotation, byte scaling, byte color) const {
+	const byte stepping[] = {
+		0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5,
+		0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18,
+		0xff
+	};
+
+	byte quadrant = rotation >> 4;
+	rotation &= 0xf;
+	byte xStep = stepping[rotation];
+	byte yStep = stepping[(rotation ^ 0xf) + 1] + 1;
+
+	while (true) {
+		byte b = corners.readByte();
+
+		if (corners.eos() || corners.err())
+			error("Error reading corners");
+
+		if (b == 0)
+			return;
+
+		do {
+			byte xFrac = 0x80;
+			byte yFrac = 0x80;
+			for (uint j = 0; j < scaling; ++j) {
+				if (xFrac + xStep + 1 > 255)
+					drawShapePixel(pos, color, b, quadrant);
+				xFrac += xStep + 1;
+				if (yFrac + yStep > 255)
+					drawShapePixel(pos, color, b, quadrant + 1);
+				yFrac += yStep;
+			}
+			b >>= 3;
+		} while (b != 0);
+	}
+}
+
+template <class T>
+void GraphicsMan_v1<T>::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) {
+	byte x, y;
+	bool bNewLine = false;
+	byte oldX = 0, oldY = 0;
+	while (1) {
+		x = pic.readByte();
+		y = pic.readByte();
+
+		if (pic.err() || pic.eos())
+			error("Error reading picture");
+
+		if (x == 0xff && y == 0xff)
+			return;
+
+		if (x == 0 && y == 0) {
+			bNewLine = true;
+			continue;
+		}
+
+		x += pos.x;
+		y += pos.y;
+
+		if (y > 160)
+			y = 160;
+
+		if (bNewLine) {
+			putPixel(Common::Point(x, y), 0x7f);
+			bNewLine = false;
+		} else {
+			drawLine(Common::Point(oldX, oldY), Common::Point(x, y), 0x7f);
+		}
+
+		oldX = x;
+		oldY = y;
+	}
+}
+
+template <class T>
+bool GraphicsMan_v2<T>::readByte(Common::SeekableReadStream &pic, byte &b) {
+	b = pic.readByte();
+
+	if (pic.eos() || pic.err())
+		error("Error reading picture");
+
+	if (b >= 0xe0) {
+		pic.seek(-1, SEEK_CUR);
+		return false;
+	}
+
+	return true;
+}
+
+template <class T>
+bool GraphicsMan_v2<T>::readPoint(Common::SeekableReadStream &pic, Common::Point &p) {
+	byte b;
+
+	if (!readByte(pic, b))
+		return false;
+
+	p.x = b + _offset.x;
+	p.x <<= 1;
+
+	if (!readByte(pic, b))
+		return false;
+
+	p.y = b + _offset.y;
+
+	return true;
+}
+
+template <class T>
+byte GraphicsMan_v2<T>::getPatternColor(const Common::Point &p, byte pattern) {
+	const byte fillPatterns[][4] = {
+		{ 0x00, 0x00, 0x00, 0x00 },
+		{ 0x80, 0x80, 0x80, 0x80 },
+		{ 0xff, 0xff, 0xff, 0xff },
+		{ 0x7f, 0x7f, 0x7f, 0x7f },
+		{ 0x2a, 0x55, 0x2a, 0x55 },
+		{ 0xaa, 0xd5, 0xaa, 0xd5 },
+		{ 0x55, 0x2a, 0x55, 0x2a },
+		{ 0xd5, 0xaa, 0xd5, 0xaa },
+		{ 0x33, 0x66, 0x4c, 0x19 },
+		{ 0xb3, 0xe6, 0xcc, 0x99 },
+		{ 0x22, 0x44, 0x08, 0x11 },
+		{ 0xa2, 0xc4, 0x88, 0x91 },
+		{ 0x11, 0x22, 0x44, 0x08 },
+		{ 0x91, 0xa2, 0xc4, 0x88 },
+		{ 0x6e, 0x5d, 0x3b, 0x77 },
+		{ 0xee, 0xdd, 0xbb, 0xf7 },
+		{ 0x5d, 0x3b, 0x77, 0x6e },
+		{ 0xdd, 0xbb, 0xf7, 0xee },
+		{ 0x66, 0x4c, 0x19, 0x33 },
+		{ 0xe6, 0xcc, 0x99, 0xb3 },
+		{ 0x33, 0x66, 0x4c, 0x19 },
+		{ 0xb3, 0xe6, 0xcc, 0x99 }
+	};
+
+	if (pattern >= ARRAYSIZE(fillPatterns))
+		error("Invalid fill pattern %i encountered in picture", pattern);
+
+	byte offset = (p.y & 1) << 1;
+	offset += (p.x / 7) & 3;
+
+	return fillPatterns[pattern][offset % sizeof(fillPatterns[0])];
+}
+
+template <class T>
+void GraphicsMan_v2<T>::drawCorners(Common::SeekableReadStream &pic, bool yFirst) {
+	Common::Point p;
+
+	if (!readPoint(pic, p))
+		return;
+
+	if (yFirst)
+		goto doYStep;
+
+	while (true) {
+		byte b;
+		int16 n;
+
+		if (!readByte(pic, b))
+			return;
+
+		n = b + _offset.x;
+
+		putPixel(p, _color);
+
+		n <<= 1;
+		drawLine(p, Common::Point(n, p.y), _color);
+		p.x = n;
+
+doYStep:
+		if (!readByte(pic, b))
+			return;
+
+		n = b + _offset.y;
+
+		putPixel(p, _color);
+		drawLine(p, Common::Point(p.x, n), _color);
+
+		putPixel(Common::Point(p.x + 1, p.y), _color);
+		drawLine(Common::Point(p.x + 1, p.y), Common::Point(p.x + 1, n), _color);
+
+		p.y = n;
+	}
+}
+
+template <class T>
+void GraphicsMan_v2<T>::drawRelativeLines(Common::SeekableReadStream &pic) {
+	Common::Point p1;
+
+	if (!readPoint(pic, p1))
+		return;
+
+	putPixel(p1, _color);
+
+	while (true) {
+		Common::Point p2(p1);
+
+		byte n;
+
+		if (!readByte(pic, n))
+			return;
+
+		byte h = (n & 0x70) >> 4;
+		byte l = n & 7;
+
+		if (n & 0x80)
+			p2.x -= (h << 1);
+		else
+			p2.x += (h << 1);
+
+		if (n & 8)
+			p2.y -= l;
+		else
+			p2.y += l;
+
+		drawLine(p1, p2, _color);
+		p1 = p2;
+	}
+}
+
+template <class T>
+void GraphicsMan_v2<T>::drawAbsoluteLines(Common::SeekableReadStream &pic) {
+	Common::Point p1;
+
+	if (!readPoint(pic, p1))
+		return;
+
+	putPixel(p1, _color);
+
+	while (true) {
+		Common::Point p2;
+
+		if (!readPoint(pic, p2))
+			return;
+
+		drawLine(p1, p2, _color);
+		p1 = p2;
+	}
+}
+
+template <class T>
+bool GraphicsMan_v2<T>::canFillAt(const Common::Point &p, const bool stopBit) {
+	return _display.getPixelBit(p) != stopBit && _display.getPixelBit(Common::Point(p.x + 1, p.y)) != stopBit;
+}
+
+template <class T>
+void GraphicsMan_v2<T>::fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) {
+	byte color = getPatternColor(p, pattern);
+
+	while (--p.x >= _bounds.left) {
+		if ((p.x % 7) == 6) {
+			color = getPatternColor(p, pattern);
+			_display.setPixelPalette(p, color);
+		}
+		if (_display.getPixelBit(p) == stopBit)
+			break;
+		_display.setPixelBit(p, color);
+	}
+}
+
+template <class T>
+void GraphicsMan_v2<T>::fillRow(Common::Point p, const byte pattern, const bool stopBit) {
+	// Set pixel at p and palette
+	byte color = getPatternColor(p, pattern);
+	_display.setPixelPalette(p, color);
+	_display.setPixelBit(p, color);
+
+	// Fill left of p
+	fillRowLeft(p, pattern, stopBit);
+
+	// Fill right of p
+	while (++p.x < _bounds.right) {
+		if ((p.x % 7) == 0) {
+			color = getPatternColor(p, pattern);
+			// Palette is set before the first bit is tested
+			_display.setPixelPalette(p, color);
+		}
+		if (_display.getPixelBit(p) == stopBit)
+			break;
+		_display.setPixelBit(p, color);
+	}
+}
+
+template <class T>
+void GraphicsMan_v2<T>::fillAt(Common::Point p, const byte pattern) {
+	const bool stopBit = !_display.getPixelBit(p);
+
+	// Move up into the open space above p
+	while (--p.y >= _bounds.top && canFillAt(p, stopBit)) {}
+
+	// Then fill by moving down
+	while (++p.y < _bounds.bottom && canFillAt(p, stopBit))
+		fillRow(p, pattern, stopBit);
+}
+
+template <class T>
+void GraphicsMan_v2<T>::fill(Common::SeekableReadStream &pic) {
+	byte pattern;
+
+	if (!readByte(pic, pattern))
+		return;
+
+	while (true) {
+		Common::Point p;
+
+		if (!readPoint(pic, p))
+			return;
+
+		if (_bounds.contains(p))
+			fillAt(p, pattern);
+	}
+}
+
+template <class T>
+void GraphicsMan_v2<T>::drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) {
+	// NOTE: The original engine only resets the color for overlays. As a result, room
+	// pictures that draw without setting a color or clearing the screen, will use the
+	// last color set by the previous picture. We assume this is unintentional and do
+	// not copy this behavior.
+	_color = 0;
+	_offset = pos;
+
+	while (true) {
+		byte opcode = pic.readByte();
+
+		if (pic.eos() || pic.err())
+			error("Error reading picture");
+
+		switch (opcode) {
+		case 0xe0:
+			drawCorners(pic, false);
+			break;
+		case 0xe1:
+			drawCorners(pic, true);
+			break;
+		case 0xe2:
+			drawRelativeLines(pic);
+			break;
+		case 0xe3:
+			drawAbsoluteLines(pic);
+			break;
+		case 0xe4:
+			fill(pic);
+			break;
+		case 0xe5:
+			this->clearScreen();
+			_color = 0x00;
+			break;
+		case 0xf0:
+			_color = 0x00;
+			break;
+		case 0xf1:
+			_color = 0x2a;
+			break;
+		case 0xf2:
+			_color = 0x55;
+			break;
+		case 0xf3:
+			_color = 0x7f;
+			break;
+		case 0xf4:
+			_color = 0x80;
+			break;
+		case 0xf5:
+			_color = 0xaa;
+			break;
+		case 0xf6:
+			_color = 0xd5;
+			break;
+		case 0xf7:
+			_color = 0xff;
+			break;
+		case 0xff:
+			return;
+		default:
+			if (opcode >= 0xe0)
+				error("Invalid pic opcode %02x", opcode);
+			else
+				warning("Expected pic opcode, but found data byte %02x", opcode);
+		}
+	}
+}
+
+template <class T>
+void GraphicsMan_v3<T>::fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) {
+	byte color = getPatternColor(p, pattern);
+
+	while (--p.x >= _bounds.left) {
+		// In this version, when moving left, it no longer sets the palette first
+		if (!_display.getPixelBit(p))
+			return;
+		if ((p.x % 7) == 6) {
+			color = getPatternColor(p, pattern);
+			_display.setPixelPalette(p, color);
+		}
+		_display.setPixelBit(p, color);
+	}
+}
+
+template <class T>
+void GraphicsMan_v3<T>::fillAt(Common::Point p, const byte pattern) {
+	// If the row at p cannot be filled, we do nothing
+	if (!canFillAt(p))
+			return;
+
+	fillRow(p, pattern);
+
+	Common::Point q(p);
+
+	// Fill up from p
+	while (--q.y >= _bounds.top && canFillAt(q))
+		fillRow(q, pattern);
+
+	// Fill down from p
+	while (++p.y < _bounds.bottom && canFillAt(p))
+		fillRow(p, pattern);
+}
+
 } // End of namespace Adl
 
 #endif
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index 2cf2931..c045ce9 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -29,7 +29,7 @@
 
 #include "adl/adl.h"
 #include "adl/graphics.h"
-#include "adl/display.h"
+#include "adl/display_a2.h"
 
 namespace Adl {
 
@@ -126,7 +126,7 @@ private:
 };
 
 void HiRes1Engine::showInstructions(Common::SeekableReadStream &stream, const uint pages[], bool goHome) {
-	_display->setMode(DISPLAY_MODE_TEXT);
+	_display->setMode(Display::kModeText);
 
 	uint page = 0;
 	while (pages[page] != 0) {
@@ -154,9 +154,9 @@ void HiRes1Engine::runIntro() {
 	// Early version have no bitmap in 'AUTO LOAD OBJ'
 	if (getGameVersion() >= GAME_VER_HR1_COARSE) {
 		stream->seek(IDI_HR1_OFS_LOGO_0);
-		_display->setMode(DISPLAY_MODE_HIRES);
-		_display->loadFrameBuffer(*stream);
-		_display->updateHiResScreen();
+		_display->setMode(Display::kModeGraphics);
+		static_cast<Display_A2 *>(_display)->loadFrameBuffer(*stream);
+		_display->copyGfxSurface();
 
 		if (getGameVersion() == GAME_VER_HR1_PD) {
 			// Only the PD version shows a title screen during the load
@@ -177,7 +177,7 @@ void HiRes1Engine::runIntro() {
 		// was present in the original PD release back in 1987.
 		StreamPtr basic(_files->createReadStream("MYSTERY.HELLO"));
 
-		_display->setMode(DISPLAY_MODE_TEXT);
+		_display->setMode(Display::kModeText);
 		_display->home();
 
 		str = readStringAt(*basic, IDI_HR1_OFS_PD_TEXT_0, '"');
@@ -197,7 +197,7 @@ void HiRes1Engine::runIntro() {
 			return;
 	}
 
-	_display->setMode(DISPLAY_MODE_MIXED);
+	_display->setMode(Display::kModeMixed);
 
 	str = readStringAt(*stream, IDI_HR1_OFS_GAME_OR_HELP);
 
@@ -238,10 +238,10 @@ void HiRes1Engine::runIntro() {
 
 	stream.reset(_files->createReadStream(IDS_HR1_EXE_1));
 	stream->seek(0x1800);
-	_display->loadFrameBuffer(*stream);
-	_display->updateHiResScreen();
+	static_cast<Display_A2 *>(_display)->loadFrameBuffer(*stream);
+	_display->copyGfxSurface();
 
-	_display->setMode(DISPLAY_MODE_MIXED);
+	_display->setMode(Display::kModeMixed);
 
 	if (getGameVersion() == GAME_VER_HR1_SIMI) {
 		// The original waits for the key after initializing the state.
@@ -268,7 +268,7 @@ void HiRes1Engine::init() {
 		_files = files;
 	}
 
-	_graphics = new GraphicsMan(*_display);
+	_graphics = new GraphicsMan_v1<Display_A2>(*static_cast<Display_A2 *>(_display));
 	_display->moveCursorTo(Common::Point(0, 3));
 
 	StreamPtr stream(_files->createReadStream(IDS_HR1_EXE_1));
@@ -478,7 +478,7 @@ void HiRes1Engine::showRoom() {
 		drawItems();
 	}
 
-	_display->updateHiResScreen();
+	_display->copyGfxSurface();
 	_messageDelay = false;
 	printString(_roomData.description);
 	_messageDelay = true;
diff --git a/engines/adl/hires2.cpp b/engines/adl/hires2.cpp
index 4575cf6..4dbda10 100644
--- a/engines/adl/hires2.cpp
+++ b/engines/adl/hires2.cpp
@@ -27,7 +27,7 @@
 #include "common/stream.h"
 
 #include "adl/adl_v2.h"
-#include "adl/display.h"
+#include "adl/display_a2.h"
 #include "adl/graphics.h"
 #include "adl/disk.h"
 
@@ -59,7 +59,7 @@ HiResBaseEngine::HiResBaseEngine(OSystem *syst, const AdlGameDescription *gd, co
 }
 
 void HiResBaseEngine::init() {
-	_graphics = new GraphicsMan_v2(*_display);
+	_graphics = new GraphicsMan_v2<Display_A2>(*static_cast<Display_A2 *>(_display));
 
 	_disk = new DiskImage();
 	if (!_disk->open(getDiskImageName(0)))
@@ -157,7 +157,7 @@ void HiRes2Engine::runIntro() {
 	_disk->setSectorLimit(0);
 	StreamPtr stream(_disk->createReadStream(0x00, 0xd, 0x17, 1));
 
-	_display->setMode(DISPLAY_MODE_TEXT);
+	_display->setMode(Display::kModeText);
 
 	Common::String str = readString(*stream);
 
diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp
index ef1b184..d914661 100644
--- a/engines/adl/hires4.cpp
+++ b/engines/adl/hires4.cpp
@@ -30,7 +30,7 @@
 
 #include "adl/adl_v3.h"
 #include "adl/detection.h"
-#include "adl/display.h"
+#include "adl/display_a2.h"
 #include "adl/graphics.h"
 #include "adl/disk.h"
 
@@ -134,7 +134,7 @@ void HiRes4Engine::putSpace(uint x, uint y) const {
 
 	_display->moveCursorTo(Common::Point(x, y));
 	_display->printChar(' ');
-	_display->updateTextScreen();
+	_display->copyTextSurface();
 	delay(2);
 }
 
@@ -167,7 +167,7 @@ void HiRes4Engine::drawText(const Common::String &str, Common::SeekableReadStrea
 		drawChar(c, shapeTable, pos);
 		drawChar(98, shapeTable, pos);
 
-		_display->updateHiResScreen();
+		_display->copyGfxSurface();
 		delay(15);
 	}
 }
@@ -179,7 +179,7 @@ void HiRes4Engine::runIntroAdvise(Common::SeekableReadStream &menu) {
 	backupText.push_back(readStringAt(menu, 0x6a9, '"'));
 	backupText.push_back(readStringAt(menu, 0x6c6, '"'));
 
-	_display->setMode(DISPLAY_MODE_TEXT);
+	_display->setMode(Display::kModeText);
 
 	for (uint x = 2; x <= 36; ++x)
 		putSpace(x, 2);
@@ -223,7 +223,7 @@ void HiRes4Engine::runIntroAdvise(Common::SeekableReadStream &menu) {
 			_display->printAsciiString(left);
 			_display->moveCursorTo(Common::Point(19, y));
 			_display->printAsciiString(right);
-			_display->updateTextScreen();
+			_display->copyTextSurface();
 			delay(35);
 		} while (x != backupText[i].size() / 2);
 
@@ -245,26 +245,31 @@ void HiRes4Engine::runIntroAdvise(Common::SeekableReadStream &menu) {
 
 		_display->moveCursorTo(Common::Point(32, 18));
 		_display->printChar(APPLECHAR(cursor[cursorIdx]));
-		_display->updateTextScreen();
+		_display->copyTextSurface();
 		g_system->delayMillis(25);
 		cursorIdx = (cursorIdx + 1) % cursor.size();
 	}
 }
 
 void HiRes4Engine::runIntroLogo(Common::SeekableReadStream &ms2) {
-	_display->clear(0x00);
-	_display->setMode(DISPLAY_MODE_HIRES);
-	byte *logo = new byte[DISPLAY_SIZE];
-	Display::loadFrameBuffer(ms2, logo);
-
-	for (uint x = 0; x < DISPLAY_WIDTH; ++x) {
-		for (uint y = 0; y < DISPLAY_HEIGHT; ++y) {
-			const byte p = logo[y * DISPLAY_PITCH + x / 7];
-			_display->setPixelBit(Common::Point(x, y), p);
+	Display_A2 *display = static_cast<Display_A2 *>(_display);
+	const uint width = display->getGfxWidth();
+	const uint height = display->getGfxHeight();
+	const uint pitch = display->getGfxPitch();
+
+	display->clear(0x00);
+	display->setMode(Display::kModeGraphics);
+	byte *logo = new byte[pitch * height];
+	display->loadFrameBuffer(ms2, logo);
+
+	for (uint x = 0; x < width; ++x) {
+		for (uint y = 0; y < height; ++y) {
+			const byte p = logo[y * pitch + x / 7];
+			display->setPixelBit(Common::Point(x, y), p);
 			if (x % 7 == 6)
-				_display->setPixelPalette(Common::Point(x, y), p);
+				display->setPixelPalette(Common::Point(x, y), p);
 		}
-		_display->updateHiResScreen();
+		display->copyGfxSurface();
 
 		if (shouldQuit()) {
 			delete[] logo;
@@ -279,11 +284,11 @@ void HiRes4Engine::runIntroLogo(Common::SeekableReadStream &ms2) {
 	for (uint i = 38; i != 0; --i) {
 		Common::Point p;
 
-		for (p.y = 1; p.y < DISPLAY_HEIGHT; ++p.y)
-			for (p.x = 0; p.x < DISPLAY_WIDTH; p.x += 7)
-				_display->setPixelByte(Common::Point(p.x, p.y - 1), _display->getPixelByte(p));
+		for (p.y = 1; p.y < (int)height; ++p.y)
+			for (p.x = 0; p.x < (int)width; p.x += 7)
+				display->setPixelByte(Common::Point(p.x, p.y - 1), display->getPixelByte(p));
 
-		_display->updateHiResScreen();
+		display->copyGfxSurface();
 
 		Tones tone;
 		tone.push_back(Tone(kClock / 2.0 / ((i * 4 + 1) * 10.0 + 10.0), 12.5));
@@ -309,13 +314,13 @@ void HiRes4Engine::runIntroTitle(Common::SeekableReadStream &menu, Common::Seeka
 	// Draw "TM" with lines
 	_graphics->drawLine(Common::Point(200, 170), Common::Point(200, 174), 0x7f);
 	_graphics->drawLine(Common::Point(198, 170), Common::Point(202, 170), 0x7f);
-	_display->updateHiResScreen();
+	_display->copyGfxSurface();
 	delay(7);
 	_graphics->drawLine(Common::Point(204, 170), Common::Point(204, 174), 0x7f);
 	_graphics->drawLine(Common::Point(204, 170), Common::Point(207, 173), 0x7f);
 	_graphics->drawLine(Common::Point(207, 173), Common::Point(209, 170), 0x7f);
 	_graphics->drawLine(Common::Point(209, 170), Common::Point(209, 174), 0x7f);
-	_display->updateHiResScreen();
+	_display->copyGfxSurface();
 	delay(7);
 
 	titleString = readStringAt(menu, 0x46c);
@@ -341,7 +346,7 @@ void HiRes4Engine::runIntroInstructions(Common::SeekableReadStream &instructions
 	instructions.seek(0);
 
 	_display->home();
-	_display->setMode(DISPLAY_MODE_TEXT);
+	_display->setMode(Display::kModeText);
 
 	// Search for PRINT commands in tokenized BASIC
 	while (1) {
@@ -397,7 +402,7 @@ void HiRes4Engine::runIntroInstructions(Common::SeekableReadStream &instructions
 
 void HiRes4Engine::runIntroLoading(Common::SeekableReadStream &adventure) {
 	_display->home();
-	_display->setMode(DISPLAY_MODE_TEXT);
+	_display->setMode(Display::kModeText);
 
 	const uint kStrings = 4;
 	const uint kStringLen = 39;
@@ -459,7 +464,7 @@ void HiRes4Engine::runIntro() {
 }
 
 void HiRes4Engine::init() {
-	_graphics = new GraphicsMan_v2(*_display);
+	_graphics = new GraphicsMan_v2<Display_A2>(*static_cast<Display_A2 *>(_display));
 
 	_boot = new DiskImage();
 	if (!_boot->open(getDiskImageName(0)))
@@ -573,7 +578,7 @@ HiRes4Engine_Atari::~HiRes4Engine_Atari() {
 }
 
 void HiRes4Engine_Atari::init() {
-	_graphics = new GraphicsMan_v2(*_display);
+	_graphics = new GraphicsMan_v2<Display_A2>(*static_cast<Display_A2 *>(_display));
 
 	_boot = new DiskImage();
 	if (!_boot->open(atariDisks[0]))
diff --git a/engines/adl/hires5.cpp b/engines/adl/hires5.cpp
index cf09ceb..2fdb9fd 100644
--- a/engines/adl/hires5.cpp
+++ b/engines/adl/hires5.cpp
@@ -28,7 +28,7 @@
 
 #include "adl/adl_v4.h"
 #include "adl/detection.h"
-#include "adl/display.h"
+#include "adl/display_a2.h"
 #include "adl/graphics.h"
 #include "adl/disk.h"
 #include "adl/sound.h"
@@ -87,6 +87,7 @@ Common::String HiRes5Engine::getLine() {
 }
 
 void HiRes5Engine::drawLight(uint index, byte color) const {
+	Display_A2 *display = static_cast<Display_A2 *>(_display);
 	const byte xCoord[5] = { 189, 161, 133, 105, 77 };
 	const byte yCoord = 72;
 
@@ -94,9 +95,9 @@ void HiRes5Engine::drawLight(uint index, byte color) const {
 
 	for (int yDelta = 0; yDelta < 4; ++yDelta)
 		for (int xDelta = 0; xDelta < 7; ++xDelta)
-			_display->putPixel(Common::Point(xCoord[index] + xDelta, yCoord + yDelta), color);
+			display->putPixel(Common::Point(xCoord[index] + xDelta, yCoord + yDelta), color);
 
-	_display->updateHiResScreen();
+	display->copyGfxSurface();
 }
 
 void HiRes5Engine::animateLights() const {
@@ -235,25 +236,27 @@ int HiRes5Engine::o_winGame(ScriptEnv &e) {
 }
 
 void HiRes5Engine::runIntro() {
+	Display_A2 *display = static_cast<Display_A2 *>(_display);
+
 	insertDisk(2);
 
 	StreamPtr stream(_disk->createReadStream(0x10, 0x0, 0x00, 31));
 
-	_display->setMode(DISPLAY_MODE_HIRES);
-	_display->loadFrameBuffer(*stream);
-	_display->updateHiResScreen();
+	display->setMode(Display::kModeGraphics);
+	display->loadFrameBuffer(*stream);
+	display->copyGfxSurface();
 
 	inputKey();
 
-	_display->home();
-	_display->setMode(DISPLAY_MODE_TEXT);
+	display->home();
+	display->setMode(Display::kModeText);
 
 	stream.reset(_disk->createReadStream(0x03, 0xc, 0x34, 1));
 	Common::String menu(readString(*stream));
 
 	while (!g_engine->shouldQuit()) {
-		_display->home();
-		_display->printString(menu);
+		display->home();
+		display->printString(menu);
 
 		Common::String cmd(inputString());
 
@@ -264,7 +267,7 @@ void HiRes5Engine::runIntro() {
 }
 
 void HiRes5Engine::init() {
-	_graphics = new GraphicsMan_v3(*_display);
+	_graphics = new GraphicsMan_v3<Display_A2>(*static_cast<Display_A2 *>(_display));
 
 	insertDisk(2);
 
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index 5cbca1c..b34a53e 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -28,7 +28,7 @@
 #include "common/memstream.h"
 
 #include "adl/adl_v5.h"
-#include "adl/display.h"
+#include "adl/display_a2.h"
 #include "adl/graphics.h"
 #include "adl/disk.h"
 
@@ -192,20 +192,22 @@ static Common::MemoryReadStream *loadSectors(DiskImage *disk, byte track, byte s
 }
 
 void HiRes6Engine::runIntro() {
+	Display_A2 *display = static_cast<Display_A2 *>(_display);
+
 	insertDisk(0);
 
 	StreamPtr stream(loadSectors(_disk, 11, 1, 96));
 
-	_display->setMode(DISPLAY_MODE_HIRES);
-	_display->loadFrameBuffer(*stream);
-	_display->updateHiResScreen();
+	display->setMode(Display::kModeGraphics);
+	display->loadFrameBuffer(*stream);
+	display->copyGfxSurface();
 	delay(256 * 8609 / 1000);
 
-	_display->loadFrameBuffer(*stream);
-	_display->updateHiResScreen();
+	display->loadFrameBuffer(*stream);
+	display->copyGfxSurface();
 	delay(256 * 8609 / 1000);
 
-	_display->loadFrameBuffer(*stream);
+	display->loadFrameBuffer(*stream);
 
 	// Load copyright string from boot file
 	Files_AppleDOS *files(new Files_AppleDOS());
@@ -218,16 +220,16 @@ void HiRes6Engine::runIntro() {
 
 	delete files;
 
-	_display->updateHiResScreen();
-	_display->home();
-	_display->setMode(DISPLAY_MODE_MIXED);
-	_display->moveCursorTo(Common::Point(0, 21));
-	_display->printString(copyright);
+	display->copyGfxSurface();
+	display->home();
+	display->setMode(Display::kModeMixed);
+	display->moveCursorTo(Common::Point(0, 21));
+	display->printString(copyright);
 	delay(256 * 8609 / 1000);
 }
 
 void HiRes6Engine::init() {
-	_graphics = new GraphicsMan_v3(*_display);
+	_graphics = new GraphicsMan_v3<Display_A2>(*static_cast<Display_A2 *>(_display));
 
 	insertDisk(0);
 
@@ -326,7 +328,7 @@ void HiRes6Engine::showRoom() {
 	if (!_state.isDark)
 		drawItems();
 
-	_display->updateHiResScreen();
+	_display->copyGfxSurface();
 	setVar(2, 0xff);
 	printString(_roomData.description);
 }
diff --git a/engines/adl/module.mk b/engines/adl/module.mk
index 30c64b5..4507206 100644
--- a/engines/adl/module.mk
+++ b/engines/adl/module.mk
@@ -10,7 +10,7 @@ MODULE_OBJS := \
 	detection.o \
 	disk.o \
 	display.o \
-	graphics.o \
+	display_a2.o \
 	hires1.o \
 	hires2.o \
 	hires4.o \


Commit: ce8a8409332ff28a80de918a5771baa20d6980d1
    https://github.com/scummvm/scummvm/commit/ce8a8409332ff28a80de918a5771baa20d6980d1
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2019-07-16T16:24:19+02:00

Commit Message:
ADL: Remove APPLECHAR macro

Changed paths:
    engines/adl/adl.cpp
    engines/adl/adl_v2.cpp
    engines/adl/adl_v4.cpp
    engines/adl/adl_v5.cpp
    engines/adl/console.cpp
    engines/adl/console.h
    engines/adl/display.cpp
    engines/adl/display.h
    engines/adl/display_a2.cpp
    engines/adl/hires1.cpp
    engines/adl/hires4.cpp
    engines/adl/hires5.cpp
    engines/adl/hires6.cpp


diff --git a/engines/adl/adl.cpp b/engines/adl/adl.cpp
index 5da587f..f8d61e5 100644
--- a/engines/adl/adl.cpp
+++ b/engines/adl/adl.cpp
@@ -182,7 +182,7 @@ Common::String AdlEngine::inputString(byte prompt) const {
 			Common::String native;
 
 			for (uint i = 0; i < line.size(); ++i)
-				native += APPLECHAR(line[i]);
+				native += _display->asciiToNative(line[i]);
 
 			_display->printString(native);
 			// Set pause flag to activate regular behaviour of delay and inputKey
@@ -214,7 +214,7 @@ Common::String AdlEngine::inputString(byte prompt) const {
 			case Common::KEYCODE_BACKSPACE | 0x80:
 				if (!s.empty()) {
 					_display->moveCursorBackward();
-					_display->setCharAtCursor(APPLECHAR(' '));
+					_display->setCharAtCursor(_display->asciiToNative(' '));
 					s.deleteLastChar();
 				}
 				break;
@@ -233,7 +233,7 @@ byte AdlEngine::inputKey(bool showCursor) const {
 
 	// If debug script is active, we fake a return press for the text overflow handling
 	if (_inputScript && !_scriptPaused)
-		return APPLECHAR('\r');
+		return _display->asciiToNative('\r');
 
 	if (showCursor)
 		_display->showCursor(true);
@@ -257,7 +257,7 @@ byte AdlEngine::inputKey(bool showCursor) const {
 
 		// If debug script was activated in the meantime, abort input
 		if (_inputScript && !_scriptPaused)
-			return APPLECHAR('\r');
+			return _display->asciiToNative('\r');
 
 		_display->copyTextSurface();
 		g_system->delayMillis(16);
@@ -991,7 +991,7 @@ byte AdlEngine::convertKey(uint16 ascii) const {
 
 Common::String AdlEngine::getLine() {
 	while (1) {
-		Common::String line = inputString(APPLECHAR('?'));
+		Common::String line = inputString(_display->asciiToNative('?'));
 
 		if (shouldQuit() || _isRestoring)
 			return Common::String();
@@ -1010,9 +1010,10 @@ Common::String AdlEngine::getLine() {
 
 Common::String AdlEngine::getWord(const Common::String &line, uint &index) const {
 	Common::String str;
+	const char spaceChar = _display->asciiToNative(' ');
 
 	for (uint i = 0; i < 8; ++i)
-		str += APPLECHAR(' ');
+		str += spaceChar;
 
 	int copied = 0;
 
@@ -1020,7 +1021,7 @@ Common::String AdlEngine::getWord(const Common::String &line, uint &index) const
 	while (1) {
 		if (index == line.size())
 			return str;
-		if (line[index] != APPLECHAR(' '))
+		if (line[index] != spaceChar)
 			break;
 		++index;
 	}
@@ -1032,7 +1033,7 @@ Common::String AdlEngine::getWord(const Common::String &line, uint &index) const
 
 		index++;
 
-		if (index == line.size() || line[index] == APPLECHAR(' '))
+		if (index == line.size() || line[index] == spaceChar)
 			return str;
 	}
 }
@@ -1249,7 +1250,7 @@ int AdlEngine::o_restart(ScriptEnv &e) {
 	_display->printString(_strings.playAgain);
 	Common::String input = inputString();
 
-	if (input.size() == 0 || input[0] != APPLECHAR('N')) {
+	if (input.size() == 0 || input[0] != _display->asciiToNative('N')) {
 		_isRestarting = true;
 		_graphics->clearScreen();
 		_display->copyGfxSurface();
diff --git a/engines/adl/adl_v2.cpp b/engines/adl/adl_v2.cpp
index aed38be..81ff145 100644
--- a/engines/adl/adl_v2.cpp
+++ b/engines/adl/adl_v2.cpp
@@ -101,7 +101,7 @@ void AdlEngine_v2::advanceClock() {
 }
 
 void AdlEngine_v2::checkTextOverflow(char c) {
-	if (c != APPLECHAR('\r'))
+	if (c != _display->asciiToNative('\r'))
 		return;
 
 	++_linesPrinted;
@@ -135,7 +135,7 @@ void AdlEngine_v2::handleTextOverflow() {
 		if (shouldQuit())
 			return;
 
-		if (key == APPLECHAR('\r'))
+		if (key == _display->asciiToNative('\r'))
 			break;
 
 		bell(3);
@@ -158,16 +158,19 @@ void AdlEngine_v2::printString(const Common::String &str) {
 	uint startPos = 0;
 	uint pos = 0;
 
+	const char spaceChar = _display->asciiToNative(' ');
+	const char returnChar = _display->asciiToNative('\r');
+
 	while (pos < s.size()) {
-		s.setChar(APPLECHAR(s[pos]), pos);
+		s.setChar(_display->asciiToNative(s[pos]), pos);
 
 		if (pos == endPos) {
-			while (s[pos] != APPLECHAR(' ') && s[pos] != APPLECHAR('\r')) {
+			while (s[pos] != spaceChar && s[pos] != returnChar) {
 				if (pos-- == startPos)
 					error("Word wrapping failed");
 			}
 
-			s.setChar(APPLECHAR('\r'), pos);
+			s.setChar(returnChar, pos);
 			endPos = pos + textWidth;
 			startPos = pos + 1;
 		}
@@ -180,8 +183,8 @@ void AdlEngine_v2::printString(const Common::String &str) {
 		_display->printChar(s[pos]);
 	}
 
-	checkTextOverflow(APPLECHAR('\r'));
-	_display->printChar(APPLECHAR('\r'));
+	checkTextOverflow(returnChar);
+	_display->printChar(returnChar);
 	_display->copyTextSurface();
 }
 
@@ -565,10 +568,12 @@ int AdlEngine_v2::o_tellTime(ScriptEnv &e) {
 
 	Common::String time = _strings_v2.time;
 
-	time.setChar(APPLECHAR('0') + _state.time.hours / 10, 12);
-	time.setChar(APPLECHAR('0') + _state.time.hours % 10, 13);
-	time.setChar(APPLECHAR('0') + _state.time.minutes / 10, 15);
-	time.setChar(APPLECHAR('0') + _state.time.minutes % 10, 16);
+	const char zeroChar = _display->asciiToNative('0');
+
+	time.setChar(zeroChar + _state.time.hours / 10, 12);
+	time.setChar(zeroChar + _state.time.hours % 10, 13);
+	time.setChar(zeroChar + _state.time.minutes / 10, 15);
+	time.setChar(zeroChar + _state.time.minutes % 10, 16);
 
 	printString(time);
 
@@ -611,8 +616,8 @@ int AdlEngine_v2::askForSlot(const Common::String &question) {
 		if (shouldQuit())
 			return -1;
 
-		if (input.size() > 0 && input[0] >= APPLECHAR('A') && input[0] <= APPLECHAR('O'))
-			return input[0] - APPLECHAR('A');
+		if (input.size() > 0 && input[0] >= _display->asciiToNative('A') && input[0] <= _display->asciiToNative('O'))
+			return input[0] - _display->asciiToNative('A');
 	}
 }
 
diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp
index dabee63..3571ec3 100644
--- a/engines/adl/adl_v4.cpp
+++ b/engines/adl/adl_v4.cpp
@@ -528,7 +528,7 @@ int AdlEngine_v4::o_save(ScriptEnv &e) {
 	if (shouldQuit())
 		return -1;
 
-	if (key != APPLECHAR('Y'))
+	if (key != _display->asciiToNative('Y'))
 		return 0;
 
 	const int slot = askForSlot(_strings_v2.saveInsert);
@@ -569,9 +569,9 @@ int AdlEngine_v4::o_restart(ScriptEnv &e) {
 		if (shouldQuit())
 			return -1;
 
-		if (input.firstChar() == APPLECHAR('N')) {
+		if (input.firstChar() == _display->asciiToNative('N')) {
 			return o_quit(e);
-		} else if (input.firstChar() == APPLECHAR('Y')) {
+		} else if (input.firstChar() == _display->asciiToNative('Y')) {
 			// The original game loads a special save game from volume 3
 			initState();
 			// Long jump
diff --git a/engines/adl/adl_v5.cpp b/engines/adl/adl_v5.cpp
index 9a970d9..a075356 100644
--- a/engines/adl/adl_v5.cpp
+++ b/engines/adl/adl_v5.cpp
@@ -115,7 +115,7 @@ int AdlEngine_v5::o_setTextMode(ScriptEnv &e) {
 	switch (e.arg(1)) {
 	case 1:
 		if (_linesPrinted != 0) {
-			_display->printChar(APPLECHAR(' '));
+			_display->printChar(_display->asciiToNative(' '));
 			handleTextOverflow();
 			_display->moveCursorTo(Common::Point(0, 23));
 			_maxLines = 4;
diff --git a/engines/adl/console.cpp b/engines/adl/console.cpp
index 777c0a9..876389c 100644
--- a/engines/adl/console.cpp
+++ b/engines/adl/console.cpp
@@ -58,20 +58,20 @@ Common::String Console::toAscii(const Common::String &str) {
 	return ascii;
 }
 
-Common::String Console::toAppleWord(const Common::String &str) {
-	Common::String apple(str);
+Common::String Console::toNative(const Common::String &str) {
+	Common::String native(str);
 
-	if (apple.size() > IDI_WORD_SIZE)
-		apple.erase(IDI_WORD_SIZE);
-	apple.toUppercase();
+	if (native.size() > IDI_WORD_SIZE)
+		native.erase(IDI_WORD_SIZE);
+	native.toUppercase();
 
-	for (uint i = 0; i < apple.size(); ++i)
-		apple.setChar(APPLECHAR(apple[i]), i);
+	for (uint i = 0; i < native.size(); ++i)
+		native.setChar(_engine->_display->asciiToNative(native[i]), i);
 
-	while (apple.size() < IDI_WORD_SIZE)
-		apple += APPLECHAR(' ');
+	while (native.size() < IDI_WORD_SIZE)
+		native += _engine->_display->asciiToNative(' ');
 
-	return apple;
+	return native;
 }
 
 bool Console::Cmd_Verbs(int argc, const char **argv) {
@@ -270,7 +270,7 @@ bool Console::Cmd_GiveItem(int argc, const char **argv) {
 	if (*end != 0) {
 		Common::Array<Item *> matches;
 
-		Common::String name = toAppleWord(argv[1]);
+		Common::String name = toNative(argv[1]);
 
 		if (!_engine->_nouns.contains(name)) {
 			debugPrintf("Item '%s' not found\n", argv[1]);
diff --git a/engines/adl/console.h b/engines/adl/console.h
index db2e8ca..df4b2ae 100644
--- a/engines/adl/console.h
+++ b/engines/adl/console.h
@@ -41,7 +41,7 @@ public:
 	Console(AdlEngine *engine);
 
 	static Common::String toAscii(const Common::String &str);
-	static Common::String toAppleWord(const Common::String &str);
+	Common::String toNative(const Common::String &str);
 
 private:
 	bool Cmd_Nouns(int argc, const char **argv);
diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp
index f2285a7..736b094 100644
--- a/engines/adl/display.cpp
+++ b/engines/adl/display.cpp
@@ -53,7 +53,7 @@ void Display::createTextBuffer(uint textWidth, uint textHeight) {
 	_textHeight = textHeight;
 
 	_textBuf = new byte[textWidth * textHeight];
-	memset(_textBuf, asciiToNative(' '), textWidth * textHeight);
+	memset(_textBuf, (byte)asciiToNative(' '), textWidth * textHeight);
 }
 
 void Display::setMode(Display::Mode mode) {
@@ -88,7 +88,7 @@ void Display::copyGfxSurface() {
 }
 
 void Display::home() {
-	memset(_textBuf, asciiToNative(' '), _textWidth * _textHeight);
+	memset(_textBuf, (byte)asciiToNative(' '), _textWidth * _textHeight);
 	_cursorPos = 0;
 }
 
diff --git a/engines/adl/display.h b/engines/adl/display.h
index d4a30cf..a92993e 100644
--- a/engines/adl/display.h
+++ b/engines/adl/display.h
@@ -23,9 +23,6 @@
 #ifndef ADL_DISPLAY_H
 #define ADL_DISPLAY_H
 
-// REMOVE
-#define APPLECHAR(C) (char)(C | 0x80)
-
 #include "common/types.h"
 
 namespace Common {
diff --git a/engines/adl/display_a2.cpp b/engines/adl/display_a2.cpp
index 393e38b..bb0e6d9 100644
--- a/engines/adl/display_a2.cpp
+++ b/engines/adl/display_a2.cpp
@@ -239,9 +239,9 @@ void Display_A2::clear(byte color) {
 
 // FIXME: This does not currently update the surfaces
 void Display_A2::printChar(char c) {
-	if (c == APPLECHAR('\r'))
+	if (c == Display_A2::asciiToNative('\r'))
 		_cursorPos = (_cursorPos / Display_A2::kTextWidth + 1) * Display_A2::kTextWidth;
-	else if (c == APPLECHAR('\a')) {
+	else if (c == Display_A2::asciiToNative('\a')) {
 		copyTextSurface();
 		static_cast<AdlEngine *>(g_engine)->bell();
 	} else if ((byte)c < 0x80 || (byte)c >= 0xa0) {
diff --git a/engines/adl/hires1.cpp b/engines/adl/hires1.cpp
index c045ce9..169a0ea 100644
--- a/engines/adl/hires1.cpp
+++ b/engines/adl/hires1.cpp
@@ -214,10 +214,10 @@ void HiRes1Engine::runIntro() {
 			if (s.empty())
 				continue;
 
-			if (s[0] == APPLECHAR('I')) {
+			if (s[0] == _display->asciiToNative('I')) {
 				instructions = true;
 				break;
-			} else if (s[0] == APPLECHAR('G')) {
+			} else if (s[0] == _display->asciiToNative('G')) {
 				break;
 			}
 		}
@@ -397,8 +397,9 @@ void HiRes1Engine::printString(const Common::String &str) {
 }
 
 Common::String HiRes1Engine::loadMessage(uint idx) const {
+	const char returnChar = _display->asciiToNative('\r');
 	StreamPtr stream(_messages[idx]->createReadStream());
-	return readString(*stream, APPLECHAR('\r')) + APPLECHAR('\r');
+	return readString(*stream, returnChar) + returnChar;
 }
 
 void HiRes1Engine::printMessage(uint idx) {
@@ -487,14 +488,17 @@ void HiRes1Engine::showRoom() {
 void HiRes1Engine::wordWrap(Common::String &str) const {
 	uint end = 39;
 
+	const char spaceChar = _display->asciiToNative(' ');
+	const char returnChar = _display->asciiToNative('\r');
+
 	while (1) {
 		if (str.size() <= end)
 			return;
 
-		while (str[end] != APPLECHAR(' '))
+		while (str[end] != spaceChar)
 			--end;
 
-		str.setChar(APPLECHAR('\r'), end);
+		str.setChar(returnChar, end);
 		end += 40;
 	}
 }
diff --git a/engines/adl/hires4.cpp b/engines/adl/hires4.cpp
index d914661..5171685 100644
--- a/engines/adl/hires4.cpp
+++ b/engines/adl/hires4.cpp
@@ -244,7 +244,7 @@ void HiRes4Engine::runIntroAdvise(Common::SeekableReadStream &menu) {
 		}
 
 		_display->moveCursorTo(Common::Point(32, 18));
-		_display->printChar(APPLECHAR(cursor[cursorIdx]));
+		_display->printChar(_display->asciiToNative(cursor[cursorIdx]));
 		_display->copyTextSurface();
 		g_system->delayMillis(25);
 		cursorIdx = (cursorIdx + 1) % cursor.size();
@@ -450,11 +450,11 @@ void HiRes4Engine::runIntro() {
 			if (shouldQuit())
 				return;
 
-			if (key == APPLECHAR('1')) {
+			if (key == _display->asciiToNative('1')) {
 				StreamPtr instructions(files->createReadStream("INSTRUCTIONS"));
 				runIntroInstructions(*instructions);
 				break;
-			} else if (key == APPLECHAR('2')) {
+			} else if (key == _display->asciiToNative('2')) {
 				StreamPtr adventure(files->createReadStream("THE ADVENTURE"));
 				runIntroLoading(*adventure);
 				return;
diff --git a/engines/adl/hires5.cpp b/engines/adl/hires5.cpp
index 2fdb9fd..3709374 100644
--- a/engines/adl/hires5.cpp
+++ b/engines/adl/hires5.cpp
@@ -261,7 +261,7 @@ void HiRes5Engine::runIntro() {
 		Common::String cmd(inputString());
 
 		// We ignore the backup and format menu options
-		if (!cmd.empty() && cmd[0] == APPLECHAR('1'))
+		if (!cmd.empty() && cmd[0] == _display->asciiToNative('1'))
 			break;
 	};
 }
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index b34a53e..29d7ea3 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -216,7 +216,7 @@ void HiRes6Engine::runIntro() {
 		error("Failed to open disk volume 0");
 
 	stream.reset(files->createReadStream("\010\010\010\010\010\010"));
-	Common::String copyright(readStringAt(*stream, 0x103, APPLECHAR('\r')));
+	Common::String copyright(readStringAt(*stream, 0x103, _display->asciiToNative('\r')));
 
 	delete files;
 
@@ -339,13 +339,15 @@ Common::String HiRes6Engine::formatVerbError(const Common::String &verb) const {
 	for (uint i = 0; i < verb.size(); ++i)
 		err.setChar(verb[i], i + 24);
 
-	err.setChar(APPLECHAR(' '), 32);
+	const char spaceChar = _display->asciiToNative(' ');
+
+	err.setChar(spaceChar, 32);
 
 	uint i = 24;
-	while (err[i] != APPLECHAR(' '))
+	while (err[i] != spaceChar)
 		++i;
 
-	err.setChar(APPLECHAR('.'), i);
+	err.setChar(_display->asciiToNative('.'), i);
 
 	return err;
 }
@@ -356,16 +358,18 @@ Common::String HiRes6Engine::formatNounError(const Common::String &verb, const C
 	for (uint i = 0; i < noun.size(); ++i)
 		err.setChar(noun[i], i + 24);
 
+	const char spaceChar = _display->asciiToNative(' ');
+
 	for (uint  i = 35; i > 31; --i)
-		err.setChar(APPLECHAR(' '), i);
+		err.setChar(spaceChar, i);
 
 	uint i = 24;
-	while (err[i] != APPLECHAR(' '))
+	while (err[i] != spaceChar)
 		++i;
 
-	err.setChar(APPLECHAR('I'), i + 1);
-	err.setChar(APPLECHAR('S'), i + 2);
-	err.setChar(APPLECHAR('.'), i + 3);
+	err.setChar(_display->asciiToNative('I'), i + 1);
+	err.setChar(_display->asciiToNative('S'), i + 2);
+	err.setChar(_display->asciiToNative('.'), i + 3);
 
 	return err;
 }
@@ -409,7 +413,7 @@ void HiRes6Engine::printString(const Common::String &str) {
 	if (getVar(2) == 0xff) {
 		if (getVar(26) == 0) {
 			// This checks for special room description string " "
-			if (str.size() == 1 && APPLECHAR(str[0]) == APPLECHAR(' ')) {
+			if (str.size() == 1 && _display->asciiToNative(str[0]) == _display->asciiToNative(' ')) {
 				setVar(2, 160);
 			} else {
 				AdlEngine_v5::printString(s);


Commit: 39acda0c9fc0e9985a8eaac51c720470eb977c10
    https://github.com/scummvm/scummvm/commit/39acda0c9fc0e9985a8eaac51c720470eb977c10
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2019-07-16T16:24:20+02:00

Commit Message:
ADL: Clean up usage of override specifier

Changed paths:
    engines/adl/adl_v2.h
    engines/adl/adl_v3.h
    engines/adl/adl_v4.h
    engines/adl/adl_v5.h
    engines/adl/detection.cpp
    engines/adl/display_a2.h
    engines/adl/graphics.h
    engines/adl/hires6.cpp


diff --git a/engines/adl/adl_v2.h b/engines/adl/adl_v2.h
index 564b4dc..f244ac4 100644
--- a/engines/adl/adl_v2.h
+++ b/engines/adl/adl_v2.h
@@ -35,20 +35,20 @@ protected:
 	AdlEngine_v2(OSystem *syst, const AdlGameDescription *gd);
 
 	// AdlEngine
-	virtual void setupOpcodeTables();
-	virtual void initState();
-	byte roomArg(byte room) const;
-	void advanceClock();
-	virtual void printString(const Common::String &str);
-	virtual Common::String loadMessage(uint idx) const;
-	void drawItems();
-	void drawItem(Item &item, const Common::Point &pos);
-	void loadRoom(byte roomNr);
-	virtual void showRoom();
-	void takeItem(byte noun);
+	void setupOpcodeTables() override;
+	void initState() override;
+	byte roomArg(byte room) const override;
+	void advanceClock() override;
+	void printString(const Common::String &str) override;
+	Common::String loadMessage(uint idx) const override;
+	void drawItems() override;
+	void drawItem(Item &item, const Common::Point &pos) override;
+	void loadRoom(byte roomNr) override;
+	void showRoom() override;
+	void takeItem(byte noun) override;
 
 	// Engine
-	bool canSaveGameStateCurrently();
+	bool canSaveGameStateCurrently() override;
 
 	void insertDisk(byte volume);
 	virtual DataBlockPtr readDataBlockPtr(Common::ReadStream &f) const;
@@ -69,13 +69,13 @@ protected:
 	virtual int o_isNounNotInRoom(ScriptEnv &e);
 	virtual int o_isCarryingSomething(ScriptEnv &e);
 
-	virtual int o_moveItem(ScriptEnv &e) override;
-	virtual int o_setCurPic(ScriptEnv &e) override;
-	virtual int o_setPic(ScriptEnv &e) override;
+	int o_moveItem(ScriptEnv &e) override;
+	int o_setCurPic(ScriptEnv &e) override;
+	int o_setPic(ScriptEnv &e) override;
 	virtual int o_moveAllItems(ScriptEnv &e);
-	virtual int o_save(ScriptEnv &e) override;
-	virtual int o_restore(ScriptEnv &e) override ;
-	virtual int o_placeItem(ScriptEnv &e) override;
+	int o_save(ScriptEnv &e) override;
+	int o_restore(ScriptEnv &e) override ;
+	int o_placeItem(ScriptEnv &e) override;
 	virtual int o_tellTime(ScriptEnv &e);
 	virtual int o_setRoomFromVar(ScriptEnv &e);
 	virtual int o_initDisk(ScriptEnv &e);
diff --git a/engines/adl/adl_v3.h b/engines/adl/adl_v3.h
index 3bb8908..9d5cb00 100644
--- a/engines/adl/adl_v3.h
+++ b/engines/adl/adl_v3.h
@@ -35,11 +35,11 @@ protected:
 	AdlEngine_v3(OSystem *syst, const AdlGameDescription *gd);
 
 	// AdlEngine
-	Common::String getItemDescription(const Item &item) const;
+	Common::String getItemDescription(const Item &item) const override;
 
 	void loadItemDescriptions(Common::SeekableReadStream &stream, byte count);
 
-	virtual int o_isNounNotInRoom(ScriptEnv &e) override;
+	int o_isNounNotInRoom(ScriptEnv &e) override;
 
 	Common::Array<Common::String> _itemDesc;
 };
diff --git a/engines/adl/adl_v4.h b/engines/adl/adl_v4.h
index 0c90c02..f4ee8c9 100644
--- a/engines/adl/adl_v4.h
+++ b/engines/adl/adl_v4.h
@@ -49,17 +49,17 @@ protected:
 	AdlEngine_v4(OSystem *syst, const AdlGameDescription *gd);
 
 	// AdlEngine
-	virtual void setupOpcodeTables();
-	virtual void gameLoop();
-	virtual void loadState(Common::ReadStream &stream);
-	virtual void saveState(Common::WriteStream &stream);
-	virtual Common::String loadMessage(uint idx) const;
-	virtual Common::String getItemDescription(const Item &item) const;
-	virtual void switchRegion(byte region);
-	virtual void switchRoom(byte roomNr);
+	void setupOpcodeTables() override;
+	void gameLoop() override;
+	void loadState(Common::ReadStream &stream) override;
+	void saveState(Common::WriteStream &stream) override;
+	Common::String loadMessage(uint idx) const override;
+	Common::String getItemDescription(const Item &item) const override;
+	void switchRegion(byte region) override;
+	void switchRoom(byte roomNr) override;
 
 	// AdlEngine_v2
-	virtual void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const;
+	void adjustDataBlockPtr(byte &track, byte &sector, byte &offset, byte &size) const override;
 
 	enum RegionChunkType {
 		kRegionChunkUnknown,
@@ -85,17 +85,17 @@ protected:
 	void backupVars();
 	void restoreVars();
 
-	virtual int o_isItemInRoom(ScriptEnv &e) override;
+	int o_isItemInRoom(ScriptEnv &e) override;
 	virtual int o_isVarGT(ScriptEnv &e);
-	virtual int o_moveItem(ScriptEnv &e) override;
+	int o_moveItem(ScriptEnv &e) override;
 	virtual int o_setRegionToPrev(ScriptEnv &e);
-	virtual int o_moveAllItems(ScriptEnv &e) override;
+	int o_moveAllItems(ScriptEnv &e) override;
 	virtual int o_setRegion(ScriptEnv &e);
-	virtual int o_save(ScriptEnv &e) override;
-	virtual int o_restore(ScriptEnv &e) override;
-	virtual int o_restart(ScriptEnv &e) override;
+	int o_save(ScriptEnv &e) override;
+	int o_restore(ScriptEnv &e) override;
+	int o_restart(ScriptEnv &e) override;
 	virtual int o_setRegionRoom(ScriptEnv &e);
-	virtual int o_setRoomPic(ScriptEnv &e) override;
+	int o_setRoomPic(ScriptEnv &e) override;
 
 	Common::Array<RegionLocation> _regionLocations;
 	Common::Array<RegionInitDataOffset> _regionInitDataOffsets;
diff --git a/engines/adl/adl_v5.h b/engines/adl/adl_v5.h
index 536f664..70d5b4f 100644
--- a/engines/adl/adl_v5.h
+++ b/engines/adl/adl_v5.h
@@ -35,19 +35,19 @@ protected:
 	AdlEngine_v5(OSystem *syst, const AdlGameDescription *gd);
 
 	// AdlEngine
-	virtual void setupOpcodeTables();
+	void setupOpcodeTables() override;
 
 	// AdlEngine_v4
-	virtual RegionChunkType getRegionChunkType(const uint16 addr) const;
-	virtual void initRoomState(RoomState &roomState) const;
-	virtual byte restoreRoomState(byte room);
+	RegionChunkType getRegionChunkType(const uint16 addr) const override;
+	void initRoomState(RoomState &roomState) const override;
+	byte restoreRoomState(byte room) override;
 
-	virtual int o_isNounNotInRoom(ScriptEnv &e) override;
+	int o_isNounNotInRoom(ScriptEnv &e) override;
 	virtual int o_abortScript(ScriptEnv &e);
 	virtual int o_dummy(ScriptEnv &e);
 	virtual int o_setTextMode(ScriptEnv &e);
-	virtual int o_setRegionRoom(ScriptEnv &e) override;
-	virtual int o_setRoomPic(ScriptEnv &e) override;
+	int o_setRegionRoom(ScriptEnv &e) override;
+	int o_setRoomPic(ScriptEnv &e) override;
 };
 
 } // End of namespace Adl
diff --git a/engines/adl/detection.cpp b/engines/adl/detection.cpp
index 7d9b03f..4eaebc7 100644
--- a/engines/adl/detection.cpp
+++ b/engines/adl/detection.cpp
@@ -319,24 +319,24 @@ class AdlMetaEngine : public AdvancedMetaEngine {
 public:
 	AdlMetaEngine() : AdvancedMetaEngine(gameFileDescriptions, sizeof(AdlGameDescription), adlGames, optionsList) { }
 
-	const char *getName() const {
+	const char *getName() const override {
 		return "ADL";
 	}
 
-	const char *getOriginalCopyright() const {
+	const char *getOriginalCopyright() const override {
 		return "Copyright (C) Sierra On-Line";
 	}
 
-	bool hasFeature(MetaEngineFeature f) const;
-	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
-	int getMaximumSaveSlot() const { return 'O' - 'A'; }
-	SaveStateList listSaves(const char *target) const;
-	void removeSaveState(const char *target, int slot) const;
+	bool hasFeature(MetaEngineFeature f) const override;
+	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
+	int getMaximumSaveSlot() const override { return 'O' - 'A'; }
+	SaveStateList listSaves(const char *target) const override;
+	void removeSaveState(const char *target, int slot) const override;
 	ADDetectedGames detectGame(const Common::FSNode &parent, const FileMap &allFiles, Common::Language language, Common::Platform platform, const Common::String &extra) const override;
 
 	bool addFileProps(const FileMap &allFiles, Common::String fname, FilePropertiesMap &filePropsMap) const;
 
-	bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const;
+	bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
 };
 
 bool AdlMetaEngine::hasFeature(MetaEngineFeature f) const {
diff --git a/engines/adl/display_a2.h b/engines/adl/display_a2.h
index 5823c24..52c7970 100644
--- a/engines/adl/display_a2.h
+++ b/engines/adl/display_a2.h
@@ -41,8 +41,8 @@ public:
 		kTextHeight = 24
 	};
 
-	virtual void init() override;
-	virtual bool saveThumbnail(Common::WriteStream &out) override;
+	void init() override;
+	bool saveThumbnail(Common::WriteStream &out) override;
 
 	// Graphics
 	uint getGfxWidth() const { return kGfxWidth; }
@@ -59,14 +59,14 @@ public:
 	void clear(byte color);
 
 	// Text
-	virtual char asciiToNative(char c) const override { return c | 0x80; }
-	virtual void printChar(char c) override;
-	virtual void showCursor(bool enable);
+	char asciiToNative(char c) const override { return c | 0x80; }
+	void printChar(char c) override;
+	void showCursor(bool enable) override;
 
 private:
 	void writeFrameBuffer(const Common::Point &p, byte color, byte mask);
-	virtual void updateTextSurface() override;
-	virtual void updateGfxSurface() override;
+	void updateTextSurface() override;
+	void updateGfxSurface() override;
 
 	void showScanlines(bool enable);
 	void drawChar(byte c, int x, int y);
diff --git a/engines/adl/graphics.h b/engines/adl/graphics.h
index ad56281..d67ba82 100644
--- a/engines/adl/graphics.h
+++ b/engines/adl/graphics.h
@@ -54,10 +54,10 @@ public:
 
 	GraphicsMan_v1<T>(T &display) : _display(display) { this->setBounds(Common::Rect(280, 160)); }
 
-	virtual void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const override;
-	virtual void drawShape(Common::ReadStream &shape, Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const override;
-	virtual void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) override;
-	virtual void clearScreen() const override;
+	void drawLine(const Common::Point &p1, const Common::Point &p2, byte color) const override;
+	void drawShape(Common::ReadStream &shape, Common::Point &pos, byte rotation = 0, byte scaling = 1, byte color = 0x7f) const override;
+	void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) override;
+	void clearScreen() const override;
 
 protected:
 	T &_display;
@@ -78,7 +78,7 @@ public:
 	using GraphicsMan_v1<T>::putPixel;
 
 	GraphicsMan_v2<T>(T &display) : GraphicsMan_v1<T>(display), _color(0) { }
-	void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos);
+	void drawPic(Common::SeekableReadStream &pic, const Common::Point &pos) override;
 
 protected:
 	bool canFillAt(const Common::Point &p, const bool stopBit = false);
@@ -94,7 +94,7 @@ private:
 	void fill(Common::SeekableReadStream &pic);
 	virtual void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit);
 	virtual void fillAt(Common::Point p, const byte pattern);
-	virtual byte getClearColor() const override { return 0xff; }
+	byte getClearColor() const override { return 0xff; }
 
 	byte _color;
 	Common::Point _offset;
@@ -113,8 +113,8 @@ public:
 	GraphicsMan_v3<T>(T &display) : GraphicsMan_v2<T>(display) { }
 
 private:
-	virtual void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) override;
-	virtual void fillAt(Common::Point p, const byte pattern) override;
+	void fillRowLeft(Common::Point p, const byte pattern, const bool stopBit) override;
+	void fillAt(Common::Point p, const byte pattern) override;
 };
 
 template <class T>
diff --git a/engines/adl/hires6.cpp b/engines/adl/hires6.cpp
index 29d7ea3..da5b465 100644
--- a/engines/adl/hires6.cpp
+++ b/engines/adl/hires6.cpp
@@ -44,23 +44,23 @@ public:
 
 private:
 	// AdlEngine
-	void gameLoop();
-	void setupOpcodeTables();
-	void runIntro();
-	void init();
-	void initGameState();
-	void showRoom();
+	void gameLoop() override;
+	void setupOpcodeTables() override;
+	void runIntro() override;
+	void init() override;
+	void initGameState() override;
+	void showRoom() override;
 	int goDirection(ScriptEnv &e, Direction dir) override;
-	Common::String formatVerbError(const Common::String &verb) const;
-	Common::String formatNounError(const Common::String &verb, const Common::String &noun) const;
-	void loadState(Common::ReadStream &stream);
-	void saveState(Common::WriteStream &stream);
+	Common::String formatVerbError(const Common::String &verb) const override;
+	Common::String formatNounError(const Common::String &verb, const Common::String &noun) const override;
+	void loadState(Common::ReadStream &stream) override;
+	void saveState(Common::WriteStream &stream) override;
 
 	// AdlEngine_v2
-	void printString(const Common::String &str);
+	void printString(const Common::String &str) override;
 
 	// Engine
-	bool canSaveGameStateCurrently();
+	bool canSaveGameStateCurrently() override;
 
 	int o_fluteSound(ScriptEnv &e);
 


Commit: 338baf827cc7dc9c335a8fed4d62ccf2d6231473
    https://github.com/scummvm/scummvm/commit/338baf827cc7dc9c335a8fed4d62ccf2d6231473
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2019-07-16T16:24:20+02:00

Commit Message:
ADL: Fix debug mode hang in hires5 animation

Changed paths:
    engines/adl/hires5.cpp


diff --git a/engines/adl/hires5.cpp b/engines/adl/hires5.cpp
index 3709374..b98dfc5 100644
--- a/engines/adl/hires5.cpp
+++ b/engines/adl/hires5.cpp
@@ -101,6 +101,10 @@ void HiRes5Engine::drawLight(uint index, byte color) const {
 }
 
 void HiRes5Engine::animateLights() const {
+	// Skip this if we're running a debug script
+	if (_inputScript)
+		return;
+
 	int index;
 	byte color = 0x2a;
 


Commit: 9c7ed5c0da84030467b61bb6a252544c98daada5
    https://github.com/scummvm/scummvm/commit/9c7ed5c0da84030467b61bb6a252544c98daada5
Author: Walter van Niftrik (walter at scummvm.org)
Date: 2019-07-16T16:24:20+02:00

Commit Message:
ADL: Silence MSVC warnings

Changed paths:
    engines/adl/display_a2.cpp


diff --git a/engines/adl/display_a2.cpp b/engines/adl/display_a2.cpp
index bb0e6d9..3a62e33 100644
--- a/engines/adl/display_a2.cpp
+++ b/engines/adl/display_a2.cpp
@@ -387,7 +387,7 @@ static void renderPixelRowMono(byte *dst, byte *src) {
 static void copyEvenSurfaceRows(Graphics::Surface &surf) {
 	byte *src = (byte *)surf.getPixels();
 
-	for (uint y = 0; y < surf.h / 2; ++y) {
+	for (uint y = 0; y < surf.h / 2u; ++y) {
 		byte *dst = src + surf.pitch;
 		for (uint x = 0; x < surf.w; ++x)
 			dst[x] = ALTCOL(src[x]);
@@ -463,7 +463,7 @@ void Display_A2::createFont() {
 	byte *buf = (byte *)_font->getPixels();
 	byte *bufInv = buf + (_font->h / 2) * _font->pitch;
 
-	for (uint row = 0; row < _font->h / 2; row += 2) {
+	for (uint row = 0; row < _font->h / 2u; row += 2) {
 		for (uint col = 0; col < _font->w; ++col)
 			bufInv[col] = (buf[col] ? 0 : 1);
 





More information about the Scummvm-git-logs mailing list