[Scummvm-git-logs] scummvm master -> bf17c9f33e48b4e091ba85b1f6868cc518839191

athrxx athrxx at scummvm.org
Wed Mar 6 22:17:32 CET 2019


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

Summary:
8b53d20b51 KYRA: (EOB1/Amiga) - add detection entries
1dfdcc7252 KYRA: cleanup dir
7cb7e41339 KYRA: (EOB) - slight improvement to character generation
2b95dd3213 KYRA: (EOB) - fix unused string
09c4912034 KYRA: (EOB) - improve comment
bc66a1ee82 KYRA: - minor cleanup
4d934ec30e KYRA: (EOB) - minor save file export fix
77a7f02e9a KYRA: (EOB) - rename var
f0a305316c KYRA: (EOB1/Amiga) - add static resources
4cc9c81a75 KYRA: (EOB1/Amiga) - add sound driver
890c4c5f41 KYRA: (EOB1/Amiga) - fix start up
e00eaa4899 KYRA: (EOB1/Amiga) - fix intro
7b8c84fa4d KYRA: (EOB1/Amiga) - fix chargen and gui colors
490e41cfad KYRA: (EOB1/Amiga) - implement AmigaDOS font support
21712209c0 KYRA: (EOB1/Amiga) - fix level loading
946597d3b2 KYRA: (EOB1/Amiga) - fix level graphics
f72ccb972d KYRA: (EOB1/Amiga) - fix environmental sound glitch
39eb1c4cc4 KYRA: (EOB1/Amiga) - fix detect magic spell
1cedb61c8c KYRA: (EOB1) - fix slow poison status display
e907965d81 KYRA: (EOB1/Amiga) - fix main menu load dialog
30ed036f6e KYRA: (EOB1/Amiga) - fix environmental sfx
75b01d367a KYRA: (EOB1/Amiga) - fix monster walk orientation
b5ac2203a5 KYRA: (EOB1/Amiga) - Amiga specific stone skin spell variant
b8893fc691 KYRA: (EOB1/Amiga) - fix level palette glitch
c6230ebbf5 KYRA: (EOB1/Amiga) - improve scaled item handling
94ab4c8352 KYRA: (EOB1/Amiga) - fix warning
c3fa4c02ab KYRA: (EOB) - fix possible out of bounds mem access
0be1fa53db KYRA: (EOB1/Amiga) - add original save file handling
412a10ede3 KYRA: (EOB1) - fix bug when attacking while invisible
8c5fcb36a5 KYRA: (EOB) - fix poison warning
ea6f44871b KYRA: (EOB2/FM-TOWNS) - fix character status text glitch
1cb8580831 KYRA: (EOB1/Amiga) - fix spell sounds
010a79099e KYRA: (EOB1/Amiga) - fix invisible character display
5af15399ec KYRA: (EOB) - improve timer handling
83f1044915 KYRA: (EOB1) - make dispel magic spell more accurate
3fccab8f92 KYRA: (EOB1) - fix turn undead spell in level 7
379df2b9e3 KYRA: (EOB1/Amiga) - fix Cone of Cold spell sfx
ec640a069a KYRA: (EOB1/Amiga) - fix Amiga cps decompression
25c72ba346 KYRA: (EOB1/Amiga) - implement ending sequence
bf17c9f33e KYRA: update NEWS file


Commit: 8b53d20b51771680c3d31aa02c0285b7a8be4e85
    https://github.com/scummvm/scummvm/commit/8b53d20b51771680c3d31aa02c0285b7a8be4e85
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:15+01:00

Commit Message:
KYRA: (EOB1/Amiga) - add detection entries

Changed paths:
    engines/kyra/detection_tables.h


diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
index da0a2de..0da2dea 100644
--- a/engines/kyra/detection_tables.h
+++ b/engines/kyra/detection_tables.h
@@ -1656,6 +1656,38 @@ const KYRAGameDescription adGameDescs[] = {
 
 	{
 		{
+			"eob",
+			0,
+			{
+				{ "TEXT.CPS", 0, "e9c2a9d81c8ce2dc35d92ece5950c45d", -1 },
+				{ 0, 0, 0, 0 }
+			},
+			Common::EN_ANY,
+			Common::kPlatformAmiga,
+			ADGF_NO_FLAGS,
+			GUIO4(GUIO_NOSPEECH, GUIO_MIDIAMIGA, GUIO_RENDERAMIGA, GAMEOPTION_EOB_HPGRAPHS)
+		},
+		EOB_FLAGS
+	},
+
+	{
+		{
+			"eob",
+			0,
+			{
+				{ "TEXT.CPS", 0, "66253c0f435c5947e6f7166bd94f21e3", -1 },
+				{ 0, 0, 0, 0 }
+			},
+			Common::DE_DEU,
+			Common::kPlatformAmiga,
+			ADGF_NO_FLAGS,
+			GUIO4(GUIO_NOSPEECH, GUIO_MIDIAMIGA, GUIO_RENDERAMIGA, GAMEOPTION_EOB_HPGRAPHS)
+		},
+		EOB_FLAGS
+	},
+
+	{
+		{
 			"eob2",
 			0,
 			{


Commit: 1dfdcc7252ac83643cae7a7447c025da2af63843
    https://github.com/scummvm/scummvm/commit/1dfdcc7252ac83643cae7a7447c025da2af63843
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:15+01:00

Commit Message:
KYRA: cleanup dir

Reorganize all files in sub directories. The file placement isn't as intuitive as it might be for other engines, which is probably the reason why this hasn't been done before.

Changed paths:
  A engines/kyra/engine/chargen.cpp
  A engines/kyra/engine/darkmoon.cpp
  A engines/kyra/engine/darkmoon.h
  A engines/kyra/engine/eob.cpp
  A engines/kyra/engine/eob.h
  A engines/kyra/engine/eobcommon.cpp
  A engines/kyra/engine/eobcommon.h
  A engines/kyra/engine/item.h
  A engines/kyra/engine/items_eob.cpp
  A engines/kyra/engine/items_hof.cpp
  A engines/kyra/engine/items_lok.cpp
  A engines/kyra/engine/items_lol.cpp
  A engines/kyra/engine/items_mr.cpp
  A engines/kyra/engine/items_v2.cpp
  A engines/kyra/engine/kyra_hof.cpp
  A engines/kyra/engine/kyra_hof.h
  A engines/kyra/engine/kyra_lok.cpp
  A engines/kyra/engine/kyra_lok.h
  A engines/kyra/engine/kyra_mr.cpp
  A engines/kyra/engine/kyra_mr.h
  A engines/kyra/engine/kyra_rpg.cpp
  A engines/kyra/engine/kyra_rpg.h
  A engines/kyra/engine/kyra_v1.cpp
  A engines/kyra/engine/kyra_v2.cpp
  A engines/kyra/engine/kyra_v2.h
  A engines/kyra/engine/lol.cpp
  A engines/kyra/engine/lol.h
  A engines/kyra/engine/magic_eob.cpp
  A engines/kyra/engine/scene_eob.cpp
  A engines/kyra/engine/scene_hof.cpp
  A engines/kyra/engine/scene_lok.cpp
  A engines/kyra/engine/scene_lol.cpp
  A engines/kyra/engine/scene_mr.cpp
  A engines/kyra/engine/scene_rpg.cpp
  A engines/kyra/engine/scene_v1.cpp
  A engines/kyra/engine/scene_v2.cpp
  A engines/kyra/engine/sprites.cpp
  A engines/kyra/engine/sprites.h
  A engines/kyra/engine/sprites_eob.cpp
  A engines/kyra/engine/sprites_lol.cpp
  A engines/kyra/engine/sprites_rpg.cpp
  A engines/kyra/engine/timer.cpp
  A engines/kyra/engine/timer.h
  A engines/kyra/engine/timer_eob.cpp
  A engines/kyra/engine/timer_hof.cpp
  A engines/kyra/engine/timer_lok.cpp
  A engines/kyra/engine/timer_lol.cpp
  A engines/kyra/engine/timer_mr.cpp
  A engines/kyra/engine/timer_rpg.cpp
  A engines/kyra/engine/util.cpp
  A engines/kyra/engine/util.h
  A engines/kyra/graphics/animator_hof.cpp
  A engines/kyra/graphics/animator_lok.cpp
  A engines/kyra/graphics/animator_lok.h
  A engines/kyra/graphics/animator_mr.cpp
  A engines/kyra/graphics/animator_tim.cpp
  A engines/kyra/graphics/animator_v2.cpp
  A engines/kyra/graphics/screen.cpp
  A engines/kyra/graphics/screen.h
  A engines/kyra/graphics/screen_eob.cpp
  A engines/kyra/graphics/screen_eob.h
  A engines/kyra/graphics/screen_hof.cpp
  A engines/kyra/graphics/screen_hof.h
  A engines/kyra/graphics/screen_lok.cpp
  A engines/kyra/graphics/screen_lok.h
  A engines/kyra/graphics/screen_lol.cpp
  A engines/kyra/graphics/screen_lol.h
  A engines/kyra/graphics/screen_mr.cpp
  A engines/kyra/graphics/screen_mr.h
  A engines/kyra/graphics/screen_v2.cpp
  A engines/kyra/graphics/screen_v2.h
  A engines/kyra/graphics/vqa.cpp
  A engines/kyra/graphics/vqa.h
  A engines/kyra/graphics/wsamovie.cpp
  A engines/kyra/graphics/wsamovie.h
  A engines/kyra/gui/debugger.cpp
  A engines/kyra/gui/debugger.h
  A engines/kyra/gui/gui.cpp
  A engines/kyra/gui/gui.h
  A engines/kyra/gui/gui_eob.cpp
  A engines/kyra/gui/gui_eob.h
  A engines/kyra/gui/gui_hof.cpp
  A engines/kyra/gui/gui_hof.h
  A engines/kyra/gui/gui_lok.cpp
  A engines/kyra/gui/gui_lok.h
  A engines/kyra/gui/gui_lol.cpp
  A engines/kyra/gui/gui_lol.h
  A engines/kyra/gui/gui_mr.cpp
  A engines/kyra/gui/gui_mr.h
  A engines/kyra/gui/gui_rpg.cpp
  A engines/kyra/gui/gui_v1.cpp
  A engines/kyra/gui/gui_v1.h
  A engines/kyra/gui/gui_v2.cpp
  A engines/kyra/gui/gui_v2.h
  A engines/kyra/gui/saveload.cpp
  A engines/kyra/gui/saveload_eob.cpp
  A engines/kyra/gui/saveload_hof.cpp
  A engines/kyra/gui/saveload_lok.cpp
  A engines/kyra/gui/saveload_lol.cpp
  A engines/kyra/gui/saveload_mr.cpp
  A engines/kyra/gui/saveload_rpg.cpp
  A engines/kyra/resource/resource.cpp
  A engines/kyra/resource/resource.h
  A engines/kyra/resource/resource_intern.cpp
  A engines/kyra/resource/resource_intern.h
  A engines/kyra/resource/staticres.cpp
  A engines/kyra/resource/staticres_eob.cpp
  A engines/kyra/resource/staticres_lol.cpp
  A engines/kyra/resource/staticres_rpg.cpp
  A engines/kyra/script/script.cpp
  A engines/kyra/script/script.h
  A engines/kyra/script/script_eob.cpp
  A engines/kyra/script/script_eob.h
  A engines/kyra/script/script_hof.cpp
  A engines/kyra/script/script_lok.cpp
  A engines/kyra/script/script_lol.cpp
  A engines/kyra/script/script_mr.cpp
  A engines/kyra/script/script_tim.cpp
  A engines/kyra/script/script_tim.h
  A engines/kyra/script/script_v1.cpp
  A engines/kyra/script/script_v2.cpp
  A engines/kyra/sequence/seqplayer.cpp
  A engines/kyra/sequence/seqplayer.h
  A engines/kyra/sequence/sequences_darkmoon.cpp
  A engines/kyra/sequence/sequences_eob.cpp
  A engines/kyra/sequence/sequences_hof.cpp
  A engines/kyra/sequence/sequences_hof.h
  A engines/kyra/sequence/sequences_lok.cpp
  A engines/kyra/sequence/sequences_lol.cpp
  A engines/kyra/sequence/sequences_mr.cpp
  A engines/kyra/sequence/sequences_v2.cpp
  A engines/kyra/sound/sound.cpp
  A engines/kyra/sound/sound.h
  A engines/kyra/sound/sound_adlib.cpp
  A engines/kyra/sound/sound_adlib.h
  A engines/kyra/sound/sound_amiga.cpp
  A engines/kyra/sound/sound_digital.cpp
  A engines/kyra/sound/sound_digital.h
  A engines/kyra/sound/sound_intern.h
  A engines/kyra/sound/sound_lok.cpp
  A engines/kyra/sound/sound_lol.cpp
  A engines/kyra/sound/sound_midi.cpp
  A engines/kyra/sound/sound_pcspk.cpp
  A engines/kyra/sound/sound_towns.cpp
  A engines/kyra/sound/sound_towns_darkmoon.cpp
  A engines/kyra/text/text.cpp
  A engines/kyra/text/text.h
  A engines/kyra/text/text_hof.cpp
  A engines/kyra/text/text_hof.h
  A engines/kyra/text/text_lok.cpp
  A engines/kyra/text/text_lol.cpp
  A engines/kyra/text/text_lol.h
  A engines/kyra/text/text_mr.cpp
  A engines/kyra/text/text_mr.h
  A engines/kyra/text/text_rpg.cpp
  A engines/kyra/text/text_rpg.h
  R engines/kyra/animator_hof.cpp
  R engines/kyra/animator_lok.cpp
  R engines/kyra/animator_lok.h
  R engines/kyra/animator_mr.cpp
  R engines/kyra/animator_tim.cpp
  R engines/kyra/animator_v2.cpp
  R engines/kyra/chargen.cpp
  R engines/kyra/darkmoon.cpp
  R engines/kyra/darkmoon.h
  R engines/kyra/debugger.cpp
  R engines/kyra/debugger.h
  R engines/kyra/eob.cpp
  R engines/kyra/eob.h
  R engines/kyra/eobcommon.cpp
  R engines/kyra/eobcommon.h
  R engines/kyra/gui.cpp
  R engines/kyra/gui.h
  R engines/kyra/gui_eob.cpp
  R engines/kyra/gui_eob.h
  R engines/kyra/gui_hof.cpp
  R engines/kyra/gui_hof.h
  R engines/kyra/gui_lok.cpp
  R engines/kyra/gui_lok.h
  R engines/kyra/gui_lol.cpp
  R engines/kyra/gui_lol.h
  R engines/kyra/gui_mr.cpp
  R engines/kyra/gui_mr.h
  R engines/kyra/gui_rpg.cpp
  R engines/kyra/gui_v1.cpp
  R engines/kyra/gui_v1.h
  R engines/kyra/gui_v2.cpp
  R engines/kyra/gui_v2.h
  R engines/kyra/item.h
  R engines/kyra/items_eob.cpp
  R engines/kyra/items_hof.cpp
  R engines/kyra/items_lok.cpp
  R engines/kyra/items_lol.cpp
  R engines/kyra/items_mr.cpp
  R engines/kyra/items_v2.cpp
  R engines/kyra/kyra_hof.cpp
  R engines/kyra/kyra_hof.h
  R engines/kyra/kyra_lok.cpp
  R engines/kyra/kyra_lok.h
  R engines/kyra/kyra_mr.cpp
  R engines/kyra/kyra_mr.h
  R engines/kyra/kyra_rpg.cpp
  R engines/kyra/kyra_rpg.h
  R engines/kyra/kyra_v1.cpp
  R engines/kyra/kyra_v2.cpp
  R engines/kyra/kyra_v2.h
  R engines/kyra/lol.cpp
  R engines/kyra/lol.h
  R engines/kyra/magic_eob.cpp
  R engines/kyra/resource.cpp
  R engines/kyra/resource.h
  R engines/kyra/resource_intern.cpp
  R engines/kyra/resource_intern.h
  R engines/kyra/saveload.cpp
  R engines/kyra/saveload_eob.cpp
  R engines/kyra/saveload_hof.cpp
  R engines/kyra/saveload_lok.cpp
  R engines/kyra/saveload_lol.cpp
  R engines/kyra/saveload_mr.cpp
  R engines/kyra/saveload_rpg.cpp
  R engines/kyra/scene_eob.cpp
  R engines/kyra/scene_hof.cpp
  R engines/kyra/scene_lok.cpp
  R engines/kyra/scene_lol.cpp
  R engines/kyra/scene_mr.cpp
  R engines/kyra/scene_rpg.cpp
  R engines/kyra/scene_v1.cpp
  R engines/kyra/scene_v2.cpp
  R engines/kyra/screen.cpp
  R engines/kyra/screen.h
  R engines/kyra/screen_eob.cpp
  R engines/kyra/screen_eob.h
  R engines/kyra/screen_hof.cpp
  R engines/kyra/screen_hof.h
  R engines/kyra/screen_lok.cpp
  R engines/kyra/screen_lok.h
  R engines/kyra/screen_lol.cpp
  R engines/kyra/screen_lol.h
  R engines/kyra/screen_mr.cpp
  R engines/kyra/screen_mr.h
  R engines/kyra/screen_v2.cpp
  R engines/kyra/screen_v2.h
  R engines/kyra/script.cpp
  R engines/kyra/script.h
  R engines/kyra/script_eob.cpp
  R engines/kyra/script_eob.h
  R engines/kyra/script_hof.cpp
  R engines/kyra/script_lok.cpp
  R engines/kyra/script_lol.cpp
  R engines/kyra/script_mr.cpp
  R engines/kyra/script_tim.cpp
  R engines/kyra/script_tim.h
  R engines/kyra/script_v1.cpp
  R engines/kyra/script_v2.cpp
  R engines/kyra/seqplayer.cpp
  R engines/kyra/seqplayer.h
  R engines/kyra/sequences_darkmoon.cpp
  R engines/kyra/sequences_eob.cpp
  R engines/kyra/sequences_hof.cpp
  R engines/kyra/sequences_hof.h
  R engines/kyra/sequences_lok.cpp
  R engines/kyra/sequences_lol.cpp
  R engines/kyra/sequences_mr.cpp
  R engines/kyra/sequences_v2.cpp
  R engines/kyra/sound.cpp
  R engines/kyra/sound.h
  R engines/kyra/sound_adlib.cpp
  R engines/kyra/sound_adlib.h
  R engines/kyra/sound_amiga.cpp
  R engines/kyra/sound_digital.cpp
  R engines/kyra/sound_digital.h
  R engines/kyra/sound_intern.h
  R engines/kyra/sound_lok.cpp
  R engines/kyra/sound_lol.cpp
  R engines/kyra/sound_midi.cpp
  R engines/kyra/sound_pcspk.cpp
  R engines/kyra/sound_towns.cpp
  R engines/kyra/sound_towns_darkmoon.cpp
  R engines/kyra/sprites.cpp
  R engines/kyra/sprites.h
  R engines/kyra/sprites_eob.cpp
  R engines/kyra/sprites_lol.cpp
  R engines/kyra/sprites_rpg.cpp
  R engines/kyra/staticres.cpp
  R engines/kyra/staticres_eob.cpp
  R engines/kyra/staticres_lol.cpp
  R engines/kyra/staticres_rpg.cpp
  R engines/kyra/text.cpp
  R engines/kyra/text.h
  R engines/kyra/text_hof.cpp
  R engines/kyra/text_hof.h
  R engines/kyra/text_lok.cpp
  R engines/kyra/text_lol.cpp
  R engines/kyra/text_lol.h
  R engines/kyra/text_mr.cpp
  R engines/kyra/text_mr.h
  R engines/kyra/text_rpg.cpp
  R engines/kyra/text_rpg.h
  R engines/kyra/timer.cpp
  R engines/kyra/timer.h
  R engines/kyra/timer_eob.cpp
  R engines/kyra/timer_hof.cpp
  R engines/kyra/timer_lok.cpp
  R engines/kyra/timer_lol.cpp
  R engines/kyra/timer_mr.cpp
  R engines/kyra/timer_rpg.cpp
  R engines/kyra/util.cpp
  R engines/kyra/util.h
  R engines/kyra/vqa.cpp
  R engines/kyra/vqa.h
  R engines/kyra/wsamovie.cpp
  R engines/kyra/wsamovie.h
    engines/kyra/detection.cpp
    engines/kyra/kyra_v1.h
    engines/kyra/module.mk


diff --git a/engines/kyra/animator_hof.cpp b/engines/kyra/animator_hof.cpp
deleted file mode 100644
index 7ce79cb..0000000
--- a/engines/kyra/animator_hof.cpp
+++ /dev/null
@@ -1,313 +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 "kyra/kyra_hof.h"
-#include "kyra/wsamovie.h"
-
-#include "common/system.h"
-
-namespace Kyra {
-
-void KyraEngine_HoF::restorePage3() {
-	screen()->copyBlockToPage(2, 0, 0, 320, 144, _gamePlayBuffer);
-}
-
-void KyraEngine_HoF::clearAnimObjects() {
-	_animObjects[0].index = 0;
-	_animObjects[0].type = 0;
-	_animObjects[0].enabled = 1;
-	_animObjects[0].flags = 0x800;
-	_animObjects[0].width = 32;
-	_animObjects[0].height = 49;
-	_animObjects[0].width2 = 4;
-	_animObjects[0].height2 = 10;
-
-	for (int i = 1; i < 11; ++i) {
-		_animObjects[i].index = i;
-		_animObjects[i].type = 2;
-	}
-
-	for (int i = 11; i <= 40; ++i) {
-		_animObjects[i].index = i;
-		_animObjects[i].type = 1;
-		_animObjects[i].flags = 0x800;
-		_animObjects[i].width = 16;
-		_animObjects[i].height = 16;
-	}
-}
-
-void KyraEngine_HoF::drawAnimObjects() {
-	for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
-		if (!curObject->enabled)
-			continue;
-
-		int x = curObject->xPos2 - (_screen->getScreenDim(2)->sx << 3);
-		int y = curObject->yPos2 - _screen->getScreenDim(2)->sy;
-		int layer = 7;
-
-		if (curObject->flags & 0x800) {
-			if (curObject->animFlags)
-				layer = 0;
-			else
-				layer = getDrawLayer(curObject->xPos1, curObject->yPos1);
-		}
-		curObject->flags |= 0x800;
-
-		if (curObject->index)
-			drawSceneAnimObject(curObject, x, y, layer);
-		else
-			drawCharacterAnimObject(curObject, x, y, layer);
-	}
-}
-
-void KyraEngine_HoF::refreshAnimObjects(int force) {
-	for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
-		if (!curObject->enabled)
-			continue;
-		if (!curObject->needRefresh && !force)
-			continue;
-
-		int x = curObject->xPos2 - curObject->width2;
-		if (x < 0)
-			x = 0;
-		if (x >= 320)
-			x = 319;
-		int y = curObject->yPos2 - curObject->height2;
-		if (y < 0)
-			y = 0;
-		if (y >= 143)
-			y = 142;
-
-		int width = curObject->width + curObject->width2 + 8;
-		int height = curObject->height + curObject->height2*2;
-		if (width + x > 320)
-			width -= width + x - 322;
-		if (height + y > 143)
-			height -= height + y - 144;
-
-		_screen->copyRegion(x, y, x, y, width, height, 2, 0, Screen::CR_NO_P_CHECK);
-
-		curObject->needRefresh = false;
-	}
-}
-
-void KyraEngine_HoF::updateItemAnimations() {
-	bool nextFrame = false;
-
-	if (_itemAnimDefinition[0].itemIndex == -1 || _inventorySaved)
-		return;
-
-	const ItemAnimDefinition *s = &_itemAnimDefinition[_nextAnimItem];
-	ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem];
-	_nextAnimItem = (_nextAnimItem + 1) % _itemAnimDefinitionSize;
-
-	if (_system->getMillis() < a->nextFrameTime)
-		return;
-
-	uint16 shpIdx = s->frames[a->currentFrame].index + 64;
-	if (s->itemIndex == _mouseState && s->itemIndex == _itemInHand && _screen->isMouseVisible()) {
-		nextFrame = true;
-		_screen->setMouseCursor(8, 15, getShapePtr(shpIdx));
-	}
-
-	for (int i = 0; i < 10; i++) {
-		if (s->itemIndex == _mainCharacter.inventory[i]) {
-			nextFrame = true;
-			_screen->drawShape(2, getShapePtr(240 + i), 304, 184, 0, 0);
-			_screen->drawShape(2, getShapePtr(shpIdx), 304, 184, 0, 0);
-			_screen->copyRegion(304, 184, _inventoryX[i], _inventoryY[i], 16, 16, 2, 0);
-		}
-	}
-
-	_screen->updateScreen();
-
-	for (int i = 11; i < 40; i++) {
-		AnimObj *animObject = &_animObjects[i];
-		if (animObject->shapeIndex2 == s->itemIndex + 64) {
-			if (s->itemIndex == 121) {
-				int f = findItem(_mainCharacter.sceneId, 121);
-				int nx = _itemList[f].x - 4;
-				if (nx > 12) {
-					if (lineIsPassable(nx, _itemList[f].y)) {
-						animObject->xPos2 -= 4;
-						_itemList[f].x -= 4;
-					}
-				}
-			}
-			animObject->shapePtr = getShapePtr(shpIdx);
-			animObject->shapeIndex1 = shpIdx;
-			animObject->needRefresh = 1;
-			nextFrame = true;
-		}
-	}
-
-	if (nextFrame) {
-		a->nextFrameTime = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength);
-		a->currentFrame = (a->currentFrame + 1) % s->numFrames;
-	}
-}
-
-void KyraEngine_HoF::updateCharFacing() {
-	if (_mainCharacter.x1 > _mouseX)
-		_mainCharacter.facing = 5;
-	else
-		_mainCharacter.facing = 3;
-
-	_mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
-	updateCharacterAnim(0);
-	refreshAnimObjectsIfNeed();
-}
-
-void KyraEngine_HoF::updateCharacterAnim(int) {
-	Character *c = &_mainCharacter;
-	AnimObj *animState = _animObjects;
-
-	animState->needRefresh = 1;
-	animState->specialRefresh = 1;
-
-	if (c->facing >= 1 && c->facing <= 3)
-		animState->flags |= 1;
-	else if (c->facing >= 5 && c->facing <= 7)
-		animState->flags &= ~1;
-
-	animState->xPos2 = animState->xPos1 = c->x1;
-	animState->yPos2 = animState->yPos1 = c->y1;
-	animState->shapePtr = getShapePtr(c->animFrame);
-	animState->shapeIndex1 = animState->shapeIndex2 = c->animFrame;
-
-	int xAdd = _shapeDescTable[c->animFrame-9].xAdd;
-	int yAdd = _shapeDescTable[c->animFrame-9].yAdd;
-
-	_charScale = getScale(c->x1, c->y1);
-
-	animState->xPos2 += (xAdd * _charScale) >> 8;
-	animState->yPos2 += (yAdd * _charScale) >> 8;
-	animState->width2 = 8;
-	animState->height2 = 10;
-
-	_animList = deleteAnimListEntry(_animList, animState);
-	if (_animList)
-		_animList = addToAnimListSorted(_animList, animState);
-	else
-		_animList = initAnimList(_animList, animState);
-
-	updateCharPal(1);
-}
-
-void KyraEngine_HoF::updateSceneAnim(int anim, int newFrame) {
-	AnimObj *animObject = &_animObjects[1+anim];
-	if (!animObject->enabled)
-		return;
-
-	animObject->needRefresh = 1;
-	animObject->specialRefresh = 1;
-	animObject->flags = 0;
-
-	if (_sceneAnims[anim].flags & 2)
-		animObject->flags |= 0x800;
-	else
-		animObject->flags &= ~0x800;
-
-	if (_sceneAnims[anim].flags & 4)
-		animObject->flags |= 1;
-	else
-		animObject->flags &= ~1;
-
-	if (_sceneAnims[anim].flags & 0x20) {
-		animObject->shapePtr = _sceneShapeTable[newFrame];
-		animObject->shapeIndex2 = 0xFFFF;
-		animObject->shapeIndex3 = 0xFFFF;
-		animObject->animNum = 0xFFFF;
-	} else {
-		animObject->shapePtr = 0;
-		animObject->shapeIndex3 = newFrame;
-		animObject->animNum = anim;
-	}
-
-	animObject->xPos1 = _sceneAnims[anim].x;
-	animObject->yPos1 = _sceneAnims[anim].y;
-	animObject->xPos2 = _sceneAnims[anim].x2;
-	animObject->yPos2 = _sceneAnims[anim].y2;
-
-	if (_sceneAnims[anim].flags & 2) {
-		_animList = deleteAnimListEntry(_animList, animObject);
-		if (!_animList)
-			_animList = initAnimList(_animList, animObject);
-		else
-			_animList = addToAnimListSorted(_animList, animObject);
-	}
-}
-
-void KyraEngine_HoF::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) {
-	if (obj->type == 1) {
-		if (obj->shapeIndex1 == 0xFFFF)
-			return;
-		int scale = getScale(obj->xPos1, obj->yPos1);
-		_screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, scale, scale);
-		return;
-	}
-
-	if (obj->shapePtr) {
-		_screen->drawShape(2, obj->shapePtr, x, y, 2, obj->flags, layer);
-	} else {
-		if (obj->shapeIndex3 == 0xFFFF || obj->animNum == 0xFFFF)
-			return;
-
-		int flags = 0x4000;
-		if (obj->flags & 0x800)
-			flags |= 0x8000;
-
-		if (_sceneAnims[obj->animNum].wsaFlag) {
-			x = y = 0;
-		} else {
-			x = obj->xPos2;
-			y = obj->yPos2;
-		}
-
-		_sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, int(flags | layer), 0, 0);
-	}
-}
-
-void KyraEngine_HoF::drawCharacterAnimObject(AnimObj *obj, int x, int y, int layer) {
-	if (_drawNoShapeFlag || obj->shapeIndex1 == 0xFFFF)
-		return;
-	_screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, _charScale, _charScale);
-}
-
-void KyraEngine_HoF::setCharacterAnimDim(int w, int h) {
-	restorePage3();
-
-	_animObj0Width = _animObjects[0].width;
-	_animObj0Height = _animObjects[0].height;
-
-	_animObjects[0].width = w;
-	_animObjects[0].height = h;
-}
-
-void KyraEngine_HoF::resetCharacterAnimDim() {
-	restorePage3();
-
-	_animObjects[0].width = _animObj0Width;
-	_animObjects[0].height = _animObj0Height;
-}
-
-} // End of namespace Kyra
diff --git a/engines/kyra/animator_lok.cpp b/engines/kyra/animator_lok.cpp
deleted file mode 100644
index ba6dc91..0000000
--- a/engines/kyra/animator_lok.cpp
+++ /dev/null
@@ -1,651 +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 "kyra/kyra_lok.h"
-#include "kyra/screen.h"
-#include "kyra/animator_lok.h"
-#include "kyra/sprites.h"
-
-namespace Kyra {
-
-Animator_LoK::Animator_LoK(KyraEngine_LoK *vm, OSystem *system) {
-	_vm = vm;
-	_screen = vm->screen();
-	_initOk = false;
-	_system = system;
-	_screenObjects = _actors = _items = _sprites = _objectQueue = 0;
-	_noDrawShapesFlag = 0;
-
-	_actorBkgBackUp[0] = new uint8[_screen->getRectSize(8, 69)];
-	memset(_actorBkgBackUp[0], 0, _screen->getRectSize(8, 69));
-	_actorBkgBackUp[1] = new uint8[_screen->getRectSize(8, 69)];
-	memset(_actorBkgBackUp[1], 0, _screen->getRectSize(8, 69));
-}
-
-Animator_LoK::~Animator_LoK() {
-	close();
-	delete[] _actorBkgBackUp[0];
-	delete[] _actorBkgBackUp[1];
-}
-
-void Animator_LoK::init(int actors_, int items_, int sprites_) {
-	_screenObjects = new AnimObject[actors_ + items_ + sprites_];
-	assert(_screenObjects);
-	memset(_screenObjects, 0, sizeof(AnimObject) * (actors_ + items_ + sprites_));
-	_actors = _screenObjects;
-	_sprites = &_screenObjects[actors_];
-	_items = &_screenObjects[actors_ + items_];
-	_brandonDrawFrame = 113;
-
-	_initOk = true;
-}
-
-void Animator_LoK::close() {
-	if (_initOk) {
-		_initOk = false;
-		delete[] _screenObjects;
-		_screenObjects = _actors = _items = _sprites = _objectQueue = 0;
-	}
-}
-
-void Animator_LoK::initAnimStateList() {
-	AnimObject *animStates = _screenObjects;
-	animStates[0].index = 0;
-	animStates[0].active = 1;
-	animStates[0].flags = 0x800;
-	animStates[0].background = _actorBkgBackUp[0];
-	animStates[0].rectSize = _screen->getRectSize(4, 48);
-	animStates[0].width = 4;
-	animStates[0].height = 48;
-	animStates[0].width2 = 4;
-	animStates[0].height2 = 3;
-
-	for (int i = 1; i <= 4; ++i) {
-		animStates[i].index = i;
-		animStates[i].active = 0;
-		animStates[i].flags = 0x800;
-		animStates[i].background = _actorBkgBackUp[1];
-		animStates[i].rectSize = _screen->getRectSize(4, 64);
-		animStates[i].width = 4;
-		animStates[i].height = 48;
-		animStates[i].width2 = 4;
-		animStates[i].height2 = 3;
-	}
-
-	for (int i = 5; i < 16; ++i) {
-		animStates[i].index = i;
-		animStates[i].active = 0;
-		animStates[i].flags = 0;
-	}
-
-	for (int i = 16; i < 28; ++i) {
-		animStates[i].index = i;
-		animStates[i].flags = 0;
-		animStates[i].background = _vm->_shapes[345 + i];
-		animStates[i].rectSize = _screen->getRectSize(3, 24);
-		animStates[i].width = 3;
-		animStates[i].height = 16;
-		animStates[i].width2 = 0;
-		animStates[i].height2 = 0;
-	}
-}
-
-void Animator_LoK::preserveAllBackgrounds() {
-	uint8 curPage = _screen->_curPage;
-	_screen->_curPage = 2;
-
-	AnimObject *curObject = _objectQueue;
-	while (curObject) {
-		if (curObject->active && !curObject->disable) {
-			preserveOrRestoreBackground(curObject, false);
-			curObject->bkgdChangeFlag = 0;
-		}
-		curObject = curObject->nextAnimObject;
-	}
-	_screen->_curPage = curPage;
-}
-
-void Animator_LoK::flagAllObjectsForBkgdChange() {
-	AnimObject *curObject = _objectQueue;
-	while (curObject) {
-		curObject->bkgdChangeFlag = 1;
-		curObject = curObject->nextAnimObject;
-	}
-}
-
-void Animator_LoK::flagAllObjectsForRefresh() {
-	AnimObject *curObject = _objectQueue;
-	while (curObject) {
-		curObject->refreshFlag = 1;
-		curObject = curObject->nextAnimObject;
-	}
-}
-
-void Animator_LoK::restoreAllObjectBackgrounds() {
-	AnimObject *curObject = _objectQueue;
-	_screen->_curPage = 2;
-
-	while (curObject) {
-		if (curObject->active && !curObject->disable) {
-			preserveOrRestoreBackground(curObject, true);
-			curObject->x2 = curObject->x1;
-			curObject->y2 = curObject->y1;
-		}
-		curObject = curObject->nextAnimObject;
-	}
-
-	_screen->_curPage = 0;
-}
-
-void Animator_LoK::preserveAnyChangedBackgrounds() {
-	AnimObject *curObject = _objectQueue;
-	_screen->_curPage = 2;
-
-	while (curObject) {
-		if (curObject->active && !curObject->disable && curObject->bkgdChangeFlag) {
-			preserveOrRestoreBackground(curObject, false);
-			curObject->bkgdChangeFlag = 0;
-		}
-		curObject = curObject->nextAnimObject;
-	}
-
-	_screen->_curPage = 0;
-}
-
-void Animator_LoK::preserveOrRestoreBackground(AnimObject *obj, bool restore) {
-	int x = 0, y = 0, width = obj->width, height = obj->height;
-
-	if (restore) {
-		x = obj->x2 >> 3;
-		y = obj->y2;
-	} else {
-		x = obj->x1 >> 3;
-		y = obj->y1;
-	}
-
-	if (x < 0)
-		x = 0;
-	if (y < 0)
-		y = 0;
-
-	int temp;
-
-	temp = x + width;
-	if (temp >= 39)
-		x = 39 - width;
-	temp = y + height;
-	if (temp >= 136)
-		y = 136 - height;
-
-	if (restore)
-		_screen->copyBlockToPage(_screen->_curPage, x << 3, y, width << 3, height, obj->background);
-	else
-		_screen->copyRegionToBuffer(_screen->_curPage, x << 3, y, width << 3, height, obj->background);
-}
-
-void Animator_LoK::prepDrawAllObjects() {
-	AnimObject *curObject = _objectQueue;
-	int drawPage = 2;
-	int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0;
-	if (_noDrawShapesFlag)
-		return;
-	if (_vm->_brandonStatusBit & 0x20)
-		flagUnk1 = 0x200;
-	if (_vm->_brandonStatusBit & 0x40)
-		flagUnk2 = 0x4000;
-
-	while (curObject) {
-		if (curObject->active) {
-			int xpos = curObject->x1;
-			int ypos = curObject->y1;
-
-			int drawLayer = 0;
-			if (!(curObject->flags & 0x800))
-				drawLayer = 7;
-			else if (curObject->disable)
-				drawLayer = 0;
-			else
-				drawLayer = _vm->_sprites->getDrawLayer(curObject->drawY);
-
-			// talking head functionallity
-			if (_vm->_talkingCharNum != -1 && (_vm->_currentCharacter->currentAnimFrame != 88 || curObject->index != 0)) {
-				const int16 baseAnimFrameTable1[] = { 0x11, 0x35, 0x59, 0x00, 0x00, 0x00 };
-				const int16 baseAnimFrameTable2[] = { 0x15, 0x39, 0x5D, 0x00, 0x00, 0x00 };
-				const int8 xOffsetTable1[] = { 2, 4, 0, 5, 2, 0, 0, 0 };
-				const int8 xOffsetTable2[] = { 6, 4, 8, 3, 6, 0, 0, 0 };
-				const int8 yOffsetTable1[] = { 0, 8, 1, 1, 0, 0, 0, 0 };
-				const int8 yOffsetTable2[] = { 0, 8, 1, 1, 0, 0, 0, 0 };
-				if (curObject->index == 0 || curObject->index <= 4) {
-					int shapesIndex = 0;
-					if (curObject->index == _vm->_charSayUnk3) {
-						shapesIndex = _vm->_currHeadShape + baseAnimFrameTable1[curObject->index];
-					} else {
-						shapesIndex = baseAnimFrameTable2[curObject->index];
-						int temp2 = 0;
-						if (curObject->index == 2) {
-							if (_vm->_characterList[2].sceneId == 77 || _vm->_characterList[2].sceneId == 86)
-								temp2 = 1;
-							else
-								temp2 = 0;
-						} else {
-							temp2 = 1;
-						}
-
-						if (!temp2)
-							shapesIndex = -1;
-					}
-
-					xpos = curObject->x1;
-					ypos = curObject->y1;
-
-					int tempX = 0, tempY = 0;
-					if (curObject->flags & 0x1) {
-						tempX = (xOffsetTable1[curObject->index] * _brandonScaleX) >> 8;
-						tempY = yOffsetTable1[curObject->index];
-					} else {
-						tempX = (xOffsetTable2[curObject->index] * _brandonScaleX) >> 8;
-						tempY = yOffsetTable2[curObject->index];
-					}
-					tempY = (tempY * _brandonScaleY) >> 8;
-					xpos += tempX;
-					ypos += tempY;
-
-					if (_vm->_scaleMode && _brandonScaleX != 256)
-						++xpos;
-
-					if (curObject->index == 0 && shapesIndex != -1) {
-						if (!(_vm->_brandonStatusBit & 2)) {
-							flagUnk3 = 0x100;
-							if ((flagUnk1 & 0x200) || (flagUnk2 & 0x4000))
-								flagUnk3 = 0;
-
-							int tempFlags = 0;
-							if (flagUnk3 & 0x100) {
-								tempFlags = curObject->flags & 1;
-								tempFlags |= 0x800 | flagUnk1 | 0x100;
-							}
-
-							if (!(flagUnk3 & 0x100) && (flagUnk2 & 0x4000)) {
-								tempFlags = curObject->flags & 1;
-								tempFlags |= 0x900 | flagUnk1 | 0x4000;
-								_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | 4, _vm->_brandonPoisonFlagsGFX, int(1), int(_vm->_brandonInvFlag), drawLayer, _brandonScaleX, _brandonScaleY);
-							} else {
-								if (!(flagUnk2 & 0x4000)) {
-									tempFlags = curObject->flags & 1;
-									tempFlags |= 0x900 | flagUnk1;
-								}
-
-								_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | 4, _vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
-							}
-						}
-					} else {
-						if (shapesIndex != -1) {
-							int tempFlags = 0;
-							if (curObject->flags & 1)
-								tempFlags = 1;
-							_screen->drawShape(drawPage, _vm->_shapes[shapesIndex], xpos, ypos, 2, tempFlags | 0x800, drawLayer);
-						}
-					}
-				}
-			}
-
-			xpos = curObject->x1;
-			ypos = curObject->y1;
-
-			curObject->flags |= 0x800;
-			if (curObject->index == 0) {
-				flagUnk3 = 0x100;
-
-				if (flagUnk1 & 0x200 || flagUnk2 & 0x4000)
-					flagUnk3 = 0;
-
-				if (_vm->_brandonStatusBit & 2)
-					curObject->flags &= 0xFFFFFFFE;
-
-				if (!_vm->_scaleMode) {
-					if (flagUnk3 & 0x100)
-						_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x100, (uint8 *)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer);
-					else if (flagUnk2 & 0x4000)
-						_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4000, int(_vm->_brandonInvFlag), drawLayer);
-					else
-						_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1, drawLayer);
-				} else {
-					if (flagUnk3 & 0x100)
-						_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x104, (uint8 *)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY);
-					else if (flagUnk2 & 0x4000)
-						_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4004, int(_vm->_brandonInvFlag), drawLayer, _brandonScaleX, _brandonScaleY);
-					else
-						_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4, drawLayer, _brandonScaleX, _brandonScaleY);
-				}
-			} else {
-				if (curObject->index >= 16 && curObject->index <= 27)
-					_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | 4, drawLayer, (int)_vm->_scaleTable[curObject->drawY], (int)_vm->_scaleTable[curObject->drawY]);
-				else
-					_screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags, drawLayer);
-			}
-		}
-		curObject = curObject->nextAnimObject;
-	}
-}
-
-void Animator_LoK::copyChangedObjectsForward(int refreshFlag) {
-	for (AnimObject *curObject = _objectQueue; curObject; curObject = curObject->nextAnimObject) {
-		if (curObject->active) {
-			if (curObject->refreshFlag || refreshFlag) {
-				int xpos = 0, ypos = 0, width = 0, height = 0;
-				xpos = (curObject->x1 >> 3) - (curObject->width2 >> 3) - 1;
-				ypos = curObject->y1 - curObject->height2;
-				width = curObject->width + (curObject->width2 >> 3) + 2;
-				height = curObject->height + curObject->height2 * 2;
-
-				if (xpos < 1)
-					xpos = 1;
-				else if (xpos > 39)
-					continue;
-
-				if (xpos + width > 39)
-					width = 39 - xpos;
-
-				if (ypos < 8)
-					ypos = 8;
-				else if (ypos > 136)
-					continue;
-
-				if (ypos + height > 136)
-					height = 136 - ypos;
-
-				_screen->copyRegion(xpos << 3, ypos, xpos << 3, ypos, width << 3, height, 2, 0);
-				curObject->refreshFlag = 0;
-			}
-		}
-	}
-
-	_screen->updateScreen();
-}
-
-void Animator_LoK::updateAllObjectShapes() {
-	restoreAllObjectBackgrounds();
-	preserveAnyChangedBackgrounds();
-	prepDrawAllObjects();
-	copyChangedObjectsForward(0);
-}
-
-void Animator_LoK::animRemoveGameItem(int index) {
-	restoreAllObjectBackgrounds();
-
-	AnimObject *animObj = &_items[index];
-	animObj->sceneAnimPtr = 0;
-	animObj->animFrameNumber = -1;
-	animObj->refreshFlag = 1;
-	animObj->bkgdChangeFlag = 1;
-	updateAllObjectShapes();
-	animObj->active = 0;
-
-	objectRemoveQueue(_objectQueue, animObj);
-}
-
-void Animator_LoK::animAddGameItem(int index, uint16 sceneId) {
-	restoreAllObjectBackgrounds();
-	assert(sceneId < _vm->_roomTableSize);
-	Room *currentRoom = &_vm->_roomTable[sceneId];
-	AnimObject *animObj = &_items[index];
-	animObj->active = 1;
-	animObj->refreshFlag = 1;
-	animObj->bkgdChangeFlag = 1;
-	animObj->drawY = currentRoom->itemsYPos[index];
-	animObj->sceneAnimPtr = _vm->_shapes[216 + currentRoom->itemsTable[index]];
-	animObj->animFrameNumber = -1;
-	animObj->x1 = currentRoom->itemsXPos[index];
-	animObj->y1 = currentRoom->itemsYPos[index];
-	animObj->x1 -= fetchAnimWidth(animObj->sceneAnimPtr, _vm->_scaleTable[animObj->drawY]) >> 1;
-	animObj->y1 -= fetchAnimHeight(animObj->sceneAnimPtr, _vm->_scaleTable[animObj->drawY]);
-	animObj->x2 = animObj->x1;
-	animObj->y2 = animObj->y1;
-	animObj->width2 = 0;
-	animObj->height2 = 0;
-	_objectQueue = objectQueue(_objectQueue, animObj);
-	preserveAnyChangedBackgrounds();
-	animObj->refreshFlag = 1;
-	animObj->bkgdChangeFlag = 1;
-}
-
-void Animator_LoK::animAddNPC(int character) {
-	restoreAllObjectBackgrounds();
-	AnimObject *animObj = &_actors[character];
-	const Character *ch = &_vm->_characterList[character];
-
-	animObj->active = 1;
-	animObj->refreshFlag = 1;
-	animObj->bkgdChangeFlag = 1;
-	animObj->drawY = ch->y1;
-	animObj->sceneAnimPtr = _vm->_shapes[ch->currentAnimFrame];
-	animObj->x1 = animObj->x2 = ch->x1 + _vm->_defaultShapeTable[ch->currentAnimFrame - 7].xOffset;
-	animObj->y1 = animObj->y2 = ch->y1 + _vm->_defaultShapeTable[ch->currentAnimFrame - 7].yOffset;
-
-	if (ch->facing >= 1 && ch->facing <= 3)
-		animObj->flags |= 1;
-	else if (ch->facing >= 5 && ch->facing <= 7)
-		animObj->flags &= 0xFFFFFFFE;
-
-	_objectQueue = objectQueue(_objectQueue, animObj);
-	preserveAnyChangedBackgrounds();
-	animObj->refreshFlag = 1;
-	animObj->bkgdChangeFlag = 1;
-}
-
-Animator_LoK::AnimObject *Animator_LoK::objectRemoveQueue(AnimObject *queue, AnimObject *rem) {
-	AnimObject *cur = queue;
-	AnimObject *prev = queue;
-
-	while (cur != rem && cur) {
-		AnimObject *temp = cur->nextAnimObject;
-		if (!temp)
-			break;
-		prev = cur;
-		cur = temp;
-	}
-
-	if (cur == queue) {
-		if (!cur)
-			return 0;
-		return cur->nextAnimObject;
-	}
-
-	if (!cur->nextAnimObject) {
-		if (cur == rem) {
-			if (!prev)
-				return 0;
-			else
-				prev->nextAnimObject = 0;
-		}
-	} else {
-		if (cur == rem)
-			prev->nextAnimObject = rem->nextAnimObject;
-	}
-
-	return queue;
-}
-
-Animator_LoK::AnimObject *Animator_LoK::objectAddHead(AnimObject *queue, AnimObject *head) {
-	head->nextAnimObject = queue;
-	return head;
-}
-
-Animator_LoK::AnimObject *Animator_LoK::objectQueue(AnimObject *queue, AnimObject *add) {
-	if (!queue || add->drawY <= queue->drawY) {
-		add->nextAnimObject = queue;
-		return add;
-	}
-	AnimObject *cur = queue;
-	AnimObject *prev = queue;
-	while (add->drawY > cur->drawY) {
-		AnimObject *temp = cur->nextAnimObject;
-		if (!temp)
-			break;
-		prev = cur;
-		cur = temp;
-	}
-
-	if (add->drawY <= cur->drawY) {
-		prev->nextAnimObject = add;
-		add->nextAnimObject = cur;
-	} else {
-		cur->nextAnimObject = add;
-		add->nextAnimObject = 0;
-	}
-	return queue;
-}
-
-void Animator_LoK::addObjectToQueue(AnimObject *object) {
-	if (!_objectQueue)
-		_objectQueue = objectAddHead(0, object);
-	else
-		_objectQueue = objectQueue(_objectQueue, object);
-}
-
-void Animator_LoK::refreshObject(AnimObject *object) {
-	_objectQueue = objectRemoveQueue(_objectQueue, object);
-	if (_objectQueue)
-		_objectQueue = objectQueue(_objectQueue, object);
-	else
-		_objectQueue = objectAddHead(0, object);
-}
-
-void Animator_LoK::makeBrandonFaceMouse() {
-	Common::Point mouse = _vm->getMousePos();
-	if (mouse.x >= _vm->_currentCharacter->x1)
-		_vm->_currentCharacter->facing = 3;
-	else
-		_vm->_currentCharacter->facing = 5;
-	animRefreshNPC(0);
-	updateAllObjectShapes();
-}
-
-int16 Animator_LoK::fetchAnimWidth(const uint8 *shape, int16 mult) {
-	if (_vm->gameFlags().useAltShapeHeader)
-		shape += 2;
-	return (((int16)READ_LE_UINT16((shape + 3))) * mult) >> 8;
-}
-
-int16 Animator_LoK::fetchAnimHeight(const uint8 *shape, int16 mult) {
-	if (_vm->gameFlags().useAltShapeHeader)
-		shape += 2;
-	return (int16)(((int8)*(shape + 2)) * mult) >> 8;
-}
-
-void Animator_LoK::setBrandonAnimSeqSize(int width, int height) {
-	restoreAllObjectBackgrounds();
-	_brandonAnimSeqSizeWidth = _actors[0].width;
-	_brandonAnimSeqSizeHeight = _actors[0].height;
-	_actors[0].width = width + 1;
-	_actors[0].height = height;
-	preserveAllBackgrounds();
-}
-
-void Animator_LoK::resetBrandonAnimSeqSize() {
-	restoreAllObjectBackgrounds();
-	_actors[0].width = _brandonAnimSeqSizeWidth;
-	_actors[0].height = _brandonAnimSeqSizeHeight;
-	preserveAllBackgrounds();
-}
-
-void Animator_LoK::animRefreshNPC(int character) {
-	AnimObject *animObj = &_actors[character];
-	Character *ch = &_vm->characterList()[character];
-
-	animObj->refreshFlag = 1;
-	animObj->bkgdChangeFlag = 1;
-	int facing = ch->facing;
-	if (facing >= 1 && facing <= 3)
-		animObj->flags |= 1;
-	else if (facing >= 5 && facing <= 7)
-		animObj->flags &= 0xFFFFFFFE;
-
-	animObj->drawY = ch->y1;
-	animObj->sceneAnimPtr = _vm->shapes()[ch->currentAnimFrame];
-	animObj->animFrameNumber = ch->currentAnimFrame;
-	if (character == 0) {
-		if (_vm->brandonStatus() & 10) {
-			animObj->animFrameNumber = 88;
-			ch->currentAnimFrame = 88;
-		}
-		if (_vm->brandonStatus() & 2) {
-			animObj->animFrameNumber = _brandonDrawFrame;
-			ch->currentAnimFrame = _brandonDrawFrame;
-			animObj->sceneAnimPtr = _vm->shapes()[_brandonDrawFrame];
-			if (_vm->_brandonStatusBit0x02Flag) {
-				++_brandonDrawFrame;
-				// TODO: check this
-				if (_brandonDrawFrame >= 122) {
-					_brandonDrawFrame = 113;
-					_vm->_brandonStatusBit0x02Flag = 0;
-				}
-			}
-		}
-	}
-
-	int xOffset = _vm->_defaultShapeTable[ch->currentAnimFrame - 7].xOffset;
-	int yOffset = _vm->_defaultShapeTable[ch->currentAnimFrame - 7].yOffset;
-
-	if (_vm->_scaleMode) {
-		animObj->x1 = ch->x1;
-		animObj->y1 = ch->y1;
-
-		int newScale = _vm->_scaleTable[ch->y1];
-		_brandonScaleX = newScale;
-		_brandonScaleY = newScale;
-
-		animObj->x1 += (_brandonScaleX * xOffset) >> 8;
-		animObj->y1 += (_brandonScaleY * yOffset) >> 8;
-	} else {
-		animObj->x1 = ch->x1 + xOffset;
-		animObj->y1 = ch->y1 + yOffset;
-	}
-	animObj->width2 = 4;
-	animObj->height2 = 3;
-
-	refreshObject(animObj);
-}
-
-void Animator_LoK::setCharacterDefaultFrame(int character) {
-	static const uint16 initFrameTable[] = {
-		7, 41, 77, 0, 0
-	};
-	assert(character < ARRAYSIZE(initFrameTable));
-	Character *edit = &_vm->characterList()[character];
-	edit->sceneId = 0xFFFF;
-	edit->facing = 0;
-	edit->currentAnimFrame = initFrameTable[character];
-	// edit->unk6 = 1;
-}
-
-void Animator_LoK::setCharactersHeight() {
-	static const int8 initHeightTable[] = {
-		48, 40, 48, 47, 56,
-		44, 42, 47, 38, 35,
-		40
-	};
-	for (int i = 0; i < 11; ++i)
-		_vm->characterList()[i].height = initHeightTable[i];
-}
-
-} // End of namespace Kyra
diff --git a/engines/kyra/animator_lok.h b/engines/kyra/animator_lok.h
deleted file mode 100644
index 55c4d57..0000000
--- a/engines/kyra/animator_lok.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KYRA_ANIMATOR_LOK_H
-#define KYRA_ANIMATOR_LOK_H
-
-namespace Kyra {
-class KyraEngine_LoK;
-class Screen;
-
-class Animator_LoK {
-public:
-	struct AnimObject {
-		uint8 index;
-		uint32 active;
-		uint32 refreshFlag;
-		uint32 bkgdChangeFlag;
-		bool disable;
-		uint32 flags;
-		int16 drawY;
-		uint8 *sceneAnimPtr;
-		int16 animFrameNumber;
-		uint8 *background;
-		uint16 rectSize;
-		int16 x1, y1;
-		int16 x2, y2;
-		uint16 width;
-		uint16 height;
-		uint16 width2;
-		uint16 height2;
-		AnimObject *nextAnimObject;
-	};
-
-	Animator_LoK(KyraEngine_LoK *vm, OSystem *system);
-	virtual ~Animator_LoK();
-
-	operator bool() const { return _initOk; }
-
-	void init(int actors, int items, int sprites);
-	void close();
-
-	AnimObject *objects() { return _screenObjects; }
-	AnimObject *actors() { return _actors; }
-	AnimObject *items() { return _items; }
-	AnimObject *sprites() { return _sprites; }
-
-	void initAnimStateList();
-	void preserveAllBackgrounds();
-	void flagAllObjectsForBkgdChange();
-	void flagAllObjectsForRefresh();
-	void restoreAllObjectBackgrounds();
-	void preserveAnyChangedBackgrounds();
-	virtual void prepDrawAllObjects();
-	void copyChangedObjectsForward(int refreshFlag);
-
-	void updateAllObjectShapes();
-	void animRemoveGameItem(int index);
-	void animAddGameItem(int index, uint16 sceneId);
-	void animAddNPC(int character);
-	void animRefreshNPC(int character);
-
-	void clearQueue() { _objectQueue = 0; }
-	void addObjectToQueue(AnimObject *object);
-	void refreshObject(AnimObject *object);
-
-	void makeBrandonFaceMouse();
-	void setBrandonAnimSeqSize(int width, int height);
-	void resetBrandonAnimSeqSize();
-	void setCharacterDefaultFrame(int character);
-	void setCharactersHeight();
-
-	int16 fetchAnimWidth(const uint8 *shape, int16 mult);
-	int16 fetchAnimHeight(const uint8 *shape, int16 mult);
-
-	int _noDrawShapesFlag;
-	uint16 _brandonDrawFrame;
-	int _brandonScaleX;
-	int _brandonScaleY;
-
-protected:
-	KyraEngine_LoK *_vm;
-	Screen *_screen;
-	OSystem *_system;
-	bool _initOk;
-
-	AnimObject *_screenObjects;
-
-	AnimObject *_actors;
-	AnimObject *_items;
-	AnimObject *_sprites;
-
-	uint8 *_actorBkgBackUp[2];
-
-	AnimObject *objectRemoveQueue(AnimObject *queue, AnimObject *rem);
-	AnimObject *objectAddHead(AnimObject *queue, AnimObject *head);
-	AnimObject *objectQueue(AnimObject *queue, AnimObject *add);
-
-	void preserveOrRestoreBackground(AnimObject *obj, bool restore);
-
-	AnimObject *_objectQueue;
-
-	int _brandonAnimSeqSizeWidth;
-	int _brandonAnimSeqSizeHeight;
-};
-
-} // End of namespace Kyra
-
-#endif
diff --git a/engines/kyra/animator_mr.cpp b/engines/kyra/animator_mr.cpp
deleted file mode 100644
index 3b9454c..0000000
--- a/engines/kyra/animator_mr.cpp
+++ /dev/null
@@ -1,456 +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 "kyra/kyra_mr.h"
-#include "kyra/resource.h"
-#include "kyra/wsamovie.h"
-
-#include "common/system.h"
-
-namespace Kyra {
-
-void KyraEngine_MR::restorePage3() {
-	screen()->copyBlockToPage(2, 0, 0, 320, 200, _gamePlayBuffer);
-}
-
-void KyraEngine_MR::clearAnimObjects() {
-	for (int i = 0; i < 67; ++i)
-		_animObjects[i].enabled = false;
-
-	_animObjects[0].index = 0;
-	_animObjects[0].type = 0;
-	_animObjects[0].enabled = true;
-	_animObjects[0].specialRefresh = 1;
-	_animObjects[0].flags = 0x800;
-	_animObjects[0].width = 57;
-	_animObjects[0].height = 91;
-	_animObjects[0].width2 = 4;
-	_animObjects[0].height2 = 10;
-
-	for (int i = 1; i < 17; ++i) {
-		_animObjects[i].index = i;
-		_animObjects[i].type = 2;
-		_animObjects[i].flags = 0;
-		_animObjects[i].enabled = false;
-		_animObjects[i].needRefresh = 0;
-		_animObjects[i].specialRefresh = 1;
-	}
-
-	for (int i = 17; i <= 66; ++i) {
-		_animObjects[i].index = i;
-		_animObjects[i].type = 1;
-		_animObjects[i].specialRefresh = 1;
-		_animObjects[i].flags = 0x800;
-		_animObjects[i].width = 24;
-		_animObjects[i].height = 20;
-		_animObjects[i].width2 = 0;
-		_animObjects[i].height2 = 0;
-	}
-}
-
-void KyraEngine_MR::animSetupPaletteEntry(AnimObj *anim) {
-	int layer = _screen->getLayer(anim->xPos1, anim->yPos1) - 1;
-	int16 count = 0;
-	for (int i = 0; i < 3; ++i)
-		count += _sceneDatPalette[layer*3+i];
-	count /= 3;
-	count *= -1;
-	count = MAX<int16>(0, MIN<int16>(count, 10));
-	anim->palette = count / 3;
-}
-
-void KyraEngine_MR::drawAnimObjects() {
-	for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
-		if (!curObject->enabled)
-			continue;
-
-		int x = curObject->xPos2 - (_screen->getScreenDim(2)->sx << 3);
-		int y = curObject->yPos2 - _screen->getScreenDim(2)->sy;
-		int layer = 7;
-
-		if (curObject->flags & 0x800) {
-			if (!curObject->specialRefresh)
-				layer = 0;
-			else
-				layer = getDrawLayer(curObject->xPos1, curObject->yPos1);
-		}
-
-		if (curObject->index)
-			drawSceneAnimObject(curObject, x, y, layer);
-		else
-			drawCharacterAnimObject(curObject, x, y, layer);
-	}
-}
-
-void KyraEngine_MR::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) {
-	if (obj->type == 1) {
-		if (obj->shapeIndex1 == 0xFFFF)
-			return;
-		int scale = getScale(obj->xPos1, obj->yPos1);
-		_screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 0x104, _paletteOverlay, obj->palette, layer, scale, scale);
-	} else {
-		if (obj->shapePtr) {
-			_screen->drawShape(2, obj->shapePtr, x, y, 2, obj->flags, 7);
-		} else {
-			if (obj->shapeIndex3 == 0xFFFF || obj->animNum == 0xFFFF)
-				return;
-			uint16 flags = 0x4000;
-			if (obj->flags & 0x800)
-				flags |= 0x8000;
-			x = obj->xPos2 - _sceneAnimMovie[obj->animNum]->xAdd();
-			y = obj->yPos2 - _sceneAnimMovie[obj->animNum]->yAdd();
-			_sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, 2, x, y, flags | layer, 0, 0);
-		}
-	}
-}
-
-void KyraEngine_MR::drawCharacterAnimObject(AnimObj *obj, int x, int y, int layer) {
-	if (_drawNoShapeFlag)
-		return;
-
-	if (_mainCharacter.animFrame < 9)
-		_mainCharacter.animFrame = 87;
-
-	if (obj->shapeIndex1 == 0xFFFF || _mainCharacter.animFrame == 87)
-		return;
-
-	_screen->drawShape(2, getShapePtr(421), _mainCharacter.x3, _mainCharacter.y3, 2, obj->flags | 0x304, _paletteOverlay, 3, layer, _charScale, _charScale);
-	uint8 *shape = getShapePtr(_mainCharacter.animFrame);
-	if (shape)
-		_screen->drawShape(2, shape, x, y, 2, obj->flags | 4, layer, _charScale, _charScale);
-}
-
-void KyraEngine_MR::refreshAnimObjects(int force) {
-	for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
-		if (!curObject->enabled)
-			continue;
-		if (!curObject->needRefresh && !force)
-			continue;
-
-		const int scale = (curObject->index == 0) ? _charScale : 0;
-
-		int x = curObject->xPos2 - curObject->width2;
-		if (scale)
-			x -= (0x100 - scale) >> 4;
-
-		if (x < 0)
-			x = 0;
-		if (x >= 320)
-			x = 319;
-
-		int y = curObject->yPos2 - curObject->height2;
-		if (scale)
-			y -= (0x100 - scale) >> 3;
-		if (y < 0)
-			y = 0;
-		if (y >= 187)
-			y = 186;
-
-		int width = curObject->width + curObject->width2 + 8;
-		int height = curObject->height + curObject->height2*2;
-		if (width + x > 320)
-			width -= width + x - 322;
-
-		const int maxY = _inventoryState ? 143 : 187;
-		if (height + y > maxY)
-			height -= height + y - (maxY + 1);
-
-		if (height > 0) {
-			_screen->copyRegion(x, y, x, y, width, height, 2, 0, Screen::CR_NO_P_CHECK);
-		}
-
-		curObject->needRefresh = false;
-	}
-}
-
-void KyraEngine_MR::updateItemAnimations() {
-	bool nextFrame = false;
-
-	if (_itemAnimDefinition[0].itemIndex == -1)
-		return;
-
-	const ItemAnimDefinition *s = &_itemAnimDefinition[_nextAnimItem];
-	ActiveItemAnim *a = &_activeItemAnim[_nextAnimItem];
-	_nextAnimItem = (_nextAnimItem + 1) % 10;
-
-	if (_system->getMillis() < a->nextFrameTime)
-		return;
-
-	uint16 shpIdx = s->frames[a->currentFrame].index + 248;
-	if (s->itemIndex == _mouseState && s->itemIndex == _itemInHand && _screen->isMouseVisible()) {
-		nextFrame = true;
-		_screen->setMouseCursor(12, 19, getShapePtr(shpIdx));
-	}
-
-	if (_inventoryState) {
-		for (int i = 0; i < 10; i++) {
-			if (s->itemIndex == _mainCharacter.inventory[i]) {
-				nextFrame = true;
-				_screen->drawShape(2, getShapePtr(422 + i), 9, 0, 0, 0);
-				_screen->drawShape(2, getShapePtr(shpIdx), 9, 0, 0, 0);
-				_screen->copyRegion(9, 0, _inventoryX[i], _inventoryY[i], 24, 20, 2, 0, Screen::CR_NO_P_CHECK);
-			}
-		}
-	}
-
-	_screen->updateScreen();
-
-	for (int i = 17; i < 66; i++) {
-		AnimObj *animObject = &_animObjects[i];
-		if (animObject->shapeIndex2 == s->itemIndex + 248) {
-			animObject->shapePtr = getShapePtr(shpIdx);
-			animObject->shapeIndex1 = shpIdx;
-			animObject->needRefresh = true;
-			nextFrame = true;
-		}
-	}
-
-	if (nextFrame) {
-		a->nextFrameTime = _system->getMillis() + (s->frames[a->currentFrame].delay * _tickLength);
-		a->currentFrame = (a->currentFrame + 1) % s->numFrames;
-	}
-}
-
-void KyraEngine_MR::updateCharacterAnim(int charId) {
-	AnimObj *obj = &_animObjects[0];
-	obj->needRefresh = true;
-	obj->flags &= ~1;
-	obj->xPos1 = _mainCharacter.x1;
-	obj->yPos1 = _mainCharacter.y1;
-	obj->shapePtr = getShapePtr(_mainCharacter.animFrame);
-	obj->shapeIndex1 = obj->shapeIndex2 = _mainCharacter.animFrame;
-
-	int shapeOffsetX = 0, shapeOffsetY = 0;
-	if (_mainCharacter.animFrame >= 50 && _mainCharacter.animFrame <= 87) {
-		shapeOffsetX = _malcolmShapeXOffset;
-		shapeOffsetY = _malcolmShapeYOffset;
-	} else {
-		shapeOffsetX = _animShapeXAdd;
-		shapeOffsetY = _animShapeYAdd;
-	}
-
-	obj->xPos2 = _mainCharacter.x1;
-	obj->yPos2 = _mainCharacter.y1;
-	_charScale = getScale(_mainCharacter.x1, _mainCharacter.y1);
-	obj->xPos2 += (shapeOffsetX * _charScale) >> 8;
-	obj->yPos2 += (shapeOffsetY * _charScale) >> 8;
-	_mainCharacter.x3 = _mainCharacter.x1 - (_charScale >> 4) - 1;
-	_mainCharacter.y3 = _mainCharacter.y1 - (_charScale >> 6) - 1;
-	if (_charBackUpWidth2 == -1) {
-		obj->width2 = 4;
-		obj->height2 = 10;
-	}
-
-	for (int i = 1; i <= 16; ++i) {
-		if (_animObjects[i].enabled && _animObjects[i].specialRefresh)
-			_animObjects[i].needRefresh = true;
-	}
-
-	_animList = deleteAnimListEntry(_animList, obj);
-	if (_animList)
-		_animList = addToAnimListSorted(_animList, obj);
-	else
-		_animList = initAnimList(_animList, obj);
-
-	if (!_loadingState)
-		updateCharPal(1);
-}
-
-void KyraEngine_MR::updateSceneAnim(int anim, int newFrame) {
-	AnimObj *animObject = &_animObjects[1+anim];
-	if (!animObject->enabled)
-		return;
-
-	animObject->needRefresh = true;
-
-	if (_sceneAnims[anim].flags & 2)
-		animObject->flags |= 1;
-	else
-		animObject->flags &= ~1;
-
-	if (_sceneAnims[anim].flags & 4) {
-		animObject->shapePtr = _sceneShapes[newFrame];
-		animObject->shapeIndex2 = 0xFFFF;
-		animObject->shapeIndex3 = 0xFFFF;
-		animObject->animNum = 0xFFFF;
-	} else {
-		animObject->shapePtr = 0;
-		animObject->shapeIndex3 = newFrame;
-		animObject->animNum = anim;
-	}
-
-	animObject->xPos1 = _sceneAnims[anim].x;
-	animObject->yPos1 = _sceneAnims[anim].y;
-	animObject->xPos2 = _sceneAnims[anim].x2;
-	animObject->yPos2 = _sceneAnims[anim].y2;
-
-	if (_sceneAnims[anim].flags & 0x20) {
-		_animList = deleteAnimListEntry(_animList, animObject);
-		if (!_animList)
-			_animList = initAnimList(_animList, animObject);
-		else
-			_animList = addToAnimListSorted(_animList, animObject);
-	}
-}
-
-void KyraEngine_MR::setupSceneAnimObject(int animId, uint16 flags, int x, int y, int x2, int y2, int w,
-										int h, int unk10, int specialSize, int unk14, int shape, const char *filename) {
-	restorePage3();
-	SceneAnim &anim = _sceneAnims[animId];
-	anim.flags = flags;
-	anim.x = x;
-	anim.y = y;
-	anim.x2 = x2;
-	anim.y2 = y2;
-	anim.width = w;
-	anim.height = h;
-	anim.specialSize = specialSize;
-	anim.shapeIndex = shape;
-	if (filename)
-		strcpy(anim.filename, filename);
-
-	if (flags & 8) {
-		_sceneAnimMovie[animId]->open(filename, 1, 0);
-		if (_sceneAnimMovie[animId]->opened()) {
-			anim.wsaFlag = 1;
-			if (x2 == -1)
-				x2 = _sceneAnimMovie[animId]->xAdd();
-			if (y2 == -1)
-				y2 = _sceneAnimMovie[animId]->yAdd();
-			if (w == -1)
-				w = _sceneAnimMovie[animId]->width();
-			if (h == -1)
-				h = _sceneAnimMovie[animId]->height();
-			if (x == -1)
-				x = (w >> 1) + x2;
-			if (y == -1)
-				y = y2 + h - 1;
-
-			anim.x = x;
-			anim.y = y;
-			anim.x2 = x2;
-			anim.y2 = y2;
-			anim.width = w;
-			anim.height = h;
-		}
-	}
-
-	AnimObj *obj = &_animObjects[1+animId];
-	obj->enabled = true;
-	obj->needRefresh = true;
-
-	obj->specialRefresh = (anim.flags & 0x20) ? 1 : 0;
-	obj->flags = (anim.flags & 0x10) ? 0x800 : 0;
-	if (anim.flags & 2)
-		obj->flags |= 1;
-
-	obj->xPos1 = anim.x;
-	obj->yPos1 = anim.y;
-
-	if ((anim.flags & 4) && anim.shapeIndex != -1)
-		obj->shapePtr = _sceneShapes[anim.shapeIndex];
-	else
-		obj->shapePtr = 0;
-
-	if (anim.flags & 8) {
-		obj->shapeIndex3 = anim.shapeIndex;
-		obj->animNum = animId;
-	} else {
-		obj->shapeIndex3 = 0xFFFF;
-		obj->animNum = 0xFFFF;
-	}
-
-	obj->xPos3 = obj->xPos2 = anim.x2;
-	obj->yPos3 = obj->yPos2 = anim.y2;
-	obj->width = anim.width;
-	obj->height = anim.height;
-	obj->width2 = obj->height2 = anim.specialSize;
-
-	if (_animList)
-		_animList = addToAnimListSorted(_animList, obj);
-	else
-		_animList = initAnimList(_animList, obj);
-}
-
-void KyraEngine_MR::removeSceneAnimObject(int anim, int refresh) {
-	AnimObj *obj = &_animObjects[anim+1];
-	restorePage3();
-	obj->shapeIndex3 = 0xFFFF;
-	obj->animNum = 0xFFFF;
-	obj->needRefresh = true;
-
-	if (refresh)
-		refreshAnimObjectsIfNeed();
-
-	obj->enabled = false;
-	_animList = deleteAnimListEntry(_animList, obj);
-	_sceneAnimMovie[anim]->close();
-}
-
-void KyraEngine_MR::setCharacterAnimDim(int w, int h) {
-	restorePage3();
-	_charBackUpWidth = _animObjects[0].width;
-	_charBackUpWidth2 = _animObjects[0].width2;
-	_charBackUpHeight = _animObjects[0].height;
-	_charBackUpHeight2 = _animObjects[0].height2;
-
-	_animObjects[0].width2 = (w - _charBackUpWidth) / 2;
-	_animObjects[0].height2 = h - _charBackUpHeight;
-	_animObjects[0].width = w;
-	_animObjects[0].height = h;
-}
-
-void KyraEngine_MR::resetCharacterAnimDim() {
-	restorePage3();
-	_animObjects[0].width2 = _charBackUpWidth2;
-	_animObjects[0].height2 = _charBackUpHeight2;
-	_animObjects[0].width = _charBackUpWidth;
-	_animObjects[0].height = _charBackUpHeight;
-	_charBackUpWidth2 = _charBackUpHeight2 = -1;
-	_charBackUpWidth = _charBackUpHeight = -1;
-}
-
-void KyraEngine_MR::showIdleAnim() {
-	if (_mainCharacter.sceneId == 20 || _mainCharacter.sceneId == 21
-			|| _mainCharacter.sceneId == 12 || _mainCharacter.sceneId == 11)
-		return;
-
-	if (_mainCharacter.animFrame == 87)
-		return;
-
-	if (!_nextIdleType && !talkObjectsInCurScene()) {
-		randomSceneChat();
-	} else {
-		static const char *const facingTable[] = {
-			"A", "R", "R", "FR", "FX", "FL", "L", "L"
-		};
-
-		Common::String filename = Common::String::format( "MI0%s%.02d.EMC", facingTable[_mainCharacter.facing], _characterShapeFile);
-
-		if (_res->exists(filename.c_str()))
-			runAnimationScript(filename.c_str(), 1, 1, 1, 1);
-	}
-
-	_nextIdleType = !_nextIdleType;
-}
-
-} // End of namespace Kyra
diff --git a/engines/kyra/animator_tim.cpp b/engines/kyra/animator_tim.cpp
deleted file mode 100644
index b1cfc6a..0000000
--- a/engines/kyra/animator_tim.cpp
+++ /dev/null
@@ -1,235 +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 "kyra/script_tim.h"
-#include "kyra/wsamovie.h"
-#include "kyra/screen_lol.h"
-
-#ifdef ENABLE_LOL
-#include "kyra/lol.h"
-#else
-#include "kyra/screen_v2.h"
-#endif
-
-#include "common/system.h"
-
-namespace Kyra {
-
-#ifdef ENABLE_LOL
-TimAnimator::TimAnimator(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts) : _vm(engine), _screen(screen_v2), _system(system), _useParts(useParts) {
-#else
-TimAnimator::TimAnimator(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSystem *system, bool useParts) : _vm(engine), _screen(screen_v2), _system(system), _useParts(useParts) {
-#endif
-	_animations = new Animation[TIM::kWSASlots];
-	memset(_animations, 0, TIM::kWSASlots * sizeof(Animation));
-
-	if (_useParts) {
-		for (int i = 0; i < TIM::kWSASlots; i++) {
-			_animations[i].parts = new AnimPart[TIM::kAnimParts];
-			memset(_animations[i].parts, 0, TIM::kAnimParts * sizeof(AnimPart));
-		}
-	}
-}
-
-TimAnimator::~TimAnimator() {
-	for (int i = 0; i < TIM::kWSASlots; i++) {
-		delete _animations[i].wsa;
-		if (_useParts)
-			delete[] _animations[i].parts;
-	}
-
-	delete[] _animations;
-}
-
-void TimAnimator::init(int animIndex, Movie *wsa, int x, int y, int wsaCopyParams, int frameDelay) {
-	Animation *anim = &_animations[animIndex];
-	anim->wsa = wsa;
-	anim->x = x;
-	anim->y = y;
-	anim->wsaCopyParams = wsaCopyParams;
-	anim->frameDelay = frameDelay;
-	anim->enable = 0;
-	anim->lastPart = -1;
-}
-
-void TimAnimator::reset(int animIndex, bool clearStruct) {
-	Animation *anim = &_animations[animIndex];
-	if (!anim)
-		return;
-	anim->field_D = 0;
-	anim->enable = 0;
-	delete anim->wsa;
-	anim->wsa = 0;
-
-	if (clearStruct) {
-		if (_useParts)
-			delete[] anim->parts;
-
-		memset(anim, 0, sizeof(Animation));
-
-		if (_useParts) {
-			anim->parts = new AnimPart[TIM::kAnimParts];
-			memset(anim->parts, 0, TIM::kAnimParts * sizeof(AnimPart));
-		}
-	}
-}
-
-void TimAnimator::displayFrame(int animIndex, int page, int frame, int flags) {
-	Animation *anim = &_animations[animIndex];
-	if ((anim->wsaCopyParams & 0x4000) != 0)
-		page = 2;
-	// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
-	if (anim->wsa)
-		anim->wsa->displayFrame(frame, page, anim->x, anim->y, (flags == -1) ? (anim->wsaCopyParams & 0xF0FF) : flags, 0, 0);
-	if (!page)
-		_screen->updateScreen();
-}
-
-#ifdef ENABLE_LOL
-void TimAnimator::setupPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame) {
-	AnimPart *a = &_animations[animIndex].parts[part];
-	a->firstFrame = firstFrame;
-	a->lastFrame = lastFrame;
-	a->cycles = cycles;
-	a->nextPart = nextPart;
-	a->partDelay = partDelay;
-	a->field_A = f;
-	a->sfxIndex = sfxIndex;
-	a->sfxFrame = sfxFrame;
-}
-
-void TimAnimator::start(int animIndex, int part) {
-	if (!_vm || !_system || !_screen)
-		return;
-
-	Animation *anim = &_animations[animIndex];
-	anim->curPart = part;
-	AnimPart *p = &anim->parts[part];
-	anim->enable = 1;
-	anim->nextFrame = _system->getMillis() + anim->frameDelay * _vm->_tickLength;
-	anim->curFrame = p->firstFrame;
-	anim->cyclesCompleted = 0;
-
-	// WORKAROUND for some bugged scripts that will try to display frames of non-existent animations
-	if (anim->wsa)
-		anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
-}
-
-void TimAnimator::stop(int animIndex) {
-	Animation *anim = &_animations[animIndex];
-	anim->enable = 0;
-	anim->field_D = 0;
-	if (animIndex == 5) {
-		delete anim->wsa;
-		anim->wsa = 0;
-	}
-}
-
-void TimAnimator::update(int animIndex) {
-	if (!_vm || !_system || !_screen)
-		return;
-
-	Animation *anim = &_animations[animIndex];
-	if (!anim->enable || anim->nextFrame >= _system->getMillis())
-		return;
-
-	AnimPart *p = &anim->parts[anim->curPart];
-	anim->nextFrame = 0;
-
-	int step = 0;
-	if (p->lastFrame >= p->firstFrame) {
-		step = 1;
-		anim->curFrame++;
-	} else {
-		step = -1;
-		anim->curFrame--;
-	}
-
-	if (anim->curFrame == (p->lastFrame + step)) {
-		anim->cyclesCompleted++;
-
-		if ((anim->cyclesCompleted > p->cycles) || anim->field_D) {
-			anim->lastPart = anim->curPart;
-
-			if ((p->nextPart == -1) || (anim->field_D && p->field_A)) {
-				anim->enable = 0;
-				anim->field_D = 0;
-				return;
-			}
-
-			anim->nextFrame += (p->partDelay * _vm->_tickLength);
-			anim->curPart = p->nextPart;
-
-			p = &anim->parts[anim->curPart];
-			anim->curFrame = p->firstFrame;
-			anim->cyclesCompleted = 0;
-
-		} else {
-			anim->curFrame = p->firstFrame;
-		}
-	}
-
-	if (p->sfxIndex != -1 && p->sfxFrame == anim->curFrame)
-		_vm->snd_playSoundEffect(p->sfxIndex, -1);
-
-	anim->nextFrame += (anim->frameDelay * _vm->_tickLength);
-
-	anim->wsa->displayFrame(anim->curFrame - 1, 0, anim->x, anim->y, 0, 0, 0);
-	anim->nextFrame += _system->getMillis();
-}
-
-void TimAnimator::playPart(int animIndex, int firstFrame, int lastFrame, int delay) {
-	if (!_vm || !_system || !_screen)
-		return;
-
-	Animation *anim = &_animations[animIndex];
-	// WORKAROUND for some bugged scripts that will try to play invalid animations
-	if (!anim->wsa)
-		return;
-
-	int step = (lastFrame >= firstFrame) ? 1 : -1;
-	for (int i = firstFrame; i != (lastFrame + step); i += step) {
-		uint32 next = _system->getMillis() + delay * _vm->_tickLength;
-		if (anim->wsaCopyParams & 0x4000) {
-			_screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 2);
-			anim->wsa->displayFrame(i - 1, 2, anim->x, anim->y, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_transparencyTable1, _vm->_transparencyTable2);
-			_screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0);
-			_screen->updateScreen();
-		} else {
-			anim->wsa->displayFrame(i - 1, 0, anim->x, anim->y, 0, 0, 0);
-			_screen->updateScreen();
-		}
-		int32 del  = (int32)(next - _system->getMillis());
-		if (del > 0)
-			_vm->delay(del, true);
-	}
-}
-
-int TimAnimator::resetLastPart(int animIndex) {
-	Animation *anim = &_animations[animIndex];
-	int8 res = -1;
-	SWAP(res, anim->lastPart);
-	return res;
-}
-#endif
-
-} // End of namespace Kyra
diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp
deleted file mode 100644
index 5ac154b..0000000
--- a/engines/kyra/animator_v2.cpp
+++ /dev/null
@@ -1,187 +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 "kyra/kyra_v2.h"
-#include "kyra/screen_v2.h"
-
-namespace Kyra {
-
-void KyraEngine_v2::allocAnimObjects(int actors, int anims, int items) {
-	_animObjects = new AnimObj[actors + anims + items];
-	assert(_animObjects);
-
-	memset(_animObjects, 0, sizeof(AnimObj) * (actors + anims + items));
-
-	_animActor = _animObjects;
-	_animAnims = _animObjects + actors;
-	_animItems = _animObjects + actors + anims;
-}
-
-KyraEngine_v2::AnimObj *KyraEngine_v2::initAnimList(AnimObj *list, AnimObj *entry) {
-	entry->nextObject = list;
-	return entry;
-}
-
-KyraEngine_v2::AnimObj *KyraEngine_v2::addToAnimListSorted(AnimObj *list, AnimObj *add) {
-	add->nextObject = 0;
-
-	if (!list)
-		return add;
-
-	if (add->yPos1 <= list->yPos1) {
-		add->nextObject = list;
-		return add;
-	}
-
-	AnimObj *cur = list;
-	AnimObj *prev = list;
-	while (add->yPos1 > cur->yPos1) {
-		AnimObj *temp = cur->nextObject;
-		if (!temp)
-			break;
-		prev = cur;
-		cur = temp;
-	}
-
-	if (add->yPos1 <= cur->yPos1) {
-		prev->nextObject = add;
-		add->nextObject = cur;
-	} else {
-		cur->nextObject = add;
-		add->nextObject = 0;
-	}
-	return list;
-}
-
-KyraEngine_v2::AnimObj *KyraEngine_v2::deleteAnimListEntry(AnimObj *list, AnimObj *entry) {
-	if (!list)
-		return 0;
-
-	AnimObj *old = 0;
-	AnimObj *cur = list;
-
-	while (true) {
-		if (cur == entry)
-			break;
-		if (!cur->nextObject)
-			break;
-		old = cur;
-		cur = cur->nextObject;
-	}
-
-	if (cur != entry)
-		return list;
-
-	if (cur == list) {
-		if (!cur->nextObject)
-			return 0;
-		cur = cur->nextObject;
-		return cur;
-	}
-
-	if (!cur->nextObject) {
-		if (!old)
-			return 0;
-		old->nextObject = 0;
-		return list;
-	}
-
-	if (cur != entry)
-		return list;
-
-	old->nextObject = entry->nextObject;
-	return list;
-}
-
-void KyraEngine_v2::refreshAnimObjectsIfNeed() {
-	for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) {
-		if (curEntry->enabled && curEntry->needRefresh) {
-			restorePage3();
-			drawAnimObjects();
-			refreshAnimObjects(0);
-			screen()->updateScreen();
-			return;
-		}
-	}
-}
-
-void KyraEngine_v2::flagAnimObjsForRefresh() {
-	for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject)
-		curEntry->needRefresh = 1;
-}
-
-void KyraEngine_v2::flagAnimObjsSpecialRefresh() {
-	for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject)
-		curEntry->specialRefresh = 1;
-}
-
-void KyraEngine_v2::addItemToAnimList(int item) {
-	assert(item >= 0 && item < _itemListSize);
-
-	restorePage3();
-
-	AnimObj *animObj = _animItems + item;
-
-	animObj->enabled = 1;
-	animObj->needRefresh = 1;
-
-	int itemId = _itemList[item].id;
-
-	animObj->xPos2 = animObj->xPos1 = _itemList[item].x;
-	animObj->yPos2 = animObj->yPos1 = _itemList[item].y;
-
-	animObj->shapePtr = getShapePtr(itemId + _desc.itemShapeStart);
-	animSetupPaletteEntry(animObj);
-	animObj->shapeIndex2 = animObj->shapeIndex1 = itemId + _desc.itemShapeStart;
-
-	int scaleY, scaleX;
-	scaleY = scaleX = getScale(animObj->xPos1, animObj->yPos1);
-
-	uint8 *shapePtr = getShapePtr(itemId + _desc.itemShapeStart);
-	animObj->xPos3 = (animObj->xPos2 -= (screen_v2()->getShapeScaledWidth(shapePtr, scaleX) >> 1));
-	animObj->yPos3 = (animObj->yPos2 -= screen_v2()->getShapeScaledHeight(shapePtr, scaleY));
-
-	animObj->width2 = animObj->height2 = 0;
-
-	_animList = addToAnimListSorted(_animList, animObj);
-	animObj->needRefresh = 1;
-}
-
-void KyraEngine_v2::deleteItemAnimEntry(int item) {
-	assert(item < _itemListSize);
-
-	AnimObj *animObj = _animItems + item;
-
-	restorePage3();
-
-	animObj->shapePtr = 0;
-	animObj->shapeIndex1 = 0xFFFF;
-	animObj->shapeIndex2 = 0xFFFF;
-	animObj->needRefresh = 1;
-
-	refreshAnimObjectsIfNeed();
-
-	animObj->enabled = 0;
-	_animList = deleteAnimListEntry(_animList, animObj);
-}
-
-} // End of namespace Kyra
diff --git a/engines/kyra/chargen.cpp b/engines/kyra/chargen.cpp
deleted file mode 100644
index 4724770..0000000
--- a/engines/kyra/chargen.cpp
+++ /dev/null
@@ -1,1982 +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.
- *
- */
-
-#ifdef ENABLE_EOB
-
-#include "kyra/eobcommon.h"
-#include "kyra/resource.h"
-#include "kyra/sound_intern.h"
-
-#include "common/savefile.h"
-#include "common/str-array.h"
-
-#include "common/config-manager.h"
-#include "base/plugins.h"
-#include "engines/metaengine.h"
-#include "engines/game.h"
-
-namespace Kyra {
-
-// Character Generator
-
-class CharacterGenerator {
-public:
-	CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen);
-	~CharacterGenerator();
-
-	bool start(EoBCharacter *characters, uint8 ***faceShapes);
-
-private:
-	void init();
-	void initButtonsFromList(int first, int numButtons);
-	void initButton(int index, int x, int y, int w, int h, int keyCode);
-	void checkForCompleteParty();
-	void toggleSpecialButton(int index, int bodyCustom, int pageNum);
-	void processSpecialButton(int index);
-	int viewDeleteCharacter();
-	void createPartyMember();
-	int raceSexMenu();
-	int classMenu(int raceSex);
-	int alignmentMenu(int cClass);
-	int getInput(Button *buttonList);
-	void updateMagicShapes();
-	void generateStats(int index);
-	void modifyMenu();
-	void statsAndFacesMenu();
-	void faceSelectMenu();
-	int getNextFreeFaceShape(int shpIndex, int charSex, int step, int8 *selectedPortraits);
-	void processFaceMenuSelection(int index);
-	void printStats(int index, int mode);
-	void processNameInput(int index, int textColor);
-	int rollDice();
-	int modifyStat(int index, int8 *stat1, int8 *stat2);
-	int getMaxHp(int cclass, int constitution, int level1, int level2, int level3);
-	int getMinHp(int cclass, int constitution, int level1, int level2, int level3);
-	void finish();
-
-	uint8 **_chargenMagicShapes;
-	uint8 *_chargenButtonLabels[17];
-	int _activeBox;
-	int _magicShapesBox;
-	int _updateBoxShapesIndex;
-	int _lastUpdateBoxShapesIndex;
-	uint32 _chargenMagicShapeTimer;
-	int8 _chargenSelectedPortraits[4];
-	int8 _chargenSelectedPortraits2[4];
-
-	uint16 _chargenMinStats[7];
-	uint16 _chargenMaxStats[7];
-
-	const char *const *_chargenStrings1;
-	const char *const *_chargenStrings2;
-	const char *const *_chargenStatStrings;
-	const char *const *_chargenRaceSexStrings;
-	const char *const *_chargenClassStrings;
-	const char *const *_chargenAlignmentStrings;
-	const char *const *_chargenEnterGameStrings;
-
-	const uint8 *_chargenStartLevels;
-	const uint8 *_chargenClassMinStats;
-	const uint8 *_chargenRaceMinStats;
-	const uint16 *_chargenRaceMaxStats;
-
-	const EoBChargenButtonDef *_chargenButtonDefs;
-
-	static const EoBChargenButtonDef _chargenButtonDefsDOS[];
-	static const uint16 _chargenButtonKeyCodesFMTOWNS[];
-	static const CreatePartyModButton _chargenModButtons[];
-	static const EoBRect8 _chargenButtonBodyCoords[];
-	static const int16 _chargenBoxX[];
-	static const int16 _chargenBoxY[];
-	static const int16 _chargenNameFieldX[];
-	static const int16 _chargenNameFieldY[];
-
-	static const int32 _classMenuMasks[];
-	static const int32 _alignmentMenuMasks[];
-
-	static const int16 _raceModifiers[];
-
-	EoBCharacter *_characters;
-	uint8 **_faceShapes;
-
-	EoBCoreEngine *_vm;
-	Screen_EoB *_screen;
-};
-
-CharacterGenerator::CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen),
-	_characters(0), _faceShapes(0), _chargenMagicShapes(0), _chargenMagicShapeTimer(0),
-	_updateBoxShapesIndex(0), _lastUpdateBoxShapesIndex(0), _magicShapesBox(6), _activeBox(0) {
-
-	_chargenStatStrings = _vm->_chargenStatStrings;
-	_chargenRaceSexStrings = _vm->_chargenRaceSexStrings;
-	_chargenClassStrings = _vm->_chargenClassStrings;
-	_chargenAlignmentStrings = _vm->_chargenAlignmentStrings;
-
-	memset(_chargenSelectedPortraits, -1, sizeof(_chargenSelectedPortraits));
-	memset(_chargenSelectedPortraits2, 0, sizeof(_chargenSelectedPortraits2));
-	memset(_chargenMinStats, 0, sizeof(_chargenMinStats));
-	memset(_chargenMaxStats, 0, sizeof(_chargenMaxStats));
-
-	int temp;
-	_chargenStrings1 = _vm->staticres()->loadStrings(kEoBBaseChargenStrings1, temp);
-	_chargenStrings2 = _vm->staticres()->loadStrings(kEoBBaseChargenStrings2, temp);
-	_chargenStartLevels = _vm->staticres()->loadRawData(kEoBBaseChargenStartLevels, temp);
-	_chargenEnterGameStrings = _vm->staticres()->loadStrings(kEoBBaseChargenEnterGameStrings, temp);
-	_chargenClassMinStats = _vm->staticres()->loadRawData(kEoBBaseChargenClassMinStats, temp);
-	_chargenRaceMinStats = _vm->staticres()->loadRawData(kEoBBaseChargenRaceMinStats, temp);
-	_chargenRaceMaxStats = _vm->staticres()->loadRawDataBe16(kEoBBaseChargenRaceMaxStats, temp);
-
-	EoBChargenButtonDef *chargenButtonDefs = new EoBChargenButtonDef[41];
-	memcpy(chargenButtonDefs, _chargenButtonDefsDOS, 41 * sizeof(EoBChargenButtonDef));
-
-	if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
-		const uint16 *c = _chargenButtonKeyCodesFMTOWNS;
-		for (int i = 0; i < 41; ++i) {
-			if (chargenButtonDefs[i].keyCode)
-				chargenButtonDefs[i].keyCode = *c++;
-		}
-	}
-
-	_chargenButtonDefs = chargenButtonDefs;
-}
-
-CharacterGenerator::~CharacterGenerator() {
-	if (_chargenMagicShapes) {
-		for (int i = 0; i < 10; i++)
-			delete[] _chargenMagicShapes[i];
-		delete[] _chargenMagicShapes;
-	}
-
-	for (int i = 0; i < 17; i++)
-		delete[] _chargenButtonLabels[i];
-
-	delete[] _chargenButtonDefs;
-
-	_screen->clearPage(2);
-}
-
-bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
-	if (!characters || !faceShapes) {
-		warning("CharacterGenerator::start: Called without character data");
-		return true;
-	}
-
-	_characters = characters;
-	_faceShapes = *faceShapes;
-
-	_vm->snd_stopSound();
-	_vm->delay(_vm->_tickLength);
-
-	init();
-
-	_screen->setScreenDim(2);
-
-	checkForCompleteParty();
-	initButtonsFromList(0, 5);
-
-	_vm->snd_playSong(_vm->game() == GI_EOB1 ? 20 : 13);
-	_activeBox = 0;
-
-	for (bool loop = true; loop && (!_vm->shouldQuit());) {
-		_vm->_gui->updateBoxFrameHighLight(_activeBox + 6);
-		int inputFlag = getInput(_vm->_activeButtons);
-		_vm->removeInputTop();
-
-		if (inputFlag) {
-			if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
-				_activeBox ^= 1;
-			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
-				_activeBox ^= 2;
-			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
-				// Unlike the original we allow returning to the main menu
-				_vm->snd_stopSound();
-				return false;
-			}
-			_vm->_gui->updateBoxFrameHighLight(-1);
-		}
-
-		if (inputFlag & 0x8000) {
-			inputFlag = (inputFlag & 0x0F) - 1;
-			if (inputFlag == 4) {
-				loop = false;
-			} else {
-				_activeBox = inputFlag;
-				inputFlag = _vm->_keyMap[Common::KEYCODE_RETURN];
-			}
-		}
-
-		if (inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5]) {
-			_vm->_gui->updateBoxFrameHighLight(-1);
-			if (_characters[_activeBox].name[0]) {
-				int b = _activeBox;
-				if (viewDeleteCharacter())
-					loop = false;
-				if (b != _activeBox && !_characters[_activeBox].name[0])
-					createPartyMember();
-			} else {
-				createPartyMember();
-			}
-
-			initButtonsFromList(0, 5);
-			checkForCompleteParty();
-		}
-
-		if (loop == false) {
-			for (int i = 0; i < 4; i++) {
-				if (!_characters[i].name[0])
-					loop = true;
-			}
-		}
-	}
-
-	if (!_vm->shouldQuit()) {
-		processSpecialButton(15);
-		finish();
-	}
-
-	if (_vm->game() == GI_EOB2)
-		_vm->snd_fadeOut();
-
-	*faceShapes = _faceShapes;
-	return true;
-}
-
-void CharacterGenerator::init() {
-	/*_screen->loadEoBBitmap("MENU", 0, 3, 3, 2);
-	Common::SeekableReadStream *s = _res->createReadStream("facedat.dmp");
-	_screen->loadFileDataToPage(s, 2, 64000);*/
-
-	_screen->loadShapeSetBitmap("CHARGENA", 3, 3);
-	if (_faceShapes) {
-		for (int i = 0; i < 44; i++)
-			delete[] _faceShapes[i];
-		delete[] _faceShapes;
-	}
-
-	_faceShapes = new uint8*[44];
-	for (int i = 0; i < 44; i++)
-		_faceShapes[i] = _screen->encodeShape((i % 10) << 2, (i / 10) << 5, 4, 32, true, _vm->_cgaMappingDefault);
-	_screen->_curPage = 0;
-
-	_screen->loadEoBBitmap("CHARGEN", _vm->_cgaMappingDefault, 3, 3, 0);
-	_screen->loadShapeSetBitmap("CHARGENB", 3, 3);
-	if (_chargenMagicShapes) {
-		for (int i = 0; i < 10; i++)
-			delete[] _chargenMagicShapes[i];
-		delete[] _chargenMagicShapes;
-	}
-
-	_chargenMagicShapes = new uint8*[10];
-	for (int i = 0; i < 10; i++)
-		_chargenMagicShapes[i] = _screen->encodeShape(i << 2, 0, 4, 32, true, _vm->_cgaMappingDefault);
-
-	for (int i = 0; i < 17; i++) {
-		const CreatePartyModButton *c = &_chargenModButtons[i];
-		_chargenButtonLabels[i] = c->labelW ? _screen->encodeShape(c->encodeLabelX, c->encodeLabelY, c->labelW, c->labelH, true, _vm->_cgaMappingDefault) : 0;
-	}
-	
-	_screen->convertPage(3, 2, _vm->_cgaMappingDefault);
-	_screen->_curPage = 0;
-	_screen->convertToHiColor(2);
-	_screen->shadeRect(142, 63, 306, 193, 4);
-	_screen->copyRegion(144, 64, 0, 0, 180, 128, 0, 2, Screen::CR_NO_P_CHECK);
-	_screen->updateScreen();
-}
-
-void CharacterGenerator::initButtonsFromList(int first, int numButtons) {
-	_vm->gui_resetButtonList();
-
-	for (int i = 0; i < numButtons; i++) {
-		const EoBChargenButtonDef *e = &_chargenButtonDefs[first + i];
-		initButton(i, e->x, e->y, e->w, e->h, e->keyCode);
-	}
-
-	_vm->gui_notifyButtonListChanged();
-}
-
-void CharacterGenerator::initButton(int index, int x, int y, int w, int h, int keyCode) {
-	Button *b = 0;
-	int cnt = 1;
-
-	if (_vm->_activeButtons) {
-		Button *n = _vm->_activeButtons;
-		while (n->nextButton) {
-			++cnt;
-			n = n->nextButton;
-		}
-
-		++cnt;
-		b = n->nextButton = &_vm->_activeButtonData[cnt];
-	} else {
-		b = &_vm->_activeButtonData[0];
-		_vm->_activeButtons = b;
-	}
-
-	*b = Button();
-	b->flags = 0x1100;
-	b->data0Val2 = 12;
-	b->data1Val2 = b->data2Val2 = 15;
-	b->data3Val2 = 8;
-
-	b->index = index + 1;
-	b->x = x << 3;
-	b->y = y;
-	b->width = w;
-	b->height = h;
-	b->keyCode = keyCode;
-	b->keyCode2 = keyCode | 0x100;
-}
-
-void CharacterGenerator::checkForCompleteParty() {
-	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
-	int cp = _screen->setCurPage(2);
-	int x = (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168;
-	_screen->printShadedText(_chargenStrings1[8], x, 16, 15, 0);
-	_screen->setCurPage(cp);
-	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-
-	int numChars = 0;
-	for (int i = 0; i < 4; i++) {
-		if (_characters[i].name[0])
-			numChars++;
-	}
-
-	if (numChars == 4) {
-		_screen->setCurPage(2);
-		_screen->printShadedText(_chargenStrings1[0], x, 61, 15, 0);
-		_screen->setCurPage(0);
-		_screen->copyRegion(168, 61, 152, 125, 136, 40, 2, 0, Screen::CR_NO_P_CHECK);
-		toggleSpecialButton(15, 0, 0);
-	} else {
-		toggleSpecialButton(14, 0, 0);
-	}
-
-	_screen->updateScreen();
-}
-
-void CharacterGenerator::toggleSpecialButton(int index, int bodyCustom, int pageNum) {
-	if (index >= 17)
-		return;
-
-	const CreatePartyModButton *c = &_chargenModButtons[index];
-	const EoBRect8 *p = &_chargenButtonBodyCoords[c->bodyIndex + bodyCustom];
-
-	int x2 = 20;
-	int y2 = 0;
-
-	if (pageNum) {
-		x2 = c->destX + 2;
-		y2 = c->destY - 64;
-	}
-
-	_screen->copyRegion(p->x << 3, p->y, x2 << 3, y2, p->w << 3, p->h, 2, 2, Screen::CR_NO_P_CHECK);
-	if (c->labelW)
-		_screen->drawShape(2, _chargenButtonLabels[index], (x2 << 3) + c->labelX, y2 + c->labelY, 0);
-
-	if (pageNum == 2)
-		return;
-
-	_screen->copyRegion(160, 0, c->destX << 3, c->destY, p->w << 3, p->h, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->updateScreen();
-}
-
-void CharacterGenerator::processSpecialButton(int index) {
-	toggleSpecialButton(index, 1, 0);
-	_vm->snd_playSoundEffect(76);
-	_vm->_system->delayMillis(80);
-	toggleSpecialButton(index, 0, 0);
-}
-
-int CharacterGenerator::viewDeleteCharacter() {
-	initButtonsFromList(0, 7);
-	_vm->removeInputTop();
-
-	_vm->_gui->updateBoxFrameHighLight(-1);
-	printStats(_activeBox, 2);
-
-	int res = 0;
-	for (bool loop = true; loop && _characters[_activeBox].name[0] && !_vm->shouldQuit();) {
-		_vm->_gui->updateBoxFrameHighLight(_activeBox + 6);
-		int inputFlag = getInput(_vm->_activeButtons);
-		int cbx = _activeBox;
-		_vm->removeInputTop();
-
-		if (inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
-			processSpecialButton(9);
-			res = 0;
-			loop = false;
-		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
-			cbx ^= 1;
-		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
-			cbx ^= 2;
-		}
-
-		if (inputFlag & 0x8000) {
-			inputFlag = (inputFlag & 0x0F) - 1;
-			if (inputFlag == 4) {
-				res = 1;
-				loop = false;
-			} else if (inputFlag == 5) {
-				processSpecialButton(9);
-				res = 0;
-				loop = false;
-			} else if (inputFlag == 6) {
-				if (_characters[_activeBox].name[0]) {
-					processSpecialButton(16);
-					_characters[_activeBox].name[0] = 0;
-					processNameInput(_activeBox, 12);
-					processFaceMenuSelection(_activeBox + 50);
-				}
-			} else {
-				cbx = inputFlag;
-			}
-		}
-
-		if (loop == false)
-			_vm->_gui->updateBoxFrameHighLight(-1);
-
-		if (!_characters[cbx].name[0])
-			loop = false;
-
-		if (cbx != _activeBox) {
-			_activeBox = cbx;
-			_vm->_gui->updateBoxFrameHighLight(-1);
-			if (loop)
-				printStats(_activeBox, 2);
-		}
-	}
-
-	return res;
-}
-
-void CharacterGenerator::createPartyMember() {
-	_screen->setScreenDim(2);
-	assert(_vm->_gui);
-
-	for (int i = 0; i != 3 && !_vm->shouldQuit(); i++) {
-		bool bck = false;
-
-		switch (i) {
-		case 0:
-			_characters[_activeBox].raceSex = raceSexMenu();
-			break;
-		case 1:
-			_characters[_activeBox].cClass = classMenu(_characters[_activeBox].raceSex);
-			if (_characters[_activeBox].cClass == _vm->_keyMap[Common::KEYCODE_ESCAPE])
-				bck = true;
-			break;
-		case 2:
-			_characters[_activeBox].alignment = alignmentMenu(_characters[_activeBox].cClass);
-			if (_characters[_activeBox].alignment == _vm->_keyMap[Common::KEYCODE_ESCAPE])
-				bck = true;
-			break;
-		default:
-			break;
-		}
-
-		if (bck)
-			i -= 2;
-	};
-
-	if (!_vm->shouldQuit()) {
-		generateStats(_activeBox);
-		statsAndFacesMenu();
-
-		for (_characters[_activeBox].name[0] = 0; _characters[_activeBox].name[0] == 0 && !_vm->shouldQuit();) {
-			processFaceMenuSelection(_chargenMinStats[6]);
-			printStats(_activeBox, 0);
-			_screen->printShadedText(_chargenStrings2[11], 149, 100, 9, 0);
-			if (!_vm->shouldQuit()) {
-				_vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, 15, 0, 8);
-				processNameInput(_activeBox, 2);
-			}
-		}
-	}
-}
-
-int CharacterGenerator::raceSexMenu() {
-	_screen->drawBox(_chargenBoxX[_activeBox], _chargenBoxY[_activeBox], _chargenBoxX[_activeBox] + 32, _chargenBoxY[_activeBox] + 33, 12);
-	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[8], 147, 67, 9, 0);
-	_vm->removeInputTop();
-
-	_vm->_gui->simpleMenu_setup(1, 0, _chargenRaceSexStrings, -1, 0, 0);
-	int16 res = -1;
-
-	while (res == -1 && !_vm->shouldQuit()) {
-		res = _vm->_gui->simpleMenu_process(1, _chargenRaceSexStrings, 0, -1, 0);
-		updateMagicShapes();
-	}
-
-	return res;
-}
-
-int CharacterGenerator::classMenu(int raceSex) {
-	int32 itemsMask = -1;
-
-	for (int i = 0; i < 4; i++) {
-		// check for evil characters
-		if (_characters[i].name[0] && _characters[i].alignment > 5)
-			itemsMask = 0xFFFB;
-	}
-
-	_vm->removeInputTop();
-	updateMagicShapes();
-
-	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[9], 147, 67, 9, 0);
-
-	toggleSpecialButton(5, 0, 0);
-
-	itemsMask &= _classMenuMasks[raceSex / 2];
-	_vm->_gui->simpleMenu_setup(2, 15, _chargenClassStrings, itemsMask, 0, 0);
-
-	_vm->_mouseX = _vm->_mouseY = 0;
-	int16 res = -1;
-
-	while (res == -1 && !_vm->shouldQuit()) {
-		updateMagicShapes();
-		int in = getInput(0) & 0xFF;
-		Common::Point mp = _vm->getMousePos();
-
-		if (in == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_b]) {
-			res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
-		} else if (_vm->posWithinRect(mp.x, mp.y, 264, 171, 303, 187)) {
-			if (in == 199 || in == 201)
-				res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
-			else
-				_vm->removeInputTop();
-		} else {
-			res = _vm->_gui->simpleMenu_process(2, _chargenClassStrings, 0, itemsMask, 0);
-		}
-	}
-
-	_vm->removeInputTop();
-
-	if (res == _vm->_keyMap[Common::KEYCODE_ESCAPE])
-		processSpecialButton(5);
-
-	return res;
-}
-
-int CharacterGenerator::alignmentMenu(int cClass) {
-	int32 itemsMask = -1;
-
-	for (int i = 0; i < 4; i++) {
-		// check for paladins
-		if (_characters[i].name[0] && _characters[i].cClass == 2)
-			itemsMask = 0xFE3F;
-	}
-
-	_vm->removeInputTop();
-	updateMagicShapes();
-
-	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[10], 147, 67, 9, 0);
-
-	toggleSpecialButton(5, 0, 0);
-
-	itemsMask &= _alignmentMenuMasks[cClass];
-	_vm->_gui->simpleMenu_setup(3, 9, _chargenAlignmentStrings, itemsMask, 0, 0);
-
-	_vm->_mouseX = _vm->_mouseY = 0;
-	int16 res = -1;
-
-	while (res == -1 && !_vm->shouldQuit()) {
-		updateMagicShapes();
-		int in = getInput(0) & 0xFF;
-		Common::Point mp = _vm->getMousePos();
-
-		if (in == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_b]) {
-			res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
-		} else if (_vm->posWithinRect(mp.x, mp.y, 264, 171, 303, 187)) {
-			if (in == 199 || in == 201)
-				res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
-			else
-				_vm->removeInputTop();
-		} else {
-			res = _vm->_gui->simpleMenu_process(3, _chargenAlignmentStrings, 0, itemsMask, 0);
-		}
-	}
-
-	_vm->removeInputTop();
-
-	if (res == _vm->_keyMap[Common::KEYCODE_ESCAPE])
-		processSpecialButton(5);
-
-	return res;
-}
-
-int CharacterGenerator::getInput(Button *buttonList) {
-	if (_vm->game() == GI_EOB1 && _vm->sound()->checkTrigger()) {
-		_vm->sound()->resetTrigger();
-		_vm->snd_playSong(20);
-	} else if (_vm->game() == GI_EOB2 && !_vm->sound()->isPlaying()) {
-		// WORKAROUND for EOB II: The original implements the same sound trigger check as in EOB I.
-		// However, Westwood seems to have forgotten to set the trigger at the end of the AdLib song,
-		// so that the music will not loop. We simply check whether the sound driver is still playing.
-		_vm->delay(3 * _vm->_tickLength);
-		_vm->snd_playSong(13);
-	}
-	return _vm->checkInput(buttonList, false, 0);
-}
-
-void CharacterGenerator::updateMagicShapes() {
-	if (_magicShapesBox != _activeBox) {
-		_chargenMagicShapeTimer = 0;
-		_magicShapesBox = _activeBox;
-	}
-
-	if (_chargenMagicShapeTimer < _vm->_system->getMillis()) {
-		if (++_updateBoxShapesIndex > 9)
-			_updateBoxShapesIndex = 0;
-		_chargenMagicShapeTimer = _vm->_system->getMillis() + 2 * _vm->_tickLength;
-	}
-
-	if (_updateBoxShapesIndex == _lastUpdateBoxShapesIndex)
-		return;
-
-	_screen->copyRegion(_activeBox << 5, 128, 288, 128, 32, 32, 2, 2, Screen::CR_NO_P_CHECK);
-	_screen->drawShape(2, _chargenMagicShapes[_updateBoxShapesIndex], 288, 128, 0);
-	_screen->copyRegion(288, 128, _chargenBoxX[_activeBox], _chargenBoxY[_activeBox] + 1, 32, 32, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->updateScreen();
-
-	_lastUpdateBoxShapesIndex = _updateBoxShapesIndex;
-}
-
-void CharacterGenerator::generateStats(int index) {
-	EoBCharacter *c = &_characters[index];
-
-	for (int i = 0; i < 3; i++) {
-		c->level[i] = _chargenStartLevels[(c->cClass << 2) + i];
-		c->experience[i] = (_vm->game() == GI_EOB2 ? 69000 : 5000) / _chargenStartLevels[(c->cClass << 2) + 3];
-	}
-
-	int rc = c->raceSex >> 1;
-	for (int i = 0; i < 6; i++) {
-		_chargenMinStats[i] = MAX(_chargenClassMinStats[c->cClass * 6 + i], _chargenRaceMinStats[rc * 6 + i]);
-		_chargenMaxStats[i] = _chargenRaceMaxStats[rc * 6 + i];
-	}
-
-	if (_vm->_charClassModifier[c->cClass])
-		_chargenMaxStats[0] = 18;
-
-	uint16 sv[6];
-	for (int i = 0; i < 6; i++) {
-		sv[i] = MAX<uint16>(rollDice() + _raceModifiers[rc * 6 + i], _chargenMinStats[i]);
-		if (!i && sv[i] == 18)
-			sv[i] |= (uint16)(_vm->rollDice(1, 100) << 8);
-		if (sv[i] > _chargenMaxStats[i])
-			sv[i] = _chargenMaxStats[i];
-	}
-
-	c->strengthCur = c->strengthMax = sv[0] & 0xFF;
-	c->strengthExtCur = c->strengthExtMax = sv[0] >> 8;
-	c->intelligenceCur = c->intelligenceMax = sv[1] & 0xFF;
-	c->wisdomCur = c->wisdomMax = sv[2] & 0xFF;
-	c->dexterityCur = c->dexterityMax = sv[3] & 0xFF;
-	c->constitutionCur = c->constitutionMax = sv[4] & 0xFF;
-	c->charismaCur = c->charismaMax = sv[5] & 0xFF;
-	c->armorClass = 10 + _vm->getDexterityArmorClassModifier(sv[3] & 0xFF);
-	c->hitPointsCur = 0;
-
-	for (int l = 0; l < 3; l++) {
-		for (int i = 0; i < c->level[l]; i++)
-			c->hitPointsCur += _vm->generateCharacterHitpointsByLevel(index, 1 << l);
-	}
-
-	c->hitPointsMax = c->hitPointsCur;
-}
-
-void CharacterGenerator::modifyMenu() {
-	_vm->removeInputTop();
-	printStats(_activeBox, 3);
-
-	EoBCharacter *c = &_characters[_activeBox];
-	int8 hpLO = c->hitPointsCur;
-
-	for (int i = 0; i >= 0 && i < 7;) {
-		switch (i) {
-		case 0:
-			i = modifyStat(i, &c->strengthCur, &c->strengthExtCur);
-			break;
-		case 1:
-			i = modifyStat(i, &c->intelligenceCur, 0);
-			break;
-		case 2:
-			i = modifyStat(i, &c->wisdomCur, 0);
-			break;
-		case 3:
-			i = modifyStat(i, &c->dexterityCur, 0);
-			break;
-		case 4:
-			i = modifyStat(i, &c->constitutionCur, 0);
-			break;
-		case 5:
-			i = modifyStat(i, &c->charismaCur, 0);
-			break;
-		case 6:
-			hpLO = c->hitPointsCur;
-			i = modifyStat(i, &hpLO, 0);
-			c->hitPointsCur = hpLO;
-			break;
-		default:
-			break;
-		}
-
-		if (i == -2 || _vm->shouldQuit())
-			break;
-		else if (i < 0)
-			i = 6;
-		i %= 7;
-
-		printStats(_activeBox, 3);
-	}
-
-	printStats(_activeBox, 1);
-}
-
-void CharacterGenerator::statsAndFacesMenu() {
-	faceSelectMenu();
-	printStats(_activeBox, 1);
-	initButtonsFromList(27, 4);
-	_vm->removeInputTop();
-	int in = 0;
-
-	while (!in && !_vm->shouldQuit()) {
-		updateMagicShapes();
-		in = getInput(_vm->_activeButtons);
-		_vm->removeInputTop();
-
-		if (in == 0x8001) {
-			processSpecialButton(4);
-			updateMagicShapes();
-			generateStats(_activeBox);
-			in = -1;
-		} else if (in == 0x8002) {
-			processSpecialButton(7);
-			modifyMenu();
-			in = -1;
-		} else if (in == 0x8003) {
-			processSpecialButton(8);
-			faceSelectMenu();
-			in = -1;
-		} else if (in == 0x8004 || in == _vm->_keyMap[Common::KEYCODE_KP5]) {
-			processSpecialButton(6);
-			in = 1;
-		} else {
-			in = 0;
-		}
-
-		if (in & 0x8000) {
-			printStats(_activeBox, 1);
-			initButtonsFromList(27, 4);
-			in = 0;
-		}
-	}
-
-	_vm->_gui->updateBoxFrameHighLight(6 + _activeBox);
-	_vm->_gui->updateBoxFrameHighLight(-1);
-}
-
-void CharacterGenerator::faceSelectMenu() {
-	int8 sp[4];
-	memcpy(sp, _chargenSelectedPortraits2, sizeof(sp));
-	_vm->removeInputTop();
-	initButtonsFromList(21, 6);
-
-	int charSex = _characters[_activeBox].raceSex % 2;
-	int8 shp = charSex ? 26 : 0;
-
-	printStats(_activeBox, 4);
-	toggleSpecialButton(12, 0, 0);
-	toggleSpecialButton(13, 0, 0);
-	_vm->_gui->updateBoxFrameHighLight(-1);
-
-	shp = getNextFreeFaceShape(shp, charSex, 1, _chargenSelectedPortraits);
-
-	int res = -1;
-	int box = 1;
-
-	while (res == -1 && !_vm->shouldQuit()) {
-		int8 shpOld = shp;
-
-		for (int i = 0; i < 4; i++) {
-			sp[i] = shp;
-			_screen->drawShape(0, _faceShapes[sp[i]], 176 + (i << 5), 66, 0);
-			shp = getNextFreeFaceShape(shp + 1, charSex, 1, _chargenSelectedPortraits);
-		}
-
-		shp = shpOld;
-		int in = 0;
-
-		while (!in && !_vm->shouldQuit()) {
-			updateMagicShapes();
-			in = getInput(_vm->_activeButtons);
-			_vm->removeInputTop();
-
-			_vm->_gui->updateBoxFrameHighLight(box + 10);
-
-			if (in == 0x8002 || in == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
-				processSpecialButton(13);
-				in = 2;
-			} else if (in > 0x8002 && in < 0x8007) {
-				box = (in & 7) - 3;
-				in = 3;
-			} else if (in == 0x8001 || in == _vm->_keyMap[Common::KEYCODE_LEFT]) {
-				processSpecialButton(12);
-				in = 1;
-			} else if (in == _vm->_keyMap[Common::KEYCODE_RETURN] || in == _vm->_keyMap[Common::KEYCODE_KP5]) {
-				in = 3;
-			} else if (in & 0x8000) {
-				in &= 0xFF;
-			} else {
-				in = 0;
-			}
-		}
-
-		_vm->_gui->updateBoxFrameHighLight(-1);
-
-		if (in == 1)
-			shp = getNextFreeFaceShape(shp - 1, charSex, -1, _chargenSelectedPortraits);
-		else if (in == 2)
-			shp = getNextFreeFaceShape(shp + 1, charSex, 1, _chargenSelectedPortraits);
-		else if (in == 3)
-			res = box;
-	}
-
-	if (!_vm->shouldQuit()) {
-		_vm->_gui->updateBoxFrameHighLight(-1);
-		updateMagicShapes();
-
-		_chargenSelectedPortraits[_activeBox] = sp[res];
-		_characters[_activeBox].portrait = sp[res];
-		_characters[_activeBox].faceShape = _faceShapes[sp[res]];
-
-		printStats(_activeBox, 1);
-	}
-}
-
-int CharacterGenerator::getNextFreeFaceShape(int shpIndex, int charSex, int step, int8 *selectedPortraits) {
-	int shpCur = ((shpIndex < 0) ? 43 : shpIndex) % 44;
-	bool notUsable = false;
-
-	do {
-		notUsable = false;
-		for (int i = 0; i < 4; i++) {
-			if (_characters[i].name[0] && selectedPortraits[i] == shpCur)
-				notUsable = true;
-		}
-
-		if ((charSex && (shpCur < 26)) || (!charSex && (shpCur > 28)))
-			notUsable = true;
-
-		if (notUsable) {
-			shpCur += step;
-			shpCur = ((shpCur < 0) ? 43 : shpCur) % 44;
-		}
-	} while (notUsable);
-
-	return shpCur;
-}
-
-void CharacterGenerator::processFaceMenuSelection(int index) {
-	_vm->_gui->updateBoxFrameHighLight(-1);
-	if (index <= 48)
-		_screen->drawShape(0, _characters[_activeBox].faceShape, _chargenBoxX[_activeBox], _chargenBoxY[_activeBox] + 1, 0);
-	else
-		toggleSpecialButton(index - 50, 0, 0);
-}
-
-void CharacterGenerator::printStats(int index, int mode) {
-	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
-	_screen->_curPage = 2;
-
-	EoBCharacter *c = &_characters[index];
-
-	if (mode != 4)
-		_screen->drawShape(2, c->faceShape, 224, 2, 0);
-
-	_screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, 15, 0);
-	_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, 15, 0);
-	_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, 15, 0);
-
-	for (int i = 0; i < 6; i++)
-		_screen->printShadedText(_chargenStatStrings[i], 163, (i + 8) << 3, 15, 0);
-
-	_screen->printShadedText(_chargenStrings1[2], 248, 64, 15, 0);
-
-	Common::String str = Common::String::format(_chargenStrings1[3], _vm->getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), c->intelligenceCur, c->wisdomCur, c->dexterityCur, c->constitutionCur, c->charismaCur);
-	_screen->printShadedText(str.c_str(), 192, 64, 15, 0);
-
-	str = Common::String::format(_chargenStrings1[4], c->armorClass, c->hitPointsMax);
-	_screen->printShadedText(str.c_str(), 280, 64, 15, 0);
-
-	const char *lvlStr = c->level[2] ? _chargenStrings1[7] : (c->level[1] ? _chargenStrings1[6] : _chargenStrings1[5]);
-	str = Common::String::format(lvlStr, c->level[0], c->level[1], c->level[2]);
-	_screen->printShadedText(str.c_str(), 280, 80, 15, 0);
-
-	switch (mode) {
-	case 1:
-		toggleSpecialButton(4, 0, 2);
-		toggleSpecialButton(7, 0, 2);
-		toggleSpecialButton(8, 0, 2);
-		toggleSpecialButton(6, 0, 2);
-		break;
-
-	case 2:
-		toggleSpecialButton(16, 0, 2);
-		toggleSpecialButton(9, 0, 2);
-		break;
-
-	case 3:
-		toggleSpecialButton(10, 0, 2);
-		toggleSpecialButton(11, 0, 2);
-		toggleSpecialButton(9, 0, 2);
-		break;
-
-	default:
-		break;
-	}
-
-	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-
-	if (mode != 3)
-		_screen->updateScreen();
-
-	_screen->_curPage = 0;
-}
-
-void CharacterGenerator::processNameInput(int index, int textColor) {
-	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
-	_screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, 12);
-	int xOffs = (60 - _screen->getTextWidth(_characters[index].name)) >> 1;
-	_screen->printText(_characters[index].name, _chargenNameFieldX[index] + xOffs, _chargenNameFieldY[index], textColor, 0);
-	_screen->updateScreen();
-	_screen->setFont(of);
-}
-
-int CharacterGenerator::rollDice() {
-	int res = 0;
-	int min = 10;
-
-	for (int i = 0; i < 4; i++) {
-		int d = _vm->rollDice(1, 6, 0);
-		res += d;
-		if (d < min)
-			min = d;
-	}
-
-	res -= min;
-	return res;
-}
-
-int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
-	uint8 *s1 = (uint8 *)stat1;
-	uint8 *s2 = (uint8 *)stat2;
-
-	initButtonsFromList(31, 10);
-	Button *b = _vm->gui_getButton(_vm->_activeButtons, index + 1);
-
-	printStats(_activeBox, 3);
-	_vm->removeInputTop();
-
-	Common::String statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
-
-	_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, 6, 0);
-	_screen->updateScreen();
-
-	EoBCharacter *c = &_characters[_activeBox];
-
-	int ci = index;
-	uint8 v2 = s2 ? *s2 : 0;
-
-	if (index == 6) {
-		_chargenMaxStats[6] = getMaxHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
-		_chargenMinStats[6] = getMinHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
-	}
-
-	for (bool loop = true; loop && !_vm->shouldQuit();) {
-		uint8 v1 = *s1;
-		updateMagicShapes();
-		int inputFlag = getInput(_vm->_activeButtons);
-		_vm->removeInputTop();
-
-		if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_MINUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP_MINUS] || inputFlag == 0x8009) {
-			processSpecialButton(11);
-			v1--;
-
-		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_PLUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP_PLUS] || inputFlag == 0x8008) {
-			processSpecialButton(10);
-			v1++;
-
-		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP8]) {
-			ci = (ci - 1) % 7;
-			loop = false;
-
-		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP2]) {
-			ci = (ci + 1) % 7;
-			loop = false;
-
-		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_o] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE] || inputFlag == 0x800A) {
-			processSpecialButton(9);
-			loop = false;
-			ci = -2;
-
-		} else if (inputFlag & 0x8000) {
-			inputFlag = (inputFlag & 0x0F) - 1;
-			if (index != inputFlag) {
-				ci = inputFlag;
-				loop = false;
-			}
-		}
-
-		if (v1 == *s1)
-			continue;
-
-		if (!index) {
-			while (v1 > 18) {
-				v1--;
-				v2++;
-			}
-			while (v2 > 0 && v1 < 18) {
-				v1++;
-				v2--;
-			}
-
-			v1 = CLIP<uint8>(v1, _chargenMinStats[index], _chargenMaxStats[index] & 0xFF);
-			v2 = (v1 == 18 && _chargenMaxStats[index] >= 19) ? CLIP<uint8>(v2, 0, 100) : 0;
-			if (s2)
-				*s2 = v2;
-			else
-				error("CharacterGenerator::modifyStat:...");
-		} else {
-			v1 = CLIP<uint8>(v1, _chargenMinStats[index], _chargenMaxStats[index]);
-		}
-
-		*s1 = v1;
-
-		if (index == 6)
-			_characters[_activeBox].hitPointsMax = v1;
-
-		statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
-
-		_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, 6, 0);
-		_screen->updateScreen();
-
-		if (index == 4) {
-			int oldVal = c->hitPointsCur;
-			_chargenMaxStats[6] = getMaxHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
-			_chargenMinStats[6] = getMinHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
-			c->hitPointsMax = c->hitPointsCur = CLIP<int16>(c->hitPointsCur, _chargenMinStats[6], _chargenMaxStats[6]);
-
-			if (c->hitPointsCur != oldVal) {
-				statStr = Common::String::format("%d", c->hitPointsCur);
-				_screen->copyRegion(120, 72, 264, 136, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
-				_screen->printShadedText(statStr.c_str(), 264, 136, 15, 0);
-				_screen->updateScreen();
-			}
-
-		} else if (index == 3) {
-			int oldVal = c->armorClass;
-			c->armorClass = _vm->getDexterityArmorClassModifier(v1) + 10;
-
-			if (c->armorClass != oldVal) {
-				statStr = Common::String::format("%d", c->armorClass);
-				_screen->copyRegion(120, 64, 264, 128, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
-				_screen->printShadedText(statStr.c_str(), 264, 128, 15, 0);
-				_screen->updateScreen();
-			}
-		}
-
-		if (loop == false) {
-			statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
-			_screen->printText(statStr.c_str(), b->x + 32, b->y, 15, 0);
-			_screen->updateScreen();
-		}
-	}
-
-	return ci;
-}
-
-int CharacterGenerator::getMaxHp(int cclass, int constitution, int level1, int level2, int level3) {
-	int res = 0;
-	constitution = _vm->getClassAndConstHitpointsModifier(cclass, constitution);
-
-	int m = _vm->getCharacterClassType(cclass, 0);
-	if (m != -1)
-		res = _vm->getModifiedHpLimits(m, constitution, level1, false);
-
-	m = _vm->getCharacterClassType(cclass, 1);
-	if (m != -1)
-		res += _vm->getModifiedHpLimits(m, constitution, level2, false);
-
-	m = _vm->getCharacterClassType(cclass, 2);
-	if (m != -1)
-		res += _vm->getModifiedHpLimits(m, constitution, level3, false);
-
-	res /= _vm->_numLevelsPerClass[cclass];
-
-	return res;
-}
-
-int CharacterGenerator::getMinHp(int cclass, int constitution, int level1, int level2, int level3) {
-	int res = 0;
-	constitution = _vm->getClassAndConstHitpointsModifier(cclass, constitution);
-
-	int m = _vm->getCharacterClassType(cclass, 0);
-	if (m != -1)
-		res = _vm->getModifiedHpLimits(m, constitution, level1, true);
-
-	m = _vm->getCharacterClassType(cclass, 1);
-	if (m != -1)
-		res += _vm->getModifiedHpLimits(m, constitution, level2, true);
-
-	m = _vm->getCharacterClassType(cclass, 2);
-	if (m != -1)
-		res += _vm->getModifiedHpLimits(m, constitution, level3, true);
-
-	res /= _vm->_numLevelsPerClass[cclass];
-
-	return res;
-}
-
-void CharacterGenerator::finish() {
-	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
-	int cp = _screen->setCurPage(2);
-	_screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, 15, 0);
-	_screen->setCurPage(cp);
-	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->updateScreen();
-
-	if (_vm->game() == GI_EOB1) {
-		static const int8 classDefaultItemsList[] = {
-			 1, 17,  2, 17, 46, -1,  4, -1,  5, -1,  6,
-			 2,  7, -1,  8, -1,  9, 21, 10,  2, 31,  2
-		};
-
-		static const int8 classDefaultItemsListIndex[] = {
-			 4,  8,  0, -1,  4,  3,  0, -1,  4, 10,
-			 0,  8,  3,  6,  1, -1,  2,  7,  0, -1,
-			 4,  5,  0, -1,  4,  7,  0,  8,  4,  5,
-			 0,  8,  4,  6,  8,  8,  4,  6,  5,  8,
-			 3,  6,  5, -1,  2,  7,  5,  0,  4,  6,
-			 7,  0,  4,  3,  7,  0,  2,  6,  7,  1
-		};
-
-		_characters[0].inventory[2] = _vm->duplicateItem(35);
-
-		for (int i = 0; i < 4; i++) {
-			EoBCharacter *c = &_characters[i];
-			c->flags = 1;
-			c->food = 100;
-			c->id = i;
-			c->inventory[3] = _vm->duplicateItem(10);
-
-			for (int ii = 0; ii < 4; ii++) {
-				int l = classDefaultItemsListIndex[(c->cClass << 2) + ii] << 1;
-				if (classDefaultItemsList[l] == -1)
-					continue;
-
-				int d = classDefaultItemsList[l];
-				int slot = classDefaultItemsList[l + 1];
-
-				if (slot < 0) {
-					slot = 0;
-					if (c->inventory[slot])
-						slot++;
-					if (c->inventory[slot])
-						slot++;
-				}
-
-				if (slot != 2 && c->inventory[slot])
-					continue;
-
-				if (d == 5 && (c->raceSex >> 1) == 3)
-					d = 36;
-
-				if (slot == 2) {
-					while (c->inventory[slot])
-						slot++;
-				}
-
-				c->inventory[slot] = _vm->duplicateItem(d);
-			}
-
-			_vm->recalcArmorClass(i);
-		}
-
-	} else {
-		static const uint8 classDefaultItemsListIndex[] = { 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 3, 2, 0, 0, 2 };
-		static const int8 itemList0[] = { 3, 36, 0, 17, -1, 0, 0, 56, 1, 17, 31, 0, 1, 23, 1, 17, 31, 1, 1 };
-		static const int8 itemList1[] = { 1, 2, 0, 17, -1, 0, 0 };
-		static const int8 itemList2[] = { 2, 56, 1, 17, 31, 0, 1, 23, 1, 17, 31, 0, 1 };
-		static const int8 itemList3[] = { 2, 1, 1, 17, 31, 1, 1, 1, 0, 17, 31, 2, 1 };
-		static const int8 *const itemList[] = { itemList0, itemList1, itemList2, itemList3 };
-
-		for (int i = 0; i < 4; i++) {
-			EoBCharacter *c = &_characters[i];
-			c->flags = 1;
-			c->food = 100;
-			c->id = i;
-			const int8 *df = itemList[classDefaultItemsListIndex[c->cClass]];
-			int v1 = _vm->rollDice(1, *df++, -1);
-
-			df = &df[v1 * 6];
-			for (int ii = 0; ii < 2; ii++) {
-				if (df[0] == -1)
-					break;
-				_vm->createInventoryItem(c, df[0], df[1], df[2]);
-				df = &df[3];
-			}
-
-			uint16 m = _vm->_classModifierFlags[c->cClass];
-			v1 = _vm->rollDice(1, 2, -1);
-
-			int ival = 0;
-			int itype = 0;
-
-			if (m & 0x31) {
-				if ((c->raceSex >> 1) == 3) {
-					itype = 22;
-					ival = 1;
-				} else {
-					if (v1 == 0) {
-						itype = 5;
-						ival = 1;
-					} else {
-						itype = 34;
-					}
-				}
-			} else if (m & 0x04) {
-				itype = 26;
-				if (v1 != 0)
-					ival = 1;
-			} else if (m & 0x08) {
-				ival = 1;
-				itype = ((c->raceSex >> 1) == 3) ? 22 : 5;
-			} else {
-				if (v1 == 0) {
-					itype = 3;
-				} else {
-					itype = 4;
-					ival = 1;
-				}
-			}
-
-			_vm->createInventoryItem(c, itype, ival, 0);
-			_vm->createInventoryItem(c, 10, -1, 2);
-			_vm->createInventoryItem(c, 10, -1, 2);
-			_vm->createInventoryItem(c, 24, 2, 2);
-
-			if (_vm->_classModifierFlags[c->cClass] & 2) {
-				_vm->createInventoryItem(c, 7, -1, 1);
-				_vm->createInventoryItem(c, 21, 4, 2);
-				_vm->createInventoryItem(c, 21, 13, 2);
-			}
-
-			if (_vm->_classModifierFlags[c->cClass] & 0x14) {
-				if (c->cClass == 2)
-					_vm->createInventoryItem(c, 27, -1, 1);
-				else
-					_vm->createInventoryItem(c, 8, -1, 1);
-
-				_vm->createInventoryItem(c, 20, 49, 1);
-			}
-
-			if (_vm->_classModifierFlags[c->cClass] & 8)
-				_vm->createInventoryItem(c, 6, -1, 1);
-
-			if (i == 0)
-				_vm->createInventoryItem(c, 93, -1, 2);
-
-			_vm->recalcArmorClass(i);
-		}
-	}
-
-	for (int i = 0; i < 4; i++) {
-		if (_vm->_classModifierFlags[_characters[i].cClass] & 2)
-			_characters[i].mageSpellsAvailableFlags = (_vm->game() == GI_EOB2) ? 0x81CB6 : 0x26C;
-
-		if (_vm->_classModifierFlags[_characters[i].cClass] & 0x14 && _vm->game() == GI_EOB2) {
-			// Cleric/Paladin: Add Turn Undead spell
-			_characters[i].clericSpells[0] = 29;
-		}
-	}
-
-	for (int i = 0; i < 4; i++) {
-		EoBCharacter *c = &_characters[i];
-		c->strengthMax = c->strengthCur;
-		c->strengthExtMax = c->strengthExtCur;
-		c->intelligenceMax = c->intelligenceCur;
-		c->wisdomMax = c->wisdomCur;
-		c->dexterityMax = c->dexterityCur;
-		c->constitutionMax = c->constitutionCur;
-		c->charismaMax = c->charismaCur;
-		c->hitPointsMax = c->hitPointsCur;
-	}
-
-	_vm->gui_resetButtonList();
-
-	if (_faceShapes) {
-		for (int i = 0; i < 44; i++) {
-			bool del = true;
-			for (int ii = 0; ii < 4; ii++) {
-				if (_characters[ii].faceShape == _faceShapes[i])
-					del = false;
-			}
-			if (del)
-				delete[] _faceShapes[i];
-		}
-		delete[] _faceShapes;
-		_faceShapes = 0;
-	}
-
-	if (_chargenMagicShapes) {
-		for (int i = 0; i < 10; i++)
-			delete[] _chargenMagicShapes[i];
-		delete[] _chargenMagicShapes;
-		_chargenMagicShapes = 0;
-	}
-
-	for (int i = 0; i < 17; i++) {
-		delete[] _chargenButtonLabels[i];
-		_chargenButtonLabels[i] = 0;
-	}
-}
-
-const EoBChargenButtonDef CharacterGenerator::_chargenButtonDefsDOS[] = {
-	{ 0x01, 0x37, 0x31, 0x32, 0x70 },
-	{ 0x09, 0x37, 0x31, 0x32, 0x71 },
-	{ 0x01, 0x77, 0x31, 0x32, 0x72 },
-	{ 0x09, 0x77, 0x31, 0x32, 0x73 },
-	{ 0x03, 0xB5, 0x53, 0x10, 0x1A },
-	{ 0x21, 0xAC, 0x26, 0x10, 0x19 },
-	{ 0x1C, 0xAC, 0x26, 0x10, 0x21 },
-	{ 0x21, 0xAC, 0x26, 0x10, 0x32 },
-	{ 0x13, 0x50, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x58, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x60, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x68, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x70, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x78, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x80, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x88, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x90, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0x98, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0xA0, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0xA8, 0x9A, 0x08, 0x00 },
-	{ 0x13, 0xB0, 0x9A, 0x08, 0x00 },
-	{ 0x12, 0x42, 0x20, 0x10, 0x00 },
-	{ 0x12, 0x52, 0x20, 0x10, 0x00 },
-	{ 0x16, 0x42, 0x20, 0x20, 0x00 },
-	{ 0x1A, 0x42, 0x20, 0x20, 0x00 },
-	{ 0x1E, 0x42, 0x20, 0x20, 0x00 },
-	{ 0x22, 0x42, 0x20, 0x20, 0x00 },
-	{ 0x1C, 0x9C, 0x26, 0x10, 0x14 },
-	{ 0x21, 0x9C, 0x26, 0x10, 0x34 },
-	{ 0x1C, 0xAC, 0x26, 0x10, 0x22 },
-	{ 0x21, 0xAC, 0x26, 0x10, 0x26 },
-	{ 0x12, 0x80, 0x35, 0x08, 0x00 },
-	{ 0x12, 0x88, 0x35, 0x08, 0x00 },
-	{ 0x12, 0x90, 0x35, 0x08, 0x00 },
-	{ 0x12, 0x98, 0x35, 0x08, 0x00 },
-	{ 0x12, 0xA0, 0x35, 0x08, 0x00 },
-	{ 0x12, 0xA8, 0x35, 0x08, 0x00 },
-	{ 0x1D, 0x88, 0x35, 0x08, 0x00 },
-	{ 0x1B, 0xAC, 0x15, 0x10, 0x0D },
-	{ 0x1E, 0xAC, 0x15, 0x10, 0x0C },
-	{ 0x21, 0xAC, 0x25, 0x10, 0x19 }
-};
-
-const uint16 CharacterGenerator::_chargenButtonKeyCodesFMTOWNS[] = {
-	93, 94, 95, 96, 80, 79, 68, 66, 82, 77, 70, 75, 43, 45, 79
-};
-
-const CreatePartyModButton CharacterGenerator::_chargenModButtons[] = {
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x40 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x80 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, 0x80 },
-	{ 0x00, 0xC0, 0x04, 0x05, 0x07, 0x05, 0x08, 0x1C, 0x9C },
-	{ 0x04, 0xC0, 0x03, 0x05, 0x0A, 0x05, 0x08, 0x21, 0xAC },
-	{ 0x07, 0xC0, 0x03, 0x05, 0x0B, 0x05, 0x08, 0x21, 0xAC },
-	{ 0x0A, 0xC0, 0x04, 0x05, 0x06, 0x05, 0x08, 0x21, 0x9C },
-	{ 0x18, 0xC0, 0x03, 0x05, 0x09, 0x05, 0x08, 0x1C, 0xAC },
-	{ 0x0E, 0xC0, 0x02, 0x05, 0x0F, 0x05, 0x08, 0x21, 0xAC },
-	{ 0x10, 0xC0, 0x01, 0x05, 0x09, 0x05, 0x04, 0x1B, 0xAC },
-	{ 0x11, 0xC0, 0x01, 0x01, 0x09, 0x07, 0x04, 0x1E, 0xAC },
-	{ 0x12, 0xC0, 0x03, 0x07, 0x07, 0x04, 0x06, 0x12, 0x42 },
-	{ 0x15, 0xC0, 0x03, 0x07, 0x07, 0x04, 0x06, 0x12, 0x52 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0xB5 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x03, 0xB5 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x1C, 0xAC }
-};
-
-const EoBRect8 CharacterGenerator::_chargenButtonBodyCoords[] = {
-	{ 0x00, 0x80, 0x04, 0x20 },
-	{ 0x04, 0x80, 0x04, 0x20 },
-	{ 0x08, 0x80, 0x04, 0x20 },
-	{ 0x0C, 0x80, 0x04, 0x20 },
-	{ 0x0E, 0xA0, 0x03, 0x10 },
-	{ 0x0B, 0xA0, 0x03, 0x10 },
-	{ 0x10, 0x80, 0x04, 0x10 },
-	{ 0x10, 0x90, 0x04, 0x10 },
-	{ 0x11, 0xA0, 0x05, 0x10 },
-	{ 0x11, 0xB0, 0x05, 0x10 },
-	{ 0x16, 0xA0, 0x05, 0x10 },
-	{ 0x16, 0xB0, 0x05, 0x10 },
-	{ 0x00, 0xA0, 0x0B, 0x10 },
-	{ 0x14, 0x80, 0x0B, 0x10 },
-	{ 0x14, 0x90, 0x0B, 0x10 }
-};
-
-const int16 CharacterGenerator::_chargenBoxX[] = { 0x10, 0x50, 0x10, 0x50 };
-const int16 CharacterGenerator::_chargenBoxY[] = { 0x3F, 0x3F, 0x7F, 0x7F };
-const int16 CharacterGenerator::_chargenNameFieldX[] = { 0x02, 0x42, 0x02, 0x42 };
-const int16 CharacterGenerator::_chargenNameFieldY[] = { 0x6B, 0x6B, 0xAB, 0xAB };
-
-const int32 CharacterGenerator::_classMenuMasks[] = {
-	0x003F, 0x07BB, 0x77FB, 0x00F1, 0x08F1, 0x00B1
-};
-
-const int32 CharacterGenerator::_alignmentMenuMasks[] = {
-	0x01FF, 0x0007, 0x0001, 0x01FF, 0x01FF, 0x01FE, 0x01FF, 0x01FE,
-	0x01FF, 0x01FE, 0x01FE, 0x01FE, 0x01FF, 0x0007, 0x01FF
-};
-
-const int16 CharacterGenerator::_raceModifiers[] = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 1, -1, 0, 1, -1, 0, 0, 0, -1, 0, 0, 1, 0, 0
-};
-
-// Transfer Party
-
-class TransferPartyWiz {
-public:
-	TransferPartyWiz(EoBCoreEngine *vm, Screen_EoB *screen);
-	~TransferPartyWiz();
-
-	bool start();
-
-private:
-	bool selectAndLoadTransferFile();
-	bool transferFileDialogue(Common::String &dest);
-
-
-	int selectCharactersMenu();
-	void drawCharPortraitWithStats(int charIndex, bool enabled);
-	void updateHighlight(int index);
-
-	void convertStats();
-	void convertInventory();
-	Item convertItem(Item eob1Item);
-	void giveKhelbensCoin();
-
-	EoBCoreEngine *_vm;
-	Screen_EoB *_screen;
-
-	int _highlight;
-	EoBItem *_oldItems;
-
-	const uint16 *_portraitFrames;
-	const uint8 *_convertTable;
-	const uint8 *_itemTable;
-	const uint32 *_expTable;
-	const char *const *_strings1;
-	const char *const *_strings2;
-	const char *const *_labels;
-};
-
-TransferPartyWiz::TransferPartyWiz(EoBCoreEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen) {
-	int temp;
-	_portraitFrames = _vm->staticres()->loadRawDataBe16(kEoB2TransferPortraitFrames, temp);
-	_convertTable = _vm->staticres()->loadRawData(kEoB2TransferConvertTable, temp);
-	_itemTable = _vm->staticres()->loadRawData(kEoB2TransferItemTable, temp);
-	_expTable = _vm->staticres()->loadRawDataBe32(kEoB2TransferExpTable, temp);
-	_strings1 = _vm->staticres()->loadStrings(kEoB2TransferStrings1, temp);
-	_strings2 = _vm->staticres()->loadStrings(kEoB2TransferStrings2, temp);
-	_labels = _vm->staticres()->loadStrings(kEoB2TransferLabels, temp);
-	_highlight = -1;
-	_oldItems = 0;
-}
-
-TransferPartyWiz::~TransferPartyWiz() {
-	delete[] _oldItems;
-}
-
-bool TransferPartyWiz::start() {
-	_screen->copyPage(0, 12);
-
-	if (!selectAndLoadTransferFile())
-		return false;
-
-	convertStats();
-
-	_oldItems = new EoBItem[600];
-	memcpy(_oldItems, _vm->_items, sizeof(EoBItem) * 600);
-	_vm->loadItemDefs();
-
-	int selection = selectCharactersMenu();
-	if (selection == 0) {
-		for (int i = 0; i < 6; i++)
-			delete[] _vm->_characters[i].faceShape;
-		memset(_vm->_characters, 0, sizeof(EoBCharacter) * 6);
-		return false;
-	}
-
-	int ch = 0;
-	for (int i = 0; i < 6; i++) {
-		if (selection & (1 << i)) {
-			if (ch != i) {
-				delete[] _vm->_characters[ch].faceShape;
-				memcpy(&_vm->_characters[ch], &_vm->_characters[i], sizeof(EoBCharacter));
-				_vm->_characters[i].faceShape = 0;
-			}
-			ch++;
-		}
-	}
-	memset(&_vm->_characters[4], 0, sizeof(EoBCharacter) * 2);
-
-	convertInventory();
-	giveKhelbensCoin();
-
-	return true;
-}
-
-bool TransferPartyWiz::selectAndLoadTransferFile() {
-	do {
-		_screen->copyPage(12, 0);
-		 if (transferFileDialogue(_vm->_savegameFilename))
-			 break;
-	} while (_vm->_gui->confirmDialogue2(15, 68, 1));
-
-	if (_vm->_savegameFilename.empty())
-		return false;
-
-	if (_vm->loadGameState(-1).getCode() != Common::kNoError)
-		return false;
-
-	return true;
-}
-
- bool TransferPartyWiz::transferFileDialogue(Common::String &dest) {
-	_vm->_gui->transferWaitBox();
-
-	Common::Array<Common::String> eobTargets;
-	const Common::ConfigManager::DomainMap dom = ConfMan.getGameDomains();
-
-	for (Common::ConfigManager::DomainMap::const_iterator i = dom.begin(); i != dom.end(); ++i) {
-		if (ConfMan.get("gameid", i->_key).equals("eob"))
-			eobTargets.push_back(i->_key);
-		_vm->updateInput();
-	}
-
-	if (eobTargets.empty())
-		return false;
-
-	Common::String target = _vm->_gui->transferTargetMenu(eobTargets);
-	_screen->copyPage(12, 0);
-
-	if (target.empty())
-		return true;
-
-	dest = target + ".fin";
-	Common::InSaveFile *in = _vm->_saveFileMan->openForLoading(dest);
-	if (in) {
-		delete in;
-		if (_vm->_gui->confirmDialogue2(15, -2, 1))
-			return true;
-	}
-
-	_screen->copyPage(12, 0);
-
-	bool result = _vm->_gui->transferFileMenu(target, dest);
-	_screen->copyPage(12, 0);
-
-	return result;
-}
-
-int TransferPartyWiz::selectCharactersMenu() {
-	_screen->setCurPage(2);
-	_screen->setFont(Screen::FID_6_FNT);
-	_screen->clearCurPage();
-
-	_vm->gui_drawBox(0, 0, 320, 163, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
-	_screen->printText(_strings2[0], 5, 3, 15, 0);
-	_screen->printText(_strings2[1], 5, 10, 15, 0);
-
-	for (int i = 0; i < 6; i++)
-		drawCharPortraitWithStats(i, 0);
-
-	_vm->gui_drawBox(4, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
-	_vm->gui_drawBox(272, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
-
-	_screen->printShadedText(_labels[0], 9, 151, 15, 0);
-	_screen->printShadedText(_labels[1], 288, 151, 15, 0);
-
-	_screen->setCurPage(0);
-	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->updateScreen();
-
-	int selection = 0;
-	int highlight = 0;
-	bool update = false;
-
-	for (bool loop = true; loop && (!_vm->shouldQuit());) {
-		int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF;
-		_vm->removeInputTop();
-
-		if (inputFlag) {
-			if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
-				highlight ^= 1;
-			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP]) {
-				highlight -= 2;
-				if (highlight < 0)
-					highlight += 8;
-			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
-				highlight += 2;
-				if (highlight >= 8)
-					highlight -= 8;
-			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE]) {
-				update = true;
-			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
-				update = true;
-				highlight = 6;
-			} else if (inputFlag == 199) {
-				for (int i = 0; i < 8; i++) {
-					int t = i << 2;
-					if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, _portraitFrames[t], _portraitFrames[t + 1], _portraitFrames[t + 2], _portraitFrames[t + 3])) {
-						highlight = i;
-						update = true;
-						break;
-					}
-				}
-			}
-		}
-
-		updateHighlight(highlight);
-
-		if (!update)
-			continue;
-
-		update = false;
-
-		if (highlight < 6) {
-			if (_vm->_characters[highlight].flags & 1) {
-				selection ^= (1 << highlight);
-				drawCharPortraitWithStats(highlight, (selection & (1 << highlight)) ? true : false);
-				_screen->updateScreen();
-			}
-			continue;
-		}
-
-		int x = (highlight - 6) * 268 + 4;
-		_vm->gui_drawBox(x, 148, 43, 12, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.fill, -1);
-		_screen->updateScreen();
-		_vm->_system->delayMillis(80);
-		_vm->gui_drawBox(x, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, -1);
-		_screen->updateScreen();
-
-		if (highlight == 6 || _vm->shouldQuit()) {
-			_screen->setFont(Screen::FID_8_FNT);
-			return 0;
-		}
-
-		int count = 0;
-		for (int i = 0; i < 6; i++) {
-			if (selection & (1 << i))
-				count++;
-		}
-
-		if (count == 4 || _vm->shouldQuit())
-			loop = false;
-		else
-			_vm->_gui->messageDialogue(16, count < 4 ? 69 : 70, 6);
-
-		_screen->updateScreen();
-	}
-
-	_screen->setFont(Screen::FID_8_FNT);
-	if (_vm->shouldQuit())
-		return 0;
-	else
-		_vm->_gui->messageDialogue(16, 71, 6);
-
-	return selection;
-}
-
-void TransferPartyWiz::drawCharPortraitWithStats(int charIndex, bool enabled) {
-	int16 x = (charIndex % 2) * 159;
-	int16 y = (charIndex / 2) * 40;
-	EoBCharacter *c = &_vm->_characters[charIndex];
-
-	_screen->fillRect(x + 4, y + 24, x + 36, y + 57, 12);
-	_vm->gui_drawBox(x + 40, y + 24, 118, 34, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
-
-	if (!(c->flags & 1))
-		return;
-
-	_screen->drawShape(_screen->_curPage, c->faceShape, x + 4, y + 25, 0);
-
-	int color1 = 15;
-	int color2 = 12;
-
-	if (enabled) {
-		color1 = 6;
-		color2 = 15;
-	} else {
-		_screen->drawShape(_screen->_curPage, _vm->_disabledCharGrid, x + 4, y + 25, 0);
-	}
-
-	_screen->printShadedText(c->name, x + 44, y + 27, color1, 0);
-	_screen->printText(_vm->_chargenRaceSexStrings[c->raceSex], x + 43, y + 36, color2, 0);
-	_screen->printText(_vm->_chargenClassStrings[c->cClass], x + 43, y + 43, color2, 0);
-
-	Common::String tmp = Common::String::format(_strings1[0], c->level[0]);
-	for (int i = 1; i < _vm->_numLevelsPerClass[c->cClass]; i++)
-		tmp += Common::String::format(_strings1[1], c->level[i]);
-	_screen->printText(tmp.c_str(), x + 43, y + 50, color2, 0);
-}
-
-void TransferPartyWiz::updateHighlight(int index) {
-	static const int16 xPos[] = { 9, 288 };
-	if (_highlight > 5 && _highlight != index)
-		_screen->printText(_labels[_highlight - 6], xPos[_highlight - 6], 151, 15, 0);
-
-	if (index < 6) {
-		_vm->_gui->updateBoxFrameHighLight(14 + index);
-		_highlight = index;
-		return;
-	}
-
-	if (_highlight == index)
-		return;
-
-	if (_highlight < 6)
-		_vm->_gui->updateBoxFrameHighLight(-1);
-
-	_screen->printText(_labels[index - 6], xPos[index - 6], 151, 6, 0);
-	_screen->updateScreen();
-	_highlight = index;
-}
-
-void TransferPartyWiz::convertStats() {
-	for (int i = 0; i < 6; i++) {
-		EoBCharacter *c = &_vm->_characters[i];
-		uint32 aflags = 0;
-
-		for (int ii = 0; ii < 25; ii++) {
-			if (c->mageSpellsAvailableFlags & (1 << ii)) {
-				int8 f = (int8)_convertTable[ii + 1] - 1;
-				if (f != -1)
-					aflags |= (1 << f);
-			}
-		}
-		c->mageSpellsAvailableFlags = aflags;
-
-		c->armorClass = 0;
-		c->disabledSlots = 0;
-		c->flags &= 1;
-		c->hitPointsCur = c->hitPointsMax;
-		c->food = 100;
-
-		c->effectFlags = 0;
-		c->damageTaken = 0;
-		memset(c->clericSpells, 0, sizeof(int8) * 80);
-		memset(c->mageSpells, 0, sizeof(int8) * 80);
-		memset(c->timers, 0, sizeof(uint32) * 10);
-		memset(c->events, 0, sizeof(int8) * 10);
-		memset(c->effectsRemainder, 0, sizeof(uint8) * 4);
-		memset(c->slotStatus, 0, sizeof(int8) * 5);
-
-		for (int ii = 0; ii < 3; ii++) {
-			int t = _vm->getCharacterClassType(c->cClass, ii);
-			if (t == -1)
-				continue;
-			if (c->experience[ii] > _expTable[t])
-				c->experience[ii] = _expTable[t];
-		}
-	}
-}
-
-void TransferPartyWiz::convertInventory() {
-	for (int i = 0; i < 4; i++) {
-		EoBCharacter *c = &_vm->_characters[i];
-
-		for (int slot = 0; slot < 27; slot++) {
-			Item itm = c->inventory[slot];
-			if (slot == 16) {
-				Item first = itm;
-				c->inventory[slot] = 0;
-
-				for (bool forceLoop = true; (itm && (itm != first)) || forceLoop; itm = _oldItems[itm].prev) {
-					forceLoop = false;
-					_vm->setItemPosition(&c->inventory[slot], -2, convertItem(itm), 0);
-				}
-			} else {
-				c->inventory[slot] = convertItem(itm);
-			}
-		}
-	}
-}
-
-Item TransferPartyWiz::convertItem(Item eob1Item) {
-	if (!eob1Item)
-		return 0;
-
-	EoBItem *itm1 = &_oldItems[eob1Item];
-
-	if (!_itemTable[itm1->type])
-		return 0;
-
-	Item newItem = _vm->duplicateItem(1);
-	EoBItem *itm2 = &_vm->_items[newItem];
-	bool match = false;
-
-	itm2->flags = itm1->flags | 0x40;
-	itm2->icon = itm1->icon;
-	itm2->type = itm1->type;
-	itm2->level = 0xFF;
-
-	switch (itm2->type) {
-	case 35:
-		itm1->value += 25;
-		// fall through
-	case 34:
-		itm2->value = _convertTable[itm1->value];
-		if (!itm2->value) {
-			itm2->block = -1;
-			return 0;
-		}
-		break;
-	case 39:
-		itm2->value = itm1->value - 1;
-		break;
-	case 48:
-		if (itm1->value == 5) {
-			memset(itm2, 0, sizeof(EoBItem));
-			itm2->block = -1;
-			return 0;
-		}
-		itm2->value = itm1->value;
-		itm2->flags = ((itm1->flags & 0x3F) + 3) | 0x40;
-		break;
-	case 18:
-		itm2->icon = 19;
-		// fall through
-	default:
-		itm2->value = itm1->value;
-		break;
-	}
-
-	switch ((_vm->_itemTypes[itm2->type].extraProperties & 0x7F) - 1) {
-	case 0:
-	case 1:
-	case 2:
-		if (itm2->value)
-			itm2->flags |= 0x80;
-		break;
-	case 4:
-	case 5:
-	case 8:
-	case 9:
-	case 13:
-	case 15:
-	case 17:
-		itm2->flags |= 0x80;
-		break;
-	default:
-		break;
-	}
-
-	for (int i = 1; i < 600; i++) {
-		if (i == 60 || i == 62 || i == 63 || i == 83)
-			continue;
-		EoBItem *tmp = &_vm->_items[i];
-		if (tmp->level || tmp->block == -2 || tmp->type != itm2->type || tmp->icon != itm2->icon)
-			continue;
-		itm2->nameUnid = tmp->nameUnid;
-		itm2->nameId = tmp->nameId;
-		match = true;
-		break;
-	}
-
-	if (!match) {
-		for (int i = 1; i < 600; i++) {
-			if (i == 60 || i == 62 || i == 63 || i == 83)
-				continue;
-			EoBItem *tmp = &_vm->_items[i];
-			if (tmp->level || tmp->block == -2 || tmp->type != itm2->type)
-				continue;
-			itm2->nameUnid = tmp->nameUnid;
-			itm2->nameId = tmp->nameId;
-			match = true;
-			break;
-		}
-	}
-
-	if (!match) {
-		memset(itm2, 0, sizeof(EoBItem));
-		itm2->block = -1;
-		return 0;
-	}
-
-	itm2->level = 0;
-	return newItem;
-}
-
-void TransferPartyWiz::giveKhelbensCoin() {
-	bool success = false;
-	for (int i = 0; i < 4 && !success; i++) {
-		EoBCharacter *c = &_vm->_characters[i];
-
-		for (int slot = 2; slot < 16; slot++) {
-			if (c->inventory[slot])
-				continue;
-			_vm->createInventoryItem(c, 93, -1, slot);
-			success = true;
-			break;
-		}
-	}
-
-	if (!success) {
-		_vm->_characters[0].inventory[2] = 0;
-		_vm->createInventoryItem(&_vm->_characters[0], 93, -1, 2);
-	}
-}
-
-// Start functions
-
-bool EoBCoreEngine::startCharacterGeneration() {
-	return CharacterGenerator(this, _screen).start(_characters, &_faceShapes);
-}
-
-bool EoBCoreEngine::startPartyTransfer() {
-	return TransferPartyWiz(this, _screen).start();
-}
-
-} // End of namespace Kyra
-
-#endif // ENABLE_EOB
diff --git a/engines/kyra/darkmoon.cpp b/engines/kyra/darkmoon.cpp
deleted file mode 100644
index 1250854..0000000
--- a/engines/kyra/darkmoon.cpp
+++ /dev/null
@@ -1,493 +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.
- *
- */
-
-#ifdef ENABLE_EOB
-
-#include "kyra/darkmoon.h"
-#include "kyra/resource.h"
-#include "kyra/sound.h"
-
-namespace Kyra {
-
-DarkMoonEngine::DarkMoonEngine(OSystem *system, const GameFlags &flags) : EoBCoreEngine(system, flags) {
-	_dscDoorType5Offs = 0;
-	_numSpells = 70;
-	_menuChoiceInit = 4;
-
-	_kheldranStrings = _npcStrings[0] = _npcStrings[1] = _hornStrings = 0;
-	_utilMenuStrings = _ascii2SjisTables = _ascii2SjisTables2 = 0;
-	_npcShpData = _dscDoorType5Offs = _hornSounds = 0;
-	_dreamSteps = 0;
-}
-
-DarkMoonEngine::~DarkMoonEngine() {
-}
-
-Common::Error DarkMoonEngine::init() {
-	Common::Error err = EoBCoreEngine::init();
-	if (err.getCode() != Common::kNoError)
-		return err;
-
-	initStaticResource();
-
-	_monsterProps = new EoBMonsterProperty[10];
-
-	if (_configRenderMode == Common::kRenderEGA) {
-		Palette pal(16);
-		_screen->loadPalette(_egaDefaultPalette, pal, 16);
-		_screen->setScreenPalette(pal);
-	}
-
-	_screen->loadPalette(_flags.platform == Common::kPlatformFMTowns ? "MENU.PAL" : "PALETTE.COL", _screen->getPalette(0));
-	_screen->setScreenPalette(_screen->getPalette(0));
-
-	// adjust menu settings for EOB II FM-Towns
-	if (_flags.platform == Common::kPlatformFMTowns) {
-		_screen->modifyScreenDim(6, 10, 100, 21, 40);
-		_screen->modifyScreenDim(27, 0, 0, 21, 2);
-	}
-
-	return Common::kNoError;
-}
-
-void DarkMoonEngine::startupNew() {
-	_currentLevel = 4;
-	_currentSub = 0;
-	loadLevel(4, 0);
-	_currentBlock = 171;
-	_currentDirection = 2;
-	setHandItem(0);
-	EoBCoreEngine::startupNew();
-}
-
-void DarkMoonEngine::drawNpcScene(int npcIndex) {
-	const uint8 *shpDef = &_npcShpData[npcIndex << 3];
-	for (int i = npcIndex; i != 255; i = shpDef[7]) {
-		shpDef = &_npcShpData[i << 3];
-		_screen->_curPage = 2;
-		const uint8 *shp = _screen->encodeShape(READ_LE_UINT16(shpDef), shpDef[2], shpDef[3], shpDef[4]);
-		_screen->_curPage = 0;
-		_screen->drawShape(0, shp, 88 + shpDef[5] - (shp[2] << 2), 104 + shpDef[6] - shp[1], 5);
-		delete[] shp;
-	}
-}
-
-void DarkMoonEngine::runNpcDialogue(int npcIndex) {
-	if (npcIndex == 0) {
-		snd_playSoundEffect(57);
-		if (npcJoinDialogue(0, 1, 3, 2))
-			setScriptFlags(0x40);
-	} else if (npcIndex == 1) {
-		snd_playSoundEffect(53);
-		gui_drawDialogueBox();
-
-		_txt->printDialogueText(4, 0);
-		int r = runDialogue(-1, 2, _npcStrings[0][0], _npcStrings[0][1]) - 1;
-
-		if (r == 0) {
-			snd_stopSound();
-			delay(3 * _tickLength);
-			snd_playSoundEffect(91);
-			npcJoinDialogue(1, 5, 6, 7);
-		} else if (r == 1) {
-			setScriptFlags(0x20);
-		}
-
-	} else if (npcIndex == 2) {
-		snd_playSoundEffect(55);
-		gui_drawDialogueBox();
-
-		_txt->printDialogueText(8, 0);
-		int r = runDialogue(-1, 2, _npcStrings[1][0], _npcStrings[1][1]) - 1;
-
-		if (r == 0) {
-			if (rollDice(1, 2, -1))
-				_txt->printDialogueText(9, _okStrings[0]);
-			else
-				npcJoinDialogue(2, 102, 103, 104);
-			setScriptFlags(8);
-		} else if (r == 1) {
-			_currentDirection = 0;
-		}
-	}
-}
-
-void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) {
-	EoBItem *itm = &_items[_characters[charIndex].inventory[slot]];
-	if (itm->type == 48 || itm->type == 62) {
-		if (itm->value == 5)
-			return;
-		int charges = itm->flags & 0x3F;
-		if (--charges)
-			--itm->flags;
-		else
-			deleteInventoryItem(charIndex, slot);
-	} else if (itm->type == 26 || itm->type == 34 || itm->type == 35) {
-		deleteInventoryItem(charIndex, slot);
-	}
-}
-
-void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) {
-	int cp = _screen->setCurPage(2);
-	_screen->loadShapeSetBitmap(file, 3, 3);
-	uint8 tmpPal[16];
-	uint8 newPal[16];
-
-	for (int i = 0; i < 6; i++) {
-		int dci = monsterIndex + i;
-		memcpy(tmpPal, _monsterShapes[dci] + 4, 16);
-		int colx = 302 + 3 * i;
-
-		for (int ii = 0; ii < 16; ii++) {
-			uint8 col = _screen->getPagePixel(_screen->_curPage, colx, 184 + ii);
-			int iii = 0;
-			for (; iii < 16; iii++) {
-				if (tmpPal[iii] == col) {
-					newPal[ii] = iii;
-					break;
-				}
-			}
-
-			if (iii == 16)
-				newPal[ii] = 0;
-		}
-
-		for (int ii = 1; ii < 3; ii++) {
-			memcpy(tmpPal, _monsterShapes[dci] + 4, 16);
-
-			for (int iii = 0; iii < 16; iii++) {
-				uint8 col = _screen->getPagePixel(_screen->_curPage, colx + ii, 184 + iii);
-				if (newPal[iii])
-					tmpPal[newPal[iii]] = col;
-			}
-
-			int c = i;
-			if (monsterIndex >= 18)
-				c += 6;
-
-			c = (c << 1) + (ii - 1);
-			assert(c < 24);
-			memcpy(_monsterPalettes[c], tmpPal, 16);
-		}
-	}
-
-	_screen->setCurPage(cp);
-}
-
-void DarkMoonEngine::loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex) {
-	int len = stream->readUint16LE();
-	Common::List<SpriteDecoration*> activeDecorations;
-
-	for (int i = 0; i < len; i++) {
-		for (int ii = 0; ii < 6; ii++) {
-			uint8 dc[6];
-			stream->read(dc, 6);
-			if (!dc[2] || !dc[3])
-				continue;
-
-			SpriteDecoration *m = &_monsterDecorations[i * 6 + ii + monsterIndex];
-			if (_flags.platform != Common::kPlatformFMTowns)
-				m->shp = _screen->encodeShape(dc[0], dc[1], dc[2], dc[3]);
-			m->x = (int8)dc[4];
-			m->y = (int8)dc[5];
-			activeDecorations.push_back(m);
-		}
-	}
-
-	if (_flags.platform == Common::kPlatformFMTowns) {
-		while (!activeDecorations.empty()) {
-			activeDecorations.front()->shp = loadTownsShape(stream);
-			activeDecorations.pop_front();
-		}
-	}
-}
-
-void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
-	uint8 flg = _levelBlockProperties[block].flags & 7;
-
-	if (flg == 7 || _currentBlock == block || (flg && (_monsterProps[type].u30 || pos == 4)))
-		return;
-
-	for (int i = 0; i < 30; i++) {
-		if (_monsters[i].block != block)
-			continue;
-		if (_monsters[i].pos == 4 || _monsterProps[_monsters[i].type].u30)
-			return;
-	}
-
-	int index = -1;
-	int maxDist = 0;
-
-	for (int i = 0; i < 30; i++) {
-		if (_monsters[i].hitPointsCur <= 0) {
-			index = i;
-			break;
-		}
-
-		if (_monsters[i].flags & 0x40)
-			continue;
-
-		// WORKAROUND for bug #3611077 (Dran's dragon transformation sequence triggered prematurely):
-		// The boss level and the mindflayer level share the same monster data. If you hang around
-		// long enough in the mindflayer level all 30 monster slots will be used up. When this
-		// happens it will trigger the dragon transformation sequence when Dran is moved around by script.
-		// We avoid removing Dran here by prefering monster slots occupied by monsters from another
-		// sub level.
-		if (_monsters[i].sub != _currentSub) {
-			index = i;
-			break;
-		}
-
-		int dist = getBlockDistance(_monsters[i].block, _currentBlock);
-
-		if (dist > maxDist) {
-			maxDist = dist;
-			index = i;
-		}
-	}
-
-	if (index == -1)
-		return;
-
-	if (_monsters[index].hitPointsCur > 0)
-		killMonster(&_monsters[index], false);
-
-	initMonster(index, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);
-}
-
-bool DarkMoonEngine::killMonsterExtra(EoBMonsterInPlay *m) {
-	// WORKAROUND for bug #3611077 (see DarkMoonEngine::replaceMonster())
-	// The mindflayers have monster type 0, just like Dran. Using a monster slot occupied by a mindflayer would trigger the dragon transformation
-	// sequence when all 30 monster slots are used up. We avoid this by checking for m->sub == 1.
-	if (_currentLevel == 16 && _currentSub == 1 && m->sub == 1 && (_monsterProps[m->type].capsFlags & 4)) {
-		if (m->type) {
-			_playFinale = true;
-			_runFlag = false;
-			delay(850);
-		} else {
-			m->hitPointsCur = 150;
-			m->curRemoteWeapon = 0;
-			m->numRemoteAttacks = 255;
-			m->shpIndex++;
-			m->type++;
-			seq_dranDragonTransformation();
-		}
-		return false;
-	}
-	return true;
-}
-
-const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) {
-	_screen->loadShapeSetBitmap(filename, 3, 3);
-	for (int i = 0; i < 3; i++) {
-		_doorShapes[doorIndex * 3 + i] = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6));
-		shapeDefs += 8;
-	}
-
-	for (int i = 0; i < 2; i++) {
-		_doorSwitches[doorIndex * 3 + i].shp = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6));
-		shapeDefs += 8;
-		_doorSwitches[doorIndex * 3 + i].x = *shapeDefs;
-		shapeDefs += 2;
-		_doorSwitches[doorIndex * 3 + i].y = *shapeDefs;
-		shapeDefs += 2;
-	}
-	_screen->_curPage = 0;
-	return shapeDefs;
-}
-
-void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16) {
-	int shapeIndex = type * 3 + 2 - mDim;
-	uint8 *shp = _doorShapes[shapeIndex];
-	if (!shp)
-		return;
-
-	if ((_doorType[type] == 0) || (_doorType[type] == 1)) {
-		y = _dscDoorY1[mDim] - shp[1];
-		x -= (shp[2] << 2);
-
-		if (_doorType[type] == 1) {
-			drawBlockObject(0, 2, shp, x, y, 5);
-			shp = _doorShapes[3 + shapeIndex];
-		}
-
-		y -= ((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim]);
-
-		if (_specialWallTypes[wall] == 5)
-			y -= _dscDoorType5Offs[shapeIndex];
-
-	} else if (_doorType[type] == 2) {
-		x -= (shp[2] << 2);
-		y = _dscDoorY2[mDim] - ((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim]);
-	}
-
-	drawBlockObject(0, 2, shp, x, y, 5);
-
-	if (_doorType[type] == 2) {
-		shp = _doorShapes[shapeIndex + 3];
-		y = _dscDoorFrameY2[mDim] - shp[1] + (((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim]) >> 1) - 1;
-		drawBlockObject(0, 2, shp, x, y, 5);
-	}
-
-	if (_wllShapeMap[wall] == -1 && !_noDoorSwitch[type])
-		drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
-}
-
-void DarkMoonEngine::restParty_npc() {
-	int insalId = -1;
-	int numChar = 0;
-
-	for (int i = 0; i < 6; i++) {
-		if (!testCharacter(i, 1))
-			continue;
-		if (testCharacter(i, 2) && _characters[i].portrait == -1)
-			insalId = i;
-		numChar++;
-	}
-
-	if (insalId == -1 || numChar < 5)
-		return;
-
-	removeCharacterFromParty(insalId);
-	if (insalId < 4)
-		exchangeCharacters(insalId, testCharacter(5, 1) ? 5 : 4);
-
-	clearScriptFlags(6);
-
-	if (!stripPartyItems(1, 1, 1, 1))
-		stripPartyItems(2, 1, 1, 1);
-	stripPartyItems(31, 0, 1, 3);
-	stripPartyItems(39, 1, 0, 3);
-	stripPartyItems(47, 0, 1, 2);
-
-	_items[createItemOnCurrentBlock(28)].value = 26;
-
-	gui_drawPlayField(false);
-	gui_drawAllCharPortraitsWithStats();
-
-	_screen->setClearScreenDim(10);
-	_screen->set16bitShadingLevel(4);
-	gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1);
-	gui_drawBox((_screen->_curDim->sx << 3) + 1, _screen->_curDim->sy + 1, (_screen->_curDim->w << 3) - 2, _screen->_curDim->h - 2, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
-	_screen->set16bitShadingLevel(0);
-	_gui->messageDialogue2(11, 63, 6);
-	_gui->messageDialogue2(11, 64, 6);
-}
-
-bool DarkMoonEngine::restParty_extraAbortCondition() {
-	if (_currentLevel != 3)
-		return false;
-
-	seq_nightmare();
-
-	return true;
-}
-
-void DarkMoonEngine::useHorn(int charIndex, int weaponSlot) {
-	int v = _items[_characters[charIndex].inventory[weaponSlot]].value - 1;
-	_txt->printMessage(_hornStrings[v]);
-	snd_playSoundEffect(_hornSounds[v]);
-}
-
-bool DarkMoonEngine::checkPartyStatusExtra() {
-	if (checkScriptFlags(0x100000))
-		seq_kheldran();
-	return _gui->confirmDialogue2(14, 67, 1);
-}
-
-void DarkMoonEngine::drawLightningColumn() {
-	int f = rollDice(1, 2, -1);
-	int y = 0;
-
-	for (int i = 0; i < 6; i++) {
-		f ^= 1;
-		drawBlockObject(f, 2, _lightningColumnShape, 72, y, 5);
-		y += 64;
-	}
-}
-
-int DarkMoonEngine::resurrectionSelectDialogue() {
-	countResurrectionCandidates();
-
-	_rrNames[_rrCount] = _abortStrings[0];
-	_rrId[_rrCount++] = 99;
-
-	int r = _rrId[runDialogue(-1, 9, _rrNames[0], _rrNames[1], _rrNames[2], _rrNames[3], _rrNames[4], _rrNames[5], _rrNames[6], _rrNames[7], _rrNames[8]) - 1];
-	if (r == 99)
-		return 0;
-
-	if (r < 0) {
-		r = -r;
-		if (prepareForNewPartyMember(33, r))
-			initNpc(r - 1);
-	} else {
-		_characters[r].hitPointsCur = 1;
-	}
-
-	return 1;
-}
-
-int DarkMoonEngine::charSelectDialogue() {
-	int cnt = 0;
-	const char *namesList[7];
-	memset(namesList, 0, 7 * sizeof(const char *));
-
-	for (int i = 0; i < 6; i++) {
-		if (!testCharacter(i, 3))
-			continue;
-		namesList[cnt++] = _characters[i].name;
-	}
-
-	namesList[cnt++] = _abortStrings[0];
-
-	int r = runDialogue(-1, 7, namesList[0], namesList[1], namesList[2], namesList[3], namesList[4], namesList[5], namesList[6]) - 1;
-	if (r == cnt - 1)
-		return 99;
-
-	for (cnt = 0; cnt < 6; cnt++) {
-		if (!testCharacter(cnt, 3))
-			continue;
-		if (--r < 0)
-			break;
-	}
-	return cnt;
-}
-
-void DarkMoonEngine::characterLevelGain(int charIndex) {
-	EoBCharacter *c = &_characters[charIndex];
-	int s = _numLevelsPerClass[c->cClass];
-	for (int i = 0; i < s; i++) {
-		uint32 er = getRequiredExperience(c->cClass, i, c->level[i] + 1);
-		if (er == 0xFFFFFFFF)
-			continue;
-
-		increaseCharacterExperience(charIndex, er - c->experience[i] + 1);
-	}
-}
-
-const KyraRpgGUISettings *DarkMoonEngine::guiSettings() {
-	return (_flags.platform == Common::kPlatformFMTowns) ? &_guiSettingsFMTowns : &_guiSettingsDOS;
-}
-
-} // End of namespace Kyra
-
-#endif // ENABLE_EOB
diff --git a/engines/kyra/darkmoon.h b/engines/kyra/darkmoon.h
deleted file mode 100644
index f7065da..0000000
--- a/engines/kyra/darkmoon.h
+++ /dev/null
@@ -1,139 +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.
- *
- */
-
-#ifdef ENABLE_EOB
-
-#ifndef KYRA_EOB2_H
-#define KYRA_EOB2_H
-
-#include "kyra/eobcommon.h"
-
-namespace Kyra {
-
-class DarkmoonSequenceHelper;
-
-struct DarkMoonAnimCommand {
-	uint8 command;
-	uint8 obj;
-	int16 x1;
-	uint8 y1;
-	uint8 delay;
-	uint8 pal;
-	uint8 x2;
-	uint8 y2;
-	uint8 w;
-	uint8 h;
-};
-
-class DarkMoonEngine : public EoBCoreEngine {
-friend class GUI_EoB;
-friend class DarkmoonSequenceHelper;
-public:
-	DarkMoonEngine(OSystem *system, const GameFlags &flags);
-	~DarkMoonEngine();
-
-private:
-	// Init / Release
-	Common::Error init();
-	void initStaticResource();
-	void initSpells();
-
-	// Main Menu
-	int mainMenu();
-	int mainMenuLoop();
-	void townsUtilitiesMenu();
-
-	int _menuChoiceInit;
-
-	// Main loop
-	void startupNew();
-	void startupLoad() {}
-
-	// Intro/Outro
-	void seq_playIntro();
-	void seq_playFinale();
-	void seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *data, int sd, int backupPage, int tempPage, int speed);
-
-	// Ingame sequence
-	void seq_nightmare();
-	void seq_kheldran();
-	void seq_dranDragonTransformation();
-
-	const int8 *_dreamSteps;
-	const char *const *_kheldranStrings;
-
-	// characters
-	void drawNpcScene(int npcIndex);
-	void runNpcDialogue(int npcIndex);
-
-	const uint8 *_npcShpData;
-	const char *const *_npcStrings[2];
-
-	// items
-	void updateUsedCharacterHandItem(int charIndex, int slot);
-
-	// Monsters
-	void generateMonsterPalettes(const char *file, int16 monsterIndex);
-	void loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex);
-	void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
-	bool killMonsterExtra(EoBMonsterInPlay *m);
-
-	// Level
-	void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {}
-	const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs);
-	void drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16);
-
-	const uint8 *_dscDoorType5Offs;
-
-	// Fight
-	static const uint8 _monsterAcHitChanceTbl1[];
-	static const uint8 _monsterAcHitChanceTbl2[];
-
-	// Rest party
-	void restParty_npc();
-	bool restParty_extraAbortCondition();
-
-	// misc
-	void useHorn(int charIndex, int weaponSlot);
-	bool checkPartyStatusExtra();
-	void drawLightningColumn();
-	int resurrectionSelectDialogue();
-	int charSelectDialogue();
-	void characterLevelGain(int charIndex);
-
-	const KyraRpgGUISettings *guiSettings();
-
-	const char *const *_hornStrings;
-	const uint8 *_hornSounds;
-
-	const char *const *_utilMenuStrings;
-
-	static const KyraRpgGUISettings _guiSettingsDOS;
-	static const KyraRpgGUISettings _guiSettingsFMTowns;
-	static const uint8 _egaDefaultPalette[];
-};
-
-} // End of namespace Kyra
-
-#endif
-
-#endif // ENABLE_EOB
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
deleted file mode 100644
index d87106c..0000000
--- a/engines/kyra/debugger.cpp
+++ /dev/null
@@ -1,744 +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 "kyra/debugger.h"
-#include "kyra/kyra_lok.h"
-#include "kyra/kyra_hof.h"
-#include "kyra/timer.h"
-#include "kyra/resource.h"
-#include "kyra/lol.h"
-#include "kyra/eobcommon.h"
-
-#include "common/system.h"
-#include "common/config-manager.h"
-
-namespace Kyra {
-
-Debugger::Debugger(KyraEngine_v1 *vm)
-	: ::GUI::Debugger(), _vm(vm) {
-}
-
-void Debugger::initialize() {
-	registerCmd("continue",           WRAP_METHOD(Debugger, cmdExit));
-	registerCmd("screen_debug_mode",  WRAP_METHOD(Debugger, cmdSetScreenDebug));
-	registerCmd("load_palette",       WRAP_METHOD(Debugger, cmdLoadPalette));
-	registerCmd("facings",            WRAP_METHOD(Debugger, cmdShowFacings));
-	registerCmd("gamespeed",          WRAP_METHOD(Debugger, cmdGameSpeed));
-	registerCmd("flags",              WRAP_METHOD(Debugger, cmdListFlags));
-	registerCmd("toggleflag",         WRAP_METHOD(Debugger, cmdToggleFlag));
-	registerCmd("queryflag",          WRAP_METHOD(Debugger, cmdQueryFlag));
-	registerCmd("timers",             WRAP_METHOD(Debugger, cmdListTimers));
-	registerCmd("settimercountdown",  WRAP_METHOD(Debugger, cmdSetTimerCountdown));
-}
-
-bool Debugger::cmdSetScreenDebug(int argc, const char **argv) {
-	if (argc > 1) {
-		if (scumm_stricmp(argv[1], "enable") == 0)
-			_vm->screen()->enableScreenDebug(true);
-		else if (scumm_stricmp(argv[1], "disable") == 0)
-			_vm->screen()->enableScreenDebug(false);
-		else
-			debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
-	} else {
-		debugPrintf("Screen debug mode is %s.\n", (_vm->screen()->queryScreenDebug() ? "enabled" : "disabled"));
-		debugPrintf("Use screen_debug_mode <enable/disable> to enable or disable it.\n");
-	}
-	return true;
-}
-
-bool Debugger::cmdLoadPalette(int argc, const char **argv) {
-	Palette palette(_vm->screen()->getPalette(0).getNumColors());
-
-	if (argc <= 1) {
-		debugPrintf("Use load_palette <file> [start_col] [end_col]\n");
-		return true;
-	}
-
-	if (_vm->game() != GI_KYRA1 && _vm->resource()->getFileSize(argv[1]) != 768) {
-		uint8 *buffer = new uint8[320 * 200 * sizeof(uint8)];
-		if (!buffer) {
-			debugPrintf("ERROR: Cannot allocate buffer for screen region!\n");
-			return true;
-		}
-
-		_vm->screen()->copyRegionToBuffer(5, 0, 0, 320, 200, buffer);
-		_vm->screen()->loadBitmap(argv[1], 5, 5, 0);
-		palette.copy(_vm->screen()->getCPagePtr(5), 0, 256);
-		_vm->screen()->copyBlockToPage(5, 0, 0, 320, 200, buffer);
-
-		delete[] buffer;
-	} else if (!_vm->screen()->loadPalette(argv[1], palette)) {
-		debugPrintf("ERROR: Palette '%s' not found!\n", argv[1]);
-		return true;
-	}
-
-	int startCol = 0;
-	int endCol = palette.getNumColors();
-	if (argc > 2)
-		startCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[2])));
-	if (argc > 3)
-		endCol = MIN(palette.getNumColors(), MAX(0, atoi(argv[3])));
-
-	if (startCol > 0)
-		palette.copy(_vm->screen()->getPalette(0), 0, startCol);
-	if (endCol < palette.getNumColors())
-		palette.copy(_vm->screen()->getPalette(0), endCol);
-
-	_vm->screen()->setScreenPalette(palette);
-	_vm->screen()->updateScreen();
-
-	return true;
-}
-
-bool Debugger::cmdShowFacings(int argc, const char **argv) {
-	debugPrintf("Facing directions:\n");
-	debugPrintf("7  0  1\n");
-	debugPrintf(" \\ | / \n");
-	debugPrintf("6--*--2\n");
-	debugPrintf(" / | \\\n");
-	debugPrintf("5  4  3\n");
-	return true;
-}
-
-bool Debugger::cmdGameSpeed(int argc, const char **argv) {
-	if (argc == 2) {
-		int val = atoi(argv[1]);
-
-		if (val < 1 || val > 1000) {
-			debugPrintf("speed must lie between 1 and 1000 (default: 60)\n");
-			return true;
-		}
-
-		_vm->_tickLength = (uint8)(1000.0 / val);
-	} else {
-		debugPrintf("Syntax: gamespeed <value>\n");
-	}
-
-	return true;
-}
-
-bool Debugger::cmdListFlags(int argc, const char **argv) {
-	for (int i = 0, p = 0; i < (int)sizeof(_vm->_flagsTable) * 8; i++, ++p) {
-		debugPrintf("(%-3i): %-2i", i, _vm->queryGameFlag(i));
-		if (p == 5) {
-			debugPrintf("\n");
-			p -= 6;
-		}
-	}
-	debugPrintf("\n");
-	return true;
-}
-
-bool Debugger::cmdToggleFlag(int argc, const char **argv) {
-	if (argc > 1) {
-		uint flag = atoi(argv[1]);
-		if (_vm->queryGameFlag(flag))
-			_vm->resetGameFlag(flag);
-		else
-			_vm->setGameFlag(flag);
-		debugPrintf("Flag %i is now %i\n", flag, _vm->queryGameFlag(flag));
-	} else {
-		debugPrintf("Syntax: toggleflag <flag>\n");
-	}
-
-	return true;
-}
-
-bool Debugger::cmdQueryFlag(int argc, const char **argv) {
-	if (argc > 1) {
-		uint flag = atoi(argv[1]);
-		debugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag));
-	} else {
-		debugPrintf("Syntax: queryflag <flag>\n");
-	}
-
-	return true;
-}
-
-bool Debugger::cmdListTimers(int argc, const char **argv) {
-	debugPrintf("Current time: %-8u\n", g_system->getMillis());
-	for (int i = 0; i < _vm->timer()->count(); i++)
-		debugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i %-8u\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i), _vm->timer()->getNextRun(i));
-
-	return true;
-}
-
-bool Debugger::cmdSetTimerCountdown(int argc, const char **argv) {
-	if (argc > 2) {
-		uint timer = atoi(argv[1]);
-		uint countdown = atoi(argv[2]);
-		_vm->timer()->setCountdown(timer, countdown);
-		debugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer));
-	} else {
-		debugPrintf("Syntax: settimercountdown <timer> <countdown>\n");
-	}
-
-	return true;
-}
-
-#pragma mark -
-
-Debugger_LoK::Debugger_LoK(KyraEngine_LoK *vm)
-	: Debugger(vm), _vm(vm) {
-}
-
-void Debugger_LoK::initialize() {
-	registerCmd("enter",              WRAP_METHOD(Debugger_LoK, cmdEnterRoom));
-	registerCmd("scenes",             WRAP_METHOD(Debugger_LoK, cmdListScenes));
-	registerCmd("give",               WRAP_METHOD(Debugger_LoK, cmdGiveItem));
-	registerCmd("birthstones",        WRAP_METHOD(Debugger_LoK, cmdListBirthstones));
-	Debugger::initialize();
-}
-
-bool Debugger_LoK::cmdEnterRoom(int argc, const char **argv) {
-	uint direction = 0;
-	if (argc > 1) {
-		int room = atoi(argv[1]);
-
-		// game will crash if entering a non-existent room
-		if (room >= _vm->_roomTableSize) {
-			debugPrintf("room number must be any value between (including) 0 and %d\n", _vm->_roomTableSize - 1);
-			return true;
-		}
-
-		if (argc > 2) {
-			direction = atoi(argv[2]);
-		} else {
-			if (_vm->_roomTable[room].northExit != 0xFFFF)
-				direction = 3;
-			else if (_vm->_roomTable[room].eastExit != 0xFFFF)
-				direction = 4;
-			else if (_vm->_roomTable[room].southExit != 0xFFFF)
-				direction = 1;
-			else if (_vm->_roomTable[room].westExit != 0xFFFF)
-				direction = 2;
-		}
-
-		_vm->_system->hideOverlay();
-		_vm->_currentCharacter->facing = direction;
-
-		_vm->enterNewScene(room, _vm->_currentCharacter->facing, 0, 0, 1);
-		while (!_vm->_screen->isMouseVisible())
-			_vm->_screen->showMouse();
-
-		detach();
-		return false;
-	}
-
-	debugPrintf("Syntax: room <roomnum> <direction>\n");
-	return true;
-}
-
-bool Debugger_LoK::cmdListScenes(int argc, const char **argv) {
-	for (int i = 0; i < _vm->_roomTableSize; i++) {
-		debugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]);
-		if (!(i % 8))
-			debugPrintf("\n");
-	}
-	debugPrintf("\n");
-	debugPrintf("Current room: %i\n", _vm->_currentRoom);
-	return true;
-}
-
-bool Debugger_LoK::cmdGiveItem(int argc, const char **argv) {
-	if (argc == 2) {
-		int item = atoi(argv[1]);
-
-		// Kyrandia 1 has only 108 items (-1 to 106), otherwise it will crash
-		if (item < -1 || item > 106) {
-			debugPrintf("'itemid' must be any value between (including) -1 and 106\n");
-			return true;
-		}
-
-		_vm->setMouseItem(item);
-		_vm->_itemInHand = item;
-	} else {
-		debugPrintf("Syntax: give <itemid>\n");
-	}
-
-	return true;
-}
-
-bool Debugger_LoK::cmdListBirthstones(int argc, const char **argv) {
-	debugPrintf("Needed birthstone gems:\n");
-	for (int i = 0; i < ARRAYSIZE(_vm->_birthstoneGemTable); ++i)
-		debugPrintf("%-3d '%s'\n", _vm->_birthstoneGemTable[i], _vm->_itemList[_vm->_birthstoneGemTable[i]]);
-	return true;
-}
-
-#pragma mark -
-
-Debugger_v2::Debugger_v2(KyraEngine_v2 *vm) : Debugger(vm), _vm(vm) {
-}
-
-void Debugger_v2::initialize() {
-	registerCmd("character_info",     WRAP_METHOD(Debugger_v2, cmdCharacterInfo));
-	registerCmd("enter",              WRAP_METHOD(Debugger_v2, cmdEnterScene));
-	registerCmd("scenes",             WRAP_METHOD(Debugger_v2, cmdListScenes));
-	registerCmd("scene_info",         WRAP_METHOD(Debugger_v2, cmdSceneInfo));
-	registerCmd("scene_to_facing",    WRAP_METHOD(Debugger_v2, cmdSceneToFacing));
-	registerCmd("give",               WRAP_METHOD(Debugger_v2, cmdGiveItem));
-	Debugger::initialize();
-}
-
-bool Debugger_v2::cmdEnterScene(int argc, const char **argv) {
-	uint direction = 0;
-	if (argc > 1) {
-		int scene = atoi(argv[1]);
-
-		// game will crash if entering a non-existent scene
-		if (scene >= _vm->_sceneListSize) {
-			debugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize - 1);
-			return true;
-		}
-
-		if (argc > 2) {
-			direction = atoi(argv[2]);
-		} else {
-			if (_vm->_sceneList[scene].exit1 != 0xFFFF)
-				direction = 4;
-			else if (_vm->_sceneList[scene].exit2 != 0xFFFF)
-				direction = 6;
-			else if (_vm->_sceneList[scene].exit3 != 0xFFFF)
-				direction = 0;
-			else if (_vm->_sceneList[scene].exit4 != 0xFFFF)
-				direction = 2;
-		}
-
-		_vm->_system->hideOverlay();
-		_vm->_mainCharacter.facing = direction;
-
-		_vm->enterNewScene(scene, _vm->_mainCharacter.facing, 0, 0, 1);
-		while (!_vm->screen_v2()->isMouseVisible())
-			_vm->screen_v2()->showMouse();
-
-		detach();
-		return false;
-	}
-
-	debugPrintf("Syntax: %s <scenenum> <direction>\n", argv[0]);
-	return true;
-}
-
-bool Debugger_v2::cmdListScenes(int argc, const char **argv) {
-	int shown = 1;
-	for (int i = 0; i < _vm->_sceneListSize; ++i) {
-		if (_vm->_sceneList[i].filename1[0]) {
-			debugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1);
-			if (!(shown % 5))
-				debugPrintf("\n");
-			++shown;
-		}
-	}
-	debugPrintf("\n");
-	debugPrintf("Current scene: %i\n", _vm->_currentScene);
-	return true;
-}
-
-bool Debugger_v2::cmdSceneInfo(int argc, const char **argv) {
-	debugPrintf("Current scene: %d '%s'\n", _vm->_currentScene, _vm->_sceneList[_vm->_currentScene].filename1);
-	debugPrintf("\n");
-	debugPrintf("Exit information:\n");
-	debugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1);
-	debugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2);
-	debugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3);
-	debugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4);
-	debugPrintf("Special exit information:\n");
-	if (!_vm->_specialExitCount) {
-		debugPrintf("No special exits.\n");
-	} else {
-		debugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount);
-		for (int i = 0; i < _vm->_specialExitCount; ++i) {
-			debugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i,
-			            _vm->_specialExitTable[20 + i], _vm->_specialExitTable[0 + i], _vm->_specialExitTable[5 + i],
-			            _vm->_specialExitTable[10 + i], _vm->_specialExitTable[15 + i]);
-		}
-	}
-
-	return true;
-}
-
-bool Debugger_v2::cmdCharacterInfo(int argc, const char **argv) {
-	debugPrintf("Main character is in scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1);
-	debugPrintf("Position: %dx%d\n", _vm->_mainCharacter.x1, _vm->_mainCharacter.y1);
-	debugPrintf("Facing: %d\n", _vm->_mainCharacter.facing);
-	debugPrintf("Inventory:\n");
-	for (int i = 0; i < 20; ++i) {
-		debugPrintf("%-2d ", int8(_vm->_mainCharacter.inventory[i]));
-		if (i == 9 || i == 19)
-			debugPrintf("\n");
-	}
-	return true;
-}
-
-bool Debugger_v2::cmdSceneToFacing(int argc, const char **argv) {
-	if (argc == 2) {
-		int facing = atoi(argv[1]);
-		int16 exit = -1;
-
-		switch (facing) {
-		case 0: case 1: case 7:
-			exit = _vm->_sceneList[_vm->_currentScene].exit1;
-			break;
-
-		case 6:
-			exit = _vm->_sceneList[_vm->_currentScene].exit2;
-			break;
-
-		case 3: case 4: case 5:
-			exit = _vm->_sceneList[_vm->_currentScene].exit3;
-			break;
-
-		case 2:
-			exit = _vm->_sceneList[_vm->_currentScene].exit4;
-			break;
-
-		default:
-			break;
-		}
-
-		debugPrintf("Exit to facing %d leads to room %d.\n", facing, exit);
-	} else {
-		debugPrintf("Usage: %s <facing>\n", argv[0]);
-	}
-
-	return true;
-}
-
-bool Debugger_v2::cmdGiveItem(int argc, const char **argv) {
-	if (argc == 2) {
-		int item = atoi(argv[1]);
-
-		if (item < -1 || item > _vm->engineDesc().maxItemId) {
-			debugPrintf("itemid must be any value between (including) -1 and %d\n", _vm->engineDesc().maxItemId);
-			return true;
-		}
-
-		_vm->setHandItem(item);
-	} else {
-		debugPrintf("Syntax: give <itemid>\n");
-	}
-
-	return true;
-}
-
-#pragma mark -
-
-Debugger_HoF::Debugger_HoF(KyraEngine_HoF *vm) : Debugger_v2(vm), _vm(vm) {
-}
-
-void Debugger_HoF::initialize() {
-	registerCmd("pass_codes",         WRAP_METHOD(Debugger_HoF, cmdPasscodes));
-	Debugger_v2::initialize();
-}
-
-bool Debugger_HoF::cmdPasscodes(int argc, const char **argv) {
-	if (argc == 2) {
-		int val = atoi(argv[1]);
-
-		if (val < 0 || val > 1) {
-			debugPrintf("value must be either 1 (on) or 0 (off)\n");
-			return true;
-		}
-
-		_vm->_dbgPass = val;
-	} else {
-		debugPrintf("Syntax: pass_codes <0/1>\n");
-	}
-
-	return true;
-}
-
-#pragma mark -
-
-#ifdef ENABLE_LOL
-Debugger_LoL::Debugger_LoL(LoLEngine *vm) : Debugger(vm), _vm(vm) {
-}
-#endif // ENABLE_LOL
-
-#ifdef ENABLE_EOB
-Debugger_EoB::Debugger_EoB(EoBCoreEngine *vm) : Debugger(vm), _vm(vm) {
-}
-
-void Debugger_EoB::initialize() {
-	registerCmd("import_savefile", WRAP_METHOD(Debugger_EoB, cmdImportSaveFile));
-	registerCmd("save_original", WRAP_METHOD(Debugger_EoB, cmdSaveOriginal));
-	registerCmd("list_monsters", WRAP_METHOD(Debugger_EoB, cmdListMonsters));
-	registerCmd("show_position", WRAP_METHOD(Debugger_EoB, cmdShowPosition));
-	registerCmd("set_position", WRAP_METHOD(Debugger_EoB, cmdSetPosition));
-	registerCmd("print_map", WRAP_METHOD(Debugger_EoB, cmdPrintMap));
-	registerCmd("open_door", WRAP_METHOD(Debugger_EoB, cmdOpenDoor));
-	registerCmd("close_door", WRAP_METHOD(Debugger_EoB, cmdCloseDoor));
-	registerCmd("list_flags", WRAP_METHOD(Debugger_EoB, cmdListFlags));
-	registerCmd("set_flag", WRAP_METHOD(Debugger_EoB, cmdSetFlag));
-	registerCmd("clear_flag", WRAP_METHOD(Debugger_EoB, cmdClearFlag));
-}
-
-bool Debugger_EoB::cmdImportSaveFile(int argc, const char **argv) {
-	if (!_vm->_allowImport) {
-		debugPrintf("This command only works from the main menu.\n");
-		return true;
-	}
-
-	if (argc == 3) {
-		int slot = atoi(argv[1]);
-		if (slot < -1 || slot > 989) {
-			debugPrintf("slot must be between (including) -1 and 989 \n");
-			return true;
-		}
-
-		debugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n");
-		_vm->loadItemDefs();
-	} else {
-		debugPrintf("Syntax:   import_savefile <dest slot> <source file>\n              (Imports source save game file to dest slot.)\n          import_savefile -1\n              (Imports all original save game files found and puts them into the first available slots.)\n\n");
-	}
-
-	return true;
-}
-
-bool Debugger_EoB::cmdSaveOriginal(int argc, const char **argv) {
-	if (!_vm->_runFlag) {
-		debugPrintf("This command doesn't work during intro or outro sequences,\nfrom the main menu or from the character generation.\n");
-		return true;
-	}
-
-	Common::String dir = ConfMan.get("savepath");
-	if (dir == "None")
-		dir.clear();
-
-	Common::FSNode nd(dir);
-	if (!nd.isDirectory())
-		return false;
-
-	if (_vm->game() == GI_EOB1) {
-		if (argc == 1) {
-			if (_vm->saveAsOriginalSaveFile()) {
-				Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA.SAV"));
-				if (nf.isReadable())
-					debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
-				else
-					debugPrintf("Failure.\n");
-			} else {
-				debugPrintf("Failure.\n");
-			}
-		} else {
-			debugPrintf("Syntax:   save_original\n          (Saves game in original file format to a file which can be used with the original game executable.)\n\n");
-		}
-		return true;
-
-	} else if (argc == 2) {
-		int slot = atoi(argv[1]);
-		if (slot < 0 || slot > 5) {
-			debugPrintf("Slot must be between (including) 0 and 5.\n");
-		} else if (_vm->saveAsOriginalSaveFile(slot)) {
-			Common::FSNode nf = nd.getChild(Common::String::format("EOBDATA%d.SAV", slot));
-			if (nf.isReadable())
-				debugPrintf("Saved to file: %s\n\n", nf.getPath().c_str());
-			else
-				debugPrintf("Failure.\n");
-		} else {
-			debugPrintf("Failure.\n");
-		}
-		return true;
-	}
-
-	debugPrintf("Syntax:   save_original <slot>\n          (Saves game in original file format to a file which can be used with the original game executable.\n          A save slot between 0 and 5 must be specified.)\n\n");
-	return true;
-}
-
-bool Debugger_EoB::cmdListMonsters(int, const char **) {
-	debugPrintf("\nCurrent level: %d\n----------------------\n\n", _vm->_currentLevel);
-	debugPrintf("Id        Type      Unit      Block     Position  Direction Sub Level Mode      Dst.block HP        Flags\n--------------------------------------------------------------------------------------------------------------\n");
-
-	for (int i = 0; i < 30; i++) {
-		EoBMonsterInPlay *m = &_vm->_monsters[i];
-		debugPrintf("%.02d        %.02d        %.02d        0x%.04x    %d         %d         %d         %.02d        0x%.04x    %.03d/%.03d   0x%.02x\n", i, m->type, m->unit, m->block, m->pos, m->dir, m->sub, m->mode, m->dest, m->hitPointsCur, m->hitPointsMax, m->flags);
-	}
-
-	debugPrintf("\n");
-
-	return true;
-}
-
-bool Debugger_EoB::cmdShowPosition(int, const char **) {
-	debugPrintf("\nCurrent level:      %d\nCurrent Sub Level:  %d\nCurrent block:      %d (0x%.04x)\nNext block:         %d (0x%.04x)\nCurrent direction:  %d\n\n", _vm->_currentLevel, _vm->_currentSub, _vm->_currentBlock, _vm->_currentBlock, _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection), _vm->_currentDirection);
-	return true;
-}
-
-bool Debugger_EoB::cmdSetPosition(int argc, const char **argv) {
-	if (argc == 4) {
-		_vm->_currentBlock = atoi(argv[3]);
-		int sub = atoi(argv[2]);
-		int level = atoi(argv[1]);
-
-		int maxLevel = (_vm->game() == GI_EOB1) ? 12 : 16;
-		if (level < 1 || level > maxLevel) {
-			debugPrintf("<level> must be a value from 1 to %d.\n\n", maxLevel);
-			return true;
-		}
-
-		if (level != _vm->_currentLevel || sub != _vm->_currentSub) {
-			_vm->completeDoorOperations();
-			_vm->generateTempData();
-			_vm->txt()->removePageBreakFlag();
-			_vm->screen()->setScreenDim(7);
-
-			_vm->loadLevel(level, sub);
-
-			if (_vm->_dialogueField)
-				_vm->restoreAfterDialogueSequence();
-		}
-
-		_vm->moveParty(_vm->_currentBlock);
-
-		_vm->_sceneUpdateRequired = true;
-		_vm->gui_drawAllCharPortraitsWithStats();
-		debugPrintf("Success.\n\n");
-
-	} else {
-		debugPrintf("Syntax:   set_position <level>, <sub level>, <block>\n");
-		debugPrintf("          (Warning: The sub level and block position parameters will not be checked. Invalid parameters may cause problems.)\n\n");
-	}
-	return true;
-}
-
-bool Debugger_EoB::cmdPrintMap(int, const char **) {
-	const uint8 illusion1 = _vm->gameFlags().gameID == GI_EOB1 ? 67 : 46;
-	const uint8 illusion2 = _vm->gameFlags().gameID == GI_EOB1 ? 64 : 46;
-	const uint8 plate1 = _vm->gameFlags().gameID == GI_EOB1 ? 28 : 35;
-	const uint8 plate2 = _vm->gameFlags().gameID == GI_EOB1 ? 28 : 36;
-	const uint8 hole = _vm->gameFlags().gameID == GI_EOB1 ? 27 : 38;
-	const uint8 stairsUp = 23;
-	const uint8 stairsDown = 24;
-	const uint8 types[] = { _vm->_teleporterWallId, illusion1, illusion2, stairsUp, stairsDown, hole, plate1, plate2 };
-	const uint8 signs[] = { 1, 15, 15, 'U', 'D', 164, 'O', 'O' };
-
-	for (int i = 0; i < 1024; ++i) {
-		if (!(i % 0x20))
-			debugPrintf("\n");
-		LevelBlockProperty *bl = &_vm->_levelBlockProperties[i];
-		uint8 f = _vm->_wllWallFlags[bl->walls[0]] | _vm->_wllWallFlags[bl->walls[1]] | _vm->_wllWallFlags[bl->walls[2]] | _vm->_wllWallFlags[bl->walls[3]];
-		uint8 s = _vm->_specialWallTypes[bl->walls[0]] | _vm->_specialWallTypes[bl->walls[1]] | _vm->_specialWallTypes[bl->walls[2]] | _vm->_specialWallTypes[bl->walls[3]];
-		uint8 c = ' ';
-		if (s == 3 || s == 4)
-			c = '/';
-		else if (s == 2 || s == 8)
-			c = (uint8)'°';
-		else if (f & 8)
-			c = 216;
-		else if (f & 1)
-			c = 2;
-
-		if (_vm->_currentBlock == i) {
-			c = 'X';			
-		} else {
-			for (int ii = 0; ii < ARRAYSIZE(types); ++ii) {
-				if (bl->walls[0] == types[ii] || bl->walls[1] == types[ii] || bl->walls[2] == types[ii] || bl->walls[3] == types[ii]) {
-					c = signs[ii];
-					break;
-				}
-			}
-		}
-		
-		debugPrintf("%c", c);
-	}
-	debugPrintf("\n\nParty Position:   %c  Door:             %c  Stairs Up/Down: %c/%c  Plate:      %c   Hole: %c\nSwitch:           %c  Clickable Object: %c  Illusion Wall:  %c    Teleporter: %c\n\n", 'X', 216, 'U', 'D', 'O', 164, '/', '°', 15, 1);
-
-	return true;
-}
-
-bool Debugger_EoB::cmdOpenDoor(int, const char **) {
-	uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection);
-	uint8 v = _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] | _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[1]];
-	int flg = (_vm->_flags.gameID == GI_EOB1) ? 1 : 0x10;
-	if (!(v & 8)) {
-		debugPrintf("Couldn't open any door. Make sure you're facing the door you wish to open and standing right in front of it.\n\n");
-	} else if (v & flg) {
-		debugPrintf("The door seems to be already open.\n\n");
-	} else {
-		_vm->openDoor(block);
-		debugPrintf("Trying to open door at block %d.\n\n", block);
-	}
-	return true;
-}
-
-bool Debugger_EoB::cmdCloseDoor(int, const char **) {
-	uint16 block = _vm->calcNewBlockPosition(_vm->_currentBlock, _vm->_currentDirection);
-	uint8 v = _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[0]] | _vm->_wllWallFlags[_vm->_levelBlockProperties[block].walls[1]];
-	if (!(v & 8)) {
-		debugPrintf("Couldn't close any door. Make sure you're facing the door you wish to close and standing right in front of it.\n\n");
-	} else if ((_vm->_flags.gameID == GI_EOB1 && !(v & 1)) || (_vm->_flags.gameID == GI_EOB2 && (v & 0x20))) {
-		debugPrintf("The door seems to be already closed.\n\n");
-	} else {
-		_vm->closeDoor(block);
-		debugPrintf("Trying to close door at block %d.\n\n", block);
-	}
-	return true;
-}
-
-bool Debugger_EoB::cmdListFlags(int, const char **) {
-	debugPrintf("Flag           Status\n----------------------\n\n");
-	for (int i = 0; i < 32; i++) {
-		uint32 flag = 1 << i;
-		debugPrintf("%.2d             %s\n", i, _vm->checkScriptFlags(flag) ? "TRUE" : "FALSE");
-	}
-	debugPrintf("\n");
-	return true;
-}
-
-bool Debugger_EoB::cmdSetFlag(int argc, const char **argv) {
-	if (argc != 2) {
-		debugPrintf("Syntax:   set_flag <flag>\n\n");
-		return true;
-	}
-
-	int flag = atoi(argv[1]);
-	if (flag < 0 || flag > 31) {
-		debugPrintf("<flag> must be a value from 0 to 31.\n\n");
-	} else {
-		_vm->setScriptFlags(1 << flag);
-		debugPrintf("Flag '%.2d' has been set.\n\n", flag);
-	}
-
-	return true;
-}
-
-bool Debugger_EoB::cmdClearFlag(int argc, const char **argv) {
-	if (argc != 2) {
-		debugPrintf("Syntax:   clear_flag <flag>\n\n");
-		return true;
-	}
-
-	int flag = atoi(argv[1]);
-	if (flag < 0 || flag > 31) {
-		debugPrintf("<flag> must be a value from 0 to 31.\n\n");
-	} else {
-		_vm->clearScriptFlags(1 << flag);
-		debugPrintf("Flag '%.2d' has been cleared.\n\n", flag);
-	}
-
-	return true;
-}
-
-#endif // ENABLE_EOB
-
-} // End of namespace Kyra
diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h
deleted file mode 100644
index 86df8ec..0000000
--- a/engines/kyra/debugger.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KYRA_DEBUGGER_H
-#define KYRA_DEBUGGER_H
-
-#include "gui/debugger.h"
-
-namespace Kyra {
-
-class KyraEngine_v1;
-class KyraEngine_LoK;
-class KyraEngine_v2;
-class KyraEngine_HoF;
-
-class Debugger : public ::GUI::Debugger {
-public:
-	Debugger(KyraEngine_v1 *vm);
-	virtual ~Debugger() {}  // we need this for __SYMBIAN32__ archaic gcc/UIQ
-
-	virtual void initialize();
-
-protected:
-	KyraEngine_v1 *_vm;
-
-	bool cmdSetScreenDebug(int argc, const char **argv);
-	bool cmdLoadPalette(int argc, const char **argv);
-	bool cmdShowFacings(int argc, const char **argv);
-	bool cmdGameSpeed(int argc, const char **argv);
-	bool cmdListFlags(int argc, const char **argv);
-	bool cmdToggleFlag(int argc, const char **argv);
-	bool cmdQueryFlag(int argc, const char **argv);
-	bool cmdListTimers(int argc, const char **argv);
-	bool cmdSetTimerCountdown(int argc, const char **argv);
-};
-
-class Debugger_LoK : public Debugger {
-public:
-	Debugger_LoK(KyraEngine_LoK *vm);
-	virtual ~Debugger_LoK() {}  // we need this for __SYMBIAN32__ archaic gcc/UIQ
-
-	virtual void initialize();
-protected:
-	KyraEngine_LoK *_vm;
-
-	bool cmdEnterRoom(int argc, const char **argv);
-	bool cmdListScenes(int argc, const char **argv);
-	bool cmdGiveItem(int argc, const char **argv);
-	bool cmdListBirthstones(int argc, const char **argv);
-};
-
-class Debugger_v2 : public Debugger {
-public:
-	Debugger_v2(KyraEngine_v2 *vm);
-	virtual ~Debugger_v2() {}
-
-	virtual void initialize();
-protected:
-	KyraEngine_v2 *_vm;
-
-	bool cmdEnterScene(int argc, const char **argv);
-	bool cmdListScenes(int argc, const char **argv);
-	bool cmdSceneInfo(int argc, const char **argv);
-	bool cmdCharacterInfo(int argc, const char **argv);
-	bool cmdSceneToFacing(int argc, const char **argv);
-	bool cmdGiveItem(int argc, const char **argv);
-};
-
-class Debugger_HoF : public Debugger_v2 {
-public:
-	Debugger_HoF(KyraEngine_HoF *vm);
-
-	virtual void initialize();
-protected:
-	KyraEngine_HoF *_vm;
-
-	bool cmdPasscodes(int argc, const char **argv);
-};
-
-#ifdef ENABLE_LOL
-class LoLEngine;
-
-class Debugger_LoL : public Debugger {
-public:
-	Debugger_LoL(LoLEngine *vm);
-
-protected:
-	LoLEngine *_vm;
-};
-#endif // ENABLE_LOL
-
-#ifdef ENABLE_EOB
-class EoBCoreEngine;
-
-class Debugger_EoB : public Debugger {
-public:
-	Debugger_EoB(EoBCoreEngine *vm);
-
-	virtual void initialize();
-protected:
-	EoBCoreEngine *_vm;
-
-	bool cmdImportSaveFile(int argc, const char **argv);
-	bool cmdSaveOriginal(int argc, const char **argv);
-	bool cmdListMonsters(int argc, const char **argv);
-	bool cmdShowPosition(int argc, const char **argv);
-	bool cmdSetPosition(int argc, const char **argv);
-	bool cmdPrintMap(int argc, const char **argv);
-	bool cmdOpenDoor(int argc, const char **argv);
-	bool cmdCloseDoor(int argc, const char **argv);
-	bool cmdListFlags(int argc, const char **argv);
-	bool cmdSetFlag(int argc, const char **argv);
-	bool cmdClearFlag(int argc, const char **argv);
-};
-#endif // ENABLE_EOB
-
-} // End of namespace Kyra
-
-#endif
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 0c345cc..a26c52a 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -20,12 +20,12 @@
  *
  */
 
-#include "kyra/kyra_lok.h"
-#include "kyra/lol.h"
-#include "kyra/kyra_hof.h"
-#include "kyra/kyra_mr.h"
-#include "kyra/eob.h"
-#include "kyra/darkmoon.h"
+#include "kyra/engine/kyra_lok.h"
+#include "kyra/engine/lol.h"
+#include "kyra/engine/kyra_hof.h"
+#include "kyra/engine/kyra_mr.h"
+#include "kyra/engine/eob.h"
+#include "kyra/engine/darkmoon.h"
 
 #include "common/config-manager.h"
 #include "common/system.h"
diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
new file mode 100644
index 0000000..c080acc
--- /dev/null
+++ b/engines/kyra/engine/chargen.cpp
@@ -0,0 +1,1982 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#include "kyra/engine/eobcommon.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/sound_intern.h"
+
+#include "common/savefile.h"
+#include "common/str-array.h"
+
+#include "common/config-manager.h"
+#include "base/plugins.h"
+#include "engines/metaengine.h"
+#include "engines/game.h"
+
+namespace Kyra {
+
+// Character Generator
+
+class CharacterGenerator {
+public:
+	CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen);
+	~CharacterGenerator();
+
+	bool start(EoBCharacter *characters, uint8 ***faceShapes);
+
+private:
+	void init();
+	void initButtonsFromList(int first, int numButtons);
+	void initButton(int index, int x, int y, int w, int h, int keyCode);
+	void checkForCompleteParty();
+	void toggleSpecialButton(int index, int bodyCustom, int pageNum);
+	void processSpecialButton(int index);
+	int viewDeleteCharacter();
+	void createPartyMember();
+	int raceSexMenu();
+	int classMenu(int raceSex);
+	int alignmentMenu(int cClass);
+	int getInput(Button *buttonList);
+	void updateMagicShapes();
+	void generateStats(int index);
+	void modifyMenu();
+	void statsAndFacesMenu();
+	void faceSelectMenu();
+	int getNextFreeFaceShape(int shpIndex, int charSex, int step, int8 *selectedPortraits);
+	void processFaceMenuSelection(int index);
+	void printStats(int index, int mode);
+	void processNameInput(int index, int textColor);
+	int rollDice();
+	int modifyStat(int index, int8 *stat1, int8 *stat2);
+	int getMaxHp(int cclass, int constitution, int level1, int level2, int level3);
+	int getMinHp(int cclass, int constitution, int level1, int level2, int level3);
+	void finish();
+
+	uint8 **_chargenMagicShapes;
+	uint8 *_chargenButtonLabels[17];
+	int _activeBox;
+	int _magicShapesBox;
+	int _updateBoxShapesIndex;
+	int _lastUpdateBoxShapesIndex;
+	uint32 _chargenMagicShapeTimer;
+	int8 _chargenSelectedPortraits[4];
+	int8 _chargenSelectedPortraits2[4];
+
+	uint16 _chargenMinStats[7];
+	uint16 _chargenMaxStats[7];
+
+	const char *const *_chargenStrings1;
+	const char *const *_chargenStrings2;
+	const char *const *_chargenStatStrings;
+	const char *const *_chargenRaceSexStrings;
+	const char *const *_chargenClassStrings;
+	const char *const *_chargenAlignmentStrings;
+	const char *const *_chargenEnterGameStrings;
+
+	const uint8 *_chargenStartLevels;
+	const uint8 *_chargenClassMinStats;
+	const uint8 *_chargenRaceMinStats;
+	const uint16 *_chargenRaceMaxStats;
+
+	const EoBChargenButtonDef *_chargenButtonDefs;
+
+	static const EoBChargenButtonDef _chargenButtonDefsDOS[];
+	static const uint16 _chargenButtonKeyCodesFMTOWNS[];
+	static const CreatePartyModButton _chargenModButtons[];
+	static const EoBRect8 _chargenButtonBodyCoords[];
+	static const int16 _chargenBoxX[];
+	static const int16 _chargenBoxY[];
+	static const int16 _chargenNameFieldX[];
+	static const int16 _chargenNameFieldY[];
+
+	static const int32 _classMenuMasks[];
+	static const int32 _alignmentMenuMasks[];
+
+	static const int16 _raceModifiers[];
+
+	EoBCharacter *_characters;
+	uint8 **_faceShapes;
+
+	EoBCoreEngine *_vm;
+	Screen_EoB *_screen;
+};
+
+CharacterGenerator::CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen),
+	_characters(0), _faceShapes(0), _chargenMagicShapes(0), _chargenMagicShapeTimer(0),
+	_updateBoxShapesIndex(0), _lastUpdateBoxShapesIndex(0), _magicShapesBox(6), _activeBox(0) {
+
+	_chargenStatStrings = _vm->_chargenStatStrings;
+	_chargenRaceSexStrings = _vm->_chargenRaceSexStrings;
+	_chargenClassStrings = _vm->_chargenClassStrings;
+	_chargenAlignmentStrings = _vm->_chargenAlignmentStrings;
+
+	memset(_chargenSelectedPortraits, -1, sizeof(_chargenSelectedPortraits));
+	memset(_chargenSelectedPortraits2, 0, sizeof(_chargenSelectedPortraits2));
+	memset(_chargenMinStats, 0, sizeof(_chargenMinStats));
+	memset(_chargenMaxStats, 0, sizeof(_chargenMaxStats));
+
+	int temp;
+	_chargenStrings1 = _vm->staticres()->loadStrings(kEoBBaseChargenStrings1, temp);
+	_chargenStrings2 = _vm->staticres()->loadStrings(kEoBBaseChargenStrings2, temp);
+	_chargenStartLevels = _vm->staticres()->loadRawData(kEoBBaseChargenStartLevels, temp);
+	_chargenEnterGameStrings = _vm->staticres()->loadStrings(kEoBBaseChargenEnterGameStrings, temp);
+	_chargenClassMinStats = _vm->staticres()->loadRawData(kEoBBaseChargenClassMinStats, temp);
+	_chargenRaceMinStats = _vm->staticres()->loadRawData(kEoBBaseChargenRaceMinStats, temp);
+	_chargenRaceMaxStats = _vm->staticres()->loadRawDataBe16(kEoBBaseChargenRaceMaxStats, temp);
+
+	EoBChargenButtonDef *chargenButtonDefs = new EoBChargenButtonDef[41];
+	memcpy(chargenButtonDefs, _chargenButtonDefsDOS, 41 * sizeof(EoBChargenButtonDef));
+
+	if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+		const uint16 *c = _chargenButtonKeyCodesFMTOWNS;
+		for (int i = 0; i < 41; ++i) {
+			if (chargenButtonDefs[i].keyCode)
+				chargenButtonDefs[i].keyCode = *c++;
+		}
+	}
+
+	_chargenButtonDefs = chargenButtonDefs;
+}
+
+CharacterGenerator::~CharacterGenerator() {
+	if (_chargenMagicShapes) {
+		for (int i = 0; i < 10; i++)
+			delete[] _chargenMagicShapes[i];
+		delete[] _chargenMagicShapes;
+	}
+
+	for (int i = 0; i < 17; i++)
+		delete[] _chargenButtonLabels[i];
+
+	delete[] _chargenButtonDefs;
+
+	_screen->clearPage(2);
+}
+
+bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
+	if (!characters || !faceShapes) {
+		warning("CharacterGenerator::start: Called without character data");
+		return true;
+	}
+
+	_characters = characters;
+	_faceShapes = *faceShapes;
+
+	_vm->snd_stopSound();
+	_vm->delay(_vm->_tickLength);
+
+	init();
+
+	_screen->setScreenDim(2);
+
+	checkForCompleteParty();
+	initButtonsFromList(0, 5);
+
+	_vm->snd_playSong(_vm->game() == GI_EOB1 ? 20 : 13);
+	_activeBox = 0;
+
+	for (bool loop = true; loop && (!_vm->shouldQuit());) {
+		_vm->_gui->updateBoxFrameHighLight(_activeBox + 6);
+		int inputFlag = getInput(_vm->_activeButtons);
+		_vm->removeInputTop();
+
+		if (inputFlag) {
+			if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
+				_activeBox ^= 1;
+			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
+				_activeBox ^= 2;
+			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
+				// Unlike the original we allow returning to the main menu
+				_vm->snd_stopSound();
+				return false;
+			}
+			_vm->_gui->updateBoxFrameHighLight(-1);
+		}
+
+		if (inputFlag & 0x8000) {
+			inputFlag = (inputFlag & 0x0F) - 1;
+			if (inputFlag == 4) {
+				loop = false;
+			} else {
+				_activeBox = inputFlag;
+				inputFlag = _vm->_keyMap[Common::KEYCODE_RETURN];
+			}
+		}
+
+		if (inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5]) {
+			_vm->_gui->updateBoxFrameHighLight(-1);
+			if (_characters[_activeBox].name[0]) {
+				int b = _activeBox;
+				if (viewDeleteCharacter())
+					loop = false;
+				if (b != _activeBox && !_characters[_activeBox].name[0])
+					createPartyMember();
+			} else {
+				createPartyMember();
+			}
+
+			initButtonsFromList(0, 5);
+			checkForCompleteParty();
+		}
+
+		if (loop == false) {
+			for (int i = 0; i < 4; i++) {
+				if (!_characters[i].name[0])
+					loop = true;
+			}
+		}
+	}
+
+	if (!_vm->shouldQuit()) {
+		processSpecialButton(15);
+		finish();
+	}
+
+	if (_vm->game() == GI_EOB2)
+		_vm->snd_fadeOut();
+
+	*faceShapes = _faceShapes;
+	return true;
+}
+
+void CharacterGenerator::init() {
+	/*_screen->loadEoBBitmap("MENU", 0, 3, 3, 2);
+	Common::SeekableReadStream *s = _res->createReadStream("facedat.dmp");
+	_screen->loadFileDataToPage(s, 2, 64000);*/
+
+	_screen->loadShapeSetBitmap("CHARGENA", 3, 3);
+	if (_faceShapes) {
+		for (int i = 0; i < 44; i++)
+			delete[] _faceShapes[i];
+		delete[] _faceShapes;
+	}
+
+	_faceShapes = new uint8*[44];
+	for (int i = 0; i < 44; i++)
+		_faceShapes[i] = _screen->encodeShape((i % 10) << 2, (i / 10) << 5, 4, 32, true, _vm->_cgaMappingDefault);
+	_screen->_curPage = 0;
+
+	_screen->loadEoBBitmap("CHARGEN", _vm->_cgaMappingDefault, 3, 3, 0);
+	_screen->loadShapeSetBitmap("CHARGENB", 3, 3);
+	if (_chargenMagicShapes) {
+		for (int i = 0; i < 10; i++)
+			delete[] _chargenMagicShapes[i];
+		delete[] _chargenMagicShapes;
+	}
+
+	_chargenMagicShapes = new uint8*[10];
+	for (int i = 0; i < 10; i++)
+		_chargenMagicShapes[i] = _screen->encodeShape(i << 2, 0, 4, 32, true, _vm->_cgaMappingDefault);
+
+	for (int i = 0; i < 17; i++) {
+		const CreatePartyModButton *c = &_chargenModButtons[i];
+		_chargenButtonLabels[i] = c->labelW ? _screen->encodeShape(c->encodeLabelX, c->encodeLabelY, c->labelW, c->labelH, true, _vm->_cgaMappingDefault) : 0;
+	}
+	
+	_screen->convertPage(3, 2, _vm->_cgaMappingDefault);
+	_screen->_curPage = 0;
+	_screen->convertToHiColor(2);
+	_screen->shadeRect(142, 63, 306, 193, 4);
+	_screen->copyRegion(144, 64, 0, 0, 180, 128, 0, 2, Screen::CR_NO_P_CHECK);
+	_screen->updateScreen();
+}
+
+void CharacterGenerator::initButtonsFromList(int first, int numButtons) {
+	_vm->gui_resetButtonList();
+
+	for (int i = 0; i < numButtons; i++) {
+		const EoBChargenButtonDef *e = &_chargenButtonDefs[first + i];
+		initButton(i, e->x, e->y, e->w, e->h, e->keyCode);
+	}
+
+	_vm->gui_notifyButtonListChanged();
+}
+
+void CharacterGenerator::initButton(int index, int x, int y, int w, int h, int keyCode) {
+	Button *b = 0;
+	int cnt = 1;
+
+	if (_vm->_activeButtons) {
+		Button *n = _vm->_activeButtons;
+		while (n->nextButton) {
+			++cnt;
+			n = n->nextButton;
+		}
+
+		++cnt;
+		b = n->nextButton = &_vm->_activeButtonData[cnt];
+	} else {
+		b = &_vm->_activeButtonData[0];
+		_vm->_activeButtons = b;
+	}
+
+	*b = Button();
+	b->flags = 0x1100;
+	b->data0Val2 = 12;
+	b->data1Val2 = b->data2Val2 = 15;
+	b->data3Val2 = 8;
+
+	b->index = index + 1;
+	b->x = x << 3;
+	b->y = y;
+	b->width = w;
+	b->height = h;
+	b->keyCode = keyCode;
+	b->keyCode2 = keyCode | 0x100;
+}
+
+void CharacterGenerator::checkForCompleteParty() {
+	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
+	int cp = _screen->setCurPage(2);
+	int x = (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168;
+	_screen->printShadedText(_chargenStrings1[8], x, 16, 15, 0);
+	_screen->setCurPage(cp);
+	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
+
+	int numChars = 0;
+	for (int i = 0; i < 4; i++) {
+		if (_characters[i].name[0])
+			numChars++;
+	}
+
+	if (numChars == 4) {
+		_screen->setCurPage(2);
+		_screen->printShadedText(_chargenStrings1[0], x, 61, 15, 0);
+		_screen->setCurPage(0);
+		_screen->copyRegion(168, 61, 152, 125, 136, 40, 2, 0, Screen::CR_NO_P_CHECK);
+		toggleSpecialButton(15, 0, 0);
+	} else {
+		toggleSpecialButton(14, 0, 0);
+	}
+
+	_screen->updateScreen();
+}
+
+void CharacterGenerator::toggleSpecialButton(int index, int bodyCustom, int pageNum) {
+	if (index >= 17)
+		return;
+
+	const CreatePartyModButton *c = &_chargenModButtons[index];
+	const EoBRect8 *p = &_chargenButtonBodyCoords[c->bodyIndex + bodyCustom];
+
+	int x2 = 20;
+	int y2 = 0;
+
+	if (pageNum) {
+		x2 = c->destX + 2;
+		y2 = c->destY - 64;
+	}
+
+	_screen->copyRegion(p->x << 3, p->y, x2 << 3, y2, p->w << 3, p->h, 2, 2, Screen::CR_NO_P_CHECK);
+	if (c->labelW)
+		_screen->drawShape(2, _chargenButtonLabels[index], (x2 << 3) + c->labelX, y2 + c->labelY, 0);
+
+	if (pageNum == 2)
+		return;
+
+	_screen->copyRegion(160, 0, c->destX << 3, c->destY, p->w << 3, p->h, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->updateScreen();
+}
+
+void CharacterGenerator::processSpecialButton(int index) {
+	toggleSpecialButton(index, 1, 0);
+	_vm->snd_playSoundEffect(76);
+	_vm->_system->delayMillis(80);
+	toggleSpecialButton(index, 0, 0);
+}
+
+int CharacterGenerator::viewDeleteCharacter() {
+	initButtonsFromList(0, 7);
+	_vm->removeInputTop();
+
+	_vm->_gui->updateBoxFrameHighLight(-1);
+	printStats(_activeBox, 2);
+
+	int res = 0;
+	for (bool loop = true; loop && _characters[_activeBox].name[0] && !_vm->shouldQuit();) {
+		_vm->_gui->updateBoxFrameHighLight(_activeBox + 6);
+		int inputFlag = getInput(_vm->_activeButtons);
+		int cbx = _activeBox;
+		_vm->removeInputTop();
+
+		if (inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
+			processSpecialButton(9);
+			res = 0;
+			loop = false;
+		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
+			cbx ^= 1;
+		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
+			cbx ^= 2;
+		}
+
+		if (inputFlag & 0x8000) {
+			inputFlag = (inputFlag & 0x0F) - 1;
+			if (inputFlag == 4) {
+				res = 1;
+				loop = false;
+			} else if (inputFlag == 5) {
+				processSpecialButton(9);
+				res = 0;
+				loop = false;
+			} else if (inputFlag == 6) {
+				if (_characters[_activeBox].name[0]) {
+					processSpecialButton(16);
+					_characters[_activeBox].name[0] = 0;
+					processNameInput(_activeBox, 12);
+					processFaceMenuSelection(_activeBox + 50);
+				}
+			} else {
+				cbx = inputFlag;
+			}
+		}
+
+		if (loop == false)
+			_vm->_gui->updateBoxFrameHighLight(-1);
+
+		if (!_characters[cbx].name[0])
+			loop = false;
+
+		if (cbx != _activeBox) {
+			_activeBox = cbx;
+			_vm->_gui->updateBoxFrameHighLight(-1);
+			if (loop)
+				printStats(_activeBox, 2);
+		}
+	}
+
+	return res;
+}
+
+void CharacterGenerator::createPartyMember() {
+	_screen->setScreenDim(2);
+	assert(_vm->_gui);
+
+	for (int i = 0; i != 3 && !_vm->shouldQuit(); i++) {
+		bool bck = false;
+
+		switch (i) {
+		case 0:
+			_characters[_activeBox].raceSex = raceSexMenu();
+			break;
+		case 1:
+			_characters[_activeBox].cClass = classMenu(_characters[_activeBox].raceSex);
+			if (_characters[_activeBox].cClass == _vm->_keyMap[Common::KEYCODE_ESCAPE])
+				bck = true;
+			break;
+		case 2:
+			_characters[_activeBox].alignment = alignmentMenu(_characters[_activeBox].cClass);
+			if (_characters[_activeBox].alignment == _vm->_keyMap[Common::KEYCODE_ESCAPE])
+				bck = true;
+			break;
+		default:
+			break;
+		}
+
+		if (bck)
+			i -= 2;
+	};
+
+	if (!_vm->shouldQuit()) {
+		generateStats(_activeBox);
+		statsAndFacesMenu();
+
+		for (_characters[_activeBox].name[0] = 0; _characters[_activeBox].name[0] == 0 && !_vm->shouldQuit();) {
+			processFaceMenuSelection(_chargenMinStats[6]);
+			printStats(_activeBox, 0);
+			_screen->printShadedText(_chargenStrings2[11], 149, 100, 9, 0);
+			if (!_vm->shouldQuit()) {
+				_vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, 15, 0, 8);
+				processNameInput(_activeBox, 2);
+			}
+		}
+	}
+}
+
+int CharacterGenerator::raceSexMenu() {
+	_screen->drawBox(_chargenBoxX[_activeBox], _chargenBoxY[_activeBox], _chargenBoxX[_activeBox] + 32, _chargenBoxY[_activeBox] + 33, 12);
+	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->printShadedText(_chargenStrings2[8], 147, 67, 9, 0);
+	_vm->removeInputTop();
+
+	_vm->_gui->simpleMenu_setup(1, 0, _chargenRaceSexStrings, -1, 0, 0);
+	int16 res = -1;
+
+	while (res == -1 && !_vm->shouldQuit()) {
+		res = _vm->_gui->simpleMenu_process(1, _chargenRaceSexStrings, 0, -1, 0);
+		updateMagicShapes();
+	}
+
+	return res;
+}
+
+int CharacterGenerator::classMenu(int raceSex) {
+	int32 itemsMask = -1;
+
+	for (int i = 0; i < 4; i++) {
+		// check for evil characters
+		if (_characters[i].name[0] && _characters[i].alignment > 5)
+			itemsMask = 0xFFFB;
+	}
+
+	_vm->removeInputTop();
+	updateMagicShapes();
+
+	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->printShadedText(_chargenStrings2[9], 147, 67, 9, 0);
+
+	toggleSpecialButton(5, 0, 0);
+
+	itemsMask &= _classMenuMasks[raceSex / 2];
+	_vm->_gui->simpleMenu_setup(2, 15, _chargenClassStrings, itemsMask, 0, 0);
+
+	_vm->_mouseX = _vm->_mouseY = 0;
+	int16 res = -1;
+
+	while (res == -1 && !_vm->shouldQuit()) {
+		updateMagicShapes();
+		int in = getInput(0) & 0xFF;
+		Common::Point mp = _vm->getMousePos();
+
+		if (in == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_b]) {
+			res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
+		} else if (_vm->posWithinRect(mp.x, mp.y, 264, 171, 303, 187)) {
+			if (in == 199 || in == 201)
+				res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
+			else
+				_vm->removeInputTop();
+		} else {
+			res = _vm->_gui->simpleMenu_process(2, _chargenClassStrings, 0, itemsMask, 0);
+		}
+	}
+
+	_vm->removeInputTop();
+
+	if (res == _vm->_keyMap[Common::KEYCODE_ESCAPE])
+		processSpecialButton(5);
+
+	return res;
+}
+
+int CharacterGenerator::alignmentMenu(int cClass) {
+	int32 itemsMask = -1;
+
+	for (int i = 0; i < 4; i++) {
+		// check for paladins
+		if (_characters[i].name[0] && _characters[i].cClass == 2)
+			itemsMask = 0xFE3F;
+	}
+
+	_vm->removeInputTop();
+	updateMagicShapes();
+
+	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->printShadedText(_chargenStrings2[10], 147, 67, 9, 0);
+
+	toggleSpecialButton(5, 0, 0);
+
+	itemsMask &= _alignmentMenuMasks[cClass];
+	_vm->_gui->simpleMenu_setup(3, 9, _chargenAlignmentStrings, itemsMask, 0, 0);
+
+	_vm->_mouseX = _vm->_mouseY = 0;
+	int16 res = -1;
+
+	while (res == -1 && !_vm->shouldQuit()) {
+		updateMagicShapes();
+		int in = getInput(0) & 0xFF;
+		Common::Point mp = _vm->getMousePos();
+
+		if (in == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_ESCAPE] || _vm->_gui->_menuLastInFlags == _vm->_keyMap[Common::KEYCODE_b]) {
+			res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
+		} else if (_vm->posWithinRect(mp.x, mp.y, 264, 171, 303, 187)) {
+			if (in == 199 || in == 201)
+				res = _vm->_keyMap[Common::KEYCODE_ESCAPE];
+			else
+				_vm->removeInputTop();
+		} else {
+			res = _vm->_gui->simpleMenu_process(3, _chargenAlignmentStrings, 0, itemsMask, 0);
+		}
+	}
+
+	_vm->removeInputTop();
+
+	if (res == _vm->_keyMap[Common::KEYCODE_ESCAPE])
+		processSpecialButton(5);
+
+	return res;
+}
+
+int CharacterGenerator::getInput(Button *buttonList) {
+	if (_vm->game() == GI_EOB1 && _vm->sound()->checkTrigger()) {
+		_vm->sound()->resetTrigger();
+		_vm->snd_playSong(20);
+	} else if (_vm->game() == GI_EOB2 && !_vm->sound()->isPlaying()) {
+		// WORKAROUND for EOB II: The original implements the same sound trigger check as in EOB I.
+		// However, Westwood seems to have forgotten to set the trigger at the end of the AdLib song,
+		// so that the music will not loop. We simply check whether the sound driver is still playing.
+		_vm->delay(3 * _vm->_tickLength);
+		_vm->snd_playSong(13);
+	}
+	return _vm->checkInput(buttonList, false, 0);
+}
+
+void CharacterGenerator::updateMagicShapes() {
+	if (_magicShapesBox != _activeBox) {
+		_chargenMagicShapeTimer = 0;
+		_magicShapesBox = _activeBox;
+	}
+
+	if (_chargenMagicShapeTimer < _vm->_system->getMillis()) {
+		if (++_updateBoxShapesIndex > 9)
+			_updateBoxShapesIndex = 0;
+		_chargenMagicShapeTimer = _vm->_system->getMillis() + 2 * _vm->_tickLength;
+	}
+
+	if (_updateBoxShapesIndex == _lastUpdateBoxShapesIndex)
+		return;
+
+	_screen->copyRegion(_activeBox << 5, 128, 288, 128, 32, 32, 2, 2, Screen::CR_NO_P_CHECK);
+	_screen->drawShape(2, _chargenMagicShapes[_updateBoxShapesIndex], 288, 128, 0);
+	_screen->copyRegion(288, 128, _chargenBoxX[_activeBox], _chargenBoxY[_activeBox] + 1, 32, 32, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->updateScreen();
+
+	_lastUpdateBoxShapesIndex = _updateBoxShapesIndex;
+}
+
+void CharacterGenerator::generateStats(int index) {
+	EoBCharacter *c = &_characters[index];
+
+	for (int i = 0; i < 3; i++) {
+		c->level[i] = _chargenStartLevels[(c->cClass << 2) + i];
+		c->experience[i] = (_vm->game() == GI_EOB2 ? 69000 : 5000) / _chargenStartLevels[(c->cClass << 2) + 3];
+	}
+
+	int rc = c->raceSex >> 1;
+	for (int i = 0; i < 6; i++) {
+		_chargenMinStats[i] = MAX(_chargenClassMinStats[c->cClass * 6 + i], _chargenRaceMinStats[rc * 6 + i]);
+		_chargenMaxStats[i] = _chargenRaceMaxStats[rc * 6 + i];
+	}
+
+	if (_vm->_charClassModifier[c->cClass])
+		_chargenMaxStats[0] = 18;
+
+	uint16 sv[6];
+	for (int i = 0; i < 6; i++) {
+		sv[i] = MAX<uint16>(rollDice() + _raceModifiers[rc * 6 + i], _chargenMinStats[i]);
+		if (!i && sv[i] == 18)
+			sv[i] |= (uint16)(_vm->rollDice(1, 100) << 8);
+		if (sv[i] > _chargenMaxStats[i])
+			sv[i] = _chargenMaxStats[i];
+	}
+
+	c->strengthCur = c->strengthMax = sv[0] & 0xFF;
+	c->strengthExtCur = c->strengthExtMax = sv[0] >> 8;
+	c->intelligenceCur = c->intelligenceMax = sv[1] & 0xFF;
+	c->wisdomCur = c->wisdomMax = sv[2] & 0xFF;
+	c->dexterityCur = c->dexterityMax = sv[3] & 0xFF;
+	c->constitutionCur = c->constitutionMax = sv[4] & 0xFF;
+	c->charismaCur = c->charismaMax = sv[5] & 0xFF;
+	c->armorClass = 10 + _vm->getDexterityArmorClassModifier(sv[3] & 0xFF);
+	c->hitPointsCur = 0;
+
+	for (int l = 0; l < 3; l++) {
+		for (int i = 0; i < c->level[l]; i++)
+			c->hitPointsCur += _vm->generateCharacterHitpointsByLevel(index, 1 << l);
+	}
+
+	c->hitPointsMax = c->hitPointsCur;
+}
+
+void CharacterGenerator::modifyMenu() {
+	_vm->removeInputTop();
+	printStats(_activeBox, 3);
+
+	EoBCharacter *c = &_characters[_activeBox];
+	int8 hpLO = c->hitPointsCur;
+
+	for (int i = 0; i >= 0 && i < 7;) {
+		switch (i) {
+		case 0:
+			i = modifyStat(i, &c->strengthCur, &c->strengthExtCur);
+			break;
+		case 1:
+			i = modifyStat(i, &c->intelligenceCur, 0);
+			break;
+		case 2:
+			i = modifyStat(i, &c->wisdomCur, 0);
+			break;
+		case 3:
+			i = modifyStat(i, &c->dexterityCur, 0);
+			break;
+		case 4:
+			i = modifyStat(i, &c->constitutionCur, 0);
+			break;
+		case 5:
+			i = modifyStat(i, &c->charismaCur, 0);
+			break;
+		case 6:
+			hpLO = c->hitPointsCur;
+			i = modifyStat(i, &hpLO, 0);
+			c->hitPointsCur = hpLO;
+			break;
+		default:
+			break;
+		}
+
+		if (i == -2 || _vm->shouldQuit())
+			break;
+		else if (i < 0)
+			i = 6;
+		i %= 7;
+
+		printStats(_activeBox, 3);
+	}
+
+	printStats(_activeBox, 1);
+}
+
+void CharacterGenerator::statsAndFacesMenu() {
+	faceSelectMenu();
+	printStats(_activeBox, 1);
+	initButtonsFromList(27, 4);
+	_vm->removeInputTop();
+	int in = 0;
+
+	while (!in && !_vm->shouldQuit()) {
+		updateMagicShapes();
+		in = getInput(_vm->_activeButtons);
+		_vm->removeInputTop();
+
+		if (in == 0x8001) {
+			processSpecialButton(4);
+			updateMagicShapes();
+			generateStats(_activeBox);
+			in = -1;
+		} else if (in == 0x8002) {
+			processSpecialButton(7);
+			modifyMenu();
+			in = -1;
+		} else if (in == 0x8003) {
+			processSpecialButton(8);
+			faceSelectMenu();
+			in = -1;
+		} else if (in == 0x8004 || in == _vm->_keyMap[Common::KEYCODE_KP5]) {
+			processSpecialButton(6);
+			in = 1;
+		} else {
+			in = 0;
+		}
+
+		if (in & 0x8000) {
+			printStats(_activeBox, 1);
+			initButtonsFromList(27, 4);
+			in = 0;
+		}
+	}
+
+	_vm->_gui->updateBoxFrameHighLight(6 + _activeBox);
+	_vm->_gui->updateBoxFrameHighLight(-1);
+}
+
+void CharacterGenerator::faceSelectMenu() {
+	int8 sp[4];
+	memcpy(sp, _chargenSelectedPortraits2, sizeof(sp));
+	_vm->removeInputTop();
+	initButtonsFromList(21, 6);
+
+	int charSex = _characters[_activeBox].raceSex % 2;
+	int8 shp = charSex ? 26 : 0;
+
+	printStats(_activeBox, 4);
+	toggleSpecialButton(12, 0, 0);
+	toggleSpecialButton(13, 0, 0);
+	_vm->_gui->updateBoxFrameHighLight(-1);
+
+	shp = getNextFreeFaceShape(shp, charSex, 1, _chargenSelectedPortraits);
+
+	int res = -1;
+	int box = 1;
+
+	while (res == -1 && !_vm->shouldQuit()) {
+		int8 shpOld = shp;
+
+		for (int i = 0; i < 4; i++) {
+			sp[i] = shp;
+			_screen->drawShape(0, _faceShapes[sp[i]], 176 + (i << 5), 66, 0);
+			shp = getNextFreeFaceShape(shp + 1, charSex, 1, _chargenSelectedPortraits);
+		}
+
+		shp = shpOld;
+		int in = 0;
+
+		while (!in && !_vm->shouldQuit()) {
+			updateMagicShapes();
+			in = getInput(_vm->_activeButtons);
+			_vm->removeInputTop();
+
+			_vm->_gui->updateBoxFrameHighLight(box + 10);
+
+			if (in == 0x8002 || in == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
+				processSpecialButton(13);
+				in = 2;
+			} else if (in > 0x8002 && in < 0x8007) {
+				box = (in & 7) - 3;
+				in = 3;
+			} else if (in == 0x8001 || in == _vm->_keyMap[Common::KEYCODE_LEFT]) {
+				processSpecialButton(12);
+				in = 1;
+			} else if (in == _vm->_keyMap[Common::KEYCODE_RETURN] || in == _vm->_keyMap[Common::KEYCODE_KP5]) {
+				in = 3;
+			} else if (in & 0x8000) {
+				in &= 0xFF;
+			} else {
+				in = 0;
+			}
+		}
+
+		_vm->_gui->updateBoxFrameHighLight(-1);
+
+		if (in == 1)
+			shp = getNextFreeFaceShape(shp - 1, charSex, -1, _chargenSelectedPortraits);
+		else if (in == 2)
+			shp = getNextFreeFaceShape(shp + 1, charSex, 1, _chargenSelectedPortraits);
+		else if (in == 3)
+			res = box;
+	}
+
+	if (!_vm->shouldQuit()) {
+		_vm->_gui->updateBoxFrameHighLight(-1);
+		updateMagicShapes();
+
+		_chargenSelectedPortraits[_activeBox] = sp[res];
+		_characters[_activeBox].portrait = sp[res];
+		_characters[_activeBox].faceShape = _faceShapes[sp[res]];
+
+		printStats(_activeBox, 1);
+	}
+}
+
+int CharacterGenerator::getNextFreeFaceShape(int shpIndex, int charSex, int step, int8 *selectedPortraits) {
+	int shpCur = ((shpIndex < 0) ? 43 : shpIndex) % 44;
+	bool notUsable = false;
+
+	do {
+		notUsable = false;
+		for (int i = 0; i < 4; i++) {
+			if (_characters[i].name[0] && selectedPortraits[i] == shpCur)
+				notUsable = true;
+		}
+
+		if ((charSex && (shpCur < 26)) || (!charSex && (shpCur > 28)))
+			notUsable = true;
+
+		if (notUsable) {
+			shpCur += step;
+			shpCur = ((shpCur < 0) ? 43 : shpCur) % 44;
+		}
+	} while (notUsable);
+
+	return shpCur;
+}
+
+void CharacterGenerator::processFaceMenuSelection(int index) {
+	_vm->_gui->updateBoxFrameHighLight(-1);
+	if (index <= 48)
+		_screen->drawShape(0, _characters[_activeBox].faceShape, _chargenBoxX[_activeBox], _chargenBoxY[_activeBox] + 1, 0);
+	else
+		toggleSpecialButton(index - 50, 0, 0);
+}
+
+void CharacterGenerator::printStats(int index, int mode) {
+	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
+	_screen->_curPage = 2;
+
+	EoBCharacter *c = &_characters[index];
+
+	if (mode != 4)
+		_screen->drawShape(2, c->faceShape, 224, 2, 0);
+
+	_screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, 15, 0);
+	_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, 15, 0);
+	_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, 15, 0);
+
+	for (int i = 0; i < 6; i++)
+		_screen->printShadedText(_chargenStatStrings[i], 163, (i + 8) << 3, 15, 0);
+
+	_screen->printShadedText(_chargenStrings1[2], 248, 64, 15, 0);
+
+	Common::String str = Common::String::format(_chargenStrings1[3], _vm->getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), c->intelligenceCur, c->wisdomCur, c->dexterityCur, c->constitutionCur, c->charismaCur);
+	_screen->printShadedText(str.c_str(), 192, 64, 15, 0);
+
+	str = Common::String::format(_chargenStrings1[4], c->armorClass, c->hitPointsMax);
+	_screen->printShadedText(str.c_str(), 280, 64, 15, 0);
+
+	const char *lvlStr = c->level[2] ? _chargenStrings1[7] : (c->level[1] ? _chargenStrings1[6] : _chargenStrings1[5]);
+	str = Common::String::format(lvlStr, c->level[0], c->level[1], c->level[2]);
+	_screen->printShadedText(str.c_str(), 280, 80, 15, 0);
+
+	switch (mode) {
+	case 1:
+		toggleSpecialButton(4, 0, 2);
+		toggleSpecialButton(7, 0, 2);
+		toggleSpecialButton(8, 0, 2);
+		toggleSpecialButton(6, 0, 2);
+		break;
+
+	case 2:
+		toggleSpecialButton(16, 0, 2);
+		toggleSpecialButton(9, 0, 2);
+		break;
+
+	case 3:
+		toggleSpecialButton(10, 0, 2);
+		toggleSpecialButton(11, 0, 2);
+		toggleSpecialButton(9, 0, 2);
+		break;
+
+	default:
+		break;
+	}
+
+	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
+
+	if (mode != 3)
+		_screen->updateScreen();
+
+	_screen->_curPage = 0;
+}
+
+void CharacterGenerator::processNameInput(int index, int textColor) {
+	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
+	_screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, 12);
+	int xOffs = (60 - _screen->getTextWidth(_characters[index].name)) >> 1;
+	_screen->printText(_characters[index].name, _chargenNameFieldX[index] + xOffs, _chargenNameFieldY[index], textColor, 0);
+	_screen->updateScreen();
+	_screen->setFont(of);
+}
+
+int CharacterGenerator::rollDice() {
+	int res = 0;
+	int min = 10;
+
+	for (int i = 0; i < 4; i++) {
+		int d = _vm->rollDice(1, 6, 0);
+		res += d;
+		if (d < min)
+			min = d;
+	}
+
+	res -= min;
+	return res;
+}
+
+int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
+	uint8 *s1 = (uint8 *)stat1;
+	uint8 *s2 = (uint8 *)stat2;
+
+	initButtonsFromList(31, 10);
+	Button *b = _vm->gui_getButton(_vm->_activeButtons, index + 1);
+
+	printStats(_activeBox, 3);
+	_vm->removeInputTop();
+
+	Common::String statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
+
+	_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, 6, 0);
+	_screen->updateScreen();
+
+	EoBCharacter *c = &_characters[_activeBox];
+
+	int ci = index;
+	uint8 v2 = s2 ? *s2 : 0;
+
+	if (index == 6) {
+		_chargenMaxStats[6] = getMaxHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
+		_chargenMinStats[6] = getMinHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
+	}
+
+	for (bool loop = true; loop && !_vm->shouldQuit();) {
+		uint8 v1 = *s1;
+		updateMagicShapes();
+		int inputFlag = getInput(_vm->_activeButtons);
+		_vm->removeInputTop();
+
+		if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_MINUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP_MINUS] || inputFlag == 0x8009) {
+			processSpecialButton(11);
+			v1--;
+
+		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_PLUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP_PLUS] || inputFlag == 0x8008) {
+			processSpecialButton(10);
+			v1++;
+
+		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP8]) {
+			ci = (ci - 1) % 7;
+			loop = false;
+
+		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP2]) {
+			ci = (ci + 1) % 7;
+			loop = false;
+
+		} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_o] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE] || inputFlag == 0x800A) {
+			processSpecialButton(9);
+			loop = false;
+			ci = -2;
+
+		} else if (inputFlag & 0x8000) {
+			inputFlag = (inputFlag & 0x0F) - 1;
+			if (index != inputFlag) {
+				ci = inputFlag;
+				loop = false;
+			}
+		}
+
+		if (v1 == *s1)
+			continue;
+
+		if (!index) {
+			while (v1 > 18) {
+				v1--;
+				v2++;
+			}
+			while (v2 > 0 && v1 < 18) {
+				v1++;
+				v2--;
+			}
+
+			v1 = CLIP<uint8>(v1, _chargenMinStats[index], _chargenMaxStats[index] & 0xFF);
+			v2 = (v1 == 18 && _chargenMaxStats[index] >= 19) ? CLIP<uint8>(v2, 0, 100) : 0;
+			if (s2)
+				*s2 = v2;
+			else
+				error("CharacterGenerator::modifyStat:...");
+		} else {
+			v1 = CLIP<uint8>(v1, _chargenMinStats[index], _chargenMaxStats[index]);
+		}
+
+		*s1 = v1;
+
+		if (index == 6)
+			_characters[_activeBox].hitPointsMax = v1;
+
+		statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
+
+		_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, 6, 0);
+		_screen->updateScreen();
+
+		if (index == 4) {
+			int oldVal = c->hitPointsCur;
+			_chargenMaxStats[6] = getMaxHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
+			_chargenMinStats[6] = getMinHp(c->cClass, c->constitutionCur, c->level[0], c->level[1], c->level[2]);
+			c->hitPointsMax = c->hitPointsCur = CLIP<int16>(c->hitPointsCur, _chargenMinStats[6], _chargenMaxStats[6]);
+
+			if (c->hitPointsCur != oldVal) {
+				statStr = Common::String::format("%d", c->hitPointsCur);
+				_screen->copyRegion(120, 72, 264, 136, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
+				_screen->printShadedText(statStr.c_str(), 264, 136, 15, 0);
+				_screen->updateScreen();
+			}
+
+		} else if (index == 3) {
+			int oldVal = c->armorClass;
+			c->armorClass = _vm->getDexterityArmorClassModifier(v1) + 10;
+
+			if (c->armorClass != oldVal) {
+				statStr = Common::String::format("%d", c->armorClass);
+				_screen->copyRegion(120, 64, 264, 128, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
+				_screen->printShadedText(statStr.c_str(), 264, 128, 15, 0);
+				_screen->updateScreen();
+			}
+		}
+
+		if (loop == false) {
+			statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
+			_screen->printText(statStr.c_str(), b->x + 32, b->y, 15, 0);
+			_screen->updateScreen();
+		}
+	}
+
+	return ci;
+}
+
+int CharacterGenerator::getMaxHp(int cclass, int constitution, int level1, int level2, int level3) {
+	int res = 0;
+	constitution = _vm->getClassAndConstHitpointsModifier(cclass, constitution);
+
+	int m = _vm->getCharacterClassType(cclass, 0);
+	if (m != -1)
+		res = _vm->getModifiedHpLimits(m, constitution, level1, false);
+
+	m = _vm->getCharacterClassType(cclass, 1);
+	if (m != -1)
+		res += _vm->getModifiedHpLimits(m, constitution, level2, false);
+
+	m = _vm->getCharacterClassType(cclass, 2);
+	if (m != -1)
+		res += _vm->getModifiedHpLimits(m, constitution, level3, false);
+
+	res /= _vm->_numLevelsPerClass[cclass];
+
+	return res;
+}
+
+int CharacterGenerator::getMinHp(int cclass, int constitution, int level1, int level2, int level3) {
+	int res = 0;
+	constitution = _vm->getClassAndConstHitpointsModifier(cclass, constitution);
+
+	int m = _vm->getCharacterClassType(cclass, 0);
+	if (m != -1)
+		res = _vm->getModifiedHpLimits(m, constitution, level1, true);
+
+	m = _vm->getCharacterClassType(cclass, 1);
+	if (m != -1)
+		res += _vm->getModifiedHpLimits(m, constitution, level2, true);
+
+	m = _vm->getCharacterClassType(cclass, 2);
+	if (m != -1)
+		res += _vm->getModifiedHpLimits(m, constitution, level3, true);
+
+	res /= _vm->_numLevelsPerClass[cclass];
+
+	return res;
+}
+
+void CharacterGenerator::finish() {
+	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
+	int cp = _screen->setCurPage(2);
+	_screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, 15, 0);
+	_screen->setCurPage(cp);
+	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->updateScreen();
+
+	if (_vm->game() == GI_EOB1) {
+		static const int8 classDefaultItemsList[] = {
+			 1, 17,  2, 17, 46, -1,  4, -1,  5, -1,  6,
+			 2,  7, -1,  8, -1,  9, 21, 10,  2, 31,  2
+		};
+
+		static const int8 classDefaultItemsListIndex[] = {
+			 4,  8,  0, -1,  4,  3,  0, -1,  4, 10,
+			 0,  8,  3,  6,  1, -1,  2,  7,  0, -1,
+			 4,  5,  0, -1,  4,  7,  0,  8,  4,  5,
+			 0,  8,  4,  6,  8,  8,  4,  6,  5,  8,
+			 3,  6,  5, -1,  2,  7,  5,  0,  4,  6,
+			 7,  0,  4,  3,  7,  0,  2,  6,  7,  1
+		};
+
+		_characters[0].inventory[2] = _vm->duplicateItem(35);
+
+		for (int i = 0; i < 4; i++) {
+			EoBCharacter *c = &_characters[i];
+			c->flags = 1;
+			c->food = 100;
+			c->id = i;
+			c->inventory[3] = _vm->duplicateItem(10);
+
+			for (int ii = 0; ii < 4; ii++) {
+				int l = classDefaultItemsListIndex[(c->cClass << 2) + ii] << 1;
+				if (classDefaultItemsList[l] == -1)
+					continue;
+
+				int d = classDefaultItemsList[l];
+				int slot = classDefaultItemsList[l + 1];
+
+				if (slot < 0) {
+					slot = 0;
+					if (c->inventory[slot])
+						slot++;
+					if (c->inventory[slot])
+						slot++;
+				}
+
+				if (slot != 2 && c->inventory[slot])
+					continue;
+
+				if (d == 5 && (c->raceSex >> 1) == 3)
+					d = 36;
+
+				if (slot == 2) {
+					while (c->inventory[slot])
+						slot++;
+				}
+
+				c->inventory[slot] = _vm->duplicateItem(d);
+			}
+
+			_vm->recalcArmorClass(i);
+		}
+
+	} else {
+		static const uint8 classDefaultItemsListIndex[] = { 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 3, 2, 0, 0, 2 };
+		static const int8 itemList0[] = { 3, 36, 0, 17, -1, 0, 0, 56, 1, 17, 31, 0, 1, 23, 1, 17, 31, 1, 1 };
+		static const int8 itemList1[] = { 1, 2, 0, 17, -1, 0, 0 };
+		static const int8 itemList2[] = { 2, 56, 1, 17, 31, 0, 1, 23, 1, 17, 31, 0, 1 };
+		static const int8 itemList3[] = { 2, 1, 1, 17, 31, 1, 1, 1, 0, 17, 31, 2, 1 };
+		static const int8 *const itemList[] = { itemList0, itemList1, itemList2, itemList3 };
+
+		for (int i = 0; i < 4; i++) {
+			EoBCharacter *c = &_characters[i];
+			c->flags = 1;
+			c->food = 100;
+			c->id = i;
+			const int8 *df = itemList[classDefaultItemsListIndex[c->cClass]];
+			int v1 = _vm->rollDice(1, *df++, -1);
+
+			df = &df[v1 * 6];
+			for (int ii = 0; ii < 2; ii++) {
+				if (df[0] == -1)
+					break;
+				_vm->createInventoryItem(c, df[0], df[1], df[2]);
+				df = &df[3];
+			}
+
+			uint16 m = _vm->_classModifierFlags[c->cClass];
+			v1 = _vm->rollDice(1, 2, -1);
+
+			int ival = 0;
+			int itype = 0;
+
+			if (m & 0x31) {
+				if ((c->raceSex >> 1) == 3) {
+					itype = 22;
+					ival = 1;
+				} else {
+					if (v1 == 0) {
+						itype = 5;
+						ival = 1;
+					} else {
+						itype = 34;
+					}
+				}
+			} else if (m & 0x04) {
+				itype = 26;
+				if (v1 != 0)
+					ival = 1;
+			} else if (m & 0x08) {
+				ival = 1;
+				itype = ((c->raceSex >> 1) == 3) ? 22 : 5;
+			} else {
+				if (v1 == 0) {
+					itype = 3;
+				} else {
+					itype = 4;
+					ival = 1;
+				}
+			}
+
+			_vm->createInventoryItem(c, itype, ival, 0);
+			_vm->createInventoryItem(c, 10, -1, 2);
+			_vm->createInventoryItem(c, 10, -1, 2);
+			_vm->createInventoryItem(c, 24, 2, 2);
+
+			if (_vm->_classModifierFlags[c->cClass] & 2) {
+				_vm->createInventoryItem(c, 7, -1, 1);
+				_vm->createInventoryItem(c, 21, 4, 2);
+				_vm->createInventoryItem(c, 21, 13, 2);
+			}
+
+			if (_vm->_classModifierFlags[c->cClass] & 0x14) {
+				if (c->cClass == 2)
+					_vm->createInventoryItem(c, 27, -1, 1);
+				else
+					_vm->createInventoryItem(c, 8, -1, 1);
+
+				_vm->createInventoryItem(c, 20, 49, 1);
+			}
+
+			if (_vm->_classModifierFlags[c->cClass] & 8)
+				_vm->createInventoryItem(c, 6, -1, 1);
+
+			if (i == 0)
+				_vm->createInventoryItem(c, 93, -1, 2);
+
+			_vm->recalcArmorClass(i);
+		}
+	}
+
+	for (int i = 0; i < 4; i++) {
+		if (_vm->_classModifierFlags[_characters[i].cClass] & 2)
+			_characters[i].mageSpellsAvailableFlags = (_vm->game() == GI_EOB2) ? 0x81CB6 : 0x26C;
+
+		if (_vm->_classModifierFlags[_characters[i].cClass] & 0x14 && _vm->game() == GI_EOB2) {
+			// Cleric/Paladin: Add Turn Undead spell
+			_characters[i].clericSpells[0] = 29;
+		}
+	}
+
+	for (int i = 0; i < 4; i++) {
+		EoBCharacter *c = &_characters[i];
+		c->strengthMax = c->strengthCur;
+		c->strengthExtMax = c->strengthExtCur;
+		c->intelligenceMax = c->intelligenceCur;
+		c->wisdomMax = c->wisdomCur;
+		c->dexterityMax = c->dexterityCur;
+		c->constitutionMax = c->constitutionCur;
+		c->charismaMax = c->charismaCur;
+		c->hitPointsMax = c->hitPointsCur;
+	}
+
+	_vm->gui_resetButtonList();
+
+	if (_faceShapes) {
+		for (int i = 0; i < 44; i++) {
+			bool del = true;
+			for (int ii = 0; ii < 4; ii++) {
+				if (_characters[ii].faceShape == _faceShapes[i])
+					del = false;
+			}
+			if (del)
+				delete[] _faceShapes[i];
+		}
+		delete[] _faceShapes;
+		_faceShapes = 0;
+	}
+
+	if (_chargenMagicShapes) {
+		for (int i = 0; i < 10; i++)
+			delete[] _chargenMagicShapes[i];
+		delete[] _chargenMagicShapes;
+		_chargenMagicShapes = 0;
+	}
+
+	for (int i = 0; i < 17; i++) {
+		delete[] _chargenButtonLabels[i];
+		_chargenButtonLabels[i] = 0;
+	}
+}
+
+const EoBChargenButtonDef CharacterGenerator::_chargenButtonDefsDOS[] = {
+	{ 0x01, 0x37, 0x31, 0x32, 0x70 },
+	{ 0x09, 0x37, 0x31, 0x32, 0x71 },
+	{ 0x01, 0x77, 0x31, 0x32, 0x72 },
+	{ 0x09, 0x77, 0x31, 0x32, 0x73 },
+	{ 0x03, 0xB5, 0x53, 0x10, 0x1A },
+	{ 0x21, 0xAC, 0x26, 0x10, 0x19 },
+	{ 0x1C, 0xAC, 0x26, 0x10, 0x21 },
+	{ 0x21, 0xAC, 0x26, 0x10, 0x32 },
+	{ 0x13, 0x50, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x58, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x60, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x68, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x70, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x78, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x80, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x88, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x90, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0x98, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0xA0, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0xA8, 0x9A, 0x08, 0x00 },
+	{ 0x13, 0xB0, 0x9A, 0x08, 0x00 },
+	{ 0x12, 0x42, 0x20, 0x10, 0x00 },
+	{ 0x12, 0x52, 0x20, 0x10, 0x00 },
+	{ 0x16, 0x42, 0x20, 0x20, 0x00 },
+	{ 0x1A, 0x42, 0x20, 0x20, 0x00 },
+	{ 0x1E, 0x42, 0x20, 0x20, 0x00 },
+	{ 0x22, 0x42, 0x20, 0x20, 0x00 },
+	{ 0x1C, 0x9C, 0x26, 0x10, 0x14 },
+	{ 0x21, 0x9C, 0x26, 0x10, 0x34 },
+	{ 0x1C, 0xAC, 0x26, 0x10, 0x22 },
+	{ 0x21, 0xAC, 0x26, 0x10, 0x26 },
+	{ 0x12, 0x80, 0x35, 0x08, 0x00 },
+	{ 0x12, 0x88, 0x35, 0x08, 0x00 },
+	{ 0x12, 0x90, 0x35, 0x08, 0x00 },
+	{ 0x12, 0x98, 0x35, 0x08, 0x00 },
+	{ 0x12, 0xA0, 0x35, 0x08, 0x00 },
+	{ 0x12, 0xA8, 0x35, 0x08, 0x00 },
+	{ 0x1D, 0x88, 0x35, 0x08, 0x00 },
+	{ 0x1B, 0xAC, 0x15, 0x10, 0x0D },
+	{ 0x1E, 0xAC, 0x15, 0x10, 0x0C },
+	{ 0x21, 0xAC, 0x25, 0x10, 0x19 }
+};
+
+const uint16 CharacterGenerator::_chargenButtonKeyCodesFMTOWNS[] = {
+	93, 94, 95, 96, 80, 79, 68, 66, 82, 77, 70, 75, 43, 45, 79
+};
+
+const CreatePartyModButton CharacterGenerator::_chargenModButtons[] = {
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40 },
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x40 },
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x80 },
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0A, 0x80 },
+	{ 0x00, 0xC0, 0x04, 0x05, 0x07, 0x05, 0x08, 0x1C, 0x9C },
+	{ 0x04, 0xC0, 0x03, 0x05, 0x0A, 0x05, 0x08, 0x21, 0xAC },
+	{ 0x07, 0xC0, 0x03, 0x05, 0x0B, 0x05, 0x08, 0x21, 0xAC },
+	{ 0x0A, 0xC0, 0x04, 0x05, 0x06, 0x05, 0x08, 0x21, 0x9C },
+	{ 0x18, 0xC0, 0x03, 0x05, 0x09, 0x05, 0x08, 0x1C, 0xAC },
+	{ 0x0E, 0xC0, 0x02, 0x05, 0x0F, 0x05, 0x08, 0x21, 0xAC },
+	{ 0x10, 0xC0, 0x01, 0x05, 0x09, 0x05, 0x04, 0x1B, 0xAC },
+	{ 0x11, 0xC0, 0x01, 0x01, 0x09, 0x07, 0x04, 0x1E, 0xAC },
+	{ 0x12, 0xC0, 0x03, 0x07, 0x07, 0x04, 0x06, 0x12, 0x42 },
+	{ 0x15, 0xC0, 0x03, 0x07, 0x07, 0x04, 0x06, 0x12, 0x52 },
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0xB5 },
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x03, 0xB5 },
+	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x1C, 0xAC }
+};
+
+const EoBRect8 CharacterGenerator::_chargenButtonBodyCoords[] = {
+	{ 0x00, 0x80, 0x04, 0x20 },
+	{ 0x04, 0x80, 0x04, 0x20 },
+	{ 0x08, 0x80, 0x04, 0x20 },
+	{ 0x0C, 0x80, 0x04, 0x20 },
+	{ 0x0E, 0xA0, 0x03, 0x10 },
+	{ 0x0B, 0xA0, 0x03, 0x10 },
+	{ 0x10, 0x80, 0x04, 0x10 },
+	{ 0x10, 0x90, 0x04, 0x10 },
+	{ 0x11, 0xA0, 0x05, 0x10 },
+	{ 0x11, 0xB0, 0x05, 0x10 },
+	{ 0x16, 0xA0, 0x05, 0x10 },
+	{ 0x16, 0xB0, 0x05, 0x10 },
+	{ 0x00, 0xA0, 0x0B, 0x10 },
+	{ 0x14, 0x80, 0x0B, 0x10 },
+	{ 0x14, 0x90, 0x0B, 0x10 }
+};
+
+const int16 CharacterGenerator::_chargenBoxX[] = { 0x10, 0x50, 0x10, 0x50 };
+const int16 CharacterGenerator::_chargenBoxY[] = { 0x3F, 0x3F, 0x7F, 0x7F };
+const int16 CharacterGenerator::_chargenNameFieldX[] = { 0x02, 0x42, 0x02, 0x42 };
+const int16 CharacterGenerator::_chargenNameFieldY[] = { 0x6B, 0x6B, 0xAB, 0xAB };
+
+const int32 CharacterGenerator::_classMenuMasks[] = {
+	0x003F, 0x07BB, 0x77FB, 0x00F1, 0x08F1, 0x00B1
+};
+
+const int32 CharacterGenerator::_alignmentMenuMasks[] = {
+	0x01FF, 0x0007, 0x0001, 0x01FF, 0x01FF, 0x01FE, 0x01FF, 0x01FE,
+	0x01FF, 0x01FE, 0x01FE, 0x01FE, 0x01FF, 0x0007, 0x01FF
+};
+
+const int16 CharacterGenerator::_raceModifiers[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1, -1, 0, 1, -1, 0, 0, 0, -1, 0, 0, 1, 0, 0
+};
+
+// Transfer Party
+
+class TransferPartyWiz {
+public:
+	TransferPartyWiz(EoBCoreEngine *vm, Screen_EoB *screen);
+	~TransferPartyWiz();
+
+	bool start();
+
+private:
+	bool selectAndLoadTransferFile();
+	bool transferFileDialogue(Common::String &dest);
+
+
+	int selectCharactersMenu();
+	void drawCharPortraitWithStats(int charIndex, bool enabled);
+	void updateHighlight(int index);
+
+	void convertStats();
+	void convertInventory();
+	Item convertItem(Item eob1Item);
+	void giveKhelbensCoin();
+
+	EoBCoreEngine *_vm;
+	Screen_EoB *_screen;
+
+	int _highlight;
+	EoBItem *_oldItems;
+
+	const uint16 *_portraitFrames;
+	const uint8 *_convertTable;
+	const uint8 *_itemTable;
+	const uint32 *_expTable;
+	const char *const *_strings1;
+	const char *const *_strings2;
+	const char *const *_labels;
+};
+
+TransferPartyWiz::TransferPartyWiz(EoBCoreEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen) {
+	int temp;
+	_portraitFrames = _vm->staticres()->loadRawDataBe16(kEoB2TransferPortraitFrames, temp);
+	_convertTable = _vm->staticres()->loadRawData(kEoB2TransferConvertTable, temp);
+	_itemTable = _vm->staticres()->loadRawData(kEoB2TransferItemTable, temp);
+	_expTable = _vm->staticres()->loadRawDataBe32(kEoB2TransferExpTable, temp);
+	_strings1 = _vm->staticres()->loadStrings(kEoB2TransferStrings1, temp);
+	_strings2 = _vm->staticres()->loadStrings(kEoB2TransferStrings2, temp);
+	_labels = _vm->staticres()->loadStrings(kEoB2TransferLabels, temp);
+	_highlight = -1;
+	_oldItems = 0;
+}
+
+TransferPartyWiz::~TransferPartyWiz() {
+	delete[] _oldItems;
+}
+
+bool TransferPartyWiz::start() {
+	_screen->copyPage(0, 12);
+
+	if (!selectAndLoadTransferFile())
+		return false;
+
+	convertStats();
+
+	_oldItems = new EoBItem[600];
+	memcpy(_oldItems, _vm->_items, sizeof(EoBItem) * 600);
+	_vm->loadItemDefs();
+
+	int selection = selectCharactersMenu();
+	if (selection == 0) {
+		for (int i = 0; i < 6; i++)
+			delete[] _vm->_characters[i].faceShape;
+		memset(_vm->_characters, 0, sizeof(EoBCharacter) * 6);
+		return false;
+	}
+
+	int ch = 0;
+	for (int i = 0; i < 6; i++) {
+		if (selection & (1 << i)) {
+			if (ch != i) {
+				delete[] _vm->_characters[ch].faceShape;
+				memcpy(&_vm->_characters[ch], &_vm->_characters[i], sizeof(EoBCharacter));
+				_vm->_characters[i].faceShape = 0;
+			}
+			ch++;
+		}
+	}
+	memset(&_vm->_characters[4], 0, sizeof(EoBCharacter) * 2);
+
+	convertInventory();
+	giveKhelbensCoin();
+
+	return true;
+}
+
+bool TransferPartyWiz::selectAndLoadTransferFile() {
+	do {
+		_screen->copyPage(12, 0);
+		 if (transferFileDialogue(_vm->_savegameFilename))
+			 break;
+	} while (_vm->_gui->confirmDialogue2(15, 68, 1));
+
+	if (_vm->_savegameFilename.empty())
+		return false;
+
+	if (_vm->loadGameState(-1).getCode() != Common::kNoError)
+		return false;
+
+	return true;
+}
+
+ bool TransferPartyWiz::transferFileDialogue(Common::String &dest) {
+	_vm->_gui->transferWaitBox();
+
+	Common::Array<Common::String> eobTargets;
+	const Common::ConfigManager::DomainMap dom = ConfMan.getGameDomains();
+
+	for (Common::ConfigManager::DomainMap::const_iterator i = dom.begin(); i != dom.end(); ++i) {
+		if (ConfMan.get("gameid", i->_key).equals("eob"))
+			eobTargets.push_back(i->_key);
+		_vm->updateInput();
+	}
+
+	if (eobTargets.empty())
+		return false;
+
+	Common::String target = _vm->_gui->transferTargetMenu(eobTargets);
+	_screen->copyPage(12, 0);
+
+	if (target.empty())
+		return true;
+
+	dest = target + ".fin";
+	Common::InSaveFile *in = _vm->_saveFileMan->openForLoading(dest);
+	if (in) {
+		delete in;
+		if (_vm->_gui->confirmDialogue2(15, -2, 1))
+			return true;
+	}
+
+	_screen->copyPage(12, 0);
+
+	bool result = _vm->_gui->transferFileMenu(target, dest);
+	_screen->copyPage(12, 0);
+
+	return result;
+}
+
+int TransferPartyWiz::selectCharactersMenu() {
+	_screen->setCurPage(2);
+	_screen->setFont(Screen::FID_6_FNT);
+	_screen->clearCurPage();
+
+	_vm->gui_drawBox(0, 0, 320, 163, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
+	_screen->printText(_strings2[0], 5, 3, 15, 0);
+	_screen->printText(_strings2[1], 5, 10, 15, 0);
+
+	for (int i = 0; i < 6; i++)
+		drawCharPortraitWithStats(i, 0);
+
+	_vm->gui_drawBox(4, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
+	_vm->gui_drawBox(272, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
+
+	_screen->printShadedText(_labels[0], 9, 151, 15, 0);
+	_screen->printShadedText(_labels[1], 288, 151, 15, 0);
+
+	_screen->setCurPage(0);
+	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->updateScreen();
+
+	int selection = 0;
+	int highlight = 0;
+	bool update = false;
+
+	for (bool loop = true; loop && (!_vm->shouldQuit());) {
+		int inputFlag = _vm->checkInput(0, false, 0) & 0x8FF;
+		_vm->removeInputTop();
+
+		if (inputFlag) {
+			if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
+				highlight ^= 1;
+			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP]) {
+				highlight -= 2;
+				if (highlight < 0)
+					highlight += 8;
+			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
+				highlight += 2;
+				if (highlight >= 8)
+					highlight -= 8;
+			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE]) {
+				update = true;
+			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
+				update = true;
+				highlight = 6;
+			} else if (inputFlag == 199) {
+				for (int i = 0; i < 8; i++) {
+					int t = i << 2;
+					if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, _portraitFrames[t], _portraitFrames[t + 1], _portraitFrames[t + 2], _portraitFrames[t + 3])) {
+						highlight = i;
+						update = true;
+						break;
+					}
+				}
+			}
+		}
+
+		updateHighlight(highlight);
+
+		if (!update)
+			continue;
+
+		update = false;
+
+		if (highlight < 6) {
+			if (_vm->_characters[highlight].flags & 1) {
+				selection ^= (1 << highlight);
+				drawCharPortraitWithStats(highlight, (selection & (1 << highlight)) ? true : false);
+				_screen->updateScreen();
+			}
+			continue;
+		}
+
+		int x = (highlight - 6) * 268 + 4;
+		_vm->gui_drawBox(x, 148, 43, 12, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.fill, -1);
+		_screen->updateScreen();
+		_vm->_system->delayMillis(80);
+		_vm->gui_drawBox(x, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, -1);
+		_screen->updateScreen();
+
+		if (highlight == 6 || _vm->shouldQuit()) {
+			_screen->setFont(Screen::FID_8_FNT);
+			return 0;
+		}
+
+		int count = 0;
+		for (int i = 0; i < 6; i++) {
+			if (selection & (1 << i))
+				count++;
+		}
+
+		if (count == 4 || _vm->shouldQuit())
+			loop = false;
+		else
+			_vm->_gui->messageDialogue(16, count < 4 ? 69 : 70, 6);
+
+		_screen->updateScreen();
+	}
+
+	_screen->setFont(Screen::FID_8_FNT);
+	if (_vm->shouldQuit())
+		return 0;
+	else
+		_vm->_gui->messageDialogue(16, 71, 6);
+
+	return selection;
+}
+
+void TransferPartyWiz::drawCharPortraitWithStats(int charIndex, bool enabled) {
+	int16 x = (charIndex % 2) * 159;
+	int16 y = (charIndex / 2) * 40;
+	EoBCharacter *c = &_vm->_characters[charIndex];
+
+	_screen->fillRect(x + 4, y + 24, x + 36, y + 57, 12);
+	_vm->gui_drawBox(x + 40, y + 24, 118, 34, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
+
+	if (!(c->flags & 1))
+		return;
+
+	_screen->drawShape(_screen->_curPage, c->faceShape, x + 4, y + 25, 0);
+
+	int color1 = 15;
+	int color2 = 12;
+
+	if (enabled) {
+		color1 = 6;
+		color2 = 15;
+	} else {
+		_screen->drawShape(_screen->_curPage, _vm->_disabledCharGrid, x + 4, y + 25, 0);
+	}
+
+	_screen->printShadedText(c->name, x + 44, y + 27, color1, 0);
+	_screen->printText(_vm->_chargenRaceSexStrings[c->raceSex], x + 43, y + 36, color2, 0);
+	_screen->printText(_vm->_chargenClassStrings[c->cClass], x + 43, y + 43, color2, 0);
+
+	Common::String tmp = Common::String::format(_strings1[0], c->level[0]);
+	for (int i = 1; i < _vm->_numLevelsPerClass[c->cClass]; i++)
+		tmp += Common::String::format(_strings1[1], c->level[i]);
+	_screen->printText(tmp.c_str(), x + 43, y + 50, color2, 0);
+}
+
+void TransferPartyWiz::updateHighlight(int index) {
+	static const int16 xPos[] = { 9, 288 };
+	if (_highlight > 5 && _highlight != index)
+		_screen->printText(_labels[_highlight - 6], xPos[_highlight - 6], 151, 15, 0);
+
+	if (index < 6) {
+		_vm->_gui->updateBoxFrameHighLight(14 + index);
+		_highlight = index;
+		return;
+	}
+
+	if (_highlight == index)
+		return;
+
+	if (_highlight < 6)
+		_vm->_gui->updateBoxFrameHighLight(-1);
+
+	_screen->printText(_labels[index - 6], xPos[index - 6], 151, 6, 0);
+	_screen->updateScreen();
+	_highlight = index;
+}
+
+void TransferPartyWiz::convertStats() {
+	for (int i = 0; i < 6; i++) {
+		EoBCharacter *c = &_vm->_characters[i];
+		uint32 aflags = 0;
+
+		for (int ii = 0; ii < 25; ii++) {
+			if (c->mageSpellsAvailableFlags & (1 << ii)) {
+				int8 f = (int8)_convertTable[ii + 1] - 1;
+				if (f != -1)
+					aflags |= (1 << f);
+			}
+		}
+		c->mageSpellsAvailableFlags = aflags;
+
+		c->armorClass = 0;
+		c->disabledSlots = 0;
+		c->flags &= 1;
+		c->hitPointsCur = c->hitPointsMax;
+		c->food = 100;
+
+		c->effectFlags = 0;
+		c->damageTaken = 0;
+		memset(c->clericSpells, 0, sizeof(int8) * 80);
+		memset(c->mageSpells, 0, sizeof(int8) * 80);
+		memset(c->timers, 0, sizeof(uint32) * 10);
+		memset(c->events, 0, sizeof(int8) * 10);
+		memset(c->effectsRemainder, 0, sizeof(uint8) * 4);
+		memset(c->slotStatus, 0, sizeof(int8) * 5);
+
+		for (int ii = 0; ii < 3; ii++) {
+			int t = _vm->getCharacterClassType(c->cClass, ii);
+			if (t == -1)
+				continue;
+			if (c->experience[ii] > _expTable[t])
+				c->experience[ii] = _expTable[t];
+		}
+	}
+}
+
+void TransferPartyWiz::convertInventory() {
+	for (int i = 0; i < 4; i++) {
+		EoBCharacter *c = &_vm->_characters[i];
+
+		for (int slot = 0; slot < 27; slot++) {
+			Item itm = c->inventory[slot];
+			if (slot == 16) {
+				Item first = itm;
+				c->inventory[slot] = 0;
+
+				for (bool forceLoop = true; (itm && (itm != first)) || forceLoop; itm = _oldItems[itm].prev) {
+					forceLoop = false;
+					_vm->setItemPosition(&c->inventory[slot], -2, convertItem(itm), 0);
+				}
+			} else {
+				c->inventory[slot] = convertItem(itm);
+			}
+		}
+	}
+}
+
+Item TransferPartyWiz::convertItem(Item eob1Item) {
+	if (!eob1Item)
+		return 0;
+
+	EoBItem *itm1 = &_oldItems[eob1Item];
+
+	if (!_itemTable[itm1->type])
+		return 0;
+
+	Item newItem = _vm->duplicateItem(1);
+	EoBItem *itm2 = &_vm->_items[newItem];
+	bool match = false;
+
+	itm2->flags = itm1->flags | 0x40;
+	itm2->icon = itm1->icon;
+	itm2->type = itm1->type;
+	itm2->level = 0xFF;
+
+	switch (itm2->type) {
+	case 35:
+		itm1->value += 25;
+		// fall through
+	case 34:
+		itm2->value = _convertTable[itm1->value];
+		if (!itm2->value) {
+			itm2->block = -1;
+			return 0;
+		}
+		break;
+	case 39:
+		itm2->value = itm1->value - 1;
+		break;
+	case 48:
+		if (itm1->value == 5) {
+			memset(itm2, 0, sizeof(EoBItem));
+			itm2->block = -1;
+			return 0;
+		}
+		itm2->value = itm1->value;
+		itm2->flags = ((itm1->flags & 0x3F) + 3) | 0x40;
+		break;
+	case 18:
+		itm2->icon = 19;
+		// fall through
+	default:
+		itm2->value = itm1->value;
+		break;
+	}
+
+	switch ((_vm->_itemTypes[itm2->type].extraProperties & 0x7F) - 1) {
+	case 0:
+	case 1:
+	case 2:
+		if (itm2->value)
+			itm2->flags |= 0x80;
+		break;
+	case 4:
+	case 5:
+	case 8:
+	case 9:
+	case 13:
+	case 15:
+	case 17:
+		itm2->flags |= 0x80;
+		break;
+	default:
+		break;
+	}
+
+	for (int i = 1; i < 600; i++) {
+		if (i == 60 || i == 62 || i == 63 || i == 83)
+			continue;
+		EoBItem *tmp = &_vm->_items[i];
+		if (tmp->level || tmp->block == -2 || tmp->type != itm2->type || tmp->icon != itm2->icon)
+			continue;
+		itm2->nameUnid = tmp->nameUnid;
+		itm2->nameId = tmp->nameId;
+		match = true;
+		break;
+	}
+
+	if (!match) {
+		for (int i = 1; i < 600; i++) {
+			if (i == 60 || i == 62 || i == 63 || i == 83)
+				continue;
+			EoBItem *tmp = &_vm->_items[i];
+			if (tmp->level || tmp->block == -2 || tmp->type != itm2->type)
+				continue;
+			itm2->nameUnid = tmp->nameUnid;
+			itm2->nameId = tmp->nameId;
+			match = true;
+			break;
+		}
+	}
+
+	if (!match) {
+		memset(itm2, 0, sizeof(EoBItem));
+		itm2->block = -1;
+		return 0;
+	}
+
+	itm2->level = 0;
+	return newItem;
+}
+
+void TransferPartyWiz::giveKhelbensCoin() {
+	bool success = false;
+	for (int i = 0; i < 4 && !success; i++) {
+		EoBCharacter *c = &_vm->_characters[i];
+
+		for (int slot = 2; slot < 16; slot++) {
+			if (c->inventory[slot])
+				continue;
+			_vm->createInventoryItem(c, 93, -1, slot);
+			success = true;
+			break;
+		}
+	}
+
+	if (!success) {
+		_vm->_characters[0].inventory[2] = 0;
+		_vm->createInventoryItem(&_vm->_characters[0], 93, -1, 2);
+	}
+}
+
+// Start functions
+
+bool EoBCoreEngine::startCharacterGeneration() {
+	return CharacterGenerator(this, _screen).start(_characters, &_faceShapes);
+}
+
+bool EoBCoreEngine::startPartyTransfer() {
+	return TransferPartyWiz(this, _screen).start();
+}
+
+} // End of namespace Kyra
+
+#endif // ENABLE_EOB
diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
new file mode 100644
index 0000000..9731f00
--- /dev/null
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -0,0 +1,493 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#include "kyra/engine/darkmoon.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/sound.h"
+
+namespace Kyra {
+
+DarkMoonEngine::DarkMoonEngine(OSystem *system, const GameFlags &flags) : EoBCoreEngine(system, flags) {
+	_dscDoorType5Offs = 0;
+	_numSpells = 70;
+	_menuChoiceInit = 4;
+
+	_kheldranStrings = _npcStrings[0] = _npcStrings[1] = _hornStrings = 0;
+	_utilMenuStrings = _ascii2SjisTables = _ascii2SjisTables2 = 0;
+	_npcShpData = _dscDoorType5Offs = _hornSounds = 0;
+	_dreamSteps = 0;
+}
+
+DarkMoonEngine::~DarkMoonEngine() {
+}
+
+Common::Error DarkMoonEngine::init() {
+	Common::Error err = EoBCoreEngine::init();
+	if (err.getCode() != Common::kNoError)
+		return err;
+
+	initStaticResource();
+
+	_monsterProps = new EoBMonsterProperty[10];
+
+	if (_configRenderMode == Common::kRenderEGA) {
+		Palette pal(16);
+		_screen->loadPalette(_egaDefaultPalette, pal, 16);
+		_screen->setScreenPalette(pal);
+	}
+
+	_screen->loadPalette(_flags.platform == Common::kPlatformFMTowns ? "MENU.PAL" : "PALETTE.COL", _screen->getPalette(0));
+	_screen->setScreenPalette(_screen->getPalette(0));
+
+	// adjust menu settings for EOB II FM-Towns
+	if (_flags.platform == Common::kPlatformFMTowns) {
+		_screen->modifyScreenDim(6, 10, 100, 21, 40);
+		_screen->modifyScreenDim(27, 0, 0, 21, 2);
+	}
+
+	return Common::kNoError;
+}
+
+void DarkMoonEngine::startupNew() {
+	_currentLevel = 4;
+	_currentSub = 0;
+	loadLevel(4, 0);
+	_currentBlock = 171;
+	_currentDirection = 2;
+	setHandItem(0);
+	EoBCoreEngine::startupNew();
+}
+
+void DarkMoonEngine::drawNpcScene(int npcIndex) {
+	const uint8 *shpDef = &_npcShpData[npcIndex << 3];
+	for (int i = npcIndex; i != 255; i = shpDef[7]) {
+		shpDef = &_npcShpData[i << 3];
+		_screen->_curPage = 2;
+		const uint8 *shp = _screen->encodeShape(READ_LE_UINT16(shpDef), shpDef[2], shpDef[3], shpDef[4]);
+		_screen->_curPage = 0;
+		_screen->drawShape(0, shp, 88 + shpDef[5] - (shp[2] << 2), 104 + shpDef[6] - shp[1], 5);
+		delete[] shp;
+	}
+}
+
+void DarkMoonEngine::runNpcDialogue(int npcIndex) {
+	if (npcIndex == 0) {
+		snd_playSoundEffect(57);
+		if (npcJoinDialogue(0, 1, 3, 2))
+			setScriptFlags(0x40);
+	} else if (npcIndex == 1) {
+		snd_playSoundEffect(53);
+		gui_drawDialogueBox();
+
+		_txt->printDialogueText(4, 0);
+		int r = runDialogue(-1, 2, _npcStrings[0][0], _npcStrings[0][1]) - 1;
+
+		if (r == 0) {
+			snd_stopSound();
+			delay(3 * _tickLength);
+			snd_playSoundEffect(91);
+			npcJoinDialogue(1, 5, 6, 7);
+		} else if (r == 1) {
+			setScriptFlags(0x20);
+		}
+
+	} else if (npcIndex == 2) {
+		snd_playSoundEffect(55);
+		gui_drawDialogueBox();
+
+		_txt->printDialogueText(8, 0);
+		int r = runDialogue(-1, 2, _npcStrings[1][0], _npcStrings[1][1]) - 1;
+
+		if (r == 0) {
+			if (rollDice(1, 2, -1))
+				_txt->printDialogueText(9, _okStrings[0]);
+			else
+				npcJoinDialogue(2, 102, 103, 104);
+			setScriptFlags(8);
+		} else if (r == 1) {
+			_currentDirection = 0;
+		}
+	}
+}
+
+void DarkMoonEngine::updateUsedCharacterHandItem(int charIndex, int slot) {
+	EoBItem *itm = &_items[_characters[charIndex].inventory[slot]];
+	if (itm->type == 48 || itm->type == 62) {
+		if (itm->value == 5)
+			return;
+		int charges = itm->flags & 0x3F;
+		if (--charges)
+			--itm->flags;
+		else
+			deleteInventoryItem(charIndex, slot);
+	} else if (itm->type == 26 || itm->type == 34 || itm->type == 35) {
+		deleteInventoryItem(charIndex, slot);
+	}
+}
+
+void DarkMoonEngine::generateMonsterPalettes(const char *file, int16 monsterIndex) {
+	int cp = _screen->setCurPage(2);
+	_screen->loadShapeSetBitmap(file, 3, 3);
+	uint8 tmpPal[16];
+	uint8 newPal[16];
+
+	for (int i = 0; i < 6; i++) {
+		int dci = monsterIndex + i;
+		memcpy(tmpPal, _monsterShapes[dci] + 4, 16);
+		int colx = 302 + 3 * i;
+
+		for (int ii = 0; ii < 16; ii++) {
+			uint8 col = _screen->getPagePixel(_screen->_curPage, colx, 184 + ii);
+			int iii = 0;
+			for (; iii < 16; iii++) {
+				if (tmpPal[iii] == col) {
+					newPal[ii] = iii;
+					break;
+				}
+			}
+
+			if (iii == 16)
+				newPal[ii] = 0;
+		}
+
+		for (int ii = 1; ii < 3; ii++) {
+			memcpy(tmpPal, _monsterShapes[dci] + 4, 16);
+
+			for (int iii = 0; iii < 16; iii++) {
+				uint8 col = _screen->getPagePixel(_screen->_curPage, colx + ii, 184 + iii);
+				if (newPal[iii])
+					tmpPal[newPal[iii]] = col;
+			}
+
+			int c = i;
+			if (monsterIndex >= 18)
+				c += 6;
+
+			c = (c << 1) + (ii - 1);
+			assert(c < 24);
+			memcpy(_monsterPalettes[c], tmpPal, 16);
+		}
+	}
+
+	_screen->setCurPage(cp);
+}
+
+void DarkMoonEngine::loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex) {
+	int len = stream->readUint16LE();
+	Common::List<SpriteDecoration*> activeDecorations;
+
+	for (int i = 0; i < len; i++) {
+		for (int ii = 0; ii < 6; ii++) {
+			uint8 dc[6];
+			stream->read(dc, 6);
+			if (!dc[2] || !dc[3])
+				continue;
+
+			SpriteDecoration *m = &_monsterDecorations[i * 6 + ii + monsterIndex];
+			if (_flags.platform != Common::kPlatformFMTowns)
+				m->shp = _screen->encodeShape(dc[0], dc[1], dc[2], dc[3]);
+			m->x = (int8)dc[4];
+			m->y = (int8)dc[5];
+			activeDecorations.push_back(m);
+		}
+	}
+
+	if (_flags.platform == Common::kPlatformFMTowns) {
+		while (!activeDecorations.empty()) {
+			activeDecorations.front()->shp = loadTownsShape(stream);
+			activeDecorations.pop_front();
+		}
+	}
+}
+
+void DarkMoonEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
+	uint8 flg = _levelBlockProperties[block].flags & 7;
+
+	if (flg == 7 || _currentBlock == block || (flg && (_monsterProps[type].u30 || pos == 4)))
+		return;
+
+	for (int i = 0; i < 30; i++) {
+		if (_monsters[i].block != block)
+			continue;
+		if (_monsters[i].pos == 4 || _monsterProps[_monsters[i].type].u30)
+			return;
+	}
+
+	int index = -1;
+	int maxDist = 0;
+
+	for (int i = 0; i < 30; i++) {
+		if (_monsters[i].hitPointsCur <= 0) {
+			index = i;
+			break;
+		}
+
+		if (_monsters[i].flags & 0x40)
+			continue;
+
+		// WORKAROUND for bug #3611077 (Dran's dragon transformation sequence triggered prematurely):
+		// The boss level and the mindflayer level share the same monster data. If you hang around
+		// long enough in the mindflayer level all 30 monster slots will be used up. When this
+		// happens it will trigger the dragon transformation sequence when Dran is moved around by script.
+		// We avoid removing Dran here by prefering monster slots occupied by monsters from another
+		// sub level.
+		if (_monsters[i].sub != _currentSub) {
+			index = i;
+			break;
+		}
+
+		int dist = getBlockDistance(_monsters[i].block, _currentBlock);
+
+		if (dist > maxDist) {
+			maxDist = dist;
+			index = i;
+		}
+	}
+
+	if (index == -1)
+		return;
+
+	if (_monsters[index].hitPointsCur > 0)
+		killMonster(&_monsters[index], false);
+
+	initMonster(index, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);
+}
+
+bool DarkMoonEngine::killMonsterExtra(EoBMonsterInPlay *m) {
+	// WORKAROUND for bug #3611077 (see DarkMoonEngine::replaceMonster())
+	// The mindflayers have monster type 0, just like Dran. Using a monster slot occupied by a mindflayer would trigger the dragon transformation
+	// sequence when all 30 monster slots are used up. We avoid this by checking for m->sub == 1.
+	if (_currentLevel == 16 && _currentSub == 1 && m->sub == 1 && (_monsterProps[m->type].capsFlags & 4)) {
+		if (m->type) {
+			_playFinale = true;
+			_runFlag = false;
+			delay(850);
+		} else {
+			m->hitPointsCur = 150;
+			m->curRemoteWeapon = 0;
+			m->numRemoteAttacks = 255;
+			m->shpIndex++;
+			m->type++;
+			seq_dranDragonTransformation();
+		}
+		return false;
+	}
+	return true;
+}
+
+const uint8 *DarkMoonEngine::loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) {
+	_screen->loadShapeSetBitmap(filename, 3, 3);
+	for (int i = 0; i < 3; i++) {
+		_doorShapes[doorIndex * 3 + i] = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6));
+		shapeDefs += 8;
+	}
+
+	for (int i = 0; i < 2; i++) {
+		_doorSwitches[doorIndex * 3 + i].shp = _screen->encodeShape(READ_LE_UINT16(shapeDefs), READ_LE_UINT16(shapeDefs + 2), READ_LE_UINT16(shapeDefs + 4), READ_LE_UINT16(shapeDefs + 6));
+		shapeDefs += 8;
+		_doorSwitches[doorIndex * 3 + i].x = *shapeDefs;
+		shapeDefs += 2;
+		_doorSwitches[doorIndex * 3 + i].y = *shapeDefs;
+		shapeDefs += 2;
+	}
+	_screen->_curPage = 0;
+	return shapeDefs;
+}
+
+void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16) {
+	int shapeIndex = type * 3 + 2 - mDim;
+	uint8 *shp = _doorShapes[shapeIndex];
+	if (!shp)
+		return;
+
+	if ((_doorType[type] == 0) || (_doorType[type] == 1)) {
+		y = _dscDoorY1[mDim] - shp[1];
+		x -= (shp[2] << 2);
+
+		if (_doorType[type] == 1) {
+			drawBlockObject(0, 2, shp, x, y, 5);
+			shp = _doorShapes[3 + shapeIndex];
+		}
+
+		y -= ((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim]);
+
+		if (_specialWallTypes[wall] == 5)
+			y -= _dscDoorType5Offs[shapeIndex];
+
+	} else if (_doorType[type] == 2) {
+		x -= (shp[2] << 2);
+		y = _dscDoorY2[mDim] - ((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim]);
+	}
+
+	drawBlockObject(0, 2, shp, x, y, 5);
+
+	if (_doorType[type] == 2) {
+		shp = _doorShapes[shapeIndex + 3];
+		y = _dscDoorFrameY2[mDim] - shp[1] + (((wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim]) >> 1) - 1;
+		drawBlockObject(0, 2, shp, x, y, 5);
+	}
+
+	if (_wllShapeMap[wall] == -1 && !_noDoorSwitch[type])
+		drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
+}
+
+void DarkMoonEngine::restParty_npc() {
+	int insalId = -1;
+	int numChar = 0;
+
+	for (int i = 0; i < 6; i++) {
+		if (!testCharacter(i, 1))
+			continue;
+		if (testCharacter(i, 2) && _characters[i].portrait == -1)
+			insalId = i;
+		numChar++;
+	}
+
+	if (insalId == -1 || numChar < 5)
+		return;
+
+	removeCharacterFromParty(insalId);
+	if (insalId < 4)
+		exchangeCharacters(insalId, testCharacter(5, 1) ? 5 : 4);
+
+	clearScriptFlags(6);
+
+	if (!stripPartyItems(1, 1, 1, 1))
+		stripPartyItems(2, 1, 1, 1);
+	stripPartyItems(31, 0, 1, 3);
+	stripPartyItems(39, 1, 0, 3);
+	stripPartyItems(47, 0, 1, 2);
+
+	_items[createItemOnCurrentBlock(28)].value = 26;
+
+	gui_drawPlayField(false);
+	gui_drawAllCharPortraitsWithStats();
+
+	_screen->setClearScreenDim(10);
+	_screen->set16bitShadingLevel(4);
+	gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1);
+	gui_drawBox((_screen->_curDim->sx << 3) + 1, _screen->_curDim->sy + 1, (_screen->_curDim->w << 3) - 2, _screen->_curDim->h - 2, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+	_screen->set16bitShadingLevel(0);
+	_gui->messageDialogue2(11, 63, 6);
+	_gui->messageDialogue2(11, 64, 6);
+}
+
+bool DarkMoonEngine::restParty_extraAbortCondition() {
+	if (_currentLevel != 3)
+		return false;
+
+	seq_nightmare();
+
+	return true;
+}
+
+void DarkMoonEngine::useHorn(int charIndex, int weaponSlot) {
+	int v = _items[_characters[charIndex].inventory[weaponSlot]].value - 1;
+	_txt->printMessage(_hornStrings[v]);
+	snd_playSoundEffect(_hornSounds[v]);
+}
+
+bool DarkMoonEngine::checkPartyStatusExtra() {
+	if (checkScriptFlags(0x100000))
+		seq_kheldran();
+	return _gui->confirmDialogue2(14, 67, 1);
+}
+
+void DarkMoonEngine::drawLightningColumn() {
+	int f = rollDice(1, 2, -1);
+	int y = 0;
+
+	for (int i = 0; i < 6; i++) {
+		f ^= 1;
+		drawBlockObject(f, 2, _lightningColumnShape, 72, y, 5);
+		y += 64;
+	}
+}
+
+int DarkMoonEngine::resurrectionSelectDialogue() {
+	countResurrectionCandidates();
+
+	_rrNames[_rrCount] = _abortStrings[0];
+	_rrId[_rrCount++] = 99;
+
+	int r = _rrId[runDialogue(-1, 9, _rrNames[0], _rrNames[1], _rrNames[2], _rrNames[3], _rrNames[4], _rrNames[5], _rrNames[6], _rrNames[7], _rrNames[8]) - 1];
+	if (r == 99)
+		return 0;
+
+	if (r < 0) {
+		r = -r;
+		if (prepareForNewPartyMember(33, r))
+			initNpc(r - 1);
+	} else {
+		_characters[r].hitPointsCur = 1;
+	}
+
+	return 1;
+}
+
+int DarkMoonEngine::charSelectDialogue() {
+	int cnt = 0;
+	const char *namesList[7];
+	memset(namesList, 0, 7 * sizeof(const char *));
+
+	for (int i = 0; i < 6; i++) {
+		if (!testCharacter(i, 3))
+			continue;
+		namesList[cnt++] = _characters[i].name;
+	}
+
+	namesList[cnt++] = _abortStrings[0];
+
+	int r = runDialogue(-1, 7, namesList[0], namesList[1], namesList[2], namesList[3], namesList[4], namesList[5], namesList[6]) - 1;
+	if (r == cnt - 1)
+		return 99;
+
+	for (cnt = 0; cnt < 6; cnt++) {
+		if (!testCharacter(cnt, 3))
+			continue;
+		if (--r < 0)
+			break;
+	}
+	return cnt;
+}
+
+void DarkMoonEngine::characterLevelGain(int charIndex) {
+	EoBCharacter *c = &_characters[charIndex];
+	int s = _numLevelsPerClass[c->cClass];
+	for (int i = 0; i < s; i++) {
+		uint32 er = getRequiredExperience(c->cClass, i, c->level[i] + 1);
+		if (er == 0xFFFFFFFF)
+			continue;
+
+		increaseCharacterExperience(charIndex, er - c->experience[i] + 1);
+	}
+}
+
+const KyraRpgGUISettings *DarkMoonEngine::guiSettings() {
+	return (_flags.platform == Common::kPlatformFMTowns) ? &_guiSettingsFMTowns : &_guiSettingsDOS;
+}
+
+} // End of namespace Kyra
+
+#endif // ENABLE_EOB
diff --git a/engines/kyra/engine/darkmoon.h b/engines/kyra/engine/darkmoon.h
new file mode 100644
index 0000000..3577bdb
--- /dev/null
+++ b/engines/kyra/engine/darkmoon.h
@@ -0,0 +1,139 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#ifndef KYRA_EOB2_H
+#define KYRA_EOB2_H
+
+#include "kyra/engine/eobcommon.h"
+
+namespace Kyra {
+
+class DarkmoonSequenceHelper;
+
+struct DarkMoonAnimCommand {
+	uint8 command;
+	uint8 obj;
+	int16 x1;
+	uint8 y1;
+	uint8 delay;
+	uint8 pal;
+	uint8 x2;
+	uint8 y2;
+	uint8 w;
+	uint8 h;
+};
+
+class DarkMoonEngine : public EoBCoreEngine {
+friend class GUI_EoB;
+friend class DarkmoonSequenceHelper;
+public:
+	DarkMoonEngine(OSystem *system, const GameFlags &flags);
+	~DarkMoonEngine();
+
+private:
+	// Init / Release
+	Common::Error init();
+	void initStaticResource();
+	void initSpells();
+
+	// Main Menu
+	int mainMenu();
+	int mainMenuLoop();
+	void townsUtilitiesMenu();
+
+	int _menuChoiceInit;
+
+	// Main loop
+	void startupNew();
+	void startupLoad() {}
+
+	// Intro/Outro
+	void seq_playIntro();
+	void seq_playFinale();
+	void seq_playCredits(DarkmoonSequenceHelper *sq, const uint8 *data, int sd, int backupPage, int tempPage, int speed);
+
+	// Ingame sequence
+	void seq_nightmare();
+	void seq_kheldran();
+	void seq_dranDragonTransformation();
+
+	const int8 *_dreamSteps;
+	const char *const *_kheldranStrings;
+
+	// characters
+	void drawNpcScene(int npcIndex);
+	void runNpcDialogue(int npcIndex);
+
+	const uint8 *_npcShpData;
+	const char *const *_npcStrings[2];
+
+	// items
+	void updateUsedCharacterHandItem(int charIndex, int slot);
+
+	// Monsters
+	void generateMonsterPalettes(const char *file, int16 monsterIndex);
+	void loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex);
+	void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
+	bool killMonsterExtra(EoBMonsterInPlay *m);
+
+	// Level
+	void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {}
+	const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs);
+	void drawDoorIntern(int type, int, int x, int y, int w, int wall, int mDim, int16, int16);
+
+	const uint8 *_dscDoorType5Offs;
+
+	// Fight
+	static const uint8 _monsterAcHitChanceTbl1[];
+	static const uint8 _monsterAcHitChanceTbl2[];
+
+	// Rest party
+	void restParty_npc();
+	bool restParty_extraAbortCondition();
+
+	// misc
+	void useHorn(int charIndex, int weaponSlot);
+	bool checkPartyStatusExtra();
+	void drawLightningColumn();
+	int resurrectionSelectDialogue();
+	int charSelectDialogue();
+	void characterLevelGain(int charIndex);
+
+	const KyraRpgGUISettings *guiSettings();
+
+	const char *const *_hornStrings;
+	const uint8 *_hornSounds;
+
+	const char *const *_utilMenuStrings;
+
+	static const KyraRpgGUISettings _guiSettingsDOS;
+	static const KyraRpgGUISettings _guiSettingsFMTowns;
+	static const uint8 _egaDefaultPalette[];
+};
+
+} // End of namespace Kyra
+
+#endif
+
+#endif // ENABLE_EOB
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
new file mode 100644
index 0000000..18ed9c6
--- /dev/null
+++ b/engines/kyra/engine/eob.cpp
@@ -0,0 +1,573 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#include "kyra/engine/eob.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/sound.h"
+
+namespace Kyra {
+
+EoBEngine::EoBEngine(OSystem *system, const GameFlags &flags)
+	: EoBCoreEngine(system, flags) {
+	_numSpells = 53;
+	_menuChoiceInit = 4;
+
+	_turnUndeadString = 0;
+	_finBonusStrings = _npcStrings[1] = _npcStrings[2] = 0;
+	_npcStrings[3] = _npcStrings[4] = _npcStrings[5] = _npcStrings[6] = 0;
+	_npcStrings[7] = _npcStrings[8] = _npcStrings[9] = _npcStrings[10] = 0;
+	_npcShpData = _npcSubShpIndex1 = _npcSubShpIndex2 = _npcSubShpY = 0;
+	_dscDoorScaleMult4 = _dscDoorScaleMult5 = _dscDoorScaleMult6 = _dscDoorY3 = 0;
+	_dscDoorY4 = _dscDoorY5 = _dscDoorY6 = _dscDoorY7 = _doorShapeEncodeDefs = 0;
+	_doorSwitchShapeEncodeDefs = _doorSwitchCoords = 0;
+	_dscDoorCoordsExt = 0;
+}
+
+EoBEngine::~EoBEngine() {
+	delete[] _itemsOverlay;
+}
+
+Common::Error EoBEngine::init() {
+	Common::Error err = EoBCoreEngine::init();
+	if (err.getCode() != Common::kNoError)
+		return err;
+
+	initStaticResource();
+
+	if (_configRenderMode != Common::kRenderCGA)
+		_itemsOverlay = _res->fileData((_configRenderMode == Common::kRenderEGA) ? "ITEMRMP.EGA" : "ITEMRMP.VGA", 0);
+
+	_screen->modifyScreenDim(7, 0x01, 0xB3, 0x22, 0x12);
+	_screen->modifyScreenDim(9, 0x01, 0x7D, 0x26, 0x3F);
+	_screen->modifyScreenDim(12, 0x01, 0x04, 0x14, 0xA0);
+
+	_scriptTimersCount = 1;
+
+	if (_configRenderMode == Common::kRenderEGA) {
+		Palette pal(16);
+		_screen->loadPalette(_egaDefaultPalette, pal, 16);
+		_screen->setScreenPalette(pal);
+	} else {
+		_screen->loadPalette("PALETTE.COL", _screen->getPalette(0));
+	}
+
+	return Common::kNoError;
+}
+
+void EoBEngine::startupNew() {
+	_currentLevel = 1;
+	_currentSub = 0;
+	loadLevel(1, 0);
+	_currentBlock = 490;
+	_currentDirection = 0;
+	setHandItem(0);
+
+	EoBCoreEngine::startupNew();
+}
+
+void EoBEngine::startupLoad() {
+	_sound->loadSoundFile("ADLIB");
+}
+
+void EoBEngine::drawNpcScene(int npcIndex) {
+	_screen->copyRegion(0, 0, 0, 0, 176, 120, 6, 0, Screen::CR_NO_P_CHECK);
+	switch (npcIndex) {
+	case 0:
+		encodeDrawNpcSeqShape(2, 88, 104);
+		break;
+
+	case 1:
+		if (_npcSequenceSub == -1) {
+			encodeDrawNpcSeqShape(0, 88, 104);
+		} else {
+			encodeDrawNpcSeqShape(0, 60, 104);
+			encodeDrawNpcSeqShape(5, 116, 104);
+		}
+		break;
+
+	case 2:
+		if (_npcSequenceSub == -1) {
+			encodeDrawNpcSeqShape(3, 88, 104);
+		} else {
+			encodeDrawNpcSeqShape(3, 60, 104);
+			encodeDrawNpcSeqShape(_npcSubShpIndex1[_npcSequenceSub], 116, 104);
+			encodeDrawNpcSeqShape(_npcSubShpIndex2[_npcSequenceSub], 116, _npcSubShpY[_npcSequenceSub]);
+		}
+		break;
+
+	case 3:
+		encodeDrawNpcSeqShape(7, 88, 104);
+		break;
+
+	case 4:
+		encodeDrawNpcSeqShape(6, 88, 104);
+		break;
+
+	case 5:
+		encodeDrawNpcSeqShape(18, 88, 88);
+		break;
+
+	case 6:
+		encodeDrawNpcSeqShape(17, 88, 104);
+		break;
+
+	case 7:
+		encodeDrawNpcSeqShape(4, 88, 104);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void EoBEngine::encodeDrawNpcSeqShape(int npcIndex, int drawX, int drawY) {
+	const uint8 *shpDef = &_npcShpData[npcIndex << 2];
+	_screen->_curPage = 2;
+	const uint8 *shp = _screen->encodeShape(shpDef[0], shpDef[1], shpDef[2], shpDef[3], false, _cgaMappingDefault);
+	_screen->_curPage = 0;
+	_screen->drawShape(0, shp, drawX - (shp[2] << 2), drawY - shp[1], 5);
+	delete[] shp;
+}
+
+#define DLG2(txt, buttonstr) (runDialogue(txt, 2, _npcStrings[buttonstr][0], _npcStrings[buttonstr][1]) - 1)
+#define DLG3(txt, buttonstr) (runDialogue(txt, 3, _npcStrings[buttonstr][0], _npcStrings[buttonstr][1], _npcStrings[buttonstr][2]) - 1)
+#define DLG2A3(cond, txt, buttonstr1, buttonstr2) ((cond) ? (DLG2(txt, buttonstr1) ? 2 : 0) : DLG3(txt, buttonstr2))
+#define TXT(txt) _txt->printDialogueText(txt, _moreStrings[0])
+
+void EoBEngine::runNpcDialogue(int npcIndex) {
+	int r = 0;
+	int a = 0;
+	Item itm = 0;
+
+	switch (npcIndex) {
+	case 0:
+		for (r = 1; r == 1;) {
+			gui_drawDialogueBox();
+			r = DLG2A3(checkScriptFlags(0x2000), 8, 2, 1);
+			if (r == 1) {
+				TXT(1);
+				setScriptFlags(0x2000);
+			} else if (r == 0) {
+				npcJoinDialogue(6, 12, 23, 2);
+				setScriptFlags(0x4000);
+			}
+		}
+		break;
+
+	case 1:
+		if (!checkScriptFlags(0x10000)) {
+			if (checkScriptFlags(0x8000)) {
+				a = 13;
+			} else {
+				setScriptFlags(0x8000);
+				r = DLG2(3, 3);
+				a = 4;
+			}
+			if (!r)
+				r = DLG2(a, 4);
+
+			if (!r) {
+				for (a = 0; a < 6; a++)
+					createItemOnCurrentBlock(55);
+				createItemOnCurrentBlock(62);
+				setScriptFlags(0x10000);
+				TXT(6);
+				npcJoinDialogue(7, 7, 29, 30);
+			} else {
+				TXT(5);
+			}
+			r = 1;
+		}
+
+		if (!checkScriptFlags(0x80000)) {
+			for (a = 0; a < 6; a++) {
+				if (testCharacter(a, 1) && _characters[a].portrait == -9)
+					break;
+			}
+			if (a != 6) {
+				TXT(25);
+				TXT(26);
+				setScriptFlags(0x80000);
+				r = 1;
+			}
+		}
+
+		if (!checkScriptFlags(0x100000)) {
+			if (deletePartyItems(6, -1)) {
+				_npcSequenceSub = 0;
+				drawNpcScene(npcIndex);
+				TXT(28);
+				createItemOnCurrentBlock(32);
+				setScriptFlags(0x100000);
+				r = 1;
+			}
+		}
+
+		if (!r)
+			_txt->printDialogueText(_npcStrings[0][0], true);
+
+		break;
+
+	case 2:
+		if (checkScriptFlags(0x10000)) {
+			if (checkScriptFlags(0x20000)) {
+				TXT(11);
+			} else {
+				r = DLG2A3(!countResurrectionCandidates(), 9, 5, 6);
+				if (r < 2) {
+					if (r == 0)
+						healParty();
+					else
+						resurrectionSelectDialogue();
+					setScriptFlags(0x20000);
+				}
+			}
+		} else {
+			TXT(24);
+		}
+		break;
+
+	case 3:
+		if (!DLG2(18, 7)) {
+			setScriptFlags(0x8400000);
+			for (a = 0; a < 30; a++) {
+				if (_monsters[a].mode == 8)
+					_monsters[a].mode = 5;
+			}
+		} else if (deletePartyItems(49, -1)) {
+			TXT(20);
+			setScriptFlags(0x400000);
+		} else {
+			TXT(19);
+		}
+		break;
+
+	case 4:
+		r = DLG3(14, 8);
+		if (r == 0)
+			setScriptFlags(0x200000);
+		else if (r == 1)
+			TXT(15);
+		setScriptFlags(0x800000);
+		break;
+
+	case 5:
+		if (!DLG2(16, 9)) {
+			TXT(17);
+			for (a = 0; a < 6; a++) {
+				for (r = 0; r < 2; r++) {
+					itm = _characters[a].inventory[r];
+					if (itm && (_items[itm].type < 51 || _items[itm].type > 56)) {
+						_characters[a].inventory[r] = 0;
+						setItemPosition((Item *)&_levelBlockProperties[_currentBlock].drawObjects, _currentBlock, itm, _dropItemDirIndex[(_currentDirection << 2) + rollDice(1, 2, -1)]);
+					}
+				}
+			}
+		}
+		setScriptFlags(0x2000000);
+		break;
+
+	case 6:
+		TXT(21);
+		setScriptFlags(0x1000000);
+		break;
+
+	case 7:
+		r = DLG3(22, 10);
+		if (r  < 2) {
+			if (r == 0)
+				npcJoinDialogue(8, 27, 44, 45);
+			else
+				TXT(31);
+			setScriptFlags(0x4000000);
+		}
+		break;
+
+	default:
+		break;
+	}
+}
+
+#undef TXT
+#undef DLG2
+#undef DLG3
+#undef DLG2A3
+
+void EoBEngine::updateUsedCharacterHandItem(int charIndex, int slot) {
+	EoBItem *itm = &_items[_characters[charIndex].inventory[slot]];
+	if (itm->type == 48) {
+		int charges = itm->flags & 0x3F;
+		if (--charges)
+			--itm->flags;
+		else
+			deleteInventoryItem(charIndex, slot);
+	} else if (itm->type == 34 || itm->type == 35) {
+		deleteInventoryItem(charIndex, slot);
+	}
+}
+
+void EoBEngine::replaceMonster(int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) {
+	if (_levelBlockProperties[block].flags & 7)
+		return;
+
+	for (int i = 0; i < 30; i++) {
+		if (_monsters[i].hitPointsCur <= 0) {
+			initMonster(i, unit, block, pos, dir, type, shpIndex, mode, h2, randItem, fixedItem);
+			break;
+		}
+	}
+}
+
+bool EoBEngine::killMonsterExtra(EoBMonsterInPlay *m) {
+	if (m->type == 21) {
+		_playFinale = true;
+		_runFlag = false;
+	}
+	return true;
+}
+
+void EoBEngine::updateScriptTimersExtra() {
+	int cnt = 0;
+	for (int i = 1; i < 30; i++) {
+		if (_monsters[i].hitPointsCur <= 0)
+			cnt++;
+	}
+
+	if (!cnt) {
+		for (int i = 1; i < 30; i++) {
+			if (getBlockDistance(_monsters[i].block, _currentBlock) > 3) {
+				killMonster(&_monsters[i], true);
+				break;
+			}
+		}
+	}
+}
+
+void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) {
+	_screen->loadShapeSetBitmap("DOOR", 5, 3);
+	_screen->_curPage = 2;
+
+	if (doorType1 != 0xFF) {
+		for (int i = 0; i < 3; i++) {
+			const uint8 *enc = &_doorShapeEncodeDefs[(doorType1 * 3 + i) << 2];
+			_doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			enc = &_doorSwitchShapeEncodeDefs[(doorType1 * 3 + i) << 2];
+			_doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 * 6 + i * 2];
+			_doorSwitches[shapeId1 + i].y = _doorSwitchCoords[doorType1 * 6 + i * 2 + 1];
+		}
+	}
+
+	if (doorType2 != 0xFF) {
+		for (int i = 0; i < 3; i++) {
+			const uint8 *enc = &_doorShapeEncodeDefs[(doorType2 * 3 + i) << 2];
+			_doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			enc = &_doorSwitchShapeEncodeDefs[(doorType2 * 3 + i) << 2];
+			_doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 * 6 + i * 2];
+			_doorSwitches[shapeId2 + i].y = _doorSwitchCoords[doorType2 * 6 + i * 2 + 1];
+		}
+	}
+
+	_screen->_curPage = 0;
+}
+
+void EoBEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wall, int mDim, int16 y1, int16 y2) {
+	int shapeIndex = type + 2 - mDim;
+	uint8 *shp = _doorShapes[shapeIndex];
+	if (!shp)
+		return;
+
+	int d1 = 0;
+	int d2 = 0;
+	int v = 0;
+	const ScreenDim *td = _screen->getScreenDim(5);
+
+	switch (_currentLevel) {
+	case 4:
+	case 5:
+	case 6:
+		y = _dscDoorY6[mDim] - shp[1];
+		d1 = _dscDoorCoordsExt[index << 1] >> 3;
+		d2 = _dscDoorCoordsExt[(index << 1) + 1] >> 3;
+		if (_shpDmX1 > d1)
+			d1 = _shpDmX1;
+		if (_shpDmX2 < d2)
+			d2 = _shpDmX2;
+		_screen->modifyScreenDim(5, d1, td->sy, d2 - d1, td->h);
+		v = ((wall < 30) ? (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult3[mDim] : _dscDoorScaleMult4[mDim]) * -1;
+		v -= (shp[2] << 3);
+		drawBlockObject(0, 2, shp, x + v, y, 5);
+		v += (shp[2] << 3);
+		drawBlockObject(1, 2, shp, x - v, y, 5);
+		if (_wllShapeMap[wall] == -1)
+			drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w - v, _doorSwitches[shapeIndex].y, 5);
+		break;
+
+	case 7:
+	case 8:
+	case 9:
+		y = _dscDoorY3[mDim] - _doorShapes[shapeIndex + 3][1];
+		d1 = x - (_doorShapes[shapeIndex + 3][2] << 2);
+		x -= (shp[2] << 2);
+		drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], d1, y, 5);
+		setDoorShapeDim(index, y1, y2, 5);
+		y = _dscDoorY3[mDim] - ((wall < 30) ? (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim] : _dscDoorScaleMult2[mDim]);
+		drawBlockObject(0, 2, shp, x, y, 5);
+		if (_wllShapeMap[wall] == -1)
+			drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
+		break;
+
+	case 10:
+	case 11:
+		v = ((wall < 30) ? (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult5[mDim] : _dscDoorScaleMult6[mDim]) * -1;
+		x -= (shp[2] << 2);
+		y = _dscDoorY4[mDim] + v;
+		drawBlockObject(0, 2, shp, x, y + v, 5);
+		v = (v >> 3) + (v >> 2);
+		y = _dscDoorY5[mDim];
+		drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], x, y - v, 5);
+		if (_wllShapeMap[wall] == -1)
+			drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
+		break;
+
+	default:
+		y = (_currentLevel == 12 ? _dscDoorY6[mDim] : _dscDoorY1[mDim]) - shp[1];
+		x -= (shp[2] << 2);
+		y -= (wall >= 30 ? _dscDoorScaleMult2[mDim] : (wall - _dscDoorScaleOffs[wall]) * _dscDoorScaleMult1[mDim]);
+		drawBlockObject(0, 2, shp, x, y, 5);
+
+		if (_wllShapeMap[wall] == -1)
+			drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
+		break;
+	}
+}
+
+void EoBEngine::turnUndeadAuto() {
+	if (_currentLevel != 2 && _currentLevel != 7)
+		return;
+
+	int oc = _openBookChar;
+
+	for (int i = 0; i < 6; i++) {
+		if (!testCharacter(i, 0x0D))
+			continue;
+
+		EoBCharacter *c = &_characters[i];
+
+		if (_itemTypes[_items[c->inventory[0]].type].extraProperties != 6 && _itemTypes[_items[c->inventory[1]].type].extraProperties != 6)
+			continue;
+
+		int l = getCharacterLevelIndex(2, c->cClass);
+		if (l > -1) {
+			if (c->level[l] > _openBookCasterLevel) {
+				_openBookCasterLevel = c->level[l];
+				_openBookChar = i;
+			}
+		} else {
+			l = getCharacterLevelIndex(4, c->cClass);
+			if (l > -1) {
+				if ((c->level[l] - 2) > _openBookCasterLevel) {
+					_openBookCasterLevel = (c->level[l] - 2);
+					_openBookChar = i;
+				}
+			}
+		}
+	}
+
+	if (_openBookCasterLevel)
+		spellCallback_start_turnUndead();
+
+	_openBookChar = oc;
+	_openBookCasterLevel = 0;
+}
+
+void EoBEngine::turnUndeadAutoHit() {
+	_txt->printMessage(_turnUndeadString[0], -1, _characters[_openBookChar].name);
+	sparkEffectOffensive();
+}
+
+bool EoBEngine::checkPartyStatusExtra() {
+	_screen->copyPage(0, 10);
+	int cd = _screen->curDimIndex();
+	gui_drawBox(0, 121, 320, 80, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+	_txt->setupField(9, false);
+	_txt->printMessage(_menuStringsDefeat[0]);
+	while (!shouldQuit()) {
+		removeInputTop();
+		if (checkInput(0, false, 0) & 0xFF)
+			break;
+	}
+	_screen->copyPage(10, 0);
+	_eventList.clear();
+	_screen->setScreenDim(cd);
+	_txt->removePageBreakFlag();
+	return true;
+}
+
+int EoBEngine::resurrectionSelectDialogue() {
+	gui_drawDialogueBox();
+	_txt->printDialogueText(_npcStrings[0][1]);
+
+	int r = _rrId[runDialogue(-1, 9, _rrNames[0], _rrNames[1], _rrNames[2], _rrNames[3], _rrNames[4], _rrNames[5], _rrNames[6], _rrNames[7], _rrNames[8]) - 1];
+
+	if (r < 0) {
+		r = -r;
+		deletePartyItems(33, r);
+		_npcSequenceSub = r - 1;
+		drawNpcScene(2);
+		npcJoinDialogue(_npcSequenceSub, 32 + (_npcSequenceSub << 1), -1, 33 + (_npcSequenceSub << 1));
+	} else {
+		_characters[r].hitPointsCur = _characters[r].hitPointsMax;
+	}
+
+	return 1;
+}
+
+void EoBEngine::healParty() {
+	int cnt = rollDice(1, 3, 2);
+	for (int i = 0; i < 6 && cnt; i++) {
+		if (testCharacter(i, 3))
+			continue;
+
+		_characters[i].flags &= ~4;
+		neutralizePoison(i);
+
+		if (_characters[i].hitPointsCur >= _characters[i].hitPointsMax)
+			continue;
+
+		cnt--;
+		_characters[i].hitPointsCur += rollDice(1, 8, 9);
+		if (_characters[i].hitPointsCur > _characters[i].hitPointsMax)
+			_characters[i].hitPointsCur = _characters[i].hitPointsMax;
+	}
+}
+
+const KyraRpgGUISettings *EoBEngine::guiSettings() {
+	return (_configRenderMode == Common::kRenderCGA || _configRenderMode == Common::kRenderEGA) ? &_guiSettingsEGA : &_guiSettingsVGA;
+}
+
+} // End of namespace Kyra
+
+#endif // ENABLE_EOB
diff --git a/engines/kyra/engine/eob.h b/engines/kyra/engine/eob.h
new file mode 100644
index 0000000..0eb8fd3
--- /dev/null
+++ b/engines/kyra/engine/eob.h
@@ -0,0 +1,125 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#ifndef KYRA_EOB1_H
+#define KYRA_EOB1_H
+
+#include "kyra/engine/eobcommon.h"
+
+namespace Kyra {
+
+class EoBEngine : public EoBCoreEngine {
+friend class GUI_EoB;
+friend class EoBIntroPlayer;
+public:
+	EoBEngine(OSystem *system, const GameFlags &flags);
+	~EoBEngine();
+
+private:
+	// Init / Release
+	Common::Error init();
+	void initStaticResource();
+	void initSpells();
+
+	// Main Menu
+	int mainMenu();
+	int mainMenuLoop();
+	int _menuChoiceInit;
+
+	// Main loop
+	void startupNew();
+	void startupLoad();
+
+	// Intro/Outro
+	void seq_playIntro();
+	void seq_playFinale();
+	void seq_xdeath();
+
+	const char *const *_finBonusStrings;
+
+	// characters
+	void drawNpcScene(int npcIndex);
+	void encodeDrawNpcSeqShape(int npcIndex, int drawX, int drawY);
+	void runNpcDialogue(int npcIndex);
+
+	const uint8 *_npcShpData;
+	const uint8 *_npcSubShpIndex1;
+	const uint8 *_npcSubShpIndex2;
+	const uint8 *_npcSubShpY;
+	const char *const *_npcStrings[11];
+
+	// items
+	void updateUsedCharacterHandItem(int charIndex, int slot);
+
+	// Monsters
+	void replaceMonster(int unit, uint16 block, int d, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem);
+	bool killMonsterExtra(EoBMonsterInPlay *m);
+	void updateScriptTimersExtra();
+
+	// Level
+	const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) { return 0; }
+	void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2);
+	void drawDoorIntern(int type, int index, int x, int y, int w, int wall, int mDim, int16 y1, int16 y2);
+
+	const int16 *_dscDoorCoordsExt;
+	const uint8 *_dscDoorScaleMult4;
+	const uint8 *_dscDoorScaleMult5;
+	const uint8 *_dscDoorScaleMult6;
+	const uint8 *_dscDoorY3;
+	const uint8 *_dscDoorY4;
+	const uint8 *_dscDoorY5;
+	const uint8 *_dscDoorY6;
+	const uint8 *_dscDoorY7;
+
+	const uint8 *_doorShapeEncodeDefs;
+	const uint8 *_doorSwitchShapeEncodeDefs;
+	const uint8 *_doorSwitchCoords;
+
+	// Fight
+	static const uint8 _monsterAcHitChanceTbl1[];
+	static const uint8 _monsterAcHitChanceTbl2[];
+
+	// Magic
+	void turnUndeadAuto();
+	void turnUndeadAutoHit();
+
+	const char *const *_turnUndeadString;
+
+	// Misc
+	bool checkPartyStatusExtra();
+	int resurrectionSelectDialogue();
+	void healParty();
+
+	const KyraRpgGUISettings *guiSettings();
+
+	static const KyraRpgGUISettings _guiSettingsVGA;
+	static const KyraRpgGUISettings _guiSettingsEGA;
+	static const uint8 _egaDefaultPalette[];
+};
+
+} // End of namespace Kyra
+
+#endif
+
+#endif // ENABLE_EOB
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
new file mode 100644
index 0000000..58cc394
--- /dev/null
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -0,0 +1,2536 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#include "kyra/engine/kyra_rpg.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/sound_intern.h"
+#include "kyra/sound/sound_adlib.h"
+#include "kyra/script/script_eob.h"
+#include "kyra/engine/timer.h"
+#include "kyra/gui/debugger.h"
+
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+#include "backends/keymapper/keymapper.h"
+
+namespace Kyra {
+
+const char *const EoBCoreEngine::kKeymapName = "eob";
+
+EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
+	: KyraRpgEngine(system, flags), _numLargeItemShapes(flags.gameID == GI_EOB1 ? 14 : 11),
+	  _numSmallItemShapes(flags.gameID == GI_EOB1 ? 23 : 26),
+	  _numThrownItemShapes(flags.gameID == GI_EOB1 ? 12 : 9),
+	  _numItemIconShapes(flags.gameID == GI_EOB1 ? 89 : 112),
+	  _teleporterWallId(flags.gameID == GI_EOB1 ? 52 : 44) {
+
+	_screen = 0;
+	_gui = 0;
+	_debugger = 0;
+
+	_playFinale = false;
+	_runFlag = true;
+	_configMouse = _config2431 = true;
+	_loading = false;
+
+	_enableHiResDithering = false;
+
+	_envAudioTimer = 0;
+	_flashShapeTimer = 0;
+	_drawSceneTimer = 0;
+
+	_largeItemShapes = _smallItemShapes = _thrownItemShapes = _spellShapes = _firebeamShapes = 0;
+	_itemIconShapes = _wallOfForceShapes = _teleporterShapes = _sparkShapes = _compassShapes = 0;
+	_redSplatShape = _greenSplatShape = _deadCharShape = _disabledCharGrid = 0;
+	_blackBoxSmallGrid = _weaponSlotGrid = _blackBoxWideGrid = _lightningColumnShape = 0;
+
+	_monsterAcHitChanceTable1 = _monsterAcHitChanceTable2 = 0;
+	
+	_monsterDustStrings = 0;
+	_enemyMageSpellList = 0;
+	_enemyMageSfx = 0;
+	_beholderSpellList = 0;
+	_beholderSfx = 0;
+
+	_faceShapes = 0;
+	_characters = 0;
+	_items = 0;
+	_itemTypes = 0;
+	_itemNames = 0;
+	_itemInHand = -1;
+	_numItems = _numItemNames = 0;
+
+	_castScrollSlot = 0;
+	_currentSub = 0;
+
+	_itemsOverlay = 0;
+
+	_partyEffectFlags = 0;
+	_lastUsedItem = 0;
+
+	_levelDecorationRects = 0;
+	_doorSwitches = 0;
+	_monsterProps = 0;
+	_monsterDecorations = 0;
+	_monsterFlashOverlay = _monsterStoneOverlay = 0;
+	_monsters = 0;
+	_dstMonsterIndex = 0;
+	_preventMonsterFlash = false;
+
+	_teleporterPulse = 0;
+
+	_dscShapeCoords = 0;
+	_dscItemPosIndex = 0;
+	_dscItemShpX = 0;
+	_dscItemScaleIndex = 0;
+	_dscItemTileIndex = 0;
+	_dscItemShapeMap = 0;
+	_dscDoorScaleOffs = 0;
+	_dscDoorScaleMult1 = 0;
+	_dscDoorScaleMult2 = 0;
+	_dscDoorScaleMult3 = 0;
+	_dscDoorY1 = 0;
+	_dscDoorXE = 0;
+
+	_greenFadingTable = _blueFadingTable = _lightBlueFadingTable = _blackFadingTable = _greyFadingTable = 0;
+
+	_menuDefs = 0;
+
+	_exchangeCharacterId = -1;
+	_charExchangeSwap = 0;
+	_configHpBarGraphs = true;
+	_configMouseBtSwap = false;
+
+	memset(_dialogueLastBitmap, 0, 13);
+	_npcSequenceSub = 0;
+	_moveCounter = 0;
+	_partyResting = false;
+
+	_flyingObjects = 0;
+
+	_inf = 0;
+	_stepCounter = 0;
+	_stepsUntilScriptCall = 0;
+	_scriptTimersMode = 3;
+	_currentDirection = 0;
+
+	_openBookSpellLevel = 0;
+	_openBookSpellSelectedItem = 0;
+	_openBookSpellListOffset = 0;
+	_openBookChar = _openBookCharBackup = _openBookCasterLevel = 0;
+	_openBookType = _openBookTypeBackup = 0;
+	_openBookSpellList = 0;
+	_openBookAvailableSpells = 0;
+	_activeSpellCharId = 0;
+	_activeSpellCharacterPos = 0;
+	_activeSpell = 0;
+	_characterSpellTarget = 0;
+	_returnAfterSpellCallback = false;
+	_spells = 0;
+	_spellAnimBuffer = 0;
+	_clericSpellOffset = 0;
+	_restPartyElapsedTime = 0;
+	_allowSkip = false;
+	_allowImport = false;
+
+	_wallsOfForce = 0;
+
+	_rrCount = 0;
+	memset(_rrNames, 0, 10 * sizeof(const char *));
+	memset(_rrId, 0, 10 * sizeof(int8));
+
+	_mainMenuStrings = _levelGainStrings = _monsterSpecAttStrings = _characterGuiStringsHp = 0;
+	_characterGuiStringsWp = _characterGuiStringsWr = _characterGuiStringsSt = 0;
+	_characterGuiStringsIn = _characterStatusStrings7 = _characterStatusStrings8 = 0;
+	_characterStatusStrings9 = _characterStatusStrings12 = _characterStatusStrings13 = 0;
+	_classModifierFlags = _saveThrowLevelIndex = _saveThrowModDiv = _saveThrowModExt = 0;
+	_wandTypes = _drawObjPosIndex = _flightObjFlipIndex = _expObjectTblIndex = 0;
+	_expObjectShpStart = _expObjectTlMode = _expObjectAnimTbl1 = _expObjectAnimTbl2 = _expObjectAnimTbl3 = 0;
+	_monsterStepTable0 = _monsterStepTable1 = _monsterStepTable2 = _monsterStepTable3 = 0;
+	_projectileWeaponAmmoTypes = _flightObjShpMap = _flightObjSclIndex = 0;
+	_monsterCloseAttPosTable1 = _monsterCloseAttPosTable2 = _monsterCloseAttChkTable1 = 0;
+	_monsterCloseAttChkTable2 = _monsterCloseAttDstTable1 = _monsterCloseAttDstTable2 = 0;
+	_monsterProximityTable = _findBlockMonstersTable = _wallOfForceDsY = _wallOfForceDsNumW = 0;
+	_wallOfForceDsNumH = _wallOfForceShpId = _wllFlagPreset = _teleporterShapeCoords = 0;
+	_monsterCloseAttUnkTable = _monsterFrmOffsTable1 = _monsterFrmOffsTable2 = 0;
+	_monsterDirChangeTable = _portalSeq = 0;
+	_wallOfForceDsX = 0;
+	_expObjectAnimTbl1Size = _expObjectAnimTbl2Size = _expObjectAnimTbl3Size = 0;
+	_wllFlagPresetSize = _scriptTimersCount = _buttonList1Size = _buttonList2Size = 0;
+	_buttonList3Size = _buttonList4Size = _buttonList5Size = _buttonList6Size = 0;
+	_buttonList7Size = _buttonList8Size = 0;
+	_inventorySlotsY = _mnDef = 0;
+	_transferStringsScummVM = 0;
+	_buttonDefs = 0;
+	_npcPreset = 0;
+	_chargenStatStrings = _chargenRaceSexStrings = _chargenClassStrings = 0;
+	_chargenAlignmentStrings = _pryDoorStrings = _warningStrings = _ripItemStrings = 0;
+	_cursedString = _enchantedString = _magicObjectStrings = _magicObjectString5 = 0;
+	_patternSuffix = _patternGrFix1 = _patternGrFix2 = _validateArmorString = 0;
+	_validateCursedString = _validateNoDropString = _potionStrings = _wandStrings = 0;
+	_itemMisuseStrings = _suffixStringsRings = _suffixStringsPotions = 0;
+	_suffixStringsWands = _takenStrings = _potionEffectStrings = _yesNoStrings = 0;
+	_npcMaxStrings = _okStrings = _npcJoinStrings = _cancelStrings = 0;
+	_abortStrings = _saveLoadStrings = _mnWord = _mnPrompt = _bookNumbers = 0;
+	_mageSpellList = _clericSpellList = _spellNames = _magicStrings1 = 0;
+	_magicStrings2 = _magicStrings3 = _magicStrings4 = _magicStrings6 = 0;
+	_magicStrings7 = _magicStrings8 = _saveNamePatterns = 0; 
+	_spellAnimBuffer = 0;
+	_sparkEffectDefSteps = _sparkEffectDefSubSteps = _sparkEffectDefShift = 0;
+	_sparkEffectDefAdd = _sparkEffectDefX = _sparkEffectDefY = _sparkEffectOfShift = 0;
+	_sparkEffectOfX = _sparkEffectOfY = _magicFlightObjectProperties = 0;
+	_turnUndeadEffect = _burningHandsDest = _coneOfColdGfxTbl = 0;
+	_sparkEffectOfFlags1 = _sparkEffectOfFlags2 = 0;
+	_coneOfColdDest1 = _coneOfColdDest2 = _coneOfColdDest3 = _coneOfColdDest4 = 0;
+	_coneOfColdGfxTblSize = 0;
+	_menuButtonDefs = 0;
+	_updateCharNum = 0;
+	_menuStringsMain = _menuStringsSaveLoad = _menuStringsOnOff = _menuStringsSpells = 0;
+	_menuStringsRest = _menuStringsDrop = _menuStringsExit = _menuStringsStarve = 0;
+	_menuStringsScribe = _menuStringsDrop2 = _menuStringsHead = _menuStringsPoison = 0;
+	_menuStringsMgc = _menuStringsPrefs = _menuStringsRest2 = _menuStringsRest3 = 0;
+	_menuStringsRest4 = _menuStringsDefeat = _menuStringsTransfer = _menuStringsSpec = 0;
+	_menuStringsSpellNo = _menuYesNoStrings = _2431Strings = _katakanaLines = _katakanaSelectStrings = 0;
+	_errorSlotEmptyString = _errorSlotNoNameString = _menuOkString = 0;
+	_spellLevelsMage = _spellLevelsCleric = _numSpellsCleric = _numSpellsWisAdj = _numSpellsPal = _numSpellsMage = 0;
+	_mnNumWord = _numSpells = _mageSpellListSize = _spellLevelsMageSize = _spellLevelsClericSize = 0;
+	_inventorySlotsX = _slotValidationFlags = _encodeMonsterShpTable = 0;
+	_cgaMappingDefault = _cgaMappingAlt = _cgaMappingInv = _cgaLevelMappingIndex = _cgaMappingItemsL = _cgaMappingItemsS = _cgaMappingThrown = _cgaMappingIcons = _cgaMappingDeco = 0;
+	memset(_cgaMappingLevel, 0, sizeof(_cgaMappingLevel));
+	memset(_expRequirementTables, 0, sizeof(_expRequirementTables));
+	memset(_saveThrowTables, 0, sizeof(_saveThrowTables));
+	memset(_doorType, 0, sizeof(_doorType));
+	memset(_noDoorSwitch, 0, sizeof(_noDoorSwitch));
+	memset(_scriptTimers, 0, sizeof(_scriptTimers));
+	memset(_monsterBlockPosArray, 0, sizeof(_monsterBlockPosArray));
+	memset(_foundMonstersArray, 0, sizeof(_foundMonstersArray));
+
+#define DWM0 _dscWallMapping.push_back(0)
+#define DWM(x) _dscWallMapping.push_back(&_sceneDrawVar##x)
+	DWM0;       DWM0;       DWM(Down);  DWM(Right);
+	DWM(Down);  DWM(Right); DWM(Down);  DWM0;
+	DWM(Down);  DWM(Left);  DWM(Down);  DWM(Left);
+	DWM0;       DWM0;       DWM(Down);  DWM(Right);
+	DWM(Down);  DWM(Right); DWM(Down);  DWM0;
+	DWM(Down);  DWM(Left);  DWM(Down);  DWM(Left);
+	DWM(Down);  DWM(Right); DWM(Down);  DWM0;
+	DWM(Down);  DWM(Left);  DWM0;       DWM(Right);
+	DWM(Down);  DWM0;       DWM0;       DWM(Left);
+#undef DWM
+#undef DWM0
+}
+
+EoBCoreEngine::~EoBCoreEngine() {
+	releaseItemsAndDecorationsShapes();
+	releaseTempData();
+
+	if (_faceShapes) {
+		for (int i = 0; i < 44; i++) {
+			if (_characters) {
+				for (int ii = 0; ii < 6; ii++) {
+					if (_characters[ii].faceShape == _faceShapes[i])
+						_characters[ii].faceShape = 0;
+				}
+			}
+			delete[] _faceShapes[i];
+			_faceShapes[i] = 0;
+		}
+		delete[] _faceShapes;
+	}
+
+	if (_characters) {
+		for (int i = 0; i < 6; i++)
+			delete[] _characters[i].faceShape;
+	}
+
+	delete[] _characters;
+	delete[] _items;
+	delete[] _itemTypes;
+	if (_itemNames) {
+		for (int i = 0; i < 130; i++)
+			delete[] _itemNames[i];
+	}
+	delete[] _itemNames;
+	delete[] _flyingObjects;
+
+	delete[] _monsterFlashOverlay;
+	delete[] _monsterStoneOverlay;
+	delete[] _monsters;
+
+	if (_monsterDecorations) {
+		releaseMonsterShapes(0, 36);
+		delete[] _monsterShapes;
+		delete[] _monsterDecorations;
+
+		for (int i = 0; i < 24; i++)
+			delete[] _monsterPalettes[i];
+		delete[] _monsterPalettes;
+	}
+
+	delete[] _monsterProps;
+
+	if (_doorSwitches) {
+		releaseDoorShapes();
+		delete[] _doorSwitches;
+	}
+
+	releaseDecorations();
+	delete[] _levelDecorationRects;
+	_dscWallMapping.clear();
+
+	delete[] _greenFadingTable;
+	delete[] _blueFadingTable;
+	delete[] _lightBlueFadingTable;
+	delete[] _blackFadingTable;
+	delete[] _greyFadingTable;
+
+	delete[] _spells;
+	delete[] _spellAnimBuffer;
+	delete[] _wallsOfForce;
+	delete[] _buttonDefs;
+
+	delete _gui;
+	_gui = 0;
+	delete _screen;
+	_screen = 0;
+
+	delete[] _menuDefs;
+	_menuDefs = 0;
+
+	delete _inf;
+	_inf = 0;
+	delete _timer;
+	_timer = 0;
+	delete _debugger;
+	_debugger = 0;
+	delete _txt;
+	_txt = 0;
+}
+
+void EoBCoreEngine::initKeymap() {
+#ifdef ENABLE_KEYMAPPER
+	Common::Keymapper *const mapper = _eventMan->getKeymapper();
+
+	// Do not try to recreate same keymap over again
+	if (mapper->getKeymap(kKeymapName) != 0)
+		return;
+
+	Common::Keymap *const engineKeyMap = new Common::Keymap(kKeymapName);
+
+	const Common::KeyActionEntry keyActionEntries[] = {
+		{ Common::KeyState(Common::KEYCODE_UP), "MVF", _("Move Forward") },
+		{ Common::KeyState(Common::KEYCODE_DOWN), "MVB", _("Move Back") },
+		{ Common::KeyState(Common::KEYCODE_LEFT), "MVL", _("Move Left") },
+		{ Common::KeyState(Common::KEYCODE_RIGHT), "MVR", _("Move Right") },
+		{ Common::KeyState(Common::KEYCODE_HOME), "TL", _("Turn Left") },
+		{ Common::KeyState(Common::KEYCODE_PAGEUP), "TR", _("Turn Right") },
+		{ Common::KeyState(Common::KEYCODE_i), "INV", _("Open/Close Inventory") },
+		{ Common::KeyState(Common::KEYCODE_p), "SCE", _("Switch Inventory/Character screen") },
+		{ Common::KeyState(Common::KEYCODE_c), "CMP", _("Camp") },
+		{ Common::KeyState(Common::KEYCODE_SPACE), "CSP", _("Cast Spell") },
+		// TODO: Spell cursor, but this needs more thought, since different
+		// game versions use different keycodes.
+		{ Common::KeyState(Common::KEYCODE_1), "SL1", _("Spell Level 1") },
+		{ Common::KeyState(Common::KEYCODE_2), "SL2", _("Spell Level 2") },
+		{ Common::KeyState(Common::KEYCODE_3), "SL3", _("Spell Level 3") },
+		{ Common::KeyState(Common::KEYCODE_4), "SL4", _("Spell Level 4") },
+		{ Common::KeyState(Common::KEYCODE_5), "SL5", _("Spell Level 5") }
+	};
+
+	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); ++i) {
+		Common::Action *const act = new Common::Action(engineKeyMap, keyActionEntries[i].id, keyActionEntries[i].description);
+		act->addKeyEvent(keyActionEntries[i].ks);
+	}
+
+	if (_flags.gameID == GI_EOB2) {
+		Common::Action *const act = new Common::Action(engineKeyMap, "SL6", _("Spell Level 6"));
+		act->addKeyEvent(Common::KeyState(Common::KEYCODE_6));
+	}
+
+	mapper->addGameKeymap(engineKeyMap);
+#endif
+}
+
+Common::Error EoBCoreEngine::init() {
+	// In EOB the timer proc is directly invoked via interrupt 0x1C, 18.2 times per second.
+	// This makes a tick length of 54.94.
+	_tickLength = 55;
+
+	if (ConfMan.hasKey("render_mode"))
+		_configRenderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
+
+	_enableHiResDithering = (_configRenderMode == Common::kRenderEGA && _flags.useHiRes);
+
+	_screen = new Screen_EoB(this, _system);
+	assert(_screen);
+	_screen->setResolution();
+
+	_res = new Resource(this);
+	assert(_res);
+	_res->reset();
+
+	_staticres = new StaticResource(this);
+	assert(_staticres);
+	if (!_staticres->init())
+		error("_staticres->init() failed");
+
+	// SoundTowns_Darkmoon requires initialized _staticres
+	if (_flags.platform == Common::kPlatformDOS) {
+		//MidiDriverType midiDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB);
+		_sound = new SoundAdLibPC(this, _mixer);
+	} else if (_flags.platform == Common::kPlatformFMTowns) {
+		_sound = new SoundTowns_Darkmoon(this, _mixer);
+	} else if (_flags.platform == Common::kPlatformPC98) {
+
+	}
+
+	assert(_sound);
+	_sound->init();
+
+	// Setup volume settings (and read in all ConfigManager settings)
+	syncSoundSettings();
+
+	if (!_screen->init())
+		error("screen()->init() failed");
+
+	if (ConfMan.hasKey("save_slot")) {
+		_gameToLoad = ConfMan.getInt("save_slot");
+		if (!saveFileLoadable(_gameToLoad))
+			_gameToLoad = -1;
+	}
+
+	setupKeyMap();
+
+	_gui = new GUI_EoB(this);
+	assert(_gui);
+	_txt = new TextDisplayer_rpg(this, _screen);
+	assert(_txt);
+	_inf = new EoBInfProcessor(this, _screen);
+	assert(_inf);
+	_debugger = new Debugger_EoB(this);
+	assert(_debugger);
+
+	_screen->loadFont(Screen::FID_6_FNT, "FONT6.FNT");
+	_screen->loadFont(Screen::FID_8_FNT, "FONT8.FNT");
+
+	Common::Error err = KyraRpgEngine::init();
+	if (err.getCode() != Common::kNoError)
+		return err;
+
+	initButtonData();
+	initMenus();
+	initStaticResource();
+	initSpells();
+
+	_timer = new TimerManager(this, _system);
+	assert(_timer);
+	setupTimers();
+
+	_wllVmpMap[1] = 1;
+	_wllVmpMap[2] = 2;
+	memset(&_wllVmpMap[3], 3, 20);
+	_wllVmpMap[23] = 4;
+	_wllVmpMap[24] = 5;
+
+	memcpy(_wllWallFlags, _wllFlagPreset, _wllFlagPresetSize);
+
+	memset(&_specialWallTypes[3], 1, 5);
+	memset(&_specialWallTypes[13], 1, 5);
+	_specialWallTypes[8] = _specialWallTypes[18] = 6;
+
+	memset(&_wllShapeMap[3], -1, 5);
+	memset(&_wllShapeMap[13], -1, 5);
+
+	_wllVcnOffset = (_flags.platform == Common::kPlatformFMTowns) ? 0 : 16;
+	int bpp = (_flags.platform == Common::kPlatformFMTowns) ? 2 : 1;
+	
+	_greenFadingTable = new uint8[256 * bpp];
+	_blueFadingTable = new uint8[256 * bpp];
+	_lightBlueFadingTable = new uint8[256 * bpp];
+	_blackFadingTable = new uint8[256 * bpp];
+	_greyFadingTable = new uint8[256 * bpp];
+
+	_monsters = new EoBMonsterInPlay[30];
+	memset(_monsters, 0, 30 * sizeof(EoBMonsterInPlay));
+
+	_characters = new EoBCharacter[6];
+	memset(_characters, 0, sizeof(EoBCharacter) * 6);
+
+	_items = new EoBItem[600];
+	memset(_items, 0, sizeof(EoBItem) * 600);
+
+	_itemNames = new char*[130];
+	for (int i = 0; i < 130; i++) {
+		_itemNames[i] = new char[35];
+		memset(_itemNames[i], 0, 35);
+	}
+
+	_flyingObjects = new EoBFlyingObject[_numFlyingObjects];
+	_flyingObjectsPtr = _flyingObjects;
+	memset(_flyingObjects, 0, _numFlyingObjects * sizeof(EoBFlyingObject));
+
+	int bufferSize = _flags.useHiColorMode ? 8192 : 4096;
+	_spellAnimBuffer = new uint8[bufferSize];
+	memset(_spellAnimBuffer, 0, bufferSize);
+
+	_wallsOfForce = new WallOfForce[5];
+	memset(_wallsOfForce, 0, 5 * sizeof(WallOfForce));
+
+	memset(_doorType, 0, sizeof(_doorType));
+	memset(_noDoorSwitch, 0, sizeof(_noDoorSwitch));
+
+	_monsterShapes = new uint8*[36];
+	memset(_monsterShapes, 0, 36 * sizeof(uint8 *));
+	_monsterDecorations = new SpriteDecoration[36];
+	memset(_monsterDecorations, 0, 36 * sizeof(SpriteDecoration));
+	_monsterPalettes = new uint8*[24];
+	for (int i = 0; i < 24; i++)
+		_monsterPalettes[i] = new uint8[16];
+
+	_doorSwitches = new SpriteDecoration[6];
+	memset(_doorSwitches, 0, 6 * sizeof(SpriteDecoration));
+
+	_monsterFlashOverlay = new uint8[16];
+	_monsterStoneOverlay = new uint8[16];
+	memset(_monsterFlashOverlay, (_configRenderMode == Common::kRenderCGA) ? 0xFF : 0x0F, 16 * sizeof(uint8));
+	memset(_monsterStoneOverlay, 0x0D, 16 * sizeof(uint8));
+	_monsterFlashOverlay[0] = _monsterStoneOverlay[0] = 0;
+
+	// Prevent autosave on game startup
+	_lastAutosave = _system->getMillis();
+
+#ifdef ENABLE_KEYMAPPER
+	_eventMan->getKeymapper()->pushKeymap(kKeymapName, true);
+#endif
+
+	return Common::kNoError;
+}
+
+Common::Error EoBCoreEngine::go() {
+	_debugger->initialize();
+	_txt->removePageBreakFlag();
+	_screen->setFont(Screen::FID_8_FNT);
+	loadItemsAndDecorationsShapes();
+	_screen->setMouseCursor(0, 0, _itemIconShapes[0]);
+
+	// Import original save game files (especially the "Quick Start Party")
+	if (ConfMan.getBool("importOrigSaves")) {
+		importOriginalSaveFile(-1);
+		ConfMan.setBool("importOrigSaves", false);
+		ConfMan.flushToDisk();
+	}
+
+	loadItemDefs();
+	int action = 0;
+
+	for (bool repeatLoop = true; repeatLoop; repeatLoop ^= true) {
+		action = 0;
+
+		if (_gameToLoad != -1) {
+			_sound->selectAudioResourceSet(kMusicIngame);
+			if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
+				error("Couldn't load game slot %d on startup", _gameToLoad);
+			startupLoad();
+			_gameToLoad = -1;
+		} else {
+			_screen->showMouse();
+			action = mainMenu();
+		}
+
+		_sound->selectAudioResourceSet(kMusicIngame);
+
+		if (action == -1) {
+			// load game
+			repeatLoop = _gui->runLoadMenu(72, 14);
+			if (repeatLoop && !shouldQuit())
+				startupLoad();
+		} else if (action == -2) {
+			// new game
+			repeatLoop = startCharacterGeneration();
+			if (repeatLoop && !shouldQuit())
+				startupNew();
+		} else if (action == -3) {
+			// transfer party
+			repeatLoop = startPartyTransfer();
+			if (repeatLoop && !shouldQuit())
+				startupNew();
+		}
+	}
+
+	if (!shouldQuit() && action >= -3) {
+		runLoop();
+
+		if (_playFinale) {
+			// make final save for party transfer
+			saveGameStateIntern(-1, 0, 0);
+			_sound->selectAudioResourceSet(kMusicFinale);
+			seq_playFinale();
+		}
+	}
+
+	return Common::kNoError;
+}
+
+void EoBCoreEngine::registerDefaultSettings() {
+	KyraEngine_v1::registerDefaultSettings();
+	ConfMan.registerDefault("hpbargraphs", true);
+	ConfMan.registerDefault("mousebtswap", false);
+	ConfMan.registerDefault("importOrigSaves", true);
+}
+
+void EoBCoreEngine::readSettings() {
+	_configHpBarGraphs = ConfMan.getBool("hpbargraphs");
+	_configMouseBtSwap = ConfMan.getBool("mousebtswap");
+	_configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1;
+	_configMusic = _configSounds ? 1 : 0;
+
+	if (_sound)
+		_sound->enableSFX(_configSounds);
+}
+
+void EoBCoreEngine::writeSettings() {
+	ConfMan.setBool("hpbargraphs", _configHpBarGraphs);
+	ConfMan.setBool("mousebtswap", _configMouseBtSwap);
+	ConfMan.setBool("sfx_mute", _configSounds == 0);
+
+	if (_sound) {
+		if (!_configSounds)
+			_sound->haltTrack();
+		_sound->enableMusic(_configSounds ? 1 : 0);
+		_sound->enableSFX(_configSounds);
+	}
+
+	ConfMan.flushToDisk();
+}
+
+void EoBCoreEngine::startupNew() {
+	gui_setPlayFieldButtons();
+	_screen->_curPage = 0;
+	gui_drawPlayField(false);
+	_screen->_curPage = 0;
+	gui_drawAllCharPortraitsWithStats();
+	drawScene(1);
+	_updateFlags = 0;
+	_updateCharNum = 0;
+}
+
+void EoBCoreEngine::runLoop() {
+	_envAudioTimer = _system->getMillis() + (rollDice(1, 10, 3) * 18 * _tickLength);
+	_flashShapeTimer = 0;
+	_drawSceneTimer = _system->getMillis();
+
+	_screen->setFont(Screen::FID_6_FNT);
+	_screen->setScreenDim(7);
+
+	_runFlag = true;
+
+	while (!shouldQuit() && _runFlag) {
+		checkPartyStatus(true);
+		checkInput(_activeButtons, true, 0);
+		removeInputTop();
+
+		if (!_runFlag)
+			break;
+
+		_timer->update();
+		updateScriptTimers();
+		updateWallOfForceTimers();
+
+		if (_sceneUpdateRequired)
+			drawScene(1);
+
+		if (_envAudioTimer >= _system->getMillis() || (_flags.gameID == GI_EOB1 && (_currentLevel == 0 || _currentLevel > 3)))
+			continue;
+
+		_envAudioTimer = _system->getMillis() + (rollDice(1, 10, 3) * 18 * _tickLength);
+		snd_processEnvironmentalSoundEffect(_flags.gameID == GI_EOB1 ? 30 : (rollDice(1, 2, -1) ? 27 : 28), _currentBlock + rollDice(1, 12, -1));
+		updateEnvironmentalSfx(0);
+		turnUndeadAuto();
+	}
+}
+
+bool EoBCoreEngine::checkPartyStatus(bool handleDeath) {
+	int numChars = 0;
+	for (int i = 0; i < 6; i++)
+		numChars += testCharacter(i, 13);
+
+	if (numChars)
+		return false;
+
+	if (!handleDeath)
+		return true;
+
+	gui_drawAllCharPortraitsWithStats();
+
+	if (checkPartyStatusExtra()) {
+		_screen->setFont(Screen::FID_8_FNT);
+		gui_updateControls();
+		if (_gui->runLoadMenu(0, 0)) {
+			_screen->setFont(Screen::FID_6_FNT);
+			return true;
+		}
+	}
+
+	quitGame();
+	return false;
+}
+
+void EoBCoreEngine::loadItemsAndDecorationsShapes() {
+	releaseItemsAndDecorationsShapes();
+	int div = (_flags.gameID == GI_EOB1) ? 3 : 8;
+	int mul = (_flags.gameID == GI_EOB1) ? 64 : 24;
+	int size = 0;
+
+	_largeItemShapes = new const uint8*[_numLargeItemShapes];
+	if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+		for (int i = 0; i < _numLargeItemShapes; i++)
+			_largeItemShapes[i] = _staticres->loadRawData(kEoB2LargeItemsShapeData00 + i, size);
+	} else {
+		_screen->loadShapeSetBitmap("ITEML1", 5, 3);
+		for (int i = 0; i < _numLargeItemShapes; i++)
+			_largeItemShapes[i] = _screen->encodeShape((i / div) << 3, (i % div) * mul, 8, 24, false, _cgaMappingItemsL);
+	}
+
+	_smallItemShapes = new const uint8*[_numSmallItemShapes];
+	if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+		for (int i = 0; i < _numSmallItemShapes; i++)
+			_smallItemShapes[i] = _staticres->loadRawData(kEoB2SmallItemsShapeData00 + i, size);
+	} else {
+		_screen->loadShapeSetBitmap("ITEMS1", 5, 3);
+		for (int i = 0; i < _numSmallItemShapes; i++)
+			_smallItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingItemsS);
+	}
+
+	_thrownItemShapes = new const uint8*[_numThrownItemShapes];
+	_spellShapes = new const uint8*[4];
+	_firebeamShapes = new const uint8*[3];
+	if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+		for (int i = 0; i < _numThrownItemShapes; i++)
+			_thrownItemShapes[i] = _staticres->loadRawData(kEoB2ThrownShapeData00 + i, size);
+		for (int i = 0; i < 4; i++)
+			_spellShapes[i] = _staticres->loadRawData(kEoB2SpellShapeData00 + i, size);
+		for (int i = 0; i < 3; i++)
+			_firebeamShapes[i] = _staticres->loadRawData(kEoB2FirebeamShapeData00 + i, size);
+		_redSplatShape = _staticres->loadRawData(kEoB2RedSplatShapeData, size);
+		_greenSplatShape = _staticres->loadRawData(kEoB2GreenSplatShapeData, size);
+	} else {
+		_screen->loadShapeSetBitmap("THROWN", 5, 3);
+		for (int i = 0; i < _numThrownItemShapes; i++)
+			_thrownItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingThrown);
+		for (int i = 0; i < 4; i++)
+			_spellShapes[i] = _screen->encodeShape(8, i << 5, 6, 32, false, _cgaMappingThrown);
+
+		_firebeamShapes[0] = _screen->encodeShape(16, 0, 4, 24, false, _cgaMappingThrown);
+		_firebeamShapes[1] = _screen->encodeShape(16, 24, 4, 24, false, _cgaMappingThrown);
+		_firebeamShapes[2] = _screen->encodeShape(16, 48, 3, 24, false, _cgaMappingThrown);
+		_redSplatShape = _screen->encodeShape(16, _flags.gameID == GI_EOB1 ? 144 : 72, 5, 24, false, _cgaMappingThrown);
+		_greenSplatShape = _screen->encodeShape(16, _flags.gameID == GI_EOB1 ? 168 : 96, 5, 16, false, _cgaMappingThrown);
+	}
+
+	_itemIconShapes = new const uint8*[_numItemIconShapes];
+	if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+		for (int i = 0; i < _numItemIconShapes; i++)
+			_itemIconShapes[i] = _staticres->loadRawData(kEoB2ItemIconShapeData00 + i, size);
+	} else {
+		_screen->loadShapeSetBitmap("ITEMICN", 5, 3);
+		for (int i = 0; i < _numItemIconShapes; i++)
+			_itemIconShapes[i] = _screen->encodeShape((i % 0x14) << 1, (i / 0x14) << 4, 2, 0x10, false, _cgaMappingIcons);
+	}
+
+	_teleporterShapes = new const uint8*[6];
+	_sparkShapes = new const uint8*[3];
+	_compassShapes = new const uint8*[12];
+	if (_flags.gameID == GI_EOB2)
+		_wallOfForceShapes = new const uint8*[6];
+
+	if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
+		_lightningColumnShape = _staticres->loadRawData(kEoB2LightningColumnShapeData, size);
+		for (int i = 0; i < 6; i++)
+			_wallOfForceShapes[i] = _staticres->loadRawData(kEoB2WallOfForceShapeData00 + i, size);
+		for (int i = 0; i < 6; i++)
+			_teleporterShapes[i] = _staticres->loadRawData(kEoB2TeleporterShapeData00 + i, size);
+		for (int i = 0; i < 3; i++)
+			_sparkShapes[i] = _staticres->loadRawData(kEoB2SparkShapeData00 + i, size);
+		for (int i = 0; i < 12; i++)
+			_compassShapes[i] = _staticres->loadRawData(kEoB2CompassShapeData00 + i, size);
+
+		_deadCharShape = _staticres->loadRawData(kEoB2DeadCharShapeData, size);
+		_disabledCharGrid = _staticres->loadRawData(kEoB2DisabledCharGridShapeData, size);
+		_blackBoxSmallGrid = _staticres->loadRawData(kEoB2SmallGridShapeData, size);
+		_weaponSlotGrid = _staticres->loadRawData(kEoB2WeaponSlotGridShapeData, size);
+		_blackBoxWideGrid = _staticres->loadRawData(kEoB2WideGridShapeData, size);
+
+	} else {
+		_screen->loadShapeSetBitmap("DECORATE", 5, 3);
+		if (_flags.gameID == GI_EOB2) {
+			_lightningColumnShape = _screen->encodeShape(18, 88, 4, 64);
+			for (int i = 0; i < 6; i++)
+				_wallOfForceShapes[i] = _screen->encodeShape(_wallOfForceShapeDefs[(i << 2)], _wallOfForceShapeDefs[(i << 2) + 1], _wallOfForceShapeDefs[(i << 2) + 2], _wallOfForceShapeDefs[(i << 2) + 3]);
+		}
+
+		for (int i = 0; i < 6; i++)
+			_teleporterShapes[i] = _screen->encodeShape(_teleporterShapeDefs[(i << 2)], _teleporterShapeDefs[(i << 2) + 1], _teleporterShapeDefs[(i << 2) + 2], _teleporterShapeDefs[(i << 2) + 3], false, _cgaMappingDefault);
+		
+		_sparkShapes[0] = _screen->encodeShape(29, 0, 2, 16, false, _cgaMappingDeco);
+		_sparkShapes[1] = _screen->encodeShape(31, 0, 2, 16, false, _cgaMappingDeco);
+		_sparkShapes[2] = _screen->encodeShape(33, 0, 2, 16, false, _cgaMappingDeco);
+		_deadCharShape = _screen->encodeShape(0, 88, 4, 32, false, _cgaMappingDeco);
+		_disabledCharGrid = _screen->encodeShape(4, 88, 4, 32, false, _cgaMappingDeco);
+		_blackBoxSmallGrid = _screen->encodeShape(9, 88, 2, 8, false, _cgaMappingDeco);
+		_weaponSlotGrid = _screen->encodeShape(8, 88, 4, 16, false, _cgaMappingDeco);
+		_blackBoxWideGrid = _screen->encodeShape(8, 104, 4, 8, false, _cgaMappingDeco);
+
+		static const uint8 dHeight[] = { 17, 10, 10 };
+		static const uint8 dY[] = { 120, 137, 147 };
+		
+		for (int y = 0; y < 3; y++) {
+			for (int x = 0; x < 4; x++)
+				_compassShapes[(y << 2) + x] = _screen->encodeShape(x * 3, dY[y], 3, dHeight[y], false, _cgaMappingDeco);
+		}
+	}
+}
+
+void EoBCoreEngine::releaseItemsAndDecorationsShapes() {
+	if (_flags.platform != Common::kPlatformFMTowns || _flags.gameID != GI_EOB2) {
+		if (_largeItemShapes) {
+			for (int i = 0; i < _numLargeItemShapes; i++) {
+				if (_largeItemShapes[i])
+					delete[] _largeItemShapes[i];
+			}
+		}
+
+		if (_smallItemShapes) {
+			for (int i = 0; i < _numSmallItemShapes; i++) {
+				if (_smallItemShapes[i])
+					delete[] _smallItemShapes[i];
+			}
+		}
+
+		if (_thrownItemShapes) {
+			for (int i = 0; i < _numThrownItemShapes; i++) {
+				if (_thrownItemShapes[i])
+					delete[] _thrownItemShapes[i];
+			}
+		}
+
+		if (_spellShapes) {
+			for (int i = 0; i < 4; i++) {
+				if (_spellShapes[i])
+					delete[] _spellShapes[i];
+			}
+		}
+
+		if (_itemIconShapes) {
+			for (int i = 0; i < _numItemIconShapes; i++) {
+				if (_itemIconShapes[i])
+					delete[] _itemIconShapes[i];
+			}
+		}
+
+		if (_sparkShapes) {
+			for (int i = 0; i < 3; i++) {
+				if (_sparkShapes[i])
+					delete[] _sparkShapes[i];
+			}
+		}
+
+		if (_wallOfForceShapes) {
+			for (int i = 0; i < 6; i++) {
+				if (_wallOfForceShapes[i])
+					delete[] _wallOfForceShapes[i];
+			}
+		}
+
+		if (_teleporterShapes) {
+			for (int i = 0; i < 6; i++) {
+				if (_teleporterShapes[i])
+					delete[] _teleporterShapes[i];
+			}
+		}
+
+		if (_compassShapes) {
+			for (int i = 0; i < 12; i++) {
+				if (_compassShapes[i])
+					delete[] _compassShapes[i];
+			}
+		}
+
+		if (_firebeamShapes) {
+			for (int i = 0; i < 3; i++) {
+				if (_firebeamShapes[i])
+					delete[] _firebeamShapes[i];
+			}
+		}
+
+		delete[] _redSplatShape;
+		delete[] _greenSplatShape;
+		delete[] _deadCharShape;
+		delete[] _disabledCharGrid;
+		delete[] _blackBoxSmallGrid;
+		delete[] _weaponSlotGrid;
+		delete[] _blackBoxWideGrid;
+		delete[] _lightningColumnShape;
+	}
+
+	delete[] _largeItemShapes;
+	delete[] _smallItemShapes;
+	delete[] _thrownItemShapes;
+	delete[] _spellShapes;
+	delete[] _itemIconShapes;
+	delete[] _sparkShapes;
+	delete[] _wallOfForceShapes;
+	delete[] _teleporterShapes;
+	delete[] _compassShapes;
+	delete[] _firebeamShapes;
+}
+
+void EoBCoreEngine::setHandItem(Item itemIndex) {
+	if (itemIndex == -1) {
+		if (_flags.platform == Common::kPlatformFMTowns)
+			_screen->setMouseCursor(8, 8, _itemIconShapes[37], 0);
+		return;
+	}
+
+	if (_screen->curDimIndex() == 7 && itemIndex) {
+		printFullItemName(itemIndex);
+		_txt->printMessage(_takenStrings[0]);
+	}
+
+	_itemInHand = itemIndex;
+	int icon = _items[_itemInHand].icon;
+	const uint8 *shp = _itemIconShapes[icon];
+	const uint8 *ovl = 0;
+
+	if (icon && (_items[_itemInHand].flags & 0x80) && (_partyEffectFlags & 2))
+		ovl = _flags.gameID == GI_EOB1 ? ((_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icon << 4]) : _screen->generateShapeOverlay(shp, _lightBlueFadingTable);
+
+	int mouseOffs = itemIndex ? 8 : 0;
+	_screen->setMouseCursor(mouseOffs, mouseOffs, shp, ovl);
+
+	if (_flags.useHiColorMode) {
+		_screen->setFadeTable(_greyFadingTable);
+		_screen->setShapeFadingLevel(0);
+	}
+}
+
+int EoBCoreEngine::getDexterityArmorClassModifier(int dexterity) {
+	static const int8 mod[] = { 5, 5, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -2, -3, -4, -4, -5, -5, -5, -6, -6 };
+	return mod[dexterity];
+}
+
+int EoBCoreEngine::generateCharacterHitpointsByLevel(int charIndex, int levelIndex) {
+	EoBCharacter *c = &_characters[charIndex];
+	int m = getClassAndConstHitpointsModifier(c->cClass, c->constitutionCur);
+
+	int h = 0;
+
+	for (int i = 0; i < 3; i++) {
+		if (!(levelIndex & (1 << i)))
+			continue;
+
+		int d = getCharacterClassType(c->cClass, i);
+
+		if (c->level[i] <= _hpIncrPerLevel[6 + i])
+			h += rollDice(1, (d >= 0) ? _hpIncrPerLevel[d] : 0);
+		else
+			h += _hpIncrPerLevel[12 + i];
+
+		h += m;
+	}
+
+	h /= _numLevelsPerClass[c->cClass];
+
+	if (h < 1)
+		h = 1;
+
+	return h;
+}
+
+int EoBCoreEngine::getClassAndConstHitpointsModifier(int cclass, int constitution) {
+	int res = _hpConstModifiers[constitution];
+	// This also applies to EOB1 despite being coded differently there
+	if (res <= 2 || (_classModifierFlags[cclass] & 0x31))
+		return res;
+
+	return 2;
+}
+
+int EoBCoreEngine::getCharacterClassType(int cclass, int levelIndex) {
+	return _characterClassType[cclass * 3 + levelIndex];
+}
+
+int EoBCoreEngine::getModifiedHpLimits(int hpModifier, int constModifier, int level, bool mode) {
+	int s = _hpIncrPerLevel[6 + hpModifier] > level ? level : _hpIncrPerLevel[6 + hpModifier];
+	int res = s;
+
+	if (!mode)
+		res *= (hpModifier >= 0 ? _hpIncrPerLevel[hpModifier] : 0);
+
+	if (level > s) {
+		s = level - s;
+		res += (s * _hpIncrPerLevel[12 + hpModifier]);
+	}
+
+	if (!mode || (constModifier > 0))
+		res += (level * constModifier);
+
+	return res;
+}
+
+Common::String EoBCoreEngine::getCharStrength(int str, int strExt) {
+	if (strExt) {
+		if (strExt == 100)
+			strExt = 0;
+		_strenghtStr = Common::String::format("%d/%02d", str, strExt);
+	} else {
+		_strenghtStr = Common::String::format("%d", str);
+	}
+
+	return _strenghtStr;
+}
+
+int EoBCoreEngine::testCharacter(int16 index, int flags) {
+	if (index == -1)
+		return 0;
+
+	EoBCharacter *c = &_characters[index];
+	int res = 1;
+
+	if (flags & 1)
+		res &= (c->flags & 1);
+
+	if (flags & 2)
+		res &= ((c->hitPointsCur <= -10) || (c->flags & 8)) ? 0 : 1;
+
+	if (flags & 4)
+		res &= ((c->hitPointsCur <= 0) || (c->flags & 8)) ? 0 : 1;
+
+	if (flags & 8)
+		res &= (c->flags & 12) ? 0 : 1;
+
+	if (flags & 0x20)
+		res &= (c->flags & 4) ? 0 : 1;
+
+	if (flags & 0x10)
+		res &= (c->flags & 2) ? 0 : 1;
+
+	if (flags & 0x40)
+		res &= (c->food <= 0) ? 0 : 1;
+
+	return res;
+}
+
+int EoBCoreEngine::getNextValidCharIndex(int curCharIndex, int searchStep) {
+	do {
+		curCharIndex += searchStep;
+		if (curCharIndex < 0)
+			curCharIndex = 5;
+		if (curCharIndex > 5)
+			curCharIndex = 0;
+	} while (!testCharacter(curCharIndex, 1));
+
+	return curCharIndex;
+}
+
+void EoBCoreEngine::recalcArmorClass(int index) {
+	EoBCharacter *c = &_characters[index];
+	int acm = getDexterityArmorClassModifier(c->dexterityCur);
+	c->armorClass = 10 + acm;
+
+	static uint8 slot[] = { 17, 0, 1, 18 };
+	for (int i = 0; i < 4; i++) {
+		int itm = c->inventory[slot[i]];
+		if (!itm)
+			continue;
+
+		if (i == 2) {
+			if (!validateWeaponSlotItem(index, 1))
+				continue;
+		}
+
+		int tp = _items[itm].type;
+
+		if (!(_itemTypes[tp].allowedClasses & _classModifierFlags[c->cClass]) || (_itemTypes[tp].extraProperties & 0x7F) || (i >= 1 && i <= 2 && tp != 27 && !(_flags.gameID == GI_EOB2 && tp == 57)))
+			continue;
+
+		c->armorClass += _itemTypes[tp].armorClass;
+		c->armorClass -= _items[itm].value;
+	}
+
+	if (!_items[c->inventory[17]].value) {
+		int8 m1 = 0;
+		int8 m2 = 0;
+
+		if (c->inventory[25]) {
+			if (!(_itemTypes[_items[c->inventory[25]].type].extraProperties & 0x7F))
+				m1 = _items[c->inventory[25]].value;
+		}
+
+		if (c->inventory[26]) {
+			if (!(_itemTypes[_items[c->inventory[26]].type].extraProperties & 0x7F))
+				m2 = _items[c->inventory[26]].value;
+		}
+
+		c->armorClass -= MAX(m1, m2);
+	}
+


Commit: 7cb7e4133936fe2348f7a0dda89961d807a4ef90
    https://github.com/scummvm/scummvm/commit/7cb7e4133936fe2348f7a0dda89961d807a4ef90
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:16+01:00

Commit Message:
KYRA: (EOB) - slight improvement to character generation

- allow returning to the main menu from the character generation via Esc only when no party characters exist

Changed paths:
    engines/kyra/engine/chargen.cpp


diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
index c080acc..7bea21e 100644
--- a/engines/kyra/engine/chargen.cpp
+++ b/engines/kyra/engine/chargen.cpp
@@ -207,9 +207,11 @@ bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
 			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
 				_activeBox ^= 2;
 			} else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
-				// Unlike the original we allow returning to the main menu
-				_vm->snd_stopSound();
-				return false;
+				// Unlike the original we allow returning to the main menu if no character has been created yet or all characters have been deleted
+				if (!_characters[0].name[0] && !_characters[1].name[0] && !_characters[2].name[0] && !_characters[3].name[0]) {
+					_vm->snd_stopSound();
+					return false;
+				}
 			}
 			_vm->_gui->updateBoxFrameHighLight(-1);
 		}


Commit: 2b95dd3213fe4800a3475c055ba7d63b640a8938
    https://github.com/scummvm/scummvm/commit/2b95dd3213fe4800a3475c055ba7d63b640a8938
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:16+01:00

Commit Message:
KYRA: (EOB) - fix unused string

This fixes the "%s can not use this item" string. AFAIK this message never appears. It would require to place an item into a character's hand which he/she can't use and right-click use it. However, when you place such an unusable item in a character's hand the slot will be greyed out/disabled immediately and can no longer be clicked.

Changed paths:
    devtools/create_kyradat/resources/eob1_dos_english.h
    devtools/create_kyradat/resources/eob1_dos_german.h
    devtools/create_kyradat/resources/eob1_dos_italian.h
    devtools/create_kyradat/resources/eob2_dos_english.h
    devtools/create_kyradat/resources/eob2_dos_german.h
    devtools/create_kyradat/resources/eob2_fmtowns_japanese.h
    dists/engine-data/kyra.dat


diff --git a/devtools/create_kyradat/resources/eob1_dos_english.h b/devtools/create_kyradat/resources/eob1_dos_english.h
index 8a9dfeb..4f6861e 100644
--- a/devtools/create_kyradat/resources/eob1_dos_english.h
+++ b/devtools/create_kyradat/resources/eob1_dos_english.h
@@ -341,7 +341,7 @@ static const char *const kEoB1WandStringsDOSEnglish[2] = {
 static const StringListProvider kEoB1WandStringsDOSEnglishProvider = { ARRAYSIZE(kEoB1WandStringsDOSEnglish), kEoB1WandStringsDOSEnglish };
 
 static const char *const kEoB1ItemMisuseStringsDOSEnglish[3] = {
-	" can not use this item.\r",
+	"%s can not use this item.\r",
 	"This item automatically used when worn.\r",
 	"This item is not used in this way.\r"
 };
diff --git a/devtools/create_kyradat/resources/eob1_dos_german.h b/devtools/create_kyradat/resources/eob1_dos_german.h
index ba2e487..8551594 100644
--- a/devtools/create_kyradat/resources/eob1_dos_german.h
+++ b/devtools/create_kyradat/resources/eob1_dos_german.h
@@ -342,7 +342,7 @@ static const char *const kEoB1WandStringsDOSGerman[2] = {
 static const StringListProvider kEoB1WandStringsDOSGermanProvider = { ARRAYSIZE(kEoB1WandStringsDOSGerman), kEoB1WandStringsDOSGerman };
 
 static const char *const kEoB1ItemMisuseStringsDOSGerman[3] = {
-	" kann dies nicht benutzen.\r",
+	"%s kann dies nicht benutzen.\r",
 	"Dies wird automatisch benutzt, wenn angelegt.\r",
 	"Dies wird nicht so benutzt.\r"
 };
diff --git a/devtools/create_kyradat/resources/eob1_dos_italian.h b/devtools/create_kyradat/resources/eob1_dos_italian.h
index 2f6baf5..f2e1a74 100644
--- a/devtools/create_kyradat/resources/eob1_dos_italian.h
+++ b/devtools/create_kyradat/resources/eob1_dos_italian.h
@@ -341,7 +341,7 @@ static const char *const kEoB1WandStringsDOSItalian[2] = {
 static const StringListProvider kEoB1WandStringsDOSItalianProvider = { ARRAYSIZE(kEoB1WandStringsDOSItalian), kEoB1WandStringsDOSItalian };
 
 static const char *const kEoB1ItemMisuseStringsDOSItalian[3] = {
-	" non pu""\x11"" usare quest'oggetto.\r",
+	"%s non pu""\x11"" usare quest'oggetto.\r",
 	"Se indossato quest'oggetto funziona in automatico.\r",
 	"Questo oggetto non si usa cos""\x10"".\r"
 };
diff --git a/devtools/create_kyradat/resources/eob2_dos_english.h b/devtools/create_kyradat/resources/eob2_dos_english.h
index 1bcf794..3fdf26d 100644
--- a/devtools/create_kyradat/resources/eob2_dos_english.h
+++ b/devtools/create_kyradat/resources/eob2_dos_english.h
@@ -246,7 +246,7 @@ static const char *const kEoB2WandStringsDOSEnglish[1] = {
 static const StringListProvider kEoB2WandStringsDOSEnglishProvider = { ARRAYSIZE(kEoB2WandStringsDOSEnglish), kEoB2WandStringsDOSEnglish };
 
 static const char *const kEoB2ItemMisuseStringsDOSEnglish[3] = {
-	" can not use this item.\r",
+	"%s can not use this item.\r",
 	"This item automatically used when worn.\r",
 	"This item is not used in this way.\r"
 };
diff --git a/devtools/create_kyradat/resources/eob2_dos_german.h b/devtools/create_kyradat/resources/eob2_dos_german.h
index 6967eac..6445d13 100644
--- a/devtools/create_kyradat/resources/eob2_dos_german.h
+++ b/devtools/create_kyradat/resources/eob2_dos_german.h
@@ -248,7 +248,7 @@ static const char *const kEoB2WandStringsDOSGerman[1] = {
 static const StringListProvider kEoB2WandStringsDOSGermanProvider = { ARRAYSIZE(kEoB2WandStringsDOSGerman), kEoB2WandStringsDOSGerman };
 
 static const char *const kEoB2ItemMisuseStringsDOSGerman[3] = {
-	" kann diesen Gegenstand nicht nutzen.\r",
+	"%s kann diesen Gegenstand nicht nutzen.\r",
 	"Der Gegenstand wird automatisch beim tragen benutzt.\r",
 	"Das kann man so nicht benutzen.\r"
 };
diff --git a/devtools/create_kyradat/resources/eob2_fmtowns_japanese.h b/devtools/create_kyradat/resources/eob2_fmtowns_japanese.h
index 8e290a3..49a815d 100644
--- a/devtools/create_kyradat/resources/eob2_fmtowns_japanese.h
+++ b/devtools/create_kyradat/resources/eob2_fmtowns_japanese.h
@@ -246,7 +246,7 @@ static const char *const kEoB2WandStringsFMTownsJapanese[1] = {
 static const StringListProvider kEoB2WandStringsFMTownsJapaneseProvider = { ARRAYSIZE(kEoB2WandStringsFMTownsJapanese), kEoB2WandStringsFMTownsJapanese };
 
 static const char *const kEoB2ItemMisuseStringsFMTownsJapanese[3] = {
-	"\x82\xCD\x82\xBB\x82\xCC\x83""A""\x83""C""\x83""e""\x83\x80\x82\xF0\x8E""g""\x82\xA6\x82\xC8\x82\xA2\x81""B\r",
+	"%s""\x82\xCD\x82\xBB\x82\xCC\x83""A""\x83""C""\x83""e""\x83\x80\x82\xF0\x8E""g""\x82\xA6\x82\xC8\x82\xA2\x81""B\r",
 	"\x82\xB1\x82\xCC\x83""A""\x83""C""\x83""e""\x83\x80\x82\xCD\x90""g""\x82\xC9\x82\xC2\x82\xAF\x82\xC4\x82\xA2\x82\xEA\x82\xCE\x8E\xA9\x93\xAE\x93""I""\x82\xC9\x8C\xF8\x89\xCA\x82\xF0\x94\xAD\x8A\xF6\x82\xB7\x82\xE9\x81""B\r",
 	"\x83""A""\x83""C""\x83""e""\x83\x80\x82\xCC\x8E""g""\x82\xA2\x95\xFB\x82\xAA\x8A\xD4\x88\xE1\x82\xC1\x82\xC4\x82\xA2\x82\xE9\x81""B\r"
 };
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 587b29e..8e1fbe9 100644
Binary files a/dists/engine-data/kyra.dat and b/dists/engine-data/kyra.dat differ


Commit: 09c49120344ac5f48c9e651bfa2c1f9e8e5e2e1e
    https://github.com/scummvm/scummvm/commit/09c49120344ac5f48c9e651bfa2c1f9e8e5e2e1e
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:17+01:00

Commit Message:
KYRA: (EOB) - improve comment

Changed paths:
    engines/kyra/graphics/screen.h


diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h
index 44113e4..68f1927 100644
--- a/engines/kyra/graphics/screen.h
+++ b/engines/kyra/graphics/screen.h
@@ -570,7 +570,11 @@ public:
 	static void convertAmigaGfx(uint8 *data, int w, int h, int depth = 5, bool wsa = false, int bytesPerPlane = -1);
 	static void convertAmigaMsc(uint8 *data);
 
-	// RPG specific, this does not belong here
+	// This seems to be a variant of shuffleScreen (which is used in LoK). At the time of coding (and long after that) the
+	// fact that this is a double implementation went unnoticed. My - admittedly limited - efforts to get rid of one of these
+	// implementations were unsatisfactory, though. Each method seems to be optimized to produce accurate results for its
+	// specifc purpose (LoK for shuffleScreen, EoB/LoL for crossFadeRegion). Merging these methods has no priority, since we
+	// can well afford the 20 lines of extra code.
 	void crossFadeRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage);
 
 	uint16 *get16bitPalette() { return _16bitPalette; }


Commit: bc66a1ee82b2aa1466fcfef78416983282a9efd8
    https://github.com/scummvm/scummvm/commit/bc66a1ee82b2aa1466fcfef78416983282a9efd8
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:17+01:00

Commit Message:
KYRA: - minor cleanup

Changed paths:
    engines/kyra/graphics/screen.cpp


diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp
index a07e437..4ceb627 100644
--- a/engines/kyra/graphics/screen.cpp
+++ b/engines/kyra/graphics/screen.cpp
@@ -51,9 +51,7 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system, const ScreenDim *dimTable, co
 	memset(_fonts, 0, sizeof(_fonts));
 
 	memset(_pagePtrs, 0, sizeof(_pagePtrs));
-	// In VGA mode the odd and even page pointers point to the same buffers.
-	for (int i = 0; i < SCREEN_PAGE_NUM; i++)
-		_pageMapping[i] = i & ~1;
+	memset(_pageMapping, 0, sizeof(_pageMapping));
 
 	_renderMode = Common::kRenderDefault;
 	_sjisMixedFontMode = false;
@@ -121,6 +119,9 @@ bool Screen::init() {
 			_renderMode = Common::parseRenderMode(ConfMan.get("render_mode"));
 	}
 
+	// In VGA mode the odd and even page pointers point to the same buffers.
+	for (int i = 0; i < SCREEN_PAGE_NUM; i++)
+		_pageMapping[i] = i & ~1;
 	// CGA and EGA modes use additional pages to do the CGA/EGA specific graphics conversions.
 	if (_vm->game() == GI_EOB1 && (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderEGA)) {
 		for (int i = 0; i < 8; i++)


Commit: 4d934ec30e4199e7cf91885e01f51963032a4637
    https://github.com/scummvm/scummvm/commit/4d934ec30e4199e7cf91885e01f51963032a4637
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:19+01:00

Commit Message:
KYRA: (EOB) - minor save file export fix

(avoid out of bounds strings when importing FM-TOWNS save files)

Changed paths:
    engines/kyra/gui/saveload_eob.cpp


diff --git a/engines/kyra/gui/saveload_eob.cpp b/engines/kyra/gui/saveload_eob.cpp
index 8f2c6e1..c73831e 100644
--- a/engines/kyra/gui/saveload_eob.cpp
+++ b/engines/kyra/gui/saveload_eob.cpp
@@ -1031,7 +1031,7 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 	Common::OutSaveFile *out = new Common::OutSaveFile(nf.createWriteStream());
 
 	if (_flags.gameID == GI_EOB2) {
-		static const char tempStr[31] = "SCUMMVM EXPORT     ";
+		static const char tempStr[31] = "SCUMMVM EXPORT\0";
 		out->write(tempStr, (_flags.platform == Common::kPlatformFMTowns) ? 30 : 20);
 	}
 


Commit: 77a7f02e9ab60ded0dac5b34228272300a1e80c9
    https://github.com/scummvm/scummvm/commit/77a7f02e9ab60ded0dac5b34228272300a1e80c9
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:19+01:00

Commit Message:
KYRA: (EOB) - rename var

Changed paths:
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/sprites_eob.cpp
    engines/kyra/gui/saveload_eob.cpp


diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 9e0fdf0..9078e50 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -196,7 +196,7 @@ struct EoBMonsterInPlay {
 	uint8 animStep;
 	uint8 shpIndex;
 	int8 mode;
-	int8 f_9;
+	int8 stray;
 	int8 curAttackFrame;
 	int8 spellStatusLeft;
 	int16 hitPointsMax;
diff --git a/engines/kyra/engine/sprites_eob.cpp b/engines/kyra/engine/sprites_eob.cpp
index d7bfe74..55e8aaf 100644
--- a/engines/kyra/engine/sprites_eob.cpp
+++ b/engines/kyra/engine/sprites_eob.cpp
@@ -1235,32 +1235,32 @@ void EoBCoreEngine::updateMonsterFollowPath(EoBMonsterInPlay *m, int turnSteps)
 }
 
 void EoBCoreEngine::updateMonstersStraying(EoBMonsterInPlay *m, int a) {
-	if (m->f_9 >= 0) {
-		if (m->f_9 == 0)
+	if (m->stray >= 0) {
+		if (m->stray == 0)
 			updateMonsterFollowPath(m, -a);
 
 		int8 d = (m->dir + a) & 3;
 		uint16 bl = calcNewBlockPosition(m->block, d);
 		uint8 flg = _wllWallFlags[_levelBlockProperties[bl].walls[_dscBlockMap[d]]] & 4;
 
-		if (m->f_9 == 0) {
+		if (m->stray == 0) {
 			if (!flg)
-				m->f_9 = -1;
+				m->stray = -1;
 			return;
 		}
 
 		if (flg) {
 			walkMonsterNextStep(m, -1, d);
-			m->f_9 = -1;
+			m->stray = -1;
 			return;
 		}
 	}
 
 	if (walkMonsterNextStep(m, calcNewBlockPosition(m->block, m->dir), -1)) {
-		m->f_9 = 1;
+		m->stray = 1;
 	} else {
 		walkMonsterNextStep(m, -1, (m->dir - a) & 3);
-		m->f_9 = 0;
+		m->stray = 0;
 	}
 }
 
diff --git a/engines/kyra/gui/saveload_eob.cpp b/engines/kyra/gui/saveload_eob.cpp
index c73831e..713c4cb 100644
--- a/engines/kyra/gui/saveload_eob.cpp
+++ b/engines/kyra/gui/saveload_eob.cpp
@@ -231,7 +231,7 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
 			m->animStep = in.readByte();
 			m->shpIndex = in.readByte();
 			m->mode = in.readSByte();
-			m->f_9 = in.readSByte();
+			m->stray = in.readSByte();
 			m->curAttackFrame = in.readSByte();
 			m->spellStatusLeft = in.readSByte();
 			m->hitPointsMax = in.readSint16BE();
@@ -477,7 +477,7 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName,
 			out->writeByte(m->animStep);
 			out->writeByte(m->shpIndex);
 			out->writeSByte(m->mode);
-			out->writeSByte(m->f_9);
+			out->writeSByte(m->stray);
 			out->writeSByte(m->curAttackFrame);
 			out->writeSByte(m->spellStatusLeft);
 			out->writeSint16BE(m->hitPointsMax);
@@ -833,7 +833,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 			m->animStep = in.readByte();
 			m->shpIndex = in.readByte();
 			m->mode = in.readSByte();
-			m->f_9 = in.readSByte();
+			m->stray = in.readSByte();
 			m->curAttackFrame = in.readSByte();
 			m->spellStatusLeft = in.readSByte();
 			m->hitPointsMax = in.readSint16();
@@ -1192,7 +1192,7 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 			out->writeByte(m->animStep);
 			out->writeByte(m->shpIndex);
 			out->writeSByte(m->mode);
-			out->writeSByte(m->f_9);
+			out->writeSByte(m->stray);
 			out->writeSByte(m->curAttackFrame);
 			out->writeSByte(m->spellStatusLeft);
 			out->writeSint16LE(m->hitPointsMax);


Commit: f0a305316c716dfadc332eb8df4c95a5e6e6cdb6
    https://github.com/scummvm/scummvm/commit/f0a305316c716dfadc332eb8df4c95a5e6e6cdb6
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:20+01:00

Commit Message:
KYRA: (EOB1/Amiga) - add static resources

Changed paths:
  A devtools/create_kyradat/resources/eob1_amiga.h
  A devtools/create_kyradat/resources/eob1_amiga_english.h
  A devtools/create_kyradat/resources/eob1_amiga_german.h
    devtools/create_kyradat/create_kyradat.cpp
    devtools/create_kyradat/create_kyradat.h
    devtools/create_kyradat/games.cpp
    devtools/create_kyradat/resources.cpp
    devtools/create_kyradat/resources/eob1_dos.h
    devtools/create_kyradat/resources/eob1_dos_english.h
    devtools/create_kyradat/resources/eob1_dos_german.h
    devtools/create_kyradat/resources/eob1_dos_italian.h
    devtools/create_kyradat/resources/eob2_dos.h
    devtools/create_kyradat/resources/eob2_fmtowns.h
    dists/engine-data/kyra.dat
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/scene_rpg.cpp
    engines/kyra/resource/resource.h
    engines/kyra/resource/staticres.cpp
    engines/kyra/resource/staticres_eob.cpp


diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp
index 99e36cf..0c43b4f 100644
--- a/devtools/create_kyradat/create_kyradat.cpp
+++ b/devtools/create_kyradat/create_kyradat.cpp
@@ -45,7 +45,7 @@
 
 
 enum {
-	kKyraDatVersion = 92
+	kKyraDatVersion = 93
 };
 
 const ExtractFilename extractFilenames[] = {
@@ -379,6 +379,7 @@ const ExtractFilename extractFilenames[] = {
 	{ kEoBBaseMagicStrings6, kStringList, true },
 	{ kEoBBaseMagicStrings7, kStringList, true },
 	{ kEoBBaseMagicStrings8, kStringList, true },
+	{ kEoBBaseMagicStrings9, kStringList, true },
 
 	{ kEoBBaseExpObjectTlMode, kRawData, false },
 	{ kEoBBaseExpObjectTblIndex, kRawData, false },
@@ -409,7 +410,14 @@ const ExtractFilename extractFilenames[] = {
 	{ kEoBBaseConeOfColdDest4, kRawData, false },
 	{ kEoBBaseConeOfColdGfxTbl, kRawData, false },
 
+	{ kEoBBaseSoundMap, kStringList, false },
+	{ kEoBBaseSoundFilesIntro, kStringList, false },
+	{ kEoBBaseSoundFilesIngame, kStringList, false },
+	{ kEoBBaseSoundFilesFinale, kStringList, false },
+
 	// EYE OF THE BEHOLDER I
+	{ kEoB1LevelSoundFiles1, kStringList, false },
+	{ kEoB1LevelSoundFiles2, kStringList, false },
 	{ kEoB1MainMenuStrings, kStringList, true },
 	{ kEoB1BonusStrings, kStringList, true },
 
@@ -433,7 +441,14 @@ const ExtractFilename extractFilenames[] = {
 	{ kEoB1IntroTvlY2, kRawData, false },
 	{ kEoB1IntroTvlW, kRawData, false },
 	{ kEoB1IntroTvlH, kRawData, false },
-
+	{ kEoB1IntroOrbFadePal, kRawData, false },
+	{ kEoB1FinaleCouncilAnim1, kRawData, false },
+	{ kEoB1FinaleCouncilAnim2, kRawData, false },
+	{ kEoB1FinaleCouncilAnim3, kRawData, false },
+	{ kEoB1FinaleCouncilAnim4, kRawData, false },
+	{ kEoB1FinaleEyesAnim, kRawData, false },
+	{ kEoB1FinaleHandsAnim, kRawDataBe16, false },
+	{ kEoB1FinaleTextDuration, kRawData, false },
 	{ kEoB1DoorShapeDefs, kRawData, false },
 	{ kEoB1DoorSwitchShapeDefs, kRawData, false },
 	{ kEoB1DoorSwitchCoords, kRawData, false },
diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h
index cb70f25..a37fab3 100644
--- a/devtools/create_kyradat/create_kyradat.h
+++ b/devtools/create_kyradat/create_kyradat.h
@@ -382,6 +382,7 @@ enum kExtractID {
 	kEoBBaseMagicStrings6,
 	kEoBBaseMagicStrings7,
 	kEoBBaseMagicStrings8,
+	kEoBBaseMagicStrings9,
 
 	kEoBBaseExpObjectTlMode,
 	kEoBBaseExpObjectTblIndex,
@@ -413,6 +414,13 @@ enum kExtractID {
 	kEoBBaseConeOfColdDest4,
 	kEoBBaseConeOfColdGfxTbl,
 
+	kEoBBaseSoundMap,
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesIngame,
+	kEoBBaseSoundFilesFinale,
+
+	kEoB1LevelSoundFiles1,
+	kEoB1LevelSoundFiles2,
 	kEoB1MainMenuStrings,
 	kEoB1BonusStrings,
 
@@ -436,6 +444,15 @@ enum kExtractID {
 	kEoB1IntroTvlY2,
 	kEoB1IntroTvlW,
 	kEoB1IntroTvlH,
+	kEoB1IntroOrbFadePal,
+
+	kEoB1FinaleCouncilAnim1,
+	kEoB1FinaleCouncilAnim2,
+	kEoB1FinaleCouncilAnim3,
+	kEoB1FinaleCouncilAnim4,
+	kEoB1FinaleEyesAnim,
+	kEoB1FinaleHandsAnim,
+	kEoB1FinaleTextDuration,
 
 	kEoB1DoorShapeDefs,
 	kEoB1DoorSwitchShapeDefs,
diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp
index 077b570..9457416 100644
--- a/devtools/create_kyradat/games.cpp
+++ b/devtools/create_kyradat/games.cpp
@@ -101,6 +101,9 @@ const Game eob1Games[] = {
 	{ kEoB1, kPlatformDOS, kNoSpecial, DE_DEU },
 	{ kEoB1, kPlatformDOS, kNoSpecial, IT_ITA },
 
+	{ kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY },
+	{ kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU },
+
 	//{ kEoB1, kPlatformPC98, kNoSpecial, JA_JPN },
 
 	GAME_DUMMY_ENTRY
@@ -110,6 +113,9 @@ const Game eob2Games[] = {
 	{ kEoB2, kPlatformDOS, kNoSpecial, EN_ANY },
 	{ kEoB2, kPlatformDOS, kNoSpecial, DE_DEU },
 
+	//{ kEoB2, kPlatformAmiga, kNoSpecial, EN_ANY },
+	//{ kEoB2, kPlatformAmiga, kNoSpecial, DE_DEU },
+
 	//{ kEoB2, kPlatformPC98, kNoSpecial, JA_JPN },
 
 	{ kEoB2, kPlatformFMTowns, kNoSpecial, JA_JPN },
@@ -1414,6 +1420,295 @@ const int eob1FloppyNeed[] = {
 	kEoBBaseMonsterDistAttStrings,
 	kEoBBaseEncodeMonsterDefs,
 	kEoBBaseNpcPresets,
+
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesIngame,
+	kEoBBaseSoundFilesFinale,
+
+	-1
+};
+
+const int eob1AmigaNeed[] = {
+	kEoBBaseChargenStrings1,
+	kEoBBaseChargenStrings2,
+	kEoBBaseChargenStartLevels,
+	kEoBBaseChargenStatStrings,
+	kEoBBaseChargenRaceSexStrings,
+	kEoBBaseChargenClassStrings,
+	kEoBBaseChargenAlignmentStrings,
+	kEoBBaseChargenEnterGameStrings,
+	kEoBBaseChargenClassMinStats,
+	kEoBBaseChargenRaceMinStats,
+	kEoBBaseChargenRaceMaxStats,
+
+	kEoBBaseSaveThrowTable1,
+	kEoBBaseSaveThrowTable2,
+	kEoBBaseSaveThrowTable3,
+	kEoBBaseSaveThrowTable4,
+	kEoBBaseSaveThrwLvlIndex,
+	kEoBBaseSaveThrwModDiv,
+	kEoBBaseSaveThrwModExt,
+
+	kEoB1MainMenuStrings,
+	kEoB1BonusStrings,
+
+	kEoB1IntroFilesOpening,
+	kEoB1IntroFilesTower,
+	kEoB1IntroFilesOrb,
+	kEoB1IntroFilesWdEntry,
+	kEoB1IntroFilesKing,
+	kEoB1IntroFilesHands,
+	kEoB1IntroFilesWdExit,
+	kEoB1IntroFilesTunnel,
+	kEoB1IntroOpeningFrmDelay,
+	kEoB1IntroWdEncodeX,
+	kEoB1IntroWdEncodeY,
+	kEoB1IntroWdEncodeWH,
+	kEoB1IntroWdDsX,
+	kEoB1IntroWdDsY,
+	kEoB1IntroTvlX1,
+	kEoB1IntroTvlY1,
+	kEoB1IntroTvlX2,
+	kEoB1IntroTvlY2,
+	kEoB1IntroTvlW,
+	kEoB1IntroTvlH,
+	kEoB1IntroOrbFadePal,
+
+	kEoB1FinaleCouncilAnim1,
+	kEoB1FinaleCouncilAnim2,
+	kEoB1FinaleCouncilAnim3,
+	kEoB1FinaleCouncilAnim4,
+	kEoB1FinaleEyesAnim,
+	kEoB1FinaleHandsAnim,
+	kEoB1FinaleTextDuration,
+
+	kEoB1DoorShapeDefs,
+	kEoB1DoorSwitchShapeDefs,
+	kEoB1DoorSwitchCoords,
+	kEoB1MonsterProperties,
+	kEoB1EnemyMageSpellList,
+	kEoB1EnemyMageSfx,
+	kEoB1BeholderSpellList,
+	kEoB1BeholderSfx,
+	kEoB1TurnUndeadString,
+
+	kEoB1NpcShpData,
+	kEoB1NpcSubShpIndex1,
+	kEoB1NpcSubShpIndex2,
+	kEoB1NpcSubShpY,
+	kEoB1Npc0Strings,
+	kEoB1Npc11Strings,
+	kEoB1Npc12Strings,
+	kEoB1Npc21Strings,
+	kEoB1Npc22Strings,
+	kEoB1Npc31Strings,
+	kEoB1Npc32Strings,
+	kEoB1Npc4Strings,
+	kEoB1Npc5Strings,
+	kEoB1Npc6Strings,
+	kEoB1Npc7Strings,
+
+	kEoBBasePryDoorStrings,
+	kEoBBaseWarningStrings,
+
+	kEoBBaseItemSuffixStringsRings,
+	kEoBBaseItemSuffixStringsPotions,
+	kEoBBaseItemSuffixStringsWands,
+
+	kEoBBaseRipItemStrings,
+	kEoBBaseCursedString,
+	kEoBBaseEnchantedString,
+	kEoBBaseMagicObjectStrings,
+	kEoBBaseMagicObjectString5,
+	kEoBBasePatternSuffix,
+	kEoBBasePatternGrFix1,
+	kEoBBasePatternGrFix2,
+	kEoBBaseValidateArmorString,
+	kEoBBaseValidateNoDropString,
+	kEoBBasePotionStrings,
+	kEoBBaseWandStrings,
+	kEoBBaseItemMisuseStrings,
+
+	kEoBBaseTakenStrings,
+	kEoBBasePotionEffectStrings,
+
+	kEoBBaseYesNoStrings,
+	kRpgCommonMoreStrings,
+	kEoBBaseNpcMaxStrings,
+	kEoBBaseNpcJoinStrings,
+	kEoBBaseCancelStrings,
+
+	kEoBBaseMenuStringsMain,
+	kEoBBaseMenuStringsSaveLoad,
+	kEoBBaseMenuStringsOnOff,
+	kEoBBaseMenuStringsSpells,
+	kEoBBaseMenuStringsRest,
+	kEoBBaseMenuStringsDrop,
+	kEoBBaseMenuStringsExit,
+	kEoBBaseMenuStringsStarve,
+	kEoBBaseMenuStringsScribe,
+	kEoBBaseMenuStringsDrop2,
+	kEoBBaseMenuStringsHead,
+	kEoBBaseMenuStringsPoison,
+	kEoBBaseMenuStringsMgc,
+	kEoBBaseMenuStringsPrefs,
+	kEoBBaseMenuStringsRest2,
+	kEoBBaseMenuStringsRest4,
+	kEoBBaseMenuStringsDefeat,
+	kEoBBaseMenuYesNoStrings,
+
+	kEoBBaseSpellLevelsMage,
+	kEoBBaseSpellLevelsCleric,
+	kEoBBaseNumSpellsCleric,
+	kEoBBaseNumSpellsWisAdj,
+	kEoBBaseNumSpellsPal,
+	kEoBBaseNumSpellsMage,
+
+	kEoBBaseCharGuiStringsHp,
+	kEoBBaseCharGuiStringsWp1,
+	kEoBBaseCharGuiStringsWr,
+	kEoBBaseCharGuiStringsSt1,
+	kEoBBaseCharGuiStringsIn,
+
+	kEoBBaseCharStatusStrings7,
+	kEoBBaseCharStatusStrings81,
+	kEoBBaseCharStatusStrings9,
+	kEoBBaseCharStatusStrings131,
+
+	kEoBBaseLevelGainStrings,
+	kEoBBaseExperienceTable0,
+	kEoBBaseExperienceTable1,
+	kEoBBaseExperienceTable2,
+	kEoBBaseExperienceTable3,
+	kEoBBaseExperienceTable4,
+
+	kEoBBaseBookNumbers,
+	kEoBBaseMageSpellsList,
+	kEoBBaseClericSpellsList,
+	kEoBBaseSpellNames,
+	kEoBBaseMagicStrings1,
+	kEoBBaseMagicStrings2,
+	kEoBBaseMagicStrings3,
+	kEoBBaseMagicStrings4,
+	kEoBBaseMagicStrings6,
+	kEoBBaseMagicStrings7,
+	kEoBBaseMagicStrings8,
+	kEoBBaseMagicStrings9,
+
+	kEoBBaseExpObjectTblIndex,
+	kEoBBaseExpObjectShpStart,
+	kEoBBaseExpObjectTbl1,
+	kEoBBaseExpObjectTbl2,
+	kEoBBaseExpObjectTbl3,
+	kEoBBaseExpObjectY,
+
+	kEoBBaseSparkDefSteps,
+	kEoBBaseSparkDefSubSteps,
+	kEoBBaseSparkDefShift,
+	kEoBBaseSparkDefAdd,
+	kEoBBaseSparkDefX,
+	kEoBBaseSparkDefY,
+	kEoBBaseSparkOfFlags1,
+	kEoBBaseSparkOfFlags2,
+	kEoBBaseSparkOfShift,
+	kEoBBaseSparkOfX,
+	kEoBBaseSparkOfY,
+
+	kEoBBaseSpellProperties,
+	kEoBBaseMagicFlightProps,
+	kEoBBaseTurnUndeadEffect,
+	kEoBBaseBurningHandsDest,
+	kEoBBaseConeOfColdDest1,
+	kEoBBaseConeOfColdDest2,
+	kEoBBaseConeOfColdDest3,
+	kEoBBaseConeOfColdDest4,
+	kEoBBaseConeOfColdGfxTbl,
+
+	kRpgCommonDscDoorShapeIndex,
+	kEoBBaseWllFlagPreset,
+	kEoBBaseDscShapeCoords,
+	kRpgCommonDscDoorScaleOffs,
+	kEoBBaseDscDoorScaleMult1,
+	kEoBBaseDscDoorScaleMult2,
+	kEoBBaseDscDoorScaleMult3,
+	kEoBBaseDscDoorScaleMult4,
+	kEoBBaseDscDoorScaleMult5,
+	kEoBBaseDscDoorScaleMult6,
+	kEoBBaseDscDoorXE,
+	kEoBBaseDscDoorY1,
+	kEoBBaseDscDoorY3,
+	kEoBBaseDscDoorY4,
+	kEoBBaseDscDoorY5,
+	kEoBBaseDscDoorY6,
+	kEoBBaseDscDoorY7,
+	kEoBBaseDscDoorCoordsExt,
+	kRpgCommonDscDoorFrameY1,
+	kRpgCommonDscDoorFrameY2,
+	kRpgCommonDscDoorFrameIndex1,
+	kRpgCommonDscDoorFrameIndex2,
+
+	kEoBBaseDscItemPosIndex,
+	kEoBBaseDscItemShpX,
+	kEoBBaseDscItemScaleIndex,
+	kEoBBaseDscItemTileIndex,
+	kEoBBaseDscItemShapeMap,
+	kEoBBaseDscTelptrShpCoords,
+
+	kEoBBasePortalSeqData,
+	kEoBBaseManDef,
+	kEoBBaseManWord,
+	kEoBBaseManPrompt,
+
+	kEoBBaseDscMonsterFrmOffsTbl1,
+	kEoBBaseDscMonsterFrmOffsTbl2,
+
+	kEoBBaseInvSlotX,
+	kEoBBaseInvSlotY,
+	kEoBBaseSlotValidationFlags,
+
+	kEoBBaseProjectileWeaponTypes,
+	kEoBBaseWandTypes,
+
+	kEoBBaseDrawObjPosIndex,
+	kEoBBaseFlightObjFlipIndex,
+	kEoBBaseFlightObjShpMap,
+	kEoBBaseFlightObjSclIndex,
+
+	kRpgCommonDscShapeIndex,
+	kRpgCommonDscX,
+	kRpgCommonDscTileIndex,
+	kRpgCommonDscDimData1,
+	kRpgCommonDscDimData2,
+	kRpgCommonDscBlockMap,
+	kRpgCommonDscDimMap,
+	kRpgCommonDscBlockIndex,
+
+	kEoBBaseClassModifierFlags,
+
+	kEoBBaseMonsterStepTable01,
+	kEoBBaseMonsterStepTable2,
+	kEoBBaseMonsterStepTable3,
+	kEoBBaseMonsterCloseAttPosTable1,
+	kEoBBaseMonsterCloseAttPosTable21,
+	kEoBBaseMonsterCloseAttChkTable1,
+	kEoBBaseMonsterCloseAttChkTable2,
+	kEoBBaseMonsterCloseAttDstTable1,
+	kEoBBaseMonsterCloseAttDstTable2,
+
+	kEoBBaseMonsterProximityTable,
+	kEoBBaseFindBlockMonstersTable,
+	kEoBBaseMonsterDirChangeTable,
+	kEoBBaseMonsterDistAttStrings,
+	kEoBBaseEncodeMonsterDefs,
+	kEoBBaseNpcPresets,
+
+	kEoBBaseSoundMap,
+	kEoB1LevelSoundFiles1,
+	kEoB1LevelSoundFiles2,
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesIngame,
+	kEoBBaseSoundFilesFinale,
+
 	-1
 };
 
@@ -1588,6 +1883,7 @@ const int eob1PC98Need[] = {
 	kEoBBaseMagicStrings6,
 	kEoBBaseMagicStrings7,
 	kEoBBaseMagicStrings8,
+	//kEoBBaseMagicStrings9,
 
 	kEoBBaseExpObjectTblIndex,
 	kEoBBaseExpObjectShpStart,
@@ -2020,6 +2316,9 @@ const int eob2FloppyNeed[] = {
 	kRpgCommonDscDimMap,
 	kRpgCommonDscBlockIndex,
 
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesFinale,
+
 	-1
 };
 
@@ -2344,6 +2643,9 @@ const int eob2PC98Need[] = {
 	kRpgCommonDscDimMap,
 	kRpgCommonDscBlockIndex,
 
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesFinale,
+
 	-1
 }; 
 
@@ -2901,6 +3203,9 @@ const int eob2FMTownsNeed[] = {
 	kEoB2Ascii2SjisTables,
 	kEoB2Ascii2SjisTables2,
 	kEoB2SaveNamePatterns,
+
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesFinale,
 	kEoB2PcmSoundEffectsIngame,
 	kEoB2PcmSoundEffectsIntro,
 	kEoB2PcmSoundEffectsFinale,
@@ -2954,13 +3259,12 @@ const GameNeed gameNeedTable[] = {
 	{ kLoL, kPlatformDOS, kTalkieVersion, lolCDNeed },
 
 	{ kEoB1, kPlatformDOS, kNoSpecial, eob1FloppyNeed },
-
+	{ kEoB1, kPlatformAmiga, kNoSpecial, eob1AmigaNeed },
 	//{ kEoB1, kPlatformPC98, kNoSpecial, eob1PC98Need },
 
 	{ kEoB2, kPlatformDOS, kNoSpecial, eob2FloppyNeed },
-
+	//{ kEoB2, kPlatformAmiga, kNoSpecial, eob2AmigaNeed },
 	//{ kEoB2, kPlatformPC98, kNoSpecial, eob2PC98Need },
-
 	{ kEoB2, kPlatformFMTowns, kNoSpecial, eob2FMTownsNeed },
 
 	{ -1, -1, -1, 0 }
diff --git a/devtools/create_kyradat/resources.cpp b/devtools/create_kyradat/resources.cpp
index 9b225bf..4de1d41 100644
--- a/devtools/create_kyradat/resources.cpp
+++ b/devtools/create_kyradat/resources.cpp
@@ -94,7 +94,9 @@
 #include "resources/eob1_dos_english.h"
 #include "resources/eob1_dos_german.h"
 #include "resources/eob1_dos_italian.h"
-
+#include "resources/eob1_amiga.h"
+#include "resources/eob1_amiga_english.h"
+#include "resources/eob1_amiga_german.h"
 //#include "resources/eob1_pc98.h"
 //#include "resources/eob1_pc98_japanese.h"
 
@@ -102,10 +104,11 @@
 #include "resources/eob2_dos.h"
 #include "resources/eob2_dos_english.h"
 #include "resources/eob2_dos_german.h"
-
+//#include "resources/eob2_amiga.h"
+//#include "resources/eob2_amiga_english.h"
+//#include "resources/eob2_amiga_german.h"
 //#include "resources/eob2_pc98.h"
 //#include "resources/eob2_pc98_japanese.h"
-
 #include "resources/eob2_fmtowns.h"
 #include "resources/eob2_fmtowns_japanese.h"
 
@@ -1075,6 +1078,7 @@ static const ResourceProvider resourceProviders[] = {
 	{ kEoBBaseMagicStrings6, kEoB1, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB1MagicStrings6DOSEnglishProvider },
 	{ kEoBBaseMagicStrings7, kEoB1, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB1MagicStrings7DOSEnglishProvider },
 	{ kEoBBaseMagicStrings8, kEoB1, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB1MagicStrings8DOSEnglishProvider },
+	//{ kEoBBaseMagicStrings9, kEoB1, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB1MagicStrings9DOSEnglishProvider },
 	{ kEoBBaseExpObjectTblIndex, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1ExpObjectTblIndexDOSProvider },
 	{ kEoBBaseExpObjectShpStart, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1ExpObjectShpStartDOSProvider },
 	{ kEoBBaseExpObjectTbl1, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1ExpObjectTbl1DOSProvider },
@@ -1168,6 +1172,9 @@ static const ResourceProvider resourceProviders[] = {
 	{ kEoBBaseMonsterDistAttStrings, kEoB1, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB1MonsterDistAttStringsDOSEnglishProvider },
 	{ kEoBBaseEncodeMonsterDefs, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1EncodeMonsterDefsDOSProvider },
 	{ kEoBBaseNpcPresets, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1NpcPresetsDOSProvider },
+	{ kEoBBaseSoundFilesIntro, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1SoundFilesIntroDOSProvider },
+	{ kEoBBaseSoundFilesIngame, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1SoundFilesIngameDOSProvider },
+	{ kEoBBaseSoundFilesFinale, kEoB1, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB1SoundFilesFinaleDOSProvider },
 	{ kEoBBaseChargenStrings1, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1ChargenStrings1DOSGermanProvider },
 	{ kEoBBaseChargenStrings2, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1ChargenStrings2DOSGermanProvider },
 	{ kEoBBaseChargenStatStrings, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1ChargenStatStringsDOSGermanProvider },
@@ -1252,6 +1259,7 @@ static const ResourceProvider resourceProviders[] = {
 	{ kEoBBaseMagicStrings6, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1MagicStrings6DOSGermanProvider },
 	{ kEoBBaseMagicStrings7, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1MagicStrings7DOSGermanProvider },
 	{ kEoBBaseMagicStrings8, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1MagicStrings8DOSGermanProvider },
+	//{ kEoBBaseMagicStrings9, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1MagicStrings9DOSGermanProvider },
 	{ kEoBBaseManDef, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1ManDefDOSGermanProvider },
 	{ kEoBBaseManWord, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1ManWordDOSGermanProvider },
 	{ kEoBBaseManPrompt, kEoB1, kPlatformDOS, kNoSpecial, DE_DEU, &kEoB1ManPromptDOSGermanProvider },
@@ -1340,10 +1348,347 @@ static const ResourceProvider resourceProviders[] = {
 	{ kEoBBaseMagicStrings6, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1MagicStrings6DOSItalianProvider },
 	{ kEoBBaseMagicStrings7, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1MagicStrings7DOSItalianProvider },
 	{ kEoBBaseMagicStrings8, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1MagicStrings8DOSItalianProvider },
+	//{ kEoBBaseMagicStrings9, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1MagicStrings9DOSItalianProvider },
 	{ kEoBBaseManDef, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1ManDefDOSItalianProvider },
 	{ kEoBBaseManWord, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1ManWordDOSItalianProvider },
 	{ kEoBBaseManPrompt, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1ManPromptDOSItalianProvider },
 	{ kEoBBaseMonsterDistAttStrings, kEoB1, kPlatformDOS, kNoSpecial, IT_ITA, &kEoB1MonsterDistAttStringsDOSItalianProvider },
+	{ kEoBBaseChargenStrings1, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenStrings1AmigaEnglishProvider },
+	{ kEoBBaseChargenStrings2, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenStrings2AmigaEnglishProvider },
+	{ kEoBBaseChargenStartLevels, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ChargenStartLevelsAmigaProvider },
+	{ kEoBBaseChargenStatStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenStatStringsAmigaEnglishProvider },
+	{ kEoBBaseChargenRaceSexStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenRaceSexStringsAmigaEnglishProvider },
+	{ kEoBBaseChargenClassStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenClassStringsAmigaEnglishProvider },
+	{ kEoBBaseChargenAlignmentStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenAlignmentStringsAmigaEnglishProvider },
+	{ kEoBBaseChargenEnterGameStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ChargenEnterGameStringsAmigaEnglishProvider },
+	{ kEoBBaseChargenClassMinStats, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ChargenClassMinStatsAmigaProvider },
+	{ kEoBBaseChargenRaceMinStats, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ChargenRaceMinStatsAmigaProvider },
+	{ kEoBBaseChargenRaceMaxStats, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ChargenRaceMaxStatsAmigaProvider },
+	{ kEoBBaseSaveThrowTable1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrowTable1AmigaProvider },
+	{ kEoBBaseSaveThrowTable2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrowTable2AmigaProvider },
+	{ kEoBBaseSaveThrowTable3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrowTable3AmigaProvider },
+	{ kEoBBaseSaveThrowTable4, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrowTable4AmigaProvider },
+	{ kEoBBaseSaveThrwLvlIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrwLvlIndexAmigaProvider },
+	{ kEoBBaseSaveThrwModDiv, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrwModDivAmigaProvider },
+	{ kEoBBaseSaveThrwModExt, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SaveThrwModExtAmigaProvider },
+	{ kEoB1MainMenuStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MainMenuStringsAmigaEnglishProvider },
+	{ kEoB1BonusStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1BonusStringsAmigaEnglishProvider },
+	{ kEoB1IntroFilesOpening, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesOpeningAmigaProvider },
+	{ kEoB1IntroFilesTower, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesTowerAmigaProvider },
+	{ kEoB1IntroFilesOrb, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesOrbAmigaProvider },
+	{ kEoB1IntroFilesWdEntry, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesWdEntryAmigaProvider },
+	{ kEoB1IntroFilesKing, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesKingAmigaProvider },
+	{ kEoB1IntroFilesHands, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesHandsAmigaProvider },
+	{ kEoB1IntroFilesWdExit, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesWdExitAmigaProvider },
+	{ kEoB1IntroFilesTunnel, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroFilesTunnelAmigaProvider },
+	{ kEoB1IntroOpeningFrmDelay, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroOpeningFrmDelayAmigaProvider },
+	{ kEoB1IntroWdEncodeX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroWdEncodeXAmigaProvider },
+	{ kEoB1IntroWdEncodeY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroWdEncodeYAmigaProvider },
+	{ kEoB1IntroWdEncodeWH, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroWdEncodeWHAmigaProvider },
+	{ kEoB1IntroWdDsX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroWdDsXAmigaProvider },
+	{ kEoB1IntroWdDsY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroWdDsYAmigaProvider },
+	{ kEoB1IntroTvlX1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroTvlX1AmigaProvider },
+	{ kEoB1IntroTvlY1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroTvlY1AmigaProvider },
+	{ kEoB1IntroTvlX2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroTvlX2AmigaProvider },
+	{ kEoB1IntroTvlY2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroTvlY2AmigaProvider },
+	{ kEoB1IntroTvlW, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroTvlWAmigaProvider },
+	{ kEoB1IntroTvlH, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroTvlHAmigaProvider },
+	{ kEoB1IntroOrbFadePal, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1IntroOrbFadePalAmigaProvider },
+	{ kEoB1FinaleCouncilAnim1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1CouncilAnimData1AmigaProvider },
+	{ kEoB1FinaleCouncilAnim2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1CouncilAnimData2AmigaProvider },
+	{ kEoB1FinaleCouncilAnim3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1CouncilAnimData3AmigaProvider },
+	{ kEoB1FinaleCouncilAnim4, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1CouncilAnimData4AmigaProvider },
+	{ kEoB1FinaleEyesAnim, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1EyesAnimDataAmigaProvider },
+	{ kEoB1FinaleHandsAnim, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1HandsAnimDataAmigaProvider },
+	{ kEoB1FinaleTextDuration, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1TextFrameDurationAmigaProvider },
+	{ kEoB1DoorShapeDefs, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DoorShapeDefsAmigaProvider },
+	{ kEoB1DoorSwitchShapeDefs, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DoorSwitchShapeDefsAmigaProvider },
+	{ kEoB1DoorSwitchCoords, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DoorSwitchCoordsAmigaProvider },
+	{ kEoB1MonsterProperties, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterPropertiesAmigaProvider },
+	{ kEoB1EnemyMageSpellList, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1EnemyMageSpellListAmigaProvider },
+	{ kEoB1EnemyMageSfx, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1EnemyMageSfxAmigaProvider },
+	{ kEoB1BeholderSpellList, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1BeholderSpellListAmigaProvider },
+	{ kEoB1BeholderSfx, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1BeholderSfxAmigaProvider },
+	{ kEoB1TurnUndeadString, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1TurnUndeadStringAmigaEnglishProvider },
+	{ kEoB1NpcShpData, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NpcShpDataAmigaProvider },
+	{ kEoB1NpcSubShpIndex1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NpcSubShpIndex1AmigaProvider },
+	{ kEoB1NpcSubShpIndex2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NpcSubShpIndex2AmigaProvider },
+	{ kEoB1NpcSubShpY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NpcSubShpYAmigaProvider },
+	{ kEoB1Npc0Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc0StringsAmigaEnglishProvider },
+	{ kEoB1Npc11Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc11StringsAmigaEnglishProvider },
+	{ kEoB1Npc12Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc12StringsAmigaEnglishProvider },
+	{ kEoB1Npc21Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc21StringsAmigaEnglishProvider },
+	{ kEoB1Npc22Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc22StringsAmigaEnglishProvider },
+	{ kEoB1Npc31Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc31StringsAmigaEnglishProvider },
+	{ kEoB1Npc32Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc32StringsAmigaEnglishProvider },
+	{ kEoB1Npc4Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc4StringsAmigaEnglishProvider },
+	{ kEoB1Npc5Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc5StringsAmigaEnglishProvider },
+	{ kEoB1Npc6Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc6StringsAmigaEnglishProvider },
+	{ kEoB1Npc7Strings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1Npc7StringsAmigaEnglishProvider },
+	{ kEoBBasePryDoorStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1PryDoorStringsAmigaEnglishProvider },
+	{ kEoBBaseWarningStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1WarningStringsAmigaEnglishProvider },
+	{ kEoBBaseItemSuffixStringsRings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ItemSuffixStringsRingsAmigaEnglishProvider },
+	{ kEoBBaseItemSuffixStringsPotions, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ItemSuffixStringsPotionsAmigaEnglishProvider },
+	{ kEoBBaseItemSuffixStringsWands, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ItemSuffixStringsWandsAmigaEnglishProvider },
+	{ kEoBBaseRipItemStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1RipItemStringsAmigaEnglishProvider },
+	{ kEoBBaseCursedString, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CursedStringAmigaEnglishProvider },
+	{ kEoBBaseEnchantedString, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1EnchantedStringAmigaProvider },
+	{ kEoBBaseMagicObjectStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicObjectStringsAmigaEnglishProvider },
+	{ kEoBBaseMagicObjectString5, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicObjectString5AmigaEnglishProvider },
+	{ kEoBBasePatternSuffix, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1PatternSuffixAmigaEnglishProvider },
+	{ kEoBBasePatternGrFix1, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1PatternGrFix1AmigaEnglishProvider },
+	{ kEoBBasePatternGrFix2, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1PatternGrFix2AmigaEnglishProvider },
+	{ kEoBBaseValidateArmorString, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ValidateArmorStringAmigaEnglishProvider },
+	{ kEoBBaseValidateNoDropString, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ValidateNoDropStringAmigaEnglishProvider },
+	{ kEoBBasePotionStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1PotionStringsAmigaEnglishProvider },
+	{ kEoBBaseWandStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1WandStringsAmigaEnglishProvider },
+	{ kEoBBaseItemMisuseStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ItemMisuseStringsAmigaEnglishProvider },
+	{ kEoBBaseTakenStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1TakenStringsAmigaEnglishProvider },
+	{ kEoBBasePotionEffectStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1PotionEffectStringsAmigaEnglishProvider },
+	{ kEoBBaseYesNoStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1YesNoStringsAmigaEnglishProvider },
+	{ kRpgCommonMoreStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MoreStringsAmigaEnglishProvider },
+	{ kEoBBaseNpcMaxStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1NpcMaxStringsAmigaEnglishProvider },
+	{ kEoBBaseNpcJoinStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1NpcJoinStringsAmigaEnglishProvider },
+	{ kEoBBaseCancelStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CancelStringsAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsMain, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsMainAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsSaveLoad, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsSaveLoadAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsOnOff, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsOnOffAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsSpells, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsSpellsAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsRest, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsRestAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsDrop, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsDropAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsExit, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsExitAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsStarve, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsStarveAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsScribe, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsScribeAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsDrop2, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsDrop2AmigaEnglishProvider },
+	{ kEoBBaseMenuStringsHead, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsHeadAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsPoison, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsPoisonAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsMgc, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsMgcAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsPrefs, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsPrefsAmigaEnglishProvider },
+	{ kEoBBaseMenuStringsRest2, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsRest2AmigaEnglishProvider },
+	{ kEoBBaseMenuStringsRest4, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsRest4AmigaEnglishProvider },
+	{ kEoBBaseMenuStringsDefeat, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuStringsDefeatAmigaEnglishProvider },
+	{ kEoBBaseMenuYesNoStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MenuYesNoStringsAmigaEnglishProvider },
+	{ kEoBBaseSpellLevelsMage, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SpellLevelsMageAmigaProvider },
+	{ kEoBBaseSpellLevelsCleric, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SpellLevelsClericAmigaProvider },
+	{ kEoBBaseNumSpellsCleric, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NumSpellsClericAmigaProvider },
+	{ kEoBBaseNumSpellsWisAdj, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NumSpellsWisAdjAmigaProvider },
+	{ kEoBBaseNumSpellsPal, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NumSpellsPalAmigaProvider },
+	{ kEoBBaseNumSpellsMage, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NumSpellsMageAmigaProvider },
+	{ kEoBBaseCharGuiStringsHp, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharGuiStringsHpAmigaEnglishProvider },
+	{ kEoBBaseCharGuiStringsWp1, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharGuiStringsWp1AmigaEnglishProvider },
+	{ kEoBBaseCharGuiStringsWr, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharGuiStringsWrAmigaEnglishProvider },
+	{ kEoBBaseCharGuiStringsSt1, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharGuiStringsSt1AmigaEnglishProvider },
+	{ kEoBBaseCharGuiStringsIn, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharGuiStringsInAmigaEnglishProvider },
+	{ kEoBBaseCharStatusStrings7, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharStatusStrings7AmigaEnglishProvider },
+	{ kEoBBaseCharStatusStrings81, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharStatusStrings81AmigaEnglishProvider },
+	{ kEoBBaseCharStatusStrings9, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharStatusStrings9AmigaEnglishProvider },
+	{ kEoBBaseCharStatusStrings131, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1CharStatusStrings131AmigaEnglishProvider },
+	{ kEoBBaseLevelGainStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1LevelGainStringsAmigaEnglishProvider },
+	{ kEoBBaseExperienceTable0, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExperienceTable0AmigaProvider },
+	{ kEoBBaseExperienceTable1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExperienceTable1AmigaProvider },
+	{ kEoBBaseExperienceTable2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExperienceTable2AmigaProvider },
+	{ kEoBBaseExperienceTable3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExperienceTable3AmigaProvider },
+	{ kEoBBaseExperienceTable4, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExperienceTable4AmigaProvider },
+	{ kEoBBaseBookNumbers, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1BookNumbersAmigaEnglishProvider },
+	{ kEoBBaseMageSpellsList, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MageSpellsListAmigaEnglishProvider },
+	{ kEoBBaseClericSpellsList, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ClericSpellsListAmigaEnglishProvider },
+	{ kEoBBaseSpellNames, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1SpellNamesAmigaEnglishProvider },
+	{ kEoBBaseMagicStrings1, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings1AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings2, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings2AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings3, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings3AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings4, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings4AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings6, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings6AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings7, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings7AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings8, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings8AmigaEnglishProvider },
+	{ kEoBBaseMagicStrings9, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MagicStrings9AmigaEnglishProvider },
+	{ kEoBBaseExpObjectTblIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExpObjectTblIndexAmigaProvider },
+	{ kEoBBaseExpObjectShpStart, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExpObjectShpStartAmigaProvider },
+	{ kEoBBaseExpObjectTbl1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExpObjectTbl1AmigaProvider },
+	{ kEoBBaseExpObjectTbl2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExpObjectTbl2AmigaProvider },
+	{ kEoBBaseExpObjectTbl3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExpObjectTbl3AmigaProvider },
+	{ kEoBBaseExpObjectY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ExpObjectYAmigaProvider },
+	{ kEoBBaseSparkDefSteps, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkDefStepsAmigaProvider },
+	{ kEoBBaseSparkDefSubSteps, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkDefSubStepsAmigaProvider },
+	{ kEoBBaseSparkDefShift, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkDefShiftAmigaProvider },
+	{ kEoBBaseSparkDefAdd, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkDefAddAmigaProvider },
+	{ kEoBBaseSparkDefX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkDefXAmigaProvider },
+	{ kEoBBaseSparkDefY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkDefYAmigaProvider },
+	{ kEoBBaseSparkOfFlags1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkOfFlags1AmigaProvider },
+	{ kEoBBaseSparkOfFlags2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkOfFlags2AmigaProvider },
+	{ kEoBBaseSparkOfShift, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkOfShiftAmigaProvider },
+	{ kEoBBaseSparkOfX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkOfXAmigaProvider },
+	{ kEoBBaseSparkOfY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SparkOfYAmigaProvider },
+	{ kEoBBaseSpellProperties, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SpellPropertiesAmigaProvider },
+	{ kEoBBaseMagicFlightProps, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MagicFlightPropsAmigaProvider },
+	{ kEoBBaseTurnUndeadEffect, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1TurnUndeadEffectAmigaProvider },
+	{ kEoBBaseBurningHandsDest, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1BurningHandsDestAmigaProvider },
+	{ kEoBBaseConeOfColdDest1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ConeOfColdDest1AmigaProvider },
+	{ kEoBBaseConeOfColdDest2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ConeOfColdDest2AmigaProvider },
+	{ kEoBBaseConeOfColdDest3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ConeOfColdDest3AmigaProvider },
+	{ kEoBBaseConeOfColdDest4, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ConeOfColdDest4AmigaProvider },
+	{ kEoBBaseConeOfColdGfxTbl, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ConeOfColdGfxTblAmigaProvider },
+	{ kRpgCommonDscDoorShapeIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorShapeIndexAmigaProvider },
+	{ kEoBBaseWllFlagPreset, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1WllFlagPresetAmigaProvider },
+	{ kEoBBaseDscShapeCoords, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscShapeCoordsAmigaProvider },
+	{ kRpgCommonDscDoorScaleOffs, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleOffsAmigaProvider },
+	{ kEoBBaseDscDoorScaleMult1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleMult1AmigaProvider },
+	{ kEoBBaseDscDoorScaleMult2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleMult2AmigaProvider },
+	{ kEoBBaseDscDoorScaleMult3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleMult3AmigaProvider },
+	{ kEoBBaseDscDoorScaleMult4, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleMult4AmigaProvider },
+	{ kEoBBaseDscDoorScaleMult5, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleMult5AmigaProvider },
+	{ kEoBBaseDscDoorScaleMult6, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorScaleMult6AmigaProvider },
+	{ kEoBBaseDscDoorXE, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorXEAmigaProvider },
+	{ kEoBBaseDscDoorY1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorY1AmigaProvider },
+	{ kEoBBaseDscDoorY3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorY3AmigaProvider },
+	{ kEoBBaseDscDoorY4, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorY4AmigaProvider },
+	{ kEoBBaseDscDoorY5, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorY5AmigaProvider },
+	{ kEoBBaseDscDoorY6, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorY6AmigaProvider },
+	{ kEoBBaseDscDoorY7, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorY7AmigaProvider },
+	{ kEoBBaseDscDoorCoordsExt, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorCoordsExtAmigaProvider },
+	{ kRpgCommonDscDoorFrameY1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorFrameY1AmigaProvider },
+	{ kRpgCommonDscDoorFrameY2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorFrameY2AmigaProvider },
+	{ kRpgCommonDscDoorFrameIndex1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorFrameIndex1AmigaProvider },
+	{ kRpgCommonDscDoorFrameIndex2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDoorFrameIndex2AmigaProvider },
+	{ kEoBBaseDscItemPosIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscItemPosIndexAmigaProvider },
+	{ kEoBBaseDscItemShpX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscItemShpXAmigaProvider },
+	{ kEoBBaseDscItemScaleIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscItemScaleIndexAmigaProvider },
+	{ kEoBBaseDscItemTileIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscItemTileIndexAmigaProvider },
+	{ kEoBBaseDscItemShapeMap, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscItemShapeMapAmigaProvider },
+	{ kEoBBaseDscTelptrShpCoords, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscTelptrShpCoordsAmigaProvider },
+	{ kEoBBasePortalSeqData, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1PortalSeqDataAmigaProvider },
+	{ kEoBBaseManDef, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ManDefAmigaEnglishProvider },
+	{ kEoBBaseManWord, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ManWordAmigaEnglishProvider },
+	{ kEoBBaseManPrompt, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1ManPromptAmigaEnglishProvider },
+	{ kEoBBaseDscMonsterFrmOffsTbl1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscMonsterFrmOffsTbl1AmigaProvider },
+	{ kEoBBaseDscMonsterFrmOffsTbl2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscMonsterFrmOffsTbl2AmigaProvider },
+	{ kEoBBaseInvSlotX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1InvSlotXAmigaProvider },
+	{ kEoBBaseInvSlotY, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1InvSlotYAmigaProvider },
+	{ kEoBBaseSlotValidationFlags, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SlotValidationFlagsAmigaProvider },
+	{ kEoBBaseProjectileWeaponTypes, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ProjectileWeaponTypesAmigaProvider },
+	{ kEoBBaseWandTypes, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1WandTypesAmigaProvider },
+	{ kEoBBaseDrawObjPosIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DrawObjPosIndexAmigaProvider },
+	{ kEoBBaseFlightObjFlipIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1FlightObjFlipIndexAmigaProvider },
+	{ kEoBBaseFlightObjShpMap, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1FlightObjShpMapAmigaProvider },
+	{ kEoBBaseFlightObjSclIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1FlightObjSclIndexAmigaProvider },
+	{ kRpgCommonDscShapeIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscShapeIndexAmigaProvider },
+	{ kRpgCommonDscX, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscXAmigaProvider },
+	{ kRpgCommonDscTileIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscTileIndexAmigaProvider },
+	{ kRpgCommonDscDimData1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDimData1AmigaProvider },
+	{ kRpgCommonDscDimData2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDimData2AmigaProvider },
+	{ kRpgCommonDscBlockMap, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscBlockMapAmigaProvider },
+	{ kRpgCommonDscDimMap, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscDimMapAmigaProvider },
+	{ kRpgCommonDscBlockIndex, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1DscBlockIndexAmigaProvider },
+	{ kEoBBaseClassModifierFlags, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1ClassModifierFlagsAmigaProvider },
+	{ kEoBBaseMonsterStepTable01, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterStepTable01AmigaProvider },
+	{ kEoBBaseMonsterStepTable2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterStepTable2AmigaProvider },
+	{ kEoBBaseMonsterStepTable3, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterStepTable3AmigaProvider },
+	{ kEoBBaseMonsterCloseAttPosTable1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterCloseAttPosTable1AmigaProvider },
+	{ kEoBBaseMonsterCloseAttPosTable21, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterCloseAttPosTable21AmigaProvider },
+	{ kEoBBaseMonsterCloseAttChkTable1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterCloseAttChkTable1AmigaProvider },
+	{ kEoBBaseMonsterCloseAttChkTable2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterCloseAttChkTable2AmigaProvider },
+	{ kEoBBaseMonsterCloseAttDstTable1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterCloseAttDstTable1AmigaProvider },
+	{ kEoBBaseMonsterCloseAttDstTable2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterCloseAttDstTable2AmigaProvider },
+	{ kEoBBaseMonsterProximityTable, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterProximityTableAmigaProvider },
+	{ kEoBBaseFindBlockMonstersTable, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1FindBlockMonstersTableAmigaProvider },
+	{ kEoBBaseMonsterDirChangeTable, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1MonsterDirChangeTableAmigaProvider },
+	{ kEoBBaseMonsterDistAttStrings, kEoB1, kPlatformAmiga, kNoSpecial, EN_ANY, &kEoB1MonsterDistAttStringsAmigaEnglishProvider },
+	{ kEoBBaseEncodeMonsterDefs, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1EncodeMonsterDefsAmigaProvider },
+	{ kEoBBaseNpcPresets, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1NpcPresetsAmigaProvider },
+	{ kEoBBaseSoundMap, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SoundMapAmigaProvider },
+	{ kEoB1LevelSoundFiles1, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1LevelSoundFiles1AmigaProvider },
+	{ kEoB1LevelSoundFiles2, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1LevelSoundFiles2AmigaProvider },
+	{ kEoBBaseSoundFilesIntro, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SoundFilesIntroAmigaProvider },
+	{ kEoBBaseSoundFilesIngame, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SoundFilesIngameAmigaProvider },
+	{ kEoBBaseSoundFilesFinale, kEoB1, kPlatformAmiga, kNoSpecial, UNK_LANG, &kEoB1SoundFilesFinaleAmigaProvider },
+	{ kEoBBaseChargenStrings1, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenStrings1AmigaGermanProvider },
+	{ kEoBBaseChargenStrings2, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenStrings2AmigaGermanProvider },
+	{ kEoBBaseChargenStatStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenStatStringsAmigaGermanProvider },
+	{ kEoBBaseChargenRaceSexStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenRaceSexStringsAmigaGermanProvider },
+	{ kEoBBaseChargenClassStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenClassStringsAmigaGermanProvider },
+	{ kEoBBaseChargenAlignmentStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenAlignmentStringsAmigaGermanProvider },
+	{ kEoBBaseChargenEnterGameStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ChargenEnterGameStringsAmigaGermanProvider },
+	{ kEoB1MainMenuStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MainMenuStringsAmigaGermanProvider },
+	{ kEoB1BonusStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1BonusStringsAmigaGermanProvider },
+	{ kEoB1TurnUndeadString, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1TurnUndeadStringAmigaGermanProvider },
+	{ kEoB1Npc0Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc0StringsAmigaGermanProvider },
+	{ kEoB1Npc11Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc11StringsAmigaGermanProvider },
+	{ kEoB1Npc12Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc12StringsAmigaGermanProvider },
+	{ kEoB1Npc21Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc21StringsAmigaGermanProvider },
+	{ kEoB1Npc22Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc22StringsAmigaGermanProvider },
+	{ kEoB1Npc31Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc31StringsAmigaGermanProvider },
+	{ kEoB1Npc32Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc32StringsAmigaGermanProvider },
+	{ kEoB1Npc4Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc4StringsAmigaGermanProvider },
+	{ kEoB1Npc5Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc5StringsAmigaGermanProvider },
+	{ kEoB1Npc6Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc6StringsAmigaGermanProvider },
+	{ kEoB1Npc7Strings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1Npc7StringsAmigaGermanProvider },
+	{ kEoBBasePryDoorStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1PryDoorStringsAmigaGermanProvider },
+	{ kEoBBaseWarningStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1WarningStringsAmigaGermanProvider },
+	{ kEoBBaseItemSuffixStringsRings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ItemSuffixStringsRingsAmigaGermanProvider },
+	{ kEoBBaseItemSuffixStringsPotions, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ItemSuffixStringsPotionsAmigaGermanProvider },
+	{ kEoBBaseItemSuffixStringsWands, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ItemSuffixStringsWandsAmigaGermanProvider },
+	{ kEoBBaseRipItemStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1RipItemStringsAmigaGermanProvider },
+	{ kEoBBaseCursedString, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CursedStringAmigaGermanProvider },
+	{ kEoBBaseMagicObjectStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicObjectStringsAmigaGermanProvider },
+	{ kEoBBaseMagicObjectString5, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicObjectString5AmigaGermanProvider },
+	{ kEoBBasePatternSuffix, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1PatternSuffixAmigaGermanProvider },
+	{ kEoBBasePatternGrFix1, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1PatternGrFix1AmigaGermanProvider },
+	{ kEoBBasePatternGrFix2, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1PatternGrFix2AmigaGermanProvider },
+	{ kEoBBaseValidateArmorString, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ValidateArmorStringAmigaGermanProvider },
+	{ kEoBBaseValidateNoDropString, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ValidateNoDropStringAmigaGermanProvider },
+	{ kEoBBasePotionStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1PotionStringsAmigaGermanProvider },
+	{ kEoBBaseWandStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1WandStringsAmigaGermanProvider },
+	{ kEoBBaseItemMisuseStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ItemMisuseStringsAmigaGermanProvider },
+	{ kEoBBaseTakenStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1TakenStringsAmigaGermanProvider },
+	{ kEoBBasePotionEffectStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1PotionEffectStringsAmigaGermanProvider },
+	{ kEoBBaseYesNoStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1YesNoStringsAmigaGermanProvider },
+	{ kRpgCommonMoreStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MoreStringsAmigaGermanProvider },
+	{ kEoBBaseNpcMaxStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1NpcMaxStringsAmigaGermanProvider },
+	{ kEoBBaseNpcJoinStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1NpcJoinStringsAmigaGermanProvider },
+	{ kEoBBaseCancelStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CancelStringsAmigaGermanProvider },
+	{ kEoBBaseMenuStringsMain, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsMainAmigaGermanProvider },
+	{ kEoBBaseMenuStringsSaveLoad, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsSaveLoadAmigaGermanProvider },
+	{ kEoBBaseMenuStringsOnOff, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsOnOffAmigaGermanProvider },
+	{ kEoBBaseMenuStringsSpells, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsSpellsAmigaGermanProvider },
+	{ kEoBBaseMenuStringsRest, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsRestAmigaGermanProvider },
+	{ kEoBBaseMenuStringsDrop, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsDropAmigaGermanProvider },
+	{ kEoBBaseMenuStringsExit, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsExitAmigaGermanProvider },
+	{ kEoBBaseMenuStringsStarve, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsStarveAmigaGermanProvider },
+	{ kEoBBaseMenuStringsScribe, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsScribeAmigaGermanProvider },
+	{ kEoBBaseMenuStringsDrop2, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsDrop2AmigaGermanProvider },
+	{ kEoBBaseMenuStringsHead, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsHeadAmigaGermanProvider },
+	{ kEoBBaseMenuStringsPoison, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsPoisonAmigaGermanProvider },
+	{ kEoBBaseMenuStringsMgc, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsMgcAmigaGermanProvider },
+	{ kEoBBaseMenuStringsPrefs, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsPrefsAmigaGermanProvider },
+	{ kEoBBaseMenuStringsRest2, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsRest2AmigaGermanProvider },
+	{ kEoBBaseMenuStringsRest4, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsRest4AmigaGermanProvider },
+	{ kEoBBaseMenuStringsDefeat, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuStringsDefeatAmigaGermanProvider },
+	{ kEoBBaseMenuYesNoStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MenuYesNoStringsAmigaGermanProvider },
+	{ kEoBBaseCharGuiStringsHp, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharGuiStringsHpAmigaGermanProvider },
+	{ kEoBBaseCharGuiStringsWp1, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharGuiStringsWp1AmigaGermanProvider },
+	{ kEoBBaseCharGuiStringsWr, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharGuiStringsWrAmigaGermanProvider },
+	{ kEoBBaseCharGuiStringsSt1, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharGuiStringsSt1AmigaGermanProvider },
+	{ kEoBBaseCharGuiStringsIn, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharGuiStringsInAmigaGermanProvider },
+	{ kEoBBaseCharStatusStrings7, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharStatusStrings7AmigaGermanProvider },
+	{ kEoBBaseCharStatusStrings81, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharStatusStrings81AmigaGermanProvider },
+	{ kEoBBaseCharStatusStrings9, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharStatusStrings9AmigaGermanProvider },
+	{ kEoBBaseCharStatusStrings131, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1CharStatusStrings131AmigaGermanProvider },
+	{ kEoBBaseLevelGainStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1LevelGainStringsAmigaGermanProvider },
+	{ kEoBBaseBookNumbers, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1BookNumbersAmigaGermanProvider },
+	{ kEoBBaseMageSpellsList, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MageSpellsListAmigaGermanProvider },
+	{ kEoBBaseClericSpellsList, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ClericSpellsListAmigaGermanProvider },
+	{ kEoBBaseSpellNames, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1SpellNamesAmigaGermanProvider },
+	{ kEoBBaseMagicStrings1, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings1AmigaGermanProvider },
+	{ kEoBBaseMagicStrings2, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings2AmigaGermanProvider },
+	{ kEoBBaseMagicStrings3, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings3AmigaGermanProvider },
+	{ kEoBBaseMagicStrings4, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings4AmigaGermanProvider },
+	{ kEoBBaseMagicStrings6, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings6AmigaGermanProvider },
+	{ kEoBBaseMagicStrings7, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings7AmigaGermanProvider },
+	{ kEoBBaseMagicStrings8, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings8AmigaGermanProvider },
+	{ kEoBBaseMagicStrings9, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MagicStrings9AmigaGermanProvider },
+	{ kEoBBaseManDef, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ManDefAmigaGermanProvider },
+	{ kEoBBaseManWord, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ManWordAmigaGermanProvider },
+	{ kEoBBaseManPrompt, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1ManPromptAmigaGermanProvider },
+	{ kEoBBaseMonsterDistAttStrings, kEoB1, kPlatformAmiga, kNoSpecial, DE_DEU, &kEoB1MonsterDistAttStringsAmigaGermanProvider },
 	{ kEoBBaseChargenStrings1, kEoB2, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB2ChargenStrings1DOSEnglishProvider },
 	{ kEoBBaseChargenStrings2, kEoB2, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB2ChargenStrings2DOSEnglishProvider },
 	{ kEoBBaseChargenStartLevels, kEoB2, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB2ChargenStartLevelsDOSProvider },
@@ -1611,6 +1956,8 @@ static const ResourceProvider resourceProviders[] = {
 	{ kEoBBaseMonsterDistAttStrings, kEoB2, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB2MonsterDistAttStringsDOSEnglishProvider },
 	{ kEoBBaseEncodeMonsterDefs, kEoB2, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB2EncodeMonsterDefsDOSProvider },
 	{ kEoBBaseNpcPresets, kEoB2, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB2NpcPresetsDOSProvider },
+	{ kEoBBaseSoundFilesIntro, kEoB2, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB2SoundFilesIntroDOSProvider },
+	{ kEoBBaseSoundFilesFinale, kEoB2, kPlatformDOS, kNoSpecial, UNK_LANG, &kEoB2SoundFilesFinaleDOSProvider },
 	{ kEoB2Npc1Strings, kEoB2, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB2Npc1StringsDOSEnglishProvider },
 	{ kEoB2Npc2Strings, kEoB2, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB2Npc2StringsDOSEnglishProvider },
 	{ kEoB2MonsterDustStrings, kEoB2, kPlatformDOS, kNoSpecial, EN_ANY, &kEoB2MonsterDustStringsDOSEnglishProvider },
@@ -2005,6 +2352,8 @@ static const ResourceProvider resourceProviders[] = {
 	{ kEoBBaseMonsterDirChangeTable, kEoB2, kPlatformFMTowns, kNoSpecial, UNK_LANG, &kEoB2MonsterDirChangeTableFMTownsProvider },
 	{ kEoBBaseMonsterDistAttStrings, kEoB2, kPlatformFMTowns, kNoSpecial, JA_JPN, &kEoB2MonsterDistAttStringsFMTownsJapaneseProvider },
 	{ kEoBBaseNpcPresets, kEoB2, kPlatformFMTowns, kNoSpecial, UNK_LANG, &kEoB2NpcPresetsFMTownsProvider },
+	{ kEoBBaseSoundFilesIntro, kEoB2, kPlatformFMTowns, kNoSpecial, UNK_LANG, &kEoB2SoundFilesIntroFMTownsProvider },
+	{ kEoBBaseSoundFilesFinale, kEoB2, kPlatformFMTowns, kNoSpecial, UNK_LANG, &kEoB2SoundFilesFinaleFMTownsProvider },
 	{ kEoB2Npc1Strings, kEoB2, kPlatformFMTowns, kNoSpecial, JA_JPN, &kEoB2Npc1StringsFMTownsJapaneseProvider },
 	{ kEoB2Npc2Strings, kEoB2, kPlatformFMTowns, kNoSpecial, JA_JPN, &kEoB2Npc2StringsFMTownsJapaneseProvider },
 	{ kEoB2MonsterDustStrings, kEoB2, kPlatformFMTowns, kNoSpecial, JA_JPN, &kEoB2MonsterDustStringsFMTownsJapaneseProvider },
diff --git a/devtools/create_kyradat/resources/eob1_amiga.h b/devtools/create_kyradat/resources/eob1_amiga.h
new file mode 100644
index 0000000..b0ca527
--- /dev/null
+++ b/devtools/create_kyradat/resources/eob1_amiga.h
@@ -0,0 +1,1952 @@
+static const byte kEoB1ChargenStartLevelsAmiga[60] = {
+	0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01,
+	0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01,
+	0x03, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01,
+	0x02, 0x02, 0x00, 0x02, 0x02, 0x03, 0x00, 0x02,
+	0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x03,
+	0x03, 0x02, 0x00, 0x02, 0x02, 0x03, 0x00, 0x02,
+	0x01, 0x02, 0x01, 0x03, 0x02, 0x02, 0x00, 0x02,
+	0x02, 0x02, 0x00, 0x02
+};
+
+static const ByteProvider kEoB1ChargenStartLevelsAmigaProvider = { ARRAYSIZE(kEoB1ChargenStartLevelsAmiga), kEoB1ChargenStartLevelsAmiga };
+
+static const byte kEoB1ChargenClassMinStatsAmiga[90] = {
+	0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00,
+	0x0e, 0x0d, 0x0e, 0x00, 0x0c, 0x00, 0x0d, 0x00,
+	0x09, 0x11, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x09, 0x00,
+	0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00,
+	0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09,
+	0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x09,
+	0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00,
+	0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00,
+	0x0e, 0x0d, 0x0e, 0x00, 0x00, 0x09, 0x09, 0x00,
+	0x00, 0x00
+};
+
+static const ByteProvider kEoB1ChargenClassMinStatsAmigaProvider = { ARRAYSIZE(kEoB1ChargenClassMinStatsAmiga), kEoB1ChargenClassMinStatsAmiga };
+
+static const byte kEoB1ChargenRaceMinStatsAmiga[36] = {
+	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x08,
+	0x03, 0x07, 0x07, 0x08, 0x03, 0x04, 0x03, 0x06,
+	0x06, 0x03, 0x08, 0x03, 0x03, 0x03, 0x0c, 0x02,
+	0x06, 0x07, 0x02, 0x03, 0x08, 0x03, 0x07, 0x06,
+	0x03, 0x08, 0x0a, 0x03
+};
+
+static const ByteProvider kEoB1ChargenRaceMinStatsAmigaProvider = { ARRAYSIZE(kEoB1ChargenRaceMinStatsAmiga), kEoB1ChargenRaceMinStatsAmiga };
+
+static const uint16 kEoB1ChargenRaceMaxStatsAmiga[36] = {
+	0x6412, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x6412, 0x0012,
+	0x0012, 0x0013, 0x0011, 0x0012, 0x6412, 0x0012, 0x0012, 0x0012,
+	0x0012, 0x0012, 0x6412, 0x0012, 0x0012, 0x0011, 0x0013, 0x0010,
+	0x6412, 0x0013, 0x0011, 0x0012, 0x0012, 0x0012, 0x0011, 0x0012,
+	0x0011, 0x0013, 0x0012, 0x0012
+};
+
+static const Uint16Provider kEoB1ChargenRaceMaxStatsAmigaProvider = { ARRAYSIZE(kEoB1ChargenRaceMaxStatsAmiga), kEoB1ChargenRaceMaxStatsAmiga };
+
+static const byte kEoB1SaveThrowTable1Amiga[50] = {
+	0x10, 0x0e, 0x0d, 0x0b, 0x0a, 0x08, 0x07, 0x05,
+	0x04, 0x03, 0x12, 0x10, 0x0f, 0x0d, 0x0c, 0x0a,
+	0x09, 0x07, 0x06, 0x05, 0x11, 0x0f, 0x0e, 0x0c,
+	0x0b, 0x09, 0x08, 0x06, 0x05, 0x04, 0x14, 0x11,
+	0x10, 0x0d, 0x0c, 0x09, 0x08, 0x05, 0x04, 0x04,
+	0x13, 0x11, 0x10, 0x0e, 0x0d, 0x0b, 0x0a, 0x08,
+	0x07, 0x06
+};
+
+static const ByteProvider kEoB1SaveThrowTable1AmigaProvider = { ARRAYSIZE(kEoB1SaveThrowTable1Amiga), kEoB1SaveThrowTable1Amiga };
+
+static const byte kEoB1SaveThrowTable2Amiga[25] = {
+	0x0e, 0x0d, 0x0b, 0x0a, 0x08, 0x0b, 0x09, 0x07,
+	0x05, 0x03, 0x0d, 0x0b, 0x09, 0x07, 0x05, 0x0f,
+	0x0d, 0x0b, 0x09, 0x07, 0x0c, 0x0a, 0x08, 0x06,
+	0x04
+};
+
+static const ByteProvider kEoB1SaveThrowTable2AmigaProvider = { ARRAYSIZE(kEoB1SaveThrowTable2Amiga), kEoB1SaveThrowTable2Amiga };
+
+static const byte kEoB1SaveThrowTable3Amiga[35] = {
+	0x0a, 0x09, 0x07, 0x06, 0x05, 0x04, 0x02, 0x0e,
+	0x0d, 0x0b, 0x0a, 0x09, 0x08, 0x06, 0x0d, 0x0c,
+	0x0a, 0x09, 0x08, 0x07, 0x05, 0x10, 0x0f, 0x0d,
+	0x0c, 0x0b, 0x0a, 0x08, 0x0f, 0x0e, 0x0c, 0x0b,
+	0x0a, 0x09, 0x07
+};
+
+static const ByteProvider kEoB1SaveThrowTable3AmigaProvider = { ARRAYSIZE(kEoB1SaveThrowTable3Amiga), kEoB1SaveThrowTable3Amiga };
+
+static const byte kEoB1SaveThrowTable4Amiga[30] = {
+	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0e, 0x0c,
+	0x0a, 0x08, 0x06, 0x07, 0x0c, 0x0b, 0x0a, 0x09,
+	0x08, 0x04, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b,
+	0x0f, 0x0d, 0x0b, 0x09, 0x07, 0x05
+};
+
+static const ByteProvider kEoB1SaveThrowTable4AmigaProvider = { ARRAYSIZE(kEoB1SaveThrowTable4Amiga), kEoB1SaveThrowTable4Amiga };
+
+static const byte kEoB1SaveThrwLvlIndexAmiga[6] = {
+	0x11, 0x15, 0x13, 0x15, 0x11, 0x11
+};
+
+static const ByteProvider kEoB1SaveThrwLvlIndexAmigaProvider = { ARRAYSIZE(kEoB1SaveThrwLvlIndexAmiga), kEoB1SaveThrwLvlIndexAmiga };
+
+static const byte kEoB1SaveThrwModDivAmiga[6] = {
+	0x02, 0x05, 0x03, 0x04, 0x02, 0x02
+};
+
+static const ByteProvider kEoB1SaveThrwModDivAmigaProvider = { ARRAYSIZE(kEoB1SaveThrwModDivAmiga), kEoB1SaveThrwModDivAmiga };
+
+static const byte kEoB1SaveThrwModExtAmiga[6] = {
+	0x0A, 0x05, 0x07, 0x06, 0x0A, 0x0A
+};
+
+static const ByteProvider kEoB1SaveThrwModExtAmigaProvider = { ARRAYSIZE(kEoB1SaveThrwModExtAmiga), kEoB1SaveThrwModExtAmiga };
+
+static const char *const kEoB1IntroFilesOpeningAmiga[6] = {
+	"AND.CPS",
+	"SSI.CPS",
+	"PRESENT.CPS",
+	"DAND.CPS",
+	"WESTWOOD.CPS",
+	""
+};
+
+static const StringListProvider kEoB1IntroFilesOpeningAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesOpeningAmiga), kEoB1IntroFilesOpeningAmiga };
+
+static const char *const kEoB1IntroFilesTowerAmiga[2] = {
+	"",
+	"TOWRMAGE.CPS"
+};
+
+static const StringListProvider kEoB1IntroFilesTowerAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesTowerAmiga), kEoB1IntroFilesTowerAmiga };
+
+static const char *const kEoB1IntroFilesOrbAmiga[2] = {
+	"ORB.CPS",
+	"TOWRMAGE.CPS"
+};
+
+static const StringListProvider kEoB1IntroFilesOrbAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesOrbAmiga), kEoB1IntroFilesOrbAmiga };
+
+static const char *const kEoB1IntroFilesWdEntryAmiga[4] = {
+	"",
+	"WTRDP1.CPS",
+	"WTRDP2.CPS",
+	"WTRDP3.CPS"
+};
+
+static const StringListProvider kEoB1IntroFilesWdEntryAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesWdEntryAmiga), kEoB1IntroFilesWdEntryAmiga };
+
+static const char *const kEoB1IntroFilesKingAmiga[2] = {
+	"KING.CPS",
+	"ADVENTUR.CPS"
+};
+
+static const StringListProvider kEoB1IntroFilesKingAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesKingAmiga), kEoB1IntroFilesKingAmiga };
+
+static const char *const kEoB1IntroFilesHandsAmiga[1] = {
+	"HANDS.CPS"
+};
+
+static const StringListProvider kEoB1IntroFilesHandsAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesHandsAmiga), kEoB1IntroFilesHandsAmiga };
+
+static const char *const kEoB1IntroFilesWdExitAmiga[5] = {
+	"WTRDP3.CPS",
+	"",
+	"ORB.CPS",
+	"TUNNEL.CPS",
+	""
+};
+
+static const StringListProvider kEoB1IntroFilesWdExitAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesWdExitAmiga), kEoB1IntroFilesWdExitAmiga };
+
+static const char *const kEoB1IntroFilesTunnelAmiga[2] = {
+	"AVALANCH.CPS",
+	"ZOOMTUNL.CPS"
+};
+
+static const StringListProvider kEoB1IntroFilesTunnelAmigaProvider = { ARRAYSIZE(kEoB1IntroFilesTunnelAmiga), kEoB1IntroFilesTunnelAmiga };
+
+static const byte kEoB1IntroOpeningFrmDelayAmiga[5] = {
+	0x14, 0x32, 0x64, 0x32, 0x8C
+};
+
+static const ByteProvider kEoB1IntroOpeningFrmDelayAmigaProvider = { ARRAYSIZE(kEoB1IntroOpeningFrmDelayAmiga), kEoB1IntroOpeningFrmDelayAmiga };
+
+static const byte kEoB1IntroWdEncodeXAmiga[31] = {
+	0x00, 0x18, 0x02, 0x04, 0x1a, 0x05, 0x10, 0x06,
+	0x10, 0x07, 0x11, 0x04, 0x13, 0x05, 0x06, 0x13,
+	0x09, 0x14, 0x0b, 0x0d, 0x16, 0x0d, 0x16, 0x0e,
+	0x1a, 0x0e, 0x17, 0x0f, 0x1b, 0x0f, 0x17
+};
+
+static const ByteProvider kEoB1IntroWdEncodeXAmigaProvider = { ARRAYSIZE(kEoB1IntroWdEncodeXAmiga), kEoB1IntroWdEncodeXAmiga };
+
+static const byte kEoB1IntroWdEncodeYAmiga[31] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+	0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01
+};
+
+static const ByteProvider kEoB1IntroWdEncodeYAmigaProvider = { ARRAYSIZE(kEoB1IntroWdEncodeYAmiga), kEoB1IntroWdEncodeYAmiga };
+
+static const byte kEoB1IntroWdEncodeWHAmiga[31] = {
+	0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const ByteProvider kEoB1IntroWdEncodeWHAmigaProvider = { ARRAYSIZE(kEoB1IntroWdEncodeWHAmiga), kEoB1IntroWdEncodeWHAmiga };
+
+static const uint16 kEoB1IntroWdDsXAmiga[31] = {
+	0x0120, 0x0120, 0x0120, 0x0130, 0x0130, 0x00b2, 0x00b2, 0x00bc,
+	0x00bc, 0x00ae, 0x00ae, 0x0125, 0x0125, 0x0125, 0x0101, 0x0101,
+	0x00e9, 0x00e9, 0x00e9, 0x00ab, 0x00ab, 0x00cc, 0x00cc, 0x00f0,
+	0x00f0, 0x010c, 0x010c, 0x00e0, 0x00e0, 0x00ba, 0x00ba
+};
+
+static const Uint16Provider kEoB1IntroWdDsXAmigaProvider = { ARRAYSIZE(kEoB1IntroWdDsXAmiga), kEoB1IntroWdDsXAmiga };
+
+static const byte kEoB1IntroWdDsYAmiga[31] = {
+	0x28, 0x28, 0x28, 0x38, 0x38, 0x26, 0x26, 0x1d,
+	0x1d, 0x34, 0x34, 0x50, 0x50, 0x50, 0x50, 0x50,
+	0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x2a, 0x2a, 0x66,
+	0x66, 0x67, 0x67, 0x1c, 0x1c, 0x44, 0x44
+};
+
+static const ByteProvider kEoB1IntroWdDsYAmigaProvider = { ARRAYSIZE(kEoB1IntroWdDsYAmiga), kEoB1IntroWdDsYAmiga };
+
+static const byte kEoB1IntroTvlX1Amiga[6] = {
+	0x00, 0x08, 0x10, 0x00, 0x0F, 0x00
+};
+
+static const ByteProvider kEoB1IntroTvlX1AmigaProvider = { ARRAYSIZE(kEoB1IntroTvlX1Amiga), kEoB1IntroTvlX1Amiga };
+
+static const byte kEoB1IntroTvlY1Amiga[6] = {
+	0x00, 0x00, 0x00, 0x30, 0x36, 0x86
+};
+
+static const ByteProvider kEoB1IntroTvlY1AmigaProvider = { ARRAYSIZE(kEoB1IntroTvlY1Amiga), kEoB1IntroTvlY1Amiga };
+
+static const byte kEoB1IntroTvlX2Amiga[6] = {
+	0x10, 0x10, 0x0F, 0x0C, 0x0B, 0x0B
+};
+
+static const ByteProvider kEoB1IntroTvlX2AmigaProvider = { ARRAYSIZE(kEoB1IntroTvlX2Amiga), kEoB1IntroTvlX2Amiga };
+
+static const byte kEoB1IntroTvlY2Amiga[6] = {
+	0x35, 0x35, 0x35, 0x35, 0x35, 0x61
+};
+
+static const ByteProvider kEoB1IntroTvlY2AmigaProvider = { ARRAYSIZE(kEoB1IntroTvlY2Amiga), kEoB1IntroTvlY2Amiga };
+
+static const byte kEoB1IntroTvlWAmiga[6] = {
+	0x08, 0x08, 0x0B, 0x0F, 0x12, 0x12
+};
+
+static const ByteProvider kEoB1IntroTvlWAmigaProvider = { ARRAYSIZE(kEoB1IntroTvlWAmiga), kEoB1IntroTvlWAmiga };
+
+static const byte kEoB1IntroTvlHAmiga[6] = {
+	0x1A, 0x30, 0x36, 0x45, 0x50, 0x28
+};
+
+static const ByteProvider kEoB1IntroTvlHAmigaProvider = { ARRAYSIZE(kEoB1IntroTvlHAmiga), kEoB1IntroTvlHAmiga };
+
+static const byte kEoB1IntroOrbFadePalAmiga[64] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x33,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x03, 0x37, 0x00, 0x00, 0x05, 0x55, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x0a, 0xdd, 0x06, 0x9c, 0x05, 0x5b, 0x0f, 0xff
+};
+
+static const ByteProvider kEoB1IntroOrbFadePalAmigaProvider = { ARRAYSIZE(kEoB1IntroOrbFadePalAmiga), kEoB1IntroOrbFadePalAmiga };
+
+static const byte kEoB1DoorShapeDefsAmiga[96] = {
+	0x00, 0x00, 0x0a, 0x48, 0x11, 0x98, 0x07, 0x2f,
+	0x19, 0x48, 0x04, 0x1d, 0x0a, 0x00, 0x0a, 0x48,
+	0x1d, 0x48, 0x07, 0x2f, 0x19, 0x68, 0x04, 0x1d,
+	0x14, 0x00, 0x06, 0x48, 0x24, 0x48, 0x04, 0x2f,
+	0x1e, 0x78, 0x03, 0x1d, 0x1a, 0x00, 0x0c, 0x48,
+	0x00, 0x90, 0x07, 0x29, 0x21, 0x78, 0x04, 0x1b,
+	0x00, 0xbc, 0x0a, 0x0c, 0x0a, 0xbc, 0x06, 0x08,
+	0x0a, 0xc4, 0x04, 0x02, 0x07, 0x4a, 0x09, 0x37,
+	0x00, 0x4a, 0x07, 0x25, 0x07, 0xa0, 0x05, 0x17,
+	0x07, 0x82, 0x09, 0x1c, 0x00, 0x70, 0x07, 0x13,
+	0x0c, 0xa0, 0x05, 0x0b, 0x10, 0x48, 0x09, 0x4b,
+	0x18, 0x98, 0x07, 0x2e, 0x1f, 0x98, 0x04, 0x1d
+};
+
+static const ByteProvider kEoB1DoorShapeDefsAmigaProvider = { ARRAYSIZE(kEoB1DoorShapeDefsAmiga), kEoB1DoorShapeDefsAmiga };
+
+static const byte kEoB1DoorSwitchShapeDefsAmiga[96] = {
+	0x25, 0x78, 0x01, 0x07, 0x25, 0x88, 0x01, 0x03,
+	0x25, 0x90, 0x01, 0x01, 0x25, 0x78, 0x01, 0x07,
+	0x25, 0x88, 0x01, 0x03, 0x25, 0x90, 0x01, 0x01,
+	0x26, 0x78, 0x01, 0x0b, 0x26, 0x88, 0x01, 0x06,
+	0x26, 0x90, 0x01, 0x04, 0x27, 0x78, 0x01, 0x0e,
+	0x27, 0x88, 0x01, 0x08, 0x25, 0x90, 0x01, 0x01,
+	0x25, 0x78, 0x01, 0x07, 0x25, 0x88, 0x01, 0x03,
+	0x25, 0x90, 0x01, 0x01, 0x25, 0x98, 0x01, 0x0b,
+	0x25, 0xa8, 0x01, 0x06, 0x25, 0xb0, 0x01, 0x04,
+	0x25, 0x98, 0x01, 0x0b, 0x25, 0xa8, 0x01, 0x05,
+	0x25, 0xb0, 0x01, 0x04, 0x26, 0x98, 0x01, 0x0a,
+	0x26, 0xa8, 0x01, 0x04, 0x25, 0x90, 0x01, 0x01
+};
+
+static const ByteProvider kEoB1DoorSwitchShapeDefsAmigaProvider = { ARRAYSIZE(kEoB1DoorSwitchShapeDefsAmiga), kEoB1DoorSwitchShapeDefsAmiga };
+
+static const byte kEoB1DoorSwitchCoordsAmiga[48] = {
+	0x82, 0x24, 0x74, 0x27, 0x00, 0x00, 0x82, 0x24,
+	0x74, 0x27, 0x00, 0x00, 0x5b, 0x36, 0x5a, 0x33,
+	0x5a, 0x2d, 0x88, 0x26, 0x74, 0x29, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x24,
+	0x73, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x80, 0x2b, 0x74, 0x2b, 0x00, 0x00
+};
+
+static const ByteProvider kEoB1DoorSwitchCoordsAmigaProvider = { ARRAYSIZE(kEoB1DoorSwitchCoordsAmiga), kEoB1DoorSwitchCoordsAmiga };
+
+static const byte kEoB1MonsterPropertiesAmiga[616] = {
+	0x07, 0x12, 0xff, 0x01, 0x01, 0x04, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x02,
+	0x4b, 0x02, 0xff, 0x00, 0x07, 0x11, 0x02, 0x01,
+	0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x78, 0x01, 0x38, 0x39, 0x00, 0xff, 0x00,
+	0x04, 0x10, 0x01, 0x01, 0x01, 0x06, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00,
+	0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x00, 0x42,
+	0x43, 0x00, 0x02, 0x00, 0x08, 0x0f, 0x02, 0x01,
+	0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+	0x00, 0x41, 0x00, 0x49, 0x4a, 0x00, 0x03, 0x00,
+	0x04, 0x10, 0x02, 0x02, 0x01, 0x04, 0x01, 0x01,
+	0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x02, 0x36,
+	0x37, 0x04, 0xff, 0x14, 0x05, 0x11, 0x03, 0x01,
+	0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03,
+	0x00, 0x41, 0x00, 0x2f, 0x30, 0x00, 0xff, 0x00,
+	0x05, 0x0f, 0x02, 0x01, 0x01, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x02, 0x8a, 0x02, 0x31,
+	0x26, 0x00, 0xff, 0x00, 0x03, 0x0c, 0x07, 0x01,
+	0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+	0x02, 0xda, 0x00, 0x2d, 0x2e, 0x00, 0xff, 0x00,
+	0x05, 0x07, 0x0a, 0x01, 0x01, 0x08, 0x06, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+	0x00, 0x00, 0x00, 0x04, 0x05, 0xdc, 0x00, 0x40,
+	0x41, 0x00, 0x07, 0x00, 0x04, 0x0f, 0x06, 0x02,
+	0x01, 0x08, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x03, 0xcf, 0x01, 0x27, 0x28, 0x00, 0xff, 0x00,
+	0x05, 0x0d, 0x06, 0x03, 0x01, 0x08, 0x00, 0x01,
+	0x04, 0x00, 0x01, 0x04, 0x00, 0x00, 0x28, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x05, 0x78, 0x02, 0x25,
+	0x24, 0x00, 0xff, 0x00, 0x04, 0x0d, 0x05, 0x02,
+	0x01, 0x04, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x04, 0xe2, 0x00, 0x3e, 0x3f, 0x00, 0xff, 0x00,
+	0x03, 0x0e, 0x04, 0x01, 0x01, 0x08, 0x04, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+	0x00, 0x00, 0x00, 0x01, 0x02, 0x8a, 0x00, 0x2b,
+	0x2c, 0x00, 0xff, 0x3c, 0xff, 0x07, 0x0a, 0x01,
+	0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x27, 0x10, 0x02, 0x44, 0x45, 0x00, 0xff, 0x64,
+	0xff, 0x07, 0x09, 0x01, 0x03, 0x04, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00,
+	0x00, 0x00, 0x00, 0x03, 0x07, 0xd0, 0x00, 0x18,
+	0xff, 0x08, 0xff, 0x00, 0x03, 0x0d, 0x07, 0x01,
+	0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x13, 0x88, 0x02, 0x29, 0x2a, 0x02, 0xff, 0x3c,
+	0x05, 0x0d, 0x07, 0x01, 0x01, 0x06, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x13, 0x88, 0x00, 0x34,
+	0x35, 0x02, 0xff, 0x00, 0x05, 0x0b, 0x08, 0x01,
+	0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x1f, 0x40, 0x00, 0x3a, 0x3b, 0xff, 0xff, 0x5a,
+	0x02, 0x0f, 0x05, 0x01, 0x01, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x01, 0x0e, 0x02, 0x3c,
+	0x3d, 0x00, 0xff, 0x00, 0xfe, 0x0d, 0x08, 0x01,
+	0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x0f, 0xa0, 0x02, 0x48, 0x47, 0x00, 0xff, 0x32,
+	0x04, 0x0d, 0x07, 0x01, 0x01, 0x0a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x03, 0xcf, 0x01, 0x33,
+	0x32, 0x00, 0xff, 0x28, 0x00, 0x05, 0x23, 0x01,
+	0x01, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x36, 0xb0, 0x02, 0xff, 0xff, 0xff, 0xff, 0x64
+};
+
+static const ByteProvider kEoB1MonsterPropertiesAmigaProvider = { ARRAYSIZE(kEoB1MonsterPropertiesAmiga), kEoB1MonsterPropertiesAmiga };
+
+static const byte kEoB1EnemyMageSpellListAmiga[10] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x05,
+	0x06, 0x00
+};
+
+static const ByteProvider kEoB1EnemyMageSpellListAmigaProvider = { ARRAYSIZE(kEoB1EnemyMageSpellListAmiga), kEoB1EnemyMageSpellListAmiga };
+
+static const byte kEoB1EnemyMageSfxAmiga[10] = {
+	0x00, 0x55, 0x55, 0x55, 0x55, 0x62, 0x62, 0x1F,
+	0x62, 0x02
+};
+
+static const ByteProvider kEoB1EnemyMageSfxAmigaProvider = { ARRAYSIZE(kEoB1EnemyMageSfxAmiga), kEoB1EnemyMageSfxAmiga };
+
+static const byte kEoB1BeholderSpellListAmiga[4] = {
+	0x02, 0x0A, 0x0B, 0x62
+};
+
+static const ByteProvider kEoB1BeholderSpellListAmigaProvider = { ARRAYSIZE(kEoB1BeholderSpellListAmiga), kEoB1BeholderSpellListAmiga };
+
+static const byte kEoB1BeholderSfxAmiga[4] = {
+	0x62, 0x53, 0x40, 0x00
+};
+
+static const ByteProvider kEoB1BeholderSfxAmigaProvider = { ARRAYSIZE(kEoB1BeholderSfxAmiga), kEoB1BeholderSfxAmiga };
+
+static const byte kEoB1NpcShpDataAmiga[76] = {
+	0x00, 0x00, 0x06, 0x40, 0x06, 0x00, 0x07, 0x48,
+	0x0d, 0x00, 0x06, 0x30, 0x13, 0x00, 0x05, 0x38,
+	0x18, 0x00, 0x05, 0x38, 0x1d, 0x00, 0x05, 0x38,
+	0x22, 0x00, 0x06, 0x48, 0x00, 0x48, 0x06, 0x56,
+	0x06, 0x48, 0x05, 0x40, 0x0b, 0x48, 0x05, 0x40,
+	0x10, 0x48, 0x05, 0x30, 0x06, 0x88, 0x03, 0x18,
+	0x09, 0x88, 0x03, 0x18, 0x0c, 0x88, 0x03, 0x18,
+	0x0f, 0x88, 0x03, 0x18, 0x12, 0x88, 0x03, 0x18,
+	0x15, 0x88, 0x03, 0x18, 0x18, 0x48, 0x06, 0x58,
+	0x1e, 0x48, 0x0a, 0x48
+};
+
+static const ByteProvider kEoB1NpcShpDataAmigaProvider = { ARRAYSIZE(kEoB1NpcShpDataAmiga), kEoB1NpcShpDataAmiga };
+
+static const byte kEoB1NpcSubShpIndex1Amiga[6] = {
+	0x09, 0x08, 0x08, 0x09, 0x09, 0x0A
+};
+
+static const ByteProvider kEoB1NpcSubShpIndex1AmigaProvider = { ARRAYSIZE(kEoB1NpcSubShpIndex1Amiga), kEoB1NpcSubShpIndex1Amiga };
+
+static const byte kEoB1NpcSubShpIndex2Amiga[6] = {
+	0x0D, 0x0B, 0x0C, 0x0E, 0x0F, 0x10
+};
+
+static const ByteProvider kEoB1NpcSubShpIndex2AmigaProvider = { ARRAYSIZE(kEoB1NpcSubShpIndex2Amiga), kEoB1NpcSubShpIndex2Amiga };
+
+static const byte kEoB1NpcSubShpYAmiga[6] = {
+	0x34, 0x31, 0x31, 0x34, 0x34, 0x45
+};
+
+static const ByteProvider kEoB1NpcSubShpYAmigaProvider = { ARRAYSIZE(kEoB1NpcSubShpYAmiga), kEoB1NpcSubShpYAmiga };
+
+static const char *const kEoB1EnchantedStringAmiga[1] = {
+	"%s +%d"
+};
+
+static const StringListProvider kEoB1EnchantedStringAmigaProvider = { ARRAYSIZE(kEoB1EnchantedStringAmiga), kEoB1EnchantedStringAmiga };
+
+static const byte kEoB1SpellLevelsMageAmiga[26] = {
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+	0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03,
+	0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05,
+	0x05, 0x00
+};
+
+static const ByteProvider kEoB1SpellLevelsMageAmigaProvider = { ARRAYSIZE(kEoB1SpellLevelsMageAmiga), kEoB1SpellLevelsMageAmiga };
+
+static const byte kEoB1SpellLevelsClericAmiga[25] = {
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
+	0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
+	0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x01,
+	0x00
+};
+
+static const ByteProvider kEoB1SpellLevelsClericAmigaProvider = { ARRAYSIZE(kEoB1SpellLevelsClericAmiga), kEoB1SpellLevelsClericAmiga };
+
+static const byte kEoB1NumSpellsClericAmiga[50] = {
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x03,
+	0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00,
+	0x00, 0x03, 0x03, 0x02, 0x00, 0x00, 0x03, 0x03,
+	0x02, 0x01, 0x00, 0x03, 0x03, 0x03, 0x02, 0x00,
+	0x04, 0x04, 0x03, 0x02, 0x01, 0x04, 0x04, 0x03,
+	0x03, 0x02
+};
+
+static const ByteProvider kEoB1NumSpellsClericAmigaProvider = { ARRAYSIZE(kEoB1NumSpellsClericAmiga), kEoB1NumSpellsClericAmiga };
+
+static const byte kEoB1NumSpellsWisAdjAmiga[40] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02,
+	0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
+	0x00, 0x02, 0x02, 0x01, 0x00, 0x00, 0x02, 0x02,
+	0x01, 0x01, 0x00, 0x03, 0x02, 0x01, 0x02, 0x00
+};
+
+static const ByteProvider kEoB1NumSpellsWisAdjAmigaProvider = { ARRAYSIZE(kEoB1NumSpellsWisAdjAmiga), kEoB1NumSpellsWisAdjAmiga };
+
+static const byte kEoB1NumSpellsPalAmiga[60] = {
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02,
+	0x02, 0x00, 0x00, 0x00
+};
+
+static const ByteProvider kEoB1NumSpellsPalAmigaProvider = { ARRAYSIZE(kEoB1NumSpellsPalAmiga), kEoB1NumSpellsPalAmiga };
+
+static const byte kEoB1NumSpellsMageAmiga[55] = {
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x03,
+	0x02, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00,
+	0x00, 0x04, 0x02, 0x02, 0x00, 0x00, 0x04, 0x03,
+	0x02, 0x01, 0x00, 0x04, 0x03, 0x03, 0x02, 0x00,
+	0x04, 0x03, 0x03, 0x02, 0x01, 0x04, 0x04, 0x03,
+	0x02, 0x02, 0x04, 0x04, 0x04, 0x03, 0x03
+};
+
+static const ByteProvider kEoB1NumSpellsMageAmigaProvider = { ARRAYSIZE(kEoB1NumSpellsMageAmiga), kEoB1NumSpellsMageAmiga };
+
+static const uint32 kEoB1ExperienceTable0Amiga[12] = {
+	0x00000000, 0x000007D0, 0x00000FA0, 0x00001F40, 0x00003E80, 0x00007D00, 0x0000FA00, 0x0001E848,
+	0x0003D090, 0x0007A120, 0x000B71B0, 0xFFFFFFFF
+};
+
+static const Uint32Provider kEoB1ExperienceTable0AmigaProvider = { ARRAYSIZE(kEoB1ExperienceTable0Amiga), kEoB1ExperienceTable0Amiga };
+
+static const uint32 kEoB1ExperienceTable1Amiga[12] = {
+	0x00000000, 0x000009C4, 0x00001388, 0x00002710, 0x00004E20, 0x00009C40, 0x0000EA60, 0x00015F90,
+	0x00020F58, 0x0003D090, 0x0005B8D8, 0xFFFFFFFF
+};
+
+static const Uint32Provider kEoB1ExperienceTable1AmigaProvider = { ARRAYSIZE(kEoB1ExperienceTable1Amiga), kEoB1ExperienceTable1Amiga };
+
+static const uint32 kEoB1ExperienceTable2Amiga[11] = {
+	0x00000000, 0x000005DC, 0x00000BB8, 0x00001770, 0x000032C8, 0x00006B6C, 0x0000D6D8, 0x0001ADB0,
+	0x00036EE8, 0x0006DDD0, 0xFFFFFFFF
+};
+
+static const Uint32Provider kEoB1ExperienceTable2AmigaProvider = { ARRAYSIZE(kEoB1ExperienceTable2Amiga), kEoB1ExperienceTable2Amiga };
+
+static const uint32 kEoB1ExperienceTable3Amiga[12] = {
+	0x00000000, 0x000004E2, 0x000009C4, 0x00001388, 0x00002710, 0x00004E20, 0x00009C40, 0x00011170,
+	0x0001ADB0, 0x00027100, 0x00035B60, 0xFFFFFFFF
+};
+
+static const Uint32Provider kEoB1ExperienceTable3AmigaProvider = { ARRAYSIZE(kEoB1ExperienceTable3Amiga), kEoB1ExperienceTable3Amiga };
+
+static const uint32 kEoB1ExperienceTable4Amiga[12] = {
+	0x00000000, 0x000008CA, 0x00001194, 0x00002328, 0x00004650, 0x00008CA0, 0x000124F8, 0x000249F0,
+	0x000493E0, 0x000927C0, 0x000DBBA0, 0xFFFFFFFF
+};
+
+static const Uint32Provider kEoB1ExperienceTable4AmigaProvider = { ARRAYSIZE(kEoB1ExperienceTable4Amiga), kEoB1ExperienceTable4Amiga };
+
+static const byte kEoB1ExpObjectTblIndexAmiga[9] = {
+	0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
+	0x00
+};
+
+static const ByteProvider kEoB1ExpObjectTblIndexAmigaProvider = { ARRAYSIZE(kEoB1ExpObjectTblIndexAmiga), kEoB1ExpObjectTblIndexAmiga };
+
+static const byte kEoB1ExpObjectShpStartAmiga[4] = {
+	0x07, 0x0C, 0x0F, 0x12
+};
+
+static const ByteProvider kEoB1ExpObjectShpStartAmigaProvider = { ARRAYSIZE(kEoB1ExpObjectShpStartAmiga), kEoB1ExpObjectShpStartAmiga };
+
+static const byte kEoB1ExpObjectTbl1Amiga[13] = {
+	0x1f, 0x07, 0x1f, 0x07, 0x18, 0x07, 0x18, 0x19,
+	0x18, 0x19, 0x18, 0x19, 0x00
+};
+
+static const ByteProvider kEoB1ExpObjectTbl1AmigaProvider = { ARRAYSIZE(kEoB1ExpObjectTbl1Amiga), kEoB1ExpObjectTbl1Amiga };
+
+static const byte kEoB1ExpObjectTbl2Amiga[10] = {
+	0x1f, 0x1c, 0x1f, 0x1c, 0x1d, 0x1e, 0x10, 0x1e,
+	0x10, 0x00
+};
+
+static const ByteProvider kEoB1ExpObjectTbl2AmigaProvider = { ARRAYSIZE(kEoB1ExpObjectTbl2Amiga), kEoB1ExpObjectTbl2Amiga };
+
+static const byte kEoB1ExpObjectTbl3Amiga[11] = {
+	0x07, 0x1b, 0x07, 0x1b, 0x08, 0x1b, 0x08, 0x10,
+	0x08, 0x10, 0x00
+};
+
+static const ByteProvider kEoB1ExpObjectTbl3AmigaProvider = { ARRAYSIZE(kEoB1ExpObjectTbl3Amiga), kEoB1ExpObjectTbl3Amiga };
+
+static const byte kEoB1ExpObjectYAmiga[4] = {
+	0x77, 0x67, 0x4F, 0x3F
+};
+
+static const ByteProvider kEoB1ExpObjectYAmigaProvider = { ARRAYSIZE(kEoB1ExpObjectYAmiga), kEoB1ExpObjectYAmiga };
+
+static const byte kEoB1SparkDefStepsAmiga[8] = {
+	0x40, 0x90, 0xE4, 0xB9, 0x6E, 0x1B, 0x06, 0x01
+};
+
+static const ByteProvider kEoB1SparkDefStepsAmigaProvider = { ARRAYSIZE(kEoB1SparkDefStepsAmiga), kEoB1SparkDefStepsAmiga };
+
+static const byte kEoB1SparkDefSubStepsAmiga[4] = {
+	0xC0, 0x30, 0x0C, 0x03
+};
+
+static const ByteProvider kEoB1SparkDefSubStepsAmigaProvider = { ARRAYSIZE(kEoB1SparkDefSubStepsAmiga), kEoB1SparkDefSubStepsAmiga };
+
+static const byte kEoB1SparkDefShiftAmiga[4] = {
+	0x06, 0x04, 0x02, 0x00
+};
+
+static const ByteProvider kEoB1SparkDefShiftAmigaProvider = { ARRAYSIZE(kEoB1SparkDefShiftAmiga), kEoB1SparkDefShiftAmiga };
+
+static const byte kEoB1SparkDefAddAmiga[8] = {
+	0x08, 0x06, 0x1C, 0x14, 0x0D, 0x18, 0x0D, 0x0F
+};
+
+static const ByteProvider kEoB1SparkDefAddAmigaProvider = { ARRAYSIZE(kEoB1SparkDefAddAmiga), kEoB1SparkDefAddAmiga };
+
+static const byte kEoB1SparkDefXAmiga[6] = {
+	0x17, 0x20, 0x17, 0x20, 0x17, 0x20
+};
+
+static const ByteProvider kEoB1SparkDefXAmigaProvider = { ARRAYSIZE(kEoB1SparkDefXAmiga), kEoB1SparkDefXAmiga };
+
+static const byte kEoB1SparkDefYAmiga[6] = {
+	0x02, 0x02, 0x34, 0x34, 0x66, 0x66
+};
+
+static const ByteProvider kEoB1SparkDefYAmigaProvider = { ARRAYSIZE(kEoB1SparkDefYAmiga), kEoB1SparkDefYAmiga };
+
+static const uint32 kEoB1SparkOfFlags1Amiga[11] = {
+	0x40000000, 0x95000000, 0xEA550000, 0xBFAA5400, 0x6AFFA954, 0x15AAFEA9, 0x0055ABFE, 0x000056AB,
+	0x00000156, 0x00000001, 0x00000000
+};
+
+static const Uint32Provider kEoB1SparkOfFlags1AmigaProvider = { ARRAYSIZE(kEoB1SparkOfFlags1Amiga), kEoB1SparkOfFlags1Amiga };
+
+static const uint32 kEoB1SparkOfFlags2Amiga[16] = {
+	0xC0000000, 0x30000000, 0x0C000000, 0x03000000, 0x00C00000, 0x00300000, 0x000C0000, 0x00030000,
+	0x0000C000, 0x00003000, 0x00000C00, 0x00000300, 0x000000C0, 0x00000030, 0x0000000C, 0x00000003
+};
+
+static const Uint32Provider kEoB1SparkOfFlags2AmigaProvider = { ARRAYSIZE(kEoB1SparkOfFlags2Amiga), kEoB1SparkOfFlags2Amiga };
+
+static const byte kEoB1SparkOfShiftAmiga[16] = {
+	0x1E, 0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10,
+	0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x00
+};
+
+static const ByteProvider kEoB1SparkOfShiftAmigaProvider = { ARRAYSIZE(kEoB1SparkOfShiftAmiga), kEoB1SparkOfShiftAmiga };
+
+static const byte kEoB1SparkOfXAmiga[16] = {
+	0x50, 0x70, 0x30, 0x68, 0x20, 0x60, 0x38, 0x78,
+	0x80, 0x48, 0x58, 0x28, 0x60, 0x40, 0x70, 0x48
+};
+
+static const ByteProvider kEoB1SparkOfXAmigaProvider = { ARRAYSIZE(kEoB1SparkOfXAmiga), kEoB1SparkOfXAmiga };
+
+static const byte kEoB1SparkOfYAmiga[16] = {
+	0x31, 0x2B, 0x48, 0x17, 0x16, 0x48, 0x35, 0x1B,
+	0x43, 0x2E, 0x24, 0x28, 0x38, 0x1C, 0x16, 0x44
+};
+
+static const ByteProvider kEoB1SparkOfYAmigaProvider = { ARRAYSIZE(kEoB1SparkOfYAmiga), kEoB1SparkOfYAmiga };
+
+static const byte kEoB1SpellPropertiesAmiga[1060] = {
+	0x00, 0x00, 0x05, 0x7e, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xd0,
+	0x01, 0x00, 0x00, 0x00, 0xb3, 0xc2, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xb4, 0x38, 0x00, 0x00,
+	0x00, 0x00, 0x07, 0xd6, 0x00, 0x00, 0x00, 0x00,
+	0xb4, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x57, 0x01, 0x00, 0x00, 0x07, 0xe4,
+	0x08, 0x00, 0x00, 0x00, 0xb5, 0x5a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xb5, 0xa6, 0x5f, 0x00,
+	0x00, 0x00, 0x07, 0xf2, 0x00, 0x00, 0x00, 0x00,
+	0xb5, 0xce, 0x00, 0x00, 0xb5, 0xf2, 0x00, 0x00,
+	0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
+	0xb6, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xb6, 0x72, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+	0x02, 0x00, 0x00, 0x00, 0xb6, 0x8e, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xb7, 0x40, 0x58, 0x00,
+	0x00, 0x00, 0x08, 0x18, 0x01, 0x00, 0x00, 0x00,
+	0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xb7, 0xaa, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x26, 0x00, 0x00, 0x00, 0x00,
+	0xb7, 0xc8, 0x00, 0x00, 0xb7, 0xf2, 0x00, 0x00,
+	0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x08, 0x38,
+	0x00, 0x00, 0x00, 0x00, 0xb8, 0x28, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x08, 0x48, 0x01, 0x00, 0x00, 0x00,
+	0xb8, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x08, 0x56,
+	0x00, 0x00, 0x00, 0x00, 0xb8, 0xf4, 0x00, 0x00,
+	0xb9, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x62, 0x01,
+	0x00, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00,
+	0xb9, 0x4e, 0x00, 0x00, 0xb9, 0x78, 0x00, 0x00,
+	0x00, 0x00, 0x63, 0x01, 0x00, 0x00, 0x08, 0x6c,
+	0x08, 0x00, 0x00, 0x00, 0xb9, 0xa8, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xba, 0x06, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x72, 0x00, 0x00, 0x00, 0x00,
+	0xba, 0x16, 0x00, 0x00, 0xba, 0x48, 0x00, 0x00,
+	0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x08, 0x7e,
+	0x08, 0x00, 0x00, 0x00, 0xba, 0xd2, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xb7, 0xaa, 0x5e, 0x00,
+	0x00, 0x00, 0x08, 0x96, 0x00, 0x00, 0x00, 0x00,
+	0xba, 0xfa, 0x00, 0x00, 0xbb, 0x24, 0x00, 0x00,
+	0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x08, 0xa6,
+	0x02, 0x00, 0x00, 0x00, 0xbb, 0x54, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xbb, 0xec, 0x66, 0x00,
+	0x00, 0x00, 0x08, 0xb6, 0x00, 0x00, 0x00, 0x00,
+	0xbc, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x67, 0x01, 0x00, 0x00, 0x08, 0xbc,
+	0x00, 0x00, 0x00, 0x00, 0xbc, 0xb4, 0x00, 0x00,
+	0xbc, 0xde, 0x00, 0x00, 0x00, 0x00, 0x59, 0x01,
+	0x00, 0x00, 0x08, 0xc6, 0x01, 0x00, 0x00, 0x00,
+	0xbd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x08, 0xd0,
+	0x00, 0x00, 0x00, 0x00, 0xbd, 0xf2, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x08, 0xda, 0x00, 0x00, 0x00, 0x00,
+	0xbd, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x76, 0x01, 0x00, 0x00, 0x08, 0xe8,
+	0x00, 0x00, 0x00, 0x00, 0xbf, 0x0c, 0x00, 0x00,
+	0xbf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x65, 0x01,
+	0x00, 0x00, 0x08, 0xf6, 0x08, 0x00, 0x00, 0x00,
+	0xbf, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xc0, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x08, 0xfc,
+	0x01, 0x00, 0x00, 0x00, 0xc0, 0x2c, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+	0x00, 0x00, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x00,
+	0xc0, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0x07, 0xe4,
+	0x08, 0x00, 0x00, 0x00, 0xb5, 0x5a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xb5, 0xa6, 0x5f, 0x00,
+	0x00, 0x00, 0x09, 0x22, 0x01, 0x00, 0x00, 0x00,
+	0xc0, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xc0, 0x9c, 0x6e, 0x00, 0x00, 0x00, 0x09, 0x38,
+	0x01, 0x00, 0x00, 0x00, 0xc0, 0xac, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc1, 0x48, 0x5b, 0x00,
+	0x00, 0x00, 0x09, 0x3c, 0x02, 0x00, 0x00, 0x00,
+	0xc2, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xb7, 0x40, 0x63, 0x00, 0x00, 0x00, 0x08, 0x72,
+	0x00, 0x00, 0x00, 0x00, 0xba, 0x16, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x01,
+	0x00, 0x00, 0x09, 0x48, 0x01, 0x00, 0x00, 0x00,
+	0xc1, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xc1, 0xc8, 0x6f, 0x00, 0x00, 0x00, 0x09, 0x54,
+	0x08, 0x00, 0x00, 0x00, 0xc2, 0xb2, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00,
+	0x00, 0x00, 0x08, 0x48, 0x01, 0x00, 0x00, 0x00,
+	0xb8, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x09, 0x60,
+	0x04, 0x00, 0x00, 0x00, 0xc2, 0xd4, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc3, 0x0e, 0x00, 0x00,
+	0x00, 0x00, 0x09, 0x72, 0x08, 0x00, 0x00, 0x00,
+	0xc3, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xc3, 0x64, 0x00, 0x00, 0x00, 0x00, 0x09, 0x7a,
+	0x08, 0x00, 0x00, 0x00, 0xc3, 0x7a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x09, 0x8c, 0x01, 0x00, 0x00, 0x00,
+	0xc3, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x09, 0xa0,
+	0x00, 0x00, 0x00, 0x00, 0xc3, 0xea, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x01,
+	0x00, 0x00, 0x09, 0xb6, 0x01, 0x00, 0x00, 0x00,
+	0xc4, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x09, 0xc8,
+	0x08, 0x00, 0x00, 0x00, 0xc4, 0x28, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc4, 0x82, 0x6e, 0x00,
+	0x00, 0x00, 0x09, 0xe8, 0x04, 0x00, 0x00, 0x00,
+	0xc4, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x0a, 0x02,
+	0x01, 0x00, 0x00, 0x00, 0xc4, 0xb4, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x00,
+	0x00, 0x00, 0x0a, 0x18, 0x00, 0x00, 0x00, 0x00,
+	0xc4, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x0a, 0x2e,
+	0x00, 0x00, 0x00, 0x00, 0xc4, 0xec, 0x00, 0x00,
+	0xc5, 0x16, 0x00, 0x00, 0x00, 0x00, 0x62, 0x01,
+	0x00, 0x00, 0x0a, 0x3c, 0x01, 0x00, 0x00, 0x00,
+	0xc5, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0a, 0x48,
+	0x01, 0x00, 0x00, 0x00, 0xc6, 0xb4, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00,
+	0x00, 0x00, 0x05, 0x7e, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc5, 0x78, 0x00, 0x00,
+	0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x05, 0x7e,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xc5, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x75, 0x00,
+	0x00, 0x00, 0x05, 0x7e, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc6, 0x3c, 0x00, 0x00,
+	0x00, 0x00, 0x75, 0x00
+};
+
+static const ByteProvider kEoB1SpellPropertiesAmigaProvider = { ARRAYSIZE(kEoB1SpellPropertiesAmiga), kEoB1SpellPropertiesAmiga };
+
+static const byte kEoB1MagicFlightPropsAmiga[80] = {
+	0x04, 0xff, 0x41, 0x09, 0x0a, 0xff, 0x04, 0x05,
+	0x0d, 0xff, 0x7a, 0x06, 0x0e, 0xff, 0x0c, 0x05,
+	0x10, 0xff, 0x4a, 0x0a, 0x12, 0x06, 0x38, 0x07,
+	0x15, 0x06, 0x7a, 0x08, 0x19, 0xff, 0x4a, 0x0a,
+	0x2f, 0xff, 0x4b, 0x06, 0x32, 0xff, 0x09, 0x07,
+	0x33, 0xff, 0x09, 0x0a, 0x34, 0xff, 0x09, 0x0a,
+	0x01, 0x01, 0x00, 0x00, 0x03, 0xfd, 0x02, 0xfe,
+	0x01, 0xff, 0x00, 0x00, 0x00, 0x98, 0x00, 0x18,
+	0x00, 0x78, 0x00, 0x38, 0x00, 0x58, 0x40, 0x40,
+	0x38, 0x38, 0x38, 0x38, 0xe0, 0x20, 0x01, 0xff
+};
+
+static const ByteProvider kEoB1MagicFlightPropsAmigaProvider = { ARRAYSIZE(kEoB1MagicFlightPropsAmiga), kEoB1MagicFlightPropsAmiga };
+
+static const byte kEoB1TurnUndeadEffectAmiga[140] = {
+	0x0a, 0x07, 0x04, 0x00, 0x00, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0d, 0x0a,
+	0x07, 0x04, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x10, 0x0d, 0x0a, 0x07,
+	0x04, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0x13, 0x10, 0x0d, 0x0a, 0x07, 0x04,
+	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0x14, 0x13, 0x10, 0x0d, 0x0a, 0x07, 0x04, 0x00,
+	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x63, 0x14,
+	0x13, 0x10, 0x0d, 0x0a, 0x07, 0x04, 0x00, 0x00,
+	0x00, 0xff, 0xff, 0x00, 0x63, 0x63, 0x14, 0x13,
+	0x10, 0x0d, 0x0a, 0x07, 0x04, 0x00, 0x00, 0x00,
+	0x00, 0xff, 0x63, 0x63, 0x63, 0x14, 0x13, 0x10,
+	0x0d, 0x0a, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00,
+	0x63, 0x63, 0x63, 0x63, 0x14, 0x13, 0x10, 0x0d,
+	0x0a, 0x07, 0x07, 0x04, 0x04, 0x00, 0x63, 0x63,
+	0x63, 0x63, 0x63, 0x14, 0x13, 0x10, 0x0d, 0x0a,
+	0x0a, 0x07, 0x07, 0x04
+};
+
+static const ByteProvider kEoB1TurnUndeadEffectAmigaProvider = { ARRAYSIZE(kEoB1TurnUndeadEffectAmiga), kEoB1TurnUndeadEffectAmiga };
+
+static const byte kEoB1BurningHandsDestAmiga[8] = {
+	0x02, 0x03, 0x00, 0x02, 0x00, 0x01, 0x01, 0x03
+};
+
+static const ByteProvider kEoB1BurningHandsDestAmigaProvider = { ARRAYSIZE(kEoB1BurningHandsDestAmiga), kEoB1BurningHandsDestAmiga };
+
+static const byte kEoB1ConeOfColdDest1Amiga[7] = {
+	0xE0, 0xC0, 0xC1, 0xBF, 0xA0, 0x9F, 0xA1
+};
+
+static const ByteProvider kEoB1ConeOfColdDest1AmigaProvider = { ARRAYSIZE(kEoB1ConeOfColdDest1Amiga), kEoB1ConeOfColdDest1Amiga };
+
+static const byte kEoB1ConeOfColdDest2Amiga[7] = {
+	0x01, 0x02, 0xE2, 0x22, 0x03, 0xE3, 0x23
+};
+
+static const ByteProvider kEoB1ConeOfColdDest2AmigaProvider = { ARRAYSIZE(kEoB1ConeOfColdDest2Amiga), kEoB1ConeOfColdDest2Amiga };
+
+static const byte kEoB1ConeOfColdDest3Amiga[7] = {
+	0x20, 0x40, 0x3F, 0x41, 0x60, 0x5F, 0x61
+};
+
+static const ByteProvider kEoB1ConeOfColdDest3AmigaProvider = { ARRAYSIZE(kEoB1ConeOfColdDest3Amiga), kEoB1ConeOfColdDest3Amiga };
+
+static const byte kEoB1ConeOfColdDest4Amiga[7] = {
+	0xFF, 0xFE, 0x1E, 0xDE, 0xFD, 0x1D, 0xDD
+};
+
+static const ByteProvider kEoB1ConeOfColdDest4AmigaProvider = { ARRAYSIZE(kEoB1ConeOfColdDest4Amiga), kEoB1ConeOfColdDest4Amiga };
+
+static const byte kEoB1ConeOfColdGfxTblAmiga[8] = {
+	0x1f, 0x1c, 0x1f, 0x1c, 0x1d, 0x1e, 0x1d, 0x00
+};
+
+static const ByteProvider kEoB1ConeOfColdGfxTblAmigaProvider = { ARRAYSIZE(kEoB1ConeOfColdGfxTblAmiga), kEoB1ConeOfColdGfxTblAmiga };
+
+static const byte kEoB1DscDoorShapeIndexAmiga[32] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
+	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
+};
+
+static const ByteProvider kEoB1DscDoorShapeIndexAmigaProvider = { ARRAYSIZE(kEoB1DscDoorShapeIndexAmiga), kEoB1DscDoorShapeIndexAmiga };
+
+static const byte kEoB1WllFlagPresetAmiga[25] = {
+	0x07, 0x00, 0x40, 0xA8, 0x88, 0x88, 0x88, 0x9F,
+	0xA8, 0x88, 0x88, 0x88, 0x9F, 0xAA, 0x8A, 0x8A,
+	0x8A, 0x9F, 0xAA, 0x8A, 0x8A, 0x8A, 0x9F, 0x03,
+	0x03
+};
+
+static const ByteProvider kEoB1WllFlagPresetAmigaProvider = { ARRAYSIZE(kEoB1WllFlagPresetAmiga), kEoB1WllFlagPresetAmiga };
+
+static const uint16 kEoB1DscShapeCoordsAmiga[180] = {
+	0xff91, 0xffc1, 0xffa1, 0xffc1, 0xff75, 0xffc5, 0xff8b, 0xffc5,
+	0xff88, 0xffc3, 0xffb4, 0xffc1, 0xffc4, 0xffc1, 0xffa1, 0xffc5,
+	0xffb6, 0xffc5, 0xffb0, 0xffc3, 0xffd5, 0xffc1, 0xffe5, 0xffc1,
+	0xffcb, 0xffc5, 0xffe1, 0xffc5, 0xffd8, 0xffc3, 0xfff8, 0xffc1,
+	0x0008, 0xffc1, 0xfff6, 0xffc5, 0x000a, 0xffc5, 0x0000, 0xffc3,
+	0x001b, 0xffc1, 0x002b, 0xffc1, 0x001f, 0xffc5, 0x0035, 0xffc5,
+	0x0028, 0xffc3, 0x003c, 0xffc1, 0x004c, 0xffc1, 0x004a, 0xffc5,
+	0x005f, 0xffc5, 0x0050, 0xffc3, 0x005f, 0xffc1, 0x006f, 0xffc1,
+	0x0075, 0xffc5, 0x008b, 0xffc5, 0x0078, 0xffc3, 0xff8a, 0xffcb,
+	0xffa4, 0xffcb, 0xff68, 0xffd3, 0xff88, 0xffd3, 0xff8a, 0xffce,
+	0xffbe, 0xffcb, 0xffd8, 0xffcb, 0xffac, 0xffd3, 0xffcd, 0xffd3,
+	0xffc5, 0xffce, 0xfff3, 0xffcb, 0x000d, 0xffcb, 0xfff0, 0xffd3,
+	0x0010, 0xffd3, 0x0000, 0xffce, 0x0028, 0xffcb, 0x0042, 0xffcb,
+	0x0033, 0xffd3, 0x0054, 0xffd3, 0x003b, 0xffce, 0x005c, 0xffcb,
+	0x0076, 0xffcb, 0x0078, 0xffd3, 0x0098, 0xffd3, 0x0076, 0xffce,
+	0xff92, 0xffdd, 0xffbd, 0xffdd, 0xff74, 0xffea, 0xffad, 0xffea,
+	0xff9e, 0xffe2, 0xffea, 0xffdd, 0x0016, 0xffdd, 0xffe5, 0xffea,
+	0x001b, 0xffea, 0x0000, 0xffe2, 0x0043, 0xffdd, 0x006e, 0xffdd,
+	0x0053, 0xffea, 0x008c, 0xffea, 0x0062, 0xffe2, 0xff80, 0xfffc,
+	0x0080, 0xfffc, 0xff80, 0xffbe, 0x0080, 0xffbe, 0x0080, 0x0000,
+	0xffda, 0xfffc, 0x0026, 0xfffc, 0xffda, 0xffbe, 0x0026, 0xffbe,
+	0x0000, 0x0000, 0xff80, 0xfffc, 0x0080, 0xfffc, 0xff80, 0xffbe,
+	0x0080, 0xffbe, 0x0080, 0x0000
+};
+
+static const Uint16Provider kEoB1DscShapeCoordsAmigaProvider = { ARRAYSIZE(kEoB1DscShapeCoordsAmiga), kEoB1DscShapeCoordsAmiga };
+
+static const byte kEoB1DscDoorScaleOffsAmiga[32] = {
+	0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x0D, 0x0D, 0x0D,
+	0x0D, 0x0D, 0x12, 0x12, 0x12, 0x12, 0x12, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x1F
+};
+
+static const ByteProvider kEoB1DscDoorScaleOffsAmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleOffsAmiga), kEoB1DscDoorScaleOffsAmiga };
+
+static const byte kEoB1DscDoorScaleMult1Amiga[4] = {
+	0x08, 0x0C, 0x12, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorScaleMult1AmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleMult1Amiga), kEoB1DscDoorScaleMult1Amiga };
+
+static const byte kEoB1DscDoorScaleMult2Amiga[4] = {
+	0x00, 0x02, 0x04, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorScaleMult2AmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleMult2Amiga), kEoB1DscDoorScaleMult2Amiga };
+
+static const byte kEoB1DscDoorScaleMult3Amiga[4] = {
+	0x04, 0x06, 0x09, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorScaleMult3AmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleMult3Amiga), kEoB1DscDoorScaleMult3Amiga };
+
+static const byte kEoB1DscDoorScaleMult4Amiga[4] = {
+	0x00, 0x02, 0x04, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorScaleMult4AmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleMult4Amiga), kEoB1DscDoorScaleMult4Amiga };
+
+static const byte kEoB1DscDoorScaleMult5Amiga[4] = {
+	0x07, 0x0B, 0x0E, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorScaleMult5AmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleMult5Amiga), kEoB1DscDoorScaleMult5Amiga };
+
+static const byte kEoB1DscDoorScaleMult6Amiga[4] = {
+	0x00, 0x02, 0x04, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorScaleMult6AmigaProvider = { ARRAYSIZE(kEoB1DscDoorScaleMult6Amiga), kEoB1DscDoorScaleMult6Amiga };
+
+static const byte kEoB1DscDoorXEAmiga[32] = {
+	0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x0D, 0x0D, 0x0D,
+	0x0D, 0x0D, 0x12, 0x12, 0x12, 0x12, 0x12, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x1F
+};
+
+static const ByteProvider kEoB1DscDoorXEAmigaProvider = { ARRAYSIZE(kEoB1DscDoorXEAmiga), kEoB1DscDoorXEAmiga };
+
+static const byte kEoB1DscDoorY1Amiga[4] = {
+	0x3A, 0x47, 0x56, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorY1AmigaProvider = { ARRAYSIZE(kEoB1DscDoorY1Amiga), kEoB1DscDoorY1Amiga };
+
+static const byte kEoB1DscDoorY3Amiga[4] = {
+	0x20, 0x20, 0x18, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorY3AmigaProvider = { ARRAYSIZE(kEoB1DscDoorY3Amiga), kEoB1DscDoorY3Amiga };
+
+static const byte kEoB1DscDoorY4Amiga[4] = {
+	0x1E, 0x18, 0x10, 0x30
+};
+
+static const ByteProvider kEoB1DscDoorY4AmigaProvider = { ARRAYSIZE(kEoB1DscDoorY4Amiga), kEoB1DscDoorY4Amiga };
+
+static const byte kEoB1DscDoorY5Amiga[4] = {
+	0x30, 0x34, 0x3B, 0x3A
+};
+
+static const ByteProvider kEoB1DscDoorY5AmigaProvider = { ARRAYSIZE(kEoB1DscDoorY5Amiga), kEoB1DscDoorY5Amiga };
+
+static const byte kEoB1DscDoorY6Amiga[4] = {
+	0x3A, 0x45, 0x5A, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorY6AmigaProvider = { ARRAYSIZE(kEoB1DscDoorY6Amiga), kEoB1DscDoorY6Amiga };
+
+static const byte kEoB1DscDoorY7Amiga[4] = {
+	0x3B, 0x47, 0x58, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorY7AmigaProvider = { ARRAYSIZE(kEoB1DscDoorY7Amiga), kEoB1DscDoorY7Amiga };
+
+static const uint16 kEoB1DscDoorCoordsExtAmiga[36] = {
+	0x0000, 0x0000, 0xFFE8, 0x0010, 0x0020, 0x0040, 0x0048, 0x0068,
+	0x0070, 0x0090, 0x00A0, 0x00C8, 0x0000, 0x0000, 0x0000, 0x0000,
+	0xFFE8, 0x0030, 0x0038, 0x0078, 0x0080, 0x00C8, 0x0000, 0x0000,
+	0xFFA8, 0x0020, 0x0028, 0x0088, 0x0090, 0x0108, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const Uint16Provider kEoB1DscDoorCoordsExtAmigaProvider = { ARRAYSIZE(kEoB1DscDoorCoordsExtAmiga), kEoB1DscDoorCoordsExtAmiga };
+
+static const byte kEoB1DscDoorFrameY1Amiga[32] = {
+	0x20, 0x18, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x20, 0x18, 0x00, 0x1E, 0x18, 0x10, 0x00,
+	0x3A, 0x48, 0x60, 0x78, 0x3A, 0x46, 0x56, 0x00,
+	0x78, 0x78, 0x78, 0x78, 0x1F, 0x18, 0x0F, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorFrameY1AmigaProvider = { ARRAYSIZE(kEoB1DscDoorFrameY1Amiga), kEoB1DscDoorFrameY1Amiga };
+
+static const byte kEoB1DscDoorFrameY2Amiga[32] = {
+	0x20, 0x18, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x20, 0x18, 0x00, 0x1E, 0x18, 0x10, 0x00,
+	0x3A, 0x48, 0x60, 0x78, 0x3A, 0x46, 0x56, 0x00,
+	0x78, 0x78, 0x78, 0x78, 0x1F, 0x18, 0x0F, 0x00
+};
+
+static const ByteProvider kEoB1DscDoorFrameY2AmigaProvider = { ARRAYSIZE(kEoB1DscDoorFrameY2Amiga), kEoB1DscDoorFrameY2Amiga };
+
+static const byte kEoB1DscDoorFrameIndex1Amiga[12] = {
+	0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08,
+	0x08, 0x0C, 0x0C, 0x1C
+};
+
+static const ByteProvider kEoB1DscDoorFrameIndex1AmigaProvider = { ARRAYSIZE(kEoB1DscDoorFrameIndex1Amiga), kEoB1DscDoorFrameIndex1Amiga };
+
+static const byte kEoB1DscDoorFrameIndex2Amiga[12] = {
+	0x10, 0x10, 0x10, 0x18, 0x18, 0x18, 0x10, 0x10,
+	0x10, 0x14, 0x14, 0x18
+};
+
+static const ByteProvider kEoB1DscDoorFrameIndex2AmigaProvider = { ARRAYSIZE(kEoB1DscDoorFrameIndex2Amiga), kEoB1DscDoorFrameIndex2Amiga };
+
+static const byte kEoB1DscItemPosIndexAmiga[16] = {
+	0x00, 0x01, 0x02, 0x03, 0x02, 0x00, 0x03, 0x01,
+	0x03, 0x02, 0x01, 0x00, 0x01, 0x03, 0x00, 0x02
+};
+
+static const ByteProvider kEoB1DscItemPosIndexAmigaProvider = { ARRAYSIZE(kEoB1DscItemPosIndexAmiga), kEoB1DscItemPosIndexAmiga };
+
+static const uint16 kEoB1DscItemShpXAmiga[18] = {
+	0xFFC8, 0xFFF8, 0x0028, 0x0058, 0x0088, 0x00B8, 0x00E8, 0xFFB8,
+	0x0008, 0x0058, 0x00A8, 0x00F8, 0xFFD8, 0x0058, 0x00D8, 0xFFA8,
+	0x0058, 0x0108
+};
+
+static const Uint16Provider kEoB1DscItemShpXAmigaProvider = { ARRAYSIZE(kEoB1DscItemShpXAmiga), kEoB1DscItemShpXAmiga };
+
+static const byte kEoB1DscItemScaleIndexAmiga[18] = {
+	0xFF, 0xFF, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
+	0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xFF, 0xFF,
+	0x25, 0x00
+};
+
+static const ByteProvider kEoB1DscItemScaleIndexAmigaProvider = { ARRAYSIZE(kEoB1DscItemScaleIndexAmiga), kEoB1DscItemScaleIndexAmiga };
+
+static const byte kEoB1DscItemTileIndexAmiga[18] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x09, 0xFF, 0x0B,
+	0x0C, 0x0D
+};
+
+static const ByteProvider kEoB1DscItemTileIndexAmigaProvider = { ARRAYSIZE(kEoB1DscItemTileIndexAmiga), kEoB1DscItemTileIndexAmiga };
+
+static const byte kEoB1DscItemShapeMapAmiga[90] = {
+	0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04,
+	0x05, 0x06, 0x07, 0x07, 0x12, 0x06, 0x0f, 0x12,
+	0x14, 0x17, 0x13, 0x11, 0x15, 0x0d, 0x09, 0x09,
+	0x16, 0x1f, 0x0c, 0x23, 0x0c, 0x0c, 0x0c, 0x0b,
+	0x0a, 0x1c, 0x1c, 0x1a, 0x1b, 0x21, 0x1d, 0x1d,
+	0x22, 0x22, 0x22, 0x00, 0x08, 0x00, 0x25, 0x18,
+	0x16, 0x17, 0x16, 0x17, 0x16, 0x17, 0x19, 0x23,
+	0x10, 0x1e, 0x24, 0x18, 0x1c, 0x20, 0x12, 0x21,
+	0x1e, 0x23, 0x1c, 0x00, 0x20, 0x11, 0x11, 0x0d,
+	0x1f, 0x09, 0x09, 0x15, 0x15, 0x0f, 0x05, 0x0c,
+	0x1e, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1b,
+	0x1b, 0x00
+};
+
+static const ByteProvider kEoB1DscItemShapeMapAmigaProvider = { ARRAYSIZE(kEoB1DscItemShapeMapAmiga), kEoB1DscItemShapeMapAmiga };
+
+static const byte kEoB1DscTelptrShpCoordsAmiga[156] = {
+	0x0c, 0x07, 0x1a, 0x01, 0x3e, 0x03, 0x0c, 0x1a,
+	0x2a, 0x13, 0x40, 0x18, 0x02, 0x2d, 0x16, 0x25,
+	0x28, 0x32, 0x36, 0x27, 0x0a, 0x3e, 0x16, 0x49,
+	0x3e, 0x44, 0x06, 0x06, 0x2a, 0x04, 0x37, 0x0a,
+	0x04, 0x1b, 0x1a, 0x16, 0x37, 0x1d, 0x0e, 0x2a,
+	0x1b, 0x35, 0x2e, 0x28, 0x42, 0x30, 0x06, 0x47,
+	0x06, 0x47, 0x2d, 0x4c, 0x0a, 0x04, 0x14, 0x00,
+	0x2e, 0x01, 0x0c, 0x10, 0x1f, 0x10, 0x2f, 0x10,
+	0x12, 0x18, 0x28, 0x1d, 0x01, 0x21, 0x08, 0x2a,
+	0x11, 0x32, 0x2f, 0x2e, 0x1f, 0x25, 0x02, 0x02,
+	0x01, 0x11, 0x01, 0x2f, 0x08, 0x1e, 0x11, 0x0e,
+	0x11, 0x26, 0x1c, 0x01, 0x1e, 0x19, 0x1f, 0x33,
+	0x24, 0x11, 0x26, 0x05, 0x28, 0x2b, 0x2f, 0x22,
+	0x00, 0x13, 0x05, 0x01, 0x06, 0x08, 0x09, 0x0c,
+	0x04, 0x1a, 0x08, 0x1f, 0x12, 0x05, 0x12, 0x15,
+	0x16, 0x10, 0x1a, 0x08, 0x1a, 0x1d, 0x0a, 0x00,
+	0x0a, 0x00, 0x00, 0x09, 0x00, 0x1e, 0x04, 0x11,
+	0x08, 0x16, 0x08, 0x06, 0x10, 0x00, 0x11, 0x0d,
+	0x12, 0x20, 0x15, 0x02, 0x14, 0x09, 0x16, 0x1b,
+	0x1a, 0x14, 0x1a, 0x14
+};
+
+static const ByteProvider kEoB1DscTelptrShpCoordsAmigaProvider = { ARRAYSIZE(kEoB1DscTelptrShpCoordsAmiga), kEoB1DscTelptrShpCoordsAmiga };
+
+static const byte kEoB1PortalSeqDataAmiga[126] = {
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00,
+	0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00,
+	0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00,
+	0x04, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
+	0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
+	0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x03, 0x02,
+	0x02, 0x03, 0x01, 0x04, 0x00, 0x02, 0x01, 0x03,
+	0x02, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x04,
+	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
+	0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x03, 0x07,
+	0x02, 0x08, 0x02, 0x08, 0x01, 0x09, 0x01, 0x09,
+	0x01, 0x09, 0x00, 0x0a, 0xff, 0xff
+};
+
+static const ByteProvider kEoB1PortalSeqDataAmigaProvider = { ARRAYSIZE(kEoB1PortalSeqDataAmiga), kEoB1PortalSeqDataAmiga };
+
+static const byte kEoB1DscMonsterFrmOffsTbl1Amiga[32] = {
+	0x04, 0xfe, 0x01, 0x03, 0x03, 0x04, 0xfe, 0x01,
+	0x01, 0x03, 0x04, 0xfe, 0xfe, 0x01, 0x03, 0x04,
+	0xfc, 0xfd, 0xff, 0x02, 0x02, 0xfc, 0xfd, 0xff,
+	0xff, 0x02, 0xfc, 0xfd, 0xfd, 0xff, 0x02, 0xfc
+};
+
+static const ByteProvider kEoB1DscMonsterFrmOffsTbl1AmigaProvider = { ARRAYSIZE(kEoB1DscMonsterFrmOffsTbl1Amiga), kEoB1DscMonsterFrmOffsTbl1Amiga };
+
+static const byte kEoB1DscMonsterFrmOffsTbl2Amiga[32] = {
+	0x04, 0xfe, 0x01, 0x03, 0x03, 0x04, 0xfe, 0x01,
+	0x01, 0x03, 0x04, 0xfe, 0xfe, 0x01, 0x03, 0x04,
+	0x04, 0xfd, 0x01, 0x02, 0x02, 0x04, 0xfd, 0x01,
+	0x01, 0x02, 0x04, 0xfd, 0xfd, 0x01, 0x02, 0x04
+};
+
+static const ByteProvider kEoB1DscMonsterFrmOffsTbl2AmigaProvider = { ARRAYSIZE(kEoB1DscMonsterFrmOffsTbl2Amiga), kEoB1DscMonsterFrmOffsTbl2Amiga };
+
+static const uint16 kEoB1InvSlotXAmiga[27] = {
+	0x00e6, 0x0116, 0x00b5, 0x00c7, 0x00b5, 0x00c7, 0x00b5, 0x00c7,
+	0x00b5, 0x00c7, 0x00b5, 0x00c7, 0x00b5, 0x00c7, 0x00b5, 0x00c7,
+	0x00e1, 0x00e0, 0x00e1, 0x012a, 0x011f, 0x0115, 0x012c, 0x012c,
+	0x012c, 0x00e4, 0x00f0
+};
+
+static const Uint16Provider kEoB1InvSlotXAmigaProvider = { ARRAYSIZE(kEoB1InvSlotXAmiga), kEoB1InvSlotXAmiga };
+
+static const byte kEoB1InvSlotYAmiga[27] = {
+	0x74, 0x74, 0x28, 0x28, 0x3a, 0x3a, 0x4c, 0x4c,
+	0x5e, 0x5e, 0x70, 0x70, 0x82, 0x82, 0x94, 0x94,
+	0x38, 0x4c, 0x60, 0x37, 0x4b, 0x89, 0x5e, 0x70,
+	0x82, 0x88, 0x88
+};
+
+static const ByteProvider kEoB1InvSlotYAmigaProvider = { ARRAYSIZE(kEoB1InvSlotYAmiga), kEoB1InvSlotYAmiga };
+
+static const uint16 kEoB1SlotValidationFlagsAmiga[27] = {
+	0x0008, 0x0008, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+	0x0001, 0x0002, 0x0004, 0x0020, 0x0040, 0x0010, 0xFFFF, 0x0080,
+	0x0080, 0x0100, 0x0100
+};
+
+static const Uint16Provider kEoB1SlotValidationFlagsAmigaProvider = { ARRAYSIZE(kEoB1SlotValidationFlagsAmiga), kEoB1SlotValidationFlagsAmiga };
+
+static const byte kEoB1ProjectileWeaponTypesAmiga[8] = {
+	0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x12
+};
+
+static const ByteProvider kEoB1ProjectileWeaponTypesAmigaProvider = { ARRAYSIZE(kEoB1ProjectileWeaponTypesAmiga), kEoB1ProjectileWeaponTypesAmiga };
+
+static const byte kEoB1WandTypesAmiga[7] = {
+	0x00, 0x12, 0x18, 0x28, 0x0D, 0xFF, 0x04
+};
+
+static const ByteProvider kEoB1WandTypesAmigaProvider = { ARRAYSIZE(kEoB1WandTypesAmiga), kEoB1WandTypesAmiga };
+
+static const byte kEoB1DrawObjPosIndexAmiga[20] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x02, 0x00, 0x03,
+	0x01, 0x04, 0x02, 0x03, 0x00, 0x01, 0x04, 0x01,
+	0x03, 0x00, 0x02, 0x04
+};
+
+static const ByteProvider kEoB1DrawObjPosIndexAmigaProvider = { ARRAYSIZE(kEoB1DrawObjPosIndexAmiga), kEoB1DrawObjPosIndexAmiga };
+
+static const byte kEoB1FlightObjFlipIndexAmiga[16] = {
+	0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01,
+	0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00
+};
+
+static const ByteProvider kEoB1FlightObjFlipIndexAmigaProvider = { ARRAYSIZE(kEoB1FlightObjFlipIndexAmiga), kEoB1FlightObjFlipIndexAmiga };
+
+static const byte kEoB1FlightObjShpMapAmiga[88] = {
+	0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+	0xff, 0xff, 0x03, 0xff, 0x05, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const ByteProvider kEoB1FlightObjShpMapAmigaProvider = { ARRAYSIZE(kEoB1FlightObjShpMapAmiga), kEoB1FlightObjShpMapAmiga };
+
+static const byte kEoB1FlightObjSclIndexAmiga[72] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+	0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0x03,
+	0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x02, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const ByteProvider kEoB1FlightObjSclIndexAmigaProvider = { ARRAYSIZE(kEoB1FlightObjSclIndexAmiga), kEoB1FlightObjSclIndexAmiga };
+
+static const byte kEoB1DscShapeIndexAmiga[36] = {
+	0x01, 0x01, 0x04, 0x0a, 0x04, 0x08, 0x04, 0x01,
+	0x04, 0xf8, 0x04, 0xf6, 0x00, 0x00, 0x03, 0x09,
+	0x03, 0x07, 0x03, 0x01, 0x03, 0xf9, 0x03, 0xf7,
+	0x02, 0x06, 0x02, 0x01, 0x02, 0xfa, 0x01, 0x05,
+	0x01, 0x01, 0x01, 0xfb
+};
+
+static const ByteProvider kEoB1DscShapeIndexAmigaProvider = { ARRAYSIZE(kEoB1DscShapeIndexAmiga), kEoB1DscShapeIndexAmiga };
+
+static const uint16 kEoB1DscXAmiga[18] = {
+	0xFF70, 0xFFA0, 0xFFD0, 0x0000, 0x0030, 0x0060, 0x0090, 0xFF60,
+	0xFFB0, 0x0000, 0x0050, 0x00A0, 0xFF80, 0x0000, 0x0080, 0x0000,
+	0x0000, 0x0000
+};
+
+static const Uint16Provider kEoB1DscXAmigaProvider = { ARRAYSIZE(kEoB1DscXAmiga), kEoB1DscXAmiga };
+
+static const byte kEoB1DscTileIndexAmiga[18] = {
+	0x00, 0x06, 0x01, 0x05, 0x02, 0x04, 0x03, 0x07,
+	0x0B, 0x08, 0x0A, 0x09, 0x0C, 0x0E, 0x0D, 0x0F,
+	0x11, 0x10
+};
+
+static const ByteProvider kEoB1DscTileIndexAmigaProvider = { ARRAYSIZE(kEoB1DscTileIndexAmiga), kEoB1DscTileIndexAmiga };
+
+static const byte kEoB1DscDimData1Amiga[324] = {
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+	0xd8, 0xd7, 0xd8, 0xd8, 0x02, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xfe, 0xd7, 0xd8, 0xd8, 0xd8, 0xd7, 0x03,
+	0xd8, 0xfd, 0xd8, 0xd8, 0xd8, 0xfe, 0xd8, 0x08,
+	0xd8, 0xd8, 0xd8, 0xfe, 0xd7, 0x06, 0xd8, 0xd8,
+	0xfa, 0x03, 0xd8, 0xfd, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xfa, 0xd7,
+	0x10, 0xd8, 0xfd, 0xd7, 0x13, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xf2, 0xd8, 0x14, 0xd8, 0xd8,
+	0xd8, 0xf0, 0xd7, 0x14, 0xd8, 0xed, 0x10, 0xd8,
+	0xd8, 0x13, 0xd8, 0xd8, 0xd8, 0xd8, 0xec, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd7, 0x14, 0xd8, 0xed,
+	0xd7, 0xd8, 0xd8, 0x13, 0xd7, 0xd7, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd7, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd7,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0x06, 0xd8, 0xd8, 0xfa, 0x03, 0xd8, 0xfd,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xfa, 0xd8, 0x10, 0xd8, 0xfd, 0xd7,
+	0x13, 0xfd, 0xd8, 0x13, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xf0, 0xd8, 0xd8,
+	0xd8, 0xed, 0x10, 0xd8, 0xd8, 0x13, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+	0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd7,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x03, 0xd8, 0xfd,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xfd, 0xd8,
+	0x13, 0xfd, 0xd8, 0x13, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xed, 0xd8, 0xd8, 0xd8, 0x13, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+	0xd8, 0xd8, 0xd8, 0xd8
+};
+
+static const ByteProvider kEoB1DscDimData1AmigaProvider = { ARRAYSIZE(kEoB1DscDimData1Amiga), kEoB1DscDimData1Amiga };
+
+static const byte kEoB1DscDimData2Amiga[648] = {
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x00, 0x16, 0x16, 0x00, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x02, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x02, 0x16, 0x00, 0x04, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x16, 0x00, 0x00, 0x03,
+	0x00, 0x16, 0x03, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x02, 0x16, 0x00, 0x16, 0x00, 0x08,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x02,
+	0x16, 0x00, 0x00, 0x06, 0x00, 0x16, 0x00, 0x16,
+	0x06, 0x16, 0x00, 0x03, 0x00, 0x16, 0x03, 0x00,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x06, 0x16, 0x08, 0x0e,
+	0x00, 0x10, 0x00, 0x16, 0x03, 0x16, 0x06, 0x10,
+	0x00, 0x13, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x0e, 0x16,
+	0x00, 0x16, 0x00, 0x14, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x10, 0x16, 0x16, 0x00, 0x00, 0x14,
+	0x00, 0x16, 0x13, 0x16, 0x00, 0x10, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x13, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x14, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x12, 0x16, 0x14, 0x16, 0x00, 0x16, 0x13, 0x16,
+	0x16, 0x00, 0x00, 0x16, 0x00, 0x16, 0x00, 0x13,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x00, 0x16, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x00, 0x16, 0x16, 0x00,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x06, 0x00, 0x16, 0x00, 0x16,
+	0x06, 0x16, 0x00, 0x03, 0x00, 0x16, 0x03, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x06, 0x16, 0x00, 0x16,
+	0x00, 0x10, 0x00, 0x16, 0x03, 0x16, 0x07, 0x0f,
+	0x00, 0x13, 0x03, 0x16, 0x00, 0x16, 0x00, 0x13,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x10, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x13, 0x16, 0x00, 0x10, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x13, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
+	0x16, 0x00, 0x16, 0x00, 0x00, 0x16, 0x16, 0x00,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x03, 0x00, 0x16, 0x03, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x03, 0x16, 0x00, 0x16,
+	0x00, 0x13, 0x03, 0x16, 0x00, 0x16, 0x00, 0x13,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x13, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x13, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16,
+	0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16
+};
+
+static const ByteProvider kEoB1DscDimData2AmigaProvider = { ARRAYSIZE(kEoB1DscDimData2Amiga), kEoB1DscDimData2Amiga };
+
+static const byte kEoB1DscBlockMapAmiga[12] = {
+	0x02, 0x03, 0x00, 0x01, 0x01, 0x02, 0x03, 0x00,
+	0x03, 0x00, 0x01, 0x02
+};
+
+static const ByteProvider kEoB1DscBlockMapAmigaProvider = { ARRAYSIZE(kEoB1DscBlockMapAmiga), kEoB1DscBlockMapAmiga };
+
+static const byte kEoB1DscDimMapAmiga[18] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03,
+	0x03, 0x03
+};
+
+static const ByteProvider kEoB1DscDimMapAmigaProvider = { ARRAYSIZE(kEoB1DscDimMapAmiga), kEoB1DscDimMapAmiga };
+
+static const byte kEoB1DscBlockIndexAmiga[72] = {
+	0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xbe,
+	0xbf, 0xc0, 0xc1, 0xc2, 0xdf, 0xe0, 0xe1, 0xff,
+	0x00, 0x01, 0xa3, 0xc3, 0xe3, 0x03, 0x23, 0x43,
+	0x63, 0xc2, 0xe2, 0x02, 0x22, 0x42, 0xe1, 0x01,
+	0x21, 0xe0, 0x00, 0x20, 0x63, 0x62, 0x61, 0x60,
+	0x5f, 0x5e, 0x5d, 0x42, 0x41, 0x40, 0x3f, 0x3e,
+	0x21, 0x20, 0x1f, 0x01, 0x00, 0xff, 0x5d, 0x3d,
+	0x1d, 0xfd, 0xdd, 0xbd, 0x9d, 0x3e, 0x1e, 0xfe,
+	0xde, 0xbe, 0x1f, 0xff, 0xdf, 0x20, 0x00, 0xe0
+};
+
+static const ByteProvider kEoB1DscBlockIndexAmigaProvider = { ARRAYSIZE(kEoB1DscBlockIndexAmiga), kEoB1DscBlockIndexAmiga };
+
+static const byte kEoB1ClassModifierFlagsAmiga[15] = {
+	0x01, 0x01, 0x05, 0x02, 0x04, 0x08, 0x05, 0x09,
+	0x03, 0x0B, 0x0A, 0x0C, 0x07, 0x05, 0x06
+};
+
+static const ByteProvider kEoB1ClassModifierFlagsAmigaProvider = { ARRAYSIZE(kEoB1ClassModifierFlagsAmiga), kEoB1ClassModifierFlagsAmiga };
+
+static const byte kEoB1MonsterStepTable01Amiga[4] = {
+	0xE0, 0x01, 0x20, 0xFF
+};
+
+static const ByteProvider kEoB1MonsterStepTable01AmigaProvider = { ARRAYSIZE(kEoB1MonsterStepTable01Amiga), kEoB1MonsterStepTable01Amiga };
+
+static const byte kEoB1MonsterStepTable2Amiga[8] = {
+	0x07, 0xFA, 0x05, 0xFC, 0x03, 0xFE, 0x01, 0x00
+};
+
+static const ByteProvider kEoB1MonsterStepTable2AmigaProvider = { ARRAYSIZE(kEoB1MonsterStepTable2Amiga), kEoB1MonsterStepTable2Amiga };
+
+static const byte kEoB1MonsterStepTable3Amiga[8] = {
+	0xF9, 0x06, 0xFB, 0x04, 0xFD, 0x02, 0xFF, 0x00
+};
+
+static const ByteProvider kEoB1MonsterStepTable3AmigaProvider = { ARRAYSIZE(kEoB1MonsterStepTable3Amiga), kEoB1MonsterStepTable3Amiga };
+
+static const byte kEoB1MonsterCloseAttPosTable1Amiga[4] = {
+	0x00, 0x01, 0x03, 0x02
+};
+
+static const ByteProvider kEoB1MonsterCloseAttPosTable1AmigaProvider = { ARRAYSIZE(kEoB1MonsterCloseAttPosTable1Amiga), kEoB1MonsterCloseAttPosTable1Amiga };
+
+static const byte kEoB1MonsterCloseAttPosTable21Amiga[8] = {
+	0x00, 0x01, 0x02, 0x03, 0x00, 0x02, 0x01, 0x03
+};
+
+static const ByteProvider kEoB1MonsterCloseAttPosTable21AmigaProvider = { ARRAYSIZE(kEoB1MonsterCloseAttPosTable21Amiga), kEoB1MonsterCloseAttPosTable21Amiga };
+
+static const byte kEoB1MonsterCloseAttChkTable1Amiga[16] = {
+	0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00
+};
+
+static const ByteProvider kEoB1MonsterCloseAttChkTable1AmigaProvider = { ARRAYSIZE(kEoB1MonsterCloseAttChkTable1Amiga), kEoB1MonsterCloseAttChkTable1Amiga };
+
+static const byte kEoB1MonsterCloseAttChkTable2Amiga[16] = {
+	0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01,
+	0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00
+};
+
+static const ByteProvider kEoB1MonsterCloseAttChkTable2AmigaProvider = { ARRAYSIZE(kEoB1MonsterCloseAttChkTable2Amiga), kEoB1MonsterCloseAttChkTable2Amiga };
+
+static const byte kEoB1MonsterCloseAttDstTable1Amiga[16] = {
+	0x02, 0x03, 0x00, 0x01, 0x01, 0x02, 0x03, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x03, 0x00, 0x01, 0x02
+};
+
+static const ByteProvider kEoB1MonsterCloseAttDstTable1AmigaProvider = { ARRAYSIZE(kEoB1MonsterCloseAttDstTable1Amiga), kEoB1MonsterCloseAttDstTable1Amiga };
+
+static const byte kEoB1MonsterCloseAttDstTable2Amiga[48] = {
+	0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x00, 0x01,
+	0x02, 0x03, 0x04, 0x05, 0x05, 0x03, 0x01, 0x04,
+	0x02, 0x00, 0x01, 0x03, 0x05, 0x00, 0x02, 0x04,
+	0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x05, 0x04,
+	0x03, 0x02, 0x01, 0x00, 0x00, 0x02, 0x04, 0x01,
+	0x03, 0x05, 0x04, 0x02, 0x00, 0x05, 0x03, 0x01
+};
+
+static const ByteProvider kEoB1MonsterCloseAttDstTable2AmigaProvider = { ARRAYSIZE(kEoB1MonsterCloseAttDstTable2Amiga), kEoB1MonsterCloseAttDstTable2Amiga };
+
+static const byte kEoB1MonsterProximityTableAmiga[32] = {
+	0x02, 0x03, 0x00, 0x01, 0x03, 0x02, 0x01, 0x00,
+	0x00, 0x02, 0x01, 0x03, 0x02, 0x00, 0x03, 0x01,
+	0x01, 0x00, 0x03, 0x02, 0x00, 0x01, 0x02, 0x03,
+	0x03, 0x01, 0x00, 0x02, 0x01, 0x03, 0x02, 0x00
+};
+
+static const ByteProvider kEoB1MonsterProximityTableAmigaProvider = { ARRAYSIZE(kEoB1MonsterProximityTableAmiga), kEoB1MonsterProximityTableAmiga };
+
+static const byte kEoB1FindBlockMonstersTableAmiga[64] = {
+	0x04, 0x02, 0x01, 0x03, 0x04, 0x03, 0x00, 0x02,
+	0x04, 0x00, 0x03, 0x01, 0x04, 0x01, 0x02, 0x00,
+	0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x03, 0x02,
+	0x04, 0x03, 0x00, 0x01, 0x04, 0x02, 0x01, 0x00,
+	0x04, 0x02, 0x01, 0x03, 0x04, 0x03, 0x00, 0x02,
+	0x04, 0x00, 0x03, 0x01, 0x04, 0x01, 0x02, 0x00,
+	0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x03, 0x02,
+	0x04, 0x03, 0x00, 0x01, 0x04, 0x02, 0x01, 0x00
+};
+
+static const ByteProvider kEoB1FindBlockMonstersTableAmigaProvider = { ARRAYSIZE(kEoB1FindBlockMonstersTableAmiga), kEoB1FindBlockMonstersTableAmiga };
+
+static const byte kEoB1MonsterDirChangeTableAmiga[48] = {
+	0xff, 0x06, 0x02, 0xff, 0x00, 0x07, 0x01, 0xff,
+	0x04, 0x05, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const ByteProvider kEoB1MonsterDirChangeTableAmigaProvider = { ARRAYSIZE(kEoB1MonsterDirChangeTableAmiga), kEoB1MonsterDirChangeTableAmiga };
+
+static const uint16 kEoB1EncodeMonsterDefsAmiga[168] = {
+	0x0000, 0x0000, 0x0007, 0x0060, 0x0007, 0x0028, 0x000c, 0x0039,
+	0x0013, 0x0028, 0x000c, 0x0039, 0x001f, 0x0000, 0x0007, 0x0060,
+	0x0000, 0x0060, 0x0007, 0x0060, 0x0007, 0x0060, 0x0007, 0x0060,
+	0x000e, 0x0060, 0x0005, 0x0038, 0x0000, 0x0000, 0x0005, 0x0042,
+	0x0007, 0x0000, 0x0008, 0x0027, 0x0013, 0x0000, 0x0008, 0x0027,
+	0x001f, 0x0000, 0x0005, 0x0042, 0x001d, 0x0060, 0x0005, 0x0038,
+	0x000e, 0x0098, 0x0003, 0x0020, 0x0000, 0x0000, 0x0004, 0x0030,
+	0x0007, 0x0000, 0x0005, 0x001a, 0x0013, 0x0000, 0x0005, 0x001a,
+	0x001f, 0x0000, 0x0004, 0x0030, 0x001f, 0x0098, 0x0003, 0x0020,
+	0x0000, 0x0000, 0x0007, 0x0060, 0x0007, 0x0000, 0x0007, 0x0060,
+	0x000e, 0x0000, 0x0007, 0x0060, 0x0015, 0x0000, 0x0007, 0x0060,
+	0x001c, 0x0000, 0x0007, 0x0060, 0x0000, 0x0060, 0x0007, 0x0060,
+	0x0007, 0x0060, 0x0006, 0x003f, 0x000d, 0x0060, 0x0006, 0x003f,
+	0x0013, 0x0060, 0x0006, 0x003f, 0x0019, 0x0060, 0x0006, 0x003f,
+	0x001b, 0x0060, 0x0005, 0x0038, 0x0020, 0x0060, 0x0005, 0x0038,
+	0x0007, 0x008c, 0x0003, 0x002b, 0x000b, 0x008c, 0x0003, 0x002b,
+	0x000f, 0x008c, 0x0003, 0x002b, 0x0013, 0x008c, 0x0003, 0x002b,
+	0x0013, 0x0098, 0x0003, 0x0020, 0x0016, 0x0098, 0x0003, 0x0020,
+	0x0000, 0x0000, 0x000a, 0x0057, 0x000a, 0x0000, 0x000a, 0x0057,
+	0x0014, 0x0000, 0x000a, 0x0057, 0x001e, 0x0000, 0x000a, 0x0057,
+	0x0000, 0x0058, 0x000a, 0x0057, 0x000a, 0x0058, 0x000a, 0x0057
+};
+
+static const Uint16Provider kEoB1EncodeMonsterDefsAmigaProvider = { ARRAYSIZE(kEoB1EncodeMonsterDefsAmiga), kEoB1EncodeMonsterDefsAmiga };
+
+static const EoBCharacter kEoB1NpcPresetsAmiga[9] = {
+	{ 0x00, 0x01, "Anya",
+	  18, 18, 59, 59,  5,  5, 11, 11, 14, 14, 16, 16,  9,  9,
+	    45,   45, 10, 0, 1, 0, 2, -1, 100, { 4, 0, 0 },
+	  { 0x00001F40, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Beohram",
+	  17, 17,  0,  0,  9,  9, 15, 15, 13, 13, 18, 18, 17, 17,
+	    55,   55, 10, 0, 0, 0, 0, -2, 100, { 7, 0, 0 },
+	  { 0x000130B0, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Kirath",
+	  11, 11,  0,  0, 17, 17, 13, 13, 18, 18,  8,  8, 12, 12,
+	    20,   20, 10, 0, 4, 3, 4, -3, 100, { 7, 0, 0 },
+	  { 0x00011170, 0x00000000, 0x00000000 }, 0x00B3126B,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Ileria",
+	  10, 10,  0,  0, 12, 12,  9,  9, 15, 15, 17, 17, 17, 17,
+	    52,   52, 10, 0, 4, 4, 0, -4, 100, { 6, 0, 0 },
+	  { 0x00004E20, 0x00000000, 0x00000000 }, 0xFFFFFFFF,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Tyrra",
+	  16, 16,  0,  0, 14, 14, 16, 16, 18, 18, 17, 17,  7,  7,
+	    45,   45, 10, 0, 1, 1, 2, -5, 100, { 6, 0, 0 },
+	  { 0x0000CF08, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Tod Uphill",
+	  17, 17,  0,  0, 11, 11, 14, 14, 19, 19, 18, 18, 16, 16,
+	    32,   32, 10, 0, 10, 5, 5, -6, 100, { 5, 0, 0 },
+	  { 0x00002D3F, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Taghor",
+	  17, 17,  0,  0, 11, 11, 15, 15, 15, 15, 19, 19,  9,  9,
+	     3,   45,  3, 0, 6, 0, 1, -7, 25, { 5, 0, 0 },
+	  { 0x00003F6A, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0024, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0029, 0x0000, 0x002B, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Dohrum",
+	  18, 18, 29, 29, 13, 13, 11, 11, 16, 16, 17, 17, 14, 14,
+	    28,   28, 10, 0, 6, 0, 0, -8, 100, { 3, 0, 0 },
+	  { 0x000013A0, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0024, 0x0000, 0x0030, 0x0037, 0x0037, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0029, 0x0000, 0x002B, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } },
+	{ 0x00, 0x01, "Keirgar",
+	  18, 18, 92, 92, 15, 15, 15, 15, 12, 12, 19, 19, 17, 17,
+	     3,   45,  3, 0, 6, 0, 1, -9, 25, { 5, 0, 0 },
+	  { 0x00001F40, 0x00000000, 0x00000000 }, 0x00000000,
+	  { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	    0x0000, 0x0000, 0x0000 } }
+};
+
+static const EoBCharacterProvider kEoB1NpcPresetsAmigaProvider = { ARRAYSIZE(kEoB1NpcPresetsAmiga), kEoB1NpcPresetsAmiga };
+
+static const byte kEoB1CouncilAnimData1Amiga[78] = {
+	0x21, 0x58, 0x03, 0x10, 0x07, 0x60, 0x24, 0x58,
+	0x03, 0x10, 0x07, 0x60, 0x00, 0x0b, 0x68, 0x02,
+	0x08, 0x0b, 0x60, 0x0d, 0x68, 0x02, 0x08, 0x0b,
+	0x60, 0x00, 0x0f, 0x68, 0x01, 0x08, 0x0f, 0x48,
+	0x10, 0x68, 0x01, 0x08, 0x0f, 0x48, 0x00, 0x07,
+	0x68, 0x02, 0x08, 0x21, 0x58, 0x09, 0x68, 0x02,
+	0x08, 0x21, 0x58, 0x00, 0x00, 0x70, 0x03, 0x10,
+	0x25, 0x60, 0x00, 0x80, 0x03, 0x10, 0x25, 0x60,
+	0x00, 0x21, 0x48, 0x03, 0x10, 0x19, 0x50, 0x24,
+	0x48, 0x03, 0x10, 0x19, 0x50, 0x00
+};
+
+static const ByteProvider kEoB1CouncilAnimData1AmigaProvider = { ARRAYSIZE(kEoB1CouncilAnimData1Amiga), kEoB1CouncilAnimData1Amiga };
+
+static const byte kEoB1CouncilAnimData2Amiga[78] = {
+	0x0f, 0x98, 0x03, 0x18, 0x00, 0x40, 0x0c, 0x98,
+	0x03, 0x18, 0x00, 0x40, 0x00, 0x06, 0x70, 0x03,
+	0x20, 0x07, 0x38, 0x03, 0x70, 0x03, 0x20, 0x07,
+	0x38, 0x00, 0x03, 0x90, 0x03, 0x20, 0x0d, 0x38,
+	0x00, 0x90, 0x03, 0x20, 0x0d, 0x38, 0x00, 0x09,
+	0x98, 0x03, 0x18, 0x19, 0x38, 0x06, 0x98, 0x03,
+	0x18, 0x19, 0x38, 0x00, 0x15, 0x98, 0x03, 0x18,
+	0x1f, 0x40, 0x12, 0x98, 0x03, 0x18, 0x1f, 0x40,
+	0x00, 0x1b, 0x98, 0x03, 0x18, 0x25, 0x38, 0x18,
+	0x98, 0x03, 0x18, 0x25, 0x38, 0x00
+};
+
+static const ByteProvider kEoB1CouncilAnimData2AmigaProvider = { ARRAYSIZE(kEoB1CouncilAnimData2Amiga), kEoB1CouncilAnimData2Amiga };
+
+static const byte kEoB1CouncilAnimData3Amiga[12] = {
+	0x1f, 0x68, 0x07, 0x30, 0x11, 0x40, 0x18, 0x68,
+	0x07, 0x30, 0x11, 0x40
+};
+
+static const ByteProvider kEoB1CouncilAnimData3AmigaProvider = { ARRAYSIZE(kEoB1CouncilAnimData3Amiga), kEoB1CouncilAnimData3Amiga };
+
+static const byte kEoB1CouncilAnimData4Amiga[24] = {
+	0x00, 0xb0, 0x05, 0x10, 0x00, 0x78, 0x09, 0x70,
+	0x04, 0x28, 0x0c, 0x68,	0x11, 0x68, 0x07, 0x30,
+	0x11, 0x60, 0x00, 0xb0,	0x05, 0x10, 0x1e, 0x78
+};
+
+static const ByteProvider kEoB1CouncilAnimData4AmigaProvider = { ARRAYSIZE(kEoB1CouncilAnimData4Amiga), kEoB1CouncilAnimData4Amiga };
+
+static const byte kEoB1EyesAnimDataAmiga[28] = {
+	0x01, 0x00, 0x0f, 0x01, 0x00, 0x0f, 0x02, 0x03,
+	0x04, 0x0f, 0x01, 0x04, 0x0f, 0x01, 0x04, 0x0f,
+	0x01, 0x04, 0x0f, 0x03, 0x02, 0x00, 0x0f, 0x02,
+	0x03, 0x04, 0x28, 0xff
+};
+
+static const ByteProvider kEoB1EyesAnimDataAmigaProvider = { ARRAYSIZE(kEoB1EyesAnimDataAmiga), kEoB1EyesAnimDataAmiga };
+
+static const uint16 kEoB1HandsAnimDataAmiga[24] = {
+	0xfffd, 0x004c, 0x0018, 0x0047, 0x0036, 0x0041, 0x004c, 0x0039,
+	0x0059, 0x0032, 0x00db, 0x0055, 0x00c2, 0x0049, 0x00a9, 0x003c,
+	0x0090, 0x0030, 0x0057, 0x0035, 0x0059, 0x0034, 0x005b, 0x0033
+};
+
+static const Uint16Provider kEoB1HandsAnimDataAmigaProvider = { ARRAYSIZE(kEoB1HandsAnimDataAmiga), kEoB1HandsAnimDataAmiga };
+
+static const byte kEoB1TextFrameDurationAmiga[153] = {
+	0x04, 0x02, 0x05, 0x02, 0x0b, 0x02, 0x04, 0x02,
+	0x08, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x04, 0x02, 0x05, 0x02, 0x06, 0x02, 0x08,
+	0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x02, 0x02, 0x05, 0x7e, 0x05,
+	0x02, 0x03, 0x02, 0x03, 0x7e, 0x7f, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x07, 0x02, 0x04, 0x02,
+	0x05, 0x02, 0x07, 0x02, 0x02, 0x02, 0x06, 0x02,
+	0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02,
+	0x08, 0x02, 0x04, 0x02, 0x03, 0x02, 0x0a, 0x7f,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x05, 0x02, 0x04, 0x02, 0x05, 0x02, 0x02, 0x05,
+	0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x02, 0x0a,
+	0x7f
+};
+
+static const ByteProvider kEoB1TextFrameDurationAmigaProvider = { ARRAYSIZE(kEoB1TextFrameDurationAmiga), kEoB1TextFrameDurationAmiga };
+
+static const char *const kEoB1SoundMapAmiga[120] = {
+	"",
+	"button",
+	"L1M1A",
+	"door",
+	"door",
+	"slam",
+	"button",
+	"button",
+	"transmute",
+	"eat",
+	"magica",
+	"throw",
+	"plate",
+	"passage",
+	"unlock",
+	"teleport",
+	"undead",
+	"pit",
+	"itemland",
+	"",
+	"",
+	"playhit",
+	"death",
+	"text",
+	"electric",
+	"dart",
+	"dart",
+	"unlock",
+	"bonus",
+	"bump",
+	"",
+	"electric",
+	"playswing",
+	"hum",
+	"panel",
+	"explode",
+	"L10M2M",
+	"L10M2A",
+	"L4M1M",
+	"beastatk",
+	"L9M2M",
+	"L8M1A",
+	"L8M1M",
+	"L7M1A",
+	"L7M1M",
+	"L5M1A",
+	"L5M1M",
+	"flindatk",
+	"L3M2M",
+	"L4M1A",
+	"L8M2M",
+	"houndatk",
+	"scream",
+	"L6M1M",
+	"L3M1A",
+	"L3M1M",
+	"sloshsuck",
+	"L1M2M",
+	"flayeratk",
+	"",
+	"rustatk",
+	"L9M1M",
+	"L10M1A",
+	"L10M1M",
+	"blade",
+	"L7M2M",
+	"blade",
+	"L2M2M",
+	"L12M2A",
+	"L12M2M",
+	"",
+	"L11M1M",
+	"L11M1A",
+	"L2M1A",
+	"L2M1M",
+	"L1M1M",
+	"button",
+	"",
+	"drop",
+	"text",
+	"magicb",
+	"lock",
+	"",
+	"",
+	"",
+	"Missile",
+	"",
+	"burnhands",
+	"electric",
+	"fireball",
+	"",
+	"magica",
+	"magica",
+	"magica",
+	"magicb",
+	"magicb",
+	"acid",
+	"magicb",
+	"fireball",
+	"acid",
+	"magica",
+	"magicb",
+	"magicb",
+	"undead",
+	"magica",
+	"magica",
+	"magica",
+	"magicb",
+	"cause",
+	"magicb",
+	"magicb",
+	"magica",
+	"magicb",
+	"magica",
+	"magica",
+	"magica",
+	"magica",
+	"cause",
+	"",
+	"door"
+};
+
+static const StringListProvider kEoB1SoundMapAmigaProvider = { ARRAYSIZE(kEoB1SoundMapAmiga), kEoB1SoundMapAmiga };
+
+static const char *const kEoB1LevelSoundFiles1Amiga[26] = {
+	"",
+	"",
+	"sloshsuck1",
+	"",
+	"blade1",
+	"",
+	"beastatk1",
+	"",
+	"rustatk1",
+	"",
+	"rustatk1",
+	"blade1",
+	"scream1",
+	"",
+	"blade1",
+	"",
+	"houndatk1",
+	"",
+	"rustatk1",
+	"beastatk1",
+	"blade1",
+	"",
+	"beastatk1",
+	"flayeratk1",
+	"",
+	""
+};
+
+static const StringListProvider kEoB1LevelSoundFiles1AmigaProvider = { ARRAYSIZE(kEoB1LevelSoundFiles1Amiga), kEoB1LevelSoundFiles1Amiga };
+
+static const char *const kEoB1LevelSoundFiles2Amiga[26] = {
+	"",
+	"",
+	"move1",
+	"leechmov1",
+	"move21",
+	"",
+	"move21",
+	"kuotoamov1",
+	"spidermov1",
+	"",
+	"spidermov1",
+	"move21",
+	"move21",
+	"",
+	"move1",
+	"move21",
+	"move1",
+	"spidermov1",
+	"move1",
+	"move21",
+	"mantismov1",
+	"move21",
+	"move21",
+	"",
+	"move21",
+	""
+};
+
+static const StringListProvider kEoB1LevelSoundFiles2AmigaProvider = { ARRAYSIZE(kEoB1LevelSoundFiles2Amiga), kEoB1LevelSoundFiles2Amiga };
+
+static const char *const kEoB1SoundFilesIntroAmiga[6] = {
+	"INTRO1.CPS",
+	"INTRO2.CPS",
+	"INTRO4.CPS",
+	"INTRO5.CPS",
+	"NEWINTRO1.CPS",
+	"CHARGEN1.CPS"
+};
+
+static const StringListProvider kEoB1SoundFilesIntroAmigaProvider = { ARRAYSIZE(kEoB1SoundFilesIntroAmiga), kEoB1SoundFilesIntroAmiga };
+
+static const char *const kEoB1SoundFilesIngameAmiga[5] = {
+	"SFX1.CPS",
+	"SFX2.CPS",
+	"SFX3.CPS",
+	"SFX4.CPS",
+	"HUM1.CPS"
+};
+
+static const StringListProvider kEoB1SoundFilesIngameAmigaProvider = { ARRAYSIZE(kEoB1SoundFilesIngameAmiga), kEoB1SoundFilesIngameAmiga };
+
+static const char *const kEoB1SoundFilesFinaleAmiga[3] = {
+	"FINALE2.CPS",
+	"FINALE1.CPS",
+	"FINALE.CPS"
+};
+
+static const StringListProvider kEoB1SoundFilesFinaleAmigaProvider = { ARRAYSIZE(kEoB1SoundFilesFinaleAmiga), kEoB1SoundFilesFinaleAmiga };
+
diff --git a/devtools/create_kyradat/resources/eob1_amiga_english.h b/devtools/create_kyradat/resources/eob1_amiga_english.h
new file mode 100644
index 0000000..7d55174
--- /dev/null
+++ b/devtools/create_kyradat/resources/eob1_amiga_english.h
@@ -0,0 +1,899 @@
+static const char *const kEoB1ChargenStrings1AmigaEnglish[9] = {
+	"Your party is\rcomplete. Select\rthe PLAY button\ror press 'P' to\rstart the game.",
+	"          ",
+	"AC\rHP\rLVL",
+	"%s\r%d\r%d\r%d\r%d\r%d",
+	"%d\r%d",
+	"%d",
+	"%d/%d",
+	"%d/%d/%d",
+	"Select the box of\rthe character you\rwish to create or\rview."
+};
+
+static const StringListProvider kEoB1ChargenStrings1AmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenStrings1AmigaEnglish), kEoB1ChargenStrings1AmigaEnglish };
+
+static const char *const kEoB1ChargenStrings2AmigaEnglish[12] = {
+	"%s",
+	"%d",
+	"%s",
+	"%d",
+	"%d",
+	"%d",
+	"%s",
+	"%d",
+	"SELECT RACE:",
+	"SELECT CLASS:",
+	"SELECT ALIGNMENT:",
+	"Name:"
+};
+
+
+
+static const StringListProvider kEoB1ChargenStrings2AmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenStrings2AmigaEnglish), kEoB1ChargenStrings2AmigaEnglish };
+
+static const char *const kEoB1ChargenStatStringsAmigaEnglish[12] = {
+	"STR",
+	"INT",
+	"WIS",
+	"DEX",
+	"CON",
+	"CHA",
+	"STRENGTH",
+	"INTELLIGENCE",
+	"WISDOM",
+	"DEXTERITY",
+	"CONSTITUTION",
+	"CHARISMA"
+};
+
+static const StringListProvider kEoB1ChargenStatStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenStatStringsAmigaEnglish), kEoB1ChargenStatStringsAmigaEnglish };
+
+static const char *const kEoB1ChargenRaceSexStringsAmigaEnglish[12] = {
+	"HUMAN MALE",
+	"HUMAN FEMALE",
+	"ELF MALE",
+	"ELF FEMALE",
+	"HALF-ELF MALE",
+	"HALF-ELF FEMALE",
+	"DWARF MALE",
+	"DWARF FEMALE",
+	"GNOME MALE",
+	"GNOME FEMALE",
+	"HALFLING MALE",
+	"HALFLING FEMALE"
+};
+
+static const StringListProvider kEoB1ChargenRaceSexStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenRaceSexStringsAmigaEnglish), kEoB1ChargenRaceSexStringsAmigaEnglish };
+
+static const char *const kEoB1ChargenClassStringsAmigaEnglish[21] = {
+	"FIGHTER",
+	"RANGER",
+	"PALADIN",
+	"MAGE",
+	"CLERIC",
+	"THIEF",
+	"FIGHTER/CLERIC",
+	"FIGHTER/THIEF",
+	"FIGHTER/MAGE",
+	"FIGHTER/MAGE/THIEF",
+	"THIEF/MAGE",
+	"CLERIC/THIEF",
+	"FIGHTER/CLERIC/MAGE",
+	"RANGER/CLERIC",
+	"CLERIC/MAGE",
+	"FIGHTER",
+	"MAGE",
+	"CLERIC",
+	"THIEF",
+	"PALADIN",
+	"RANGER"
+};
+
+static const StringListProvider kEoB1ChargenClassStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenClassStringsAmigaEnglish), kEoB1ChargenClassStringsAmigaEnglish };
+
+static const char *const kEoB1ChargenAlignmentStringsAmigaEnglish[9] = {
+	"LAWFUL GOOD",
+	"NEUTRAL GOOD",
+	"CHAOTIC GOOD",
+	"LAWFUL NEUTRAL",
+	"TRUE NEUTRAL",
+	"CHAOTIC NEUTRAL",
+	"LAWFUL EVIL",
+	"NEUTRAL EVIL",
+	"CHAOTIC EVIL"
+};
+
+static const StringListProvider kEoB1ChargenAlignmentStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenAlignmentStringsAmigaEnglish), kEoB1ChargenAlignmentStringsAmigaEnglish };
+
+static const char *const kEoB1ChargenEnterGameStringsAmigaEnglish[1] = {
+	"  Entering game.\r  Please wait."
+};
+
+static const StringListProvider kEoB1ChargenEnterGameStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ChargenEnterGameStringsAmigaEnglish), kEoB1ChargenEnterGameStringsAmigaEnglish };
+
+static const char *const kEoB1MainMenuStringsAmigaEnglish[3] = {
+	"LOAD GAME IN PROGRESS\r",
+	"START A NEW PARTY\r",
+	"EXIT TO DOS\r"
+};
+
+static const StringListProvider kEoB1MainMenuStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MainMenuStringsAmigaEnglish), kEoB1MainMenuStringsAmigaEnglish };
+
+static const char *const kEoB1BonusStringsAmigaEnglish[3] = {
+	"Congratulations on completing all 12 Beholder Bonuses.\r\rThe names of the character in your winning Beholder Bonus party are:\r\r",
+	"\r",
+	"\r\rPassword: %04x\r"
+};
+
+static const StringListProvider kEoB1BonusStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1BonusStringsAmigaEnglish), kEoB1BonusStringsAmigaEnglish };
+
+static const char *const kEoB1TurnUndeadStringAmigaEnglish[1] = {
+	"\x06\x06""%s uses the power to turn undead!""\x06\x1F""\r"
+};
+
+static const StringListProvider kEoB1TurnUndeadStringAmigaEnglishProvider = { ARRAYSIZE(kEoB1TurnUndeadStringAmigaEnglish), kEoB1TurnUndeadStringAmigaEnglish };
+
+static const char *const kEoB1Npc0StringsAmigaEnglish[2] = {
+	"\r     I wish you luck in your travels.",
+	"Which should be resurrected?"
+};
+
+static const StringListProvider kEoB1Npc0StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc0StringsAmigaEnglish), kEoB1Npc0StringsAmigaEnglish };
+
+static const char *const kEoB1Npc11StringsAmigaEnglish[3] = {
+	"Tend his wounds",
+	"Talk",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc11StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc11StringsAmigaEnglish), kEoB1Npc11StringsAmigaEnglish };
+
+static const char *const kEoB1Npc12StringsAmigaEnglish[2] = {
+	"Tend his wounds",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc12StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc12StringsAmigaEnglish), kEoB1Npc12StringsAmigaEnglish };
+
+static const char *const kEoB1Npc21StringsAmigaEnglish[2] = {
+	"Hear proposal",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc21StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc21StringsAmigaEnglish), kEoB1Npc21StringsAmigaEnglish };
+
+static const char *const kEoB1Npc22StringsAmigaEnglish[2] = {
+	"Help him",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc22StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc22StringsAmigaEnglish), kEoB1Npc22StringsAmigaEnglish };
+
+static const char *const kEoB1Npc31StringsAmigaEnglish[2] = {
+	"Heal Party",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc31StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc31StringsAmigaEnglish), kEoB1Npc31StringsAmigaEnglish };
+
+static const char *const kEoB1Npc32StringsAmigaEnglish[3] = {
+	"Heal Party",
+	"Resurrect Dead",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc32StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc32StringsAmigaEnglish), kEoB1Npc32StringsAmigaEnglish };
+
+static const char *const kEoB1Npc4StringsAmigaEnglish[2] = {
+	"Attack",
+	"Bribe"
+};
+
+static const StringListProvider kEoB1Npc4StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc4StringsAmigaEnglish), kEoB1Npc4StringsAmigaEnglish };
+
+static const char *const kEoB1Npc5StringsAmigaEnglish[3] = {
+	"Kill her",
+	"Hear her out",
+	"Let her go"
+};
+
+static const StringListProvider kEoB1Npc5StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc5StringsAmigaEnglish), kEoB1Npc5StringsAmigaEnglish };
+
+static const char *const kEoB1Npc6StringsAmigaEnglish[2] = {
+	"Surrender",
+	"Attack"
+};
+
+static const StringListProvider kEoB1Npc6StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc6StringsAmigaEnglish), kEoB1Npc6StringsAmigaEnglish };
+
+static const char *const kEoB1Npc7StringsAmigaEnglish[3] = {
+	"Free Him",
+	"Kill Him",
+	"Leave"
+};
+
+static const StringListProvider kEoB1Npc7StringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1Npc7StringsAmigaEnglish), kEoB1Npc7StringsAmigaEnglish };
+
+static const char *const kEoB1PryDoorStringsAmigaEnglish[7] = {
+	"Nobody is able to force the door.\r",
+	"The party forces the door.\r",
+	"%s forces the door!\r",
+	"The party tries to force the door and fails.\r",
+	"You can't put that item there.\r",
+	"The item is too large to fit.\r",
+	"No one is able to pry this door open.\r"
+};
+
+static const StringListProvider kEoB1PryDoorStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1PryDoorStringsAmigaEnglish), kEoB1PryDoorStringsAmigaEnglish };
+
+static const char *const kEoB1WarningStringsAmigaEnglish[3] = {
+	"You can't go that way.\r",
+	"%s isn't capable of eating food!\r",
+	"You may only eat food!\r"
+};
+
+static const StringListProvider kEoB1WarningStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1WarningStringsAmigaEnglish), kEoB1WarningStringsAmigaEnglish };
+
+static const char *const kEoB1ItemSuffixStringsRingsAmigaEnglish[4] = {
+	"Adornment",
+	"Wizardry",
+	"Sustenance",
+	"Feather Fall"
+};
+
+static const StringListProvider kEoB1ItemSuffixStringsRingsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ItemSuffixStringsRingsAmigaEnglish), kEoB1ItemSuffixStringsRingsAmigaEnglish };
+
+static const char *const kEoB1ItemSuffixStringsPotionsAmigaEnglish[8] = {
+	"Giant Strength",
+	"Healing",
+	"Extra Healing",
+	"Poison",
+	"Vitality",
+	"Speed",
+	"Invisibility",
+	"Cure Poison"
+};
+
+static const StringListProvider kEoB1ItemSuffixStringsPotionsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ItemSuffixStringsPotionsAmigaEnglish), kEoB1ItemSuffixStringsPotionsAmigaEnglish };
+
+static const char *const kEoB1ItemSuffixStringsWandsAmigaEnglish[7] = {
+	"Stick",
+	"Lightning",
+	"Frost",
+	"Curing",
+	"Fireball",
+	"Silvias",
+	"Magic Missile"
+};
+
+static const StringListProvider kEoB1ItemSuffixStringsWandsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ItemSuffixStringsWandsAmigaEnglish), kEoB1ItemSuffixStringsWandsAmigaEnglish };
+
+static const char *const kEoB1RipItemStringsAmigaEnglish[3] = {
+	"%s has lost her ",
+	"%s has lost his ",
+	".\r"
+};
+
+static const StringListProvider kEoB1RipItemStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1RipItemStringsAmigaEnglish), kEoB1RipItemStringsAmigaEnglish };
+
+static const char *const kEoB1CursedStringAmigaEnglish[1] = {
+	"Cursed %s %d"
+};
+
+static const StringListProvider kEoB1CursedStringAmigaEnglishProvider = { ARRAYSIZE(kEoB1CursedStringAmigaEnglish), kEoB1CursedStringAmigaEnglish };
+
+static const char *const kEoB1MagicObjectStringsAmigaEnglish[5] = {
+	"Mage Scroll",
+	"Cleric Scroll",
+	"Ring",
+	"Potion",
+	"Wand"
+};
+
+static const StringListProvider kEoB1MagicObjectStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicObjectStringsAmigaEnglish), kEoB1MagicObjectStringsAmigaEnglish };
+
+static const char *const kEoB1MagicObjectString5AmigaEnglish[1] = {
+	"Stick"
+};
+
+static const StringListProvider kEoB1MagicObjectString5AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicObjectString5AmigaEnglish), kEoB1MagicObjectString5AmigaEnglish };
+
+static const char *const kEoB1PatternSuffixAmigaEnglish[1] = {
+	"%s of %s"
+};
+
+static const StringListProvider kEoB1PatternSuffixAmigaEnglishProvider = { ARRAYSIZE(kEoB1PatternSuffixAmigaEnglish), kEoB1PatternSuffixAmigaEnglish };
+
+static const char *const kEoB1PatternGrFix1AmigaEnglish[1] = {
+	"%s of %s"
+};
+
+static const StringListProvider kEoB1PatternGrFix1AmigaEnglishProvider = { ARRAYSIZE(kEoB1PatternGrFix1AmigaEnglish), kEoB1PatternGrFix1AmigaEnglish };
+
+static const char *const kEoB1PatternGrFix2AmigaEnglish[1] = {
+	"%s of %s"
+};
+
+static const StringListProvider kEoB1PatternGrFix2AmigaEnglishProvider = { ARRAYSIZE(kEoB1PatternGrFix2AmigaEnglish), kEoB1PatternGrFix2AmigaEnglish };
+
+static const char *const kEoB1ValidateArmorStringAmigaEnglish[1] = {
+	"%s can't wear that type of armor.\r"
+};
+
+static const StringListProvider kEoB1ValidateArmorStringAmigaEnglishProvider = { ARRAYSIZE(kEoB1ValidateArmorStringAmigaEnglish), kEoB1ValidateArmorStringAmigaEnglish };
+
+static const char *const kEoB1ValidateNoDropStringAmigaEnglish[1] = {
+	"You can't put that item there.\r"
+};
+
+static const StringListProvider kEoB1ValidateNoDropStringAmigaEnglishProvider = { ARRAYSIZE(kEoB1ValidateNoDropStringAmigaEnglish), kEoB1ValidateNoDropStringAmigaEnglish };
+
+static const char *const kEoB1PotionStringsAmigaEnglish[2] = {
+	"poisoned",
+	"%s feels %s!\r"
+};
+
+static const StringListProvider kEoB1PotionStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1PotionStringsAmigaEnglish), kEoB1PotionStringsAmigaEnglish };
+
+static const char *const kEoB1WandStringsAmigaEnglish[2] = {
+	"The wand has no apparent magical effect\r",
+	"no effect.\r"
+};
+
+static const StringListProvider kEoB1WandStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1WandStringsAmigaEnglish), kEoB1WandStringsAmigaEnglish };
+
+static const char *const kEoB1ItemMisuseStringsAmigaEnglish[3] = {
+	"%s can not use this item.\r",
+	"This item automatically used when worn.\r",
+	"This item is not used in this way.\r"
+};
+
+static const StringListProvider kEoB1ItemMisuseStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1ItemMisuseStringsAmigaEnglish), kEoB1ItemMisuseStringsAmigaEnglish };
+
+static const char *const kEoB1TakenStringsAmigaEnglish[1] = {
+	" taken.\r"
+};
+
+static const StringListProvider kEoB1TakenStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1TakenStringsAmigaEnglish), kEoB1TakenStringsAmigaEnglish };
+
+static const char *const kEoB1PotionEffectStringsAmigaEnglish[8] = {
+	"much stronger",
+	"better",
+	"much better",
+	"ill for a moment",
+	"no longer hungry",
+	"fast and agile",
+	"transparent",
+	"better"
+};
+
+static const StringListProvider kEoB1PotionEffectStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1PotionEffectStringsAmigaEnglish), kEoB1PotionEffectStringsAmigaEnglish };
+
+static const char *const kEoB1YesNoStringsAmigaEnglish[2] = {
+	"yes",
+	"no"
+};
+
+static const StringListProvider kEoB1YesNoStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1YesNoStringsAmigaEnglish), kEoB1YesNoStringsAmigaEnglish };
+
+static const char *const kEoB1MoreStringsAmigaEnglish[1] = {
+	"MORE"
+};
+
+static const StringListProvider kEoB1MoreStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MoreStringsAmigaEnglish), kEoB1MoreStringsAmigaEnglish };
+
+static const char *const kEoB1NpcMaxStringsAmigaEnglish[1] = {
+	"You may only have six characters in your party.  Select the one you wish to drop."
+};
+
+static const StringListProvider kEoB1NpcMaxStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1NpcMaxStringsAmigaEnglish), kEoB1NpcMaxStringsAmigaEnglish };
+
+static const char *const kEoB1NpcJoinStringsAmigaEnglish[1] = {
+	"%s joins the party.\r"
+};
+
+static const StringListProvider kEoB1NpcJoinStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1NpcJoinStringsAmigaEnglish), kEoB1NpcJoinStringsAmigaEnglish };
+
+static const char *const kEoB1CancelStringsAmigaEnglish[1] = {
+	"CANCEL"
+};
+
+static const StringListProvider kEoB1CancelStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1CancelStringsAmigaEnglish), kEoB1CancelStringsAmigaEnglish };
+
+static const char *const kEoB1MenuStringsMainAmigaEnglish[8] = {
+	"Select Option:",
+	"Rest Party",
+	"Memorize Spells",
+	"Pray for Spells",
+	"Scribe Scrolls",
+	"Preferences",
+	"Game Options",
+	"Exit"
+};
+
+static const StringListProvider kEoB1MenuStringsMainAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsMainAmigaEnglish), kEoB1MenuStringsMainAmigaEnglish };
+
+static const char *const kEoB1MenuStringsSaveLoadAmigaEnglish[8] = {
+	"Load Game",
+	"Save Game",
+	"Drop Character",
+	"Quit Game",
+	"Game Options:",
+	"\r   Game saved.",
+	"\r Save game\r failure!",
+	"\r Load game\r failure!"
+};
+
+static const StringListProvider kEoB1MenuStringsSaveLoadAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsSaveLoadAmigaEnglish), kEoB1MenuStringsSaveLoadAmigaEnglish };
+
+static const char *const kEoB1MenuStringsOnOffAmigaEnglish[2] = {
+	"ON",
+	"OFF"
+};
+
+static const StringListProvider kEoB1MenuStringsOnOffAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsOnOffAmigaEnglish), kEoB1MenuStringsOnOffAmigaEnglish };
+
+static const char *const kEoB1MenuStringsSpellsAmigaEnglish[17] = {
+	"\r\r Select a character\r from your party who\r would like to learn\r spells.",
+	"\r Your Paladin is \r too low a level\r for spells.",
+	"\r\r The Mage has no\r Spell Book!",
+	"\r\r\r Select a character\r from your party\r who would like to\r pray for spells.",
+	"\r You don't have\r any Cleric able\r to pray in your\r party.",
+	"\r You don't have\r any Mage able to\r learn spells.",
+	" An unconscious\r or dead Mage\r cannot memorize\r spells.",
+	" An unconscious\r or dead Cleric\r cannot pray for\r spells.",
+	"1",
+	"2",
+	"3",
+	"4",
+	"5",
+	"Clear",
+	"Spells Available:",
+	"Yes",
+	"No"
+};
+
+static const StringListProvider kEoB1MenuStringsSpellsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsSpellsAmigaEnglish), kEoB1MenuStringsSpellsAmigaEnglish };
+
+static const char *const kEoB1MenuStringsRestAmigaEnglish[5] = {
+	"\rWill your healers\rheal the party?",
+	" Someone is still\r injured. Rest\r until healed?",
+	"Resting party.",
+	"\r All characters\r are fully\r rested.",
+	" Your party needs\r to rest to gain\r spells."
+};
+
+static const StringListProvider kEoB1MenuStringsRestAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsRestAmigaEnglish), kEoB1MenuStringsRestAmigaEnglish };
+
+static const char *const kEoB1MenuStringsDropAmigaEnglish[1] = {
+	" You cannot have\r less than four\r characters."
+};
+
+static const StringListProvider kEoB1MenuStringsDropAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsDropAmigaEnglish), kEoB1MenuStringsDropAmigaEnglish };
+
+static const char *const kEoB1MenuStringsExitAmigaEnglish[1] = {
+	" Are you sure you\r wish to exit the\r game?"
+};
+
+static const StringListProvider kEoB1MenuStringsExitAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsExitAmigaEnglish), kEoB1MenuStringsExitAmigaEnglish };
+
+static const char *const kEoB1MenuStringsStarveAmigaEnglish[1] = {
+	" Your party is\r starving. Do you\r wish to continue\r resting?"
+};
+
+static const StringListProvider kEoB1MenuStringsStarveAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsStarveAmigaEnglish), kEoB1MenuStringsStarveAmigaEnglish };
+
+static const char *const kEoB1MenuStringsScribeAmigaEnglish[5] = {
+	"Select the scroll(s)\ryou wish to scribe.",
+	"\r\r\r Select a Mage\r from your party\r who would like to\r scribe spells.",
+	" You don't have\r any scrolls to\r be scribed.",
+	" You don't have\r any scrolls that\r this Mage needs.",
+	"\r You don't have\r any Mage able to\r scribe scrolls."
+};
+
+static const StringListProvider kEoB1MenuStringsScribeAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsScribeAmigaEnglish), kEoB1MenuStringsScribeAmigaEnglish };
+
+static const char *const kEoB1MenuStringsDrop2AmigaEnglish[3] = {
+	" Select the\r character you\r wish to drop.",
+	" Are you sure you\r wish to SAVE the\r game?",
+	" Are you sure you\r wish to LOAD a\r saved game?"
+};
+
+static const StringListProvider kEoB1MenuStringsDrop2AmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsDrop2AmigaEnglish), kEoB1MenuStringsDrop2AmigaEnglish };
+
+static const char *const kEoB1MenuStringsHeadAmigaEnglish[3] = {
+	"Camp:",
+	"Preferences:",
+	"Game Options:"
+};
+
+static const StringListProvider kEoB1MenuStringsHeadAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsHeadAmigaEnglish), kEoB1MenuStringsHeadAmigaEnglish };
+
+static const char *const kEoB1MenuStringsPoisonAmigaEnglish[1] = {
+	"Poisoned party\rmembers will die!\rRest anyway?"
+};
+
+static const StringListProvider kEoB1MenuStringsPoisonAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsPoisonAmigaEnglish), kEoB1MenuStringsPoisonAmigaEnglish };
+
+static const char *const kEoB1MenuStringsMgcAmigaEnglish[2] = {
+	"%-18s %1d",
+	"%d of %d Remaining.  "
+};
+
+static const StringListProvider kEoB1MenuStringsMgcAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsMgcAmigaEnglish), kEoB1MenuStringsMgcAmigaEnglish };
+
+static const char *const kEoB1MenuStringsPrefsAmigaEnglish[4] = {
+	"Tunes are %-3s",
+	"Sounds are %-3s",
+	"Bar Graphs are %-3s",
+	""
+};
+
+static const StringListProvider kEoB1MenuStringsPrefsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsPrefsAmigaEnglish), kEoB1MenuStringsPrefsAmigaEnglish };
+
+static const char *const kEoB1MenuStringsRest2AmigaEnglish[4] = {
+	"%s gained %s.\r",
+	"%s memorized %s.\r",
+	"%s casts healing on %s.\r",
+	"Hours rested: %-4d"
+};
+
+static const StringListProvider kEoB1MenuStringsRest2AmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsRest2AmigaEnglish), kEoB1MenuStringsRest2AmigaEnglish };
+
+static const char *const kEoB1MenuStringsRest4AmigaEnglish[1] = {
+	"\rYou can't rest here, monsters are near.\r"
+};
+
+static const StringListProvider kEoB1MenuStringsRest4AmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsRest4AmigaEnglish), kEoB1MenuStringsRest4AmigaEnglish };
+
+static const char *const kEoB1MenuStringsDefeatAmigaEnglish[1] = {
+	"All of your party has been defeated.  The minions of evil will be able to carry out their plans unhindered!\r"
+};
+
+static const StringListProvider kEoB1MenuStringsDefeatAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuStringsDefeatAmigaEnglish), kEoB1MenuStringsDefeatAmigaEnglish };
+
+static const char *const kEoB1MenuYesNoStringsAmigaEnglish[2] = {
+	"Yes",
+	"No"
+};
+
+static const StringListProvider kEoB1MenuYesNoStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MenuYesNoStringsAmigaEnglish), kEoB1MenuYesNoStringsAmigaEnglish };
+
+static const char *const kEoB1CharGuiStringsHpAmigaEnglish[2] = {
+	"HP",
+	"%3d of %-3d"
+};
+
+static const StringListProvider kEoB1CharGuiStringsHpAmigaEnglishProvider = { ARRAYSIZE(kEoB1CharGuiStringsHpAmigaEnglish), kEoB1CharGuiStringsHpAmigaEnglish };
+
+static const char *const kEoB1CharGuiStringsWp1AmigaEnglish[2] = {
+	"MISS",
+	"HACK"
+};
+
+static const StringListProvider kEoB1CharGuiStringsWp1AmigaEnglishProvider = { ARRAYSIZE(kEoB1CharGuiStringsWp1AmigaEnglish), kEoB1CharGuiStringsWp1AmigaEnglish };
+
+static const char *const kEoB1CharGuiStringsWrAmigaEnglish[4] = {
+	"CAN'T",
+	"REACH",
+	"NO",
+	"AMMO"
+};
+
+static const StringListProvider kEoB1CharGuiStringsWrAmigaEnglishProvider = { ARRAYSIZE(kEoB1CharGuiStringsWrAmigaEnglish), kEoB1CharGuiStringsWrAmigaEnglish };
+
+static const char *const kEoB1CharGuiStringsSt1AmigaEnglish[6] = {
+	"Swapping",
+	"DEAD",
+	"UNCONSCIOUS",
+	"POISON (SLOW)",
+	"POISONED",
+	"PARALYZED"
+};
+
+static const StringListProvider kEoB1CharGuiStringsSt1AmigaEnglishProvider = { ARRAYSIZE(kEoB1CharGuiStringsSt1AmigaEnglish), kEoB1CharGuiStringsSt1AmigaEnglish };
+
+static const char *const kEoB1CharGuiStringsInAmigaEnglish[4] = {
+	"CHARACTER INFO",
+	"ARMOR CLASS",
+	"EXP",
+	"LVL"
+};
+
+static const StringListProvider kEoB1CharGuiStringsInAmigaEnglishProvider = { ARRAYSIZE(kEoB1CharGuiStringsInAmigaEnglish), kEoB1CharGuiStringsInAmigaEnglish };
+
+static const char *const kEoB1CharStatusStrings7AmigaEnglish[1] = {
+	"%s no longer has giant strength.\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings7AmigaEnglishProvider = { ARRAYSIZE(kEoB1CharStatusStrings7AmigaEnglish), kEoB1CharStatusStrings7AmigaEnglish };
+
+static const char *const kEoB1CharStatusStrings81AmigaEnglish[1] = {
+	"%s feels the effects of poison!\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings81AmigaEnglishProvider = { ARRAYSIZE(kEoB1CharStatusStrings81AmigaEnglish), kEoB1CharStatusStrings81AmigaEnglish };
+
+static const char *const kEoB1CharStatusStrings9AmigaEnglish[1] = {
+	"%s is no longer paralyzed!\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings9AmigaEnglishProvider = { ARRAYSIZE(kEoB1CharStatusStrings9AmigaEnglish), kEoB1CharStatusStrings9AmigaEnglish };
+
+static const char *const kEoB1CharStatusStrings131AmigaEnglish[1] = {
+	"%s is %s!\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings131AmigaEnglishProvider = { ARRAYSIZE(kEoB1CharStatusStrings131AmigaEnglish), kEoB1CharStatusStrings131AmigaEnglish };
+
+static const char *const kEoB1LevelGainStringsAmigaEnglish[1] = {
+	"\x06\x06""%s has gained a level of experience.""\x06\x1F""\r"
+};
+
+static const StringListProvider kEoB1LevelGainStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1LevelGainStringsAmigaEnglish), kEoB1LevelGainStringsAmigaEnglish };
+
+static const char *const kEoB1BookNumbersAmigaEnglish[5] = {
+	"First",
+	"Second",
+	"Third",
+	"Fourth",
+	"Fifth"
+};
+
+static const StringListProvider kEoB1BookNumbersAmigaEnglishProvider = { ARRAYSIZE(kEoB1BookNumbersAmigaEnglish), kEoB1BookNumbersAmigaEnglish };
+
+static const char *const kEoB1MageSpellsListAmigaEnglish[26] = {
+	"",
+	"Armor",
+	"Burning Hands",
+	"Detect Magic",
+	"Magic Missile",
+	"Read Magic",
+	"Shield",
+	"Shocking Grasp",
+	"Invisibility",
+	"Knock",
+	"M's Acid Arrow",
+	"Stinking Cloud",
+	"Dispel Magic",
+	"Fireball",
+	"Flame Arrow",
+	"Haste",
+	"Hold Person",
+	"Invisibility 10'",
+	"Lightning Bolt",
+	"Vampiric Touch",
+	"Fear",
+	"Ice Storm",
+	"Stoneskin",
+	"Cloudkill",
+	"Cone of Cold",
+	"Hold Monster"
+};
+
+static const StringListProvider kEoB1MageSpellsListAmigaEnglishProvider = { ARRAYSIZE(kEoB1MageSpellsListAmigaEnglish), kEoB1MageSpellsListAmigaEnglish };
+
+static const char *const kEoB1ClericSpellsListAmigaEnglish[25] = {
+	"",
+	"Bless",
+	"Cure Light Wnds",
+	"Cause Light Wnds",
+	"Detect Magic",
+	"Protect-Evil",
+	"Aid",
+	"Flame Blade",
+	"Hold Person",
+	"Slow Poison",
+	"Create Food",
+	"Dispel Magic",
+	"Magical Vestment",
+	"Prayer",
+	"Remove Paralysis",
+	"Cure Serious",
+	"Cause Serious",
+	"Neutral-Poison",
+	"Protect-Evil 10'",
+	"Protect-Lightning",
+	"Cure Critical",
+	"Cause Critical",
+	"Flame Strike",
+	"Raise Dead",
+	"Lay on Hands"
+};
+
+static const StringListProvider kEoB1ClericSpellsListAmigaEnglishProvider = { ARRAYSIZE(kEoB1ClericSpellsListAmigaEnglish), kEoB1ClericSpellsListAmigaEnglish };
+
+static const char *const kEoB1SpellNamesAmigaEnglish[51] = {
+	"",
+	"armor",
+	"burning hands",
+	"detect magic",
+	"magic missile",
+	"shield",
+	"shocking grasp",
+	"invisibility",
+	"melf's acid arrow",
+	"stinking cloud",
+	"dispel magic",
+	"fireball",
+	"flame arrow",
+	"haste",
+	"hold person",
+	"invisibility 10' radius",
+	"lightning bolt",
+	"vampiric touch",
+	"fear",
+	"ice storm",
+	"stoneskin",
+	"cloudkill",
+	"cone of cold",
+	"hold monster",
+	"bless",
+	"cure light wounds",
+	"cause light wounds",
+	"detect magic",
+	"protection from evil",
+	"aid",
+	"flame blade",
+	"hold person",
+	"slow poison",
+	"create food",
+	"dispel magic",
+	"magical vestment",
+	"prayer",
+	"remove paralysis",
+	"cure serious wounds",
+	"cause serious wounds",
+	"neutralize poison",
+	"protection from evil 10' radius",
+	"protection from lightning",
+	"cure critical wounds",
+	"cause critical wounds",
+	"flame strike",
+	"raise dead",
+	"lay on hands",
+	"",
+	"",
+	""
+};
+
+static const StringListProvider kEoB1SpellNamesAmigaEnglishProvider = { ARRAYSIZE(kEoB1SpellNamesAmigaEnglish), kEoB1SpellNamesAmigaEnglish };
+
+static const char *const kEoB1MagicStrings1AmigaEnglish[6] = {
+	"ABORT SPELL",
+	"ABORT SPELL",
+	"You must have a free hand for this spell.\r",
+	"You can't have two of this spell type active.\r",
+	"%s casts %s.\r",
+	"ok\r"
+};
+
+static const StringListProvider kEoB1MagicStrings1AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings1AmigaEnglish), kEoB1MagicStrings1AmigaEnglish };
+
+static const char *const kEoB1MagicStrings2AmigaEnglish[3] = {
+	"no effect\r",
+	"%s has been disintegrated!\r",
+	"The party has been hit by a death spell!\r"
+};
+
+static const StringListProvider kEoB1MagicStrings2AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings2AmigaEnglish), kEoB1MagicStrings2AmigaEnglish };
+
+static const char *const kEoB1MagicStrings3AmigaEnglish[6] = {
+	"Cast spell on which character? ",
+	"\rok\r",
+	"\rSpell aborted.\r",
+	"%s's %s spell expires.\r",
+	"%s missed the monster.\r",
+	"%s must be in the front ranks to hit!\r"
+};
+
+static const StringListProvider kEoB1MagicStrings3AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings3AmigaEnglish), kEoB1MagicStrings3AmigaEnglish };
+
+static const char *const kEoB1MagicStrings4AmigaEnglish[1] = {
+	"no effect.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings4AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings4AmigaEnglish), kEoB1MagicStrings4AmigaEnglish };
+
+static const char *const kEoB1MagicStrings6AmigaEnglish[1] = {
+	"%s already has a high base armor class.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings6AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings6AmigaEnglish), kEoB1MagicStrings6AmigaEnglish };
+
+static const char *const kEoB1MagicStrings7AmigaEnglish[5] = {
+	"1ST",
+	"2ND",
+	"3RD",
+	"4TH",
+	"5TH"
+};
+
+static const StringListProvider kEoB1MagicStrings7AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings7AmigaEnglish), kEoB1MagicStrings7AmigaEnglish };
+
+static const char *const kEoB1MagicStrings8AmigaEnglish[3] = {
+	"All spells on %s are dispelled.\r",
+	"The party is already blessed!\r",
+	"The aid spell fails!\r"
+};
+
+static const StringListProvider kEoB1MagicStrings8AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings8AmigaEnglish), kEoB1MagicStrings8AmigaEnglish };
+
+static const char *const kEoB1MagicStrings9AmigaEnglish[1] = {
+	"%s is already protected by stoneskin.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings9AmigaEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings9AmigaEnglish), kEoB1MagicStrings9AmigaEnglish };
+
+static const byte kEoB1ManDefAmigaEnglish[120] = {
+	0x09, 0x0a, 0x02, 0x00, 0x09, 0x04, 0x03, 0x00,
+	0x09, 0x06, 0x06, 0x00, 0x09, 0x03, 0x03, 0x00,
+	0x09, 0x04, 0x02, 0x00, 0x09, 0x01, 0x02, 0x00,
+	0x09, 0x05, 0x01, 0x00, 0x09, 0x09, 0x02, 0x00,
+	0x09, 0x06, 0x02, 0x00, 0x23, 0x01, 0x05, 0x00,
+	0x23, 0x02, 0x02, 0x00, 0x23, 0x03, 0x06, 0x00,
+	0x23, 0x05, 0x01, 0x00, 0x23, 0x06, 0x03, 0x00,
+	0x23, 0x07, 0x01, 0x00, 0x1a, 0x01, 0x01, 0x00,
+	0x1a, 0x03, 0x02, 0x00, 0x1a, 0x06, 0x01, 0x00,
+	0x24, 0x01, 0x03, 0x00, 0x24, 0x03, 0x04, 0x00,
+	0x24, 0x03, 0x01, 0x00, 0x02, 0x04, 0x03, 0x00,
+	0x02, 0x03, 0x03, 0x00, 0x02, 0x05, 0x03, 0x00,
+	0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x03, 0x00,
+	0x01, 0x04, 0x03, 0x00, 0x0c, 0x02, 0x01, 0x00,
+	0x0c, 0x03, 0x03, 0x00, 0x0c, 0x04, 0x02, 0x00
+};
+
+static const ByteProvider kEoB1ManDefAmigaEnglishProvider = { ARRAYSIZE(kEoB1ManDefAmigaEnglish), kEoB1ManDefAmigaEnglish };
+
+static const char *const kEoB1ManWordAmigaEnglish[31] = {
+	"attacks",
+	"short",
+	"line",
+	"weapons",
+	"certain",
+	"rank",
+	"rear",
+	"can",
+	"away",
+	"dungeon",
+	"cursor",
+	"feature",
+	"information",
+	"displayed",
+	"below",
+	"around",
+	"carefree",
+	"gnomes",
+	"clerics",
+	"mystic",
+	"pummel",
+	"fitness",
+	"using",
+	"toughness",
+	"wealth",
+	"wizard",
+	"officials",
+	"hound",
+	"disturbing",
+	"flaming",
+	""
+};
+
+static const StringListProvider kEoB1ManWordAmigaEnglishProvider = { ARRAYSIZE(kEoB1ManWordAmigaEnglish), kEoB1ManWordAmigaEnglish };
+
+static const char *const kEoB1ManPromptAmigaEnglish[1] = {
+	"\r\r\r\rOn the page with this symbol...\r\rFind line %d\rEnter word %d\r"
+};
+
+static const StringListProvider kEoB1ManPromptAmigaEnglishProvider = { ARRAYSIZE(kEoB1ManPromptAmigaEnglish), kEoB1ManPromptAmigaEnglish };
+
+static const char *const kEoB1MonsterDistAttStringsAmigaEnglish[5] = {
+	"%s is hit by a cause serious wounds spell!\r",
+	"The party is hit with a psychic mind blast!\r",
+	"paralyzed",
+	"poisoned",
+	"paralyzed"
+};
+
+static const StringListProvider kEoB1MonsterDistAttStringsAmigaEnglishProvider = { ARRAYSIZE(kEoB1MonsterDistAttStringsAmigaEnglish), kEoB1MonsterDistAttStringsAmigaEnglish };
+
diff --git a/devtools/create_kyradat/resources/eob1_amiga_german.h b/devtools/create_kyradat/resources/eob1_amiga_german.h
new file mode 100644
index 0000000..feb856f
--- /dev/null
+++ b/devtools/create_kyradat/resources/eob1_amiga_german.h
@@ -0,0 +1,899 @@
+static const char *const kEoB1ChargenStrings1AmigaGerman[9] = {
+	"Ihr Team ist\rkomplett. SPIEL-\rKnopf oder 'P'\rdruecken, um zu\rbeginnen.",
+	"          ",
+	"RK\rHP\rEBN",
+	"%s\r%d\r%d\r%d\r%d\r%d",
+	"%d\r%d",
+	"%d",
+	"%d/%d",
+	"%d/%d/%d",
+	"Waehle das Feld\rdes Charakters\rzum Erstellen oder\rAnschauen."
+};
+
+static const StringListProvider kEoB1ChargenStrings1AmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenStrings1AmigaGerman), kEoB1ChargenStrings1AmigaGerman };
+
+static const char *const kEoB1ChargenStrings2AmigaGerman[12] = {
+	"%s",
+	"%d",
+	"%s",
+	"%d",
+	"%d",
+	"%d",
+	"%s",
+	"%d",
+	"WAEHLE RASSE:",
+	"WAEHLE KLASSE:",
+	"GESINNUNG WAEHLEN:",
+	"Name:"
+};
+
+static const StringListProvider kEoB1ChargenStrings2AmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenStrings2AmigaGerman), kEoB1ChargenStrings2AmigaGerman };
+
+static const char *const kEoB1ChargenStatStringsAmigaGerman[12] = {
+	"STR",
+	"INT",
+	"WIS",
+	"DEX",
+	"CON",
+	"CHA",
+	"STAERKE",
+	"INTELLIGENZ",
+	"WEISHEIT",
+	"GEWANDHEIT",
+	"KONSTITUTION",
+	"CHARISMA"
+};
+
+static const StringListProvider kEoB1ChargenStatStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenStatStringsAmigaGerman), kEoB1ChargenStatStringsAmigaGerman };
+
+static const char *const kEoB1ChargenRaceSexStringsAmigaGerman[12] = {
+	"MENSCH MAENNL.",
+	"MENSCH WEIBL.",
+	"ELF MAENNL.",
+	"ELF WEIBL.",
+	"HALB-ELF MAENNL.",
+	"HALB-ELF WEIBL.",
+	"ZWERG MAENNL.",
+	"ZWERG WEIBL.",
+	"GNOM MAENNL.",
+	"GNOM WEIBL.",
+	"HALBLING MAENNL.",
+	"HALBLING WEIBL."
+};
+
+static const StringListProvider kEoB1ChargenRaceSexStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenRaceSexStringsAmigaGerman), kEoB1ChargenRaceSexStringsAmigaGerman };
+
+static const char *const kEoB1ChargenClassStringsAmigaGerman[21] = {
+	"KAEMPFER",
+	"WALDLAEUFER",
+	"PALADIN",
+	"MAGIER",
+	"KLERIKER",
+	"DIEB",
+	"KAEMPFER/KLERIKER",
+	"KAEMPFER/DIEB",
+	"KAEMPFER/MAGIER",
+	"KAEMPF./MAGIER/DIEB",
+	"DIEB/MAGIER",
+	"KLERIKER/DIEB",
+	"KAEMPF./KLE./MAGIER",
+	"WALDL./KLER.",
+	"KLER./MAGIER",
+	"KAEMPFER",
+	"MAGIER",
+	"KLERIKER",
+	"DIEB",
+	"PALADIN",
+	"WALDLAEUFER"
+};
+
+static const StringListProvider kEoB1ChargenClassStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenClassStringsAmigaGerman), kEoB1ChargenClassStringsAmigaGerman };
+
+static const char *const kEoB1ChargenAlignmentStringsAmigaGerman[9] = {
+	"RECHTSCH. GUT",
+	"NEUTRAL GUT",
+	"CHAOTISCH GUT",
+	"RECHTSCH. NEUTRAL",
+	"ABSOLUT NEUTRAL",
+	"CHAOTISCH NEUTRAL",
+	"RECHTSCH. BOESE",
+	"NEUTRAL BOESE",
+	"CHAOTISCH BOESE"
+};
+
+static const StringListProvider kEoB1ChargenAlignmentStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenAlignmentStringsAmigaGerman), kEoB1ChargenAlignmentStringsAmigaGerman };
+
+static const char *const kEoB1ChargenEnterGameStringsAmigaGerman[1] = {
+	"  Spiel startet.\r  Bitte warten."
+};
+
+static const StringListProvider kEoB1ChargenEnterGameStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1ChargenEnterGameStringsAmigaGerman), kEoB1ChargenEnterGameStringsAmigaGerman };
+
+static const char *const kEoB1MainMenuStringsAmigaGerman[3] = {
+	"ALTES SPIEL LADEN\r",
+	"NEUES TEAM AUFBAUEN\r",
+	"ENDE > AMIGADOS\r"
+};
+
+static const StringListProvider kEoB1MainMenuStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1MainMenuStringsAmigaGerman), kEoB1MainMenuStringsAmigaGerman };
+
+static const char *const kEoB1BonusStringsAmigaGerman[3] = {
+	"Herzlichen Glueckwunsch fuer das Auffinden aller 12 Beholder-Boni.\r\rDie beteiligten Charaktere des gluecklichen Teams waren:\r\r",
+	"\r",
+	"\r\rPasswort: %04x\r"
+};
+
+static const StringListProvider kEoB1BonusStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1BonusStringsAmigaGerman), kEoB1BonusStringsAmigaGerman };
+
+static const char *const kEoB1TurnUndeadStringAmigaGerman[1] = {
+	"\x06\x06""%s benutzt die Macht, Untote zu vertreiben!""\x06\x1F""\r"
+};
+
+static const StringListProvider kEoB1TurnUndeadStringAmigaGermanProvider = { ARRAYSIZE(kEoB1TurnUndeadStringAmigaGerman), kEoB1TurnUndeadStringAmigaGerman };
+
+static const char *const kEoB1Npc0StringsAmigaGerman[2] = {
+	"\r     Ich wuensche Euch Glueck auf Euren Reisen.",
+	"Wer soll wiedererweckt werden?"
+};
+
+static const StringListProvider kEoB1Npc0StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc0StringsAmigaGerman), kEoB1Npc0StringsAmigaGerman };
+
+static const char *const kEoB1Npc11StringsAmigaGerman[3] = {
+	"Wunden heilen",
+	"Reden",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc11StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc11StringsAmigaGerman), kEoB1Npc11StringsAmigaGerman };
+
+static const char *const kEoB1Npc12StringsAmigaGerman[2] = {
+	"Wunden heilen",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc12StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc12StringsAmigaGerman), kEoB1Npc12StringsAmigaGerman };
+
+static const char *const kEoB1Npc21StringsAmigaGerman[2] = {
+	"Angebot hoeren",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc21StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc21StringsAmigaGerman), kEoB1Npc21StringsAmigaGerman };
+
+static const char *const kEoB1Npc22StringsAmigaGerman[2] = {
+	"Helfen",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc22StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc22StringsAmigaGerman), kEoB1Npc22StringsAmigaGerman };
+
+static const char *const kEoB1Npc31StringsAmigaGerman[2] = {
+	"Team heilen",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc31StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc31StringsAmigaGerman), kEoB1Npc31StringsAmigaGerman };
+
+static const char *const kEoB1Npc32StringsAmigaGerman[3] = {
+	"Team heilen",
+	"Tote erwecken",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc32StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc32StringsAmigaGerman), kEoB1Npc32StringsAmigaGerman };
+
+static const char *const kEoB1Npc4StringsAmigaGerman[2] = {
+	"Angreifen",
+	"Bestechen"
+};
+
+static const StringListProvider kEoB1Npc4StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc4StringsAmigaGerman), kEoB1Npc4StringsAmigaGerman };
+
+static const char *const kEoB1Npc5StringsAmigaGerman[3] = {
+	"toeten",
+	"anhoeren",
+	"gehen lassen"
+};
+
+static const StringListProvider kEoB1Npc5StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc5StringsAmigaGerman), kEoB1Npc5StringsAmigaGerman };
+
+static const char *const kEoB1Npc6StringsAmigaGerman[2] = {
+	"Ergeben",
+	"Angreifen"
+};
+
+static const StringListProvider kEoB1Npc6StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc6StringsAmigaGerman), kEoB1Npc6StringsAmigaGerman };
+
+static const char *const kEoB1Npc7StringsAmigaGerman[3] = {
+	"befreien",
+	"toeten",
+	"Gehen"
+};
+
+static const StringListProvider kEoB1Npc7StringsAmigaGermanProvider = { ARRAYSIZE(kEoB1Npc7StringsAmigaGerman), kEoB1Npc7StringsAmigaGerman };
+
+static const char *const kEoB1PryDoorStringsAmigaGerman[8] = {
+	"Niemand kann die Tuer aufbrechen.\r",
+	"Das Team bricht die Tuer auf.\r",
+	"%s bricht die tuer auf!\r",
+	"Das Team versucht die Tuer aufzubrechen,\raber schafft es nicht.\r",
+	"Dieser Gegenstand kann hier nicht plaziert werden.\r",
+	"Dieser Gegenstand ist zu gross.\r",
+	"Niemand schafft es, die Tuer aufzubrechen.\r",
+	"\r"
+};
+
+static const StringListProvider kEoB1PryDoorStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1PryDoorStringsAmigaGerman), kEoB1PryDoorStringsAmigaGerman };
+
+static const char *const kEoB1WarningStringsAmigaGerman[3] = {
+	"Hier geht es nicht weiter.\r",
+	"%s kann keine Nahrung zu sich nehmen!\r",
+	"Dies kann man nicht essen!\r"
+};
+
+static const StringListProvider kEoB1WarningStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1WarningStringsAmigaGerman), kEoB1WarningStringsAmigaGerman };
+
+static const char *const kEoB1ItemSuffixStringsRingsAmigaGerman[4] = {
+	"Schmuck",
+	"Zauber",
+	"Nahrungs",
+	"Federfall"
+};
+
+static const StringListProvider kEoB1ItemSuffixStringsRingsAmigaGermanProvider = { ARRAYSIZE(kEoB1ItemSuffixStringsRingsAmigaGerman), kEoB1ItemSuffixStringsRingsAmigaGerman };
+
+static const char *const kEoB1ItemSuffixStringsPotionsAmigaGerman[8] = {
+	"Riesenstaerke",
+	"Heilungs",
+	"Extra Heilungs",
+	"Gift",
+	"Vitalitaets",
+	"Schnelligkeits",
+	"Unsichtbarkeits",
+	"Gift-Heilungs-"
+};
+
+static const StringListProvider kEoB1ItemSuffixStringsPotionsAmigaGermanProvider = { ARRAYSIZE(kEoB1ItemSuffixStringsPotionsAmigaGerman), kEoB1ItemSuffixStringsPotionsAmigaGerman };
+
+static const char *const kEoB1ItemSuffixStringsWandsAmigaGerman[7] = {
+	"Stock",
+	"Blitz",
+	"Frost",
+	"Heilungs",
+	"Feuerball",
+	"Silvias",
+	"Magisches Geschoss"
+};
+
+static const StringListProvider kEoB1ItemSuffixStringsWandsAmigaGermanProvider = { ARRAYSIZE(kEoB1ItemSuffixStringsWandsAmigaGerman), kEoB1ItemSuffixStringsWandsAmigaGerman };
+
+static const char *const kEoB1RipItemStringsAmigaGerman[3] = {
+	"%s verlor ihr ",
+	"%s verlor sein ",
+	".\r"
+};
+
+static const StringListProvider kEoB1RipItemStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1RipItemStringsAmigaGerman), kEoB1RipItemStringsAmigaGerman };
+
+static const char *const kEoB1CursedStringAmigaGerman[1] = {
+	"Verflucht %s %d"
+};
+
+static const StringListProvider kEoB1CursedStringAmigaGermanProvider = { ARRAYSIZE(kEoB1CursedStringAmigaGerman), kEoB1CursedStringAmigaGerman };
+
+static const char *const kEoB1MagicObjectStringsAmigaGerman[5] = {
+	"Magier-Schriftrolle",
+	"Kleriker-Scriftrolle",
+	"Ring",
+	"Trank",
+	"Stab"
+};
+
+static const StringListProvider kEoB1MagicObjectStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1MagicObjectStringsAmigaGerman), kEoB1MagicObjectStringsAmigaGerman };
+
+static const char *const kEoB1MagicObjectString5AmigaGerman[1] = {
+	"Stock"
+};
+
+static const StringListProvider kEoB1MagicObjectString5AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicObjectString5AmigaGerman), kEoB1MagicObjectString5AmigaGerman };
+
+static const char *const kEoB1PatternSuffixAmigaGerman[1] = {
+	"%s-%s"
+};
+
+static const StringListProvider kEoB1PatternSuffixAmigaGermanProvider = { ARRAYSIZE(kEoB1PatternSuffixAmigaGerman), kEoB1PatternSuffixAmigaGerman };
+
+static const char *const kEoB1PatternGrFix1AmigaGerman[1] = {
+	"%s-%s"
+};
+
+static const StringListProvider kEoB1PatternGrFix1AmigaGermanProvider = { ARRAYSIZE(kEoB1PatternGrFix1AmigaGerman), kEoB1PatternGrFix1AmigaGerman };
+
+static const char *const kEoB1PatternGrFix2AmigaGerman[1] = {
+	"%s-%s"
+};
+
+static const StringListProvider kEoB1PatternGrFix2AmigaGermanProvider = { ARRAYSIZE(kEoB1PatternGrFix2AmigaGerman), kEoB1PatternGrFix2AmigaGerman };
+
+static const char *const kEoB1ValidateArmorStringAmigaGerman[1] = {
+	"%s kann diese Ruestung nicht tragen.\r"
+};
+
+static const StringListProvider kEoB1ValidateArmorStringAmigaGermanProvider = { ARRAYSIZE(kEoB1ValidateArmorStringAmigaGerman), kEoB1ValidateArmorStringAmigaGerman };
+
+static const char *const kEoB1ValidateNoDropStringAmigaGerman[1] = {
+	"Das kannst du hier nicht ablegen.\r"
+};
+
+static const StringListProvider kEoB1ValidateNoDropStringAmigaGermanProvider = { ARRAYSIZE(kEoB1ValidateNoDropStringAmigaGerman), kEoB1ValidateNoDropStringAmigaGerman };
+
+static const char *const kEoB1PotionStringsAmigaGerman[2] = {
+	"vergiftet",
+	"%s fuehlt sich %s!\r"
+};
+
+static const StringListProvider kEoB1PotionStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1PotionStringsAmigaGerman), kEoB1PotionStringsAmigaGerman };
+
+static const char *const kEoB1WandStringsAmigaGerman[2] = {
+	"der stab hat offensichtlich keinen magischen effekt.\r",
+	"kein effekt.\r",
+};
+
+static const StringListProvider kEoB1WandStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1WandStringsAmigaGerman), kEoB1WandStringsAmigaGerman };
+
+static const char *const kEoB1ItemMisuseStringsAmigaGerman[3] = {
+	"%s kann das nicht benutzen.\r",
+	"Dies wird automatisch benutzt.\r",
+	"Das laesst sich so nicht benutzen.\r"
+};
+
+static const StringListProvider kEoB1ItemMisuseStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1ItemMisuseStringsAmigaGerman), kEoB1ItemMisuseStringsAmigaGerman };
+
+static const char *const kEoB1TakenStringsAmigaGerman[1] = {
+	" genommen.\r"
+};
+
+static const StringListProvider kEoB1TakenStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1TakenStringsAmigaGerman), kEoB1TakenStringsAmigaGerman };
+
+static const char *const kEoB1PotionEffectStringsAmigaGerman[8] = {
+	"viel staerker",
+	"besser",
+	"viel besser",
+	"einen Moment uebel",
+	"nicht mehr hungrig",
+	"schnell und agil",
+	"transparent",
+	"besser"
+};
+
+static const StringListProvider kEoB1PotionEffectStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1PotionEffectStringsAmigaGerman), kEoB1PotionEffectStringsAmigaGerman };
+
+static const char *const kEoB1YesNoStringsAmigaGerman[2] = {
+	"ja",
+	"nein"
+};
+
+static const StringListProvider kEoB1YesNoStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1YesNoStringsAmigaGerman), kEoB1YesNoStringsAmigaGerman };
+
+static const char *const kEoB1MoreStringsAmigaGerman[1] = {
+	"MEHR"
+};
+
+static const StringListProvider kEoB1MoreStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1MoreStringsAmigaGerman), kEoB1MoreStringsAmigaGerman };
+
+static const char *const kEoB1NpcMaxStringsAmigaGerman[1] = {
+	"Es sind nur sechs Charaktere in einem Team erlaubt.  \rWaehlen Sie aus, welchen Sie entlassen wollen."
+};
+
+static const StringListProvider kEoB1NpcMaxStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1NpcMaxStringsAmigaGerman), kEoB1NpcMaxStringsAmigaGerman };
+
+static const char *const kEoB1NpcJoinStringsAmigaGerman[1] = {
+	"%s wird in's Team aufgenommen.\r"
+};
+
+static const StringListProvider kEoB1NpcJoinStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1NpcJoinStringsAmigaGerman), kEoB1NpcJoinStringsAmigaGerman };
+
+static const char *const kEoB1CancelStringsAmigaGerman[1] = {
+	"ABBRECHEN"
+};
+
+static const StringListProvider kEoB1CancelStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1CancelStringsAmigaGerman), kEoB1CancelStringsAmigaGerman };
+
+static const char *const kEoB1MenuStringsMainAmigaGerman[8] = {
+	"Option Waehlen:",
+	"Ausruhen",
+	"Zauber lernen",
+	"Fuer Zauber beten",
+	"Schriftrollen",
+	"Einstellungen",
+	"Spieloptionen",
+	"Ende"
+};
+
+static const StringListProvider kEoB1MenuStringsMainAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsMainAmigaGerman), kEoB1MenuStringsMainAmigaGerman };
+
+static const char *const kEoB1MenuStringsSaveLoadAmigaGerman[8] = {
+	"Spiel laden",
+	"Spiel speichern",
+	"Charakter entlassen",
+	"Spielende",
+	"Spieloptionen:",
+	"\r   Gespeichert.",
+	"\r Speichern\r Fehler!",
+	"\r Spiel laden\r Fehler!"
+};
+
+static const StringListProvider kEoB1MenuStringsSaveLoadAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsSaveLoadAmigaGerman), kEoB1MenuStringsSaveLoadAmigaGerman };
+
+static const char *const kEoB1MenuStringsOnOffAmigaGerman[2] = {
+	"AN",
+	"AUS"
+};
+
+static const StringListProvider kEoB1MenuStringsOnOffAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsOnOffAmigaGerman), kEoB1MenuStringsOnOffAmigaGerman };
+
+static const char *const kEoB1MenuStringsSpellsAmigaGerman[17] = {
+	"\r\r Charakter aus dem \r Team waehlen, der\r den zauber lernen\r moechte\r ",
+	"\r Der Paladin ist \r noch zu\r unerfahren.",
+	"\r\r Der Magier hat \r kein Zauberbuch!",
+	"\r\r\r Charakter aus dem\r Team waehlen, der\r fuer Sprueche\r meditieren moechte.",
+	"\r Das Team hat kei-\r nen Kleriker, der\r meditieren koennte\r ",
+	"\r Das Team hat kei-\r nen Magier, der\r zaubern koennte.",
+	" Ein bewusstloser\r oder toter Magier\r kann keine Zauber\r lernen.",
+	" Ein bewusstloser\r oder toter Kleriker\r kann nicht fuer Zauber\r meditieren.",
+	"1",
+	"2",
+	"3",
+	"4",
+	"5",
+	"Neu",
+	"Verfuegbare Zauber:",
+	"Ja",
+	"Nein"
+};
+
+static const StringListProvider kEoB1MenuStringsSpellsAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsSpellsAmigaGerman), kEoB1MenuStringsSpellsAmigaGerman };
+
+static const char *const kEoB1MenuStringsRestAmigaGerman[5] = {
+	"\rWerden die Heiler\rdas Team heilen?",
+	" Jemand ist noch\r verletzt. Rasten,\r bis geheilt?",
+	"Ausruhen",
+	"\r Alle Charactere\r sind ganz\r ausgeruht.",
+	" Das Team muss\r zum Lernen der\r Sprueche aus-\r ruhen."
+};
+
+static const StringListProvider kEoB1MenuStringsRestAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsRestAmigaGerman), kEoB1MenuStringsRestAmigaGerman };
+
+static const char *const kEoB1MenuStringsDropAmigaGerman[1] = {
+	" Sie muessen min-\r destens vier\r Charaktere be-\r sitzen."
+};
+
+static const StringListProvider kEoB1MenuStringsDropAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsDropAmigaGerman), kEoB1MenuStringsDropAmigaGerman };
+
+static const char *const kEoB1MenuStringsExitAmigaGerman[1] = {
+	" Wollen Sie das\r Spiel wirklich\r beenden?"
+};
+
+static const StringListProvider kEoB1MenuStringsExitAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsExitAmigaGerman), kEoB1MenuStringsExitAmigaGerman };
+
+static const char *const kEoB1MenuStringsStarveAmigaGerman[1] = {
+	" Ihr Team verhungert.\r Soll weiter gerastet\r werden?"
+};
+
+static const StringListProvider kEoB1MenuStringsStarveAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsStarveAmigaGerman), kEoB1MenuStringsStarveAmigaGerman };
+
+static const char *const kEoB1MenuStringsScribeAmigaGerman[5] = {
+	"Schriftrolle(n) waeh-\rlen, die Uebertragen\rwerden soll(en).",
+	"\r\r\r Welcher Magier des\r Teams moechte eine\r Schriftrolle Ueber-\r tragen?.",
+	" Es gibt keine\r Schriftrollen zum\r Uebertragen.",
+	" Sie haben keine\r Schriftrollen fuer\r diesen Magier.",
+	"\r Keiner ihrer Magier\r kann Schriftrollen\r uebertragen."
+};
+
+static const StringListProvider kEoB1MenuStringsScribeAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsScribeAmigaGerman), kEoB1MenuStringsScribeAmigaGerman };
+
+static const char *const kEoB1MenuStringsDrop2AmigaGerman[3] = {
+	" Waehlen Sie den\r zu entlassenden\r Charakter.",
+	" Wollen Sie das\r Spiel wirklich\r SPEICHERN?",
+	" Wollen Sie wirk-\r lich ein altes\r Spiel LADEN?"
+};
+
+static const StringListProvider kEoB1MenuStringsDrop2AmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsDrop2AmigaGerman), kEoB1MenuStringsDrop2AmigaGerman };
+
+static const char *const kEoB1MenuStringsHeadAmigaGerman[3] = {
+	"Camp:",
+	"Einstellungen:",
+	"Spieloptionen:"
+};
+
+static const StringListProvider kEoB1MenuStringsHeadAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsHeadAmigaGerman), kEoB1MenuStringsHeadAmigaGerman };
+
+static const char *const kEoB1MenuStringsPoisonAmigaGerman[1] = {
+	"Vergiftete Team-\rmitglieder werden\rsterben.\rTrotzdem rasten?"
+};
+
+static const StringListProvider kEoB1MenuStringsPoisonAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsPoisonAmigaGerman), kEoB1MenuStringsPoisonAmigaGerman };
+
+static const char *const kEoB1MenuStringsMgcAmigaGerman[2] = {
+	"%-18s %1d",
+	"%d von %d Uebrigen.  "
+};
+
+static const StringListProvider kEoB1MenuStringsMgcAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsMgcAmigaGerman), kEoB1MenuStringsMgcAmigaGerman };
+
+static const char *const kEoB1MenuStringsPrefsAmigaGerman[4] = {
+	"Musik ist %-3s",
+	"Geraeusche sind %-3s",
+	"Grafikzeilen %-3s",
+	""
+};
+
+static const StringListProvider kEoB1MenuStringsPrefsAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsPrefsAmigaGerman), kEoB1MenuStringsPrefsAmigaGerman };
+
+static const char *const kEoB1MenuStringsRest2AmigaGerman[4] = {
+	"%s erhaelt %s.\r",
+	"%s lernt %s.\r",
+	"%s spricht heilung auf %s.\r",
+	"Ruhestunden:   %-4d"
+};
+
+static const StringListProvider kEoB1MenuStringsRest2AmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsRest2AmigaGerman), kEoB1MenuStringsRest2AmigaGerman };
+
+static const char *const kEoB1MenuStringsRest4AmigaGerman[1] = {
+	"\rRast ist nicht moeglich, Monster sind in der Naehe."
+};
+
+static const StringListProvider kEoB1MenuStringsRest4AmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsRest4AmigaGerman), kEoB1MenuStringsRest4AmigaGerman };
+
+static const char *const kEoB1MenuStringsDefeatAmigaGerman[1] = {
+	"   Dein ganzes team ist geschlagen.  \rDie Helfer des boesen koennen ihre Plaene ungehindert erfuellen!   \r"
+};
+
+static const StringListProvider kEoB1MenuStringsDefeatAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuStringsDefeatAmigaGerman), kEoB1MenuStringsDefeatAmigaGerman };
+
+static const char *const kEoB1MenuYesNoStringsAmigaGerman[2] = {
+	"Ja",
+	"Nein"
+};
+
+static const StringListProvider kEoB1MenuYesNoStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1MenuYesNoStringsAmigaGerman), kEoB1MenuYesNoStringsAmigaGerman };
+
+static const char *const kEoB1CharGuiStringsHpAmigaGerman[2] = {
+	"HP",
+	"%3d / %-3d"
+};
+
+static const StringListProvider kEoB1CharGuiStringsHpAmigaGermanProvider = { ARRAYSIZE(kEoB1CharGuiStringsHpAmigaGerman), kEoB1CharGuiStringsHpAmigaGerman };
+
+static const char *const kEoB1CharGuiStringsWp1AmigaGerman[2] = {
+	"FEHL",
+	"HACK"
+};
+
+static const StringListProvider kEoB1CharGuiStringsWp1AmigaGermanProvider = { ARRAYSIZE(kEoB1CharGuiStringsWp1AmigaGerman), kEoB1CharGuiStringsWp1AmigaGerman };
+
+static const char *const kEoB1CharGuiStringsWrAmigaGerman[4] = {
+	" ZU",
+	"WEIT",
+	"KEINE",
+	" MUN"
+};
+
+static const StringListProvider kEoB1CharGuiStringsWrAmigaGermanProvider = { ARRAYSIZE(kEoB1CharGuiStringsWrAmigaGerman), kEoB1CharGuiStringsWrAmigaGerman };
+
+static const char *const kEoB1CharGuiStringsSt1AmigaGerman[6] = {
+	"Tausche",
+	"TOT",
+	"BEWUSSTLOS",
+	"GIFT (LANGSAM)",
+	"VERGIFTED",
+	"BETAEUBT"
+};
+
+static const StringListProvider kEoB1CharGuiStringsSt1AmigaGermanProvider = { ARRAYSIZE(kEoB1CharGuiStringsSt1AmigaGerman), kEoB1CharGuiStringsSt1AmigaGerman };
+
+static const char *const kEoB1CharGuiStringsInAmigaGerman[4] = {
+	"CHARAKTER INFO",
+	"RUESTUNG",
+	"ERF",
+	"EBN"
+};
+
+static const StringListProvider kEoB1CharGuiStringsInAmigaGermanProvider = { ARRAYSIZE(kEoB1CharGuiStringsInAmigaGerman), kEoB1CharGuiStringsInAmigaGerman };
+
+static const char *const kEoB1CharStatusStrings7AmigaGerman[1] = {
+	"%s besitzt nun keine Riesen-Staerke mehr.\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings7AmigaGermanProvider = { ARRAYSIZE(kEoB1CharStatusStrings7AmigaGerman), kEoB1CharStatusStrings7AmigaGerman };
+
+static const char *const kEoB1CharStatusStrings81AmigaGerman[1] = {
+	"%s fuehlt, wie das Gift wirkt!\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings81AmigaGermanProvider = { ARRAYSIZE(kEoB1CharStatusStrings81AmigaGerman), kEoB1CharStatusStrings81AmigaGerman };
+
+static const char *const kEoB1CharStatusStrings9AmigaGerman[1] = {
+	"%s ist nicht mehr gelaehmt!\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings9AmigaGermanProvider = { ARRAYSIZE(kEoB1CharStatusStrings9AmigaGerman), kEoB1CharStatusStrings9AmigaGerman };
+
+static const char *const kEoB1CharStatusStrings131AmigaGerman[1] = {
+	"%s ist %s!\r"
+};
+
+static const StringListProvider kEoB1CharStatusStrings131AmigaGermanProvider = { ARRAYSIZE(kEoB1CharStatusStrings131AmigaGerman), kEoB1CharStatusStrings131AmigaGerman };
+
+static const char *const kEoB1LevelGainStringsAmigaGerman[1] = {
+	"\x06\x06""%s steigt eine erfahrungsstufe auf.""\x06\x1F""\r"
+};
+
+static const StringListProvider kEoB1LevelGainStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1LevelGainStringsAmigaGerman), kEoB1LevelGainStringsAmigaGerman };
+
+static const char *const kEoB1BookNumbersAmigaGerman[5] = {
+	"Erster",
+	"Zweiter",
+	"Dritter",
+	"Vierter",
+	"Fuenfter"
+};
+
+static const StringListProvider kEoB1BookNumbersAmigaGermanProvider = { ARRAYSIZE(kEoB1BookNumbersAmigaGerman), kEoB1BookNumbersAmigaGerman };
+
+static const char *const kEoB1MageSpellsListAmigaGerman[26] = {
+	"",
+	"Ruestung",
+	"Brennende Haende",
+	"Magie entdecken",
+	"Magisch. Geschoss",
+	"Magie lesen",
+	"Schild",
+	"Schockgriff",
+	"Unsichtbarkeit",
+	"Klopfen",
+	"Ms Saeurepfeil",
+	"Stinkende Wolke",
+	"Magie bannen",
+	"Feuerball",
+	"Flammenpfeil",
+	"Hast",
+	"Person festhalten",
+	"Unsichtbarkeit 3m",
+	"Blitzstrahl",
+	"Vampirgriff",
+	"Furcht",
+	"Eissturm",
+	"Steinhaut",
+	"Todeswolke",
+	"Kaeltekegel",
+	"Monster festhalten"
+};
+
+static const StringListProvider kEoB1MageSpellsListAmigaGermanProvider = { ARRAYSIZE(kEoB1MageSpellsListAmigaGerman), kEoB1MageSpellsListAmigaGerman };
+
+static const char *const kEoB1ClericSpellsListAmigaGerman[25] = {
+	"",
+	"Segen",
+	"L. Wnd. heilen",
+	"L. Wnd verurs.",
+	"Magie entdecken",
+	"Schutz vor Boesem",
+	"Staerkung",
+	"Flammenklinge",
+	"Person festhalten",
+	"Gift verlangsamen",
+	"Nahrung machen",
+	"Magie bannen",
+	"Schutzgewand",
+	"Gebet",
+	"Laehmung aufheben",
+	"Schwere W. heilen",
+	"Schwere W. verurs.",
+	"Gift neutral.",
+	"Schutz v. Boes. 3m",
+	"Schutz v. Blitzen",
+	"Krit. W. heilen",
+	"Krit. W. verurs.",
+	"Flammenschlag",
+	"Tote erwecken",
+	"Haende auflegen"
+};
+
+static const StringListProvider kEoB1ClericSpellsListAmigaGermanProvider = { ARRAYSIZE(kEoB1ClericSpellsListAmigaGerman), kEoB1ClericSpellsListAmigaGerman };
+
+static const char *const kEoB1SpellNamesAmigaGerman[51] = {
+	"",
+	"Ruestung",
+	"brennende Haende",
+	"Magie entdecken",
+	"magisches Geschoss",
+	"Schild",
+	"Schockgriff",
+	"Unsichtbarkeit",
+	"Ms saeurepfeil",
+	"stinkende Wolke",
+	"Magie bannen",
+	"Feuerball",
+	"Flammenpfeil",
+	"hast",
+	"Person festhalten",
+	"Unsichtbarkeit 3m",
+	"Blitzstrahl",
+	"Vampirgriff",
+	"Furcht",
+	"Eissturm",
+	"Steinhaut",
+	"Todeswolke",
+	"Kaeltekegel",
+	"Monster festhalten",
+	"Segen",
+	"leichte Wunden heilen",
+	"leichte Wunden verursachen",
+	"Magie entdecken",
+	"Schutz vor boesem",
+	"Staerkung",
+	"Flammenklinge",
+	"Person festhalten",
+	"Gift verlangsamen",
+	"Nahrung erschaffen",
+	"Magie bannen",
+	"Schutzgewand",
+	"Gebet",
+	"Laehmung aufheben",
+	"schwere Wunden heilen",
+	"schwere Wunden verursachen",
+	"Gift neutralisieren",
+	"Schutz vor Boes. 3m",
+	"Schutz vor Blitzen",
+	"kritische Wunden heilen",
+	"kritische Wunden verursachen",
+	"Flammenschlag",
+	"Tote erwecken",
+	"Haende auflegen",
+	"",
+	"",
+	""
+};
+
+static const StringListProvider kEoB1SpellNamesAmigaGermanProvider = { ARRAYSIZE(kEoB1SpellNamesAmigaGerman), kEoB1SpellNamesAmigaGerman };
+
+static const char *const kEoB1MagicStrings1AmigaGerman[6] = {
+	"KEIN ZAUBER",
+	"KEIN ZAUBER",
+	"Fuer diesen Zauber musst du eine Hand frei haben.\r",
+	"Zwei Zauber dieses Typs koennen nicht gleichzeitig aktiv sein.\r",
+	"%s zaubert %s.\r",
+	"ok\r"
+};
+
+static const StringListProvider kEoB1MagicStrings1AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings1AmigaGerman), kEoB1MagicStrings1AmigaGerman };
+
+static const char *const kEoB1MagicStrings2AmigaGerman[3] = {
+	"keine wirkung\r",
+	"%s wurde aufgeloest!\r",
+	"Das Team wurde mit einem Todesbann belegt!\r"
+};
+
+static const StringListProvider kEoB1MagicStrings2AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings2AmigaGerman), kEoB1MagicStrings2AmigaGerman };
+
+static const char *const kEoB1MagicStrings3AmigaGerman[6] = {
+	"Zauber auf welchen Charakter anwenden ? ",
+	"\rok\r",
+	"\rZauber abgebrochen.\r",
+	"%ss %s Zauber laesst nach.\r",
+	"%s traf das monster nicht.\r",
+	"%s kann nur in vorderen Reihen zuschlagen!\r"
+};
+
+static const StringListProvider kEoB1MagicStrings3AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings3AmigaGerman), kEoB1MagicStrings3AmigaGerman };
+
+static const char *const kEoB1MagicStrings4AmigaGerman[2] = {
+	"keine wirkung.\r",
+	"keine wirkung\r"
+};
+
+static const StringListProvider kEoB1MagicStrings4AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings4AmigaGerman), kEoB1MagicStrings4AmigaGerman };
+
+static const char *const kEoB1MagicStrings6AmigaGerman[1] = {
+	"%s hat bereits eine hochrangige Ruestungsklasse.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings6AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings6AmigaGerman), kEoB1MagicStrings6AmigaGerman };
+
+static const char *const kEoB1MagicStrings7AmigaGerman[5] = {
+	"1.",
+	"2.",
+	"3.",
+	"4.",
+	"5."
+};
+
+static const StringListProvider kEoB1MagicStrings7AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings7AmigaGerman), kEoB1MagicStrings7AmigaGerman };
+
+static const char *const kEoB1MagicStrings8AmigaGerman[3] = {
+	"Alle Zauber auf %s wurden abgewehrt.\r",
+	"Das Team ist schon gesegnet!\r",
+	"Der Heilzauber versagt!\r"
+};
+
+static const StringListProvider kEoB1MagicStrings8AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings8AmigaGerman), kEoB1MagicStrings8AmigaGerman };
+
+static const char *const kEoB1MagicStrings9AmigaGerman[1] = {
+	"%s wurde schon mit Steinhaut geschuetzt.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings9AmigaGermanProvider = { ARRAYSIZE(kEoB1MagicStrings9AmigaGerman), kEoB1MagicStrings9AmigaGerman };
+
+static const byte kEoB1ManDefAmigaGerman[120] = {
+	0x09, 0x0A, 0x01, 0x00, 0x09, 0x04, 0x03, 0x00,
+	0x09, 0x06, 0x01, 0x00, 0x09, 0x03, 0x03, 0x00,
+	0x09, 0x04, 0x02, 0x00, 0x09, 0x01, 0x02, 0x00,
+	0x09, 0x05, 0x01, 0x00, 0x09, 0x09, 0x02, 0x00,
+	0x09, 0x01, 0x03, 0x00, 0x23, 0x01, 0x05, 0x00,
+	0x23, 0x02, 0x02, 0x00, 0x23, 0x03, 0x06, 0x00,
+	0x23, 0x05, 0x01, 0x00, 0x23, 0x06, 0x03, 0x00,
+	0x23, 0x07, 0x01, 0x00, 0x1A, 0x02, 0x01, 0x00,
+	0x1A, 0x03, 0x02, 0x00, 0x1A, 0x06, 0x01, 0x00,
+	0x24, 0x01, 0x03, 0x00, 0x24, 0x03, 0x03, 0x00,
+	0x24, 0x03, 0x01, 0x00, 0x02, 0x04, 0x03, 0x00,
+	0x02, 0x03, 0x03, 0x00, 0x02, 0x07, 0x02, 0x00,
+	0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x03, 0x00,
+	0x01, 0x04, 0x03, 0x00, 0x0C, 0x02, 0x01, 0x00,
+	0x0C, 0x03, 0x03, 0x00, 0x0C, 0x02, 0x04, 0x00
+};
+
+static const ByteProvider kEoB1ManDefAmigaGermanProvider = { ARRAYSIZE(kEoB1ManDefAmigaGerman), kEoB1ManDefAmigaGerman };
+
+static const char *const kEoB1ManWordAmigaGerman[31] = {
+	"dargestellt",
+	"nur",
+	"attackieren",
+	"sie",
+	"handwaffen",
+	"monster",
+	"diese",
+	"wird",
+	"jedoch",
+	"sie",
+	"getragene",
+	"sobald",
+	"klerikale",
+	"getragene",
+	"sich",
+	"elternteile",
+	"gesicht",
+	"nicht",
+	"ihrer",
+	"magische",
+	"einige",
+	"sich",
+	"charaktere",
+	"gesinnung",
+	"versammlung",
+	"wachen",
+	"des",
+	"werden",
+	"seinen",
+	"greift",
+	""
+};
+
+static const StringListProvider kEoB1ManWordAmigaGermanProvider = { ARRAYSIZE(kEoB1ManWordAmigaGerman), kEoB1ManWordAmigaGerman };
+
+static const char *const kEoB1ManPromptAmigaGerman[1] = {
+	"\r\r\r\rAuf der Seite mit diesem Symbol...\r\rFinde Zeile %d\rGib Wort %d ein\r"
+};
+
+static const StringListProvider kEoB1ManPromptAmigaGermanProvider = { ARRAYSIZE(kEoB1ManPromptAmigaGerman), kEoB1ManPromptAmigaGerman };
+
+static const char *const kEoB1MonsterDistAttStringsAmigaGerman[5] = {
+	"%s wurde von einem Schwere-Wunden-Zauber getroffen!\r",
+	"Das Team wurde von einem psychischen Hirnstoss getroffen!\r",
+	"gelaehmt",
+	"vergiftet",
+	"gelaehmt"
+};
+
+static const StringListProvider kEoB1MonsterDistAttStringsAmigaGermanProvider = { ARRAYSIZE(kEoB1MonsterDistAttStringsAmigaGerman), kEoB1MonsterDistAttStringsAmigaGerman };
+
diff --git a/devtools/create_kyradat/resources/eob1_dos.h b/devtools/create_kyradat/resources/eob1_dos.h
index c278f50..88f82d1 100644
--- a/devtools/create_kyradat/resources/eob1_dos.h
+++ b/devtools/create_kyradat/resources/eob1_dos.h
@@ -1755,3 +1755,20 @@ static const EoBCharacter kEoB1NpcPresetsDOS[9] = {
 
 static const EoBCharacterProvider kEoB1NpcPresetsDOSProvider = { ARRAYSIZE(kEoB1NpcPresetsDOS), kEoB1NpcPresetsDOS };
 
+static const char *const kEoB1SoundFilesIntroDOS[1] = {
+	"SOUND"
+};
+
+static const StringListProvider kEoB1SoundFilesIntroDOSProvider = { ARRAYSIZE(kEoB1SoundFilesIntroDOS), kEoB1SoundFilesIntroDOS };
+
+static const char *const kEoB1SoundFilesIngameDOS[1] = {
+	"ADLIB"
+};
+
+static const StringListProvider kEoB1SoundFilesIngameDOSProvider = { ARRAYSIZE(kEoB1SoundFilesIngameDOS), kEoB1SoundFilesIngameDOS };
+
+static const char *const kEoB1SoundFilesFinaleDOS[1] = {
+	"ADLIB"
+};
+
+static const StringListProvider kEoB1SoundFilesFinaleDOSProvider = { ARRAYSIZE(kEoB1SoundFilesFinaleDOS), kEoB1SoundFilesFinaleDOS };
\ No newline at end of file
diff --git a/devtools/create_kyradat/resources/eob1_dos_english.h b/devtools/create_kyradat/resources/eob1_dos_english.h
index 4f6861e..2b2beb4 100644
--- a/devtools/create_kyradat/resources/eob1_dos_english.h
+++ b/devtools/create_kyradat/resources/eob1_dos_english.h
@@ -817,6 +817,13 @@ static const char *const kEoB1MagicStrings8DOSEnglish[3] = {
 
 static const StringListProvider kEoB1MagicStrings8DOSEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings8DOSEnglish), kEoB1MagicStrings8DOSEnglish };
 
+/*
+static const char *const kEoB1MagicStrings9DOSEnglish[1] = {
+	"%s is already protected by stoneskin.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings9DOSEnglishProvider = { ARRAYSIZE(kEoB1MagicStrings9DOSEnglish), kEoB1MagicStrings9DOSEnglish };
+*/
 static const byte kEoB1ManDefDOSEnglish[120] = {
 	0x09, 0x0A, 0x02, 0x00, 0x09, 0x04, 0x03, 0x00,
 	0x09, 0x06, 0x06, 0x00, 0x09, 0x03, 0x03, 0x00,
diff --git a/devtools/create_kyradat/resources/eob1_dos_german.h b/devtools/create_kyradat/resources/eob1_dos_german.h
index 8551594..9cab7cb 100644
--- a/devtools/create_kyradat/resources/eob1_dos_german.h
+++ b/devtools/create_kyradat/resources/eob1_dos_german.h
@@ -819,6 +819,12 @@ static const char *const kEoB1MagicStrings8DOSGerman[3] = {
 
 static const StringListProvider kEoB1MagicStrings8DOSGermanProvider = { ARRAYSIZE(kEoB1MagicStrings8DOSGerman), kEoB1MagicStrings8DOSGerman };
 
+/*static const char *const kEoB1MagicStrings9DOSGerman[1] = {
+	"%s is already protected by stoneskin.\r"
+};
+
+static const StringListProvider kEoB1MagicStrings9DOSGermanProvider = { ARRAYSIZE(kEoB1MagicStrings9DOSGerman), kEoB1MagicStrings9DOSGerman };
+*/
 static const byte kEoB1ManDefDOSGerman[120] = {
 	0x09, 0x0A, 0x01, 0x00, 0x09, 0x04, 0x03, 0x00,
 	0x09, 0x06, 0x01, 0x00, 0x09, 0x03, 0x03, 0x00,
diff --git a/devtools/create_kyradat/resources/eob1_dos_italian.h b/devtools/create_kyradat/resources/eob1_dos_italian.h
index f2e1a74..abb9453 100644
--- a/devtools/create_kyradat/resources/eob1_dos_italian.h
+++ b/devtools/create_kyradat/resources/eob1_dos_italian.h
@@ -816,7 +816,13 @@ static const char *const kEoB1MagicStrings8DOSItalian[3] = {
 };
 
 static const StringListProvider kEoB1MagicStrings8DOSItalianProvider = { ARRAYSIZE(kEoB1MagicStrings8DOSItalian), kEoB1MagicStrings8DOSItalian };
+/*
+static const char *const kEoB1MagicStrings9DOSItalian[1] = {
+	"%s e gia protetto da pelle di pietra.\r"
+};
 
+static const StringListProvider kEoB1MagicStrings9DOSItalianProvider = { ARRAYSIZE(kEoB1MagicStrings9DOSItalian), kEoB1MagicStrings9DOSItalian };
+*/
 static const byte kEoB1ManDefDOSItalian[120] = {
 	0x09, 0x0A, 0x02, 0x00, 0x09, 0x04, 0x03, 0x00,
 	0x09, 0x06, 0x06, 0x00, 0x09, 0x03, 0x03, 0x00,
diff --git a/devtools/create_kyradat/resources/eob2_dos.h b/devtools/create_kyradat/resources/eob2_dos.h
index 3a44d78..6daf018 100644
--- a/devtools/create_kyradat/resources/eob2_dos.h
+++ b/devtools/create_kyradat/resources/eob2_dos.h
@@ -2491,3 +2491,15 @@ static const byte kEoB2DscBlockIndexDOS[72] = {
 
 static const ByteProvider kEoB2DscBlockIndexDOSProvider = { ARRAYSIZE(kEoB2DscBlockIndexDOS), kEoB2DscBlockIndexDOS };
 
+static const char *const kEoB2SoundFilesIntroDOS[1] = {
+	"INTRO"
+};
+
+static const StringListProvider kEoB2SoundFilesIntroDOSProvider = { ARRAYSIZE(kEoB2SoundFilesIntroDOS), kEoB2SoundFilesIntroDOS };
+
+static const char *const kEoB2SoundFilesFinaleDOS[2] = {
+	"FINALE1",
+	"FINALE2"
+};
+
+static const StringListProvider kEoB2SoundFilesFinaleDOSProvider = { ARRAYSIZE(kEoB2SoundFilesFinaleDOS), kEoB2SoundFilesFinaleDOS };
\ No newline at end of file
diff --git a/devtools/create_kyradat/resources/eob2_fmtowns.h b/devtools/create_kyradat/resources/eob2_fmtowns.h
index 74af7a3..128c7e4 100644
--- a/devtools/create_kyradat/resources/eob2_fmtowns.h
+++ b/devtools/create_kyradat/resources/eob2_fmtowns.h
@@ -73655,4 +73655,16 @@ static const uint16 kEoB2FontDmpSearchTblFMTowns[149] = {
 	0x9681, 0x4881, 0x8381, 0x8481, 0x0000
 };
 
-static const Uint16Provider kEoB2FontDmpSearchTblFMTownsProvider = { ARRAYSIZE(kEoB2FontDmpSearchTblFMTowns), kEoB2FontDmpSearchTblFMTowns };
\ No newline at end of file
+static const Uint16Provider kEoB2FontDmpSearchTblFMTownsProvider = { ARRAYSIZE(kEoB2FontDmpSearchTblFMTowns), kEoB2FontDmpSearchTblFMTowns };
+
+static const char *const kEoB2SoundFilesIntroFMTowns[1] = {
+	"INTRO"
+};
+
+static const StringListProvider kEoB2SoundFilesIntroFMTownsProvider = { ARRAYSIZE(kEoB2SoundFilesIntroFMTowns), kEoB2SoundFilesIntroFMTowns };
+
+static const char *const kEoB2SoundFilesFinaleFMTowns[1] = {
+	"FINALE"
+};
+
+static const StringListProvider kEoB2SoundFilesFinaleFMTownsProvider = { ARRAYSIZE(kEoB2SoundFilesFinaleFMTowns), kEoB2SoundFilesFinaleFMTowns };
\ No newline at end of file
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 8e1fbe9..20114e5 100644
Binary files a/dists/engine-data/kyra.dat and b/dists/engine-data/kyra.dat differ
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 58cc394..21677ac 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -196,7 +196,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
 	_abortStrings = _saveLoadStrings = _mnWord = _mnPrompt = _bookNumbers = 0;
 	_mageSpellList = _clericSpellList = _spellNames = _magicStrings1 = 0;
 	_magicStrings2 = _magicStrings3 = _magicStrings4 = _magicStrings6 = 0;
-	_magicStrings7 = _magicStrings8 = _saveNamePatterns = 0; 
+	_magicStrings7 = _magicStrings8 = _magicStrings9 = _saveNamePatterns = 0;
 	_spellAnimBuffer = 0;
 	_sparkEffectDefSteps = _sparkEffectDefSubSteps = _sparkEffectDefShift = 0;
 	_sparkEffectDefAdd = _sparkEffectDefX = _sparkEffectDefY = _sparkEffectOfShift = 0;
@@ -432,8 +432,12 @@ Common::Error EoBCoreEngine::init() {
 	_debugger = new Debugger_EoB(this);
 	assert(_debugger);
 
-	_screen->loadFont(Screen::FID_6_FNT, "FONT6.FNT");
-	_screen->loadFont(Screen::FID_8_FNT, "FONT8.FNT");
+	if (_flags.platform == Common::kPlatformAmiga) {
+
+	} else {
+		_screen->loadFont(Screen::FID_6_FNT, "FONT6.FNT");
+		_screen->loadFont(Screen::FID_8_FNT, "FONT8.FNT");
+	}
 
 	Common::Error err = KyraRpgEngine::init();
 	if (err.getCode() != Common::kNoError)
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 9078e50..c56a41b 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -1096,6 +1096,7 @@ protected:
 	const char *const *_magicStrings6;
 	const char *const *_magicStrings7;
 	const char *const *_magicStrings8;
+	const char *const *_magicStrings9;
 
 	uint8 *_spellAnimBuffer;
 
diff --git a/engines/kyra/engine/scene_rpg.cpp b/engines/kyra/engine/scene_rpg.cpp
index 72922d4..0528df6 100644
--- a/engines/kyra/engine/scene_rpg.cpp
+++ b/engines/kyra/engine/scene_rpg.cpp
@@ -87,7 +87,6 @@ void KyraRpgEngine::setLevelShapesDim(int index, int16 &x1, int16 &x2, int dim)
 		x1 += (_sceneXoffset >> 3);
 		x2 += (_sceneXoffset >> 3);
 
-
 		_lvlShapeTop[index] = y1;
 		_lvlShapeBottom[index] = y2;
 		_lvlShapeLeftRight[index << 1] = x1;
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index 077b4ea..a1ff902 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -455,6 +455,7 @@ enum KyraResources {
 	kEoBBaseMagicStrings6,
 	kEoBBaseMagicStrings7,
 	kEoBBaseMagicStrings8,
+	kEoBBaseMagicStrings9,
 
 	kEoBBaseExpObjectTlMode,
 	kEoBBaseExpObjectTblIndex,
@@ -486,6 +487,13 @@ enum KyraResources {
 	kEoBBaseConeOfColdDest4,
 	kEoBBaseConeOfColdGfxTbl,
 
+	kEoBBaseSoundMap,
+	kEoBBaseSoundFilesIntro,
+	kEoBBaseSoundFilesIngame,
+	kEoBBaseSoundFilesFinale,
+
+	kEoB1BaseLevelSounds1,
+	kEoB1BaseLevelSounds2,
 	kEoB1MainMenuStrings,
 	kEoB1BonusStrings,
 
@@ -509,6 +517,15 @@ enum KyraResources {
 	kEoB1IntroTvlY2,
 	kEoB1IntroTvlW,
 	kEoB1IntroTvlH,
+	kEoB1IntroOrbFadePal,
+
+	kEoB1FinaleCouncilAnim1,
+	kEoB1FinaleCouncilAnim2,
+	kEoB1FinaleCouncilAnim3,
+	kEoB1FinaleCouncilAnim4,
+	kEoB1FinaleEyesAnim,
+	kEoB1FinaleHandsAnim,
+	kEoB1FinaleTextDuration,
 
 	kEoB1DoorShapeDefs,
 	kEoB1DoorSwitchShapeDefs,
diff --git a/engines/kyra/resource/staticres.cpp b/engines/kyra/resource/staticres.cpp
index fb6d14d..e569cf1 100644
--- a/engines/kyra/resource/staticres.cpp
+++ b/engines/kyra/resource/staticres.cpp
@@ -39,7 +39,7 @@
 
 namespace Kyra {
 
-#define RESFILE_VERSION 92
+#define RESFILE_VERSION 93
 
 namespace {
 bool checkKyraDat(Common::SeekableReadStream *file) {
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index 4a94c84..23a5203 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -432,6 +432,7 @@ void EoBCoreEngine::initStaticResource() {
 	_magicStrings6 = _staticres->loadStrings(kEoBBaseMagicStrings6, temp);
 	_magicStrings7 = _staticres->loadStrings(kEoBBaseMagicStrings7, temp);
 	_magicStrings8 = _staticres->loadStrings(kEoBBaseMagicStrings8, temp);
+	_magicStrings9 = _staticres->loadStrings(kEoBBaseMagicStrings9, temp);
 
 	_expObjectTlMode = _staticres->loadRawData(kEoBBaseExpObjectTlMode, temp);
 	_expObjectTblIndex = _staticres->loadRawData(kEoBBaseExpObjectTblIndex, temp);
@@ -460,6 +461,13 @@ void EoBCoreEngine::initStaticResource() {
 	_coneOfColdDest4 = (const int8 *)_staticres->loadRawData(kEoBBaseConeOfColdDest4, temp);
 	_coneOfColdGfxTbl = _staticres->loadRawData(kEoBBaseConeOfColdGfxTbl, _coneOfColdGfxTblSize);
 
+	_staticres->loadStrings(kEoBBaseSoundMap, temp);
+	_staticres->loadStrings(kEoBBaseLevelSounds1, temp);
+	_staticres->loadStrings(kEoBBaseLevelSounds2, temp);
+	_staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
+	_staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
+	_staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
+
 	// Hard code the following strings, since EOB I doesn't have them in the original.
 	// EOB I doesn't have load and save menus, because there is only one single
 	// save slot. Instead of emulating this we provide a menu similiar to EOB II.
@@ -1129,11 +1137,9 @@ void EoBEngine::initStaticResource() {
 		p->dmgDc[2].base = (int8)*ps++;
 		ps++;
 		p->capsFlags = *ps++;
-		p->typeFlags = READ_LE_UINT16(ps);
-		ps += 2;
-		ps++;
-		ps++;
-		p->experience = READ_LE_UINT16(ps);
+		p->typeFlags = (_flags.platform == Common::kPlatformAmiga) ? READ_BE_UINT32(++ps) : READ_LE_UINT32(ps);
+		ps += 4;
+		p->experience = (_flags.platform == Common::kPlatformAmiga) ? READ_BE_UINT16(ps) : READ_LE_UINT16(ps);
 		ps += 2;
 		p->u30 = *ps++;
 		p->sound1 = (int8)*ps++;
@@ -1226,6 +1232,8 @@ void EoBEngine::initSpells() {
 
 	for (int i = 0; i < _numSpells; i++) {
 		EoBSpell *s = &_spells[i];
+		if (_flags.platform == Common::kPlatformAmiga)
+			src++;
 		src += 4;
 		s->flags = flagTable[i].typeFlag;
 		s->damageFlags = flagTable[i].damageFlag;


Commit: 4cc9c81a75f73216ba98b3744a32c900aad36061
    https://github.com/scummvm/scummvm/commit/4cc9c81a75f73216ba98b3744a32c900aad36061
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:20+01:00

Commit Message:
KYRA: (EOB1/Amiga) - add sound driver

Changed paths:
  A engines/kyra/sound/drivers/audiomaster2.cpp
  A engines/kyra/sound/drivers/audiomaster2.h
  A engines/kyra/sound/sound_amiga_eob.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/module.mk
    engines/kyra/sound/sound.h
    engines/kyra/sound/sound_intern.h


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 21677ac..0e3e130 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -404,6 +404,8 @@ Common::Error EoBCoreEngine::init() {
 		_sound = new SoundTowns_Darkmoon(this, _mixer);
 	} else if (_flags.platform == Common::kPlatformPC98) {
 
+	} else if (_flags.platform == Common::kPlatformAmiga) {
+		_sound = new SoundAmiga_EoB(this, _mixer);
 	}
 
 	assert(_sound);
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index 037ebe9..9c20ad6 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -123,7 +123,9 @@ MODULE_OBJS += \
 	script/script_eob.o \
 	sequence/sequences_eob.o \
 	sequence/sequences_darkmoon.o \
-	sound/sound_towns_darkmoon.o
+	sound/sound_amiga_eob.o \
+	sound/sound_towns_darkmoon.o \
+	sound/drivers/audiomaster2.o
 endif
 
 # This module can be built as a plugin
diff --git a/engines/kyra/sound/drivers/audiomaster2.cpp b/engines/kyra/sound/drivers/audiomaster2.cpp
new file mode 100644
index 0000000..404bb84
--- /dev/null
+++ b/engines/kyra/sound/drivers/audiomaster2.cpp
@@ -0,0 +1,1390 @@
+/* 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 "kyra/resource/resource.h"
+#include "kyra/sound/drivers/audiomaster2.h"
+
+#include "audio/mods/paula.h"
+
+#include "common/iff_container.h"
+
+namespace Kyra {
+
+class AudioMaster2ResourceManager;
+class AudioMaster2Internal;
+class SoundResource;
+
+class AudioMaster2IOManager {
+public:
+	AudioMaster2IOManager();
+	~AudioMaster2IOManager();
+
+	struct IOUnit {
+		IOUnit() : _next(0), _sampleData(0), _sampleDataRepeat(0), _lenOnce(0), _lenRepeat(0), _startTick(0), _endTick(0), _transposeData(0), _rate(0), _period(0), _transposePara(0), _transposeCounter(0),
+			_levelAdjustData(0), _volumeSetting(0), _outputVolume(0), _levelAdjustPara(0), _levelAdjustCounter(0), _flags(0) {}
+
+		IOUnit *_next;
+		const int8 *_sampleData;
+		const int8 *_sampleDataRepeat;
+		uint32 _lenOnce;
+		uint32 _lenRepeat;
+		uint32 _startTick;
+		uint32 _endTick;
+		const uint8 *_transposeData;
+		uint16 _rate;
+		uint16 _period;
+		uint16 _transposePara;
+		uint8 _transposeCounter;
+		const uint8 *_levelAdjustData;
+		uint16 _volumeSetting;
+		uint16 _outputVolume;
+		int16 _levelAdjustPara;
+		uint8 _levelAdjustCounter;
+		uint8 _flags;
+	};
+
+	void clearChain();
+	void deployChannels(IOUnit **dest);
+	IOUnit *requestFreeUnit();
+
+	uint32 _sync;
+	uint32 _tempo;
+
+private:
+	IOUnit *_units[8];
+	IOUnit *_ioChain;
+};
+
+class AudioMaster2Internal : public Audio::Paula {
+friend class AudioMaster2IOManager;
+private:
+	AudioMaster2Internal(Audio::Mixer *mixer);
+public:
+	~AudioMaster2Internal();
+
+	static AudioMaster2Internal *open(Audio::Mixer *mixer);
+	static void close();
+
+	bool init();
+	bool loadRessourceFile(Common::SeekableReadStream *data);
+
+	bool startSound(const Common::String &name);
+	bool stopSound(const Common::String &name);
+
+	void flushResource(const Common::String &name);
+	void flushAllResources();
+
+	void interrupt();
+
+	void sync(SoundResource *res);
+	void stopChannels();
+
+private:
+	void updateDevice();
+
+	AudioMaster2IOManager::IOUnit *_channels[4];
+
+	AudioMaster2IOManager *_io;
+	AudioMaster2ResourceManager *_res;
+	Audio::Mixer *_mixer;
+
+	static AudioMaster2Internal *_refInstance;
+	static int _refCount;
+
+	Audio::SoundHandle _soundHandle;
+	bool _ready;
+};
+
+class SoundResource {
+protected:
+	SoundResource(AudioMaster2ResourceManager *res, int type) : _res(res), _type(type), _playing(false), _next(0), _refCnt(1) {}
+	virtual ~SoundResource() {}
+public:
+	void loadName(Common::ReadStream *stream, uint32 size);
+
+	void open();
+	void close();
+
+	virtual void prepare() {}
+	virtual void setSync(uint32 sync) {}
+
+	const Common::String &getName() const;
+	uint8 getType() const;
+	bool getPlayStatus() const;
+	void setPlayStatus(bool playing);
+
+	virtual void interrupt(AudioMaster2IOManager *io);
+	virtual void setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume) {}
+
+	enum Mode {
+		kIdle = 0,
+		kRestart = 1
+	};
+
+	SoundResource *_next;
+
+protected:
+	Common::String _name;
+	const uint8 _type;
+	uint8 _flags;
+	AudioMaster2ResourceManager *_res;
+
+private:
+	virtual void release() = 0;
+	virtual void setupEnvelopes(AudioMaster2IOManager::IOUnit *unit) {}
+	virtual void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 tempo) {}
+
+	int _refCnt;
+	bool _playing;
+};
+
+class SoundResource8SVX : public SoundResource {
+public:
+	SoundResource8SVX(AudioMaster2ResourceManager *res);
+private:
+	virtual ~SoundResource8SVX();
+public:
+	void loadHeader(Common::ReadStream *stream, uint32 size);
+	void loadData(Common::ReadStream *stream, uint32 size);
+
+	void setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume);
+	void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 tempo);
+
+private:
+	void release();
+
+	void setupEnvelopes(AudioMaster2IOManager::IOUnit *unit);
+
+	uint32 _numSamplesOnce;
+	uint32 _numSamplesRepeat;
+	uint32 _numSamplesPerCycle;
+	uint16 _rate;
+	uint8 _numBlocks;
+	uint8 _format;
+	uint32 _volume;
+
+	const int8 *_data;
+	uint32 _dataSize;
+
+	static const uint32 _periods[128];
+};
+
+class SoundResourceINST : public SoundResource {
+public:
+	SoundResourceINST(AudioMaster2ResourceManager *res) : SoundResource(res, 2), _samplesResource(0), _transpose(0), _levelAdjust(0) {}
+private:
+	virtual ~SoundResourceINST();
+public:
+	void loadPitchData(Common::ReadStream *stream, uint32 size);
+	void loadSamples(Common::ReadStream *stream, uint32 size);
+	void loadVolumeData(Common::ReadStream *stream, uint32 size);
+
+	void setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume);
+
+	struct EnvelopeData {
+		EnvelopeData(const uint8 *data, uint32 size) : volume(0x40), _data(data), _dataSize(size) {}
+		~EnvelopeData() { delete[] _data; }
+		uint8 volume;
+		const uint8 *_data;
+		uint32 _dataSize;
+	};
+
+private:
+	void release();
+
+	void setupEnvelopes(AudioMaster2IOManager::IOUnit *unit);
+	void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 rate);
+
+	EnvelopeData *_transpose;
+	EnvelopeData *_levelAdjust;
+	SoundResource8SVX *_samplesResource;
+};
+
+class SoundResourceSMUS : public SoundResource {
+public:
+	SoundResourceSMUS(AudioMaster2ResourceManager *res) : SoundResource(res, 1), _tempo(0), _vol(0), _masterVolume(0x40), _playFlags(0) {}
+private:
+	virtual ~SoundResourceSMUS();
+public:
+	void loadHeader(Common::ReadStream *stream, uint32 size);
+	void loadInstrument(Common::ReadStream *stream, uint32 size);
+	void loadTrack(Common::ReadStream *stream, uint32 size);
+
+	void prepare();
+	uint16 getTempo() const;
+	void setSync(uint32 sync);
+
+	void interrupt(AudioMaster2IOManager *io);
+
+private:
+	void release();
+
+	struct Track {
+		Track() : _dataStart(0), _dataEnd(0), _dataCur(0), _instrument(0), _volume(0), _sync(0) {}
+		~Track() {
+			if (_instrument)
+				_instrument->close();
+			delete[] _dataStart;
+		}
+
+		void setInstrument(SoundResource *instr) {
+			if (_instrument)
+				_instrument->close();
+			_instrument = instr;
+			_instrument->open();
+		}
+
+		uint32 _sync;
+		SoundResource *_instrument;
+		uint8 _volume;
+		const uint8 *_dataStart;
+		const uint8 *_dataEnd;
+		const uint8 *_dataCur;
+	};
+
+	bool parse(AudioMaster2IOManager *io, Track *track);
+	
+	uint16 _tempo;
+	uint16 _masterVolume;
+	uint8 _vol;
+
+	static const uint16 _durationTable[64];
+
+	Common::Array<Track*> _tracks;
+	Common::Array<SoundResource*> _instruments;
+	uint16 _playFlags;
+};
+
+class AudioMaster2ResourceManager {
+public:
+	AudioMaster2ResourceManager(AudioMaster2Internal *driver, Common::Mutex *mutex) : _driver(driver), _mutex(mutex), _chainPlaying(0), _chainInactive(0) {}
+	~AudioMaster2ResourceManager();
+
+	void loadResourceFile(Common::SeekableReadStream *data);
+
+	void initResource(SoundResource *resource);
+	void releaseResource(const Common::String &resName);
+
+	void flush();
+
+	SoundResource *getResource(const Common::String &resName, SoundResource::Mode mode);
+
+	void interrupt(AudioMaster2IOManager *io);
+	
+private:
+	SoundResource *retrieveFromChain(const Common::String &resName);
+	void linkToChain(SoundResource *resource, SoundResource::Mode mode);
+	void stopChain();
+
+	SoundResource *_chainPlaying;
+	SoundResource *_chainInactive;
+
+	AudioMaster2Internal *_driver;
+	Common::Mutex *_mutex;
+};
+
+class AudioMaster2IFFLoader : public Common::IFFParser {
+public:
+	AudioMaster2IFFLoader(Common::SeekableReadStream *stream, AudioMaster2ResourceManager *res) : Common::IFFParser(stream), _res(res), _curSong(0), _curSfx(0), _curIns(0) {}
+	virtual ~AudioMaster2IFFLoader();
+
+	bool loadChunk(Common::IFFChunk &chunk);
+
+private:
+	void initResource();
+
+	// define only additional chunk types which aren't already defined in common/iff_container.h
+	enum ChunkTypes {
+		ID_INST = MKTAG('I', 'N', 'S', 'T'),
+		ID_PTCH = MKTAG('P', 'T', 'C', 'H'),
+		ID_SAMP = MKTAG('S', 'A', 'M', 'P'),
+		ID_VLUM = MKTAG('V', 'L', 'U', 'M'),
+		ID_SMUS = MKTAG('S', 'M', 'U', 'S'),
+		ID_TRAK = MKTAG('T', 'R', 'A', 'K'),
+		ID_SHDR = MKTAG('S', 'H', 'D', 'R'),
+		ID_INS1 = MKTAG('I', 'N', 'S', '1')
+	};
+
+	SoundResourceINST *_curIns;
+	SoundResourceSMUS *_curSong;
+	SoundResource8SVX *_curSfx;
+
+	AudioMaster2ResourceManager *_res;
+};
+
+AudioMaster2IOManager::AudioMaster2IOManager() : _sync(1), _tempo(1), _ioChain(0) {
+	for (int i = 0; i < 8; ++i)
+		_units[i] = new IOUnit();
+}
+
+AudioMaster2IOManager::~AudioMaster2IOManager() {
+	for (int i = 0; i < 8; ++i)
+		delete _units[i];
+}
+
+void AudioMaster2IOManager::clearChain() {
+	_ioChain = 0;
+}
+
+void AudioMaster2IOManager::deployChannels(IOUnit **dest) {
+	IOUnit *cur = _ioChain;
+	IOUnit *prev = 0;
+	_ioChain = 0;
+
+	for (; cur; cur = cur->_next) {
+		if (!(cur->_flags & 1)) {
+			cur->_flags &= ~2;
+
+			if (prev)
+				prev->_next = cur->_next;
+			else
+				_ioChain = cur->_next;
+
+			continue;
+		}
+
+		IOUnit *unit = 0;
+		uint32 lowest = 0xFFFFFFFF;
+		uint8 chan = 3;
+		bool foundFree = false;
+
+		for (uint8 i = 3; i < 4; --i) {
+			unit = dest[i];
+			if (!unit) {
+				chan = i;
+				foundFree = true;
+				break;
+			}
+
+			if (unit->_endTick < lowest) {
+				lowest = unit->_endTick;
+				chan = i;
+			}
+		}
+
+		if (!foundFree) {
+			dest[chan]->_flags &= ~2;
+			// The original driver sends ADCMD_FINISH here, but we don't need to do anything,
+			// since this driver runs on the same thread as the emulated hardware.
+		}
+
+		dest[chan] = cur;
+		prev = cur;
+	}
+}
+
+AudioMaster2IOManager::IOUnit *AudioMaster2IOManager::requestFreeUnit() {
+	for (int i = 0; i < 8; ++i) {
+		if (_units[i]->_flags & 2)
+			continue;
+		_units[i]->_flags = 7;
+		_units[i]->_next = _ioChain;
+		_ioChain = _units[i];
+		return _units[i];
+	}
+
+	return 0;
+}
+
+void SoundResource::loadName(Common::ReadStream *stream, uint32 size) {
+	char *data = new char[size + 1];
+
+	stream->read(data, size);
+	data[size] = '\0';
+	_name = data;
+
+	delete[] data;
+}
+
+void SoundResource::open() {
+	_refCnt++;
+}
+
+void SoundResource::close() {
+	if (--_refCnt <= 0)
+		release();
+}
+
+const Common::String &SoundResource::getName() const {
+	return _name;
+}
+
+uint8 SoundResource::getType() const {
+	return _type;
+}
+
+bool SoundResource::getPlayStatus() const {
+	return _playing;
+}
+
+void SoundResource::setPlayStatus(bool playing) {
+	_playing = playing;
+}
+
+void SoundResource::interrupt(AudioMaster2IOManager *io) {
+	setPlayStatus(false);
+	AudioMaster2IOManager::IOUnit *unit = io->requestFreeUnit();
+	setupSoundEffect(unit, io->_sync, io->_tempo);
+}
+
+SoundResource8SVX::SoundResource8SVX(AudioMaster2ResourceManager *res) : SoundResource(res, 4) {
+	_numSamplesOnce = _numSamplesRepeat = _numSamplesPerCycle = _volume = _dataSize = 0;
+	_rate = 0;
+	_numBlocks = _format = 0;
+	_data = 0;
+}
+
+SoundResource8SVX::~SoundResource8SVX() {
+	delete[] _data;
+}
+
+void SoundResource8SVX::loadHeader(Common::ReadStream *stream, uint32 size) {
+	if (size < 20)
+		error("SoundResource8SVX:loadHeader(): Invalid data chunk size");
+
+	_numSamplesOnce = stream->readUint32BE();
+	_numSamplesRepeat = stream->readUint32BE();
+	_numSamplesPerCycle = stream->readUint32BE();
+	_rate = stream->readUint16BE();
+	_numBlocks = stream->readByte();
+	_format = stream->readByte();
+
+	if (_format)
+		error("SoundResource8SVX:loadHeader(): Unsupported data format");
+
+	_volume = stream->readUint32BE();
+}
+
+void SoundResource8SVX::loadData(Common::ReadStream *stream, uint32 size) {
+	delete[] _data;
+	_dataSize = size;
+	int8 *data = new int8[size];
+	stream->read(data, size);
+	_data = data;
+}
+
+void SoundResource8SVX::setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume) {
+	uint32 no = _numSamplesOnce;
+	uint32 nr = _numSamplesRepeat;
+	// The original code uses 3579546 here. But since the Paula code uses kPalPaulaClock I do the same.
+	uint32 rt = Audio::Paula::kPalPaulaClock;
+	uint32 offs = 0;
+	
+	if (_numSamplesRepeat && _numSamplesPerCycle) {
+		uint32 octave = _numBlocks;		
+		rt = _periods[note] << 13;
+
+		for (rt /= _numSamplesPerCycle; rt >= 0x4000000 && octave > 1; octave--) {
+			offs += (no + nr);
+			no <<= 1;
+			nr <<= 1;
+			rt >>= 1;
+			rt /= _numSamplesPerCycle;
+		}
+
+		for (; octave > 1 && rt >= 0x46000; octave--) {
+			offs += (no + nr);
+			no <<= 1;
+			nr <<= 1;
+			rt >>= 1;
+		}
+		rt >>= 13;
+
+	} else if (_rate) {
+		rt /= _rate;
+	}
+
+	unit->_sampleData = _data + offs;
+	unit->_sampleDataRepeat = nr ? unit->_sampleData + no : 0;
+	unit->_lenOnce = no;
+	unit->_lenRepeat = nr;
+	unit->_rate = unit->_period = rt;
+	unit->_volumeSetting = unit->_outputVolume = volume;
+	setupEnvelopes(unit);
+}
+
+void SoundResource8SVX::setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 tempo) {
+	if (!unit)
+		return;
+
+	unit->_startTick = sync;
+	// The original code uses 3579546 here. But since the Paula code uses kPalPaulaClock I do the same.
+	unit->_rate = unit->_period = Audio::Paula::kPalPaulaClock / (_rate ? _rate : 2000);
+
+	uint32 no = _numSamplesOnce;
+	uint32 nr = _numSamplesRepeat;
+	uint32 octave = _numBlocks;
+	uint32 offs = 0;
+
+	for (; octave > 1; octave--) {
+		offs += (no + nr);
+		no <<= 1;
+		nr <<= 1;
+	}
+
+	unit->_sampleData = _data + offs;
+	unit->_sampleDataRepeat = nr ? unit->_sampleData + no : 0;
+	unit->_lenOnce = no;
+	unit->_lenRepeat = nr;
+
+	unit->_endTick = _numSamplesRepeat ? 0xFFFFFFFF : (tempo * _numSamplesOnce * 60) / _rate + sync;
+	unit->_volumeSetting = unit->_outputVolume = (_volume >= 0xFFFF) ? _volume >> 2 : 0x4000;
+	setupEnvelopes(unit);
+}
+
+void SoundResource8SVX::release() {
+	delete this;
+}
+
+void SoundResource8SVX::setupEnvelopes(AudioMaster2IOManager::IOUnit *unit) {
+	assert(unit);
+	unit->_transposeData = 0;
+	unit->_levelAdjustData = 0;
+}
+
+const uint32 SoundResource8SVX::_periods[128] = {
+	0x0006ae3f, 0x00064e42, 0x0005f3a8, 0x00059e23, 0x00054d6c, 0x0005013c, 0x0004b953, 0x00047573,
+	0x00043563, 0x0003f8eb, 0x0003bfd7, 0x000389f8, 0x0003571f, 0x00032721, 0x0002f9d4, 0x0002cf11,
+	0x0002a6b6, 0x0002809e, 0x00025ca9, 0x00023ab9, 0x00021ab1, 0x0001fc75, 0x0001dfeb, 0x0001c4fc,
+	0x0001ab8f, 0x00019390, 0x00017cea, 0x00016788, 0x0001535b, 0x0001404f, 0x00012e54, 0x00011d5c,
+	0x00010d58, 0x0000fe3a, 0x0000eff5, 0x0000e27e, 0x0000d5c7, 0x0000c9c8, 0x0000be75, 0x0000b3c4,
+	0x0000a9ad, 0x0000a027, 0x0000972a, 0x00008eae, 0x000086ac, 0x00007f1d, 0x000077fa, 0x0000713f,
+	0x00006ae3, 0x000064e4, 0x00005f3a, 0x000059e2, 0x000054d6, 0x00005013, 0x00004b95, 0x00004757,
+	0x00004356, 0x00003f8e, 0x00003bfd, 0x0000389f, 0x00003571, 0x00003272, 0x00002f9d, 0x00002cf1,
+	0x00002a6b, 0x00002809, 0x000025ca, 0x000023ab, 0x000021ab, 0x00001fc7, 0x00001dfe, 0x00001c4f,
+	0x00001ab8, 0x00001939, 0x000017ce, 0x00001678, 0x00001535, 0x00001404, 0x000012e5, 0x000011d5,
+	0x000010d5, 0x00000fe3, 0x00000eff, 0x00000e27, 0x00000d5c, 0x00000c9c, 0x00000be7, 0x00000b3c,
+	0x00000a9a, 0x00000a02, 0x00000972, 0x000008ea, 0x0000086a, 0x000007f1, 0x0000077f, 0x00000713,
+	0x000006ae, 0x0000064e, 0x000005f3, 0x0000059e, 0x0000054d, 0x00000501, 0x000004b9, 0x00000475,
+	0x00000435, 0x000003f8, 0x000003bf, 0x00000389, 0x00000357, 0x00000327, 0x000002f9, 0x000002cf,
+	0x000002a6, 0x00000280, 0x0000025c, 0x0000023a, 0x0000021a, 0x000001fc, 0x000001df, 0x000001c4,
+	0x000001ab, 0x00000193, 0x0000017c, 0x00000167, 0x00000153, 0x00000140, 0x0000012e, 0x0000011d
+};
+
+SoundResourceINST::~SoundResourceINST() {
+	if (_samplesResource)
+		_samplesResource->close();
+
+	delete _transpose;
+	delete _levelAdjust;
+}
+
+void SoundResourceINST::loadPitchData(Common::ReadStream *stream, uint32 size) {
+	delete _transpose;
+	uint8 *data = new uint8[size];
+	stream->read(data, size);
+	_transpose = new EnvelopeData(data, size);
+}
+
+void SoundResourceINST::loadSamples(Common::ReadStream *stream, uint32 size) {
+	char *data = new char[size + 1];
+	stream->read(data, size);
+	data[size] = '\0';
+	
+	if (_samplesResource)
+		_samplesResource->close();
+
+	SoundResource *instr = _res->getResource(data, SoundResource::kIdle);
+	if (instr) {
+		int type = instr->getType();
+		if (type != 4)
+			error("SoundResourceINST::loadInstrument(): Unexpected resource type");
+		instr->open();
+		_samplesResource = (SoundResource8SVX*)instr;
+	} else {
+		warning("SoundResourceINST::loadInstrument(): Samples resource '%s' not found for '%s'.", data, _name.c_str());
+	}
+
+	delete[] data;
+}
+
+void SoundResourceINST::loadVolumeData(Common::ReadStream *stream, uint32 size) {
+	delete _levelAdjust;
+	uint8 *data = new uint8[size];
+	stream->read(data, size);
+	_levelAdjust = new EnvelopeData(data, size);
+}
+
+void SoundResourceINST::setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume) {
+	assert(unit);
+	_samplesResource->setupMusicNote(unit, note, volume);
+	setupEnvelopes(unit);
+}
+
+void SoundResourceINST::release() {
+	delete this;
+}
+
+void SoundResourceINST::setupEnvelopes(AudioMaster2IOManager::IOUnit *unit) {
+	assert(unit);
+	if (_transpose) {
+		unit->_transposeData = _transpose->_data;
+		unit->_transposeCounter = 0;
+		unit->_transposePara = 0;
+	} else {
+		unit->_transposeData = 0;
+	}
+
+	if (_levelAdjust) {
+		unit->_levelAdjustData = _levelAdjust->_data;
+		unit->_levelAdjustCounter = 0;
+		unit->_levelAdjustPara = 0;
+	} else {
+		unit->_levelAdjustData = 0;
+	}
+}
+
+void SoundResourceINST::setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 rate) {
+	if (!unit)
+		return;
+	
+	if (_samplesResource)
+		_samplesResource->setupSoundEffect(unit, sync, rate);
+
+	setupEnvelopes(unit);
+}
+
+SoundResourceSMUS::~SoundResourceSMUS() {
+	for (Common::Array<Track*>::iterator i = _tracks.begin(); i != _tracks.end(); ++i)
+		delete *i;
+	for (Common::Array<SoundResource*>::iterator i = _instruments.begin(); i != _instruments.end(); ++i)
+		(*i)->close();
+}
+
+void SoundResourceSMUS::loadHeader(Common::ReadStream *stream, uint32 size) {
+	if (size < 3)
+		error("SoundResourceSMUS:loadHeader(): Invalid data chunk size");
+	
+	_tempo = stream->readUint16BE() / 68;
+	_vol = stream->readByte();
+}
+
+void SoundResourceSMUS::loadInstrument(Common::ReadStream *stream, uint32 size) {
+	stream->readUint32BE();
+	size -= 4;
+
+	char *data = new char[size + 1];
+	stream->read(data, size);
+	data[size] = '\0';
+
+	SoundResource *instr = _res->getResource(data, SoundResource::kIdle);
+	if (instr) {
+		int type = instr->getType();
+		if (type == 1)
+			error("SoundResourceSMUS::loadInstrument(): Unexpected resource type");
+		instr->open();
+		_instruments.push_back(instr);
+	} else {
+		warning("SoundResourceSMUS::loadInstrument(): Samples resource '%s' not found for '%s'.", data, _name.c_str());
+	}
+
+	delete[] data;	
+}
+
+void SoundResourceSMUS::loadTrack(Common::ReadStream *stream, uint32 size) {
+	Track *track = new Track();
+	uint8 *data = new uint8[size];
+	stream->read(data, size);
+	
+	track->_dataStart = data;
+	track->_dataEnd = data + size;
+	track->_volume = 128;
+
+	_tracks.push_back(track);
+}
+
+void SoundResourceSMUS::prepare() {
+	_playFlags = 0;
+	for (Common::Array<Track*>::iterator trk = _tracks.begin(); trk != _tracks.end(); ++trk) {
+		(*trk)->_dataCur = (*trk)->_dataStart;
+
+		for (Common::Array<SoundResource*>::iterator instr = _instruments.begin(); instr != _instruments.end(); ++instr) {
+			(*trk)->setInstrument(*instr);
+			break;
+		}
+
+		if (!(*trk)->_instrument)
+			error("SoundResourceSMUS::prepare():: Unable to assign default instrument to track (resource files loaded in the wrong order?)");
+
+		_playFlags = (_playFlags << 1) | 1;
+	}
+}
+
+uint16 SoundResourceSMUS::getTempo() const {
+	return _tempo;
+}
+
+void SoundResourceSMUS::setSync(uint32 sync) {
+	for (Common::Array<Track*>::iterator i = _tracks.begin(); i != _tracks.end(); ++i)
+		(*i)->_sync = sync;
+	_masterVolume = 0x40;
+}
+
+void SoundResourceSMUS::interrupt(AudioMaster2IOManager *io) {
+	for (uint32 i = 0; i < _tracks.size(); ++i) {
+		if (!parse(io, _tracks[i]))
+			_playFlags &= ~(1 << i);
+	}
+
+	if (!_playFlags)
+		setPlayStatus(false);
+}
+
+void SoundResourceSMUS::release() {
+	delete this;
+}
+
+bool SoundResourceSMUS::parse(AudioMaster2IOManager *io, Track *track) {
+	uint32 duration = 0;
+	
+	while (track->_sync <= io->_sync) {
+		if (track->_dataCur >= track->_dataEnd)
+			return false;
+
+		uint8 cmd = *track->_dataCur++;
+		uint8 para = *track->_dataCur++;
+
+		if (cmd <= 0x80) {
+			if (para & 0x80)
+				continue;
+
+			duration += _durationTable[para & 0x3f];
+			if (para & 0x40)
+				continue;
+
+			if (cmd < 0x80) {
+				AudioMaster2IOManager::IOUnit *unit = io->requestFreeUnit();
+				if (unit) {
+					unit->_startTick = track->_sync;
+					unit->_endTick = unit->_startTick + duration;					
+					track->_instrument->setupMusicNote(unit, cmd, _masterVolume * track->_volume);
+				}
+			}
+
+			track->_sync += duration;
+			duration = 0;
+
+		} else {
+			switch (cmd) {
+			case 0x81:
+				assert(para < _instruments.size());
+				track->setInstrument(_instruments[para]);
+				break;
+
+			case 0x84:
+				track->_volume = para;
+				break;
+
+			case 0x88:
+				//not implemented
+				break;
+
+			case 0xFF:
+				return false;
+
+			default:
+				break;
+			}
+		}
+	}
+
+	return true;
+}
+
+const uint16 SoundResourceSMUS::_durationTable[64] = {
+	0x6900, 0x3480, 0x1a40, 0x0d20, 0x0690, 0x0348, 0x01a4, 0x00d2,
+	0x9d80, 0x4ec0, 0x2760, 0x13b0, 0x09d8, 0x04ec, 0x0276, 0x013b,
+	0x4600, 0x2300, 0x1180, 0x08c0, 0x0460, 0x0230, 0x0118, 0x008c,
+	0x6900, 0x3480, 0x1a40, 0x0d20, 0x0690, 0x0348, 0x01a4, 0x00d2,
+	0x5400, 0x2a00, 0x1500, 0x0a80, 0x0540, 0x02a0, 0x0150, 0x00a8,
+	0x7e00, 0x3f00, 0x1f80, 0x0fc0, 0x07e0, 0x03f0, 0x01f8, 0x00fc,
+	0x5a00, 0x2d00, 0x1680, 0x0b40, 0x05a0, 0x02d0, 0x0168, 0x00b4,
+	0x8700, 0x4380, 0x21c0, 0x10e0, 0x0870, 0x0438, 0x021c, 0x010e
+};
+
+AudioMaster2ResourceManager::~AudioMaster2ResourceManager() {
+	flush();
+}
+
+void AudioMaster2ResourceManager::loadResourceFile(Common::SeekableReadStream *data) {
+	do {
+		AudioMaster2IFFLoader loader(data, this);
+		Common::Functor1Mem<Common::IFFChunk&, bool, AudioMaster2IFFLoader> cb(&loader, &AudioMaster2IFFLoader::loadChunk);
+		loader.parse(cb);
+	} while (data->pos() < data->size());
+}
+
+void AudioMaster2ResourceManager::initResource(SoundResource *resource) {
+	if (!resource)
+		return;
+
+	SoundResource *res = retrieveFromChain(resource->getName());
+	// The driver does not replace resources with the same name, but disposes the new resource instead.
+	// So these names seem to be considered "globally unique".
+	if (res)
+		resource->close();
+	else
+		res = resource;
+
+	linkToChain(res, SoundResource::kIdle);
+}
+
+void AudioMaster2ResourceManager::releaseResource(const Common::String &resName) {
+	stopChain();
+
+	SoundResource *res = retrieveFromChain(resName);
+	if (!res)
+		return;
+
+	res->setPlayStatus(false);
+	res->close();
+}
+
+void AudioMaster2ResourceManager::flush() {
+	stopChain();
+
+	Common::StackLock lock(*_mutex);
+
+	for (SoundResource *res = _chainPlaying; _chainPlaying; res = _chainPlaying) {
+		_chainPlaying = res->_next;
+		res->_next = 0;
+		res->setPlayStatus(false);
+		res->close();
+	}
+
+	for (SoundResource *res = _chainInactive; _chainInactive; res = _chainInactive) {
+		_chainInactive = res->_next;
+		res->_next = 0;
+		res->setPlayStatus(false);
+		res->close();
+	}
+}
+
+SoundResource *AudioMaster2ResourceManager::getResource(const Common::String &resName, SoundResource::Mode mode) {
+	if (resName.empty())
+		return 0;
+
+	SoundResource *res = retrieveFromChain(resName);
+	if (!res)
+		return 0;
+
+	linkToChain(res, mode);
+
+	return res;
+}
+
+void AudioMaster2ResourceManager::interrupt(AudioMaster2IOManager *io) {
+	SoundResource *cur = _chainPlaying;
+	SoundResource *prev = 0;
+
+	while (cur) {
+		cur->interrupt(io);
+
+		if (cur->getPlayStatus()) {
+			prev = cur;
+			cur = cur->_next;
+		} else if (prev) {
+			prev->_next = cur->_next;
+			cur->_next = _chainInactive;
+			_chainInactive = cur;
+			cur = prev->_next;
+		} else {
+			_chainPlaying = cur->_next;
+			cur->_next = _chainInactive;
+			_chainInactive = cur;
+			cur = _chainPlaying;
+		}
+	}
+}
+
+SoundResource *AudioMaster2ResourceManager::retrieveFromChain(const Common::String &resName) {
+	if (resName.empty())
+		return 0;
+
+	// The requesting (SMUS or INST) resources use shorter (cut off) versions of the actual name strings stored in the requested
+	// (INST or 8SVX) resources. E. g. the EOB intro song will request (among other things) a 'flute' and a 'vibe', although
+	// the actual resource names are 'flute3c' and 'vibe3c'. I would have liked to have all these strings hashed into uint32 IDs,
+	// but this "feature" spoils that idea.
+
+	const char *srchStr = resName.c_str();
+	uint32 srchDepth = strlen(srchStr);
+
+	SoundResource *cur = _chainPlaying;
+	SoundResource *prev = 0;
+
+	Common::StackLock lock(*_mutex);
+
+	while (cur) {
+		if (!scumm_strnicmp(cur->getName().c_str(), srchStr, srchDepth)) {
+			if (prev)
+				prev->_next = cur->_next;
+			else
+				_chainPlaying = cur->_next;
+			cur->_next = 0;
+			return cur;
+		}
+		prev = cur;
+		cur = cur->_next;
+	}
+
+	cur = _chainInactive;
+	prev = 0;
+
+	while (cur) {
+		if (!scumm_strnicmp(cur->getName().c_str(), srchStr, srchDepth)) {
+			if (prev)
+				prev->_next = cur->_next;
+			else
+				_chainInactive = cur->_next;
+			cur->_next = 0;
+			return cur;
+		}
+		prev = cur;
+		cur = cur->_next;
+	}
+
+	return 0;
+}
+
+
+void AudioMaster2ResourceManager::linkToChain(SoundResource *resource, SoundResource::Mode mode) {
+	if (resource->getType() == 1) {
+		stopChain();
+		resource->prepare();
+	}
+
+	Common::StackLock lock(*_mutex);
+
+	if (mode == SoundResource::kRestart) {
+		resource->setPlayStatus(true);
+		resource->_next = _chainPlaying;
+		_chainPlaying = resource;
+
+		if (resource->getType() == 1)
+			_driver->sync(resource);
+
+	} else {
+		resource->_next = _chainInactive;
+		_chainInactive = resource;
+	}
+}
+
+void AudioMaster2ResourceManager::stopChain() {
+	Common::StackLock lock(*_mutex);
+
+	SoundResource *cur = _chainPlaying;
+	while (cur) {
+		cur->setPlayStatus(false);
+		cur = cur->_next;
+	}
+
+	_driver->stopChannels();
+}
+
+AudioMaster2IFFLoader::~AudioMaster2IFFLoader() {
+	initResource();
+}
+
+bool AudioMaster2IFFLoader::loadChunk(Common::IFFChunk &chunk) {
+	if (_formType == ID_INST) {
+		if (_curIns == 0)
+			_curIns = new SoundResourceINST(_res);
+
+		switch (chunk._type) {
+		case ID_NAME:
+			_curIns->loadName(chunk._stream, chunk._size);
+			break;
+		case ID_SAMP:
+			_curIns->loadSamples(chunk._stream, chunk._size);
+			break;
+		case ID_VLUM:
+			_curIns->loadVolumeData(chunk._stream, chunk._size);
+			break;
+		case ID_PTCH:
+			_curIns->loadPitchData(chunk._stream, chunk._size);
+			break;
+		default:
+			break;
+		}
+
+	} else if (_formType == ID_SMUS) {
+		if (_curSong == 0)
+			_curSong = new SoundResourceSMUS(_res);
+
+		switch (chunk._type) {
+		case ID_SHDR:
+			_curSong->loadHeader(chunk._stream, chunk._size);
+			break;
+		case ID_NAME:
+			_curSong->loadName(chunk._stream, chunk._size);
+			break;
+		case ID_TRAK:
+			_curSong->loadTrack(chunk._stream, chunk._size);
+			break;
+		case ID_INS1:
+			_curSong->loadInstrument(chunk._stream, chunk._size);
+			break;
+		default:
+			break;
+		}
+
+	} else if (_formType == ID_8SVX) {
+		if (_curSfx == 0)
+			_curSfx = new SoundResource8SVX(_res);
+
+		switch (chunk._type) {
+		case ID_VHDR:
+			_curSfx->loadHeader(chunk._stream, chunk._size);
+			break;
+		case ID_NAME:
+			_curSfx->loadName(chunk._stream, chunk._size);
+			break;
+		case ID_BODY:
+			_curSfx->loadData(chunk._stream, chunk._size);
+			break;
+		case ID_ANNO:
+			break;
+		default:
+			break;
+		}
+	}
+
+	return false;
+}
+
+void AudioMaster2IFFLoader::initResource() {
+	if (_curIns) {
+		_res->initResource(_curIns);
+		_curIns = 0;
+	} else if (_curSong) {
+		_res->initResource(_curSong);
+		_curSong = 0;
+	} else if (_curSfx) {
+		_res->initResource(_curSfx);
+		_curSfx = 0;
+	}
+}
+
+AudioMaster2Internal *AudioMaster2Internal::_refInstance = 0;
+int AudioMaster2Internal::_refCount = 0;
+
+AudioMaster2Internal::AudioMaster2Internal(Audio::Mixer *mixer) : Paula(true, mixer->getOutputRate(), mixer->getOutputRate() / 50), _mixer(mixer), _res(0), _ready(false) {
+	_channels[0] = _channels[1] = _channels[2] = _channels[3] = 0;
+}
+
+AudioMaster2Internal::~AudioMaster2Internal() {
+	Common::StackLock lock(_mutex);
+
+	stopPaula();
+
+	_mixer->stopHandle(_soundHandle);
+
+	delete _res;
+	delete _io;
+}
+
+AudioMaster2Internal *AudioMaster2Internal::open(Audio::Mixer *mixer) {
+	_refCount++;
+
+	if (_refCount == 1 && _refInstance == 0)
+		_refInstance = new AudioMaster2Internal(mixer);
+	else if (_refCount < 2 || _refInstance == 0)
+		error("AudioMaster2Internal::open(): Internal instance management failure");
+
+	return _refInstance;
+}
+
+void AudioMaster2Internal::close() {
+	if (!_refCount)
+		return;
+
+	_refCount--;
+
+	if (!_refCount) {
+		delete _refInstance;
+		_refInstance = 0;
+	}
+}
+
+bool AudioMaster2Internal::init() {
+	if (_ready)
+		return true;
+
+	_io = new AudioMaster2IOManager();
+	_res = new AudioMaster2ResourceManager(this, &_mutex);
+
+	_mixer->playStream(Audio::Mixer::kPlainSoundType,
+		&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+
+	startPaula();
+
+	_ready = true;
+
+	return true;
+}
+
+bool AudioMaster2Internal::loadRessourceFile(Common::SeekableReadStream *data) {
+	if (!_ready || !data)
+		return false;
+
+	_res->loadResourceFile(data);
+
+	return true;
+}
+
+bool AudioMaster2Internal::startSound(const Common::String &name) {
+	return _ready ? (_res->getResource(name, SoundResource::kRestart) != 0) : false;
+}
+
+bool AudioMaster2Internal::stopSound(const Common::String &name) {
+	return _ready ? (_res->getResource(name, SoundResource::kIdle) != 0) : false;
+}
+
+void AudioMaster2Internal::flushResource(const Common::String &name) {
+	if (_ready)
+		_res->releaseResource(name);
+}
+
+void AudioMaster2Internal::flushAllResources() {
+	if (_ready)
+		_res->flush();
+}
+
+void AudioMaster2Internal::interrupt() {
+	if (!_ready)
+		return;
+
+	_io->_sync += _io->_tempo;
+	_res->interrupt(_io);
+	_io->deployChannels(_channels);
+	updateDevice();
+}
+
+void AudioMaster2Internal::sync(SoundResource *res) {
+	if (!_ready || !res)
+		return;
+
+	if (res->getType() != 1)
+		return;
+
+	SoundResourceSMUS *smus = static_cast<SoundResourceSMUS*>(res);
+
+	Common::StackLock lock(_mutex);
+	_io->_tempo = smus->getTempo();
+	smus->setSync(_io->_sync);
+}
+
+void AudioMaster2Internal::stopChannels() {
+	if (!_ready)
+		return;
+
+	Common::StackLock lock(_mutex);
+
+	for (uint8 i = 0; i < 4; ++i) {
+		if (_channels[i]) {
+			_channels[i]->_endTick = 0;
+			disableChannel(i);
+		}
+	}
+
+	_io->clearChain();
+}
+
+void AudioMaster2Internal::updateDevice() {
+	for (uint8 i = 3; i < 4; --i) {
+		AudioMaster2IOManager::IOUnit *unit = _channels[i];
+		if (!unit)
+			continue;
+
+		if (_io->_sync > unit->_endTick) {
+			_channels[i] = 0;
+			unit->_flags &= ~2;
+			disableChannel(i);
+			continue;
+		}
+
+		bool next = false;
+		
+		if (unit->_transposeData) {
+			unit->_period += unit->_transposePara;
+			const uint8 *data = unit->_transposeData;
+			
+			if (unit->_transposeCounter-- <= 1) {
+				for (bool loop = true; loop; ) {
+					uint8 para = *data++;
+
+					if (para == 0xFF) {
+						para = *data++;
+
+						if (para == 0) {
+							unit->_flags &= ~2;
+							disableChannel(i);
+							loop = false;
+							next = true;
+							continue;
+
+						} else if (para == 1) {
+							unit->_transposeData = 0;
+							loop = false;
+
+						} else {
+							unit->_period = READ_BE_UINT16(data);
+							data += 2;
+						}
+
+					} else if (para == 0xFE) {
+						para = *data++;
+						data -= ((para + 1) << 1);
+
+					} else {
+						unit->_transposeCounter = para;
+						unit->_transposePara = *data++;
+						unit->_transposeData = data;
+						loop = false;
+					}
+				}
+			}
+		}
+
+		if (next)
+			continue;
+
+		next = false;
+
+		if (unit->_levelAdjustData) {
+			unit->_outputVolume += unit->_levelAdjustPara;
+			const uint8 *data = unit->_levelAdjustData;
+
+			if (unit->_levelAdjustCounter-- <= 1) {
+				for (bool loop = true; loop; ) {
+					uint8 para = *data++;
+					if (para == 0xFF) {
+						para = *data++;
+
+						if (para == 0) {
+							unit->_flags &= ~2;
+							disableChannel(i);
+							loop = false;
+							next = true;
+							continue;
+
+						} else {
+							unit->_levelAdjustData = 0;
+							loop = false;
+						}
+
+					} else if (para == 0xFE) {
+						para = *data++;
+						data -= ((para + 1) << 1);
+
+					} else {
+						uint16 para2 = *data++;
+
+						if (para2 & 0x80) {
+							para2 = unit->_outputVolume + ((para2 - 0xC0) << 8);
+
+						} else {
+							para2 = (unit->_volumeSetting * para2) >> 6;
+							if (para2 > 0x4000)
+								para2 = 0x4000;							
+						}
+
+						if (!para) {
+							unit->_outputVolume = para2;
+							continue;
+						}
+
+						unit->_levelAdjustCounter = para;
+
+						if (para == 1) {
+							unit->_outputVolume = para2;
+							unit->_levelAdjustPara = 0;
+						} else {
+							int16 va = para2 - unit->_outputVolume;
+							va /= para;
+							unit->_levelAdjustPara =  va / para;
+						}
+
+						unit->_levelAdjustData = data;
+						loop = false;
+					}
+				}
+			}
+		}
+
+		if (next)
+			continue;
+
+		if (unit->_flags & 4) {
+			unit->_flags &= ~4;
+
+			setChannelPeriod(i, unit->_period);
+			setChannelVolume(i, unit->_outputVolume >> 8);
+
+			if (unit->_lenOnce) {
+				setChannelData(i, unit->_sampleData, unit->_sampleDataRepeat, unit->_lenOnce, unit->_lenRepeat);
+			} else if (unit->_lenRepeat) {
+				setChannelSampleStart(i, unit->_sampleDataRepeat);
+				setChannelSampleLen(i, unit->_lenRepeat);
+			}
+	
+		} else if (unit->_transposeData || unit->_levelAdjustData) {
+			setChannelPeriod(i, unit->_period);
+			setChannelVolume(i, unit->_outputVolume >> 8);
+		}
+	}
+}
+
+AudioMaster2::AudioMaster2(Audio::Mixer *mixer) {
+	_am2i = AudioMaster2Internal::open(mixer);
+}
+
+AudioMaster2::~AudioMaster2() {
+	AudioMaster2Internal::close();
+	_am2i = 0;
+}
+
+bool AudioMaster2::init() {
+	return _am2i->init();
+}
+
+bool AudioMaster2::loadRessourceFile(Common::SeekableReadStream *data) {
+	return _am2i->loadRessourceFile(data);
+}
+
+bool AudioMaster2::startSound(const Common::String &name) {
+	return _am2i->startSound(name);
+}
+
+bool AudioMaster2::stopSound(const Common::String &name) {
+	return _am2i->stopSound(name);
+}
+
+void AudioMaster2::flushResource(const Common::String &name) {
+	_am2i->flushResource(name);
+}
+
+void AudioMaster2::flushAllResources() {
+	_am2i->flushAllResources();
+}
+
+} // End of namespace Kyra
diff --git a/engines/kyra/sound/drivers/audiomaster2.h b/engines/kyra/sound/drivers/audiomaster2.h
new file mode 100644
index 0000000..d20048c
--- /dev/null
+++ b/engines/kyra/sound/drivers/audiomaster2.h
@@ -0,0 +1,78 @@
+/* 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.
+ *
+ * LGPL License
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef KYRA_SOUND_AUDIOMASTER2_H
+#define KYRA_SOUND_AUDIOMASTER2_H
+
+namespace Audio {
+	class Mixer;
+}
+
+namespace Common {
+	class SeekableReadStream;
+	class String;
+}
+
+namespace Kyra {
+
+class AudioMaster2Internal;
+
+class AudioMaster2 {
+public:
+	AudioMaster2(Audio::Mixer *mixer);
+	~AudioMaster2();
+
+	bool init();
+	bool loadRessourceFile(Common::SeekableReadStream *data);
+
+	bool startSound(const Common::String &name);
+	bool stopSound(const Common::String &name);
+
+	void flushResource(const Common::String &name);
+	void flushAllResources();
+
+	void setMusicVolume(int volume) {}
+	void setSoundEffectVolume(int volume) {}
+
+private:
+	AudioMaster2Internal *_am2i;
+};
+
+} // End of namespace Kyra
+
+#endif
diff --git a/engines/kyra/sound/sound.h b/engines/kyra/sound/sound.h
index 3f4216c..ab0e6a1 100644
--- a/engines/kyra/sound/sound.h
+++ b/engines/kyra/sound/sound.h
@@ -73,6 +73,15 @@ struct SoundResourceInfo_TownsEoB {
 	int pcmVolume;
 };
 
+
+struct SoundResourceInfo_AmigaEoB {
+	SoundResourceInfo_AmigaEoB(const char *const *files, int numFiles, const char *const *sounds, int numSounds) : fileList(files), fileListSize(numFiles), soundList(sounds), soundListSize(numSounds) {}
+	const char *const *fileList;
+	uint fileListSize;
+	const char *const *soundList;
+	uint soundListSize;
+};
+
 /**
  * Analog audio output device API for Kyrandia games.
  * It contains functionality to play music tracks,
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
new file mode 100644
index 0000000..781ec46
--- /dev/null
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -0,0 +1,311 @@
+/* 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 "kyra/sound/sound_intern.h"
+#include "kyra/resource/resource.h"
+#include "kyra/sound/drivers/audiomaster2.h"
+
+#include "common/memstream.h"
+
+namespace Kyra {
+
+SoundAmiga_EoB::SoundAmiga_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _vm(vm), _driver(0), _currentResourceSet(0), _ready(false) {
+	_fileBuffer = new uint8[64000];
+	_version2 = _vm->game() == GI_EOB2;
+	memset(_resInfo, 0, sizeof(_resInfo));
+}
+
+SoundAmiga_EoB::~SoundAmiga_EoB() {
+	delete _driver;
+	delete[] _fileBuffer;
+	for (int i = 0; i < 3; i++)
+		initAudioResourceInfo(i, 0);
+}
+
+Sound::kType SoundAmiga_EoB::getMusicType() const {
+	return kAmiga;
+}
+
+bool SoundAmiga_EoB::init() {
+	_driver = new AudioMaster2(_mixer);
+	if (!_driver->init())
+		return false;
+
+	_ready = true;
+	return true;
+}
+
+void SoundAmiga_EoB::initAudioResourceInfo(int set, void *info) {
+	delete _resInfo[set];
+	_resInfo[set] = info ? new SoundResourceInfo_AmigaEoB(*(SoundResourceInfo_AmigaEoB*)info) : 0;
+}
+
+void SoundAmiga_EoB::selectAudioResourceSet(int set) {
+	_driver->flushAllResources();
+	if (!_resInfo[set])
+		return;
+
+	for (uint i = 0; i < _resInfo[set]->fileListSize; ++i)
+		loadSoundFile(_resInfo[set]->fileList[i]);
+
+	_currentResourceSet = set;
+}
+
+bool SoundAmiga_EoB::hasSoundFile(uint file) const {
+	return false;
+}
+
+void SoundAmiga_EoB::loadSoundFile(uint file) {
+	/*
+	_sound->loadSoundFile("INTRO1.CPS");
+	_sound->loadSoundFile("INTRO2.CPS");
+	_sound->loadSoundFile("INTRO4.CPS");
+	_sound->loadSoundFile("INTRO5.CPS");
+	_sound->loadSoundFile("NEWINTRO1.CPS");
+	_sound->loadSoundFile("CHARGEN1.CPS");
+
+	_sound->loadSoundFile("SFX1.CPS");
+	_sound->loadSoundFile("SFX2.CPS");
+	_sound->loadSoundFile("SFX3.CPS");
+	_sound->loadSoundFile("SFX4.CPS");
+
+	_sound->loadSoundFile("HUM1.CPS");
+
+	_sound->loadSoundFile("SPIDERMOV1.CPS");
+	_sound->loadSoundFile("MOVE1.CPS");
+	_sound->loadSoundFile("MOVE21.CPS");
+	_sound->loadSoundFile("MOVE31.CPS");
+	_sound->loadSoundFile("BEASTATK1.CPS");
+	_sound->loadSoundFile("BLADE1.CPS");
+	_sound->loadSoundFile("MANTISMOV1.CPS");
+	_sound->loadSoundFile("FLAYERATK1.CPS");
+	_sound->loadSoundFile("LEECHMOV1.CPS");
+	_sound->loadSoundFile("SLOSHSUCK1.CPS");
+	_sound->loadSoundFile("SCREAM1.CPS");
+	_sound->loadSoundFile("RUSTATK1.CPS");
+	_sound->loadSoundFile("HOUNDATK1.CPS");
+	_sound->loadSoundFile("KUOTOAMOV1.CPS");
+
+	_sound->loadSoundFile("FINALE2.CPS");
+	_sound->loadSoundFile("FINALE1.CPS");
+	_sound->loadSoundFile("FINALE.CPS");
+
+	for (int i = 1; i < 12; ++i) {
+		char n[13];
+		sprintf(n, "LEVELSAM%d.CPS", i);
+		_sound->loadSoundFile(n);
+	}*/
+}
+
+void SoundAmiga_EoB::loadSoundFile(Common::String file) {
+	if (!_ready)
+		return;
+
+	Common::SeekableReadStream *in = _vm->resource()->createReadStream(file);
+	if (!in)
+		return;
+
+	uint16 readSize = in->readUint16LE() - 10;
+	uint8 cmp = in->readByte();
+	in->seek(1, SEEK_CUR);
+	uint32 outSize = in->readUint32LE();
+	in->seek(2, SEEK_CUR);
+
+	if (in->read(_fileBuffer, readSize) != readSize)
+		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.c_str());
+	delete in;
+
+	uint8 *buf = new uint8[outSize];
+
+	if (cmp == 0) {
+		assert(readSize == outSize);
+		memcpy(buf, _fileBuffer, outSize);
+	} else if (cmp == 3) {			
+		Screen::decodeFrame3(_fileBuffer, buf, outSize);
+	} else if (cmp == 4) {
+		Screen::decodeFrame4(_fileBuffer, buf, outSize);
+	} else {
+		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.c_str());
+	}
+
+	Common::MemoryReadStream soundFile(buf, outSize);
+	if (!_driver->loadRessourceFile(&soundFile))
+		error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.c_str());
+
+	delete[] buf;
+}
+
+void SoundAmiga_EoB::playTrack(uint8 track) {
+	_driver->startSound("newintro1.smus");
+	//_driver->startSound("hum1.sam");
+	//_driver->startSound("hum");
+	//_driver->startSound("playswing");
+	//_driver->startSound("door");
+	//_driver->startSound("death");
+	//_driver->startSound("teleport");
+	//_driver->startSound("scream");
+	//_driver->startSound("magica");
+	//_driver->startSound("magicb");
+
+	//_driver->startSound("chargen1.smus");
+	//_driver->startSound("finale.smus");
+}
+
+void SoundAmiga_EoB::haltTrack() {
+
+}
+
+void SoundAmiga_EoB::playSoundEffect(uint8 track, uint8 volume) {
+	if (!_resInfo[_currentResourceSet]->soundList || track >= 120 || !_sfxEnabled)
+		return;
+
+	_driver->startSound(_resInfo[_currentResourceSet]->soundList[track]);
+
+	static const char *const kEoB1SoundsAmiga[120] = {
+		0,
+		"button",
+		"L1M1A",
+		"door",
+		"door",
+		"slam",
+		"button",
+		"button",
+		"transmute",
+		"eat",
+		"magica",
+		"throw",
+		"plate",
+		"passage",
+		"unlock",
+		"teleport",
+		"undead",
+		"pit",
+		"itemland",
+		0,
+		0,
+		"playhit",
+		"death",
+		"text",
+		"electric",
+		"dart",
+		"dart",
+		"unlock",
+		"bonus",
+		"bump",
+		0,
+		"electric",
+		"playswing",
+		"hum",
+		"panel",
+		"explode",
+		"L10M2M",
+		"L10M2A",
+		"L4M1M",
+		"beastatk",
+		"L9M2M",
+		"L8M1A",
+		"L8M1M",
+		"L7M1A",
+		"L7M1M",
+		"L5M1A",
+		"L5M1M",
+		"flindatk",
+		"L3M2M",
+		"L4M1A",
+		"L8M2M",
+		"houndatk",
+		"scream",
+		"L6M1M",
+		"L3M1A",
+		"L3M1M",
+		"sloshsuck",
+		"L1M2M",
+		"flayeratk",
+		0,
+		"rustatk",
+		"L9M1M",
+		"L10M1A",
+		"L10M1M",
+		"blade",
+		"L7M2M",
+		"blade",
+		"L2M2M",
+		"L12M2A",
+		"L12M2M",
+		0,
+		"L11M1M",
+		"L11M1A",
+		"L2M1A",
+		"L2M1M",
+		"L1M1M",
+		"button",
+		0,
+		"drop",
+		"text",
+		"magicb",
+		"lock",
+		0,
+		0,
+		0,
+		"Missile",
+		0,
+		"burnhands",
+		"electric",
+		"fireball",
+		0,
+		"magica",
+		"magica",
+		"magica",
+		"magicb",
+		"magicb",
+		"acid",
+		"magicb",
+		"fireball",
+		"acid",
+		"magica",
+		"magicb",
+		"magicb",
+		"undead",
+		"magica",
+		"magica",
+		"magica",
+		"magicb",
+		"cause",
+		"magicb",
+		"magicb",
+		"magica",
+		"magicb",
+		"magica",
+		"magica",
+		"magica",
+		"magica",
+		"cause",
+		0,
+		"door"
+	};
+}
+
+void SoundAmiga_EoB::beginFadeOut() {
+
+}
+
+} // End of namespace Kyra
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index 77436d0..fccdc03 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -402,6 +402,37 @@ private:
 	TownsAudioInterface *_intf;
 };
 
+class AudioMaster2;
+class SoundAmiga_EoB: public Sound {
+public:
+	SoundAmiga_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer);
+	virtual ~SoundAmiga_EoB();
+
+	kType getMusicType() const;
+
+	bool init();
+	void initAudioResourceInfo(int set, void *info);
+	void selectAudioResourceSet(int set);
+	bool hasSoundFile(uint file) const;
+	void loadSoundFile(uint file);
+	void loadSoundFile(Common::String file);
+	void playTrack(uint8 track);
+	void haltTrack();
+	void playSoundEffect(uint8 track, uint8 volume = 0xFF);
+	void beginFadeOut();
+
+private:
+	uint8 *_fileBuffer;
+
+	KyraEngine_v1 *_vm;
+	AudioMaster2 *_driver;
+	SoundResourceInfo_AmigaEoB *_resInfo[3];
+	int _currentResourceSet;
+
+	bool _version2;
+	bool _ready;
+};
+
 } // End of namespace Kyra
 
 #endif


Commit: 890c4c5f41e74938640f4bc8ddb843ac3ca9928d
    https://github.com/scummvm/scummvm/commit/890c4c5f41e74938640f4bc8ddb843ac3ca9928d
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:20+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix start up

First efforts to get this running. The intro is shown with severe palette glitches. The Main Menu does not show, thanks to the lack of font drawing.

- implement endian aware stream wrapper for amiga files
- implement sound file handling
- implement some Amiga palette handling
- etc

Changed paths:
    engines/kyra/engine/chargen.cpp
    engines/kyra/engine/darkmoon.cpp
    engines/kyra/engine/darkmoon.h
    engines/kyra/engine/eob.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/items_eob.cpp
    engines/kyra/graphics/screen.cpp
    engines/kyra/graphics/screen.h
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/graphics/screen_eob.h
    engines/kyra/graphics/screen_lok.cpp
    engines/kyra/graphics/screen_lok.h
    engines/kyra/resource/resource.cpp
    engines/kyra/resource/resource.h
    engines/kyra/resource/staticres_eob.cpp
    engines/kyra/sequence/sequences_darkmoon.cpp
    engines/kyra/sequence/sequences_eob.cpp
    engines/kyra/sound/drivers/audiomaster2.cpp
    engines/kyra/sound/sound.h
    engines/kyra/sound/sound_amiga_eob.cpp
    engines/kyra/sound/sound_intern.h
    engines/kyra/sound/sound_towns_darkmoon.cpp


diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
index 7bea21e..5032e86 100644
--- a/engines/kyra/engine/chargen.cpp
+++ b/engines/kyra/engine/chargen.cpp
@@ -1972,6 +1972,7 @@ void TransferPartyWiz::giveKhelbensCoin() {
 // Start functions
 
 bool EoBCoreEngine::startCharacterGeneration() {
+	_sound->selectAudioResourceSet(_flags.platform == Common::kPlatformAmiga ? kMusicIntro : kMusicIngame);
 	return CharacterGenerator(this, _screen).start(_characters, &_faceShapes);
 }
 
diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index 9731f00..4978164 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -70,15 +70,21 @@ Common::Error DarkMoonEngine::init() {
 }
 
 void DarkMoonEngine::startupNew() {
+	_sound->selectAudioResourceSet(kMusicIngame);
 	_currentLevel = 4;
 	_currentSub = 0;
 	loadLevel(4, 0);
 	_currentBlock = 171;
 	_currentDirection = 2;
 	setHandItem(0);
+
 	EoBCoreEngine::startupNew();
 }
 
+void DarkMoonEngine::startupLoad() {
+	_sound->selectAudioResourceSet(kMusicIngame);
+}
+
 void DarkMoonEngine::drawNpcScene(int npcIndex) {
 	const uint8 *shpDef = &_npcShpData[npcIndex << 3];
 	for (int i = npcIndex; i != 255; i = shpDef[7]) {
diff --git a/engines/kyra/engine/darkmoon.h b/engines/kyra/engine/darkmoon.h
index 3577bdb..d1012db 100644
--- a/engines/kyra/engine/darkmoon.h
+++ b/engines/kyra/engine/darkmoon.h
@@ -66,7 +66,7 @@ private:
 
 	// Main loop
 	void startupNew();
-	void startupLoad() {}
+	void startupLoad();
 
 	// Intro/Outro
 	void seq_playIntro();
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index 18ed9c6..b1cf500 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -76,6 +76,8 @@ Common::Error EoBEngine::init() {
 }
 
 void EoBEngine::startupNew() {
+	_sound->selectAudioResourceSet(kMusicIngame);
+	_sound->loadSoundFile(0);
 	_currentLevel = 1;
 	_currentSub = 0;
 	loadLevel(1, 0);
@@ -87,7 +89,8 @@ void EoBEngine::startupNew() {
 }
 
 void EoBEngine::startupLoad() {
-	_sound->loadSoundFile("ADLIB");
+	_sound->selectAudioResourceSet(kMusicIngame);
+	_sound->loadSoundFile(0);
 }
 
 void EoBEngine::drawNpcScene(int npcIndex) {
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 0e3e130..e6e01ff 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -214,6 +214,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
 	_menuStringsRest4 = _menuStringsDefeat = _menuStringsTransfer = _menuStringsSpec = 0;
 	_menuStringsSpellNo = _menuYesNoStrings = _2431Strings = _katakanaLines = _katakanaSelectStrings = 0;
 	_errorSlotEmptyString = _errorSlotNoNameString = _menuOkString = 0;
+	_levelSoundFiles1 = _levelSoundFiles2 = 0;
 	_spellLevelsMage = _spellLevelsCleric = _numSpellsCleric = _numSpellsWisAdj = _numSpellsPal = _numSpellsMage = 0;
 	_mnNumWord = _numSpells = _mageSpellListSize = _spellLevelsMageSize = _spellLevelsClericSize = 0;
 	_inventorySlotsX = _slotValidationFlags = _encodeMonsterShpTable = 0;
@@ -435,7 +436,10 @@ Common::Error EoBCoreEngine::init() {
 	assert(_debugger);
 
 	if (_flags.platform == Common::kPlatformAmiga) {
-
+		if (_res->exists("EOBF6.FONT"))
+			_screen->loadFont(Screen::FID_6_FNT, "EOBF6.FONT");
+		if (_res->exists("EOBF8.FONT"))
+			_screen->loadFont(Screen::FID_8_FNT, "EOBF8.FONT");
 	} else {
 		_screen->loadFont(Screen::FID_6_FNT, "FONT6.FNT");
 		_screen->loadFont(Screen::FID_8_FNT, "FONT8.FNT");
@@ -555,7 +559,6 @@ Common::Error EoBCoreEngine::go() {
 		action = 0;
 
 		if (_gameToLoad != -1) {
-			_sound->selectAudioResourceSet(kMusicIngame);
 			if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
 				error("Couldn't load game slot %d on startup", _gameToLoad);
 			startupLoad();
@@ -565,8 +568,6 @@ Common::Error EoBCoreEngine::go() {
 			action = mainMenu();
 		}
 
-		_sound->selectAudioResourceSet(kMusicIngame);
-
 		if (action == -1) {
 			// load game
 			repeatLoop = _gui->runLoadMenu(72, 14);
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index c56a41b..38bdae0 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -1175,6 +1175,9 @@ protected:
 	void snd_stopSound();
 	void snd_fadeOut();
 
+	const char *const *_levelSoundFiles1;
+	const char *const *_levelSoundFiles2;
+
 	// keymap
 	static const char *const kKeymapName;
 };
diff --git a/engines/kyra/engine/items_eob.cpp b/engines/kyra/engine/items_eob.cpp
index 54d3d50..4d11d0d 100644
--- a/engines/kyra/engine/items_eob.cpp
+++ b/engines/kyra/engine/items_eob.cpp
@@ -29,9 +29,9 @@
 namespace Kyra {
 
 void EoBCoreEngine::loadItemDefs() {
-	Common::SeekableReadStream *s = _res->createReadStream("item.dat");
+	Common::SeekableReadStreamEndian *s = _res->createEndianAwareReadStream("item.dat");
 	memset(_items, 0, sizeof(EoBItem) * 600);
-	_numItems = s->readUint16LE();
+	_numItems = s->readUint16();
 
 	for (int i = 0; i < 600; i++)
 		_items[i].block = -1;
@@ -43,29 +43,29 @@ void EoBCoreEngine::loadItemDefs() {
 		_items[i].icon = s->readSByte();
 		_items[i].type = s->readSByte();
 		_items[i].pos = s->readSByte();
-		_items[i].block = s->readSint16LE();
-		_items[i].next = s->readSint16LE();
-		_items[i].prev = s->readSint16LE();
+		_items[i].block = s->readSint16();
+		_items[i].next = s->readSint16();
+		_items[i].prev = s->readSint16();
 		_items[i].level = s->readSByte();
 		_items[i].value = s->readSByte();
 	}
 
-	_numItemNames = s->readUint16LE();
+	_numItemNames = s->readUint16();
 	for (int i = 0; i < _numItemNames; i++)
 		s->read(_itemNames[i], 35);
 
 	delete s;
 
-	s = _res->createReadStream("itemtype.dat");
-	uint16 numTypes = s->readUint16LE();
+	s = _res->createEndianAwareReadStream("itemtype.dat");
+	uint16 numTypes = s->readUint16();
 
 	delete[] _itemTypes;
 	_itemTypes = new EoBItemType[65];
 	memset(_itemTypes, 0, sizeof(EoBItemType) * 65);
 
 	for (int i = 0; i < numTypes; i++) {
-		_itemTypes[i].invFlags = s->readUint16LE();
-		_itemTypes[i].handFlags = s->readUint16LE();
+		_itemTypes[i].invFlags = s->readUint16();
+		_itemTypes[i].handFlags = s->readUint16();
 		_itemTypes[i].armorClass = s->readSByte();
 		_itemTypes[i].allowedClasses = s->readSByte();
 		_itemTypes[i].requiredHands = s->readSByte();
@@ -76,7 +76,7 @@ void EoBCoreEngine::loadItemDefs() {
 		_itemTypes[i].dmgNumPipsL = s->readSByte();
 		_itemTypes[i].dmgIncL = s->readSByte();
 		_itemTypes[i].unk1 = s->readByte();
-		_itemTypes[i].extraProperties = s->readUint16LE();
+		_itemTypes[i].extraProperties = s->readUint16();
 	}
 
 	delete s;
diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp
index 4ceb627..6af970e 100644
--- a/engines/kyra/graphics/screen.cpp
+++ b/engines/kyra/graphics/screen.cpp
@@ -3265,13 +3265,6 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette
 		error("Unhandled bitmap compression %d", compType);
 	}
 
-	if (_isAmiga) {
-		if (!scumm_stricmp(ext, "MSC"))
-			Screen::convertAmigaMsc(dstData);
-		else
-			Screen::convertAmigaGfx(dstData, 320, 200);
-	}
-
 	if (skip)
 		srcData -= 4;
 
@@ -3732,7 +3725,7 @@ int AMIGAFont::getCharWidth(uint16 c) const {
 }
 
 void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
-	if (c >= 255)
+	//if (c >= 255)
 		return;
 
 	if (_chars[c].yOffset == 255)
diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h
index 68f1927..8ed17a1 100644
--- a/engines/kyra/graphics/screen.h
+++ b/engines/kyra/graphics/screen.h
@@ -532,7 +532,7 @@ public:
 	void rectClip(int &x, int &y, int w, int h);
 
 	// misc
-	void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip=false);
+	virtual void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip=false);
 
 	virtual bool loadPalette(const char *filename, Palette &pal);
 	bool loadPaletteTable(const char *filename, int firstPalette);
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index 3945c03..bf5f7af 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -219,6 +219,18 @@ void Screen_EoB::loadShapeSetBitmap(const char *file, int tempPage, int destPage
 	_curPage = 2;
 }
 
+void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool) {
+	Screen::loadBitmap(filename, tempPage, dstPage, pal);
+
+	if (_isAmiga) {
+		// Yay, this is where EOB1 Amiga hides the palette data
+		loadPalette(_pagePtrs[3] + 40000, *_palettes[0], 64);
+		_palettes[0]->fill(0, 1, 0);
+
+		Screen::convertAmigaGfx(getPagePtr(dstPage), 320, 200);
+	}
+}
+
 void Screen_EoB::loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage) {
 	const char *filePattern = _vm->gameFlags().platform == Common::kPlatformFMTowns ? "%s.SHP" : ((_vm->game() == GI_EOB1 && (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA)) ? "%s.EGA" : "%s.CPS");
 	Common::String tmp = Common::String::format(filePattern, file);
diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h
index 401a229..60290df 100644
--- a/engines/kyra/graphics/screen_eob.h
+++ b/engines/kyra/graphics/screen_eob.h
@@ -47,6 +47,7 @@ public:
 
 	void printShadedText(const char *string, int x, int y, int col1, int col2);
 
+	virtual void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip = false);
 	void loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage);
 	void loadShapeSetBitmap(const char *file, int tempPage, int destPage);
 
diff --git a/engines/kyra/graphics/screen_lok.cpp b/engines/kyra/graphics/screen_lok.cpp
index 114382b..ea619a6 100644
--- a/engines/kyra/graphics/screen_lok.cpp
+++ b/engines/kyra/graphics/screen_lok.cpp
@@ -70,6 +70,19 @@ bool Screen_LoK::init() {
 	return true;
 }
 
+void Screen_LoK::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip) {
+	const char *ext = filename + strlen(filename) - 3;
+
+	Screen::loadBitmap(filename, tempPage, dstPage, pal, skip);
+
+	if (_isAmiga) {
+		if (!scumm_stricmp(ext, "MSC"))
+			Screen::convertAmigaMsc(getPagePtr(dstPage));
+		else
+			Screen::convertAmigaGfx(getPagePtr(dstPage), 320, 200);
+	}
+}
+
 void Screen_LoK::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) {
 	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
 		return;
diff --git a/engines/kyra/graphics/screen_lok.h b/engines/kyra/graphics/screen_lok.h
index 3a4ebfd..34d0e2f 100644
--- a/engines/kyra/graphics/screen_lok.h
+++ b/engines/kyra/graphics/screen_lok.h
@@ -36,6 +36,8 @@ public:
 
 	bool init();
 
+	virtual void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip = false);
+
 	int getRectSize(int w, int h);
 
 	void setTextColorMap(const uint8 *cmap);
diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index e13e644..19603a1 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -28,6 +28,28 @@
 
 namespace Kyra {
 
+class EndianAwareStreamWrapper : public Common::SeekableReadStreamEndian {
+public:
+	EndianAwareStreamWrapper(Common::SeekableReadStream *stream, bool bigEndian, bool disposeAfterUse = true) : Common::SeekableReadStreamEndian(bigEndian), _stream(stream), _dispose(disposeAfterUse) {}
+	~EndianAwareStreamWrapper() { if (_dispose) delete _stream; }
+
+	// Common::Stream interface
+	bool err() const { return _stream->err(); }
+
+	// Common::ReadStream interface
+	bool eos() const { return _stream->eos(); }
+	uint32 read(void *dataPtr, uint32 dataSize) { return _stream->read(dataPtr, dataSize); }
+
+	// Common::SeekableReadStream interface
+	int32 pos() const { return _stream->pos(); }
+	int32 size() const { return _stream->size(); }
+	bool seek(int32 offset, int whence = SEEK_SET) { return _stream->seek(offset, whence); }
+	
+private:
+	Common::SeekableReadStream *_stream;
+	bool _dispose;
+};
+
 Resource::Resource(KyraEngine_v1 *vm) : _archiveCache(), _files(), _archiveFiles(), _protectedFiles(), _loaders(), _vm(vm) {
 	initializeLoaders();
 
@@ -316,6 +338,10 @@ Common::SeekableReadStream *Resource::createReadStream(const Common::String &fil
 	return _files.createReadStreamForMember(file);
 }
 
+Common::SeekableReadStreamEndian *Resource::createEndianAwareReadStream(const Common::String &file) {
+	return new EndianAwareStreamWrapper(_files.createReadStreamForMember(file), _vm->gameFlags().platform == Common::kPlatformAmiga);
+}
+
 Common::Archive *Resource::loadArchive(const Common::String &name, Common::ArchiveMemberPtr member) {
 	ArchiveMap::iterator cachedArchive = _archiveCache.find(name);
 	if (cachedArchive != _archiveCache.end())
diff --git a/engines/kyra/resource/resource.h b/engines/kyra/resource/resource.h
index a1ff902..02415cf 100644
--- a/engines/kyra/resource/resource.h
+++ b/engines/kyra/resource/resource.h
@@ -74,6 +74,7 @@ public:
 	uint32 getFileSize(const char *file);
 	uint8 *fileData(const char *file, uint32 *size);
 	Common::SeekableReadStream *createReadStream(const Common::String &file);
+	Common::SeekableReadStreamEndian *createEndianAwareReadStream(const Common::String &file);
 
 	bool loadFileToBuf(const char *file, void *buf, uint32 maxSize);
 protected:
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index 23a5203..eaa9112 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -269,7 +269,7 @@ const uint8 EoBCoreEngine::_clock2Timers[] = {
 const uint8 EoBCoreEngine::_numClock2Timers = ARRAYSIZE(EoBCoreEngine::_clock2Timers);
 
 void EoBCoreEngine::initStaticResource() {
-	int temp;
+	int temp, temp2;
 	_chargenStatStrings = _staticres->loadStrings(kEoBBaseChargenStatStrings, temp);
 	_chargenRaceSexStrings = _staticres->loadStrings(kEoBBaseChargenRaceSexStrings, temp);
 	_chargenClassStrings = _staticres->loadStrings(kEoBBaseChargenClassStrings, temp);
@@ -461,12 +461,51 @@ void EoBCoreEngine::initStaticResource() {
 	_coneOfColdDest4 = (const int8 *)_staticres->loadRawData(kEoBBaseConeOfColdDest4, temp);
 	_coneOfColdGfxTbl = _staticres->loadRawData(kEoBBaseConeOfColdGfxTbl, _coneOfColdGfxTblSize);
 
-	_staticres->loadStrings(kEoBBaseSoundMap, temp);
-	_staticres->loadStrings(kEoBBaseLevelSounds1, temp);
-	_staticres->loadStrings(kEoBBaseLevelSounds2, temp);
-	_staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
-	_staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
-	_staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
+	void *sndInfo_ingame = 0;
+	void *sndInfo_intro = 0;
+	void *sndInfo_finale = 0;
+
+	if (_flags.platform == Common::kPlatformAmiga) {
+		const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
+		const char *const *map = _staticres->loadStrings(kEoBBaseSoundMap, temp2);
+		SoundResourceInfo_AmigaEoB ingame(files, temp, map, temp2);
+		sndInfo_ingame = &ingame;
+		files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
+		SoundResourceInfo_AmigaEoB intro(files, temp, 0, 0);
+		sndInfo_intro = &intro;
+		files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
+		SoundResourceInfo_AmigaEoB finale(files, temp, 0, 0);
+		sndInfo_finale = &finale;
+	} else if (_flags.platform == Common::kPlatformFMTowns) {
+		const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
+		const uint8 *data = _staticres->loadRawData(kEoB2PcmSoundEffectsIngame, temp2);
+		SoundResourceInfo_TownsEoB ingame(files, temp, data, temp2, 127);
+		sndInfo_ingame = &ingame;
+		files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
+		data = _staticres->loadRawData(kEoB2PcmSoundEffectsIntro, temp2);
+		SoundResourceInfo_TownsEoB intro(files, temp, data, temp2, 40);
+		sndInfo_intro = &intro;
+		files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
+		data = _staticres->loadRawData(kEoB2PcmSoundEffectsFinale, temp2);
+		SoundResourceInfo_TownsEoB finale(files, temp, data, temp2, 40);
+		sndInfo_finale = &finale;
+	} else if (_flags.platform == Common::kPlatformPC98) {
+
+	} else {
+		const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
+		SoundResourceInfo_PC ingame(files, temp);
+		sndInfo_ingame = &ingame;
+		files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
+		SoundResourceInfo_PC intro(files, temp);
+		sndInfo_intro = &intro;
+		files = _staticres->loadStrings(kEoBBaseSoundFilesFinale, temp);
+		SoundResourceInfo_PC finale(files, temp);
+		sndInfo_finale = &finale;
+	}
+	
+	_sound->initAudioResourceInfo(kMusicIngame, sndInfo_ingame);
+	_sound->initAudioResourceInfo(kMusicIntro, sndInfo_intro);
+	_sound->initAudioResourceInfo(kMusicFinale, sndInfo_finale);
 
 	// Hard code the following strings, since EOB I doesn't have them in the original.
 	// EOB I doesn't have load and save menus, because there is only one single
@@ -1106,6 +1145,9 @@ void EoBEngine::initStaticResource() {
 	for (int i = 0; i < 5; i++)
 		_cgaMappingLevel[i] = _staticres->loadRawData(kEoB1CgaMappingLevel0 + i, temp);
 
+	_levelSoundFiles1 = _staticres->loadStrings(kEoB1BaseLevelSounds1, temp);
+	_levelSoundFiles2 = _staticres->loadStrings(kEoB1BaseLevelSounds2, temp);
+
 	_turnUndeadString = _staticres->loadStrings(kEoB1TurnUndeadString, temp);
 
 	_npcShpData = _staticres->loadRawData(kEoB1NpcShpData, temp);
@@ -1295,17 +1337,6 @@ void DarkMoonEngine::initStaticResource() {
 	_ascii2SjisTables2 = _staticres->loadStrings(kEoB2Ascii2SjisTables2, temp);
 	_saveNamePatterns = _staticres->loadStrings(kEoB2SaveNamePatterns, temp);
 
-	const uint8 *data = _staticres->loadRawData(kEoB2PcmSoundEffectsIngame, temp);
-	SoundResourceInfo_TownsEoB ingame(data, temp, 127);
-	data = _staticres->loadRawData(kEoB2PcmSoundEffectsIntro, temp);
-	SoundResourceInfo_TownsEoB intro(data, temp, 40);
-	data = _staticres->loadRawData(kEoB2PcmSoundEffectsFinale, temp);
-	SoundResourceInfo_TownsEoB finale(data, temp, 40);
-
-	_sound->initAudioResourceInfo(kMusicIngame, &ingame);
-	_sound->initAudioResourceInfo(kMusicIntro, &intro);
-	_sound->initAudioResourceInfo(kMusicFinale, &finale);
-
 	_monsterAcHitChanceTable1 = _monsterAcHitChanceTbl1;
 	_monsterAcHitChanceTable2 = _monsterAcHitChanceTbl2;
 
diff --git a/engines/kyra/sequence/sequences_darkmoon.cpp b/engines/kyra/sequence/sequences_darkmoon.cpp
index 532591e..59f2550 100644
--- a/engines/kyra/sequence/sequences_darkmoon.cpp
+++ b/engines/kyra/sequence/sequences_darkmoon.cpp
@@ -111,7 +111,7 @@ int DarkMoonEngine::mainMenu() {
 	_menuChoiceInit = 0;
 
 	_sound->selectAudioResourceSet(kMusicIntro);
-	_sound->loadSoundFile("INTRO");
+	_sound->loadSoundFile(0);
 
 	Screen::FontId of = _screen->_currentFont;
 	int op = 0;
@@ -542,7 +542,7 @@ void DarkMoonEngine::seq_playFinale() {
 
 	_screen->setCurPage(0);
 
-	_sound->loadSoundFile(_flags.platform == Common::kPlatformFMTowns ?  "FINALE" : "FINALE1");
+	_sound->loadSoundFile(0);
 	snd_stopSound();
 	sq.delay(3);
 
@@ -827,8 +827,7 @@ void DarkMoonEngine::seq_playFinale() {
 	snd_stopSound();
 	sq.delay(3);
 
-	if (_flags.platform != Common::kPlatformFMTowns)
-		_sound->loadSoundFile("FINALE2");
+	_sound->loadSoundFile(1);
 
 	sq.delay(18);
 	if (!skipFlag() && !shouldQuit())
diff --git a/engines/kyra/sequence/sequences_eob.cpp b/engines/kyra/sequence/sequences_eob.cpp
index a04c5f7..1f0b4ab 100644
--- a/engines/kyra/sequence/sequences_eob.cpp
+++ b/engines/kyra/sequence/sequences_eob.cpp
@@ -110,7 +110,7 @@ void EoBIntroPlayer::start() {
 
 	if (!_vm->shouldQuit() && !_vm->skipFlag()) {
 		_vm->snd_playSong(2);
-		_screen->loadBitmap((_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA) ? "TITLE-E.CMP" : "TITLE-V.CMP", 3, 5, 0);
+		_screen->loadBitmap(_vm->gameFlags().platform == Common::kPlatformAmiga ? "TITLE.CPS" : (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA) ? "TITLE-E.CMP" : "TITLE-V.CMP", 3, 5, 0);
 		_screen->convertPage(5, 2, _vm->_cgaMappingDefault);
 		_screen->crossFadeRegion(0, 0, 0, 0, 320, 200, 2, 0);
 		_vm->delay(120 * _vm->_tickLength);
@@ -122,7 +122,7 @@ void EoBIntroPlayer::start() {
 		_screen->loadFileDataToPage(s, 5, s->size() - 768);
 		delete s;
 	} else {
-		_screen->loadBitmap("TEXT.CMP", 3, 5, 0);
+		_screen->loadBitmap(_vm->gameFlags().platform == Common::kPlatformAmiga ? "TEXT.CPS" : "TEXT.CMP", 3, 5, 0);
 	}
 	_screen->convertPage(5, 6, _vm->_cgaMappingAlt);
 
@@ -142,11 +142,16 @@ void EoBIntroPlayer::start() {
 void EoBIntroPlayer::openingCredits() {
 	loadAndSetPalette(_filesOpening[5]);
 
+	_vm->snd_playSong(1);
+
 	_screen->loadBitmap(_filesOpening[4], 5, 3, 0);
 	_screen->convertPage(3, 0, _vm->_cgaMappingAlt);
-	_screen->updateScreen();
 
-	_vm->snd_playSong(1);
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) 
+		_screen->fadePalette(_screen->getPalette(0), 64);
+	else
+		_screen->updateScreen();
+
 	_vm->delay(_openingFrmDelay[0] * _vm->_tickLength);
 
 	for (int i = 0; i < 4 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
@@ -829,7 +834,7 @@ void EoBIntroPlayer::tunnel() {
 }
 
 void EoBIntroPlayer::loadAndSetPalette(const char *filename) {
-	if (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA)
+	if (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA || _vm->gameFlags().platform == Common::kPlatformAmiga)
 		return;
 	_screen->loadPalette(filename, _screen->getPalette(0));
 	_screen->getPalette(0).fill(0, 1, 0);
@@ -983,7 +988,7 @@ int EoBEngine::mainMenu() {
 		case 0: {
 			if (_configRenderMode != Common::kRenderEGA)
 				_screen->loadPalette("EOBPAL.COL", _screen->getPalette(0));
-			_screen->loadEoBBitmap("INTRO", _cgaMappingDefault, 5, 3, 2);
+			_screen->loadEoBBitmap(_flags.platform == Common::kPlatformAmiga ? "TITLE" : "INTRO", _cgaMappingDefault, 5, 3, 2);
 			_screen->setScreenPalette(_screen->getPalette(0));
 			_screen->_curPage = 2;
 			of = _screen->setFont(Screen::FID_6_FNT);
@@ -1018,11 +1023,13 @@ int EoBEngine::mainMenu() {
 
 		case 4:
 			// intro
-			_sound->loadSoundFile("SOUND");
+			_sound->selectAudioResourceSet(kMusicIntro);
+			_sound->loadSoundFile(0);
 			_screen->hideMouse();
 			seq_playIntro();
 			_screen->showMouse();
-			_sound->loadSoundFile("ADLIB");
+			_sound->selectAudioResourceSet(kMusicIngame);
+			_sound->loadSoundFile(0);
 			menuChoice = 0;
 			break;
 		}
diff --git a/engines/kyra/sound/drivers/audiomaster2.cpp b/engines/kyra/sound/drivers/audiomaster2.cpp
index 404bb84..3ade175 100644
--- a/engines/kyra/sound/drivers/audiomaster2.cpp
+++ b/engines/kyra/sound/drivers/audiomaster2.cpp
@@ -830,7 +830,7 @@ void AudioMaster2ResourceManager::loadResourceFile(Common::SeekableReadStream *d
 		AudioMaster2IFFLoader loader(data, this);
 		Common::Functor1Mem<Common::IFFChunk&, bool, AudioMaster2IFFLoader> cb(&loader, &AudioMaster2IFFLoader::loadChunk);
 		loader.parse(cb);
-	} while (data->pos() < data->size());
+	} while (data->pos() + 8 < data->size());
 }
 
 void AudioMaster2ResourceManager::initResource(SoundResource *resource) {
diff --git a/engines/kyra/sound/sound.h b/engines/kyra/sound/sound.h
index ab0e6a1..abeb605 100644
--- a/engines/kyra/sound/sound.h
+++ b/engines/kyra/sound/sound.h
@@ -67,15 +67,17 @@ struct SoundResourceInfo_TownsPC98V2 {
 };
 
 struct SoundResourceInfo_TownsEoB {
-	SoundResourceInfo_TownsEoB(const uint8 *pcmdata, uint dataSize, int pcmvolume) : pcmData(pcmdata), pcmDataSize(dataSize), pcmVolume(pcmvolume) {}
+	SoundResourceInfo_TownsEoB(const char *const *filelist, uint numfiles, const uint8 *pcmdata, uint pcmdataSize, int pcmvolume) : fileList(filelist), numFiles(numfiles), pcmData(pcmdata), pcmDataSize(pcmdataSize), pcmVolume(pcmvolume) {}
 	const uint8 *pcmData;
 	uint pcmDataSize;
 	int pcmVolume;
+	const char *const *fileList;
+	uint numFiles;
 };
 
 
 struct SoundResourceInfo_AmigaEoB {
-	SoundResourceInfo_AmigaEoB(const char *const *files, int numFiles, const char *const *sounds, int numSounds) : fileList(files), fileListSize(numFiles), soundList(sounds), soundListSize(numSounds) {}
+	SoundResourceInfo_AmigaEoB(const char *const *files, int numFiles, const char *const *soundmap, int numSounds) : fileList(files), fileListSize(numFiles), soundList(soundmap), soundListSize(numSounds) {}
 	const char *const *fileList;
 	uint fileListSize;
 	const char *const *soundList;
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
index 781ec46..de8bf22 100644
--- a/engines/kyra/sound/sound_amiga_eob.cpp
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -24,13 +24,14 @@
 #include "kyra/resource/resource.h"
 #include "kyra/sound/drivers/audiomaster2.h"
 
+#include "common/config-manager.h"
 #include "common/memstream.h"
 
 namespace Kyra {
 
-SoundAmiga_EoB::SoundAmiga_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer), _vm(vm), _driver(0), _currentResourceSet(0), _ready(false) {
+SoundAmiga_EoB::SoundAmiga_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer),
+	_vm(vm), _driver(0), _currentResourceSet(-1), _currentFile(-1), _levelSoundList1(0), _levelSoundList2(0), _ready(false) {
 	_fileBuffer = new uint8[64000];
-	_version2 = _vm->game() == GI_EOB2;
 	memset(_resInfo, 0, sizeof(_resInfo));
 }
 
@@ -50,6 +51,10 @@ bool SoundAmiga_EoB::init() {
 	if (!_driver->init())
 		return false;
 
+	int temp = 0;
+	_levelSoundList1 = _vm->staticres()->loadStrings(kEoB1BaseLevelSounds1, temp);
+	_levelSoundList2 = _vm->staticres()->loadStrings(kEoB1BaseLevelSounds2, temp);
+
 	_ready = true;
 	return true;
 }
@@ -60,6 +65,9 @@ void SoundAmiga_EoB::initAudioResourceInfo(int set, void *info) {
 }
 
 void SoundAmiga_EoB::selectAudioResourceSet(int set) {
+	if (set == _currentResourceSet || !_ready)
+		return;
+
 	_driver->flushAllResources();
 	if (!_resInfo[set])
 		return;
@@ -70,50 +78,22 @@ void SoundAmiga_EoB::selectAudioResourceSet(int set) {
 	_currentResourceSet = set;
 }
 
-bool SoundAmiga_EoB::hasSoundFile(uint file) const {
-	return false;
-}
-
 void SoundAmiga_EoB::loadSoundFile(uint file) {
-	/*
-	_sound->loadSoundFile("INTRO1.CPS");
-	_sound->loadSoundFile("INTRO2.CPS");
-	_sound->loadSoundFile("INTRO4.CPS");
-	_sound->loadSoundFile("INTRO5.CPS");
-	_sound->loadSoundFile("NEWINTRO1.CPS");
-	_sound->loadSoundFile("CHARGEN1.CPS");
-
-	_sound->loadSoundFile("SFX1.CPS");
-	_sound->loadSoundFile("SFX2.CPS");
-	_sound->loadSoundFile("SFX3.CPS");
-	_sound->loadSoundFile("SFX4.CPS");
-
-	_sound->loadSoundFile("HUM1.CPS");
-
-	_sound->loadSoundFile("SPIDERMOV1.CPS");
-	_sound->loadSoundFile("MOVE1.CPS");
-	_sound->loadSoundFile("MOVE21.CPS");
-	_sound->loadSoundFile("MOVE31.CPS");
-	_sound->loadSoundFile("BEASTATK1.CPS");
-	_sound->loadSoundFile("BLADE1.CPS");
-	_sound->loadSoundFile("MANTISMOV1.CPS");
-	_sound->loadSoundFile("FLAYERATK1.CPS");
-	_sound->loadSoundFile("LEECHMOV1.CPS");
-	_sound->loadSoundFile("SLOSHSUCK1.CPS");
-	_sound->loadSoundFile("SCREAM1.CPS");
-	_sound->loadSoundFile("RUSTATK1.CPS");
-	_sound->loadSoundFile("HOUNDATK1.CPS");
-	_sound->loadSoundFile("KUOTOAMOV1.CPS");
-
-	_sound->loadSoundFile("FINALE2.CPS");
-	_sound->loadSoundFile("FINALE1.CPS");
-	_sound->loadSoundFile("FINALE.CPS");
-
-	for (int i = 1; i < 12; ++i) {
-		char n[13];
-		sprintf(n, "LEVELSAM%d.CPS", i);
-		_sound->loadSoundFile(n);
-	}*/
+	if (_vm->gameFlags().platform != Common::kPlatformAmiga || _currentResourceSet != kMusicIngame || !_ready)
+		return;
+
+	unloadLevelSounds();
+
+	for (int i = 0; i < 2; ++i) {
+		if (_levelSoundList1[file * 2 + i][0])
+			loadSoundFile(Common::String::format("%s.CPS", _levelSoundList1[file * 2 + i]));
+		if (_levelSoundList2[file * 2 + i][0])
+			loadSoundFile(Common::String::format("%s.CPS", _levelSoundList2[file * 2 + i]));
+	}
+
+	loadSoundFile(Common::String::format("LEVELSAM%d.CPS", file));
+
+	_currentFile = file;
 }
 
 void SoundAmiga_EoB::loadSoundFile(Common::String file) {
@@ -155,157 +135,77 @@ void SoundAmiga_EoB::loadSoundFile(Common::String file) {
 }
 
 void SoundAmiga_EoB::playTrack(uint8 track) {
-	_driver->startSound("newintro1.smus");
-	//_driver->startSound("hum1.sam");
-	//_driver->startSound("hum");
-	//_driver->startSound("playswing");
-	//_driver->startSound("door");
-	//_driver->startSound("death");
-	//_driver->startSound("teleport");
-	//_driver->startSound("scream");
-	//_driver->startSound("magica");
-	//_driver->startSound("magicb");
-
-	//_driver->startSound("chargen1.smus");
-	//_driver->startSound("finale.smus");
+	Common::String newSound;
+	if (_vm->game() == GI_EOB1) {
+		if (_currentResourceSet == kMusicIntro) {
+			if (track == 1)
+				newSound = "newintro1.smus";
+			else if (track == 20)
+				newSound = "chargen1.smus";
+		}
+	} else if (_vm->game() == GI_EOB2) {
+		
+	}
+
+	if (!newSound.empty() && _ready) {
+		_driver->startSound(newSound);
+		_lastSound = newSound;
+	}
 }
 
 void SoundAmiga_EoB::haltTrack() {
-
+	if (!_lastSound.empty())
+		_driver->stopSound(_lastSound);
 }
 
 void SoundAmiga_EoB::playSoundEffect(uint8 track, uint8 volume) {
+	if (_currentResourceSet == -1 || !_ready)
+		return;
+
 	if (!_resInfo[_currentResourceSet]->soundList || track >= 120 || !_sfxEnabled)
 		return;
 
-	_driver->startSound(_resInfo[_currentResourceSet]->soundList[track]);
-
-	static const char *const kEoB1SoundsAmiga[120] = {
-		0,
-		"button",
-		"L1M1A",
-		"door",
-		"door",
-		"slam",
-		"button",
-		"button",
-		"transmute",
-		"eat",
-		"magica",
-		"throw",
-		"plate",
-		"passage",
-		"unlock",
-		"teleport",
-		"undead",
-		"pit",
-		"itemland",
-		0,
-		0,
-		"playhit",
-		"death",
-		"text",
-		"electric",
-		"dart",
-		"dart",
-		"unlock",
-		"bonus",
-		"bump",
-		0,
-		"electric",
-		"playswing",
-		"hum",
-		"panel",
-		"explode",
-		"L10M2M",
-		"L10M2A",
-		"L4M1M",
-		"beastatk",
-		"L9M2M",
-		"L8M1A",
-		"L8M1M",
-		"L7M1A",
-		"L7M1M",
-		"L5M1A",
-		"L5M1M",
-		"flindatk",
-		"L3M2M",
-		"L4M1A",
-		"L8M2M",
-		"houndatk",
-		"scream",
-		"L6M1M",
-		"L3M1A",
-		"L3M1M",
-		"sloshsuck",
-		"L1M2M",
-		"flayeratk",
-		0,
-		"rustatk",
-		"L9M1M",
-		"L10M1A",
-		"L10M1M",
-		"blade",
-		"L7M2M",
-		"blade",
-		"L2M2M",
-		"L12M2A",
-		"L12M2M",
-		0,
-		"L11M1M",
-		"L11M1A",
-		"L2M1A",
-		"L2M1M",
-		"L1M1M",
-		"button",
-		0,
-		"drop",
-		"text",
-		"magicb",
-		"lock",
-		0,
-		0,
-		0,
-		"Missile",
-		0,
-		"burnhands",
-		"electric",
-		"fireball",
-		0,
-		"magica",
-		"magica",
-		"magica",
-		"magicb",
-		"magicb",
-		"acid",
-		"magicb",
-		"fireball",
-		"acid",
-		"magica",
-		"magicb",
-		"magicb",
-		"undead",
-		"magica",
-		"magica",
-		"magica",
-		"magicb",
-		"cause",
-		"magicb",
-		"magicb",
-		"magica",
-		"magicb",
-		"magica",
-		"magica",
-		"magica",
-		"magica",
-		"cause",
-		0,
-		"door"
-	};
+	Common::String newSound = _resInfo[_currentResourceSet]->soundList[track];
+
+	if (!newSound.empty()) {
+		_driver->startSound(newSound);
+		_lastSound = newSound;
+	}
 }
 
 void SoundAmiga_EoB::beginFadeOut() {
+	haltTrack();
+}
 
+void SoundAmiga_EoB::updateVolumeSettings() {
+	if (!_driver || !_ready)
+		return;
+
+	bool mute = false;
+	if (ConfMan.hasKey("mute"))
+		mute = ConfMan.getBool("mute");
+
+	_driver->setMusicVolume((mute ? 0 : ConfMan.getInt("music_volume")));
+	_driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
+}
+
+void SoundAmiga_EoB::unloadLevelSounds() {
+	if (_currentFile != -1) {
+		_driver->flushResource(Common::String::format("L%dM1A1", _currentFile));
+		_driver->flushResource(Common::String::format("L%dM2A1", _currentFile));
+
+		for (int i = 1; i < 5; ++i) {
+			_driver->flushResource(Common::String::format("L%dM1M%d", _currentFile, i));
+			_driver->flushResource(Common::String::format("L%dM2M%d", _currentFile, i));
+		}
+
+		for (int i = 0; i < 2; ++i) {
+			if (_levelSoundList1[_currentFile * 2 + i][0])
+				_driver->flushResource(_levelSoundList1[_currentFile * 2 + i]);
+			if (_levelSoundList2[_currentFile * 2 + i][0])
+				_driver->flushResource(_levelSoundList2[_currentFile * 2 + i]);
+		}
+	}
 }
 
 } // End of namespace Kyra
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index fccdc03..b6e28da 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -363,7 +363,7 @@ public:
 	virtual void initAudioResourceInfo(int set, void *info);
 	virtual void selectAudioResourceSet(int set);
 	virtual bool hasSoundFile(uint file) const;
-	virtual void loadSoundFile(uint file) {}
+	virtual void loadSoundFile(uint file);
 	virtual void loadSoundFile(Common::String name);
 
 	virtual void playTrack(uint8 track);
@@ -388,6 +388,9 @@ private:
 		int16 para2;
 	} _soundTable[120];
 
+	const char *const *_fileList;
+	uint _fileListLen;
+
 	uint8 _lastSfxChan;
 	uint8 _lastEnvChan;
 	uint8 *_pcmData;
@@ -397,7 +400,7 @@ private:
 	int _timer;
 	int _timerSwitch;
 
-	SoundResourceInfo_TownsEoB *_pcmResource[3];
+	SoundResourceInfo_TownsEoB *_resource[3];
 
 	TownsAudioInterface *_intf;
 };
@@ -413,23 +416,31 @@ public:
 	bool init();
 	void initAudioResourceInfo(int set, void *info);
 	void selectAudioResourceSet(int set);
-	bool hasSoundFile(uint file) const;
+	bool hasSoundFile(uint file) const { return false; }
 	void loadSoundFile(uint file);
 	void loadSoundFile(Common::String file);
 	void playTrack(uint8 track);
 	void haltTrack();
 	void playSoundEffect(uint8 track, uint8 volume = 0xFF);
 	void beginFadeOut();
+	void updateVolumeSettings();
 
 private:
+	void unloadLevelSounds();
+
 	uint8 *_fileBuffer;
 
 	KyraEngine_v1 *_vm;
 	AudioMaster2 *_driver;
 	SoundResourceInfo_AmigaEoB *_resInfo[3];
+	Common::String _lastSound;
+
 	int _currentResourceSet;
+	int _currentFile;
+
+	const char *const *_levelSoundList1;
+	const char *const *_levelSoundList2;
 
-	bool _version2;
 	bool _ready;
 };
 
diff --git a/engines/kyra/sound/sound_towns_darkmoon.cpp b/engines/kyra/sound/sound_towns_darkmoon.cpp
index 25fd414..747e1bd 100644
--- a/engines/kyra/sound/sound_towns_darkmoon.cpp
+++ b/engines/kyra/sound/sound_towns_darkmoon.cpp
@@ -39,7 +39,7 @@ SoundTowns_Darkmoon::SoundTowns_Darkmoon(KyraEngine_v1 *vm, Audio::Mixer *mixer)
 	_pcmVol = 0;
 	_timer = 0;
 	_timerSwitch = 0;
-	memset(_pcmResource, 0, sizeof(_pcmResource));
+	memset(_resource, 0, sizeof(_resource));
 }
 	
 SoundTowns_Darkmoon::~SoundTowns_Darkmoon() {
@@ -85,31 +85,39 @@ void SoundTowns_Darkmoon::timerCallback(int timerId) {
 }
 
 void SoundTowns_Darkmoon::initAudioResourceInfo(int set, void *info) {
-	delete _pcmResource[set];
-	_pcmResource[set] = info ? new SoundResourceInfo_TownsEoB(*(SoundResourceInfo_TownsEoB*)info) : 0;
+	delete _resource[set];
+	_resource[set] = info ? new SoundResourceInfo_TownsEoB(*(SoundResourceInfo_TownsEoB*)info) : 0;
 }
 
 void SoundTowns_Darkmoon::selectAudioResourceSet(int set) {
 	delete[] _pcmData;
 
-	if (!_pcmResource[set] || !_pcmResource[kMusicIngame])
+	if (!_resource[set] || !_resource[kMusicIngame])
 		return;
-	
-	_pcmDataSize = _pcmResource[kMusicIngame]->pcmDataSize;
+
+	_fileList = _resource[set]->fileList;
+	_fileListLen = _resource[set]->numFiles;
+
+	_pcmDataSize = _resource[kMusicIngame]->pcmDataSize;
 	_pcmData = new uint8[_pcmDataSize];	
-	_pcmVol = _pcmResource[set]->pcmVolume;
-	memcpy(_pcmData, _pcmResource[kMusicIngame]->pcmData, _pcmDataSize);
+	_pcmVol = _resource[set]->pcmVolume;
+	memcpy(_pcmData, _resource[kMusicIngame]->pcmData, _pcmDataSize);
 
 	if (set == kMusicIngame)
 		return;
 
-	memcpy(_pcmData, _pcmResource[set]->pcmData, _pcmResource[set]->pcmDataSize);
+	memcpy(_pcmData, _resource[set]->pcmData, _resource[set]->pcmDataSize);
 }
 
 bool SoundTowns_Darkmoon::hasSoundFile(uint file) const {
 	return true;
 }
 
+void SoundTowns_Darkmoon::loadSoundFile(uint file) {
+	if (file < _fileListLen)
+		loadSoundFile(_fileList[file]);
+}
+
 void SoundTowns_Darkmoon::loadSoundFile(Common::String name) {
 	Common::SeekableReadStream *s = _vm->resource()->createReadStream(Common::String::format("%s.SDT", name.c_str()));
 	if (!s)


Commit: e00eaa4899d86fb97c333d4b609de4612895ffea
    https://github.com/scummvm/scummvm/commit/e00eaa4899d86fb97c333d4b609de4612895ffea
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:20+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix intro

Changed paths:
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/sequence/sequences_eob.cpp


diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index bf5f7af..df859b0 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -224,7 +224,7 @@ void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Pal
 
 	if (_isAmiga) {
 		// Yay, this is where EOB1 Amiga hides the palette data
-		loadPalette(_pagePtrs[3] + 40000, *_palettes[0], 64);
+		loadPalette(_pagePtrs[dstPage] + 40000, *_palettes[0], 64);
 		_palettes[0]->fill(0, 1, 0);
 
 		Screen::convertAmigaGfx(getPagePtr(dstPage), 320, 200);
diff --git a/engines/kyra/sequence/sequences_eob.cpp b/engines/kyra/sequence/sequences_eob.cpp
index 1f0b4ab..7b3618f 100644
--- a/engines/kyra/sequence/sequences_eob.cpp
+++ b/engines/kyra/sequence/sequences_eob.cpp
@@ -78,9 +78,13 @@ private:
 	const uint8 *_tvlY2;
 	const uint8 *_tvlW;
 	const uint8 *_tvlH;
+	
+	const uint8 _fillColor1;
+	const uint8 _fillColor2;
 };
 
-EoBIntroPlayer::EoBIntroPlayer(EoBEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen) {
+EoBIntroPlayer::EoBIntroPlayer(EoBEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen), 
+	_fillColor1(vm->gameFlags().platform == Common::kPlatformAmiga ? 19 : 12), _fillColor2(vm->gameFlags().platform == Common::kPlatformAmiga ? 10 : 157) {
 	int temp = 0;
 	_filesOpening = _vm->staticres()->loadStrings(kEoB1IntroFilesOpening, temp);
 	_filesTower = _vm->staticres()->loadStrings(kEoB1IntroFilesTower, temp);
@@ -102,6 +106,8 @@ EoBIntroPlayer::EoBIntroPlayer(EoBEngine *vm, Screen_EoB *screen) : _vm(vm), _sc
 	_tvlY2 = _vm->staticres()->loadRawData(kEoB1IntroTvlY2, temp);
 	_tvlW = _vm->staticres()->loadRawData(kEoB1IntroTvlW, temp);
 	_tvlH = _vm->staticres()->loadRawData(kEoB1IntroTvlH, temp);
+	const uint8 *orbFadePal = _vm->staticres()->loadRawData(kEoB1IntroOrbFadePal, temp);
+	_screen->loadPalette(orbFadePal, _screen->getPalette(2), temp);
 }
 
 void EoBIntroPlayer::start() {
@@ -112,8 +118,9 @@ void EoBIntroPlayer::start() {
 		_vm->snd_playSong(2);
 		_screen->loadBitmap(_vm->gameFlags().platform == Common::kPlatformAmiga ? "TITLE.CPS" : (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA) ? "TITLE-E.CMP" : "TITLE-V.CMP", 3, 5, 0);
 		_screen->convertPage(5, 2, _vm->_cgaMappingDefault);
+		uint32 del = 120 * _vm->_tickLength;
 		_screen->crossFadeRegion(0, 0, 0, 0, 320, 200, 2, 0);
-		_vm->delay(120 * _vm->_tickLength);
+		_vm->delay(del);
 	}
 
 	Common::SeekableReadStream *s = _vm->resource()->createReadStream("TEXT.RAW");
@@ -140,17 +147,17 @@ void EoBIntroPlayer::start() {
 }
 
 void EoBIntroPlayer::openingCredits() {
-	loadAndSetPalette(_filesOpening[5]);
-
 	_vm->snd_playSong(1);
 
 	_screen->loadBitmap(_filesOpening[4], 5, 3, 0);
 	_screen->convertPage(3, 0, _vm->_cgaMappingAlt);
 
-	if (_vm->gameFlags().platform == Common::kPlatformAmiga) 
-		_screen->fadePalette(_screen->getPalette(0), 64);
-	else
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
+		_screen->fadeFromBlack(64);
+	} else {
+		loadAndSetPalette(_filesOpening[5]);
 		_screen->updateScreen();
+	}
 
 	_vm->delay(_openingFrmDelay[0] * _vm->_tickLength);
 
@@ -161,13 +168,17 @@ void EoBIntroPlayer::openingCredits() {
 		_screen->crossFadeRegion(0, 50, 0, 50, 320, 102, 4, 0);
 		_vm->delayUntil(nextFrameTimer);
 	}
+
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_vm->delay(50 * _vm->_tickLength);
 }
 
 void EoBIntroPlayer::tower() {
 	if (_vm->shouldQuit() || _vm->skipFlag())
-		return;
-
+		return; 
+ 
 	_screen->loadBitmap(_filesTower[1], 5, 3, 0);
+
 	_screen->setCurPage(2);
 	uint8 *shp = _screen->encodeShape(0, 0, 16, 56, true, _vm->_cgaMappingAlt);
 	_screen->convertPage(3, 4, _vm->_cgaMappingAlt);
@@ -176,8 +187,9 @@ void EoBIntroPlayer::tower() {
 	for (int i = 0; i < 200; i += 64)
 		_screen->copyRegion(128, 104, 96, i, 128, 64, 4, 2, Screen::CR_NO_P_CHECK);
 
-	_screen->fillRect(0, 184, 319, 199, 12);
+	_screen->fillRect(0, 184, 319, 199, _fillColor1);
 	int cp = _screen->setCurPage(0);
+
 	whirlTransition();
 	loadAndSetPalette(_filesTower[0]);
 
@@ -217,10 +229,10 @@ void EoBIntroPlayer::tower() {
 		_screen->copyRegion(0, 110, 96, 54 + i, 128, 34, 4, 0, Screen::CR_NO_P_CHECK);
 
 		if (i < 32) {
-			_screen->fillRect(128, 0, 255, i + 1, 12, 2);
+			_screen->fillRect(128, 0, 255, i + 1, _fillColor1, 2);
 			_screen->copyRegion(152, 0, 120, 32, 80, i + 25, 4, 0, Screen::CR_NO_P_CHECK);
 		} else {
-			_screen->fillRect(128, 0, 255, i + 1, 12, 2);
+			_screen->fillRect(128, 0, 255, i + 1, _fillColor1, 2);
 			_screen->copyRegion(152, i + 1, 120, 32 + i + 1, 80, 23, 4, 0, Screen::CR_NO_P_CHECK);
 			_screen->copyRegion(152, 0, 152, 32, 80, i + 1, 4, 2, Screen::CR_NO_P_CHECK);
 		}
@@ -249,47 +261,64 @@ void EoBIntroPlayer::orb() {
 	_screen->loadBitmap(_filesOrb[1], 5, 3, 0);
 	shp[3] = _screen->encodeShape(16, 0, 16, 104, true, _vm->_cgaMappingAlt);
 
-	_screen->fillRect(0, 0, 127, 103, 12);
+	_screen->fillRect(0, 0, 127, 103, _fillColor1);
 	for (int i = 1; i < 4; i++) {
 		copyBlurRegion(128, 0, 0, 0, 128, 104, i);
 		shp[3 - i] = _screen->encodeShape(0, 0, 16, 104, true, _vm->_cgaMappingAlt);
 	}
 
-	_screen->fillRect(0, 0, 159, 135, 12);
+	_screen->fillRect(0, 0, 159, 135, _fillColor1);
 	_screen->setCurPage(0);
 	_screen->convertPage(3, 4, _vm->_cgaMappingAlt);
+
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
+		_screen->fadeToBlack(16);
+		loadAndSetPalette(0);
+	}
+
 	_screen->clearCurPage();
 
 	_vm->snd_playSoundEffect(6);
 
-	for (int i = -1; i < 4 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
+	int startFrame = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 3 : -1;
+	for (int i = startFrame; i < 4 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
 		uint32 end = _vm->_system->getMillis() + 3 * _vm->_tickLength;
 		if (i >= 0)
 			_screen->drawShape(2, shp[i], 16, 16, 0);
 		_screen->drawShape(2, shp[4], 0, 0, 0);
 		_screen->copyRegion(0, 0, 80, 24, 160, 136, 2, 0, Screen::CR_NO_P_CHECK);
 		_screen->updateScreen();
-		_vm->delayUntil(end);
+		if (startFrame < 0)
+			_vm->delayUntil(end);
 	}
 
 	_screen->copyRegion(0, 64, 0, 168, 320, 16, 6, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
-	_vm->delay(40 * _vm->_tickLength);
-
-	_vm->snd_playSoundEffect(6);
 
-	for (int i = 3; i > -2 && !_vm->shouldQuit() && !_vm->skipFlag(); i--) {
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
+		_vm->delay(80 * _vm->_tickLength);
+		_screen->fadePalette(_screen->getPalette(2), 48);
+		_screen->clearCurPage();
+	} else {		
+		_vm->delay(40 * _vm->_tickLength);
+		_vm->snd_playSoundEffect(6);
+	}	
+
+	startFrame = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? -1 : 3;
+	for (int i = startFrame; i > -2 && !_vm->shouldQuit() && !_vm->skipFlag(); i--) {
 		uint32 end = _vm->_system->getMillis() + 3 * _vm->_tickLength;
-		_screen->fillRect(16, 16, 143, 119, 12, 2);
+		_screen->fillRect(16, 16, 143, 119, _fillColor1, 2);
 		if (i >= 0)
 			_screen->drawShape(2, shp[i], 16, 16, 0);
 		_screen->drawShape(2, shp[4], 0, 0, 0);
 		_screen->copyRegion(0, 0, 80, 24, 160, 136, 2, 0, Screen::CR_NO_P_CHECK);
 		_screen->updateScreen();
-		_vm->delayUntil(end);
+		if (startFrame > 0)
+			_vm->delayUntil(end);
 	}
 
-	_vm->delay(40 * _vm->_tickLength);
+	if (startFrame > 0)
+		_vm->delay(40 * _vm->_tickLength);
 
 	for (int i = 0; i < 5; i++)
 		delete[] shp[i];
@@ -305,6 +334,10 @@ void EoBIntroPlayer::waterdeepEntry() {
 
 	loadAndSetPalette(_filesWdEntry[0]);
 	_screen->loadBitmap(_filesWdEntry[1], 5, 3, 0);
+
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_screen->fadePalette(_screen->getPalette(0), 16);
+
 	_screen->setCurPage(2);
 	shp[3] = _screen->encodeShape(0, 0, 20, 136, true, _vm->_cgaMappingAlt);
 	for (int i = 1; i < 4; i++) {
@@ -314,10 +347,11 @@ void EoBIntroPlayer::waterdeepEntry() {
 	_screen->setCurPage(0);
 
 	_screen->convertPage(3, 4, _vm->_cgaMappingAlt);
-	_screen->fillRect(0, 168, 319, 199, 12, 0);
+	_screen->fillRect(0, 168, 319, 199, _fillColor1, 0);
 	_vm->snd_playSoundEffect(6);
 
-	for (int i = 0; i < 4 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
+	int startFrame = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 3 : 0;
+	for (int i = startFrame; i < 4 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
 		uint32 end = _vm->_system->getMillis() + 3 * _vm->_tickLength;
 		_screen->drawShape(0, shp[i], 80, 24, 0);
 		delete[] shp[i];
@@ -345,7 +379,7 @@ void EoBIntroPlayer::waterdeepEntry() {
 
 	for (int i = 0; i < 3 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
 		uint32 end = _vm->_system->getMillis() + 3 * _vm->_tickLength;
-		_screen->fillRect(0, 0, 159, 135, 12, 2);
+		_screen->fillRect(0, 0, 159, 135, _fillColor1, 2);
 		_screen->drawShape(2, shp[i], 0, 0, 0);
 		_screen->copyRegion(0, 0, 80, 24, 160, 136, 2, 0, Screen::CR_NO_P_CHECK);
 		_screen->updateScreen();
@@ -356,7 +390,7 @@ void EoBIntroPlayer::waterdeepEntry() {
 	_screen->updateScreen();
 	_vm->delay(4 * _vm->_tickLength);
 	_screen->copyRegion(160, 0, 80, 24, 160, 136, 4, 0, Screen::CR_NO_P_CHECK);
-	_screen->fillRect(0, 168, 319, 199, 12, 0);
+	_screen->fillRect(0, 168, 319, 199, _fillColor1, 0);
 	_screen->updateScreen();
 	_vm->delay(4 * _vm->_tickLength);
 	_screen->copyRegion(0, 184, 40, 184, 232, 16, 4, 0, Screen::CR_NO_P_CHECK);
@@ -402,6 +436,11 @@ void EoBIntroPlayer::king() {
 	_screen->loadBitmap(_filesKing[0], 5, 3, 0);
 	_screen->convertPage(3, 4, _vm->_cgaMappingAlt);
 
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
+		_screen->fadeToBlack(32);
+		loadAndSetPalette(0);
+	}
+
 	int x = 15;
 	int y = 14;
 	int w = 1;
@@ -490,8 +529,11 @@ void EoBIntroPlayer::hands() {
 	uint8 *shp2 = _screen->encodeShape(21, 140, 12, 60, true, _vm->_cgaMappingAlt);
 	_screen->loadBitmap(_filesHands[0], 3, 5, 0);
 
-	_screen->fillRect(0, 160, 319, 199, 12, 0);
-	_screen->fillRect(0, 0, 191, 63, 157, 2);
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_vm->delay(60 * _vm->_tickLength);
+
+	_screen->fillRect(0, 160, 319, 199, _fillColor1, 0);
+	_screen->fillRect(0, 0, 191, 63, _fillColor2, 2);
 	_screen->drawShape(2, shp1, 0, 4, 0);
 	_screen->drawShape(2, shp2, 151, 4, 0);
 	boxMorphTransition(25, 8, 18, 4, 3, 0, 21, 8, 6, 0, 28, 23);
@@ -503,7 +545,7 @@ void EoBIntroPlayer::hands() {
 
 	for (int i = -22; i <= 20 && !_vm->shouldQuit() && !_vm->skipFlag(); i += 4) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->fillRect(0, 0, 167, 63, 157);
+		_screen->fillRect(0, 0, 167, 63, _fillColor2);
 		_screen->drawShape(2, shp1, i, 4, 0);
 		_screen->drawShape(2, shp2, 105 - i, 4, 0);
 		_screen->copyRegion(0, 0, 144, 32, 168, 64, 2, 0, Screen::CR_NO_P_CHECK);
@@ -523,7 +565,7 @@ void EoBIntroPlayer::hands() {
 	uint8 *shp3 = _screen->encodeShape(9, 138, 14, 54, true, _vm->_cgaMappingAlt);
 
 	_screen->setCurPage(2);
-	_screen->fillRect(0, 0, 135, 63, 157);
+	_screen->fillRect(0, 0, 135, 63, _fillColor2);
 	_screen->drawShape(2, shp1, 32, -80, 0);
 	_screen->drawShape(2, shp2, 40, -16, 0);
 	boxMorphTransition(18, 16, 10, 12, 0, 0, 17, 8, 17, 3, 25, 10);
@@ -531,7 +573,7 @@ void EoBIntroPlayer::hands() {
 
 	for (int i = -80; i <= 0 && !_vm->shouldQuit() && !_vm->skipFlag(); i += 4) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->fillRect(0, 0, 135, 63, 157);
+		_screen->fillRect(0, 0, 135, 63, _fillColor2);
 		_screen->drawShape(2, shp1, 32, i, 0);
 		_screen->drawShape(2, shp2, 40, i + 64, 0);
 		_screen->copyRegion(0, 0, 80, 96, 136, 64, 2, 0, Screen::CR_NO_P_CHECK);
@@ -544,7 +586,7 @@ void EoBIntroPlayer::hands() {
 
 	for (int i = 0; i > -54 && !_vm->shouldQuit() && !_vm->skipFlag(); i -= 4) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->fillRect(0, 0, 135, 63, 157);
+		_screen->fillRect(0, 0, 135, 63, _fillColor2);
 		_screen->drawShape(2, shp3, 12, 64 + i, 0);
 		_screen->drawShape(2, shp1, 32, i, 0);
 		_screen->copyRegion(0, 0, 80, 96, 136, 64, 2, 0, Screen::CR_NO_P_CHECK);
@@ -562,7 +604,7 @@ void EoBIntroPlayer::hands() {
 	shp2 = _screen->encodeShape(0, 136, 9, 48, true, _vm->_cgaMappingAlt);
 
 	_screen->setCurPage(2);
-	_screen->fillRect(0, 0, 143, 95, 157);
+	_screen->fillRect(0, 0, 143, 95, _fillColor2);
 	_screen->drawShape(2, shp1, -56, -56, 0);
 	_screen->drawShape(2, shp2, 52, 49, 0);
 	boxMorphTransition(9, 6, 0, 0, 0, 0, 18, 12, 8, 11, 21, 10);
@@ -571,7 +613,7 @@ void EoBIntroPlayer::hands() {
 
 	for (int i = -56; i <= -8 && !_vm->shouldQuit() && !_vm->skipFlag(); i += 4) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->fillRect(0, 0, 143, 95, 157);
+		_screen->fillRect(0, 0, 143, 95, _fillColor2);
 		_screen->drawShape(2, shp1, i, i, 0);
 		_screen->drawShape(2, shp2, (i == -8) ? 55 : 52, (i == -8) ? 52 : 49, 0);
 		_screen->copyRegion(0, 0, 0, 0, 144, 96, 2, 0, Screen::CR_NO_P_CHECK);
@@ -589,7 +631,7 @@ void EoBIntroPlayer::hands() {
 	shp2 = _screen->encodeShape(28, 40, 10, 72, true, _vm->_cgaMappingAlt);
 
 	_screen->setCurPage(2);
-	_screen->fillRect(0, 0, 87, 112, 157);
+	_screen->fillRect(0, 0, 87, 112, _fillColor2);
 	_screen->drawShape(2, shp2, 0, 90, 0);
 	boxMorphTransition(20, 13, 15, 6, 0, 0, 11, 14, 0, 0, 24, 16);
 	_vm->delay(15 * _vm->_tickLength);
@@ -597,7 +639,7 @@ void EoBIntroPlayer::hands() {
 	int dy = 90;
 	for (int i = -40; i <= 0 && !_vm->shouldQuit() && !_vm->skipFlag(); i += 4) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->fillRect(0, 0, 87, 112, 157);
+		_screen->fillRect(0, 0, 87, 112, _fillColor2);
 		_screen->drawShape(2, shp2, 0, dy, 0);
 		_screen->copyRegion(0, 0, 120, 48, 88, 112, 2, 0, Screen::CR_NO_P_CHECK);
 		_screen->updateScreen();
@@ -609,7 +651,7 @@ void EoBIntroPlayer::hands() {
 
 	for (int i = -40; i <= 0 && !_vm->shouldQuit() && !_vm->skipFlag(); i += 4) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->fillRect(0, 0, 87, 39, 157);
+		_screen->fillRect(0, 0, 87, 39, _fillColor2);
 		_screen->drawShape(2, shp1, 0, i, 0);
 		_screen->copyRegion(0, 0, 120, 48, 88, 112, 2, 0, Screen::CR_NO_P_CHECK);
 		_screen->updateScreen();
@@ -637,7 +679,7 @@ void EoBIntroPlayer::waterdeepExit() {
 	uint8 *shp1 = _screen->encodeShape(31, 136, 5, 32, true, _vm->_cgaMappingAlt);
 	_screen->convertPage(3, 4, _vm->_cgaMappingAlt);
 	_screen->copyRegion(0, 0, 0, 136, 48, 36, 4, 4, Screen::CR_NO_P_CHECK);
-	_screen->fillRect(0, 168, 319, 199, 12, 0);
+	_screen->fillRect(0, 168, 319, 199, _fillColor1, 0);
 	_screen->copyRegion(160, 0, 80, 24, 160, 136, 4, 0, Screen::CR_NO_P_CHECK);
 
 	int cx = 140;
@@ -680,13 +722,14 @@ void EoBIntroPlayer::waterdeepExit() {
 	delete[] shp1;
 
 	_screen->setCurPage(0);
-	_screen->fillRect(0, 168, 319, 199, 12, 0);
+	_screen->fillRect(0, 168, 319, 199, _fillColor1, 0);
 	_screen->copyRegion(0, 136, 0, 0, 48, 36, 0, 4, Screen::CR_NO_P_CHECK);
 
-	loadAndSetPalette(_filesWdExit[1]);
-	_screen->loadBitmap(_filesWdExit[2], 3, 5, 0);
-	_screen->convertPage(5, 2, _vm->_cgaMappingAlt);
+	int dstPage = (_vm->gameFlags().platform == Common::kPlatformAmiga) ? 4 : 5; 
+	_screen->loadBitmap(_filesWdExit[2], 3, dstPage, 0);
+	_screen->convertPage(dstPage, 2, _vm->_cgaMappingAlt);
 	whirlTransition();
+	loadAndSetPalette(_filesWdExit[1]);
 	_vm->delay(6 * _vm->_tickLength);
 
 	_screen->copyRegion(0, 144, 0, 184, 320, 16, 6, 0, Screen::CR_NO_P_CHECK);
@@ -725,12 +768,12 @@ void EoBIntroPlayer::waterdeepExit() {
 		_vm->delayUntil(end);
 	}
 
-	_screen->loadBitmap(_filesWdExit[3], 3, 5, 0);
-	_screen->convertPage(5, 2, _vm->_cgaMappingAlt);
+	_screen->loadBitmap(_filesWdExit[3], 3, dstPage, 0);
+	_screen->convertPage(dstPage, 2, _vm->_cgaMappingAlt);
 	_vm->delay(30 * _vm->_tickLength);
 	_screen->setCurPage(0);
-	_screen->fillRect(0, 16, 319, 31, 12);
-	_screen->fillRect(0, 136, 319, 199, 12);
+	_screen->fillRect(0, 16, 319, 31, _fillColor1);
+	_screen->fillRect(0, 136, 319, 199, _fillColor1);
 	_screen->copyRegion(0, 0, 80, 32, 160, 120, 2, 0, Screen::CR_NO_P_CHECK);
 	loadAndSetPalette(_filesWdExit[4]);
 	_screen->updateScreen();
@@ -780,6 +823,9 @@ void EoBIntroPlayer::tunnel() {
 	_screen->copyRegion(0, 0, 80, 32, 160, 120, 2, 0, Screen::CR_NO_P_CHECK);
 
 	_screen->loadBitmap(_filesTunnel[0], 5, 3, 0);
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_screen->setScreenPalette(_screen->getPalette(0));
+
 	_screen->convertPage(3, 4, _vm->_cgaMappingAlt);
 	_screen->updateScreen();
 	_vm->delay(40 * _vm->_tickLength);
@@ -794,7 +840,7 @@ void EoBIntroPlayer::tunnel() {
 	for (int i = 0; i < 30 && !_vm->shouldQuit() && !_vm->skipFlag(); i++) {
 		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
 		if (i == 0)
-			_screen->fillRect(0, 168, 319, 199, 12, 0);
+			_screen->fillRect(0, 168, 319, 199, _fillColor1, 0);
 		_screen->copyRegion(80, 25 + (_vm->_rnd.getRandomNumber(255) & 7), 80, 24, 160, 144, 2, 0, Screen::CR_NO_P_CHECK);
 		_screen->updateScreen();
 		_vm->delayUntil(end);
@@ -834,9 +880,12 @@ void EoBIntroPlayer::tunnel() {
 }
 
 void EoBIntroPlayer::loadAndSetPalette(const char *filename) {
-	if (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA || _vm->gameFlags().platform == Common::kPlatformAmiga)
+	if (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA)
 		return;
-	_screen->loadPalette(filename, _screen->getPalette(0));
+
+	if (_vm->gameFlags().platform != Common::kPlatformAmiga)
+		_screen->loadPalette(filename, _screen->getPalette(0));
+
 	_screen->getPalette(0).fill(0, 1, 0);
 	_screen->setScreenPalette(_screen->getPalette(0));
 }
@@ -959,6 +1008,12 @@ void EoBIntroPlayer::boxMorphTransition(int targetDestX, int targetDestY, int ta
 }
 
 void EoBIntroPlayer::whirlTransition() {
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
+		_screen->fadeToBlack(48);
+		_screen->clearPage(0);
+		return;
+	}
+
 	for (int i = 0; i < 2; i++) {
 		for (int ii = 0; ii < 8; ii++) {
 			uint32 e = _vm->_system->getMillis() + 3;


Commit: 7b8c84fa4d3f3d8e1c5fa543fae7ddbd7a495bb7
    https://github.com/scummvm/scummvm/commit/7b8c84fa4d3f3d8e1c5fa543fae7ddbd7a495bb7
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:21+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix chargen and gui colors

Changed paths:
    engines/kyra/engine/chargen.cpp
    engines/kyra/engine/darkmoon.cpp
    engines/kyra/engine/darkmoon.h
    engines/kyra/engine/eob.cpp
    engines/kyra/engine/eob.h
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/kyra_rpg.h
    engines/kyra/engine/lol.cpp
    engines/kyra/engine/lol.h
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/gui/gui_eob.cpp
    engines/kyra/gui/gui_eob.h
    engines/kyra/resource/staticres_eob.cpp
    engines/kyra/resource/staticres_lol.cpp
    engines/kyra/script/script_eob.cpp
    engines/kyra/sequence/sequences_eob.cpp
    engines/kyra/text/text_rpg.cpp
    engines/kyra/text/text_rpg.h


diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
index 5032e86..14e72f8 100644
--- a/engines/kyra/engine/chargen.cpp
+++ b/engines/kyra/engine/chargen.cpp
@@ -160,6 +160,8 @@ CharacterGenerator::CharacterGenerator(EoBCoreEngine *vm, Screen_EoB *screen) :
 }
 
 CharacterGenerator::~CharacterGenerator() {
+	_vm->_gui->updateBoxFrameHighLight(-1);
+
 	if (_chargenMagicShapes) {
 		for (int i = 0; i < 10; i++)
 			delete[] _chargenMagicShapes[i];
@@ -263,10 +265,6 @@ bool CharacterGenerator::start(EoBCharacter *characters, uint8 ***faceShapes) {
 }
 
 void CharacterGenerator::init() {
-	/*_screen->loadEoBBitmap("MENU", 0, 3, 3, 2);
-	Common::SeekableReadStream *s = _res->createReadStream("facedat.dmp");
-	_screen->loadFileDataToPage(s, 2, 64000);*/
-
 	_screen->loadShapeSetBitmap("CHARGENA", 3, 3);
 	if (_faceShapes) {
 		for (int i = 0; i < 44; i++)
@@ -279,7 +277,14 @@ void CharacterGenerator::init() {
 		_faceShapes[i] = _screen->encodeShape((i % 10) << 2, (i / 10) << 5, 4, 32, true, _vm->_cgaMappingDefault);
 	_screen->_curPage = 0;
 
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_screen->fadeToBlack(32);
+
 	_screen->loadEoBBitmap("CHARGEN", _vm->_cgaMappingDefault, 3, 3, 0);
+
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_screen->fadeFromBlack(32);
+
 	_screen->loadShapeSetBitmap("CHARGENB", 3, 3);
 	if (_chargenMagicShapes) {
 		for (int i = 0; i < 10; i++)
@@ -352,7 +357,7 @@ void CharacterGenerator::checkForCompleteParty() {
 	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
 	int cp = _screen->setCurPage(2);
 	int x = (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168;
-	_screen->printShadedText(_chargenStrings1[8], x, 16, 15, 0);
+	_screen->printShadedText(_chargenStrings1[8], x, 16, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->setCurPage(cp);
 	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
 
@@ -364,7 +369,7 @@ void CharacterGenerator::checkForCompleteParty() {
 
 	if (numChars == 4) {
 		_screen->setCurPage(2);
-		_screen->printShadedText(_chargenStrings1[0], x, 61, 15, 0);
+		_screen->printShadedText(_chargenStrings1[0], x, 61, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 		_screen->setCurPage(0);
 		_screen->copyRegion(168, 61, 152, 125, 136, 40, 2, 0, Screen::CR_NO_P_CHECK);
 		toggleSpecialButton(15, 0, 0);
@@ -445,7 +450,7 @@ int CharacterGenerator::viewDeleteCharacter() {
 				if (_characters[_activeBox].name[0]) {
 					processSpecialButton(16);
 					_characters[_activeBox].name[0] = 0;
-					processNameInput(_activeBox, 12);
+					processNameInput(_activeBox, _vm->guiSettings()->colors.menuTxtColBlack);
 					processFaceMenuSelection(_activeBox + 50);
 				}
 			} else {
@@ -506,10 +511,10 @@ void CharacterGenerator::createPartyMember() {
 		for (_characters[_activeBox].name[0] = 0; _characters[_activeBox].name[0] == 0 && !_vm->shouldQuit();) {
 			processFaceMenuSelection(_chargenMinStats[6]);
 			printStats(_activeBox, 0);
-			_screen->printShadedText(_chargenStrings2[11], 149, 100, 9, 0);
+			_screen->printShadedText(_chargenStrings2[11], 149, 100, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 			if (!_vm->shouldQuit()) {
-				_vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, 15, 0, 8);
-				processNameInput(_activeBox, 2);
+				_vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColDarkRed);
+				processNameInput(_activeBox, _vm->guiSettings()->colors.menuTxtColBlue);
 			}
 		}
 	}
@@ -518,7 +523,7 @@ void CharacterGenerator::createPartyMember() {
 int CharacterGenerator::raceSexMenu() {
 	_screen->drawBox(_chargenBoxX[_activeBox], _chargenBoxY[_activeBox], _chargenBoxX[_activeBox] + 32, _chargenBoxY[_activeBox] + 33, 12);
 	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[8], 147, 67, 9, 0);
+	_screen->printShadedText(_chargenStrings2[8], 147, 67, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_vm->removeInputTop();
 
 	_vm->_gui->simpleMenu_setup(1, 0, _chargenRaceSexStrings, -1, 0, 0);
@@ -545,7 +550,7 @@ int CharacterGenerator::classMenu(int raceSex) {
 	updateMagicShapes();
 
 	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[9], 147, 67, 9, 0);
+	_screen->printShadedText(_chargenStrings2[9], 147, 67, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	toggleSpecialButton(5, 0, 0);
 
@@ -593,7 +598,7 @@ int CharacterGenerator::alignmentMenu(int cClass) {
 	updateMagicShapes();
 
 	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[10], 147, 67, 9, 0);
+	_screen->printShadedText(_chargenStrings2[10], 147, 67, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	toggleSpecialButton(5, 0, 0);
 
@@ -918,24 +923,24 @@ void CharacterGenerator::printStats(int index, int mode) {
 	if (mode != 4)
 		_screen->drawShape(2, c->faceShape, 224, 2, 0);
 
-	_screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, 15, 0);
-	_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, 15, 0);
-	_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, 15, 0);
+	_screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	for (int i = 0; i < 6; i++)
-		_screen->printShadedText(_chargenStatStrings[i], 163, (i + 8) << 3, 15, 0);
+		_screen->printShadedText(_chargenStatStrings[i], 163, (i + 8) << 3, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
-	_screen->printShadedText(_chargenStrings1[2], 248, 64, 15, 0);
+	_screen->printShadedText(_chargenStrings1[2], 248, 64, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	Common::String str = Common::String::format(_chargenStrings1[3], _vm->getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), c->intelligenceCur, c->wisdomCur, c->dexterityCur, c->constitutionCur, c->charismaCur);
-	_screen->printShadedText(str.c_str(), 192, 64, 15, 0);
+	_screen->printShadedText(str.c_str(), 192, 64, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	str = Common::String::format(_chargenStrings1[4], c->armorClass, c->hitPointsMax);
-	_screen->printShadedText(str.c_str(), 280, 64, 15, 0);
+	_screen->printShadedText(str.c_str(), 280, 64, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	const char *lvlStr = c->level[2] ? _chargenStrings1[7] : (c->level[1] ? _chargenStrings1[6] : _chargenStrings1[5]);
 	str = Common::String::format(lvlStr, c->level[0], c->level[1], c->level[2]);
-	_screen->printShadedText(str.c_str(), 280, 80, 15, 0);
+	_screen->printShadedText(str.c_str(), 280, 80, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	switch (mode) {
 	case 1:
@@ -970,7 +975,7 @@ void CharacterGenerator::printStats(int index, int mode) {
 
 void CharacterGenerator::processNameInput(int index, int textColor) {
 	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
-	_screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, 12);
+	_screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, _vm->guiSettings()->colors.menuTxtColBlack);
 	int xOffs = (60 - _screen->getTextWidth(_characters[index].name)) >> 1;
 	_screen->printText(_characters[index].name, _chargenNameFieldX[index] + xOffs, _chargenNameFieldY[index], textColor, 0);
 	_screen->updateScreen();
@@ -1005,7 +1010,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 	Common::String statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
 
 	_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, 6, 0);
+	_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->updateScreen();
 
 	EoBCharacter *c = &_characters[_activeBox];
@@ -1084,7 +1089,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 		statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
 
 		_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, 6, 0);
+		_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 		_screen->updateScreen();
 
 		if (index == 4) {
@@ -1096,7 +1101,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 			if (c->hitPointsCur != oldVal) {
 				statStr = Common::String::format("%d", c->hitPointsCur);
 				_screen->copyRegion(120, 72, 264, 136, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
-				_screen->printShadedText(statStr.c_str(), 264, 136, 15, 0);
+				_screen->printShadedText(statStr.c_str(), 264, 136, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 				_screen->updateScreen();
 			}
 
@@ -1107,14 +1112,14 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 			if (c->armorClass != oldVal) {
 				statStr = Common::String::format("%d", c->armorClass);
 				_screen->copyRegion(120, 64, 264, 128, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
-				_screen->printShadedText(statStr.c_str(), 264, 128, 15, 0);
+				_screen->printShadedText(statStr.c_str(), 264, 128, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 				_screen->updateScreen();
 			}
 		}
 
 		if (loop == false) {
 			statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
-			_screen->printText(statStr.c_str(), b->x + 32, b->y, 15, 0);
+			_screen->printText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.menuTxtColWhite, 0);
 			_screen->updateScreen();
 		}
 	}
@@ -1167,7 +1172,7 @@ int CharacterGenerator::getMinHp(int cclass, int constitution, int level1, int l
 void CharacterGenerator::finish() {
 	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
 	int cp = _screen->setCurPage(2);
-	_screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, 15, 0);
+	_screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->setCurPage(cp);
 	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
@@ -1626,8 +1631,8 @@ int TransferPartyWiz::selectCharactersMenu() {
 	_screen->clearCurPage();
 
 	_vm->gui_drawBox(0, 0, 320, 163, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
-	_screen->printText(_strings2[0], 5, 3, 15, 0);
-	_screen->printText(_strings2[1], 5, 10, 15, 0);
+	_screen->printText(_strings2[0], 5, 3, _vm->guiSettings()->colors.menuTxtColWhite, 0);
+	_screen->printText(_strings2[1], 5, 10, _vm->guiSettings()->colors.menuTxtColWhite, 0);
 
 	for (int i = 0; i < 6; i++)
 		drawCharPortraitWithStats(i, 0);
@@ -1635,8 +1640,8 @@ int TransferPartyWiz::selectCharactersMenu() {
 	_vm->gui_drawBox(4, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
 	_vm->gui_drawBox(272, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
 
-	_screen->printShadedText(_labels[0], 9, 151, 15, 0);
-	_screen->printShadedText(_labels[1], 288, 151, 15, 0);
+	_screen->printShadedText(_labels[0], 9, 151, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_labels[1], 288, 151, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	_screen->setCurPage(0);
 	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
@@ -1715,7 +1720,7 @@ int TransferPartyWiz::selectCharactersMenu() {
 		if (count == 4 || _vm->shouldQuit())
 			loop = false;
 		else
-			_vm->_gui->messageDialogue(16, count < 4 ? 69 : 70, 6);
+			_vm->_gui->messageDialogue(16, count < 4 ? 69 : 70, _vm->guiSettings()->colors.menuTxtColLightRed);
 
 		_screen->updateScreen();
 	}
@@ -1724,7 +1729,7 @@ int TransferPartyWiz::selectCharactersMenu() {
 	if (_vm->shouldQuit())
 		return 0;
 	else
-		_vm->_gui->messageDialogue(16, 71, 6);
+		_vm->_gui->messageDialogue(16, 71, _vm->guiSettings()->colors.menuTxtColLightRed);
 
 	return selection;
 }
@@ -1742,17 +1747,17 @@ void TransferPartyWiz::drawCharPortraitWithStats(int charIndex, bool enabled) {
 
 	_screen->drawShape(_screen->_curPage, c->faceShape, x + 4, y + 25, 0);
 
-	int color1 = 15;
-	int color2 = 12;
+	int color1 = _vm->guiSettings()->colors.menuTxtColWhite;
+	int color2 = _vm->guiSettings()->colors.menuTxtColBlack;
 
 	if (enabled) {
-		color1 = 6;
-		color2 = 15;
+		color1 = _vm->guiSettings()->colors.menuTxtColLightRed;
+		color2 = _vm->guiSettings()->colors.menuTxtColWhite;
 	} else {
 		_screen->drawShape(_screen->_curPage, _vm->_disabledCharGrid, x + 4, y + 25, 0);
 	}
 
-	_screen->printShadedText(c->name, x + 44, y + 27, color1, 0);
+	_screen->printShadedText(c->name, x + 44, y + 27, color1, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->printText(_vm->_chargenRaceSexStrings[c->raceSex], x + 43, y + 36, color2, 0);
 	_screen->printText(_vm->_chargenClassStrings[c->cClass], x + 43, y + 43, color2, 0);
 
@@ -1765,7 +1770,7 @@ void TransferPartyWiz::drawCharPortraitWithStats(int charIndex, bool enabled) {
 void TransferPartyWiz::updateHighlight(int index) {
 	static const int16 xPos[] = { 9, 288 };
 	if (_highlight > 5 && _highlight != index)
-		_screen->printText(_labels[_highlight - 6], xPos[_highlight - 6], 151, 15, 0);
+		_screen->printText(_labels[_highlight - 6], xPos[_highlight - 6], 151, _vm->guiSettings()->colors.menuTxtColWhite, 0);
 
 	if (index < 6) {
 		_vm->_gui->updateBoxFrameHighLight(14 + index);
@@ -1779,7 +1784,7 @@ void TransferPartyWiz::updateHighlight(int index) {
 	if (_highlight < 6)
 		_vm->_gui->updateBoxFrameHighLight(-1);
 
-	_screen->printText(_labels[index - 6], xPos[index - 6], 151, 6, 0);
+	_screen->printText(_labels[index - 6], xPos[index - 6], 151, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
 	_screen->updateScreen();
 	_highlight = index;
 }
diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index 4978164..e3b151b 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -395,8 +395,8 @@ void DarkMoonEngine::restParty_npc() {
 	gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1);
 	gui_drawBox((_screen->_curDim->sx << 3) + 1, _screen->_curDim->sy + 1, (_screen->_curDim->w << 3) - 2, _screen->_curDim->h - 2, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
 	_screen->set16bitShadingLevel(0);
-	_gui->messageDialogue2(11, 63, 6);
-	_gui->messageDialogue2(11, 64, 6);
+	_gui->messageDialogue2(11, 63, guiSettings()->colors.menuTxtColLightRed);
+	_gui->messageDialogue2(11, 64, guiSettings()->colors.menuTxtColLightRed);
 }
 
 bool DarkMoonEngine::restParty_extraAbortCondition() {
@@ -490,7 +490,7 @@ void DarkMoonEngine::characterLevelGain(int charIndex) {
 	}
 }
 
-const KyraRpgGUISettings *DarkMoonEngine::guiSettings() {
+const KyraRpgGUISettings *DarkMoonEngine::guiSettings() const {
 	return (_flags.platform == Common::kPlatformFMTowns) ? &_guiSettingsFMTowns : &_guiSettingsDOS;
 }
 
diff --git a/engines/kyra/engine/darkmoon.h b/engines/kyra/engine/darkmoon.h
index d1012db..ab8d93f 100644
--- a/engines/kyra/engine/darkmoon.h
+++ b/engines/kyra/engine/darkmoon.h
@@ -120,7 +120,7 @@ private:
 	int charSelectDialogue();
 	void characterLevelGain(int charIndex);
 
-	const KyraRpgGUISettings *guiSettings();
+	const KyraRpgGUISettings *guiSettings() const;
 
 	const char *const *_hornStrings;
 	const uint8 *_hornSounds;
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index b1cf500..25ab86d 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -567,8 +567,13 @@ void EoBEngine::healParty() {
 	}
 }
 
-const KyraRpgGUISettings *EoBEngine::guiSettings() {
-	return (_configRenderMode == Common::kRenderCGA || _configRenderMode == Common::kRenderEGA) ? &_guiSettingsEGA : &_guiSettingsVGA;
+const KyraRpgGUISettings *EoBEngine::guiSettings() const {
+	if (_flags.platform == Common::kPlatformAmiga)
+		return &_guiSettingsAmiga;
+	else if (_configRenderMode == Common::kRenderCGA || _configRenderMode == Common::kRenderEGA)
+		return &_guiSettingsEGA;
+	else
+		return &_guiSettingsVGA;
 }
 
 } // End of namespace Kyra
diff --git a/engines/kyra/engine/eob.h b/engines/kyra/engine/eob.h
index 0eb8fd3..896f332 100644
--- a/engines/kyra/engine/eob.h
+++ b/engines/kyra/engine/eob.h
@@ -111,10 +111,11 @@ private:
 	int resurrectionSelectDialogue();
 	void healParty();
 
-	const KyraRpgGUISettings *guiSettings();
+	const KyraRpgGUISettings *guiSettings() const;
 
 	static const KyraRpgGUISettings _guiSettingsVGA;
 	static const KyraRpgGUISettings _guiSettingsEGA;
+	static const KyraRpgGUISettings _guiSettingsAmiga;
 	static const uint8 _egaDefaultPalette[];
 };
 
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index e6e01ff..bf991c9 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -33,18 +33,17 @@
 #include "common/config-manager.h"
 #include "common/translation.h"
 
+#include "gui/error.h"
+
 #include "backends/keymapper/keymapper.h"
 
 namespace Kyra {
 
 const char *const EoBCoreEngine::kKeymapName = "eob";
 
-EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags)
-	: KyraRpgEngine(system, flags), _numLargeItemShapes(flags.gameID == GI_EOB1 ? 14 : 11),
-	  _numSmallItemShapes(flags.gameID == GI_EOB1 ? 23 : 26),
-	  _numThrownItemShapes(flags.gameID == GI_EOB1 ? 12 : 9),
-	  _numItemIconShapes(flags.gameID == GI_EOB1 ? 89 : 112),
-	  _teleporterWallId(flags.gameID == GI_EOB1 ? 52 : 44) {
+EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgEngine(system, flags), _numLargeItemShapes(flags.gameID == GI_EOB1 ? 14 : 11),
+	_numSmallItemShapes(flags.gameID == GI_EOB1 ? 23 : 26),	_numThrownItemShapes(flags.gameID == GI_EOB1 ? 12 : 9),
+	_numItemIconShapes(flags.gameID == GI_EOB1 ? 89 : 112),	_teleporterWallId(flags.gameID == GI_EOB1 ? 52 : 44) {
 
 	_screen = 0;
 	_gui = 0;
@@ -436,10 +435,27 @@ Common::Error EoBCoreEngine::init() {
 	assert(_debugger);
 
 	if (_flags.platform == Common::kPlatformAmiga) {
+		bool showErrorDlg = false;
 		if (_res->exists("EOBF6.FONT"))
 			_screen->loadFont(Screen::FID_6_FNT, "EOBF6.FONT");
+		else if (_res->exists("FONTS/EOBF6.FONT"))
+			_screen->loadFont(Screen::FID_6_FNT, "FONTS/EOBF6.FONT");
+		else
+			showErrorDlg = true;
+
 		if (_res->exists("EOBF8.FONT"))
 			_screen->loadFont(Screen::FID_8_FNT, "EOBF8.FONT");
+		else if (_res->exists("FONTS/EOBF8.FONT"))
+			_screen->loadFont(Screen::FID_8_FNT, "FONTS/EOBF8.FONT");
+		else
+			showErrorDlg = true;
+
+		if (showErrorDlg) {
+			::GUI::displayErrorDialog("This AMIGA version requires the following font files:\n\nEOBF6.FONT\nEOBF6/6\nEOBF8.FONT\nEOBF8/8\n\n"
+				"If you used the orginal installer for the installation these files\nshould be located in the AmigaDOS system 'Fonts/' folder.\n"
+				"Please copy them into the EOB game data directory.\n");
+			error("Failed to load font files.");
+		}
 	} else {
 		_screen->loadFont(Screen::FID_6_FNT, "FONT6.FNT");
 		_screen->loadFont(Screen::FID_8_FNT, "FONT8.FNT");
@@ -1863,11 +1879,11 @@ bool EoBCoreEngine::checkPassword() {
 		const uint8 *shp = (_mnDef[c << 2] < _numLargeItemShapes) ? _largeItemShapes[_mnDef[c << 2]] : (_mnDef[c << 2] < 15 ? 0 : _smallItemShapes[_mnDef[c << 2] - 15]);
 		assert(shp);
 		_screen->drawShape(0, shp, 100, 2, 13);
-		_screen->printShadedText(Common::String::format(_mnPrompt[0], _mnDef[(c << 2) + 1], _mnDef[(c << 2) + 2]).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy, _screen->_curDim->unk8, guiSettings()->colors.fill);
+		_screen->printShadedText(Common::String::format(_mnPrompt[0], _mnDef[(c << 2) + 1], _mnDef[(c << 2) + 2]).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.fill, guiSettings()->colors.menuTxtColBlack);
 		memset(answ, 0, 20);
 		gui_drawBox(76, 100, 133, 14, guiSettings()->colors.frame2, guiSettings()->colors.frame1, -1);
 		gui_drawBox(77, 101, 131, 12, guiSettings()->colors.frame2, guiSettings()->colors.frame1, -1);
-		if (_gui->getTextInput(answ, 10, 103, 15, _screen->_curDim->unk8, guiSettings()->colors.fill, 8) < 0)
+		if (_gui->getTextInput(answ, 10, 103, 15, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.fill, guiSettings()->colors.menuTxtColDarkRed) < 0)
 			i = 3;
 		if (!scumm_stricmp(_mnWord[c], answ))
 			break;
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 38bdae0..74e8ad4 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -682,7 +682,7 @@ protected:
 	void gui_drawFoodStatusGraph(int index);
 	void gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2);
 	void gui_drawCharPortraitStatusFrame(int index);
-	void gui_drawInventoryItem(int slot, int special, int pageNum);
+	void gui_drawInventoryItem(int slot, int redraw, int pageNum);
 	void gui_drawCompass(bool force);
 	void gui_drawDialogueBox();
 	void gui_drawSpellbook();
diff --git a/engines/kyra/engine/kyra_rpg.h b/engines/kyra/engine/kyra_rpg.h
index a446c87..0e04c77 100644
--- a/engines/kyra/engine/kyra_rpg.h
+++ b/engines/kyra/engine/kyra_rpg.h
@@ -97,7 +97,7 @@ struct KyraRpgGUISettings {
 		uint8 frame2;
 		int fill;
 
-		uint8 unused;
+		uint8 sfill;
 		uint8 barGraph;
 
 		uint8 warningFrame1;
@@ -111,6 +111,13 @@ struct KyraRpgGUISettings {
 		uint8 inactiveTabFrame1;
 		uint8 inactiveTabFrame2;
 		int inactiveTabFill;
+
+		uint8 menuTxtColWhite;
+		uint8 menuTxtColLightRed;
+		uint8 menuTxtColDarkRed;
+		uint8 menuTxtColLightBlue;
+		uint8 menuTxtColBlue;
+		uint8 menuTxtColBlack;
 	} colors;
 };
 
@@ -291,7 +298,7 @@ protected:
 
 	bool clickedShape(int shapeIndex);
 
-	virtual const KyraRpgGUISettings *guiSettings() = 0;
+	virtual const KyraRpgGUISettings *guiSettings() const = 0;
 
 	int _clickedShapeXOffs;
 	int _clickedShapeYOffs;
diff --git a/engines/kyra/engine/lol.cpp b/engines/kyra/engine/lol.cpp
index 9cf045a..c80d7fe 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -1977,7 +1977,7 @@ void LoLEngine::delay(uint32 millis, bool doUpdate, bool) {
 	}
 }
 
-const KyraRpgGUISettings *LoLEngine::guiSettings() {
+const KyraRpgGUISettings *LoLEngine::guiSettings() const {
 	return &_guiSettings;
 }
 
diff --git a/engines/kyra/engine/lol.h b/engines/kyra/engine/lol.h
index 14811d2..bbaae98 100644
--- a/engines/kyra/engine/lol.h
+++ b/engines/kyra/engine/lol.h
@@ -1151,7 +1151,7 @@ private:
 	// misc
 	void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false);
 
-	const KyraRpgGUISettings *guiSettings();
+	const KyraRpgGUISettings *guiSettings() const;
 
 	uint8 _compassBroken;
 	uint8 _drainMagic;
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index df859b0..c7bfec9 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -120,7 +120,8 @@ void Screen_EoB::setClearScreenDim(int dim) {
 }
 
 void Screen_EoB::clearCurDim() {
-	fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA);
+	static const uint8 amigaColorMap[16] = { 0x00, 0x06, 0x1d, 0x1b, 0x1a, 0x17, 0x18, 0x0e, 0x19, 0x1c, 0x1c, 0x1e, 0x13, 0x0a, 0x11, 0x1f };
+	fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _isAmiga ? amigaColorMap[_curDim->unkA] : _curDim->unkA);
 }
 
 void Screen_EoB::setMouseCursor(int x, int y, const byte *shape) {
diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index 7615241..3f7843e 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -83,12 +83,12 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 	static const uint16 charPortraitPosY[] = { 2, 54, 106 };
 
 	EoBCharacter *c = &_characters[index];
-	int txtCol1 = 12;
-	int txtCol2 = 15;
+	int txtCol1 = guiSettings()->colors.menuTxtColBlack;
+	int txtCol2 = guiSettings()->colors.menuTxtColWhite;
 
 	if ((_flags.gameID == GI_EOB1 && c->flags & 6) || (_flags.gameID == GI_EOB2 && c->flags & 0x0E)) {
-		txtCol1 = 8;
-		txtCol2 = 6;
+		txtCol1 = guiSettings()->colors.menuTxtColDarkRed;
+		txtCol2 = guiSettings()->colors.menuTxtColLightRed;
 	}
 
 	if (_currentControlMode == 0) {
@@ -101,7 +101,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		int cp = _screen->setCurPage(2);
 
 		if (index == _exchangeCharacterId)
-			_screen->printText(_characterGuiStringsSt[0], x2 + 2, y2 + 2, 8, guiSettings()->colors.fill);
+			_screen->printText(_characterGuiStringsSt[0], x2 + 2, y2 + 2, guiSettings()->colors.menuTxtColDarkRed, guiSettings()->colors.fill);
 		else
 			_screen->printText(c->name, x2 + 2, y2 + (_flags.platform == Common::kPlatformFMTowns ? 1 : 2), txtCol1, guiSettings()->colors.fill);
 
@@ -116,7 +116,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		if (c->damageTaken > 0) {
 			_screen->drawShape(2, _redSplatShape, x2 + 13, y2 + 30, 0);
 			Common::String tmpStr = Common::String::format("%d", c->damageTaken);
-			_screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, (_configRenderMode == Common::kRenderCGA) ? 12 : 15, 0);
+			_screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, (_configRenderMode == Common::kRenderCGA) ? 12 : guiSettings()->colors.menuTxtColWhite, 0);
 		}
 
 		_screen->setCurPage(cp);
@@ -130,23 +130,23 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		_screen->copyRegion(176, 0, 0, 0, 144, 168, 2, 2, Screen::CR_NO_P_CHECK);
 		_screen->_curPage = 2;
 		gui_drawFaceShape(index);
-		_screen->printShadedText(c->name, 219, 6, txtCol2, guiSettings()->colors.fill);
+		_screen->printShadedText(c->name, 219, 6, txtCol2, 0, guiSettings()->colors.menuTxtColBlack);
 		gui_drawHitpoints(index);
 		gui_drawFoodStatusGraph(index);
 
 		if (_currentControlMode == 1) {
 			if (c->hitPointsCur == -10)
-				_screen->printShadedText(_characterGuiStringsSt[1], 247, 158, 6, guiSettings()->colors.extraFill);
+				_screen->printShadedText(_characterGuiStringsSt[1], 247, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->hitPointsCur < 1)
-				_screen->printShadedText(_characterGuiStringsSt[2], 226, 158, 6, guiSettings()->colors.extraFill);
+				_screen->printShadedText(_characterGuiStringsSt[2], 226, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->effectFlags & (_flags.gameID == GI_EOB1 ? 0x80 : 0x2000))
-				_screen->printShadedText(_characterGuiStringsSt[3], 220, 158, 6, guiSettings()->colors.extraFill);
+				_screen->printShadedText(_characterGuiStringsSt[3], 220, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->flags & 2)
-				_screen->printShadedText(_characterGuiStringsSt[4], 235, 158, 6, guiSettings()->colors.extraFill);
+				_screen->printShadedText(_characterGuiStringsSt[4], 235, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->flags & 4)
-				_screen->printShadedText(_characterGuiStringsSt[5], 232, 158, 6, guiSettings()->colors.extraFill);
+				_screen->printShadedText(_characterGuiStringsSt[5], 232, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->flags & 8)
-				_screen->printShadedText(_characterGuiStringsSt[6], 232, 158, 6, guiSettings()->colors.extraFill);
+				_screen->printShadedText(_characterGuiStringsSt[6], 232, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 
 			for (int i = 0; i < 27; i++)
 				gui_drawInventoryItem(i, 0, 2);
@@ -159,38 +159,38 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 			static const uint16 cm2Y2[] = { 165, 165, 147 };
 
 			for (int i = 0; i < 3; i++)
-				_screen->fillRect(cm2X1[i], cm2Y1[i], cm2X2[i], cm2Y2[i], guiSettings()->colors.extraFill);
+				_screen->fillRect(cm2X1[i], cm2Y1[i], cm2X2[i], cm2Y2[i], guiSettings()->colors.sfill);
 
-			_screen->printShadedText(_characterGuiStringsIn[0], 183, 42, 15, guiSettings()->colors.extraFill);
-			_screen->printText(_chargenClassStrings[c->cClass], 183, 55, 12, guiSettings()->colors.extraFill);
-			_screen->printText(_chargenAlignmentStrings[c->alignment], 183, 62, 12, guiSettings()->colors.extraFill);
-			_screen->printText(_chargenRaceSexStrings[c->raceSex], 183, 69, 12, guiSettings()->colors.extraFill);
+			_screen->printShadedText(_characterGuiStringsIn[0], 183, 42, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+			_screen->printText(_chargenClassStrings[c->cClass], 183, 55, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+			_screen->printText(_chargenAlignmentStrings[c->alignment], 183, 62, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+			_screen->printText(_chargenRaceSexStrings[c->raceSex], 183, 69, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
 
 			for (int i = 0; i < 6; i++)
-				_screen->printText(_chargenStatStrings[6 + i], 183, 82 + i * 7, 12, guiSettings()->colors.extraFill);
+				_screen->printText(_chargenStatStrings[6 + i], 183, 82 + i * 7, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
 
-			_screen->printText(_characterGuiStringsIn[1], 183, 124, 12, guiSettings()->colors.extraFill);
-			_screen->printText(_characterGuiStringsIn[2], 239, 138, 12, guiSettings()->colors.extraFill);
-			_screen->printText(_characterGuiStringsIn[3], 278, 138, 12, guiSettings()->colors.extraFill);
+			_screen->printText(_characterGuiStringsIn[1], 183, 124, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+			_screen->printText(_characterGuiStringsIn[2], 239, 138, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+			_screen->printText(_characterGuiStringsIn[3], 278, 138, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
 
-			_screen->printText(getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), 275, 82, 15, guiSettings()->colors.extraFill);
-			_screen->printText(Common::String::format("%d", c->intelligenceCur).c_str(), 275, 89, 15, guiSettings()->colors.extraFill);
-			_screen->printText(Common::String::format("%d", c->wisdomCur).c_str(), 275, 96, 15, guiSettings()->colors.extraFill);
-			_screen->printText(Common::String::format("%d", c->dexterityCur).c_str(), 275, 103, 15, guiSettings()->colors.extraFill);
-			_screen->printText(Common::String::format("%d", c->constitutionCur).c_str(), 275, 110, 15, guiSettings()->colors.extraFill);
-			_screen->printText(Common::String::format("%d", c->charismaCur).c_str(), 275, 117, 15, guiSettings()->colors.extraFill);
-			_screen->printText(Common::String::format("%d", c->armorClass).c_str(), 275, 124, 15, guiSettings()->colors.extraFill);
+			_screen->printText(getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), 275, 82, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->intelligenceCur).c_str(), 275, 89, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->wisdomCur).c_str(), 275, 96, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->dexterityCur).c_str(), 275, 103, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->constitutionCur).c_str(), 275, 110, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->charismaCur).c_str(), 275, 117, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->armorClass).c_str(), 275, 124, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
 
 			for (int i = 0; i < 3; i++) {
 				int t = getCharacterClassType(c->cClass, i);
 				if (t == -1)
 					continue;
 
-				_screen->printText(_chargenClassStrings[t + 15], 180, 145 + 7 * i, 12, guiSettings()->colors.extraFill);
+				_screen->printText(_chargenClassStrings[t + 15], 180, 145 + 7 * i, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
 				Common::String tmpStr = Common::String::format("%d", c->experience[i]);
-				_screen->printText(tmpStr.c_str(), 251 - tmpStr.size() * 3, 145 + 7 * i, 15, guiSettings()->colors.extraFill);
+				_screen->printText(tmpStr.c_str(), 251 - tmpStr.size() * 3, 145 + 7 * i, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
 				tmpStr = Common::String::format("%d", c->level[i]);
-				_screen->printText(tmpStr.c_str(), 286 - tmpStr.size() * 3, 145 + 7 * i, 15, guiSettings()->colors.extraFill);
+				_screen->printText(tmpStr.c_str(), 286 - tmpStr.size() * 3, 145 + 7 * i, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
 			}
 		}
 
@@ -323,7 +323,7 @@ void EoBCoreEngine::gui_drawWeaponSlotStatus(int x, int y, int status) {
 		break;
 	}
 
-	int textColor = (_configRenderMode == Common::kRenderCGA) ? 2 : 15;
+	int textColor = (_configRenderMode == Common::kRenderCGA) ? 2 : guiSettings()->colors.menuTxtColWhite;
 
 	if (!tmpStr2.empty()) {
 		_screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 2, textColor, 0);
@@ -342,7 +342,9 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 
 	static const uint8 xCoords[] = { 23, 95 };
 	static const uint8 yCoords[] = { 46, 98, 150 };
-	static const uint8 barColor[] = { 3, 5, 8 };
+	static const uint8 barColorDefault[] = { 3, 5, 8 };
+	static const uint8 barColorAmiga[] = { 27, 7, 25 };
+	const uint8 *barColor = (_flags.platform == Common::kPlatformAmiga) ? barColorAmiga : barColorDefault;
 
 	int x = xCoords[index & 1];
 	int y = yCoords[index >> 1];
@@ -369,7 +371,7 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 			col = 2;
 
 		if (!_currentControlMode)
-			_screen->printText(_characterGuiStringsHp[0], x - 13, y - 1, 12, 0);
+			_screen->printText(_characterGuiStringsHp[0], x - 13, y - 1, guiSettings()->colors.menuTxtColBlack, 0);
 
 
 		gui_drawHorizontalBarGraph(x, y, w, h, bgCur, bgMax, barColor[col], guiSettings()->colors.barGraph);
@@ -382,7 +384,7 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 			y -= 1;
 		}
 
-		_screen->printText(tmpString.c_str(), x, y, 12, guiSettings()->colors.fill);
+		_screen->printText(tmpString.c_str(), x, y, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.fill);
 	}
 }
 
@@ -400,7 +402,11 @@ void EoBCoreEngine::gui_drawFoodStatusGraph(int index) {
 	if (index != _updateCharNum)
 		return;
 
-	uint8 col = c->food < 20 ? 8 : (c->food < 33 ? 5 : 3);
+	static const uint8 barColorDefault[] = { 3, 5, 8 };
+	static const uint8 barColorAmiga[] = { 27, 7, 25 };
+	const uint8 *barColor = (_flags.platform == Common::kPlatformAmiga) ? barColorAmiga : barColorDefault;
+
+	uint8 col = c->food < 20 ? barColor[2] : (c->food < 33 ? barColor[1] : barColor[0]);
 	gui_drawHorizontalBarGraph(250, 25, 51, 5, c->food, 100, col, guiSettings()->colors.barGraph);
 }
 
@@ -475,19 +481,22 @@ void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
 	}
 }
 
-void EoBCoreEngine::gui_drawInventoryItem(int slot, int special, int pageNum) {
+void EoBCoreEngine::gui_drawInventoryItem(int slot, int redraw, int pageNum) {
 	int x = _inventorySlotsX[slot];
 	int y = _inventorySlotsY[slot];
 
 	int item = _characters[_updateCharNum].inventory[slot];
 	int cp = _screen->setCurPage(pageNum);
 
-	if (special) {
+	if (redraw) {
 		int wh = (slot == 25 || slot == 26) ? 10 : 18;
 
 		uint8 col1 = guiSettings()->colors.frame1;
 		uint8 col2 = guiSettings()->colors.frame2;
-		if (_configRenderMode == Common::kRenderCGA) {
+		if (_flags.platform == Common::kPlatformAmiga) {
+			col1 = guiSettings()->colors.inactiveTabFrame1;
+			col2 = guiSettings()->colors.inactiveTabFrame2;
+		} else if (_configRenderMode == Common::kRenderCGA) {
 			col1 = 1;
 			col2 = 3;
 		}
@@ -495,11 +504,11 @@ void EoBCoreEngine::gui_drawInventoryItem(int slot, int special, int pageNum) {
 		gui_drawBox(x - 1, y - 1, wh, wh, col1, col2, slot == 16 ? -1 : guiSettings()->colors.fill);
 
 		if (slot == 16) {
-			_screen->fillRect(227, 65, 238, 69, 12);
+			_screen->fillRect(227, 65, 238, 69, guiSettings()->colors.menuTxtColBlack);
 			int cnt = countQueuedItems(_characters[_updateCharNum].inventory[slot], -1, -1, 1, 1);
 			x = cnt >= 10 ? 227 : 233;
 			Common::String str = Common::String::format("%d", cnt);
-			_screen->printText(str.c_str(), x, 65, 15, 0);
+			_screen->printText(str.c_str(), x, 65, guiSettings()->colors.menuTxtColWhite, 0);
 		}
 	}
 
@@ -557,20 +566,20 @@ void EoBCoreEngine::gui_drawSpellbook() {
 			col3 = guiSettings()->colors.inactiveTabFill;
 
 			if (i == _openBookSpellLevel) {
-				col1 =  guiSettings()->colors.frame1;
-				col2 =  guiSettings()->colors.frame2;
-				col3 =  guiSettings()->colors.fill;
+				col1 = guiSettings()->colors.frame1;
+				col2 = _flags.platform == Common::kPlatformAmiga ? 31 : guiSettings()->colors.frame2;
+				col3 = _flags.platform == Common::kPlatformAmiga ? guiSettings()->colors.frame2 : guiSettings()->colors.fill;
 			}
 		}
 
 		if (_flags.gameID == GI_EOB1) {
 			gui_drawBox(i * 21 + 71, 122, 21, 9, col1, col2, col3);
-			_screen->printText(_magicStrings7[i], i * 21 + 73, 123, 12, 0);
+			_screen->printText(_magicStrings7[i], i * 21 + 73, 123, guiSettings()->colors.menuTxtColBlack, 0);
 		} else {
 			_screen->set16bitShadingLevel(4);
 			gui_drawBox(i * 18 + 68, 121, 18, 9, col1, col2, col3);
 			_screen->set16bitShadingLevel(0);
-			_screen->printText(Common::String::format("%d", i + 1).c_str(), i * 18 + 75, 123, 12, 0);
+			_screen->printText(Common::String::format("%d", i + 1).c_str(), i * 18 + 75, 123, guiSettings()->colors.menuTxtColBlack, 0);
 		}
 	}
 
@@ -587,8 +596,8 @@ void EoBCoreEngine::gui_drawSpellbook() {
 		gui_drawSpellbookScrollArrow(165, 169, 1);
 	}
 
-	int textCol1 = (_configRenderMode == Common::kRenderCGA) ? 3 : 15;
-	int textCol2 = 8;
+	int textCol1 = (_configRenderMode == Common::kRenderCGA) ? 3 : guiSettings()->colors.menuTxtColWhite;
+	int textCol2 = guiSettings()->colors.menuTxtColDarkRed;
 	int textXa = 74;
 	int textXs = 71;
 	int textY = 170;
@@ -597,7 +606,7 @@ void EoBCoreEngine::gui_drawSpellbook() {
 	int col5 = 12;
 
 	if (_flags.gameID == GI_EOB1) {
-		textCol2 = (_configRenderMode == Common::kRenderCGA) ? 12 : 11;
+		textCol2 = (_configRenderMode == Common::kRenderCGA) ? 12 : (_flags.platform == Common::kPlatformAmiga ? 16 : 11);
 		textXa = textXs = 73;
 		textY = 168;
 		col4 = col3;
@@ -1414,7 +1423,13 @@ GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
 
 	_charSelectRedraw = false;
 
-	_highLightColorTable = (_vm->game() == GI_EOB1 && (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA)) ? _highlightColorTableEGA : _highlightColorTableVGA;
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+		_highLightColorTable = _highlightColorTableAmiga;
+	else if (_vm->game() == GI_EOB1 && (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA))
+		_highLightColorTable = _highlightColorTableEGA;
+	else
+		_highLightColorTable = _highlightColorTableVGA;
+
 	_updateBoxIndex = -1;
 	_highLightBoxTimer = 0;
 	_updateBoxColorIndex = 0;
@@ -1938,9 +1953,9 @@ void GUI_EoB::simpleMenu_setup(int sd, int maxItem, const char *const *strings,
 	for (int i = 0; i < _menuNumItems; i++) {
 		int item = simpleMenu_getMenuItem(i, menuItemsMask, itemOffset);
 		int ty = y + i * (lineSpacing + _screen->getFontHeight());
-		_screen->printShadedText(strings[item], x, ty, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : dm->unkA, 0);
+		_screen->printShadedText(strings[item], x, ty, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 		if (item == v)
-			_screen->printText(strings[item], x, ty, dm->unkC, 0);
+			_screen->printText(strings[item], x, ty, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
 	}
 
 	_screen->updateScreen();
@@ -1991,14 +2006,14 @@ int GUI_EoB::simpleMenu_process(int sd, const char *const *strings, void *b, int
 	}
 
 	if (newItem != currentItem) {
-		_screen->printText(strings[simpleMenu_getMenuItem(currentItem, menuItemsMask, itemOffset)], x, y + currentItem * lineH, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : dm->unkA, 0);
-		_screen->printText(strings[simpleMenu_getMenuItem(newItem,  menuItemsMask, itemOffset)], x, y + newItem * lineH , dm->unkC, 0);
+		_screen->printText(strings[simpleMenu_getMenuItem(currentItem, menuItemsMask, itemOffset)], x, y + currentItem * lineH, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite, 0);
+		_screen->printText(strings[simpleMenu_getMenuItem(newItem,  menuItemsMask, itemOffset)], x, y + newItem * lineH , _vm->guiSettings()->colors.menuTxtColLightRed, 0);
 		_screen->updateScreen();
 	}
 
 	if (result != -1) {
 		result = simpleMenu_getMenuItem(result, menuItemsMask, itemOffset);
-		simpleMenu_flashSelection(strings[result], x, y + newItem * lineH, dm->unkA, dm->unkC, 0);
+		simpleMenu_flashSelection(strings[result], x, y + newItem * lineH, _vm->guiSettings()->colors.menuTxtColWhite, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
 	}
 
 	_menuCur = newItem;
@@ -2292,10 +2307,10 @@ bool GUI_EoB::runLoadMenu(int x, int y) {
 			runLoop = result = false;
 		} else if (slot >= 0) {
 			if (_saveSlotIdTemp[slot] == -1) {
-				messageDialogue(11, 65, 6);
+				messageDialogue(11, 65, _vm->guiSettings()->colors.menuTxtColLightRed);
 			} else {
 				if (_vm->loadGameState(_saveSlotIdTemp[slot]).getCode() != Common::kNoError)
-					messageDialogue(11, 16, 6);
+					messageDialogue(11, 16, _vm->guiSettings()->colors.menuTxtColLightRed);
 				runLoop = false;
 				result = true;
 			}
@@ -2355,7 +2370,7 @@ bool GUI_EoB::confirmDialogue2(int dim, int id, int deflt) {
 
 		if (newHighlight != lastHighlight) {
 			for (int i = 0; i < 2; i++)
-				_screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (_screen->getTextWidth(_vm->_menuYesNoStrings[i]) / 2) + 1, y + 3, i == newHighlight ? 6 : 15, 0);
+				_screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (_screen->getTextWidth(_vm->_menuYesNoStrings[i]) / 2) + 1, y + 3, i == newHighlight ? _vm->guiSettings()->colors.menuTxtColLightRed : _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 			_screen->updateScreen();
 			lastHighlight = newHighlight;
 		}
@@ -2387,7 +2402,7 @@ void GUI_EoB::messageDialogue(int dim, int id, int buttonTextCol) {
 	int bw = _screen->getTextWidth(_vm->_menuOkString) + 7;
 
 	drawMenuButtonBox(bx, by, bw, 14, false, false);
-	_screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0);
+	_screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->updateScreen();
 
 	for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
@@ -2418,7 +2433,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
 	_screen->_curPage = 2;
 	_screen->setClearScreenDim(dim);
 	drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
-	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx << 3) + 5, _screen->_curDim->sy + 5, 15, 0);
+	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx << 3) + 5, _screen->_curDim->sy + 5, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->_curPage = 0;
 	_screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK);
 
@@ -2426,7 +2441,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
 	int y = _screen->_curDim->sy + _screen->_curDim->h - 21;
 	int w = _screen->getTextWidth(_vm->_menuOkString) + 8;
 	drawMenuButtonBox(x, y, w, 14, false, false);
-	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0);
+	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->updateScreen();
 
 	for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
@@ -2447,7 +2462,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
 	_screen->updateScreen();
 	_vm->_system->delayMillis(80);
 	drawMenuButtonBox(x, y, w, 14, false, false);
-	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0);
+	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->updateScreen();
 
 }
@@ -2504,7 +2519,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 	_screen->copyRegion((x - 1) << 3, y, 0, 191, (destMaxLen + 2) << 3, 9, 0, 2, Screen::CR_NO_P_CHECK);
 	if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
 		_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(dest, x << 3, y, textColor1, textColor2);
+	_screen->printShadedText(dest, x << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	uint32 next = _vm->_system->getMillis() + 2 * _vm->_tickLength;
 	sufx[0] = (pos < len) ? dest[pos] : 32;
@@ -2523,7 +2538,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 			if (next <= _vm->_system->getMillis()) {
 				if (cursorState) {
 					_screen->copyRegion((pos + 1) << 3, 191, (x + pos) << 3, y, 8, 9, 2, 0, Screen::CR_NO_P_CHECK);
-					_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2);
+					_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
 				} else {
 					_screen->fillRect((x + pos) << 3, y, ((x + pos) << 3) + 7, y + 7, cursorColor);
 					_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
@@ -2638,7 +2653,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 		}
 
 		_screen->copyRegion(0, 191, (x - 1) << 3, y, (destMaxLen + 2) << 3, 9, 2, 0, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(dest, x << 3, y, textColor1, textColor2);
+		_screen->printShadedText(dest, x << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
 		
 		if (_vm->_flags.platform == Common::kPlatformFMTowns) {
 			if (pos < len) {
@@ -2655,7 +2670,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 		if (cursorState)
 			_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
 		else
-			_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2);
+			_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
 		_screen->updateScreen();
 
 	} while (_keyPressed.keycode != Common::KEYCODE_RETURN && _keyPressed.keycode != Common::KEYCODE_ESCAPE && !_vm->shouldQuit());
@@ -2689,7 +2704,7 @@ int GUI_EoB::checkKatakanaSelection() {
 
 			if (_csjis[0] != '\x81' || _csjis[1] != '\x40') {
 				highlight = lineOffs << 8 | column;
-				_screen->printShadedText(_csjis, x & ~7, y & ~15, 6, 0);
+				_screen->printShadedText(_csjis, x & ~7, y & ~15, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 			}
 
 			x = 288; y = 168;
@@ -2702,7 +2717,7 @@ int GUI_EoB::checkKatakanaSelection() {
 				continue;
 
 			highlight = 0x400 | i;
-			_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelXCrds[i], 176, 6, 0);
+			_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelXCrds[i], 176, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 			i = 3;
 		}
 	}
@@ -2718,13 +2733,13 @@ int GUI_EoB::checkKatakanaSelection() {
 
 	if (_menuCur != -1) {
 		if (_menuCur & 0x400) {
-			_screen->printShadedText(_vm->_katakanaSelectStrings[_menuCur & 3], kanaSelXCrds[_menuCur & 3], 176, 15, 0);
+			_screen->printShadedText(_vm->_katakanaSelectStrings[_menuCur & 3], kanaSelXCrds[_menuCur & 3], 176, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 		} else {
 			char osjis[3];
 			osjis[0] = _vm->_katakanaLines[_currentKanaPage * 4 + (_menuCur >> 8)][_menuCur & 0xFF];
 			osjis[1] = _vm->_katakanaLines[_currentKanaPage * 4 + (_menuCur >> 8)][(_menuCur & 0xFF) + 1];
 			osjis[2] = 0;
-			_screen->printShadedText(osjis, 152 + ((_menuCur & 0xFF) << 2), 112 + ((_menuCur >> 4) & ~0x0F), 15, 0);
+			_screen->printShadedText(osjis, 152 + ((_menuCur & 0xFF) << 2), 112 + ((_menuCur >> 4) & ~0x0F), _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 		}
 	}
 
@@ -2762,11 +2777,11 @@ void GUI_EoB::printKatakanaOptions(int page) {
 	_currentKanaPage = page;
 	_screen->copyRegion(160, 44, 144, 108, 160, 84, 2, 0, Screen::CR_NO_P_CHECK);
 	for (int i = 0; i < 4; i++)
-		_screen->printShadedText(_vm->_katakanaLines[page * 4 + i], 152, (i << 4) + 112, 15, 0);
+		_screen->printShadedText(_vm->_katakanaLines[page * 4 + i], 152, (i << 4) + 112, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	static uint16 kanaSelCrds[] = { 224, 272, 186 };
 	for (int i = 0; i < 3; i++)
-		_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelCrds[i], 176, 15, 0);
+		_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelCrds[i], 176, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 }
 
 void GUI_EoB::transferWaitBox() {
@@ -2833,7 +2848,7 @@ bool GUI_EoB::transferFileMenu(Common::String &targetName, Common::String &selec
 			break;
 
 		if (_saveSlotIdTemp[slot] == -1)
-			messageDialogue(11, 65, 6);
+			messageDialogue(11, 65, _vm->guiSettings()->colors.menuTxtColLightRed);
 		else {
 			_screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
 			selection = _vm->getSavegameFilename(targetName, _saveSlotIdTemp[slot]);
@@ -2904,7 +2919,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 					of = _vm->screen()->setFont(Screen::FID_6_FNT);
 					y++;
 				} else {
-					in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, 2, 0, 8);
+					in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, _vm->guiSettings()->colors.menuTxtColBlue, 0, _vm->guiSettings()->colors.menuTxtColDarkRed);
 				}
 				if (in == -1) {
 					useSlot = false;
@@ -2912,7 +2927,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 				}
 
 				if (!strlen(_saveSlotStringsTemp[slot])) {
-					messageDialogue(11, 54, 6);
+					messageDialogue(11, 54, _vm->guiSettings()->colors.menuTxtColLightRed);
 					in = -1;
 				}
 			}
@@ -2922,7 +2937,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 			}
 
 			_screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill);
-			_screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, 15, 0);
+			_screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 			_screen->set16bitShadingLevel(0);
 			_screen->setFont(of);
 			_screen->updateScreen();
@@ -2935,7 +2950,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 			if (err.getCode() == Common::kNoError)
 				result = true;
 			else
-				messageDialogue(11, 15, 6);
+				messageDialogue(11, 15, _vm->guiSettings()->colors.menuTxtColLightRed);
 
 			runLoop = false;
 		}
@@ -2947,14 +2962,14 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 
 int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
 	_saveSlotX = _saveSlotY = 0;
-	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite;
 	_screen->setCurPage(2);
 
 	_savegameOffset = 0;
 
 	drawMenuButtonBox(0, 0, 176, 144, false, false);
 	const char *title = (id < 2) ? _vm->_saveLoadStrings[2 + id] : _vm->_transferStringsScummVM[id - 1];
-	_screen->printShadedText(title, 52, 5, col1, 0);
+	_screen->printShadedText(title, 52, 5, col1, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	_screen->copyRegion(0, 0, x, y, 176, 144, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->setCurPage(0);
@@ -3033,11 +3048,11 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
 
 		if (lastHighlight != newHighlight) {
 			drawSaveSlotButton(lastHighlight, 0, col1);
-			drawSaveSlotButton(newHighlight, 0, 6);
+			drawSaveSlotButton(newHighlight, 0, _vm->guiSettings()->colors.menuTxtColLightRed);
 
 			// Display highlighted slot index in the bottom left corner to avoid people getting lost with the 990 save slots
 			_screen->setFont(Screen::FID_6_FNT);
-			int sli = (newHighlight == 6) ?  _savegameOffset : (_savegameOffset + newHighlight);
+			int sli = (newHighlight == 6) ? _savegameOffset : (_savegameOffset + newHighlight);
 			_screen->set16bitShadingLevel(4);
 			_screen->printText(Common::String::format("%03d/989", sli).c_str(), _saveSlotX + 5, _saveSlotY + 135, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
 			_screen->set16bitShadingLevel(0);
@@ -3048,10 +3063,10 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
 		}
 	}
 
-	drawSaveSlotButton(newHighlight, 2, 6);
+	drawSaveSlotButton(newHighlight, 2, _vm->guiSettings()->colors.menuTxtColLightRed);
 	_screen->updateScreen();
 	_vm->_system->delayMillis(80);
-	drawSaveSlotButton(newHighlight, 1, 6);
+	drawSaveSlotButton(newHighlight, 1, _vm->guiSettings()->colors.menuTxtColLightRed);
 	_screen->updateScreen();
 
 	return newHighlight;
@@ -3200,7 +3215,7 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) {
 		if (updateDesc) {
 			updateDesc = false;
 			_screen->set16bitShadingLevel(4);
-			_screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill);
+			_screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.menuTxtColBlack);
 			_screen->set16bitShadingLevel(0);
 		}
 
@@ -3393,7 +3408,7 @@ void GUI_EoB::scribeScrollDialogue() {
 						buttonList = initMenu(6);
 
 						for (int i = 0; i < s; i++)
-							_screen->printShadedText(_vm->_mageSpellList[menuItems[i]], 8, 9 * i + 50, 15, 0);
+							_screen->printShadedText(_vm->_mageSpellList[menuItems[i]], 8, 9 * i + 50, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 						redraw = false;
 						lastHighLight = -1;
@@ -3402,9 +3417,9 @@ void GUI_EoB::scribeScrollDialogue() {
 
 					if (lastHighLight != newHighLight) {
 						if (lastHighLight >= 0)
-							_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, 15, 0);
+							_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, _vm->guiSettings()->colors.menuTxtColWhite, 0);
 						lastHighLight = newHighLight;
-						_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, 6, 0);
+						_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
 						_screen->updateScreen();
 					}
 
@@ -3746,7 +3761,7 @@ bool GUI_EoB::confirmDialogue(int id) {
 
 	Button *buttonList = initMenu(5);
 
-	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 4, 15, 0);
+	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 4, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	int newHighlight = 0;
 	int lastHighlight = -1;
@@ -3968,7 +3983,7 @@ void GUI_EoB::displayTextBox(int id) {
 	const ScreenDim *dm = _screen->getScreenDim(11);
 
 	drawMenuButtonBox(dm->sx << 3, dm->sy, dm->w << 3, dm->h, false, false);
-	_screen->printShadedText(getMenuString(id), (dm->sx << 3) + 5, dm->sy + 5, 15, 0);
+	_screen->printShadedText(getMenuString(id), (dm->sx << 3) + 5, dm->sy + 5, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
 
@@ -3997,7 +4012,7 @@ Button *GUI_EoB::initMenu(int id) {
 		drawMenuButtonBox(dm->sx << 3, dm->sy, dm->w << 3, dm->h, false, false);
 	}
 
-	_screen->printShadedText(getMenuString(m->titleStrId), 5, 5, m->titleCol, 0);
+	_screen->printShadedText(getMenuString(m->titleStrId), 5, 5, m->titleCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	Button *buttons = 0;
 	for (int i = 0; i < m->numButtons; i++) {
@@ -4054,12 +4069,12 @@ void GUI_EoB::drawMenuButton(Button *b, bool clicked, bool highlight, bool noFil
 			yOffs = (b->height - 7) >> 1;
 		}
 
-		int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+		int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite;
 
 		if (noFill || clicked)
-			_screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : col1, 0);
+			_screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, 0);
 		else
-			_screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : col1, 0);
+			_screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	}
 }
 
@@ -4088,7 +4103,7 @@ void GUI_EoB::drawTextBox(int dim, int id) {
 	_screen->setCurPage(2);
 
 	drawMenuButtonBox(0, 0, dm->w << 3, dm->h, false, false);
-	_screen->printShadedText(getMenuString(id), 5, 5, 15, 0);
+	_screen->printShadedText(getMenuString(id), 5, 5, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 
 	_screen->setCurPage(0);
 	_screen->copyRegion(0, 0, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
@@ -4122,7 +4137,7 @@ void GUI_EoB::drawSaveSlotButton(int slot, int redrawBox, int textCol) {
 		y++;
 	}
 
-	_screen->printShadedText(slotString, x + 4, y + 3, textCol, 0);
+	_screen->printShadedText(slotString, x + 4, y + 3, textCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	_vm->screen()->setFont(fnt);
 }
 
@@ -4131,7 +4146,7 @@ void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int sp
 		return;
 
 	int y = bookPageIndex * 9 + 50;
-	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite;
 	_screen->set16bitShadingLevel(4);
 
 	if (spellId) {
@@ -4146,9 +4161,9 @@ void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int sp
 		}
 
 		if (noFill)
-			_screen->printText(s.c_str(), 8, y, highLight ? 6 : col1, 0);
+			_screen->printText(s.c_str(), 8, y, highLight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, 0);
 		else
-			_screen->printShadedText(s.c_str(), 8, y, highLight ? 6 : col1, _vm->guiSettings()->colors.fill);
+			_screen->printShadedText(s.c_str(), 8, y, highLight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.menuTxtColBlack);
 	} else {
 		_screen->fillRect(6, y, 168, y + 8,  _vm->guiSettings()->colors.fill);
 	}
@@ -4293,13 +4308,13 @@ void GUI_EoB::restParty_updateRestTime(int hours, bool init) {
 		_vm->_txt->clearCurDim();
 		drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
 		_screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 0, 2, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0);
+		_screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0, _vm->guiSettings()->colors.menuTxtColBlack);
 	}
 
 	_screen->setCurPage(0);
 	_screen->set16bitShadingLevel(4);
 	_screen->fillRect((_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, ((_screen->_curDim->sx + 19) << 3) + 1, _screen->_curDim->sy + 29, _vm->guiSettings()->colors.fill);
-	_screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, 15, _vm->guiSettings()->colors.fill);
+	_screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, _vm->guiSettings()->colors.menuTxtColWhite, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.menuTxtColBlack);
 	_screen->set16bitShadingLevel(0);
 	_screen->updateScreen();
 	_vm->delay(160);
@@ -4334,6 +4349,8 @@ const uint8 GUI_EoB::_highlightColorTableVGA[] = { 0x0F, 0xB0, 0xB2, 0xB4, 0xB6,
 
 const uint8 GUI_EoB::_highlightColorTableEGA[] = { 0x0C, 0x0D, 0x0E, 0x0F, 0x0E, 0x0D, 0x00 };
 
+const uint8 GUI_EoB::_highlightColorTableAmiga[] = { 0x13, 0x0B, 0x12, 0x0A, 0x11, 0x09, 0x11, 0x0A, 0x12, 0x0B, 0x00 };
+
 } // End of namespace Kyra
 
 #endif // ENABLE_EOB
diff --git a/engines/kyra/gui/gui_eob.h b/engines/kyra/gui/gui_eob.h
index eadb7b0..82721fc 100644
--- a/engines/kyra/gui/gui_eob.h
+++ b/engines/kyra/gui/gui_eob.h
@@ -154,6 +154,7 @@ private:
 	static const EoBRect16 _highlightFrames[];
 	static const uint8 _highlightColorTableVGA[];
 	static const uint8 _highlightColorTableEGA[];
+	static const uint8 _highlightColorTableAmiga[];
 
 	// FM-Towns specific
 	int checkKatakanaSelection();
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index eaa9112..35b0d2b 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -801,6 +801,12 @@ void EoBCoreEngine::initMenus() {
 		_menuDefs[2].numButtons = 4;
 		_menuDefs[2].firstButtonStrId = 44;
 	}
+
+	if (_flags.platform == Common::kPlatformAmiga) {
+		// assign Amiga text colors
+		_menuDefs[0].titleCol = _menuDefs[1].titleCol = _menuDefs[2].titleCol = _menuDefs[4].titleCol = _menuDefs[6].titleCol = guiSettings()->colors.menuTxtColLightBlue;
+		_menuDefs[3].titleCol = _menuDefs[5].titleCol = guiSettings()->colors.menuTxtColWhite;
+	}
 }
 
 
@@ -1287,12 +1293,17 @@ void EoBEngine::initSpells() {
 
 const KyraRpgGUISettings EoBEngine::_guiSettingsVGA = {
 	{ 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
-	{ 135, 130, 132, 133, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180 }
+	{ 135, 130, 132, 180, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180, 15, 6, 8, 9, 2, 12 }
 };
 
 const KyraRpgGUISettings EoBEngine::_guiSettingsEGA = {
 	{ 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
-	{ 13, 9, 2, 133, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14 }
+	{ 13, 9, 2, 14, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14, 15, 6, 8, 9, 2, 12 }
+};
+
+const KyraRpgGUISettings EoBEngine::_guiSettingsAmiga = {
+	{ 28, 31, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
+	{ 18, 17, 10, 17, 11, 24, 22, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 19 }
 };
 
 const uint8 EoBEngine::_egaDefaultPalette[] = {
@@ -1393,12 +1404,12 @@ void DarkMoonEngine::initSpells() {
 
 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsFMTowns = {
 	{ 9, 15, 95, 11, 7, { 221, 76 }, { 187, 162 }, { 95, 95 } },
-	{ 186, 181, 183, 133, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180 }
+	{ 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 12 }
 };
 
 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsDOS = {
 	{ 9, 15, 95, 9, 7, { 221, 76 }, { 189, 162 }, { 95, 95 } },
-	{ 186, 181, 183, 133, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180 }
+	{ 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 12 }
 };
 
 const uint8 DarkMoonEngine::_egaDefaultPalette[] = {
diff --git a/engines/kyra/resource/staticres_lol.cpp b/engines/kyra/resource/staticres_lol.cpp
index b4093ce..d2fbcef 100644
--- a/engines/kyra/resource/staticres_lol.cpp
+++ b/engines/kyra/resource/staticres_lol.cpp
@@ -779,7 +779,7 @@ const int8 LoLEngine::_mapCoords[12][4] = {
 
 const KyraRpgGUISettings LoLEngine::_guiSettings = {
 	{ 144, 254, 74, 9, 80, { 0, 0 }, { 0, 0 }, { 0, 0 } },
-	{ 136, 251, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+	{ 136, 251, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
 const MistOfDoomAnimData LoLEngine::_mistAnimData[] = {
diff --git a/engines/kyra/script/script_eob.cpp b/engines/kyra/script/script_eob.cpp
index 709921d..cc3fc0a 100644
--- a/engines/kyra/script/script_eob.cpp
+++ b/engines/kyra/script/script_eob.cpp
@@ -514,6 +514,7 @@ int EoBInfProcessor::oeob_moveInventoryItemToBlock(int8 *data) {
 }
 
 int EoBInfProcessor::oeob_printMessage_v1(int8 *data) {
+	static const uint8 amigaColorMap[16] = { 0x00, 0x06, 0x1d, 0x1b, 0x1a, 0x17, 0x18, 0x0e, 0x19, 0x1c, 0x1c, 0x1e, 0x13, 0x0a, 0x11, 0x1f };
 	static const char colorConfig[] = "\x6\x21\x2\x21";
 	char col[5];
 	int8 *pos = data;
@@ -524,11 +525,19 @@ int EoBInfProcessor::oeob_printMessage_v1(int8 *data) {
 
 	col[1] = *pos++;
 	col[3] = *pos++;
+
+	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
+		assert(col[1] < 16);
+		assert(col[3] < 16);
+		col[1] = amigaColorMap[col[1]];
+		col[3] = amigaColorMap[col[3]];
+	}
+
 	_vm->txt()->printMessage(col);
 	_vm->txt()->printMessage(str);
 
-	col[1] = _screen->_curDim->unk8;
-	col[3] = _screen->_curDim->unkA;
+	col[1] = _vm->txt()->colorMap()[_screen->_curDim->unk8];
+	col[3] = _vm->txt()->colorMap()[_screen->_curDim->unkA];
 	_vm->txt()->printMessage(col);
 	_vm->txt()->printMessage("\r");
 
@@ -1495,7 +1504,7 @@ int EoBInfProcessor::oeob_sequence(int8 *data) {
 		break;
 
 	case -1:
-		if (_vm->gameFlags().platform == Common::kPlatformDOS)
+		if (_vm->gameFlags().platform == Common::kPlatformDOS || _vm->gameFlags().platform == Common::kPlatformAmiga)
 			_vm->_runFlag = _vm->checkPassword();
 		break;
 
diff --git a/engines/kyra/sequence/sequences_eob.cpp b/engines/kyra/sequence/sequences_eob.cpp
index 7b3618f..a0b10e3 100644
--- a/engines/kyra/sequence/sequences_eob.cpp
+++ b/engines/kyra/sequence/sequences_eob.cpp
@@ -1041,25 +1041,42 @@ int EoBEngine::mainMenu() {
 	while (menuChoice >= 0 && !shouldQuit()) {
 		switch (menuChoice) {
 		case 0: {
-			if (_configRenderMode != Common::kRenderEGA)
-				_screen->loadPalette("EOBPAL.COL", _screen->getPalette(0));
-			_screen->loadEoBBitmap(_flags.platform == Common::kPlatformAmiga ? "TITLE" : "INTRO", _cgaMappingDefault, 5, 3, 2);
-			_screen->setScreenPalette(_screen->getPalette(0));
+			if (_flags.platform == Common::kPlatformAmiga) {
+				_screen->fadeToBlack(10);
+				_screen->loadEoBBitmap("TITLE", 0, 5, 3, 1);
+				_screen->fadeFromBlack(10);
+			} else {
+				if (_configRenderMode != Common::kRenderEGA)
+					_screen->loadPalette("EOBPAL.COL", _screen->getPalette(0));
+				_screen->loadEoBBitmap("INTRO", _cgaMappingDefault, 5, 3, 2);
+				_screen->setScreenPalette(_screen->getPalette(0));
+			}
+
 			_screen->_curPage = 2;
 			of = _screen->setFont(Screen::FID_6_FNT);
 			Common::String versionString(Common::String::format("ScummVM %s", gScummVMVersion));
 			_screen->printText(versionString.c_str(), 280 - versionString.size() * 6, 153, _screen->getPagePixel(2, 0, 0), 0);
 			_screen->setFont(of);
 			_screen->fillRect(0, 159, 319, 199, _screen->getPagePixel(2, 0, 0));
-			gui_drawBox(77, 165, 173, 29, 14, 13, 12);
-			gui_drawBox(76, 164, 175, 31, 14, 13, -1);
+
+			if (_flags.platform == Common::kPlatformAmiga) {
+				gui_drawBox(75, 165, 177, 29, 22, 28, -1);
+				gui_drawBox(74, 164, 179, 31, 22, 28, -1);
+			} else {
+				gui_drawBox(77, 165, 173, 29, 14, 13, 12);
+				gui_drawBox(76, 164, 175, 31, 14, 13, -1);
+			}
+
 			_screen->_curPage = 0;
 			_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
 			_screen->updateScreen();
+
 			_allowImport = true;
 			menuChoice = mainMenuLoop();
 			_allowImport = false;
-			} break;
+			}
+
+			break;
 
 		case 1:
 			// load game in progress
@@ -1081,10 +1098,13 @@ int EoBEngine::mainMenu() {
 			_sound->selectAudioResourceSet(kMusicIntro);
 			_sound->loadSoundFile(0);
 			_screen->hideMouse();
+
 			seq_playIntro();
+
 			_screen->showMouse();
 			_sound->selectAudioResourceSet(kMusicIngame);
 			_sound->loadSoundFile(0);
+
 			menuChoice = 0;
 			break;
 		}
diff --git a/engines/kyra/text/text_rpg.cpp b/engines/kyra/text/text_rpg.cpp
index 10e1a44..d865fc7 100644
--- a/engines/kyra/text/text_rpg.cpp
+++ b/engines/kyra/text/text_rpg.cpp
@@ -45,10 +45,22 @@ TextDisplayer_rpg::TextDisplayer_rpg(KyraRpgEngine *engine, Screen *scr) : _vm(e
 
 	_textDimData = new TextDimData[_screen->screenDimTableCount()];
 
+	for (int i = 0; i < 256; ++i)
+		_colorMap[i] = i;
+
+	if (_vm->game() != GI_LOL) {
+		_colorMap[15] = _vm->guiSettings()->colors.menuTxtColWhite;
+		_colorMap[6] = _vm->guiSettings()->colors.menuTxtColLightRed;
+		_colorMap[8] = _vm->guiSettings()->colors.menuTxtColDarkRed;
+		_colorMap[9] = _vm->guiSettings()->colors.menuTxtColLightBlue;
+		_colorMap[2] = _vm->guiSettings()->colors.menuTxtColBlue;
+		_colorMap[12] = _vm->guiSettings()->colors.menuTxtColBlack;
+	}
+
 	for (int i = 0; i < _screen->screenDimTableCount(); i++) {
 		const ScreenDim *d = _screen->getScreenDim(i);
-		_textDimData[i].color1 = d->unk8;
-		_textDimData[i].color2 = d->unkA;
+		_textDimData[i].color1 = _colorMap[d->unk8];
+		_textDimData[i].color2 = _colorMap[d->unkA];
 		_textDimData[i].line = d->unkC;
 		_textDimData[i].column = d->unkE;
 	}
@@ -554,8 +566,8 @@ void TextDisplayer_rpg::printMessage(const char *str, int textColor, ...) {
 int TextDisplayer_rpg::clearDim(int dim) {
 	int res = _screen->curDimIndex();
 	_screen->setScreenDim(dim);
-	_textDimData[dim].color1 = _screen->_curDim->unk8;
-	_textDimData[dim].color2 = _vm->game() == GI_LOL ? _screen->_curDim->unkA : _vm->guiSettings()->colors.fill;
+	_textDimData[dim].color1 = _colorMap[_screen->_curDim->unk8];
+	_textDimData[dim].color2 = (_vm->game() == GI_LOL || _vm->gameFlags().platform == Common::kPlatformAmiga) ? _colorMap[_screen->_curDim->unkA] : _vm->guiSettings()->colors.fill;
 	clearCurDim();
 	return res;
 }
diff --git a/engines/kyra/text/text_rpg.h b/engines/kyra/text/text_rpg.h
index 30d3463..7f5825f 100644
--- a/engines/kyra/text/text_rpg.h
+++ b/engines/kyra/text/text_rpg.h
@@ -53,7 +53,8 @@ public:
 
 	void allowPageBreak(bool mode) { _allowPageBreak = mode; }
 	void setWaitButtonMode(int mode) { _waitButtonMode = mode; }
-	int lineCount() { return _lineCount; }
+	int lineCount() const { return _lineCount; }
+	const uint8 *colorMap() const { return _colorMap; }
 
 protected:
 	virtual KyraRpgEngine *vm() { return _vm; }
@@ -106,6 +107,8 @@ private:
 
 	char *_table1;
 	char *_table2;
+
+	uint8 _colorMap[256];
 };
 
 } // End of namespace Kyra


Commit: 490e41cfad44505a4f742db9092d9a960783da6c
    https://github.com/scummvm/scummvm/commit/490e41cfad44505a4f742db9092d9a960783da6c
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:21+01:00

Commit Message:
KYRA: (EOB1/Amiga) - implement AmigaDOS font support

- only basic support - no kerning, spacing, etc., since EOB doesn't need that
- also improve palette loading

Changed paths:
    engines/kyra/graphics/screen.cpp
    engines/kyra/graphics/screen.h
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/graphics/screen_eob.h
    engines/kyra/resource/resource.cpp


diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp
index 6af970e..2a5e511 100644
--- a/engines/kyra/graphics/screen.cpp
+++ b/engines/kyra/graphics/screen.cpp
@@ -1361,9 +1361,11 @@ bool Screen::loadFont(FontId fontId, const char *filename) {
 	Font *&fnt = _fonts[fontId];
 
 	if (!fnt) {
-		if (_isAmiga)
+		if (_vm->game() == GI_KYRA1 && _isAmiga)
 			fnt = new AMIGAFont();
 #ifdef ENABLE_EOB
+		else if (_isAmiga)
+			fnt = new AmigaDOSFont(_vm->resource());
 		else if (_vm->game() == GI_EOB1 || _vm->game() == GI_EOB2)
 			// We use normal VGA rendering in EOB II, since we do the complete EGA dithering in updateScreen().
 			fnt = new OldDOSFont(_useHiResEGADithering ? Common::kRenderVGA : _renderMode);
@@ -3725,7 +3727,7 @@ int AMIGAFont::getCharWidth(uint16 c) const {
 }
 
 void AMIGAFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
-	//if (c >= 255)
+	if (c >= 255)
 		return;
 
 	if (_chars[c].yOffset == 255)
diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h
index 8ed17a1..23bce62 100644
--- a/engines/kyra/graphics/screen.h
+++ b/engines/kyra/graphics/screen.h
@@ -30,6 +30,7 @@
 #include "common/rect.h"
 #include "common/rendermode.h"
 #include "common/stream.h"
+#include "common/ptr.h"
 
 class OSystem;
 
@@ -179,10 +180,77 @@ private:
 	static uint16 *_cgaDitheringTable;
 	static int _numRef;
 };
+
+/**
+ * Implementation of the Font interface for native AmigaDOS system fonts (normally to be loaded via diskfont.library)
+ */
+class Resource;
+class AmigaDOSFont : public Font {
+public:
+	AmigaDOSFont(Resource *res);
+	~AmigaDOSFont() { unload(); }
+
+	bool load(Common::SeekableReadStream &file);
+	int getHeight() const { return _height; }
+	int getWidth() const { return _width; }
+	int getCharWidth(uint16 c) const;
+	void setColorMap(const uint8 *src) { _colorMap = src;  }
+	void drawChar(uint16 c, byte *dst, int pitch, int) const;
+
+private:
+	void unload();
+
+	struct TextFont {
+		TextFont() : data(0), bitmap(0), location(0), spacing(0), kerning(0), height(0), width(0), baseLine(0), firstChar(0), lastChar(0), modulo(0) {}
+		~TextFont() {
+			delete[] data;
+		}
+
+		uint16 height;
+		uint16 width;
+		uint16 baseLine;
+		uint8 firstChar;
+		uint8 lastChar;		
+		uint16 modulo;
+		const uint8 *data;
+		const uint8 *bitmap;
+		const uint16 *location;
+		const int16 *spacing;
+		const int16 *kerning;
+	};
+
+	TextFont *loadContentFile(const Common::String fileName);
+	void selectMode(int mode);
+
+	struct FontContent {
+		FontContent() : height(0), style(0), flags(0) {}
+		~FontContent() {
+			data.reset();
+		}
+
+		Common::String contentFile;
+		Common::SharedPtr<TextFont> data;
+		uint16 height;
+		uint8 style;
+		uint8 flags;
+	};
+
+	int _width, _height;
+	uint8 _first, _last;
+	FontContent *_content;
+	uint16 _numElements;
+	uint16 _selectedElement;
+
+	const uint8 *_colorMap;
+
+	const uint16 _maxPathLen;
+
+	Resource *_res;
+};
 #endif // ENABLE_EOB
 
 /**
- * Implementation of the Font interface for AMIGA fonts.
+ * Implementation of the Font interface for Kyra 1 style (non-native AmigaDOS) AMIGA fonts.
  */
 class AMIGAFont : public Font {
 public:
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index c7bfec9..823740c 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -36,6 +36,8 @@
 #include "graphics/palette.h"
 #include "graphics/sjis.h"
 
+#include "gui/error.h"
+
 namespace Kyra {
 
 Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, _screenDimTable, _screenDimTableCount), _cursorColorKey16Bit(0x8000) {
@@ -204,11 +206,11 @@ void Screen_EoB::loadFileDataToPage(Common::SeekableReadStream *s, int pageNum,
 	s->read(_pagePtrs[pageNum], size);
 }
 
-void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int col2) {
+void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int col2, int shadowCol) {
 	if (_vm->gameFlags().platform != Common::kPlatformFMTowns) {
-		printText(string, x - 1, y, 12, col2);
-		printText(string, x, y + 1, 12, 0);
-		printText(string, x - 1, y + 1, 12, 0);
+		printText(string, x - 1, y, shadowCol, col2);
+		printText(string, x, y + 1, shadowCol, 0);
+		printText(string, x - 1, y + 1, shadowCol, 0);
 	} else if (col2) {
 		fillRect(x, y, x + getTextWidth(string) - 1, y + getFontHeight() - 1, col2);
 	}
@@ -220,14 +222,20 @@ void Screen_EoB::loadShapeSetBitmap(const char *file, int tempPage, int destPage
 	_curPage = 2;
 }
 
-void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool) {
+void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip) {
 	Screen::loadBitmap(filename, tempPage, dstPage, pal);
 
-	if (_isAmiga) {
-		// Yay, this is where EOB1 Amiga hides the palette data
-		loadPalette(_pagePtrs[dstPage] + 40000, *_palettes[0], 64);
-		_palettes[0]->fill(0, 1, 0);
+	Common::SeekableReadStream *str = _vm->resource()->createReadStream(filename);
+	str->skip(4);
+	uint32 imgSize = str->readUint32LE();
+	delete str;
 
+	if (_isAmiga && !skip) {
+		if ((dstPage == 3 || dstPage == 4) && imgSize == 40064) {
+			// Yay, this is where EOB1 Amiga hides the palette data
+			loadPalette(_pagePtrs[dstPage] + 40000, *_palettes[0], 64);
+			_palettes[0]->fill(0, 1, 0);
+		}
 		Screen::convertAmigaGfx(getPagePtr(dstPage), 320, 200);
 	}
 }
@@ -1922,6 +1930,223 @@ void OldDOSFont::unload() {
 	_bitmapOffsets = 0;
 }
 
+AmigaDOSFont::AmigaDOSFont(Resource *res) : _res(res), _width(0), _height(0), _first(0), _last(0), _content(0), _numElements(0), _selectedElement(0), _maxPathLen(256) {
+	assert(_res);
+}
+
+bool AmigaDOSFont::load(Common::SeekableReadStream &file) {
+	unload();
+
+	uint16 id = file.readUint16BE();
+	// We only support type 0x0f00, since this is the only type used for EOB 
+	if (id != 0x0f00)
+		return false;
+
+	_numElements = file.readUint16BE();
+	_content = new FontContent[_numElements];
+	char *cfile = new char[_maxPathLen];
+
+	for (int i = 0; i < _numElements; ++i) {
+		file.read(cfile, _maxPathLen);
+		_content[i].height = file.readUint16BE();;
+		_content[i].style = file.readByte();
+		_content[i].flags = file.readByte();
+		_content[i].contentFile = cfile;
+
+		for (int ii = 0; ii < i; ++ii) {
+			if (_content[ii].contentFile == _content[i].contentFile && _content[ii].data.get())
+				_content[i].data = _content[ii].data;
+		}
+
+		if (!_content[i].data.get()) {
+			TextFont *contentData = loadContentFile(cfile);
+			if (contentData) {
+				_content[i].data = Common::SharedPtr<TextFont>(contentData);
+			} else {
+				unload();
+				return false;
+			}
+		}
+
+		if (!(_content[i].flags & 0x40) && (_content[i].height != _content[i].data->height)) {
+			warning("Amiga DOS Font construction / scaling not implemented.");
+		}
+	}
+	
+	delete[] cfile;
+
+	selectMode(0);
+
+	return true;
+}
+
+int AmigaDOSFont::getCharWidth(uint16 c) const {
+	if (c < _first || c > _last)
+		return 0;
+	c -= _first;
+
+	int width = _content[_selectedElement].data->spacing ? _content[_selectedElement].data->spacing[c] : _content[_selectedElement].data->width;
+
+	/*if (_content[_selectedElement].data->kerning)
+		width += _content[_selectedElement].data->kerning[c];*/
+
+	return width;
+}
+
+void AmigaDOSFont::drawChar(uint16 c, byte *dst, int pitch, int) const {
+	if (c < _first || c > _last || !dst)
+		return;
+
+	static const uint16 table[] = {
+		0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
+		0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff
+	};
+
+	c -= _first;
+
+	int w = _content[_selectedElement].data->spacing ? _content[_selectedElement].data->spacing[c] : _content[_selectedElement].data->width;
+	int xbits = _content[_selectedElement].data->location[c * 2 + 1];
+	int h = _content[_selectedElement].data->height;
+	
+	uint16 bitPos = _content[_selectedElement].data->location[c * 2] & 0x0F;
+	uint16 mod = _content[_selectedElement].data->modulo;
+	const uint8 *data = _content[_selectedElement].data->bitmap + ((_content[_selectedElement].data->location[c * 2] >> 3) & ~1);
+	uint32 xbt_mask = xbits ? table[(xbits - 1) & 0x0F] << 16 : 0;
+
+	for (int y = 0; y < h; ++y) {
+		uint32 mask = 0x80000000;
+		uint32 bits = (READ_BE_UINT32(data) << bitPos) & xbt_mask;
+		data += mod;
+		
+		for (int x = 0; x < w; ++x) {
+			if (bits & mask) {
+				if (_colorMap[1])
+					*dst = _colorMap[1];
+			} else {
+				if (_colorMap[0])
+					*dst = _colorMap[0];
+			}
+			mask >>= 1;
+			dst++;
+		}
+		dst += (pitch - w);
+	}
+}
+
+void AmigaDOSFont::unload() {
+	delete[] _content;
+}
+
+AmigaDOSFont::TextFont *AmigaDOSFont::loadContentFile(const Common::String fileName) {
+	Common::SeekableReadStreamEndian *str = _res->createEndianAwareReadStream(fileName);
+
+	if (!str && fileName.contains('/')) {
+		// These content files are usually located in sub directories (i. e. the eobf8.font
+		// has a sub dir named 'eobf8' with a file '8' in it). In case someone put the content
+		// files directly in the game directory we still try to open it.
+		Common::String fileNameAlt = fileName;
+		while (fileNameAlt.firstChar() != '/')
+			fileNameAlt.deleteChar(0);
+		fileNameAlt.deleteChar(0);
+
+		str = _res->createEndianAwareReadStream(fileNameAlt);
+
+		if (!str) {
+			// Someone might even have copied the floppy disks to the game directory with the
+			// full sub directory structure. So we also try that...
+			fileNameAlt = "fonts/";
+			fileNameAlt += fileName;
+
+			str = _res->createEndianAwareReadStream(fileNameAlt);
+		}
+
+		if (!str) {
+			::GUI::displayErrorDialog("This AMIGA version requires the following font files:\n\nEOBF6.FONT\nEOBF6/6\nEOBF8.FONT\nEOBF8/8\n\n"
+				"If you used the orginal installer for the installation these files\nshould be located in the AmigaDOS system 'Fonts/' folder.\n"
+				"Please copy them into the EOB game data directory.\n");
+			error("Failed to load font files.");
+		}
+	}
+
+	uint32 hunkId = str->readUint32();
+	// Except for some sanity checks we skip all of the Amiga hunk file magic
+	if (hunkId != 0x03f3)
+		return 0;
+	str->seek(20, SEEK_CUR);
+
+	uint32 hunkType = str->readUint32();
+	if (hunkType != 0x3E9)
+		return 0;
+	uint32 dataSize = str->readUint32() * 4;
+	int32 hunkStartPos = str->pos();
+
+	str->seek(34, SEEK_CUR);
+	TextFont *fnt = new TextFont();
+	int32 fntStartPos = str->pos();
+	str->seek(44, SEEK_CUR);
+	fnt->height = str->readUint16();
+	str->seek(2, SEEK_CUR);
+	fnt->width = str->readUint16();
+	fnt->baseLine = str->readUint16();
+	str->seek(4, SEEK_CUR);
+	fnt->firstChar = str->readByte();
+	fnt->lastChar = str->readByte();
+
+	str->seek(18, SEEK_CUR);
+	int32 curPos = str->pos();
+	uint32 bufferSize = dataSize - (curPos - fntStartPos);
+	uint8 *buffer = new uint8[bufferSize];
+	str->read(buffer, bufferSize);
+
+	str->seek(curPos - 18, SEEK_SET);
+	uint32 offset = str->readUint32();
+	fnt->bitmap = offset ? buffer + offset - (curPos - hunkStartPos) : 0;
+	fnt->modulo = str->readUint16();
+
+	offset = str->readUint32();
+	uint16 *loc = (uint16*) (offset ? buffer + offset - (curPos - hunkStartPos) : 0);
+	for (int i = 0; i <= (fnt->lastChar - fnt->firstChar) * 2 + 1; ++i)
+		loc[i] = READ_BE_UINT16(&loc[i]);
+	fnt->location = loc;
+
+	offset = str->readUint32();
+	int16 *idat = offset ? (int16*)(buffer + offset - (curPos - hunkStartPos)) : 0;
+	if (idat) {
+		for (int i = 0; i <= (fnt->lastChar - fnt->firstChar) * 2 + 1; ++i)
+			idat[i] = (int16)READ_BE_UINT16(&idat[i]);
+	}
+	fnt->spacing = idat;
+
+	offset = str->readUint32();
+	// This warning will only show up if someone tries to use this code elsewhere. It cannot happen with EOB fonts.
+	if (offset)
+		warning("Trying to load an AmigaDOS font with kerning data. This is not implemented. Font Rendering will not be accurate.");
+	idat = offset ? (int16*)(buffer + offset - (curPos - hunkStartPos)) : 0;
+	if (idat) {
+		for (int i = 0; i <= (fnt->lastChar - fnt->firstChar) * 2 + 1; ++i)
+			idat[i] = (int16)READ_BE_UINT16(&idat[i]);
+	}
+	fnt->kerning = idat;	
+
+	fnt->data = buffer;
+
+	delete str;
+
+	return fnt;
+}
+
+void AmigaDOSFont::selectMode(int mode) {
+	if (mode < 0 || mode > _numElements - 1)
+		return;
+
+	_selectedElement = mode;
+
+	_width = _content[mode].data->width;
+	_height = _content[mode].data->height;
+	_first = _content[mode].data->firstChar;
+	_last = _content[mode].data->lastChar;
+}
+
 SJISFontLarge::SJISFontLarge(Graphics::FontSJIS *font) : SJISFont(font, 0, false, false, false, 0) {
 	_sjisWidth = _font->getMaxFontWidth();
 	_fontHeight = _font->getFontHeight();
diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h
index 60290df..6889755 100644
--- a/engines/kyra/graphics/screen_eob.h
+++ b/engines/kyra/graphics/screen_eob.h
@@ -45,7 +45,7 @@ public:
 
 	void loadFileDataToPage(Common::SeekableReadStream *s, int pageNum, uint32 size);
 
-	void printShadedText(const char *string, int x, int y, int col1, int col2);
+	void printShadedText(const char *string, int x, int y, int col1, int col2, int shadowCol);
 
 	virtual void loadBitmap(const char *filename, int tempPage, int dstPage, Palette *pal, bool skip = false);
 	void loadEoBBitmap(const char *file, const uint8 *cgaMapping, int tempPage, int destPage, int convertToPage);
diff --git a/engines/kyra/resource/resource.cpp b/engines/kyra/resource/resource.cpp
index 19603a1..bbafc1b 100644
--- a/engines/kyra/resource/resource.cpp
+++ b/engines/kyra/resource/resource.cpp
@@ -339,7 +339,8 @@ Common::SeekableReadStream *Resource::createReadStream(const Common::String &fil
 }
 
 Common::SeekableReadStreamEndian *Resource::createEndianAwareReadStream(const Common::String &file) {
-	return new EndianAwareStreamWrapper(_files.createReadStreamForMember(file), _vm->gameFlags().platform == Common::kPlatformAmiga);
+	Common::SeekableReadStream *stream = _files.createReadStreamForMember(file);
+	return stream ? new EndianAwareStreamWrapper(stream, _vm->gameFlags().platform == Common::kPlatformAmiga) : 0;
 }
 
 Common::Archive *Resource::loadArchive(const Common::String &name, Common::ArchiveMemberPtr member) {


Commit: 21712209c05605d4a75ef2e0f1f9b8bce3a547e7
    https://github.com/scummvm/scummvm/commit/21712209c05605d4a75ef2e0f1f9b8bce3a547e7
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:21+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix level loading

Now it is at least possible to enter the game after creating a party. Graphics are still messed up.

Changed paths:
    engines/kyra/engine/eob.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/gui/gui_eob.cpp
    engines/kyra/resource/staticres_eob.cpp


diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index 25ab86d..3a83643 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -374,9 +374,9 @@ void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s
 	if (doorType1 != 0xFF) {
 		for (int i = 0; i < 3; i++) {
 			const uint8 *enc = &_doorShapeEncodeDefs[(doorType1 * 3 + i) << 2];
-			_doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_doorShapes[shapeId1 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
 			enc = &_doorSwitchShapeEncodeDefs[(doorType1 * 3 + i) << 2];
-			_doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_doorSwitches[shapeId1 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
 			_doorSwitches[shapeId1 + i].x = _doorSwitchCoords[doorType1 * 6 + i * 2];
 			_doorSwitches[shapeId1 + i].y = _doorSwitchCoords[doorType1 * 6 + i * 2 + 1];
 		}
@@ -385,9 +385,9 @@ void EoBEngine::loadDoorShapes(int doorType1, int shapeId1, int doorType2, int s
 	if (doorType2 != 0xFF) {
 		for (int i = 0; i < 3; i++) {
 			const uint8 *enc = &_doorShapeEncodeDefs[(doorType2 * 3 + i) << 2];
-			_doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_doorShapes[shapeId2 + i] = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
 			enc = &_doorSwitchShapeEncodeDefs[(doorType2 * 3 + i) << 2];
-			_doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_doorSwitches[shapeId2 + i].shp = _screen->encodeShape(enc[0], enc[1], enc[2], enc[3], false, (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
 			_doorSwitches[shapeId2 + i].x = _doorSwitchCoords[doorType2 * 6 + i * 2];
 			_doorSwitches[shapeId2 + i].y = _doorSwitchCoords[doorType2 * 6 + i * 2 + 1];
 		}
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index bf991c9..9b15c60 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -213,7 +213,6 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
 	_menuStringsRest4 = _menuStringsDefeat = _menuStringsTransfer = _menuStringsSpec = 0;
 	_menuStringsSpellNo = _menuYesNoStrings = _2431Strings = _katakanaLines = _katakanaSelectStrings = 0;
 	_errorSlotEmptyString = _errorSlotNoNameString = _menuOkString = 0;
-	_levelSoundFiles1 = _levelSoundFiles2 = 0;
 	_spellLevelsMage = _spellLevelsCleric = _numSpellsCleric = _numSpellsWisAdj = _numSpellsPal = _numSpellsMage = 0;
 	_mnNumWord = _numSpells = _mageSpellListSize = _spellLevelsMageSize = _spellLevelsClericSize = 0;
 	_inventorySlotsX = _slotValidationFlags = _encodeMonsterShpTable = 0;
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 74e8ad4..3d71fe0 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -1175,9 +1175,6 @@ protected:
 	void snd_stopSound();
 	void snd_fadeOut();
 
-	const char *const *_levelSoundFiles1;
-	const char *const *_levelSoundFiles2;
-
 	// keymap
 	static const char *const kKeymapName;
 };
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 3ff26ca..539d81d 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -92,8 +92,11 @@ void EoBCoreEngine::loadLevel(int level, int sub) {
 	if (_flags.gameID == GI_EOB1 && level == 7 && _levelBlockProperties[0x035C].assignedObjects == 0x0E89)
 		_levelBlockProperties[0x035C].assignedObjects = 0x0E8D;
 
-	loadVcnData(gfxFile.c_str(), (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[level - 1]] : 0);
+	loadVcnData(gfxFile.c_str(), (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[level - 1]] : 0);
 	_screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2);
+	if (_flags.platform == Common::kPlatformAmiga)
+		_screen->setScreenPalette(_screen->getPalette(0));
+
 	delayUntil(end);
 	snd_stopSound();
 
@@ -121,7 +124,7 @@ void EoBCoreEngine::readLevelFileData(int level) {
 		if (s->readUint16LE() == 4) {
 			delete s;
 			s = 0;
-			_screen->loadBitmap(file.c_str(), 5, 5, 0);
+			_screen->loadBitmap(file.c_str(), 5, 5, 0, true);
 		}
 	}
 
@@ -150,12 +153,12 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 		pos += slen;
 
 		const char *vmpPattern = (_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.EMP" : "%s.VMP";
-		Common::SeekableReadStream *s = _res->createReadStream(Common::String::format(vmpPattern, (const char *)pos));
-		uint16 size = (_flags.platform == Common::kPlatformFMTowns) ? 2916 : s->readUint16LE();
+		Common::SeekableReadStreamEndian *s = _res->createEndianAwareReadStream(Common::String::format(vmpPattern, (const char *)pos));
+		uint16 size = (_flags.platform == Common::kPlatformFMTowns) ? 2916 : s->readUint16();
 		delete[] _vmpPtr;
 		_vmpPtr = new uint16[size];
 		for (int i = 0; i < size; i++)
-			_vmpPtr[i] = s->readUint16LE();
+			_vmpPtr[i] = s->readUint16();
 		delete s;
 
 		const char *paletteFilePattern = (_flags.gameID == GI_EOB2 && _configRenderMode == Common::kRenderEGA) ? "%s.EGA" : "%s.PAL";
@@ -175,7 +178,7 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 			_screen->enableShapeBackgroundFading(false);
 		}
 
-		if (_flags.gameID == GI_EOB2 || _configRenderMode != Common::kRenderEGA)
+		if (_flags.platform != Common::kPlatformAmiga && (_flags.gameID == GI_EOB2 || _configRenderMode != Common::kRenderEGA))
 			_screen->loadPalette(tmpStr.c_str(), _screen->getPalette(0));
 
 		if (_flags.platform == Common::kPlatformFMTowns) {
@@ -186,6 +189,8 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 			_screen->createFadeTable16bit(src, (uint16*)_lightBlueFadingTable, 11, 125);
 			_screen->createFadeTable16bit(src, (uint16*)_greyFadingTable, 0, 85);
 			_screen->setScreenPalette(_screen->getPalette(0));
+		} else if (_flags.platform == Common::kPlatformAmiga) {
+
 		} else if (_configRenderMode != Common::kRenderCGA) {
 			Palette backupPal(256);
 			backupPal.copy(_screen->getPalette(0), 224, 32, 224);
@@ -209,6 +214,9 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 		delay(3 * _tickLength);
 		_sound->loadSoundFile((const char *)pos);
 		pos += 13;
+	} else if (_flags.platform == Common::kPlatformAmiga) {
+		delay(3 * _tickLength);
+		_sound->loadSoundFile(_currentLevel);
 	}
 
 	releaseDoorShapes();
@@ -302,10 +310,20 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 	}
 
 	const char *filePattern = ((_flags.gameID == GI_EOB1 && (_configRenderMode == Common::kRenderEGA || _configRenderMode == Common::kRenderCGA)) ? "%s.ECN" : "%s.VCN");
-	_screen->loadBitmap(Common::String::format(filePattern, _lastBlockDataFile).c_str(), 3, 3, 0);
-	const uint8 *pos = _screen->getCPagePtr(3);
+	Common::String fn = Common::String::format(filePattern, _lastBlockDataFile);
+
+	if (_flags.platform == Common::kPlatformAmiga) {
+		Common::SeekableReadStream *in = _res->createReadStream(fn);
+		uint16 size = in->readUint16LE() << 5;
+		in->seek(0, SEEK_SET);
+		_screen->loadFileDataToPage(in, 3, size + 34);
+		delete in;
+	} else {
+		_screen->loadBitmap(fn.c_str(), 3, 3, 0, true);
+	}
 
-	uint32 vcnSize = READ_LE_UINT16(pos) << 5;
+	const uint8 *pos = _screen->getCPagePtr(3);
+	uint16 vcnSize = READ_LE_UINT16(pos) << 5;
 	pos += 2;
 
 	const uint8 *colMap = pos;
@@ -459,7 +477,7 @@ void EoBCoreEngine::assignWallsAndDecorations(int wallIndex, int vmpIndex, int d
 			if (r->w == 0 || r->h == 0)
 				error("Error trying to make decoration %d (x: %d, y: %d, w: %d, h: %d)", decIndex, r->x, r->y, r->w, r->h);
 
-			_levelDecorationShapes[t] = _screen->encodeShape(r->x, r->y, r->w, r->h, false, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+			_levelDecorationShapes[t] = _screen->encodeShape(r->x, r->y, r->w, r->h, false, (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
 		}
 
 		decIndex = _levelDecorationProperties[_mappedDecorationsCount++].next;
diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index 3f7843e..41703ca 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -64,7 +64,7 @@ void EoBCoreEngine::gui_drawPlayField(bool refresh) {
 }
 
 void EoBCoreEngine::gui_restorePlayField() {
-	loadVcnData(0, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+	loadVcnData(0, (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
 	_screen->_curPage = 0;
 	gui_drawPlayField(true);
 	gui_drawAllCharPortraitsWithStats();
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index 35b0d2b..ed2f368 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -1151,9 +1151,6 @@ void EoBEngine::initStaticResource() {
 	for (int i = 0; i < 5; i++)
 		_cgaMappingLevel[i] = _staticres->loadRawData(kEoB1CgaMappingLevel0 + i, temp);
 
-	_levelSoundFiles1 = _staticres->loadStrings(kEoB1BaseLevelSounds1, temp);
-	_levelSoundFiles2 = _staticres->loadStrings(kEoB1BaseLevelSounds2, temp);
-
 	_turnUndeadString = _staticres->loadStrings(kEoB1TurnUndeadString, temp);
 
 	_npcShpData = _staticres->loadRawData(kEoB1NpcShpData, temp);


Commit: 946597d3b293fa75d7f0a39f345ad07a36052bd1
    https://github.com/scummvm/scummvm/commit/946597d3b293fa75d7f0a39f345ad07a36052bd1
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:21+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix level graphics

Changed paths:
    engines/kyra/engine/kyra_rpg.cpp
    engines/kyra/engine/kyra_rpg.h
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/engine/scene_rpg.cpp


diff --git a/engines/kyra/engine/kyra_rpg.cpp b/engines/kyra/engine/kyra_rpg.cpp
index 3d7a4df..46fef3f 100644
--- a/engines/kyra/engine/kyra_rpg.cpp
+++ b/engines/kyra/engine/kyra_rpg.cpp
@@ -43,12 +43,16 @@ KyraRpgEngine::KyraRpgEngine(OSystem *system, const GameFlags &flags) : KyraEngi
 
 	_vcnBlocks = 0;
 	_vcfBlocks = 0;
-	_vcnTransitionMask = 0;
+	_vcnTransitionMask = _vcnMaskTbl = 0;
 	_vcnShift = 0;
 	_vcnColTable = 0;
+	_vcnShiftVal = 0;
 	_vcnBpp = flags.useHiColorMode ? 2 : 1;
+	_vcnSrcBitsPerPixel = (flags.platform == Common::kPlatformAmiga) ? 5 : (_vcnBpp == 2 ? 8 : 4);
+	_vcnDrawLine = 0;
+
 	_vmpPtr = 0;
-	_blockBrightness = _wllVcnOffset = 0;
+	_blockBrightness = _wllVcnOffset = _wllVcnOffset2 = _wllVcnRmdOffset = 0;
 	_blockDrawingBuffer = 0;
 	_sceneWindowBuffer = 0;
 	_monsterShapes = _monsterPalettes = 0;
@@ -135,6 +139,7 @@ KyraRpgEngine::~KyraRpgEngine() {
 	delete[] _vcnShift;
 	delete[] _blockDrawingBuffer;
 	delete[] _sceneWindowBuffer;
+	delete _vcnDrawLine;
 
 	delete[] _lvlShapeTop;
 	delete[] _lvlShapeBottom;
@@ -184,6 +189,16 @@ Common::Error KyraRpgEngine::init() {
 	for (int i = 0; i < 128; i++)
 		_vcnColTable[i] = i & 0x0F;
 
+	if (_vcnBpp == 2)
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_hiCol), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_hiCol),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_hiCol), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_hiCol));
+	else if (_flags.platform == Common::kPlatformAmiga)
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_Amiga), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_Amiga),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_Amiga), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_Amiga));
+	else
+		_vcnDrawLine = new VcnLineDrawingMethods(new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_4bit), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_4bit),
+			new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_fw_trans_4bit), new VcnDrawProc(this, &KyraRpgEngine::vcnDraw_bw_trans_4bit));
+
 	_doorShapes = new uint8*[6];
 	memset(_doorShapes, 0, 6 * sizeof(uint8 *));
 
diff --git a/engines/kyra/engine/kyra_rpg.h b/engines/kyra/engine/kyra_rpg.h
index 0e04c77..dbdd256 100644
--- a/engines/kyra/engine/kyra_rpg.h
+++ b/engines/kyra/engine/kyra_rpg.h
@@ -198,9 +198,39 @@ protected:
 	bool hasWall(int index);
 	void assignVisibleBlocks(int block, int direction);
 	bool checkSceneUpdateNeed(int block);
-	void drawVcnBlocks();
 	uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction);
 
+	void drawVcnBlocks();
+	void vcnDraw_fw_4bit(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_bw_4bit(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_fw_trans_4bit(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_bw_trans_4bit(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_fw_Amiga(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_bw_Amiga(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_fw_trans_Amiga(uint8 *&dst, const uint8 *&src);
+	void vcnDraw_bw_trans_Amiga(uint8 *&dst, const uint8 *&src);
+
+	typedef Common::Functor2Mem<uint8 *&, const uint8 *&, void, KyraRpgEngine> VcnDrawProc;
+	struct VcnLineDrawingMethods {
+		VcnLineDrawingMethods(VcnDrawProc *fw, VcnDrawProc *bw, VcnDrawProc *fw_t, VcnDrawProc *bw_t) : forward(fw), backwards(bw), forward_trans(fw_t), backwards_trans(bw_t) {}
+		~VcnLineDrawingMethods() {
+			delete forward;
+			delete backwards;
+			delete forward_trans;
+			delete backwards_trans;
+		}
+
+		VcnDrawProc *forward;
+		VcnDrawProc *backwards;
+		VcnDrawProc *forward_trans;
+		VcnDrawProc *backwards_trans;
+	};
+	VcnLineDrawingMethods *_vcnDrawLine;
+
 	virtual int clickedDoorSwitch(uint16 block, uint16 direction) = 0;
 	int clickedWallShape(uint16 block, uint16 direction);
 	int clickedLeverOn(uint16 block, uint16 direction);
@@ -232,13 +262,18 @@ protected:
 	uint8 *_vcnBlocks;
 	uint8 *_vcfBlocks;
 	uint8 *_vcnTransitionMask;
+	uint8 *_vcnMaskTbl;
 	uint8 *_vcnShift;
+	uint8 _vcnShiftVal;
 	uint8 *_vcnColTable;
+	uint8 _vcnSrcBitsPerPixel;
 	uint8 _vcnBpp;
 	uint16 *_blockDrawingBuffer;
 	uint8 *_sceneWindowBuffer;
 	uint8 _blockBrightness;
 	uint8 _wllVcnOffset;
+	uint8 _wllVcnOffset2;
+	uint8 _wllVcnRmdOffset;
 
 	uint8 **_doorShapes;
 
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 539d81d..0bd4ca9 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -30,7 +30,6 @@
 
 #include "common/system.h"
 
-
 namespace Kyra {
 
 void EoBCoreEngine::loadLevel(int level, int sub) {
@@ -298,14 +297,15 @@ void EoBCoreEngine::addLevelItems() {
 	}
 }
 
-void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
+void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {	
 	if (file)
 		strcpy(_lastBlockDataFile, file);
 
+	delete[] _vcnBlocks;
+	uint32 vcnSize = 0;
+
 	if (_flags.platform == Common::kPlatformFMTowns) {
-		uint32 size;
-		delete[] _vcnBlocks;
-		_vcnBlocks = _res->fileData(Common::String::format("%s.VCC", _lastBlockDataFile).c_str(), &size);
+		_vcnBlocks = _res->fileData(Common::String::format("%s.VCC", _lastBlockDataFile).c_str(), &vcnSize);
 		return;
 	}
 
@@ -314,22 +314,24 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 
 	if (_flags.platform == Common::kPlatformAmiga) {
 		Common::SeekableReadStream *in = _res->createReadStream(fn);
-		uint16 size = in->readUint16LE() << 5;
-		in->seek(0, SEEK_SET);
-		_screen->loadFileDataToPage(in, 3, size + 34);
+		vcnSize = in->readUint16LE() * (_vcnSrcBitsPerPixel << 3);
+		_vcnBlocks = new uint8[vcnSize];
+		_screen->getPalette(0).loadAmigaPalette(*in, 1, 5);
+		in->seek(22, SEEK_CUR);
+		in->read(_vcnBlocks, vcnSize);
 		delete in;
-	} else {
-		_screen->loadBitmap(fn.c_str(), 3, 3, 0, true);
+		return;
 	}
 
+	_screen->loadBitmap(fn.c_str(), 3, 3, 0, true);
+
 	const uint8 *pos = _screen->getCPagePtr(3);
-	uint16 vcnSize = READ_LE_UINT16(pos) << 5;
+	vcnSize = READ_LE_UINT16(pos) * (_vcnSrcBitsPerPixel << 3);
 	pos += 2;
 
 	const uint8 *colMap = pos;
 	pos += 32;
 
-	delete[] _vcnBlocks;
 	_vcnBlocks = new uint8[vcnSize];
 
 	if (_configRenderMode == Common::kRenderCGA) {
@@ -355,6 +357,7 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 	} else {
 		if (!(_flags.gameID == GI_EOB1 && _configRenderMode == Common::kRenderEGA))
 			memcpy(_vcnColTable, colMap, 32);
+		
 		memcpy(_vcnBlocks, pos, vcnSize);
 	}
 }
diff --git a/engines/kyra/engine/scene_rpg.cpp b/engines/kyra/engine/scene_rpg.cpp
index 0528df6..4c0a97e 100644
--- a/engines/kyra/engine/scene_rpg.cpp
+++ b/engines/kyra/engine/scene_rpg.cpp
@@ -344,24 +344,28 @@ bool KyraRpgEngine::checkSceneUpdateNeed(int block) {
 	return false;
 }
 
+uint16 KyraRpgEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) {
+	static const int16 blockPosTable[] = { -32, 1, 32, -1 };
+	return (curBlock + blockPosTable[direction]) & 0x3FF;
+}
+
 void KyraRpgEngine::drawVcnBlocks() {
 	uint8 *d = _sceneWindowBuffer;
 	uint16 *bdb = _blockDrawingBuffer;
-	uint16 *hiColorPal = screen()->get16bitPalette();
-
+	
 	for (int y = 0; y < 15; y++) {
 		for (int x = 0; x < 22; x++) {
 			bool horizontalFlip = false;
 			uint16 vcnOffset = *bdb++;
 			uint16 vcnExtraOffsetWll = 0;
-			int wllVcnOffset = 0;
-			int wllVcnRmdOffset = 0;
+			_wllVcnOffset2 = 0;
+			_wllVcnRmdOffset = 0;
 
 			if (vcnOffset & 0x8000) {
 				// this renders a wall block over the transparent pixels of a floor/ceiling block
 				vcnExtraOffsetWll = vcnOffset - 0x8000;
 				vcnOffset = 0;
-				wllVcnRmdOffset = _wllVcnOffset;
+				_wllVcnRmdOffset = _wllVcnOffset;
 			}
 
 			if (vcnOffset & 0x4000) {
@@ -371,8 +375,8 @@ void KyraRpgEngine::drawVcnBlocks() {
 
 			const uint8 *src = 0;
 			if (vcnOffset) {
-				src = &_vcnBlocks[vcnOffset << (4 + _vcnBpp)];
-				wllVcnOffset = _wllVcnOffset;
+				src = &_vcnBlocks[vcnOffset * (_vcnSrcBitsPerPixel << 3)];
+				_wllVcnOffset2 = _wllVcnOffset;
 			} else {
 				// floor/ceiling blocks
 				vcnOffset = bdb[329];
@@ -381,46 +385,22 @@ void KyraRpgEngine::drawVcnBlocks() {
 					vcnOffset &= 0x3FFF;
 				}
 
-				src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset << (4 + _vcnBpp));
+				src = (_vcfBlocks ? _vcfBlocks : _vcnBlocks) + (vcnOffset * (_vcnSrcBitsPerPixel << 3));
 			}
 
-			uint8 shift = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness;
+			_vcnShiftVal = _vcnShift ? _vcnShift[vcnOffset] : _blockBrightness;
 
-			if (horizontalFlip) {
-				for (int blockY = 0; blockY < 8; blockY++) {
-					src += ((_vcnBpp << 2) - 1);
-					for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
-						if (_vcnBpp == 2) {
-							*(uint16*)d = hiColorPal[*src--];
-							d += 2;
-						} else {
-							uint8 bl = *src--;
-							*d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift];
-							*d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];
-						}
-					}
-					src += ((_vcnBpp << 2) + 1);
-					d += 168 * _vcnBpp;
-				}
-			} else {
-				for (int blockY = 0; blockY < 8; blockY++) {
-					for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
-						if (_vcnBpp == 2) {
-							*(uint16*)d = hiColorPal[*src++];
-							d += 2;
-						} else {
-							uint8 bl = *src++;
-							*d++ = _vcnColTable[((bl >> 4) + wllVcnOffset) | shift];
-							*d++ = _vcnColTable[((bl & 0x0F) + wllVcnOffset) | shift];
-						}
-					}
-					d += 168 * _vcnBpp;
-				}
+			for (int blockY = 0; blockY < 8; blockY++) {
+				if (horizontalFlip)
+					(*_vcnDrawLine->backwards)(d, src);
+				else
+					(*_vcnDrawLine->forward)(d, src);
+				d += 168 * _vcnBpp;
 			}
 			d -= 1400 * _vcnBpp;
 
 			if (vcnExtraOffsetWll) {
-				d -= 8 * _vcnBpp;
+				d -= (8 * _vcnBpp);
 				horizontalFlip = false;
 
 				if (vcnExtraOffsetWll & 0x4000) {
@@ -428,72 +408,16 @@ void KyraRpgEngine::drawVcnBlocks() {
 					horizontalFlip = true;
 				}
 
-				shift = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness;
-				src = &_vcnBlocks[vcnExtraOffsetWll << (4 + _vcnBpp)];
-				uint8 *maskTable = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll << 5] : 0;
-
-				if (horizontalFlip) {
-					for (int blockY = 0; blockY < 8; blockY++) {
-						src += ((_vcnBpp << 2) - 1);
-						maskTable += 3;
-						for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
-							if (_vcnBpp == 2) {
-								uint8 bl = *src--;
-								if (bl)
-									*(uint16*)d = hiColorPal[bl];
-								d += 2;
-							} else {
-								uint8 bl = *src--;
-								uint8 mask = _vcnTransitionMask ? *maskTable-- : 0;
-								uint8 h = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift];
-								uint8 l = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];
-
-								if (_vcnTransitionMask)
-									*d = (*d & (mask & 0x0F)) | h;
-								else if (h)
-									*d = h;
-								d++;
-
-								if (_vcnTransitionMask)
-									*d = (*d & (mask >> 4)) | l;
-								else if (l)
-									*d = l;
-								d++;
-								}
-						}
-						src += ((_vcnBpp << 2) + 1);
-						maskTable += 5;
-						d += 168 * _vcnBpp;
-					}
-				} else {
-					for (int blockY = 0; blockY < 8; blockY++) {
-						for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
-							if (_vcnBpp == 2) {
-								uint8 bl = *src++;
-								if (bl)
-									*(uint16*)d = hiColorPal[bl];
-								d += 2;
-							} else {
-								uint8 bl = *src++;
-								uint8 mask = _vcnTransitionMask ? *maskTable++ : 0;
-								uint8 h = _vcnColTable[((bl >> 4) + wllVcnRmdOffset) | shift];
-								uint8 l = _vcnColTable[((bl & 0x0F) + wllVcnRmdOffset) | shift];
-
-								if (_vcnTransitionMask)
-									*d = (*d & (mask >> 4)) | h;
-								else if (h)
-									*d = h;
-								d++;
-
-								if (_vcnTransitionMask)
-									*d = (*d & (mask & 0x0F)) | l;
-								else if (l)
-									*d = l;
-								d++;
-							}
-						}
-						d += 168 * _vcnBpp;
-					}
+				_vcnShiftVal = _vcnShift ? _vcnShift[vcnExtraOffsetWll] : _blockBrightness;
+				src = &_vcnBlocks[vcnExtraOffsetWll * (_vcnSrcBitsPerPixel << 3)];
+				_vcnMaskTbl = _vcnTransitionMask ? &_vcnTransitionMask[vcnExtraOffsetWll * (_vcnSrcBitsPerPixel << 3)] : 0;
+
+				for (int blockY = 0; blockY < 8; blockY++) {
+					if (horizontalFlip)
+						(*_vcnDrawLine->backwards_trans)(d, src);
+					else
+						(*_vcnDrawLine->forward_trans)(d, src);
+					d += 168 * _vcnBpp;
 				}
 				d -= 1400 * _vcnBpp;
 			}
@@ -504,11 +428,157 @@ void KyraRpgEngine::drawVcnBlocks() {
 	screen()->copyBlockToPage(_sceneDrawPage1, _sceneXoffset, 0, 176, 120, _sceneWindowBuffer);
 }
 
-uint16 KyraRpgEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) {
-	static const int16 blockPosTable[] = { -32, 1, 32, -1 };
-	return (curBlock + blockPosTable[direction]) & 0x3FF;
+void KyraRpgEngine::vcnDraw_fw_4bit(uint8 *&dst, const uint8 *&src) {
+	for (int blockX = 0; blockX < 4; blockX++) {
+		uint8 bl = *src++;
+		*dst++ = _vcnColTable[((bl >> 4) + _wllVcnOffset2) | _vcnShiftVal];
+		*dst++ = _vcnColTable[((bl & 0x0F) + _wllVcnOffset2) | _vcnShiftVal];
+	}		
+}
+
+void KyraRpgEngine::vcnDraw_bw_4bit(uint8 *&dst, const uint8 *&src) {
+	src += 3;
+	for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+		uint8 bl = *src--;
+		*dst++ = _vcnColTable[((bl & 0x0F) + _wllVcnOffset2) | _vcnShiftVal];
+		*dst++ = _vcnColTable[((bl >> 4) + _wllVcnOffset2) | _vcnShiftVal];
+	}
+	src += 5;
+}
+
+void KyraRpgEngine::vcnDraw_fw_trans_4bit(uint8 *&dst, const uint8 *&src) {
+	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
+		uint8 bl = *src++;
+		uint8 mask = _vcnTransitionMask ? *_vcnMaskTbl++ : 0;
+		uint8 h = _vcnColTable[((bl >> 4) + _wllVcnRmdOffset) | _vcnShiftVal];
+		uint8 l = _vcnColTable[((bl & 0x0F) + _wllVcnRmdOffset) | _vcnShiftVal];
+
+		if (_vcnTransitionMask)
+			*dst = (*dst & (mask >> 4)) | h;
+		else if (h)
+			*dst = h;
+		dst++;
+
+		if (_vcnTransitionMask)
+			*dst = (*dst & (mask & 0x0F)) | l;
+		else if (l)
+			*dst = l;
+		dst++;
+	}
+}
+
+void KyraRpgEngine::vcnDraw_bw_trans_4bit(uint8 *&dst, const uint8 *&src) {
+	src += 3;
+	_vcnMaskTbl += 3;
+	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
+		uint8 bl = *src--;
+		uint8 mask = _vcnTransitionMask ? *_vcnMaskTbl-- : 0;
+		uint8 h = _vcnColTable[((bl & 0x0F) + _wllVcnRmdOffset) | _vcnShiftVal];
+		uint8 l = _vcnColTable[((bl >> 4) + _wllVcnRmdOffset) | _vcnShiftVal];
+
+		if (_vcnTransitionMask)
+			*dst = (*dst & (mask & 0x0F)) | h;
+		else if (h)
+			*dst = h;
+		dst++;
+
+		if (_vcnTransitionMask)
+			*dst = (*dst & (mask >> 4)) | l;
+		else if (l)
+			*dst = l;
+		dst++;
+	}
+	src += 5;
+	_vcnMaskTbl += 5;
 }
 
+void KyraRpgEngine::vcnDraw_fw_hiCol(uint8 *&dst, const uint8 *&src) {
+	const uint16 *hiColorPal = screen()->get16bitPalette();
+	for (int blockX = 0; blockX < 8; blockX++) {
+		*(uint16*)dst = hiColorPal[*src++];
+		dst += 2;
+	}
+}
+
+void KyraRpgEngine::vcnDraw_bw_hiCol(uint8 *&dst, const uint8 *&src) {
+	src += 7;
+	const uint16 *hiColorPal = screen()->get16bitPalette();
+	for (int blockX = 0; blockX < 4 * _vcnBpp; blockX++) {
+		*(uint16*)dst = hiColorPal[*src--];
+		dst += 2;
+	}
+	src += 9;
+}
+
+void KyraRpgEngine::vcnDraw_fw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
+	const uint16 *hiColorPal = screen()->get16bitPalette();
+	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
+		uint8 bl = *src++;
+		if (bl)
+			*(uint16*)dst = hiColorPal[bl];
+		dst += 2;
+	}
+}
+
+void KyraRpgEngine::vcnDraw_bw_trans_hiCol(uint8 *&dst, const uint8 *&src) {
+	src += 7;
+	const uint16 *hiColorPal = screen()->get16bitPalette();
+	for (int blockX = 0; blockX < _vcnSrcBitsPerPixel; blockX++) {
+		uint8 bl = *src--;
+		if (bl)
+			*(uint16*)dst = hiColorPal[bl];
+		dst += 2;
+	}
+	src += 9;
+}
+
+void KyraRpgEngine::vcnDraw_fw_Amiga(uint8 *&dst, const uint8 *&src) {
+	for (int blockX = 0; blockX < 8; blockX++) {
+		*dst = 0;
+		for (int i = 0; i < 5; ++i)
+			*dst |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i);
+		dst++;
+	}
+	src += 5;
+}
+
+void KyraRpgEngine::vcnDraw_bw_Amiga(uint8 *&dst, const uint8 *&src) {
+	for (int blockX = 7; blockX >= 0; blockX--) {
+		*dst = 0;
+		for (int i = 0; i < 5; ++i)
+			*dst |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i);
+		dst++;
+	}
+	src += 5;
+}
+
+void KyraRpgEngine::vcnDraw_fw_trans_Amiga(uint8 *&dst, const uint8 *&src) {
+	for (int blockX = 0; blockX < 8; blockX++) {
+		uint8 col = 0;
+		for (int i = 0; i < 5; ++i)
+			col |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i);
+
+		if (col)
+			*dst = col;
+		dst++;
+	}
+	src += 5;
+}
+
+void KyraRpgEngine::vcnDraw_bw_trans_Amiga(uint8 *&dst, const uint8 *&src) {
+	for (int blockX = 7; blockX >= 0; blockX--) {
+		uint8 col = 0;
+		for (int i = 0; i < 5; ++i)
+			col |= (((src[i] & (0x80 >> blockX)) >> (7 - blockX)) << i);
+
+		if (col)
+			*dst = col;
+		dst++;
+	}
+	src += 5;
+}
+
+
 int KyraRpgEngine::clickedWallShape(uint16 block, uint16 direction) {
 	uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]];
 	if (!clickedShape(v))


Commit: f72ccb972d02adde75ebf1cc8dbb5b687ecaa57c
    https://github.com/scummvm/scummvm/commit/f72ccb972d02adde75ebf1cc8dbb5b687ecaa57c
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:22+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix environmental sound glitch

Changed paths:
    engines/kyra/engine/eobcommon.cpp


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 9b15c60..198fc5e 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -574,9 +574,9 @@ Common::Error EoBCoreEngine::go() {
 		action = 0;
 
 		if (_gameToLoad != -1) {
+			startupLoad();
 			if (loadGameState(_gameToLoad).getCode() != Common::kNoError)
 				error("Couldn't load game slot %d on startup", _gameToLoad);
-			startupLoad();
 			_gameToLoad = -1;
 		} else {
 			_screen->showMouse();
@@ -585,9 +585,10 @@ Common::Error EoBCoreEngine::go() {
 
 		if (action == -1) {
 			// load game
+			startupLoad();
 			repeatLoop = _gui->runLoadMenu(72, 14);
-			if (repeatLoop && !shouldQuit())
-				startupLoad();
+			//if (!repeatLoop && !shouldQuit())
+				
 		} else if (action == -2) {
 			// new game
 			repeatLoop = startCharacterGeneration();


Commit: 39eb1c4cc4a409b08197eaf67a5bd51e2ba6b3c6
    https://github.com/scummvm/scummvm/commit/39eb1c4cc4a409b08197eaf67a5bd51e2ba6b3c6
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:22+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix detect magic spell

Changed paths:
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/items_eob.cpp
    engines/kyra/engine/kyra_rpg.h


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 198fc5e..456282c 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -61,7 +61,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
 	_drawSceneTimer = 0;
 
 	_largeItemShapes = _smallItemShapes = _thrownItemShapes = _spellShapes = _firebeamShapes = 0;
-	_itemIconShapes = _wallOfForceShapes = _teleporterShapes = _sparkShapes = _compassShapes = 0;
+	_itemIconShapes = _amigaBlueItemIconShapes = _wallOfForceShapes = _teleporterShapes = _sparkShapes = _compassShapes = 0;
 	_redSplatShape = _greenSplatShape = _deadCharShape = _disabledCharGrid = 0;
 	_blackBoxSmallGrid = _weaponSlotGrid = _blackBoxWideGrid = _lightningColumnShape = 0;
 
@@ -780,6 +780,15 @@ void EoBCoreEngine::loadItemsAndDecorationsShapes() {
 		_screen->loadShapeSetBitmap("ITEMICN", 5, 3);
 		for (int i = 0; i < _numItemIconShapes; i++)
 			_itemIconShapes[i] = _screen->encodeShape((i % 0x14) << 1, (i / 0x14) << 4, 2, 0x10, false, _cgaMappingIcons);
+		
+		if (_flags.platform == Common::kPlatformAmiga && _flags.gameID == GI_EOB1) {
+			_amigaBlueItemIconShapes = new const uint8*[_numItemIconShapes];
+			for (int i = 0; i < _numItemIconShapes; i++) {
+				int bx = (i % 0x14) << 1;
+				int by = (i / 0x14) << 4;
+				_amigaBlueItemIconShapes[i] = _screen->getPagePixel(2, (bx << 3) + 8, by + 88) ? _screen->encodeShape(bx, by + 80, 2, 0x10, false, 0) : _screen->encodeShape(bx, by, 2, 0x10, false, 0);
+			}
+		}
 	}
 
 	_teleporterShapes = new const uint8*[6];
@@ -872,6 +881,13 @@ void EoBCoreEngine::releaseItemsAndDecorationsShapes() {
 			}
 		}
 
+		if (_amigaBlueItemIconShapes) {
+			for (int i = 0; i < _numItemIconShapes; i++) {
+				if (_amigaBlueItemIconShapes[i])
+					delete[] _amigaBlueItemIconShapes[i];
+			}
+		}
+
 		if (_sparkShapes) {
 			for (int i = 0; i < 3; i++) {
 				if (_sparkShapes[i])
@@ -922,6 +938,7 @@ void EoBCoreEngine::releaseItemsAndDecorationsShapes() {
 	delete[] _thrownItemShapes;
 	delete[] _spellShapes;
 	delete[] _itemIconShapes;
+	delete[] _amigaBlueItemIconShapes;
 	delete[] _sparkShapes;
 	delete[] _wallOfForceShapes;
 	delete[] _teleporterShapes;
@@ -946,8 +963,12 @@ void EoBCoreEngine::setHandItem(Item itemIndex) {
 	const uint8 *shp = _itemIconShapes[icon];
 	const uint8 *ovl = 0;
 
-	if (icon && (_items[_itemInHand].flags & 0x80) && (_partyEffectFlags & 2))
-		ovl = _flags.gameID == GI_EOB1 ? ((_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icon << 4]) : _screen->generateShapeOverlay(shp, _lightBlueFadingTable);
+	if (icon && (_items[_itemInHand].flags & 0x80) && (_partyEffectFlags & 2)) {
+		if (_amigaBlueItemIconShapes)
+			shp = _amigaBlueItemIconShapes[icon];
+		else
+			ovl = _flags.gameID == GI_EOB1 ? ((_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icon << 4]) : _screen->generateShapeOverlay(shp, _lightBlueFadingTable);
+	}
 
 	int mouseOffs = itemIndex ? 8 : 0;
 	_screen->setMouseCursor(mouseOffs, mouseOffs, shp, ovl);
diff --git a/engines/kyra/engine/items_eob.cpp b/engines/kyra/engine/items_eob.cpp
index 4d11d0d..b4d9d67 100644
--- a/engines/kyra/engine/items_eob.cpp
+++ b/engines/kyra/engine/items_eob.cpp
@@ -463,17 +463,21 @@ void EoBCoreEngine::drawItemIconShape(int pageNum, Item itemId, int x, int y) {
 	int icn = _items[itemId].icon;
 	bool applyBluePal = ((_partyEffectFlags & 2) && (_items[itemId].flags & 0x80)) ? true : false;
 	const uint8 *ovl = 0;
+	const uint8 *shp = _itemIconShapes[icn];
 
 	if (applyBluePal) {
 		if (_flags.gameID == GI_EOB1) {
-			ovl = (_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icn << 4];
+			if (_amigaBlueItemIconShapes)
+				shp = _amigaBlueItemIconShapes[icn];
+			else
+				ovl = (_configRenderMode == Common::kRenderCGA) ? _itemsOverlayCGA : &_itemsOverlay[icn << 4];
 		} else {
 			_screen->setFadeTable(_lightBlueFadingTable);
 			_screen->setShapeFadingLevel(1);
 		}
 	}
 
-	_screen->drawShape(pageNum, _itemIconShapes[icn], x, y, 0, ovl ? 2 : 0, ovl);
+	_screen->drawShape(pageNum, shp, x, y, 0, ovl ? 2 : 0, ovl);
 
 	if (applyBluePal) {
 		_screen->setFadeTable(_greyFadingTable);
diff --git a/engines/kyra/engine/kyra_rpg.h b/engines/kyra/engine/kyra_rpg.h
index dbdd256..13853fb 100644
--- a/engines/kyra/engine/kyra_rpg.h
+++ b/engines/kyra/engine/kyra_rpg.h
@@ -139,6 +139,7 @@ protected:
 	void initStaticResource();
 
 	const uint8 **_itemIconShapes;
+	const uint8 **_amigaBlueItemIconShapes;
 
 	// Main loop
 	virtual void update() = 0;


Commit: 1cedb61c8ccd9f30372452c7b0f01cf0dab25157
    https://github.com/scummvm/scummvm/commit/1cedb61c8ccd9f30372452c7b0f01cf0dab25157
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:22+01:00

Commit Message:
KYRA: (EOB1) - fix slow poison status display

(in the character tab it would still say "poisoned" instead of "poisoned (slow)")

Changed paths:
    engines/kyra/gui/gui_eob.cpp


diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index 41703ca..bfe338b 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -139,7 +139,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 				_screen->printShadedText(_characterGuiStringsSt[1], 247, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->hitPointsCur < 1)
 				_screen->printShadedText(_characterGuiStringsSt[2], 226, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
-			else if (c->effectFlags & (_flags.gameID == GI_EOB1 ? 0x80 : 0x2000))
+			else if (c->effectFlags & 0x2000)
 				_screen->printShadedText(_characterGuiStringsSt[3], 220, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
 			else if (c->flags & 2)
 				_screen->printShadedText(_characterGuiStringsSt[4], 235, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);


Commit: e907965d81456c1612777499d52b253cbd7c059d
    https://github.com/scummvm/scummvm/commit/e907965d81456c1612777499d52b253cbd7c059d
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:22+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix main menu load dialog

Changed paths:
    engines/kyra/engine/chargen.cpp
    engines/kyra/engine/darkmoon.cpp
    engines/kyra/engine/eob.cpp
    engines/kyra/engine/eob.h
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/kyra_rpg.h
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/gui/gui_eob.cpp
    engines/kyra/gui/gui_eob.h
    engines/kyra/resource/staticres_eob.cpp
    engines/kyra/resource/staticres_lol.cpp
    engines/kyra/text/text_rpg.cpp


diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
index 14e72f8..7adca7f 100644
--- a/engines/kyra/engine/chargen.cpp
+++ b/engines/kyra/engine/chargen.cpp
@@ -357,7 +357,7 @@ void CharacterGenerator::checkForCompleteParty() {
 	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
 	int cp = _screen->setCurPage(2);
 	int x = (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168;
-	_screen->printShadedText(_chargenStrings1[8], x, 16, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenStrings1[8], x, 16, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->setCurPage(cp);
 	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
 
@@ -369,7 +369,7 @@ void CharacterGenerator::checkForCompleteParty() {
 
 	if (numChars == 4) {
 		_screen->setCurPage(2);
-		_screen->printShadedText(_chargenStrings1[0], x, 61, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(_chargenStrings1[0], x, 61, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 		_screen->setCurPage(0);
 		_screen->copyRegion(168, 61, 152, 125, 136, 40, 2, 0, Screen::CR_NO_P_CHECK);
 		toggleSpecialButton(15, 0, 0);
@@ -450,7 +450,7 @@ int CharacterGenerator::viewDeleteCharacter() {
 				if (_characters[_activeBox].name[0]) {
 					processSpecialButton(16);
 					_characters[_activeBox].name[0] = 0;
-					processNameInput(_activeBox, _vm->guiSettings()->colors.menuTxtColBlack);
+					processNameInput(_activeBox, _vm->guiSettings()->colors.guiColorBlack);
 					processFaceMenuSelection(_activeBox + 50);
 				}
 			} else {
@@ -511,10 +511,10 @@ void CharacterGenerator::createPartyMember() {
 		for (_characters[_activeBox].name[0] = 0; _characters[_activeBox].name[0] == 0 && !_vm->shouldQuit();) {
 			processFaceMenuSelection(_chargenMinStats[6]);
 			printStats(_activeBox, 0);
-			_screen->printShadedText(_chargenStrings2[11], 149, 100, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(_chargenStrings2[11], 149, 100, _vm->guiSettings()->colors.guiColorLightBlue, 0, _vm->guiSettings()->colors.guiColorBlack);
 			if (!_vm->shouldQuit()) {
-				_vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColDarkRed);
-				processNameInput(_activeBox, _vm->guiSettings()->colors.menuTxtColBlue);
+				_vm->_gui->getTextInput(_characters[_activeBox].name, 24, 100, 10, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorDarkRed);
+				processNameInput(_activeBox, _vm->guiSettings()->colors.guiColorBlue);
 			}
 		}
 	}
@@ -523,7 +523,7 @@ void CharacterGenerator::createPartyMember() {
 int CharacterGenerator::raceSexMenu() {
 	_screen->drawBox(_chargenBoxX[_activeBox], _chargenBoxY[_activeBox], _chargenBoxX[_activeBox] + 32, _chargenBoxY[_activeBox] + 33, 12);
 	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[8], 147, 67, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenStrings2[8], 147, 67, _vm->guiSettings()->colors.guiColorLightBlue, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_vm->removeInputTop();
 
 	_vm->_gui->simpleMenu_setup(1, 0, _chargenRaceSexStrings, -1, 0, 0);
@@ -550,7 +550,7 @@ int CharacterGenerator::classMenu(int raceSex) {
 	updateMagicShapes();
 
 	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[9], 147, 67, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenStrings2[9], 147, 67, _vm->guiSettings()->colors.guiColorLightBlue, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	toggleSpecialButton(5, 0, 0);
 
@@ -598,7 +598,7 @@ int CharacterGenerator::alignmentMenu(int cClass) {
 	updateMagicShapes();
 
 	_screen->copyRegion(0, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(_chargenStrings2[10], 147, 67, _vm->guiSettings()->colors.menuTxtColLightBlue, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenStrings2[10], 147, 67, _vm->guiSettings()->colors.guiColorLightBlue, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	toggleSpecialButton(5, 0, 0);
 
@@ -923,24 +923,24 @@ void CharacterGenerator::printStats(int index, int mode) {
 	if (mode != 4)
 		_screen->drawShape(2, c->faceShape, 224, 2, 0);
 
-	_screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
-	_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
-	_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(c->name, 160 + ((160 - _screen->getTextWidth(c->name)) / 2), 35, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
+	_screen->printShadedText(_chargenRaceSexStrings[c->raceSex], 160 + ((20 - strlen(_chargenRaceSexStrings[c->raceSex])) << 2), 45, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
+	_screen->printShadedText(_chargenClassStrings[c->cClass], 160 + ((20 - strlen(_chargenClassStrings[c->cClass])) << 2), 54, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	for (int i = 0; i < 6; i++)
-		_screen->printShadedText(_chargenStatStrings[i], 163, (i + 8) << 3, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(_chargenStatStrings[i], 163, (i + 8) << 3, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
-	_screen->printShadedText(_chargenStrings1[2], 248, 64, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenStrings1[2], 248, 64, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	Common::String str = Common::String::format(_chargenStrings1[3], _vm->getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), c->intelligenceCur, c->wisdomCur, c->dexterityCur, c->constitutionCur, c->charismaCur);
-	_screen->printShadedText(str.c_str(), 192, 64, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(str.c_str(), 192, 64, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	str = Common::String::format(_chargenStrings1[4], c->armorClass, c->hitPointsMax);
-	_screen->printShadedText(str.c_str(), 280, 64, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(str.c_str(), 280, 64, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	const char *lvlStr = c->level[2] ? _chargenStrings1[7] : (c->level[1] ? _chargenStrings1[6] : _chargenStrings1[5]);
 	str = Common::String::format(lvlStr, c->level[0], c->level[1], c->level[2]);
-	_screen->printShadedText(str.c_str(), 280, 80, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(str.c_str(), 280, 80, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	switch (mode) {
 	case 1:
@@ -975,7 +975,7 @@ void CharacterGenerator::printStats(int index, int mode) {
 
 void CharacterGenerator::processNameInput(int index, int textColor) {
 	Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
-	_screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->fillRect(_chargenNameFieldX[index], _chargenNameFieldY[index], _chargenNameFieldX[index] + 59, _chargenNameFieldY[index] + 5, _vm->guiSettings()->colors.guiColorBlack);
 	int xOffs = (60 - _screen->getTextWidth(_characters[index].name)) >> 1;
 	_screen->printText(_characters[index].name, _chargenNameFieldX[index] + xOffs, _chargenNameFieldY[index], textColor, 0);
 	_screen->updateScreen();
@@ -1010,7 +1010,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 	Common::String statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
 
 	_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.guiColorLightRed, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->updateScreen();
 
 	EoBCharacter *c = &_characters[_activeBox];
@@ -1089,7 +1089,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 		statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
 
 		_screen->copyRegion(b->x - 112, b->y - 64, b->x + 32, b->y, 40, b->height, 2, 0, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.guiColorLightRed, 0, _vm->guiSettings()->colors.guiColorBlack);
 		_screen->updateScreen();
 
 		if (index == 4) {
@@ -1101,7 +1101,7 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 			if (c->hitPointsCur != oldVal) {
 				statStr = Common::String::format("%d", c->hitPointsCur);
 				_screen->copyRegion(120, 72, 264, 136, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
-				_screen->printShadedText(statStr.c_str(), 264, 136, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(statStr.c_str(), 264, 136, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 				_screen->updateScreen();
 			}
 
@@ -1112,14 +1112,14 @@ int CharacterGenerator::modifyStat(int index, int8 *stat1, int8 *stat2) {
 			if (c->armorClass != oldVal) {
 				statStr = Common::String::format("%d", c->armorClass);
 				_screen->copyRegion(120, 64, 264, 128, 40, 8, 2, 0, Screen::CR_NO_P_CHECK);
-				_screen->printShadedText(statStr.c_str(), 264, 128, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(statStr.c_str(), 264, 128, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 				_screen->updateScreen();
 			}
 		}
 
 		if (loop == false) {
 			statStr = index ? Common::String::format("%d", *s1) : _vm->getCharStrength(*s1, *s2);
-			_screen->printText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.menuTxtColWhite, 0);
+			_screen->printText(statStr.c_str(), b->x + 32, b->y, _vm->guiSettings()->colors.guiColorWhite, 0);
 			_screen->updateScreen();
 		}
 	}
@@ -1172,7 +1172,7 @@ int CharacterGenerator::getMinHp(int cclass, int constitution, int level1, int l
 void CharacterGenerator::finish() {
 	_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
 	int cp = _screen->setCurPage(2);
-	_screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_chargenEnterGameStrings[0], (_vm->gameFlags().platform == Common::kPlatformFMTowns) ? 184 : 168, 32, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->setCurPage(cp);
 	_screen->copyRegion(160, 0, 144, 64, 160, 128, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
@@ -1631,8 +1631,8 @@ int TransferPartyWiz::selectCharactersMenu() {
 	_screen->clearCurPage();
 
 	_vm->gui_drawBox(0, 0, 320, 163, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
-	_screen->printText(_strings2[0], 5, 3, _vm->guiSettings()->colors.menuTxtColWhite, 0);
-	_screen->printText(_strings2[1], 5, 10, _vm->guiSettings()->colors.menuTxtColWhite, 0);
+	_screen->printText(_strings2[0], 5, 3, _vm->guiSettings()->colors.guiColorWhite, 0);
+	_screen->printText(_strings2[1], 5, 10, _vm->guiSettings()->colors.guiColorWhite, 0);
 
 	for (int i = 0; i < 6; i++)
 		drawCharPortraitWithStats(i, 0);
@@ -1640,8 +1640,8 @@ int TransferPartyWiz::selectCharactersMenu() {
 	_vm->gui_drawBox(4, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
 	_vm->gui_drawBox(272, 148, 43, 12, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
 
-	_screen->printShadedText(_labels[0], 9, 151, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
-	_screen->printShadedText(_labels[1], 288, 151, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_labels[0], 9, 151, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
+	_screen->printShadedText(_labels[1], 288, 151, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	_screen->setCurPage(0);
 	_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
@@ -1720,7 +1720,7 @@ int TransferPartyWiz::selectCharactersMenu() {
 		if (count == 4 || _vm->shouldQuit())
 			loop = false;
 		else
-			_vm->_gui->messageDialogue(16, count < 4 ? 69 : 70, _vm->guiSettings()->colors.menuTxtColLightRed);
+			_vm->_gui->messageDialogue(16, count < 4 ? 69 : 70, _vm->guiSettings()->colors.guiColorLightRed);
 
 		_screen->updateScreen();
 	}
@@ -1729,7 +1729,7 @@ int TransferPartyWiz::selectCharactersMenu() {
 	if (_vm->shouldQuit())
 		return 0;
 	else
-		_vm->_gui->messageDialogue(16, 71, _vm->guiSettings()->colors.menuTxtColLightRed);
+		_vm->_gui->messageDialogue(16, 71, _vm->guiSettings()->colors.guiColorLightRed);
 
 	return selection;
 }
@@ -1747,17 +1747,17 @@ void TransferPartyWiz::drawCharPortraitWithStats(int charIndex, bool enabled) {
 
 	_screen->drawShape(_screen->_curPage, c->faceShape, x + 4, y + 25, 0);
 
-	int color1 = _vm->guiSettings()->colors.menuTxtColWhite;
-	int color2 = _vm->guiSettings()->colors.menuTxtColBlack;
+	int color1 = _vm->guiSettings()->colors.guiColorWhite;
+	int color2 = _vm->guiSettings()->colors.guiColorBlack;
 
 	if (enabled) {
-		color1 = _vm->guiSettings()->colors.menuTxtColLightRed;
-		color2 = _vm->guiSettings()->colors.menuTxtColWhite;
+		color1 = _vm->guiSettings()->colors.guiColorLightRed;
+		color2 = _vm->guiSettings()->colors.guiColorWhite;
 	} else {
 		_screen->drawShape(_screen->_curPage, _vm->_disabledCharGrid, x + 4, y + 25, 0);
 	}
 
-	_screen->printShadedText(c->name, x + 44, y + 27, color1, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(c->name, x + 44, y + 27, color1, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->printText(_vm->_chargenRaceSexStrings[c->raceSex], x + 43, y + 36, color2, 0);
 	_screen->printText(_vm->_chargenClassStrings[c->cClass], x + 43, y + 43, color2, 0);
 
@@ -1770,7 +1770,7 @@ void TransferPartyWiz::drawCharPortraitWithStats(int charIndex, bool enabled) {
 void TransferPartyWiz::updateHighlight(int index) {
 	static const int16 xPos[] = { 9, 288 };
 	if (_highlight > 5 && _highlight != index)
-		_screen->printText(_labels[_highlight - 6], xPos[_highlight - 6], 151, _vm->guiSettings()->colors.menuTxtColWhite, 0);
+		_screen->printText(_labels[_highlight - 6], xPos[_highlight - 6], 151, _vm->guiSettings()->colors.guiColorWhite, 0);
 
 	if (index < 6) {
 		_vm->_gui->updateBoxFrameHighLight(14 + index);
@@ -1784,7 +1784,7 @@ void TransferPartyWiz::updateHighlight(int index) {
 	if (_highlight < 6)
 		_vm->_gui->updateBoxFrameHighLight(-1);
 
-	_screen->printText(_labels[index - 6], xPos[index - 6], 151, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
+	_screen->printText(_labels[index - 6], xPos[index - 6], 151, _vm->guiSettings()->colors.guiColorLightRed, 0);
 	_screen->updateScreen();
 	_highlight = index;
 }
diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index e3b151b..d8cb125 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -395,8 +395,8 @@ void DarkMoonEngine::restParty_npc() {
 	gui_drawBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, guiSettings()->colors.frame1, guiSettings()->colors.frame2, -1);
 	gui_drawBox((_screen->_curDim->sx << 3) + 1, _screen->_curDim->sy + 1, (_screen->_curDim->w << 3) - 2, _screen->_curDim->h - 2, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
 	_screen->set16bitShadingLevel(0);
-	_gui->messageDialogue2(11, 63, guiSettings()->colors.menuTxtColLightRed);
-	_gui->messageDialogue2(11, 64, guiSettings()->colors.menuTxtColLightRed);
+	_gui->messageDialogue2(11, 63, guiSettings()->colors.guiColorLightRed);
+	_gui->messageDialogue2(11, 64, guiSettings()->colors.guiColorLightRed);
 }
 
 bool DarkMoonEngine::restParty_extraAbortCondition() {
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index 3a83643..8c59d4d 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -42,6 +42,7 @@ EoBEngine::EoBEngine(OSystem *system, const GameFlags &flags)
 	_dscDoorY4 = _dscDoorY5 = _dscDoorY6 = _dscDoorY7 = _doorShapeEncodeDefs = 0;
 	_doorSwitchShapeEncodeDefs = _doorSwitchCoords = 0;
 	_dscDoorCoordsExt = 0;
+	_useMainMenuGUISettings = false;
 }
 
 EoBEngine::~EoBEngine() {
@@ -569,7 +570,7 @@ void EoBEngine::healParty() {
 
 const KyraRpgGUISettings *EoBEngine::guiSettings() const {
 	if (_flags.platform == Common::kPlatformAmiga)
-		return &_guiSettingsAmiga;
+		return _useMainMenuGUISettings ? &_guiSettingsAmigaMainMenu : &_guiSettingsAmiga;
 	else if (_configRenderMode == Common::kRenderCGA || _configRenderMode == Common::kRenderEGA)
 		return &_guiSettingsEGA;
 	else
diff --git a/engines/kyra/engine/eob.h b/engines/kyra/engine/eob.h
index 896f332..d0a1c01 100644
--- a/engines/kyra/engine/eob.h
+++ b/engines/kyra/engine/eob.h
@@ -112,11 +112,14 @@ private:
 	void healParty();
 
 	const KyraRpgGUISettings *guiSettings() const;
+	void useMainMenuGUISettings(bool toggle) { _useMainMenuGUISettings = toggle; }
 
 	static const KyraRpgGUISettings _guiSettingsVGA;
 	static const KyraRpgGUISettings _guiSettingsEGA;
 	static const KyraRpgGUISettings _guiSettingsAmiga;
+	static const KyraRpgGUISettings _guiSettingsAmigaMainMenu;
 	static const uint8 _egaDefaultPalette[];
+	bool _useMainMenuGUISettings;
 };
 
 } // End of namespace Kyra
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 456282c..a184b7f 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -539,7 +539,7 @@ Common::Error EoBCoreEngine::init() {
 
 	_monsterFlashOverlay = new uint8[16];
 	_monsterStoneOverlay = new uint8[16];
-	memset(_monsterFlashOverlay, (_configRenderMode == Common::kRenderCGA) ? 0xFF : 0x0F, 16 * sizeof(uint8));
+	memset(_monsterFlashOverlay, (_configRenderMode == Common::kRenderCGA) ? 0xFF : guiSettings()->colors.guiColorWhite, 16 * sizeof(uint8));
 	memset(_monsterStoneOverlay, 0x0D, 16 * sizeof(uint8));
 	_monsterFlashOverlay[0] = _monsterStoneOverlay[0] = 0;
 
@@ -586,8 +586,7 @@ Common::Error EoBCoreEngine::go() {
 		if (action == -1) {
 			// load game
 			startupLoad();
-			repeatLoop = _gui->runLoadMenu(72, 14);
-			//if (!repeatLoop && !shouldQuit())
+			repeatLoop = _gui->runLoadMenu(72, 14, true);
 				
 		} else if (action == -2) {
 			// new game
@@ -1900,11 +1899,11 @@ bool EoBCoreEngine::checkPassword() {
 		const uint8 *shp = (_mnDef[c << 2] < _numLargeItemShapes) ? _largeItemShapes[_mnDef[c << 2]] : (_mnDef[c << 2] < 15 ? 0 : _smallItemShapes[_mnDef[c << 2] - 15]);
 		assert(shp);
 		_screen->drawShape(0, shp, 100, 2, 13);
-		_screen->printShadedText(Common::String::format(_mnPrompt[0], _mnDef[(c << 2) + 1], _mnDef[(c << 2) + 2]).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.fill, guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(Common::String::format(_mnPrompt[0], _mnDef[(c << 2) + 1], _mnDef[(c << 2) + 2]).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy, guiSettings()->colors.guiColorWhite, guiSettings()->colors.fill, guiSettings()->colors.guiColorBlack);
 		memset(answ, 0, 20);
 		gui_drawBox(76, 100, 133, 14, guiSettings()->colors.frame2, guiSettings()->colors.frame1, -1);
 		gui_drawBox(77, 101, 131, 12, guiSettings()->colors.frame2, guiSettings()->colors.frame1, -1);
-		if (_gui->getTextInput(answ, 10, 103, 15, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.fill, guiSettings()->colors.menuTxtColDarkRed) < 0)
+		if (_gui->getTextInput(answ, 10, 103, 15, guiSettings()->colors.guiColorWhite, guiSettings()->colors.fill, guiSettings()->colors.guiColorDarkRed) < 0)
 			i = 3;
 		if (!scumm_stricmp(_mnWord[c], answ))
 			break;
diff --git a/engines/kyra/engine/kyra_rpg.h b/engines/kyra/engine/kyra_rpg.h
index 13853fb..a132ec7 100644
--- a/engines/kyra/engine/kyra_rpg.h
+++ b/engines/kyra/engine/kyra_rpg.h
@@ -112,12 +112,15 @@ struct KyraRpgGUISettings {
 		uint8 inactiveTabFrame2;
 		int inactiveTabFill;
 
-		uint8 menuTxtColWhite;
-		uint8 menuTxtColLightRed;
-		uint8 menuTxtColDarkRed;
-		uint8 menuTxtColLightBlue;
-		uint8 menuTxtColBlue;
-		uint8 menuTxtColBlack;
+		uint8 guiColorWhite;
+		uint8 guiColorLightRed;
+		uint8 guiColorDarkRed;
+		uint8 guiColorLightBlue;
+		uint8 guiColorBlue;
+		uint8 guiColorYellow;
+		uint8 guiColorLightGreen;
+		uint8 guiColorDarkGreen;
+		uint8 guiColorBlack;
 	} colors;
 };
 
@@ -335,6 +338,7 @@ protected:
 	bool clickedShape(int shapeIndex);
 
 	virtual const KyraRpgGUISettings *guiSettings() const = 0;
+	virtual void useMainMenuGUISettings(bool toggle) {};
 
 	int _clickedShapeXOffs;
 	int _clickedShapeYOffs;
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 0bd4ca9..aebb8ae 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -93,8 +93,8 @@ void EoBCoreEngine::loadLevel(int level, int sub) {
 
 	loadVcnData(gfxFile.c_str(), (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[level - 1]] : 0);
 	_screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2);
-	if (_flags.platform == Common::kPlatformAmiga)
-		_screen->setScreenPalette(_screen->getPalette(0));
+	//if (_flags.platform == Common::kPlatformAmiga)
+	//	_screen->setScreenPalette(_screen->getPalette(0));
 
 	delayUntil(end);
 	snd_stopSound();
diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index bfe338b..f521b9b 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -83,12 +83,12 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 	static const uint16 charPortraitPosY[] = { 2, 54, 106 };
 
 	EoBCharacter *c = &_characters[index];
-	int txtCol1 = guiSettings()->colors.menuTxtColBlack;
-	int txtCol2 = guiSettings()->colors.menuTxtColWhite;
+	int txtCol1 = guiSettings()->colors.guiColorBlack;
+	int txtCol2 = guiSettings()->colors.guiColorWhite;
 
 	if ((_flags.gameID == GI_EOB1 && c->flags & 6) || (_flags.gameID == GI_EOB2 && c->flags & 0x0E)) {
-		txtCol1 = guiSettings()->colors.menuTxtColDarkRed;
-		txtCol2 = guiSettings()->colors.menuTxtColLightRed;
+		txtCol1 = guiSettings()->colors.guiColorDarkRed;
+		txtCol2 = guiSettings()->colors.guiColorLightRed;
 	}
 
 	if (_currentControlMode == 0) {
@@ -101,7 +101,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		int cp = _screen->setCurPage(2);
 
 		if (index == _exchangeCharacterId)
-			_screen->printText(_characterGuiStringsSt[0], x2 + 2, y2 + 2, guiSettings()->colors.menuTxtColDarkRed, guiSettings()->colors.fill);
+			_screen->printText(_characterGuiStringsSt[0], x2 + 2, y2 + 2, guiSettings()->colors.guiColorDarkRed, guiSettings()->colors.fill);
 		else
 			_screen->printText(c->name, x2 + 2, y2 + (_flags.platform == Common::kPlatformFMTowns ? 1 : 2), txtCol1, guiSettings()->colors.fill);
 
@@ -116,7 +116,7 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		if (c->damageTaken > 0) {
 			_screen->drawShape(2, _redSplatShape, x2 + 13, y2 + 30, 0);
 			Common::String tmpStr = Common::String::format("%d", c->damageTaken);
-			_screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, (_configRenderMode == Common::kRenderCGA) ? 12 : guiSettings()->colors.menuTxtColWhite, 0);
+			_screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, (_configRenderMode == Common::kRenderCGA) ? 12 : guiSettings()->colors.guiColorWhite, 0);
 		}
 
 		_screen->setCurPage(cp);
@@ -130,23 +130,23 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		_screen->copyRegion(176, 0, 0, 0, 144, 168, 2, 2, Screen::CR_NO_P_CHECK);
 		_screen->_curPage = 2;
 		gui_drawFaceShape(index);
-		_screen->printShadedText(c->name, 219, 6, txtCol2, 0, guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(c->name, 219, 6, txtCol2, 0, guiSettings()->colors.guiColorBlack);
 		gui_drawHitpoints(index);
 		gui_drawFoodStatusGraph(index);
 
 		if (_currentControlMode == 1) {
 			if (c->hitPointsCur == -10)
-				_screen->printShadedText(_characterGuiStringsSt[1], 247, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_characterGuiStringsSt[1], 247, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
 			else if (c->hitPointsCur < 1)
-				_screen->printShadedText(_characterGuiStringsSt[2], 226, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_characterGuiStringsSt[2], 226, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
 			else if (c->effectFlags & 0x2000)
-				_screen->printShadedText(_characterGuiStringsSt[3], 220, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_characterGuiStringsSt[3], 220, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
 			else if (c->flags & 2)
-				_screen->printShadedText(_characterGuiStringsSt[4], 235, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_characterGuiStringsSt[4], 235, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
 			else if (c->flags & 4)
-				_screen->printShadedText(_characterGuiStringsSt[5], 232, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_characterGuiStringsSt[5], 232, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
 			else if (c->flags & 8)
-				_screen->printShadedText(_characterGuiStringsSt[6], 232, 158, guiSettings()->colors.menuTxtColLightRed, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_characterGuiStringsSt[6], 232, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
 
 			for (int i = 0; i < 27; i++)
 				gui_drawInventoryItem(i, 0, 2);
@@ -161,36 +161,36 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 			for (int i = 0; i < 3; i++)
 				_screen->fillRect(cm2X1[i], cm2Y1[i], cm2X2[i], cm2Y2[i], guiSettings()->colors.sfill);
 
-			_screen->printShadedText(_characterGuiStringsIn[0], 183, 42, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill, guiSettings()->colors.menuTxtColBlack);
-			_screen->printText(_chargenClassStrings[c->cClass], 183, 55, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
-			_screen->printText(_chargenAlignmentStrings[c->alignment], 183, 62, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
-			_screen->printText(_chargenRaceSexStrings[c->raceSex], 183, 69, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+			_screen->printShadedText(_characterGuiStringsIn[0], 183, 42, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+			_screen->printText(_chargenClassStrings[c->cClass], 183, 55, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
+			_screen->printText(_chargenAlignmentStrings[c->alignment], 183, 62, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
+			_screen->printText(_chargenRaceSexStrings[c->raceSex], 183, 69, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
 
 			for (int i = 0; i < 6; i++)
-				_screen->printText(_chargenStatStrings[6 + i], 183, 82 + i * 7, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+				_screen->printText(_chargenStatStrings[6 + i], 183, 82 + i * 7, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
 
-			_screen->printText(_characterGuiStringsIn[1], 183, 124, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
-			_screen->printText(_characterGuiStringsIn[2], 239, 138, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
-			_screen->printText(_characterGuiStringsIn[3], 278, 138, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+			_screen->printText(_characterGuiStringsIn[1], 183, 124, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
+			_screen->printText(_characterGuiStringsIn[2], 239, 138, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
+			_screen->printText(_characterGuiStringsIn[3], 278, 138, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
 
-			_screen->printText(getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), 275, 82, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
-			_screen->printText(Common::String::format("%d", c->intelligenceCur).c_str(), 275, 89, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
-			_screen->printText(Common::String::format("%d", c->wisdomCur).c_str(), 275, 96, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
-			_screen->printText(Common::String::format("%d", c->dexterityCur).c_str(), 275, 103, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
-			_screen->printText(Common::String::format("%d", c->constitutionCur).c_str(), 275, 110, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
-			_screen->printText(Common::String::format("%d", c->charismaCur).c_str(), 275, 117, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
-			_screen->printText(Common::String::format("%d", c->armorClass).c_str(), 275, 124, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+			_screen->printText(getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), 275, 82, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->intelligenceCur).c_str(), 275, 89, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->wisdomCur).c_str(), 275, 96, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->dexterityCur).c_str(), 275, 103, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->constitutionCur).c_str(), 275, 110, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->charismaCur).c_str(), 275, 117, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
+			_screen->printText(Common::String::format("%d", c->armorClass).c_str(), 275, 124, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
 
 			for (int i = 0; i < 3; i++) {
 				int t = getCharacterClassType(c->cClass, i);
 				if (t == -1)
 					continue;
 
-				_screen->printText(_chargenClassStrings[t + 15], 180, 145 + 7 * i, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.sfill);
+				_screen->printText(_chargenClassStrings[t + 15], 180, 145 + 7 * i, guiSettings()->colors.guiColorBlack, guiSettings()->colors.sfill);
 				Common::String tmpStr = Common::String::format("%d", c->experience[i]);
-				_screen->printText(tmpStr.c_str(), 251 - tmpStr.size() * 3, 145 + 7 * i, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+				_screen->printText(tmpStr.c_str(), 251 - tmpStr.size() * 3, 145 + 7 * i, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
 				tmpStr = Common::String::format("%d", c->level[i]);
-				_screen->printText(tmpStr.c_str(), 286 - tmpStr.size() * 3, 145 + 7 * i, guiSettings()->colors.menuTxtColWhite, guiSettings()->colors.sfill);
+				_screen->printText(tmpStr.c_str(), 286 - tmpStr.size() * 3, 145 + 7 * i, guiSettings()->colors.guiColorWhite, guiSettings()->colors.sfill);
 			}
 		}
 
@@ -323,7 +323,7 @@ void EoBCoreEngine::gui_drawWeaponSlotStatus(int x, int y, int status) {
 		break;
 	}
 
-	int textColor = (_configRenderMode == Common::kRenderCGA) ? 2 : guiSettings()->colors.menuTxtColWhite;
+	int textColor = (_configRenderMode == Common::kRenderCGA) ? 2 : guiSettings()->colors.guiColorWhite;
 
 	if (!tmpStr2.empty()) {
 		_screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 2, textColor, 0);
@@ -342,14 +342,12 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 
 	static const uint8 xCoords[] = { 23, 95 };
 	static const uint8 yCoords[] = { 46, 98, 150 };
-	static const uint8 barColorDefault[] = { 3, 5, 8 };
-	static const uint8 barColorAmiga[] = { 27, 7, 25 };
-	const uint8 *barColor = (_flags.platform == Common::kPlatformAmiga) ? barColorAmiga : barColorDefault;
 
 	int x = xCoords[index & 1];
 	int y = yCoords[index >> 1];
 	int w = 38;
 	int h = 3;
+	uint8 bgCol = guiSettings()->colors.fill;
 
 	if (!_screen->_curPage)
 		x += 176;
@@ -359,6 +357,8 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 		y = 16;
 		w = 51;
 		h = 5;
+		if (_flags.platform == Common::kPlatformAmiga)
+			bgCol = guiSettings()->colors.sfill;
 	}
 
 	EoBCharacter *c = &_characters[index];
@@ -366,15 +366,15 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 	if (_configHpBarGraphs) {
 		int bgCur = c->hitPointsCur + 10;
 		int bgMax = c->hitPointsMax + 10;
-		int col = ((bgMax / 3) > bgCur) ? 1 : 0;
+		int col = ((bgMax / 3) > bgCur) ? guiSettings()->colors.guiColorYellow : guiSettings()->colors.guiColorDarkGreen;
 		if (bgCur <= 10)
-			col = 2;
+			col = guiSettings()->colors.guiColorDarkRed;
 
 		if (!_currentControlMode)
-			_screen->printText(_characterGuiStringsHp[0], x - 13, y - 1, guiSettings()->colors.menuTxtColBlack, 0);
+			_screen->printText(_characterGuiStringsHp[0], x - 13, y - 1, guiSettings()->colors.guiColorBlack, 0);
 
 
-		gui_drawHorizontalBarGraph(x, y, w, h, bgCur, bgMax, barColor[col], guiSettings()->colors.barGraph);
+		gui_drawHorizontalBarGraph(x, y, w, h, bgCur, bgMax, col, guiSettings()->colors.barGraph);
 
 	} else {
 		Common::String tmpString = Common::String::format(_characterGuiStringsHp[1], c->hitPointsCur, c->hitPointsMax);
@@ -384,7 +384,7 @@ void EoBCoreEngine::gui_drawHitpoints(int index) {
 			y -= 1;
 		}
 
-		_screen->printText(tmpString.c_str(), x, y, guiSettings()->colors.menuTxtColBlack, guiSettings()->colors.fill);
+		_screen->printText(tmpString.c_str(), x, y, guiSettings()->colors.guiColorBlack, bgCol);
 	}
 }
 
@@ -402,11 +402,7 @@ void EoBCoreEngine::gui_drawFoodStatusGraph(int index) {
 	if (index != _updateCharNum)
 		return;
 
-	static const uint8 barColorDefault[] = { 3, 5, 8 };
-	static const uint8 barColorAmiga[] = { 27, 7, 25 };
-	const uint8 *barColor = (_flags.platform == Common::kPlatformAmiga) ? barColorAmiga : barColorDefault;
-
-	uint8 col = c->food < 20 ? barColor[2] : (c->food < 33 ? barColor[1] : barColor[0]);
+	uint8 col = c->food < 20 ? guiSettings()->colors.guiColorDarkRed : (c->food < 33 ? guiSettings()->colors.guiColorYellow : guiSettings()->colors.guiColorDarkGreen);
 	gui_drawHorizontalBarGraph(250, 25, 51, 5, c->food, 100, col, guiSettings()->colors.barGraph);
 }
 
@@ -416,7 +412,7 @@ void EoBCoreEngine::gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32
 }
 
 void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
-	uint8 redGreenColor = (_partyEffectFlags & 0x20000) ? 4 : ((_configRenderMode == Common::kRenderCGA) ? 3 : 6);
+	uint8 redGreenColor = (_partyEffectFlags & 0x20000) ? guiSettings()->colors.guiColorLightGreen : ((_configRenderMode == Common::kRenderCGA) ? 3 : guiSettings()->colors.guiColorLightRed);
 
 	static const uint8 xCoords[] = { 8, 80 };
 	static const uint8 yCoords[] = { 2, 54, 106 };
@@ -439,7 +435,7 @@ void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
 		}
 
 		if (yellow && !redGreen) {
-			_screen->drawBox(x, y, x + 63, y + 49, 5);
+			_screen->drawBox(x, y, x + 63, y + 49, guiSettings()->colors.guiColorYellow);
 			return;
 		}
 
@@ -453,8 +449,8 @@ void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
 				_screen->drawClippedLine(x + 8, y + 49, x + 15, y + 49, redGreenColor);
 			}
 			if (yellow) {
-				_screen->drawClippedLine(x + 8, y, x + 15, y, 5);
-				_screen->drawClippedLine(x, y + 49, x + 7, y + 49, 5);
+				_screen->drawClippedLine(x + 8, y, x + 15, y, guiSettings()->colors.guiColorYellow);
+				_screen->drawClippedLine(x, y + 49, x + 7, y + 49, guiSettings()->colors.guiColorYellow);
 			}
 		}
 
@@ -464,8 +460,8 @@ void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
 			y = iY + i - 1;
 
 			if (yellow) {
-				_screen->drawClippedLine(x, y + 1, x, y + 6, 5);
-				_screen->drawClippedLine(x + 63, y + 7, x + 63, y + 12, 5);
+				_screen->drawClippedLine(x, y + 1, x, y + 6, guiSettings()->colors.guiColorYellow);
+				_screen->drawClippedLine(x + 63, y + 7, x + 63, y + 12, guiSettings()->colors.guiColorYellow);
 			}
 			if (redGreen) {
 				_screen->drawClippedLine(x, y + 7, x, y + 12, redGreenColor);
@@ -476,8 +472,8 @@ void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
 	} else {
 		_screen->drawClippedLine(x, y, x + 62, y, guiSettings()->colors.frame2);
 		_screen->drawClippedLine(x, y + 49, x + 62, y + 49, guiSettings()->colors.frame1);
-		_screen->drawClippedLine(x - xOffset, y, x - xOffset, y + 50, 12);
-		_screen->drawClippedLine(x + 63, y, x + 63, y + 50, 12);
+		_screen->drawClippedLine(x - xOffset, y, x - xOffset, y + 50, guiSettings()->colors.guiColorBlack);
+		_screen->drawClippedLine(x + 63, y, x + 63, y + 50, guiSettings()->colors.guiColorBlack);
 	}
 }
 
@@ -504,11 +500,11 @@ void EoBCoreEngine::gui_drawInventoryItem(int slot, int redraw, int pageNum) {
 		gui_drawBox(x - 1, y - 1, wh, wh, col1, col2, slot == 16 ? -1 : guiSettings()->colors.fill);
 
 		if (slot == 16) {
-			_screen->fillRect(227, 65, 238, 69, guiSettings()->colors.menuTxtColBlack);
+			_screen->fillRect(227, 65, 238, 69, guiSettings()->colors.guiColorBlack);
 			int cnt = countQueuedItems(_characters[_updateCharNum].inventory[slot], -1, -1, 1, 1);
 			x = cnt >= 10 ? 227 : 233;
 			Common::String str = Common::String::format("%d", cnt);
-			_screen->printText(str.c_str(), x, 65, guiSettings()->colors.menuTxtColWhite, 0);
+			_screen->printText(str.c_str(), x, 65, guiSettings()->colors.guiColorWhite, 0);
 		}
 	}
 
@@ -574,12 +570,12 @@ void EoBCoreEngine::gui_drawSpellbook() {
 
 		if (_flags.gameID == GI_EOB1) {
 			gui_drawBox(i * 21 + 71, 122, 21, 9, col1, col2, col3);
-			_screen->printText(_magicStrings7[i], i * 21 + 73, 123, guiSettings()->colors.menuTxtColBlack, 0);
+			_screen->printText(_magicStrings7[i], i * 21 + 73, 123, guiSettings()->colors.guiColorBlack, 0);
 		} else {
 			_screen->set16bitShadingLevel(4);
 			gui_drawBox(i * 18 + 68, 121, 18, 9, col1, col2, col3);
 			_screen->set16bitShadingLevel(0);
-			_screen->printText(Common::String::format("%d", i + 1).c_str(), i * 18 + 75, 123, guiSettings()->colors.menuTxtColBlack, 0);
+			_screen->printText(Common::String::format("%d", i + 1).c_str(), i * 18 + 75, 123, guiSettings()->colors.guiColorBlack, 0);
 		}
 	}
 
@@ -596,8 +592,8 @@ void EoBCoreEngine::gui_drawSpellbook() {
 		gui_drawSpellbookScrollArrow(165, 169, 1);
 	}
 
-	int textCol1 = (_configRenderMode == Common::kRenderCGA) ? 3 : guiSettings()->colors.menuTxtColWhite;
-	int textCol2 = guiSettings()->colors.menuTxtColDarkRed;
+	int textCol1 = (_configRenderMode == Common::kRenderCGA) ? 3 : guiSettings()->colors.guiColorWhite;
+	int textCol2 = guiSettings()->colors.guiColorDarkRed;
 	int textXa = 74;
 	int textXs = 71;
 	int textY = 170;
@@ -1953,9 +1949,9 @@ void GUI_EoB::simpleMenu_setup(int sd, int maxItem, const char *const *strings,
 	for (int i = 0; i < _menuNumItems; i++) {
 		int item = simpleMenu_getMenuItem(i, menuItemsMask, itemOffset);
 		int ty = y + i * (lineSpacing + _screen->getFontHeight());
-		_screen->printShadedText(strings[item], x, ty, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(strings[item], x, ty, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 		if (item == v)
-			_screen->printText(strings[item], x, ty, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
+			_screen->printText(strings[item], x, ty, _vm->guiSettings()->colors.guiColorLightRed, 0);
 	}
 
 	_screen->updateScreen();
@@ -2006,14 +2002,14 @@ int GUI_EoB::simpleMenu_process(int sd, const char *const *strings, void *b, int
 	}
 
 	if (newItem != currentItem) {
-		_screen->printText(strings[simpleMenu_getMenuItem(currentItem, menuItemsMask, itemOffset)], x, y + currentItem * lineH, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite, 0);
-		_screen->printText(strings[simpleMenu_getMenuItem(newItem,  menuItemsMask, itemOffset)], x, y + newItem * lineH , _vm->guiSettings()->colors.menuTxtColLightRed, 0);
+		_screen->printText(strings[simpleMenu_getMenuItem(currentItem, menuItemsMask, itemOffset)], x, y + currentItem * lineH, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.guiColorWhite, 0);
+		_screen->printText(strings[simpleMenu_getMenuItem(newItem,  menuItemsMask, itemOffset)], x, y + newItem * lineH , _vm->guiSettings()->colors.guiColorLightRed, 0);
 		_screen->updateScreen();
 	}
 
 	if (result != -1) {
 		result = simpleMenu_getMenuItem(result, menuItemsMask, itemOffset);
-		simpleMenu_flashSelection(strings[result], x, y + newItem * lineH, _vm->guiSettings()->colors.menuTxtColWhite, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
+		simpleMenu_flashSelection(strings[result], x, y + newItem * lineH, _vm->guiSettings()->colors.guiColorWhite, _vm->guiSettings()->colors.guiColorLightRed, 0);
 	}
 
 	_menuCur = newItem;
@@ -2292,7 +2288,7 @@ void GUI_EoB::runCampMenu() {
 	_vm->writeSettings();
 }
 
-bool GUI_EoB::runLoadMenu(int x, int y) {
+bool GUI_EoB::runLoadMenu(int x, int y, bool fromMainMenu) {
 	const ScreenDim *dm = _screen->getScreenDim(11);
 	int xo = dm->sx;
 	int yo = dm->sy;
@@ -2302,15 +2298,24 @@ bool GUI_EoB::runLoadMenu(int x, int y) {
 
 	for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
 		updateSaveSlotsList(_vm->_targetName);
+		
+		_vm->useMainMenuGUISettings(fromMainMenu);
 		int slot = selectSaveSlotDialogue(x, y, 1);
+		_vm->useMainMenuGUISettings(false);
+
 		if (slot > 5) {
 			runLoop = result = false;
 		} else if (slot >= 0) {
 			if (_saveSlotIdTemp[slot] == -1) {
-				messageDialogue(11, 65, _vm->guiSettings()->colors.menuTxtColLightRed);
+				_vm->useMainMenuGUISettings(fromMainMenu);
+				messageDialogue(11, 65, _vm->guiSettings()->colors.guiColorLightRed);
+				_vm->useMainMenuGUISettings(false);
 			} else {
-				if (_vm->loadGameState(_saveSlotIdTemp[slot]).getCode() != Common::kNoError)
-					messageDialogue(11, 16, _vm->guiSettings()->colors.menuTxtColLightRed);
+				if (_vm->loadGameState(_saveSlotIdTemp[slot]).getCode() != Common::kNoError) {
+					_vm->useMainMenuGUISettings(fromMainMenu);
+					messageDialogue(11, 16, _vm->guiSettings()->colors.guiColorLightRed);
+					_vm->useMainMenuGUISettings(false);
+				}
 				runLoop = false;
 				result = true;
 			}
@@ -2318,6 +2323,7 @@ bool GUI_EoB::runLoadMenu(int x, int y) {
 	}
 
 	_screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+
 	return result;
 }
 
@@ -2370,7 +2376,7 @@ bool GUI_EoB::confirmDialogue2(int dim, int id, int deflt) {
 
 		if (newHighlight != lastHighlight) {
 			for (int i = 0; i < 2; i++)
-				_screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (_screen->getTextWidth(_vm->_menuYesNoStrings[i]) / 2) + 1, y + 3, i == newHighlight ? _vm->guiSettings()->colors.menuTxtColLightRed : _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (_screen->getTextWidth(_vm->_menuYesNoStrings[i]) / 2) + 1, y + 3, i == newHighlight ? _vm->guiSettings()->colors.guiColorLightRed : _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 			_screen->updateScreen();
 			lastHighlight = newHighlight;
 		}
@@ -2402,7 +2408,7 @@ void GUI_EoB::messageDialogue(int dim, int id, int buttonTextCol) {
 	int bw = _screen->getTextWidth(_vm->_menuOkString) + 7;
 
 	drawMenuButtonBox(bx, by, bw, 14, false, false);
-	_screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->updateScreen();
 
 	for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
@@ -2433,7 +2439,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
 	_screen->_curPage = 2;
 	_screen->setClearScreenDim(dim);
 	drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
-	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx << 3) + 5, _screen->_curDim->sy + 5, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx << 3) + 5, _screen->_curDim->sy + 5, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->_curPage = 0;
 	_screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK);
 
@@ -2441,7 +2447,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
 	int y = _screen->_curDim->sy + _screen->_curDim->h - 21;
 	int w = _screen->getTextWidth(_vm->_menuOkString) + 8;
 	drawMenuButtonBox(x, y, w, 14, false, false);
-	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->updateScreen();
 
 	for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
@@ -2462,7 +2468,7 @@ void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
 	_screen->updateScreen();
 	_vm->_system->delayMillis(80);
 	drawMenuButtonBox(x, y, w, 14, false, false);
-	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->updateScreen();
 
 }
@@ -2519,7 +2525,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 	_screen->copyRegion((x - 1) << 3, y, 0, 191, (destMaxLen + 2) << 3, 9, 0, 2, Screen::CR_NO_P_CHECK);
 	if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
 		_screen->copyRegion(0, 0, 160, 0, 160, 128, 2, 2, Screen::CR_NO_P_CHECK);
-	_screen->printShadedText(dest, x << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(dest, x << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.guiColorBlack);
 
 	uint32 next = _vm->_system->getMillis() + 2 * _vm->_tickLength;
 	sufx[0] = (pos < len) ? dest[pos] : 32;
@@ -2538,7 +2544,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 			if (next <= _vm->_system->getMillis()) {
 				if (cursorState) {
 					_screen->copyRegion((pos + 1) << 3, 191, (x + pos) << 3, y, 8, 9, 2, 0, Screen::CR_NO_P_CHECK);
-					_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
+					_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.guiColorBlack);
 				} else {
 					_screen->fillRect((x + pos) << 3, y, ((x + pos) << 3) + 7, y + 7, cursorColor);
 					_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
@@ -2653,7 +2659,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 		}
 
 		_screen->copyRegion(0, 191, (x - 1) << 3, y, (destMaxLen + 2) << 3, 9, 2, 0, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(dest, x << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(dest, x << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.guiColorBlack);
 		
 		if (_vm->_flags.platform == Common::kPlatformFMTowns) {
 			if (pos < len) {
@@ -2670,7 +2676,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 		if (cursorState)
 			_screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
 		else
-			_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2, _vm->guiSettings()->colors.guiColorBlack);
 		_screen->updateScreen();
 
 	} while (_keyPressed.keycode != Common::KEYCODE_RETURN && _keyPressed.keycode != Common::KEYCODE_ESCAPE && !_vm->shouldQuit());
@@ -2704,7 +2710,7 @@ int GUI_EoB::checkKatakanaSelection() {
 
 			if (_csjis[0] != '\x81' || _csjis[1] != '\x40') {
 				highlight = lineOffs << 8 | column;
-				_screen->printShadedText(_csjis, x & ~7, y & ~15, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+				_screen->printShadedText(_csjis, x & ~7, y & ~15, _vm->guiSettings()->colors.guiColorLightRed, 0, _vm->guiSettings()->colors.guiColorBlack);
 			}
 
 			x = 288; y = 168;
@@ -2717,7 +2723,7 @@ int GUI_EoB::checkKatakanaSelection() {
 				continue;
 
 			highlight = 0x400 | i;
-			_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelXCrds[i], 176, _vm->guiSettings()->colors.menuTxtColLightRed, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelXCrds[i], 176, _vm->guiSettings()->colors.guiColorLightRed, 0, _vm->guiSettings()->colors.guiColorBlack);
 			i = 3;
 		}
 	}
@@ -2733,13 +2739,13 @@ int GUI_EoB::checkKatakanaSelection() {
 
 	if (_menuCur != -1) {
 		if (_menuCur & 0x400) {
-			_screen->printShadedText(_vm->_katakanaSelectStrings[_menuCur & 3], kanaSelXCrds[_menuCur & 3], 176, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(_vm->_katakanaSelectStrings[_menuCur & 3], kanaSelXCrds[_menuCur & 3], 176, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 		} else {
 			char osjis[3];
 			osjis[0] = _vm->_katakanaLines[_currentKanaPage * 4 + (_menuCur >> 8)][_menuCur & 0xFF];
 			osjis[1] = _vm->_katakanaLines[_currentKanaPage * 4 + (_menuCur >> 8)][(_menuCur & 0xFF) + 1];
 			osjis[2] = 0;
-			_screen->printShadedText(osjis, 152 + ((_menuCur & 0xFF) << 2), 112 + ((_menuCur >> 4) & ~0x0F), _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(osjis, 152 + ((_menuCur & 0xFF) << 2), 112 + ((_menuCur >> 4) & ~0x0F), _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 		}
 	}
 
@@ -2777,11 +2783,11 @@ void GUI_EoB::printKatakanaOptions(int page) {
 	_currentKanaPage = page;
 	_screen->copyRegion(160, 44, 144, 108, 160, 84, 2, 0, Screen::CR_NO_P_CHECK);
 	for (int i = 0; i < 4; i++)
-		_screen->printShadedText(_vm->_katakanaLines[page * 4 + i], 152, (i << 4) + 112, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(_vm->_katakanaLines[page * 4 + i], 152, (i << 4) + 112, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	static uint16 kanaSelCrds[] = { 224, 272, 186 };
 	for (int i = 0; i < 3; i++)
-		_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelCrds[i], 176, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(_vm->_katakanaSelectStrings[i], kanaSelCrds[i], 176, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 }
 
 void GUI_EoB::transferWaitBox() {
@@ -2848,7 +2854,7 @@ bool GUI_EoB::transferFileMenu(Common::String &targetName, Common::String &selec
 			break;
 
 		if (_saveSlotIdTemp[slot] == -1)
-			messageDialogue(11, 65, _vm->guiSettings()->colors.menuTxtColLightRed);
+			messageDialogue(11, 65, _vm->guiSettings()->colors.guiColorLightRed);
 		else {
 			_screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
 			selection = _vm->getSavegameFilename(targetName, _saveSlotIdTemp[slot]);
@@ -2919,7 +2925,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 					of = _vm->screen()->setFont(Screen::FID_6_FNT);
 					y++;
 				} else {
-					in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, _vm->guiSettings()->colors.menuTxtColBlue, 0, _vm->guiSettings()->colors.menuTxtColDarkRed);
+					in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, _vm->guiSettings()->colors.guiColorBlue, 0, _vm->guiSettings()->colors.guiColorDarkRed);
 				}
 				if (in == -1) {
 					useSlot = false;
@@ -2927,7 +2933,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 				}
 
 				if (!strlen(_saveSlotStringsTemp[slot])) {
-					messageDialogue(11, 54, _vm->guiSettings()->colors.menuTxtColLightRed);
+					messageDialogue(11, 54, _vm->guiSettings()->colors.guiColorLightRed);
 					in = -1;
 				}
 			}
@@ -2937,7 +2943,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 			}
 
 			_screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill);
-			_screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 			_screen->set16bitShadingLevel(0);
 			_screen->setFont(of);
 			_screen->updateScreen();
@@ -2950,7 +2956,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 			if (err.getCode() == Common::kNoError)
 				result = true;
 			else
-				messageDialogue(11, 15, _vm->guiSettings()->colors.menuTxtColLightRed);
+				messageDialogue(11, 15, _vm->guiSettings()->colors.guiColorLightRed);
 
 			runLoop = false;
 		}
@@ -2962,14 +2968,14 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
 
 int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
 	_saveSlotX = _saveSlotY = 0;
-	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite;
+	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.guiColorWhite;
 	_screen->setCurPage(2);
 
 	_savegameOffset = 0;
 
 	drawMenuButtonBox(0, 0, 176, 144, false, false);
 	const char *title = (id < 2) ? _vm->_saveLoadStrings[2 + id] : _vm->_transferStringsScummVM[id - 1];
-	_screen->printShadedText(title, 52, 5, col1, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(title, 52, 5, col1, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	_screen->copyRegion(0, 0, x, y, 176, 144, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->setCurPage(0);
@@ -3048,7 +3054,7 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
 
 		if (lastHighlight != newHighlight) {
 			drawSaveSlotButton(lastHighlight, 0, col1);
-			drawSaveSlotButton(newHighlight, 0, _vm->guiSettings()->colors.menuTxtColLightRed);
+			drawSaveSlotButton(newHighlight, 0, _vm->guiSettings()->colors.guiColorLightRed);
 
 			// Display highlighted slot index in the bottom left corner to avoid people getting lost with the 990 save slots
 			_screen->setFont(Screen::FID_6_FNT);
@@ -3063,10 +3069,10 @@ int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
 		}
 	}
 
-	drawSaveSlotButton(newHighlight, 2, _vm->guiSettings()->colors.menuTxtColLightRed);
+	drawSaveSlotButton(newHighlight, 2, _vm->guiSettings()->colors.guiColorLightRed);
 	_screen->updateScreen();
 	_vm->_system->delayMillis(80);
-	drawSaveSlotButton(newHighlight, 1, _vm->guiSettings()->colors.menuTxtColLightRed);
+	drawSaveSlotButton(newHighlight, 1, _vm->guiSettings()->colors.guiColorLightRed);
 	_screen->updateScreen();
 
 	return newHighlight;
@@ -3215,7 +3221,7 @@ void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) {
 		if (updateDesc) {
 			updateDesc = false;
 			_screen->set16bitShadingLevel(4);
-			_screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.guiColorBlack);
 			_screen->set16bitShadingLevel(0);
 		}
 
@@ -3408,7 +3414,7 @@ void GUI_EoB::scribeScrollDialogue() {
 						buttonList = initMenu(6);
 
 						for (int i = 0; i < s; i++)
-							_screen->printShadedText(_vm->_mageSpellList[menuItems[i]], 8, 9 * i + 50, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+							_screen->printShadedText(_vm->_mageSpellList[menuItems[i]], 8, 9 * i + 50, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 						redraw = false;
 						lastHighLight = -1;
@@ -3417,9 +3423,9 @@ void GUI_EoB::scribeScrollDialogue() {
 
 					if (lastHighLight != newHighLight) {
 						if (lastHighLight >= 0)
-							_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, _vm->guiSettings()->colors.menuTxtColWhite, 0);
+							_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, _vm->guiSettings()->colors.guiColorWhite, 0);
 						lastHighLight = newHighLight;
-						_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, _vm->guiSettings()->colors.menuTxtColLightRed, 0);
+						_screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, _vm->guiSettings()->colors.guiColorLightRed, 0);
 						_screen->updateScreen();
 					}
 
@@ -3761,7 +3767,7 @@ bool GUI_EoB::confirmDialogue(int id) {
 
 	Button *buttonList = initMenu(5);
 
-	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 4, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(getMenuString(id), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 4, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	int newHighlight = 0;
 	int lastHighlight = -1;
@@ -3983,7 +3989,7 @@ void GUI_EoB::displayTextBox(int id) {
 	const ScreenDim *dm = _screen->getScreenDim(11);
 
 	drawMenuButtonBox(dm->sx << 3, dm->sy, dm->w << 3, dm->h, false, false);
-	_screen->printShadedText(getMenuString(id), (dm->sx << 3) + 5, dm->sy + 5, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(getMenuString(id), (dm->sx << 3) + 5, dm->sy + 5, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->updateScreen();
 
@@ -4012,7 +4018,7 @@ Button *GUI_EoB::initMenu(int id) {
 		drawMenuButtonBox(dm->sx << 3, dm->sy, dm->w << 3, dm->h, false, false);
 	}
 
-	_screen->printShadedText(getMenuString(m->titleStrId), 5, 5, m->titleCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(getMenuString(m->titleStrId), 5, 5, m->titleCol, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	Button *buttons = 0;
 	for (int i = 0; i < m->numButtons; i++) {
@@ -4069,12 +4075,12 @@ void GUI_EoB::drawMenuButton(Button *b, bool clicked, bool highlight, bool noFil
 			yOffs = (b->height - 7) >> 1;
 		}
 
-		int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite;
+		int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.guiColorWhite;
 
 		if (noFill || clicked)
-			_screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, 0);
+			_screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? _vm->guiSettings()->colors.guiColorLightRed : col1, 0);
 		else
-			_screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? _vm->guiSettings()->colors.guiColorLightRed : col1, 0, _vm->guiSettings()->colors.guiColorBlack);
 	}
 }
 
@@ -4103,7 +4109,7 @@ void GUI_EoB::drawTextBox(int dim, int id) {
 	_screen->setCurPage(2);
 
 	drawMenuButtonBox(0, 0, dm->w << 3, dm->h, false, false);
-	_screen->printShadedText(getMenuString(id), 5, 5, _vm->guiSettings()->colors.menuTxtColWhite, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(getMenuString(id), 5, 5, _vm->guiSettings()->colors.guiColorWhite, 0, _vm->guiSettings()->colors.guiColorBlack);
 
 	_screen->setCurPage(0);
 	_screen->copyRegion(0, 0, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
@@ -4137,7 +4143,7 @@ void GUI_EoB::drawSaveSlotButton(int slot, int redrawBox, int textCol) {
 		y++;
 	}
 
-	_screen->printShadedText(slotString, x + 4, y + 3, textCol, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(slotString, x + 4, y + 3, textCol, 0, _vm->guiSettings()->colors.guiColorBlack);
 	_vm->screen()->setFont(fnt);
 }
 
@@ -4146,7 +4152,7 @@ void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int sp
 		return;
 
 	int y = bookPageIndex * 9 + 50;
-	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.menuTxtColWhite;
+	int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : _vm->guiSettings()->colors.guiColorWhite;
 	_screen->set16bitShadingLevel(4);
 
 	if (spellId) {
@@ -4161,9 +4167,9 @@ void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int sp
 		}
 
 		if (noFill)
-			_screen->printText(s.c_str(), 8, y, highLight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, 0);
+			_screen->printText(s.c_str(), 8, y, highLight ? _vm->guiSettings()->colors.guiColorLightRed : col1, 0);
 		else
-			_screen->printShadedText(s.c_str(), 8, y, highLight ? _vm->guiSettings()->colors.menuTxtColLightRed : col1, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.menuTxtColBlack);
+			_screen->printShadedText(s.c_str(), 8, y, highLight ? _vm->guiSettings()->colors.guiColorLightRed : col1, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.guiColorBlack);
 	} else {
 		_screen->fillRect(6, y, 168, y + 8,  _vm->guiSettings()->colors.fill);
 	}
@@ -4308,13 +4314,13 @@ void GUI_EoB::restParty_updateRestTime(int hours, bool init) {
 		_vm->_txt->clearCurDim();
 		drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
 		_screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 0, 2, Screen::CR_NO_P_CHECK);
-		_screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0, _vm->guiSettings()->colors.menuTxtColBlack);
+		_screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0, _vm->guiSettings()->colors.guiColorBlack);
 	}
 
 	_screen->setCurPage(0);
 	_screen->set16bitShadingLevel(4);
 	_screen->fillRect((_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, ((_screen->_curDim->sx + 19) << 3) + 1, _screen->_curDim->sy + 29, _vm->guiSettings()->colors.fill);
-	_screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, _vm->guiSettings()->colors.menuTxtColWhite, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.menuTxtColBlack);
+	_screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, _vm->guiSettings()->colors.guiColorWhite, _vm->guiSettings()->colors.fill, _vm->guiSettings()->colors.guiColorBlack);
 	_screen->set16bitShadingLevel(0);
 	_screen->updateScreen();
 	_vm->delay(160);
diff --git a/engines/kyra/gui/gui_eob.h b/engines/kyra/gui/gui_eob.h
index 82721fc..0e10d56 100644
--- a/engines/kyra/gui/gui_eob.h
+++ b/engines/kyra/gui/gui_eob.h
@@ -60,7 +60,7 @@ public:
 
 	// Button based menus (camp menu, load menu)
 	void runCampMenu();
-	bool runLoadMenu(int x, int y);
+	bool runLoadMenu(int x, int y, bool fromMainMenu = false);
 
 	bool confirmDialogue2(int dim, int id, int deflt);
 	void messageDialogue(int dim, int id, int buttonTextCol);
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index ed2f368..281cb7f 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -804,8 +804,8 @@ void EoBCoreEngine::initMenus() {
 
 	if (_flags.platform == Common::kPlatformAmiga) {
 		// assign Amiga text colors
-		_menuDefs[0].titleCol = _menuDefs[1].titleCol = _menuDefs[2].titleCol = _menuDefs[4].titleCol = _menuDefs[6].titleCol = guiSettings()->colors.menuTxtColLightBlue;
-		_menuDefs[3].titleCol = _menuDefs[5].titleCol = guiSettings()->colors.menuTxtColWhite;
+		_menuDefs[0].titleCol = _menuDefs[1].titleCol = _menuDefs[2].titleCol = _menuDefs[4].titleCol = _menuDefs[6].titleCol = guiSettings()->colors.guiColorLightBlue;
+		_menuDefs[3].titleCol = _menuDefs[5].titleCol = guiSettings()->colors.guiColorWhite;
 	}
 }
 
@@ -1290,17 +1290,22 @@ void EoBEngine::initSpells() {
 
 const KyraRpgGUISettings EoBEngine::_guiSettingsVGA = {
 	{ 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
-	{ 135, 130, 132, 180, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180, 15, 6, 8, 9, 2, 12 }
+	{ 135, 130, 132, 180, 133, 17, 23, 20, 184, 177, 180, 184, 177, 180, 15, 6, 8, 9, 2, 5, 4, 3, 12 }
 };
 
 const KyraRpgGUISettings EoBEngine::_guiSettingsEGA = {
 	{ 9, 15, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
-	{ 13, 9, 2, 14, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14, 15, 6, 8, 9, 2, 12 }
+	{ 13, 9, 2, 14, 2, 6, 13, 8, 13, 15, 14, 13, 15, 14, 15, 6, 8, 9, 2, 5, 4, 3, 12 }
 };
 
 const KyraRpgGUISettings EoBEngine::_guiSettingsAmiga = {
 	{ 28, 31, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
-	{ 18, 17, 10, 17, 11, 24, 22, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 19 }
+	{ 18, 17, 10, 17, 11, 24, 22, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 7, 26, 27, 19 }
+};
+
+const KyraRpgGUISettings EoBEngine::_guiSettingsAmigaMainMenu = {
+	{ 28, 31, 95, 9, 7, { 285, 139 }, { 189, 162 }, { 31, 31 } },
+	{ 22, 28, 30, 17, 11, 24, 22, 25, 18, 9, 10, 18, 9, 10, 31, 24, 25, 28, 29, 7, 26, 27, 19 }
 };
 
 const uint8 EoBEngine::_egaDefaultPalette[] = {
@@ -1401,12 +1406,12 @@ void DarkMoonEngine::initSpells() {
 
 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsFMTowns = {
 	{ 9, 15, 95, 11, 7, { 221, 76 }, { 187, 162 }, { 95, 95 } },
-	{ 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 12 }
+	{ 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 5, 4, 3, 12 }
 };
 
 const KyraRpgGUISettings DarkMoonEngine::_guiSettingsDOS = {
 	{ 9, 15, 95, 9, 7, { 221, 76 }, { 189, 162 }, { 95, 95 } },
-	{ 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 12 }
+	{ 186, 181, 183, 183, 184, 17, 23, 20, 186, 181, 183, 182, 177, 180, 15, 6, 8, 9, 2, 5, 4, 3, 12 }
 };
 
 const uint8 DarkMoonEngine::_egaDefaultPalette[] = {
diff --git a/engines/kyra/resource/staticres_lol.cpp b/engines/kyra/resource/staticres_lol.cpp
index d2fbcef..24076aa 100644
--- a/engines/kyra/resource/staticres_lol.cpp
+++ b/engines/kyra/resource/staticres_lol.cpp
@@ -779,7 +779,7 @@ const int8 LoLEngine::_mapCoords[12][4] = {
 
 const KyraRpgGUISettings LoLEngine::_guiSettings = {
 	{ 144, 254, 74, 9, 80, { 0, 0 }, { 0, 0 }, { 0, 0 } },
-	{ 136, 251, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+	{ 136, 251, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
 const MistOfDoomAnimData LoLEngine::_mistAnimData[] = {
diff --git a/engines/kyra/text/text_rpg.cpp b/engines/kyra/text/text_rpg.cpp
index d865fc7..6f1ed2a 100644
--- a/engines/kyra/text/text_rpg.cpp
+++ b/engines/kyra/text/text_rpg.cpp
@@ -49,12 +49,12 @@ TextDisplayer_rpg::TextDisplayer_rpg(KyraRpgEngine *engine, Screen *scr) : _vm(e
 		_colorMap[i] = i;
 
 	if (_vm->game() != GI_LOL) {
-		_colorMap[15] = _vm->guiSettings()->colors.menuTxtColWhite;
-		_colorMap[6] = _vm->guiSettings()->colors.menuTxtColLightRed;
-		_colorMap[8] = _vm->guiSettings()->colors.menuTxtColDarkRed;
-		_colorMap[9] = _vm->guiSettings()->colors.menuTxtColLightBlue;
-		_colorMap[2] = _vm->guiSettings()->colors.menuTxtColBlue;
-		_colorMap[12] = _vm->guiSettings()->colors.menuTxtColBlack;
+		_colorMap[15] = _vm->guiSettings()->colors.guiColorWhite;
+		_colorMap[6] = _vm->guiSettings()->colors.guiColorLightRed;
+		_colorMap[8] = _vm->guiSettings()->colors.guiColorDarkRed;
+		_colorMap[9] = _vm->guiSettings()->colors.guiColorLightBlue;
+		_colorMap[2] = _vm->guiSettings()->colors.guiColorBlue;
+		_colorMap[12] = _vm->guiSettings()->colors.guiColorBlack;
 	}
 
 	for (int i = 0; i < _screen->screenDimTableCount(); i++) {


Commit: 30ed036f6e42d9f4caa9d0eafe343e72cc318c66
    https://github.com/scummvm/scummvm/commit/30ed036f6e42d9f4caa9d0eafe343e72cc318c66
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:23+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix environmental sfx

Changed paths:
    engines/kyra/engine/kyra_rpg.cpp
    engines/kyra/sound/sound_amiga_eob.cpp


diff --git a/engines/kyra/engine/kyra_rpg.cpp b/engines/kyra/engine/kyra_rpg.cpp
index 46fef3f..6164024 100644
--- a/engines/kyra/engine/kyra_rpg.cpp
+++ b/engines/kyra/engine/kyra_rpg.cpp
@@ -204,7 +204,7 @@ Common::Error KyraRpgEngine::init() {
 
 	initStaticResource();
 
-	_envSfxDistThreshold = (_flags.gameID == GI_EOB2 || _sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : 3;
+	_envSfxDistThreshold = ((_flags.gameID == GI_EOB2 && _sound->getSfxType() == Sound::kTowns) || _sound->getSfxType() == Sound::kAdLib || _sound->getSfxType() == Sound::kPCSpkr) ? 15 : (_sound->getSfxType() == Sound::kAmiga ? 4 : 3);
 
 	_dialogueButtonLabelColor1 = guiSettings()->buttons.labelColor1;
 	_dialogueButtonLabelColor2 = guiSettings()->buttons.labelColor2;
@@ -367,7 +367,13 @@ bool KyraRpgEngine::snd_processEnvironmentalSoundEffect(int soundId, int block)
 	}
 
 	_environmentSfx = soundId;
-	_environmentSfxVol = (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns) ? (dist ? (16 - dist) * 8 - 1 : 127) : ((15 - ((block || (_flags.gameID == GI_LOL && dist < 2)) ? dist : 0)) << 4);
+
+	if (_flags.gameID == GI_EOB2 && _flags.platform == Common::kPlatformFMTowns)
+		_environmentSfxVol = dist ? (16 - dist) * 8 - 1 : 127;
+	else if (_flags.platform == Common::kPlatformAmiga)
+		_environmentSfxVol = dist ? (soundId != 13 ? dist : (dist >= 4) ? 4 : dist) : 1;
+	else
+		_environmentSfxVol = (15 - ((block || (_flags.gameID == GI_LOL && dist < 2)) ? dist : 0)) << 4;
 
 	return true;
 }
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
index de8bf22..8007724 100644
--- a/engines/kyra/sound/sound_amiga_eob.cpp
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -139,9 +139,9 @@ void SoundAmiga_EoB::playTrack(uint8 track) {
 	if (_vm->game() == GI_EOB1) {
 		if (_currentResourceSet == kMusicIntro) {
 			if (track == 1)
-				newSound = "newintro1.smus";
+				newSound = "NEWINTRO1.SMUS";
 			else if (track == 20)
-				newSound = "chargen1.smus";
+				newSound = "CHARGEN1.SMUS";
 		}
 	} else if (_vm->game() == GI_EOB2) {
 		
@@ -168,7 +168,20 @@ void SoundAmiga_EoB::playSoundEffect(uint8 track, uint8 volume) {
 	Common::String newSound = _resInfo[_currentResourceSet]->soundList[track];
 
 	if (!newSound.empty()) {
-		_driver->startSound(newSound);
+		if (volume == 255) {
+			if (_driver->startSound(newSound + "1.SAM")) {
+				_lastSound = newSound + "1.SAM";
+				return;
+			} else {
+				volume = 1;
+			}
+		}
+
+		if (volume > 0 && volume < 5) {
+			newSound = Common::String::format("%s%d", newSound.c_str(), volume);		
+			_driver->startSound(newSound);
+		}
+
 		_lastSound = newSound;
 	}
 }


Commit: 75b01d367a7dcdf74a80cbe59c434fcd7980ef8d
    https://github.com/scummvm/scummvm/commit/75b01d367a7dcdf74a80cbe59c434fcd7980ef8d
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:23+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix monster walk orientation

Changed paths:
    engines/kyra/engine/sprites_eob.cpp


diff --git a/engines/kyra/engine/sprites_eob.cpp b/engines/kyra/engine/sprites_eob.cpp
index 55e8aaf..540710e 100644
--- a/engines/kyra/engine/sprites_eob.cpp
+++ b/engines/kyra/engine/sprites_eob.cpp
@@ -833,7 +833,7 @@ int EoBCoreEngine::getNextMonsterDirection(int curBlock, int destBlock) {
 
 	int r = 0;
 
-	int s1 = f - d;
+	int s1 = (_flags.platform == Common::kPlatformAmiga) ? (d - f) : (f - d);
 	int d1 = ABS(s1);
 	s1 <<= 1;
 	int s2 = c - e;


Commit: b5ac2203a5c75fadaa6ad78640cea65388ed4524
    https://github.com/scummvm/scummvm/commit/b5ac2203a5c75fadaa6ad78640cea65388ed4524
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:23+01:00

Commit Message:
KYRA: (EOB1/Amiga) - Amiga specific stone skin spell variant

Changed paths:
    engines/kyra/engine/magic_eob.cpp


diff --git a/engines/kyra/engine/magic_eob.cpp b/engines/kyra/engine/magic_eob.cpp
index d443b85..814e92d 100644
--- a/engines/kyra/engine/magic_eob.cpp
+++ b/engines/kyra/engine/magic_eob.cpp
@@ -997,7 +997,10 @@ bool EoBCoreEngine::spellCallback_end_iceStorm(void *obj) {
 }
 
 void EoBCoreEngine::spellCallback_start_stoneSkin() {
-	_characters[_activeSpellCharId].effectsRemainder[1] = (getMageLevel(_openBookChar) >> 1) + rollDice(1, 4);
+	if (_magicStrings9[0] && _characters[_activeSpellCharId].effectsRemainder[1])
+		_txt->printMessage(_magicStrings9[0], -1, _characters[_activeSpellCharId].name);
+	else
+		_characters[_activeSpellCharId].effectsRemainder[1] = (getMageLevel(_openBookChar) >> 1) + rollDice(1, 4);
 }
 
 void EoBCoreEngine::spellCallback_start_removeCurse() {


Commit: b8893fc691bdca370539d032014c6f2b598c8d72
    https://github.com/scummvm/scummvm/commit/b8893fc691bdca370539d032014c6f2b598c8d72
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:23+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix level palette glitch

Changed paths:
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/gui/gui_eob.cpp


diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index aebb8ae..fb334bf 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -93,8 +93,8 @@ void EoBCoreEngine::loadLevel(int level, int sub) {
 
 	loadVcnData(gfxFile.c_str(), (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformDOS) ? _cgaMappingLevel[_cgaLevelMappingIndex[level - 1]] : 0);
 	_screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2);
-	//if (_flags.platform == Common::kPlatformAmiga)
-	//	_screen->setScreenPalette(_screen->getPalette(0));
+	if (_flags.platform == Common::kPlatformAmiga)
+		_screen->getPalette(0).copy(_screen->getPalette(1), 1, 5, 1);
 
 	delayUntil(end);
 	snd_stopSound();
@@ -316,7 +316,7 @@ void EoBCoreEngine::loadVcnData(const char *file, const uint8 *cgaMapping) {
 		Common::SeekableReadStream *in = _res->createReadStream(fn);
 		vcnSize = in->readUint16LE() * (_vcnSrcBitsPerPixel << 3);
 		_vcnBlocks = new uint8[vcnSize];
-		_screen->getPalette(0).loadAmigaPalette(*in, 1, 5);
+		_screen->getPalette(1).loadAmigaPalette(*in, 1, 5);
 		in->seek(22, SEEK_CUR);
 		in->read(_vcnBlocks, vcnSize);
 		delete in;
diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index f521b9b..2b16e76 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -61,6 +61,8 @@ void EoBCoreEngine::gui_drawPlayField(bool refresh) {
 		_screen->updateScreen();
 
 	_screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2);
+	if (_flags.platform == Common::kPlatformAmiga)
+		_screen->getPalette(0).copy(_screen->getPalette(1), 1, 5, 1);
 }
 
 void EoBCoreEngine::gui_restorePlayField() {


Commit: c6230ebbf5bc0a80e50a58e6652c828b75c83dcf
    https://github.com/scummvm/scummvm/commit/c6230ebbf5bc0a80e50a58e6652c828b75c83dcf
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:24+01:00

Commit Message:
KYRA: (EOB1/Amiga) - improve scaled item handling

Changed paths:
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/engine/sprites_eob.cpp
    engines/kyra/graphics/screen_eob.cpp


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index a184b7f..c7aaf40 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -65,6 +65,10 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
 	_redSplatShape = _greenSplatShape = _deadCharShape = _disabledCharGrid = 0;
 	_blackBoxSmallGrid = _weaponSlotGrid = _blackBoxWideGrid = _lightningColumnShape = 0;
 
+	memset(_largeItemShapesScl, 0, sizeof(_largeItemShapesScl));
+	memset(_smallItemShapesScl, 0, sizeof(_smallItemShapesScl));
+	memset(_thrownItemShapesScl, 0, sizeof(_thrownItemShapesScl));
+
 	_monsterAcHitChanceTable1 = _monsterAcHitChanceTable2 = 0;
 	
 	_monsterDustStrings = 0;
@@ -733,6 +737,14 @@ void EoBCoreEngine::loadItemsAndDecorationsShapes() {
 		_screen->loadShapeSetBitmap("ITEML1", 5, 3);
 		for (int i = 0; i < _numLargeItemShapes; i++)
 			_largeItemShapes[i] = _screen->encodeShape((i / div) << 3, (i % div) * mul, 8, 24, false, _cgaMappingItemsL);
+
+		if (_flags.gameID == GI_EOB1) {
+			for (int c = 0; c < 3; ++c) {
+				_largeItemShapesScl[c] = new const uint8*[_numLargeItemShapes];
+				for (int i = 0; i < _numLargeItemShapes; i++)
+					_largeItemShapesScl[c][i] = _screen->encodeShape((i / div) << 3, (i % div) * mul + 24 + (c << 4), 6 - 2 * c, 16 - ((c >> 1) << 3), false, _cgaMappingItemsL);
+			}
+		}
 	}
 
 	_smallItemShapes = new const uint8*[_numSmallItemShapes];
@@ -743,11 +755,21 @@ void EoBCoreEngine::loadItemsAndDecorationsShapes() {
 		_screen->loadShapeSetBitmap("ITEMS1", 5, 3);
 		for (int i = 0; i < _numSmallItemShapes; i++)
 			_smallItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingItemsS);
+
+		if (_flags.gameID == GI_EOB1) {
+			for (int c = 0; c < 3; ++c) {
+				_smallItemShapesScl[c] = new const uint8*[_numSmallItemShapes];
+				for (int i = 0; i < _numSmallItemShapes; i++)
+					_smallItemShapesScl[c][i] = _screen->encodeShape((i / div) << 2, (i % div) * mul + 24 + (c << 4), 3 - c, 16 - ((c >> 1) << 3), false, _cgaMappingItemsS);
+			}
+		}
 	}
 
 	_thrownItemShapes = new const uint8*[_numThrownItemShapes];
-	_spellShapes = new const uint8*[4];
+	if (_flags.gameID == GI_EOB2)
+		_spellShapes = new const uint8*[4];
 	_firebeamShapes = new const uint8*[3];
+
 	if (_flags.platform == Common::kPlatformFMTowns && _flags.gameID == GI_EOB2) {
 		for (int i = 0; i < _numThrownItemShapes; i++)
 			_thrownItemShapes[i] = _staticres->loadRawData(kEoB2ThrownShapeData00 + i, size);
@@ -761,8 +783,17 @@ void EoBCoreEngine::loadItemsAndDecorationsShapes() {
 		_screen->loadShapeSetBitmap("THROWN", 5, 3);
 		for (int i = 0; i < _numThrownItemShapes; i++)
 			_thrownItemShapes[i] = _screen->encodeShape((i / div) << 2, (i % div) * mul, 4, 24, false, _cgaMappingThrown);
-		for (int i = 0; i < 4; i++)
-			_spellShapes[i] = _screen->encodeShape(8, i << 5, 6, 32, false, _cgaMappingThrown);
+
+		if (_flags.gameID == GI_EOB1) {
+			for (int c = 0; c < 3; ++c) {
+				_thrownItemShapesScl[c] = new const uint8*[_numThrownItemShapes];
+				for (int i = 0; i < _numThrownItemShapes; i++)
+					_thrownItemShapesScl[c][i] = _screen->encodeShape((i / div) << 2, (i % div) * mul + 24 + (c << 4), 3 - c, 16 - ((c >> 1) << 3), false, _cgaMappingThrown);
+			}
+		} else {
+			for (int i = 0; i < 4; i++)
+				_spellShapes[i] = _screen->encodeShape(8, i << 5, 6, 32, false, _cgaMappingThrown);
+		}
 
 		_firebeamShapes[0] = _screen->encodeShape(16, 0, 4, 24, false, _cgaMappingThrown);
 		_firebeamShapes[1] = _screen->encodeShape(16, 24, 4, 24, false, _cgaMappingThrown);
@@ -943,6 +974,33 @@ void EoBCoreEngine::releaseItemsAndDecorationsShapes() {
 	delete[] _teleporterShapes;
 	delete[] _compassShapes;
 	delete[] _firebeamShapes;
+
+	for (int i = 0; i < 3; ++i) {
+		if (_largeItemShapesScl[i]) {
+			for (int ii = 0; ii < _numLargeItemShapes; ++ii) {
+				if (_largeItemShapesScl[i][ii])
+					delete[] _largeItemShapesScl[i][ii];
+			}
+		}
+
+		if (_smallItemShapesScl[i]) {
+			for (int ii = 0; ii < _numSmallItemShapes; ++ii) {
+				if (_smallItemShapesScl[i][ii])
+					delete[] _smallItemShapesScl[i][ii];
+			}
+		}
+
+		if (_thrownItemShapesScl[i]) {
+			for (int ii = 0; ii < _numThrownItemShapes; ++ii) {
+				if (_thrownItemShapesScl[i][ii])
+					delete[] _thrownItemShapesScl[i][ii];
+			}
+		}
+
+		delete[] _largeItemShapesScl[i];
+		delete[] _smallItemShapesScl[i];
+		delete[] _thrownItemShapesScl[i];
+	}
 }
 
 void EoBCoreEngine::setHandItem(Item itemIndex) {
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 3d71fe0..b9785ac 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -283,6 +283,9 @@ protected:
 	const uint8 **_largeItemShapes;
 	const uint8 **_smallItemShapes;
 	const uint8 **_thrownItemShapes;
+	const uint8 **_largeItemShapesScl[3];
+	const uint8 **_smallItemShapesScl[3];
+	const uint8 **_thrownItemShapesScl[3];
 	const int _numLargeItemShapes;
 	const int _numSmallItemShapes;
 	const int _numThrownItemShapes;
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index fb334bf..7eab7ce 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -189,7 +189,7 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
 			_screen->createFadeTable16bit(src, (uint16*)_greyFadingTable, 0, 85);
 			_screen->setScreenPalette(_screen->getPalette(0));
 		} else if (_flags.platform == Common::kPlatformAmiga) {
-
+			// Amiga versions don't have shape shading
 		} else if (_configRenderMode != Common::kRenderCGA) {
 			Palette backupPal(256);
 			backupPal.copy(_screen->getPalette(0), 224, 32, 224);
diff --git a/engines/kyra/engine/sprites_eob.cpp b/engines/kyra/engine/sprites_eob.cpp
index 540710e..5e2e58e 100644
--- a/engines/kyra/engine/sprites_eob.cpp
+++ b/engines/kyra/engine/sprites_eob.cpp
@@ -453,7 +453,12 @@ void EoBCoreEngine::drawBlockItems(int index) {
 			}
 
 			if (scaleSteps >= 0) {
-				const uint8 *shp = _screen->scaleShape(_dscItemShapeMap[itm->icon] < _numLargeItemShapes ? _largeItemShapes[_dscItemShapeMap[itm->icon]] : (_dscItemShapeMap[itm->icon] < 15 ? 0 : _smallItemShapes[_dscItemShapeMap[itm->icon] - 15]), scaleSteps);
+				const uint8 *shp = 0;
+				if (_flags.gameID == GI_EOB2 || scaleSteps == 0)
+					shp = _screen->scaleShape(_dscItemShapeMap[itm->icon] < _numLargeItemShapes ? _largeItemShapes[_dscItemShapeMap[itm->icon]] : (_dscItemShapeMap[itm->icon] < 15 ? 0 : _smallItemShapes[_dscItemShapeMap[itm->icon] - 15]), scaleSteps);
+				else
+					shp = _dscItemShapeMap[itm->icon] < _numLargeItemShapes ? _largeItemShapesScl[scaleSteps - 1][_dscItemShapeMap[itm->icon]] : (_dscItemShapeMap[itm->icon] < 15 ? 0 : _smallItemShapesScl[scaleSteps - 1][_dscItemShapeMap[itm->icon] - 15]);
+
 				x = x + (itemPosFin[o & 7] << 1) - ((shp[2] << 3) >> 1);
 				y -= shp[1];
 
@@ -658,16 +663,25 @@ void EoBCoreEngine::drawFlyingObjects(int index) {
 			int dirOffs = (fo->direction == _currentDirection) ? 0 : ((fo->direction == (_currentDirection ^ 2)) ? 1 : -1);
 
 			if (dirOffs == -1 || _flightObjShpMap[shpIx] == -1) {
-				shp = shpIx < _numLargeItemShapes ? _largeItemShapes[shpIx] : (shpIx < 15 ? 0 : _smallItemShapes[shpIx - 15]);
+				if (_flags.gameID == GI_EOB2 || sclValue == 0)
+					shp = shpIx < _numLargeItemShapes ? _largeItemShapes[shpIx] : (shpIx < 15 ? 0 : _smallItemShapes[shpIx - 15]);
+				else
+					shp = shpIx < _numLargeItemShapes ? _largeItemShapesScl[sclValue - 1][shpIx] : (shpIx < 15 ? 0 : _smallItemShapesScl[sclValue - 1][shpIx - 15]);
 				flipped = fo->direction == ((_currentDirection + 1) & 3) ? 1 : 0;
 			} else {
-				shp = (_flightObjShpMap[shpIx] + dirOffs) < _numThrownItemShapes ? _thrownItemShapes[_flightObjShpMap[shpIx] + dirOffs] : _spellShapes[_flightObjShpMap[shpIx - _numThrownItemShapes] + dirOffs];
+				if (_flags.gameID == GI_EOB2 || sclValue == 0)
+					shp = (_flightObjShpMap[shpIx] + dirOffs) < _numThrownItemShapes ? _thrownItemShapes[_flightObjShpMap[shpIx] + dirOffs] : _spellShapes[_flightObjShpMap[shpIx - _numThrownItemShapes] + dirOffs];
+				else
+					shp = (_flightObjShpMap[shpIx] + dirOffs) < _numThrownItemShapes ? _thrownItemShapesScl[sclValue - 1][_flightObjShpMap[shpIx] + dirOffs] : 0;
 				flipped = _flightObjFlipIndex[(fo->direction << 2) + (fo->curPos & 3)];
 			}
 
 		} else {
 			noFade = true;
-			shp = (fo->objectType < _numThrownItemShapes) ? _thrownItemShapes[fo->objectType] : _spellShapes[fo->objectType - _numThrownItemShapes];
+			if (_flags.gameID == GI_EOB2 || sclValue == 0)
+				shp = (fo->objectType < _numThrownItemShapes) ? _thrownItemShapes[fo->objectType] : _spellShapes[fo->objectType - _numThrownItemShapes];
+			else
+				shp = (fo->objectType < _numThrownItemShapes) ? _thrownItemShapesScl[sclValue - 1][fo->objectType] : 0;
 			flipped = _flightObjFlipIndex[(fo->direction << 2) + (fo->curPos & 3)];
 
 			if (fo->flags & 0x40) {
@@ -678,7 +692,8 @@ void EoBCoreEngine::drawFlyingObjects(int index) {
 
 		assert(shp);
 
-		shp = _screen->scaleShape(shp, sclValue);
+		if (_flags.gameID == GI_EOB2 || sclValue == 0)
+			shp = _screen->scaleShape(shp, sclValue);
 
 		if (noFade) {
 			_screen->setShapeFadingLevel(0);
diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index 823740c..90e2d1f 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -1534,7 +1534,7 @@ void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) {
 	if (_bytesPerPixel == 2) {
 		*(uint16*)dst = _16bitPalette[(_dsShapeFadingLevel << 8) + col];
 		return;
-	} else if ((_renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) {
+	} else if ((!_isAmiga && _renderMode != Common::kRenderCGA && _renderMode != Common::kRenderEGA) || _useHiResEGADithering) {
 		if (_dsBackgroundFading) {
 			if (_dsShapeFadingLevel) {
 				col = *dst;
@@ -1545,6 +1545,7 @@ void Screen_EoB::drawShapeSetPixel(uint8 *dst, uint8 col) {
 		}
 
 		if (_dsShapeFadingLevel) {
+			assert(_dsShapeFadingTable);
 			uint8 cnt = _dsShapeFadingLevel;
 			while (cnt--)
 				col = _dsShapeFadingTable[col];


Commit: 94ab4c83527d9f7bcec97bf959899dc655f8ba66
    https://github.com/scummvm/scummvm/commit/94ab4c83527d9f7bcec97bf959899dc655f8ba66
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:24+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix warning

Changed paths:
    engines/kyra/script/script_eob.cpp


diff --git a/engines/kyra/script/script_eob.cpp b/engines/kyra/script/script_eob.cpp
index cc3fc0a..c0c143b 100644
--- a/engines/kyra/script/script_eob.cpp
+++ b/engines/kyra/script/script_eob.cpp
@@ -514,7 +514,7 @@ int EoBInfProcessor::oeob_moveInventoryItemToBlock(int8 *data) {
 }
 
 int EoBInfProcessor::oeob_printMessage_v1(int8 *data) {
-	static const uint8 amigaColorMap[16] = { 0x00, 0x06, 0x1d, 0x1b, 0x1a, 0x17, 0x18, 0x0e, 0x19, 0x1c, 0x1c, 0x1e, 0x13, 0x0a, 0x11, 0x1f };
+	static const char amigaColorMap[16] = { 0x00, 0x06, 0x1d, 0x1b, 0x1a, 0x17, 0x18, 0x0e, 0x19, 0x1c, 0x1c, 0x1e, 0x13, 0x0a, 0x11, 0x1f };
 	static const char colorConfig[] = "\x6\x21\x2\x21";
 	char col[5];
 	int8 *pos = data;
@@ -527,10 +527,10 @@ int EoBInfProcessor::oeob_printMessage_v1(int8 *data) {
 	col[3] = *pos++;
 
 	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
-		assert(col[1] < 16);
-		assert(col[3] < 16);
-		col[1] = amigaColorMap[col[1]];
-		col[3] = amigaColorMap[col[3]];
+		assert((uint8)col[1] < 16);
+		assert((uint8)col[3] < 16);
+		col[1] = amigaColorMap[(uint8)col[1]];
+		col[3] = amigaColorMap[(uint8)col[3]];
 	}
 
 	_vm->txt()->printMessage(col);


Commit: c3fa4c02ab11381b9139709882d85a14a19aa39a
    https://github.com/scummvm/scummvm/commit/c3fa4c02ab11381b9139709882d85a14a19aa39a
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:24+01:00

Commit Message:
KYRA: (EOB) - fix possible out of bounds mem access

(This can't happen through normal gameplay, but still better to be fixed)

Changed paths:
    engines/kyra/graphics/screen_eob.cpp
    engines/kyra/gui/gui_eob.cpp


diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp
index 90e2d1f..4cd471e 100644
--- a/engines/kyra/graphics/screen_eob.cpp
+++ b/engines/kyra/graphics/screen_eob.cpp
@@ -1755,7 +1755,7 @@ bool OldDOSFont::load(Common::SeekableReadStream &file) {
 
 	_width = _data[0x103];
 	_height = _data[0x102];
-	_numGlyphs = 255;
+	_numGlyphs = (READ_LE_UINT16(_data + 2) / 2) - 2;
 
 	_bitmapOffsets = (uint16 *)(_data + 2);
 
@@ -1766,8 +1766,10 @@ bool OldDOSFont::load(Common::SeekableReadStream &file) {
 }
 
 int OldDOSFont::getCharWidth(uint16 c) const {
-	if (c >= _numGlyphs)
-		return 0;
+	// Since these fonts have a fixed character width we always give a return value
+	// even if there is no glyph for the specified character (which can't normally
+	// happen anyway - you'd have to do something like importing a Japanese save file
+	// into the English version).
 	return _width;
 }
 
@@ -1822,6 +1824,9 @@ void OldDOSFont::drawChar(uint16 c, byte *dst, int pitch, int bpp) const {
 		}
 	}
 
+	if (c >= _numGlyphs)
+		return;
+
 	pitch *= bpp;
 	const uint8 *src = &_data[_bitmapOffsets[c]];
 	uint8 *dst2 = dst + pitch;
diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index 2b16e76..1babce7 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -2536,6 +2536,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 	_menuCur = -1;
 	printKatakanaOptions(0);
 
+	int bytesPerChar = (_vm->_flags.lang == Common::JA_JPN) ? 2 : 1;
 	int in = 0;
 
 	do {
@@ -2586,9 +2587,9 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 		if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE) {
 			if (pos > 0 && pos < len ) {
 				for (int i = pos; i < len; i++) {
-					if (dest[i * 2] & 0x80) {
-						dest[(i - 1) * 2] = dest[i * 2];
-						dest[(i - 1) * 2 + 1] = dest[i * 2 + 1];
+					if (bytesPerChar == 2 && dest[i * bytesPerChar] & 0x80) {
+						dest[(i - 1) * bytesPerChar] = dest[i * bytesPerChar];
+						dest[(i - 1) * bytesPerChar + 1] = dest[i * bytesPerChar + 1];
 					} else {
 						dest[i - 1] = dest[i];
 					}
@@ -2596,8 +2597,8 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 			}
 
 			if (pos > 0) {
-				if (dest[(len - 1) * 2] & 0x80)
-					dest[--len * 2] = 0;
+				if (bytesPerChar == 2 && dest[(len - 1) * bytesPerChar] & 0x80)
+					dest[--len * bytesPerChar] = 0;
 				else
 					dest[--len] = 0;
 				pos--;
@@ -2618,19 +2619,19 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 
 				if (pos < len) {
 					for (int i = destMaxLen - 2; i >= pos; i--) {
-						if (in == 0x89) {
-							dest[(i + 1) * 2] = dest[i * 2];
-							dest[(i + 1) * 2 + 1] = dest[i * 2 + 1];
+						if (bytesPerChar == 2 && in == 0x89) {
+							dest[(i + 1) * bytesPerChar] = dest[i * bytesPerChar];
+							dest[(i + 1) * bytesPerChar + 1] = dest[i * bytesPerChar + 1];
 						} else {
 							dest[i + 1] = dest[i];
 						}
 					}
 
-					if (in == 0x89) {
-						dest[pos * 2] = _csjis[0];
-						dest[pos++ * 2 + 1] = _csjis[1];
+					if (bytesPerChar == 2 && in == 0x89) {
+						dest[pos * bytesPerChar] = _csjis[0];
+						dest[pos++ * bytesPerChar + 1] = _csjis[1];
 						if (len == destMaxLen)
-							dest[len * 2] = 0;
+							dest[len * bytesPerChar] = 0;
 					} else {
 						dest[pos++] = in;
 						if (len == destMaxLen)
@@ -2642,10 +2643,10 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 						len--;
 					}
 
-					if (in == 0x89) {
-						dest[pos * 2] = _csjis[0];
-						dest[pos * 2 + 1] = _csjis[1];
-						dest[++pos * 2] = 0;
+					if (bytesPerChar == 2 && in == 0x89) {
+						dest[pos * bytesPerChar] = _csjis[0];
+						dest[pos * bytesPerChar + 1] = _csjis[1];
+						dest[++pos * bytesPerChar] = 0;
 					} else {
 						dest[pos++] = in;
 						dest[pos] = 0;
@@ -2665,8 +2666,8 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 		
 		if (_vm->_flags.platform == Common::kPlatformFMTowns) {
 			if (pos < len) {
-				sufx[0] = dest[pos * 2];
-				sufx[1] = dest[pos * 2 + 1];
+				sufx[0] = dest[pos * bytesPerChar];
+				sufx[1] = dest[pos * bytesPerChar + 1];
 			} else {
 				sufx[0] = 32;
 				sufx[1] = 0;


Commit: 0be1fa53dbc24868abb51a700f15d2af5a12ab37
    https://github.com/scummvm/scummvm/commit/0be1fa53dbc24868abb51a700f15d2af5a12ab37
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:24+01:00

Commit Message:
KYRA: (EOB1/Amiga) - add original save file handling

Changed paths:
    engines/kyra/gui/saveload_eob.cpp
    engines/kyra/script/script_eob.cpp


diff --git a/engines/kyra/gui/saveload_eob.cpp b/engines/kyra/gui/saveload_eob.cpp
index 713c4cb..f88266d 100644
--- a/engines/kyra/gui/saveload_eob.cpp
+++ b/engines/kyra/gui/saveload_eob.cpp
@@ -644,21 +644,29 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 	if (!fs)
 		return desc;
 
-	Common::SeekableSubReadStreamEndian in(fs, 0, fs->size(), _flags.platform == Common::kPlatformAmiga, DisposeAfterUse::YES);
-
+	Common::SeekableSubReadStream test(fs, 0, fs->size(), DisposeAfterUse::NO);
+	
 	// detect source platform
 	Common::Platform sourcePlatform = Common::kPlatformDOS;
-	in.seek(32);
-	uint16 testSJIS = in.readByte();
-	in.seek(53);
-	int8 testStr = in.readSByte();
-	in.seek(66);
-	int8 testChr = in.readSByte();
-	in.seek(0);
+	test.seek(32);
+	uint16 testSJIS = test.readByte();
+	test.seek(53);
+	int8 testStr = test.readSByte();
+	test.seek(66);
+	int8 testChr = test.readSByte();
+	test.seek(_flags.gameID == GI_EOB1 ? 48 : 50);
+	uint32 exp = test.readUint32LE();
+	test.seek(0);
+		
 	if (testStr >= 0 && testStr <= 25 && testChr >= 0 && testChr <= 25) {
 		if (testSJIS >= 0xE0 || (testSJIS > 0x80 && testSJIS < 0xA0))
 			sourcePlatform = Common::kPlatformFMTowns;
 	}
+	
+	if (sourcePlatform == Common::kPlatformDOS && exp & 0xFF000000)
+		sourcePlatform = Common::kPlatformAmiga;
+
+	Common::SeekableSubReadStreamEndian in(fs, 0, fs->size(), sourcePlatform == Common::kPlatformAmiga, DisposeAfterUse::YES);
 
 	if (_flags.gameID == GI_EOB1) {
 		// Nothing to read here for EOB 1. Original EOB 1 has
@@ -693,6 +701,12 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 		c->charismaMax = in.readSByte();
 		c->hitPointsCur = (_flags.gameID == GI_EOB1) ? in.readSByte() : in.readSint16();
 		c->hitPointsMax = (_flags.gameID == GI_EOB1) ? in.readSByte() : in.readSint16();
+		if (_flags.gameID == GI_EOB1) {
+			if (c->hitPointsCur < -10)
+				c->hitPointsCur = c->hitPointsCur & 0xFF;
+			if (c->hitPointsMax < -10)
+				c->hitPointsMax = c->hitPointsMax & 0xFF;
+		}
 		c->armorClass = in.readSByte();
 		c->disabledSlots = in.readByte();
 		c->raceSex = in.readByte();
@@ -701,22 +715,36 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 		c->portrait = in.readSByte();
 		c->food = in.readByte();
 		in.read(c->level, 3);
+		if (sourcePlatform == Common::kPlatformAmiga)
+			in.skip(1);
 		for (int ii = 0; ii < 3; ii++)
 			c->experience[ii] = in.readUint32();
 		in.skip(4);
 		delete[] c->faceShape;
 		c->faceShape = 0;
-		in.read(c->mageSpells, (_flags.gameID == GI_EOB1) ? 30 : 80);
-		in.read(c->clericSpells, (_flags.gameID == GI_EOB1) ? 30 : 80);
+
+		if (_flags.gameID == GI_EOB1) {
+			for (int ii = 0; ii < 5; ++ii)
+				in.read(c->mageSpells + ii * 10, 6);
+			for (int ii = 0; ii < 5; ++ii)
+				in.read(c->clericSpells + ii * 10, 6);
+		} else {
+			in.read(c->mageSpells, 80);
+			in.read(c->clericSpells, 80);
+		}
+
 		c->mageSpellsAvailableFlags = in.readUint32();
+
 		for (int ii = 0; ii < 27; ii++)
 			c->inventory[ii] = in.readSint16();
+
 		uint32 ct = _system->getMillis();
 		for (int ii = 0; ii < 10; ii++) {
 			c->timers[ii] = in.readUint32() * _tickLength;
 			if (c->timers[ii])
 				c->timers[ii] += ct;
 		}
+
 		in.read(c->events, 10);
 		in.read(c->effectsRemainder, 4);
 		c->effectFlags = in.readUint32();
@@ -751,6 +779,8 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 	
 	_inf->loadState(in, true);
 
+	loadItemDefs();
+
 	int numItems = (_flags.gameID == GI_EOB1) ? 500 : 600;
 	for (int i = 0; i < numItems; i++) {
 		EoBItem *t = &_items[i];
@@ -772,7 +802,7 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 	uint32 nextPart = in.pos();
 	uint8 *cmpData = new uint8[1200];
 
-	for (int i = 0; i < numParts; i++) {
+	for (int i = 0; i < numParts + 1; i++) {
 		in.seek(nextPart);
 		nextPart += partSize;
 
@@ -879,10 +909,6 @@ Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
 
 	in.skip(3);
 
-	delete[] _itemTypes;
-	_itemTypes = new EoBItemType[65];
-	memset(_itemTypes, 0, sizeof(EoBItemType) * 65);
-
 	for (int i = 51; i < 57; i++) {
 		EoBItemType *t = &_itemTypes[i];
 		t->invFlags = in.readUint16();
@@ -1062,13 +1088,18 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 		out->writeSByte(c->constitutionMax);
 		out->writeSByte(c->charismaCur);
 		out->writeSByte(c->charismaMax);
+
 		if (_flags.gameID == GI_EOB1) {
 			out->writeSByte(c->hitPointsCur);
 			out->writeSByte(c->hitPointsMax);
+		} else if (_flags.platform == Common::kPlatformAmiga) {
+			out->writeSint16BE(c->hitPointsCur);
+			out->writeSint16BE(c->hitPointsMax);
 		} else {
 			out->writeSint16LE(c->hitPointsCur);
 			out->writeSint16LE(c->hitPointsMax);
 		}
+
 		out->writeSByte(c->armorClass);
 		out->writeByte(c->disabledSlots);
 		out->writeByte(c->raceSex);
@@ -1077,17 +1108,44 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 		out->writeSByte(c->portrait);
 		out->writeByte(c->food);
 		out->write(c->level, 3);
-		for (int ii = 0; ii < 3; ii++)
-			out->writeUint32LE(c->experience[ii]);
+
+		if (_flags.platform == Common::kPlatformAmiga) {
+			out->writeByte(0);
+			for (int ii = 0; ii < 3; ii++)
+				out->writeUint32BE(c->experience[ii]);
+		} else {
+			for (int ii = 0; ii < 3; ii++)
+				out->writeUint32LE(c->experience[ii]);
+		}
+
 		out->writeUint32LE(0);
-		out->write(c->mageSpells, (_flags.gameID == GI_EOB1) ? 30 : 80);
-		out->write(c->clericSpells, (_flags.gameID == GI_EOB1) ? 30 : 80);
-		out->writeUint32LE(c->mageSpellsAvailableFlags);
-		for (int ii = 0; ii < 27; ii++)
-			out->writeSint16LE(c->inventory[ii]);
-		uint32 ct = _system->getMillis();
-		for (int ii = 0; ii < 10; ii++)
-			out->writeUint32LE((c->timers[ii] && c->timers[ii] > ct) ? (c->timers[ii] - ct) / _tickLength : 0);
+
+		if (_flags.gameID == GI_EOB1) {
+			for (int ii = 0; ii < 5; ++ii)
+				out->write(c->mageSpells + ii * 10, 6);
+			for (int ii = 0; ii < 5; ++ii)
+				out->write(c->clericSpells + ii * 10, 6);
+		} else {
+			out->write(c->mageSpells, 80);
+			out->write(c->clericSpells, 80);
+		}
+
+		if (_flags.platform == Common::kPlatformAmiga) {
+			out->writeUint32BE(c->mageSpellsAvailableFlags);
+			for (int ii = 0; ii < 27; ii++)
+				out->writeSint16BE(c->inventory[ii]);
+			uint32 ct = _system->getMillis();
+			for (int ii = 0; ii < 10; ii++)
+				out->writeUint32BE((c->timers[ii] && c->timers[ii] > ct) ? (c->timers[ii] - ct) / _tickLength : 0);
+		} else {
+			out->writeUint32LE(c->mageSpellsAvailableFlags);
+			for (int ii = 0; ii < 27; ii++)
+				out->writeSint16LE(c->inventory[ii]);
+			uint32 ct = _system->getMillis();
+			for (int ii = 0; ii < 10; ii++)
+				out->writeUint32LE((c->timers[ii] && c->timers[ii] > ct) ? (c->timers[ii] - ct) / _tickLength : 0);
+		}
+
 		out->write(c->events, 10);
 		out->write(c->effectsRemainder, 4);
 
@@ -1096,34 +1154,61 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 			// This doesn't matter much here, since these flags only apply to the temporary spell effects (things like prayer, haste, etc.) anyway.
 			warning("EoBCoreEngine::saveAsOriginalFile(): Character effect flags lost while exporting original EOB1 save file");
 			out->writeUint32LE(0);
+		} else if (_flags.platform == Common::kPlatformAmiga) {
+			out->writeUint32BE(c->effectFlags);
 		} else {
 			out->writeUint32LE(c->effectFlags);
 		}
+
 		out->writeByte(c->damageTaken);
 		out->write(c->slotStatus, 5);
 		for (int ii = 0; ii < 6; ii++)
 			out->writeByte(0);
 	}
 
-	out->writeUint16LE(_currentLevel);
-	if (_flags.gameID == GI_EOB2)
-		out->writeSint16LE(_currentSub);
-	out->writeUint16LE(_currentBlock);
-	out->writeUint16LE(_currentDirection);
-	out->writeSint16LE(_itemInHand);
-	if (_flags.gameID == GI_EOB1) {
-		out->writeUint16LE(_hasTempDataFlags);
-		out->writeUint16LE(0);
-		if (_partyEffectFlags)
-			// Spell effect flags are completely different in original EOB I. We only use EOB II style flags in ScummVM.
-			// This doesn't matter much here, since these flags only apply to the temporary spell effects (things like prayer, haste, etc.) anyway.
-			warning("EoBCoreEngine::saveAsOriginalFile(): Party effect flags lost while exporting original EOB1 save file");
+	if (_flags.platform == Common::kPlatformAmiga) {
+		out->writeUint16BE(_currentLevel);
+		if (_flags.gameID == GI_EOB2)
+			out->writeSint16BE(_currentSub);
+		out->writeUint16BE(_currentBlock);
+		out->writeUint16BE(_currentDirection);
+		out->writeSint16BE(_itemInHand);
+
+		if (_flags.gameID == GI_EOB1) {
+			out->writeUint16BE(_hasTempDataFlags);
+			out->writeUint16BE(0);
+			if (_partyEffectFlags)
+				// Spell effect flags are completely different in original EOB I. We only use EOB II style flags in ScummVM.
+				// This doesn't matter much here, since these flags only apply to the temporary spell effects (things like prayer, haste, etc.) anyway.
+				warning("EoBCoreEngine::saveAsOriginalFile(): Party effect flags lost while exporting original EOB1 save file");
+		} else {
+			out->writeUint32BE(_hasTempDataFlags);
+			out->writeUint32BE(_partyEffectFlags);
+		}
 	} else {
-		out->writeUint32LE(_hasTempDataFlags);
-		out->writeUint32LE(_partyEffectFlags);
+		out->writeUint16LE(_currentLevel);
+		if (_flags.gameID == GI_EOB2)
+			out->writeSint16LE(_currentSub);
+		out->writeUint16LE(_currentBlock);
+		out->writeUint16LE(_currentDirection);
+		out->writeSint16LE(_itemInHand);
+
+		if (_flags.gameID == GI_EOB1) {
+			out->writeUint16LE(_hasTempDataFlags);
+			out->writeUint16LE(0);
+			if (_partyEffectFlags)
+				// Spell effect flags are completely different in original EOB I. We only use EOB II style flags in ScummVM.
+				// This doesn't matter much here, since these flags only apply to the temporary spell effects (things like prayer, haste, etc.) anyway.
+				warning("EoBCoreEngine::saveAsOriginalFile(): Party effect flags lost while exporting original EOB1 save file");
+		} else {
+			out->writeUint32LE(_hasTempDataFlags);
+			out->writeUint32LE(_partyEffectFlags);
+		}
 	}
+
 	if (_flags.gameID == GI_EOB2)
 		out->writeByte(0);
+	
 	_inf->saveState(out, true);
 
 	int numItems = (_flags.gameID == GI_EOB1) ? 500 : 600;
@@ -1135,9 +1220,17 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 		out->writeSByte(t->icon);
 		out->writeSByte(t->type);
 		out->writeSByte(t->pos);
-		out->writeSint16LE(t->block);
-		out->writeSint16LE(t->next);
-		out->writeSint16LE(t->prev);
+
+		if (_flags.platform == Common::kPlatformAmiga) {
+			out->writeSint16BE(t->block);
+			out->writeSint16BE(t->next);
+			out->writeSint16BE(t->prev);
+		} else {
+			out->writeSint16LE(t->block);
+			out->writeSint16LE(t->next);
+			out->writeSint16LE(t->prev);
+		}
+
 		out->writeByte(t->level);
 		out->writeSByte(t->value);
 	}
@@ -1158,8 +1251,10 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 			continue;
 		}
 
+		Common::String curBlockFile = _curBlockFile;
 		_curBlockFile = getBlockFileName(i + 1, 0);
 		const uint8 *p = getBlockFileData();
+		_curBlockFile = curBlockFile;
 		uint16 len = READ_LE_UINT16(p + 4);
 		p += 6;
 
@@ -1186,7 +1281,10 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 			EoBMonsterInPlay *m = &((EoBMonsterInPlay*)l->monsters)[ii];
 			out->writeByte(m->type);
 			out->writeByte(m->unit);
-			out->writeUint16LE(m->block);
+			if (_flags.platform == Common::kPlatformAmiga)
+				out->writeUint16BE(m->block);
+			else
+				out->writeUint16LE(m->block);
 			out->writeByte(m->pos);
 			out->writeSByte(m->dir);
 			out->writeByte(m->animStep);
@@ -1195,11 +1293,21 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 			out->writeSByte(m->stray);
 			out->writeSByte(m->curAttackFrame);
 			out->writeSByte(m->spellStatusLeft);
-			out->writeSint16LE(m->hitPointsMax);
-			out->writeSint16LE(m->hitPointsCur);
-			out->writeUint16LE(m->dest);
-			out->writeUint16LE(m->randItem);
-			out->writeUint16LE(m->fixedItem);
+
+			if (_flags.platform == Common::kPlatformAmiga) {
+				out->writeSint16BE(m->hitPointsMax);
+				out->writeSint16BE(m->hitPointsCur);
+				out->writeUint16BE(m->dest);
+				out->writeUint16BE(m->randItem);
+				out->writeUint16BE(m->fixedItem);
+			} else {
+				out->writeSint16LE(m->hitPointsMax);
+				out->writeSint16LE(m->hitPointsCur);
+				out->writeUint16LE(m->dest);
+				out->writeUint16LE(m->randItem);
+				out->writeUint16LE(m->fixedItem);
+			}
+
 			out->writeByte(m->flags);
 			out->writeByte(m->idleAnimState);
 
@@ -1225,8 +1333,13 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 
 		for (int ii = 0; ii < 5; ii++) {
 			WallOfForce *w= &((WallOfForce*)l->wallsOfForce)[ii];
-			out->writeUint16LE(w->block);
-			out->writeUint32LE(w->duration / _tickLength);
+			if (_flags.platform == Common::kPlatformAmiga) {
+				out->writeUint16BE(w->block);
+				out->writeUint32BE(w->duration / _tickLength);
+			} else {
+				out->writeUint16LE(w->block);
+				out->writeUint32LE(w->duration / _tickLength);
+			}
 		}
 	}
 
@@ -1239,8 +1352,14 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 
 	for (int i = 51; i < 57; i++) {
 		EoBItemType *t = &_itemTypes[i];
-		out->writeUint16LE(t->invFlags);
-		out->writeUint16LE(t->handFlags);
+		if (_flags.platform == Common::kPlatformAmiga) {
+			out->writeUint16BE(t->invFlags);
+			out->writeUint16BE(t->handFlags);
+		} else {
+			out->writeUint16LE(t->invFlags);
+			out->writeUint16LE(t->handFlags);
+		}
+
 		out->writeSByte(t->armorClass);
 		out->writeSByte(t->allowedClasses);
 		out->writeSByte(t->requiredHands);
@@ -1251,7 +1370,11 @@ bool EoBCoreEngine::saveAsOriginalSaveFile(int slot) {
 		out->writeSByte(t->dmgNumPipsL);
 		out->writeSByte(t->dmgIncL);
 		out->writeByte(t->unk1);
-		out->writeUint16LE(t->extraProperties);
+
+		if (_flags.platform == Common::kPlatformAmiga)
+			out->writeUint16BE(t->extraProperties);
+		else
+			out->writeUint16LE(t->extraProperties);
 	}
 
 	out->finalize();
diff --git a/engines/kyra/script/script_eob.cpp b/engines/kyra/script/script_eob.cpp
index c0c143b..b063b08 100644
--- a/engines/kyra/script/script_eob.cpp
+++ b/engines/kyra/script/script_eob.cpp
@@ -228,13 +228,17 @@ void EoBInfProcessor::saveState(Common::OutSaveFile *out, bool origFile) {
 		out->writeByte(_preventRest);
 	int numFlags = (_vm->game() == GI_EOB1 && origFile) ? 12 : 18;
 	for (int i = 0; i < numFlags; i++) {
-		if (origFile)
+		if (origFile && _vm->gameFlags().platform != Common::kPlatformAmiga)
 			out->writeUint32LE(_flagTable[i]);
 		else
 			out->writeUint32BE(_flagTable[i]);
 	}
-	if (_vm->game() == GI_EOB1 && origFile)
-		out->writeUint32LE(_flagTable[17]);
+	if (_vm->game() == GI_EOB1 && origFile) {
+		if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+			out->writeUint32BE(_flagTable[17]);
+		else
+			out->writeUint32LE(_flagTable[17]);
+	}
 }
 
 void EoBInfProcessor::reset() {


Commit: 412a10ede3133a6bd06d0975f242a59416c76a56
    https://github.com/scummvm/scummvm/commit/412a10ede3133a6bd06d0975f242a59416c76a56
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:25+01:00

Commit Message:
KYRA: (EOB1) - fix bug when attacking while invisible

(wrong callback function called in EOB1)

Changed paths:
    engines/kyra/engine/eobcommon.cpp


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index c7aaf40..96cc131 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -2004,7 +2004,7 @@ void EoBCoreEngine::useSlotWeapon(int charIndex, int slotIndex, Item item) {
 	int tp = item ? _items[item].type : 0;
 
 	if (c->effectFlags & 0x40)
-		removeCharacterEffect(10, charIndex, 1); // remove invisibility effect
+		removeCharacterEffect(_flags.gameID == GI_EOB1 ? 8 : 10, charIndex, 1); // remove invisibility effect
 
 	int ep = _itemTypes[tp].extraProperties & 0x7F;
 	int8 inflict = 0;


Commit: 8c5fcb36a5e914f9f7e694fd7ef41c7717bf39ed
    https://github.com/scummvm/scummvm/commit/8c5fcb36a5e914f9f7e694fd7ef41c7717bf39ed
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:26+01:00

Commit Message:
KYRA: (EOB) - fix poison warning

(There should be a death warning when trying to rest the party while poisoned. This did not work correctly.)

Changed paths:
    engines/kyra/gui/gui_eob.cpp


diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index 1babce7..b89f308 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -3506,14 +3506,15 @@ bool GUI_EoB::restParty() {
 
 	drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
 
-	int nonPoisoned = 0;
+	bool poisoned = false;
 	for (int i = 0; i < 6; i++) {
 		if (!_vm->testCharacter(i, 1))
 			continue;
-		nonPoisoned |= _vm->testCharacter(i, 0x10);
+		if (!_vm->testCharacter(i, 0x10))
+			poisoned = true;
 	}
 
-	if (!nonPoisoned) {
+	if (poisoned) {
 		if (!confirmDialogue(59))
 			return false;
 	}


Commit: ea6f44871ba00da50b26e64d36b301dc48b1a2b7
    https://github.com/scummvm/scummvm/commit/ea6f44871ba00da50b26e64d36b301dc48b1a2b7
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:26+01:00

Commit Message:
KYRA: (EOB2/FM-TOWNS) - fix character status text glitch

Changed paths:
    engines/kyra/gui/gui_eob.cpp


diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index b89f308..ae787a5 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -137,18 +137,27 @@ void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
 		gui_drawFoodStatusGraph(index);
 
 		if (_currentControlMode == 1) {
+			Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT);
+			int statusTxtY = 158;
+			if (_flags.platform == Common::kPlatformFMTowns) {
+				statusTxtY = 157;
+				_screen->setFont(Screen::FID_8_FNT);
+			}
+
 			if (c->hitPointsCur == -10)
-				_screen->printShadedText(_characterGuiStringsSt[1], 247, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+				_screen->printShadedText(_characterGuiStringsSt[1], 247, statusTxtY, guiSettings()->colors.guiColorLightRed, 0, guiSettings()->colors.guiColorBlack);
 			else if (c->hitPointsCur < 1)
-				_screen->printShadedText(_characterGuiStringsSt[2], 226, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+				_screen->printShadedText(_characterGuiStringsSt[2], 226, statusTxtY, guiSettings()->colors.guiColorLightRed, 0, guiSettings()->colors.guiColorBlack);
 			else if (c->effectFlags & 0x2000)
-				_screen->printShadedText(_characterGuiStringsSt[3], 220, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+				_screen->printShadedText(_characterGuiStringsSt[3], 220, statusTxtY, guiSettings()->colors.guiColorLightRed, 0, guiSettings()->colors.guiColorBlack);
 			else if (c->flags & 2)
-				_screen->printShadedText(_characterGuiStringsSt[4], 235, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+				_screen->printShadedText(_characterGuiStringsSt[4], 235, statusTxtY, guiSettings()->colors.guiColorLightRed, 0, guiSettings()->colors.guiColorBlack);
 			else if (c->flags & 4)
-				_screen->printShadedText(_characterGuiStringsSt[5], 232, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+				_screen->printShadedText(_characterGuiStringsSt[5], 232, statusTxtY, guiSettings()->colors.guiColorLightRed, 0, guiSettings()->colors.guiColorBlack);
 			else if (c->flags & 8)
-				_screen->printShadedText(_characterGuiStringsSt[6], 232, 158, guiSettings()->colors.guiColorLightRed, guiSettings()->colors.sfill, guiSettings()->colors.guiColorBlack);
+				_screen->printShadedText(_characterGuiStringsSt[6], 232, statusTxtY, guiSettings()->colors.guiColorLightRed, 0, guiSettings()->colors.guiColorBlack);
+
+			_screen->setFont(cf);
 
 			for (int i = 0; i < 27; i++)
 				gui_drawInventoryItem(i, 0, 2);


Commit: 1cb85808318cc560a045068b48d981d1695ed4bc
    https://github.com/scummvm/scummvm/commit/1cb85808318cc560a045068b48d981d1695ed4bc
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:27+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix spell sounds

Changed paths:
    engines/kyra/engine/darkmoon.cpp
    engines/kyra/engine/darkmoon.h
    engines/kyra/engine/eob.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/magic_eob.cpp


diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index d8cb125..617cd09 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -358,6 +358,10 @@ void DarkMoonEngine::drawDoorIntern(int type, int, int x, int y, int w, int wall
 		drawBlockObject(0, 2, _doorSwitches[shapeIndex].shp, _doorSwitches[shapeIndex].x + w, _doorSwitches[shapeIndex].y, 5);
 }
 
+void DarkMoonEngine::turnUndeadAutoHit() {
+	snd_playSoundEffect(95);
+}
+
 void DarkMoonEngine::restParty_npc() {
 	int insalId = -1;
 	int numChar = 0;
diff --git a/engines/kyra/engine/darkmoon.h b/engines/kyra/engine/darkmoon.h
index ab8d93f..16fe856 100644
--- a/engines/kyra/engine/darkmoon.h
+++ b/engines/kyra/engine/darkmoon.h
@@ -104,6 +104,9 @@ private:
 
 	const uint8 *_dscDoorType5Offs;
 
+	// Magic
+	void turnUndeadAutoHit();
+
 	// Fight
 	static const uint8 _monsterAcHitChanceTbl1[];
 	static const uint8 _monsterAcHitChanceTbl2[];
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index 8c59d4d..f2d06e0 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -509,6 +509,7 @@ void EoBEngine::turnUndeadAuto() {
 
 void EoBEngine::turnUndeadAutoHit() {
 	_txt->printMessage(_turnUndeadString[0], -1, _characters[_openBookChar].name);
+	snd_playSoundEffect(_flags.platform == Common::kPlatformAmiga ? 16 : 95);
 	sparkEffectOffensive();
 }
 
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index b9785ac..293878c 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -942,7 +942,7 @@ protected:
 	void useWand(int charIndex, int weaponSlot);
 
 	virtual void turnUndeadAuto() {}
-	virtual void turnUndeadAutoHit() {}
+	virtual void turnUndeadAutoHit() = 0;
 
 	void castSpell(int spell, int weaponSlot);
 	void removeCharacterEffect(int spell, int charIndex, int showWarning);
diff --git a/engines/kyra/engine/magic_eob.cpp b/engines/kyra/engine/magic_eob.cpp
index 814e92d..448f7f0 100644
--- a/engines/kyra/engine/magic_eob.cpp
+++ b/engines/kyra/engine/magic_eob.cpp
@@ -385,6 +385,9 @@ void EoBCoreEngine::sparkEffectDefensive(int charIndex) {
 		first = 0;
 		last = 5;
 	}
+	
+	if (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformAmiga)
+		snd_playSoundEffect(104);
 
 	for (int i = 0; i < 8; i++) {
 		for (int ii = first; ii <= last; ii++) {
@@ -1282,7 +1285,6 @@ void EoBCoreEngine::spellCallback_start_turnUndead() {
 
 	if (hit) {
 		turnUndeadAutoHit();
-		snd_playSoundEffect(95);
 		updateAllMonsterShapes();
 	}
 


Commit: 010a79099eebe051d42f90b8f99d5342ae0fe249
    https://github.com/scummvm/scummvm/commit/010a79099eebe051d42f90b8f99d5342ae0fe249
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:27+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix invisible character display

Changed paths:
    engines/kyra/gui/gui_eob.cpp


diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index ae787a5..005c67c 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -241,8 +241,8 @@ void EoBCoreEngine::gui_drawFaceShape(int index) {
 	}
 
 	if (_flags.gameID == GI_EOB1) {
-		if (c->effectFlags & 4) {
-			_screen->fillRect(x, y, x + 31, y + 31, 12);
+		if (c->effectFlags & 0x40) {
+			_screen->fillRect(x, y, x + 31, y + 31, guiSettings()->colors.guiColorBlack);
 			return;
 		}
 	} else {


Commit: 5af15399ec1e00feab1d80fcdb65bac2b66c5499
    https://github.com/scummvm/scummvm/commit/5af15399ec1e00feab1d80fcdb65bac2b66c5499
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:27+01:00

Commit Message:
KYRA: (EOB) - improve timer handling

Changed paths:
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/kyra_rpg.h
    engines/kyra/engine/scene_eob.cpp
    engines/kyra/engine/timer_eob.cpp


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 96cc131..0efaab8 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -154,7 +154,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
 	_spells = 0;
 	_spellAnimBuffer = 0;
 	_clericSpellOffset = 0;
-	_restPartyElapsedTime = 0;
+	_restPartyElapsedTime = _disableElapsedTime = 0;
 	_allowSkip = false;
 	_allowImport = false;
 
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 293878c..c7f3fbc 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -338,6 +338,8 @@ protected:
 
 	// timers
 	void setupTimers();
+	virtual void enableSysTimer(int sysTimer);
+	virtual void disableSysTimer(int sysTimer);
 	void setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer);
 	void deleteCharEventTimer(int charIndex, int evnt);
 	void setupCharacterTimers();
@@ -357,7 +359,8 @@ protected:
 	static const uint8 _clock2Timers[];
 	static const uint8 _numClock2Timers;
 
-	int32 _restPartyElapsedTime;
+	uint32 _disableElapsedTime;
+	uint32 _restPartyElapsedTime;
 
 	// Mouse
 	void setHandItem(Item itemIndex);
diff --git a/engines/kyra/engine/kyra_rpg.h b/engines/kyra/engine/kyra_rpg.h
index a132ec7..a6625e1 100644
--- a/engines/kyra/engine/kyra_rpg.h
+++ b/engines/kyra/engine/kyra_rpg.h
@@ -150,8 +150,8 @@ protected:
 
 	// timers
 	virtual void setupTimers() = 0;
-	void enableSysTimer(int sysTimer);
-	void disableSysTimer(int sysTimer);
+	virtual void enableSysTimer(int sysTimer);
+	virtual void disableSysTimer(int sysTimer);
 	void enableTimer(int id);
 	virtual uint8 getClock2Timer(int index) = 0;
 	virtual uint8 getNumClock2Timers() = 0;
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 7eab7ce..80d3e7d 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -35,8 +35,11 @@ namespace Kyra {
 void EoBCoreEngine::loadLevel(int level, int sub) {
 	_currentLevel = level;
 	_currentSub = sub;
+
 	if (!_loading)
 		setHandItem(-1);
+
+	disableSysTimer(2);
 	uint32 end = _system->getMillis() + 500;
 
 	readLevelFileData(level);
diff --git a/engines/kyra/engine/timer_eob.cpp b/engines/kyra/engine/timer_eob.cpp
index 8cac8d8..ef50201 100644
--- a/engines/kyra/engine/timer_eob.cpp
+++ b/engines/kyra/engine/timer_eob.cpp
@@ -55,6 +55,48 @@ void EoBCoreEngine::setupTimers() {
 	_timer->resetNextRun();
 }
 
+void EoBCoreEngine::enableSysTimer(int sysTimer) {
+	if (sysTimer != 2)
+		return;
+
+	KyraRpgEngine::enableSysTimer(sysTimer);
+
+	_disableElapsedTime = _system->getMillis() - _disableElapsedTime;
+
+	for (int i = 0; i < 6; i++) {
+		EoBCharacter *c = &_characters[i];
+		for (int ii = 0; ii < 10; ii++) {
+			if (c->timers[ii])
+				c->timers[ii] += _disableElapsedTime;
+		}
+	}
+
+	setupCharacterTimers();
+
+	if (_scriptTimersMode & 1) {
+		for (int i = 0; i < _scriptTimersCount; i++) {
+			if (_scriptTimers[i].next)
+				_scriptTimers[i].next += _disableElapsedTime;
+		}
+	}
+
+	for (int i = 0; i < 5; i++) {
+		if (_wallsOfForce[i].block)
+			_wallsOfForce[i].duration += _disableElapsedTime;
+	}
+
+	_disableElapsedTime = 0;
+}
+
+void EoBCoreEngine::disableSysTimer(int sysTimer) {
+	if (sysTimer != 2)
+		return;
+
+	KyraRpgEngine::disableSysTimer(sysTimer);
+
+	_disableElapsedTime = _system->getMillis();
+}
+
 void EoBCoreEngine::setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer) {
 	uint32 ntime = _system->getMillis() + countdown * _tickLength;
 	uint8 timerId = 0x30 | (charIndex & 0x0F);
@@ -130,7 +172,7 @@ void EoBCoreEngine::setupCharacterTimers() {
 			_timer->disable(0x30 | i);
 		else {
 			enableTimer(0x30 | i);
-			_timer->setCountdown(0x30 | i, (nextTimer - ctime) / _tickLength);
+			_timer->setCountdown(0x30 | i, nextTimer >= ctime ? (nextTimer - ctime) / _tickLength : 1);
 		}
 	}
 	_timer->resetNextRun();
@@ -143,27 +185,38 @@ void EoBCoreEngine::advanceTimers(uint32 millis) {
 		for (int ii = 0; ii < 10; ii++) {
 			if (c->timers[ii] > ct) {
 				uint32 chrt = c->timers[ii] - ct;
-				c->timers[ii] = chrt > millis ? ct + chrt - millis : ct;
-			}
+                c->timers[ii] = chrt > millis ? ct + chrt - millis : 1;
+			} else if (c->timers[ii]) {
+                c->timers[ii] = 1;
+            }
 		}
 	}
 
+	if (_disableElapsedTime)
+		_disableElapsedTime += (ct - _disableElapsedTime);
+
 	setupCharacterTimers();
 
 	if (_scriptTimersMode & 1) {
 		for (int i = 0; i < _scriptTimersCount; i++) {
 			if (_scriptTimers[i].next > ct) {
 				uint32 chrt = _scriptTimers[i].next - ct;
-				_scriptTimers[i].next = chrt > millis ? ct + chrt - millis : ct;
-			}
+				_scriptTimers[i].next = chrt > millis ? ct + chrt - millis : 1;
+			} else if (_scriptTimers[i].next) {
+                _scriptTimers[i].next = 1;
+            }
 		}
 	}
 
 	for (int i = 0; i < 5; i++) {
+		if (!_wallsOfForce[i].block)
+			continue;
 		if (_wallsOfForce[i].duration > ct) {
 			uint32 chrt = _wallsOfForce[i].duration - ct;
-			_wallsOfForce[i].duration = chrt > millis ? ct + chrt - millis : ct;
-		}
+			_wallsOfForce[i].duration = chrt > millis ? ct + chrt - millis : 1;
+		} else {
+            _wallsOfForce[i].duration = 1;
+        }
 	}
 }
 


Commit: 83f104491528a6a7c92cf017c53a56793fc213e0
    https://github.com/scummvm/scummvm/commit/83f104491528a6a7c92cf017c53a56793fc213e0
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:28+01:00

Commit Message:
KYRA: (EOB1) - make dispel magic spell more accurate

(In EOB1 this spell is supposed to affect only one selected party member and not the whole party)

Changed paths:
    engines/kyra/engine/magic_eob.cpp
    engines/kyra/resource/staticres_eob.cpp


diff --git a/engines/kyra/engine/magic_eob.cpp b/engines/kyra/engine/magic_eob.cpp
index 448f7f0..a0e01c3 100644
--- a/engines/kyra/engine/magic_eob.cpp
+++ b/engines/kyra/engine/magic_eob.cpp
@@ -886,7 +886,15 @@ bool EoBCoreEngine::spellCallback_end_melfsAcidArrow(void *obj) {
 }
 
 void EoBCoreEngine::spellCallback_start_dispelMagic() {
-	for (int i = 0; i < 6; i++) {
+	int first = 0;
+	int last = 5;
+
+	if (_flags.gameID == GI_EOB1) {
+		_txt->printMessage(_magicStrings8[0], -1, _characters[_activeSpellCharId].name);
+		first = last = _activeSpellCharId;
+	}
+
+	for (int i = first; i <= last; i++) {
 		if (testCharacter(i, 1))
 			removeAllCharacterEffects(i);
 	}
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index 281cb7f..a9f9c33 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -1228,7 +1228,7 @@ void EoBEngine::initSpells() {
 		{ 0x0000, 0x000000, 0x00 }, // dummy
 		{ 0x0100, 0x000000, 0x11 }, // melf's acid arrow
 		{ 0x0000, 0x000000, 0x00 }, // STINKING CLOUD
-		{ 0x1000, 0x000000, 0x00 }, // dispel magic
+		{ 0x00A0, 0x000000, 0x00 }, // dispel magic
 		{ 0x0100, 0x000000, 0x21 }, // fireball
 		{ 0x0100, 0x000000, 0x11 }, // FLAME ARROW
 		{ 0x0248, 0x010000, 0x00 }, // haste
@@ -1252,7 +1252,7 @@ void EoBEngine::initSpells() {
 		{ 0x0100, 0x000000, 0x00 }, // hold person
 		{ 0x0028, 0x002000, 0x00 }, // slow poison
 		{ 0x0040, 0x000000, 0x00 }, // create food
-		{ 0x1000, 0x000000, 0x00 }, // dispel magic
+		{ 0x00A0, 0x000000, 0x00 }, // dispel magic
 		{ 0x0099, 0x004000, 0x00 }, // magical vestment
 		{ 0x004C, 0x008000, 0x00 }, // prayer
 		{ 0x0040, 0x000000, 0x00 }, // remove paralysis


Commit: 3fccab8f929dedb0d918e09feaccfbe1e2714ba4
    https://github.com/scummvm/scummvm/commit/3fccab8f929dedb0d918e09feaccfbe1e2714ba4
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:28+01:00

Commit Message:
KYRA: (EOB1) - fix turn undead spell in level 7

Changed paths:
    engines/kyra/engine/eobcommon.cpp


diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 0efaab8..c2ce853 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -687,11 +687,11 @@ void EoBCoreEngine::runLoop() {
 		if (_sceneUpdateRequired)
 			drawScene(1);
 
-		if (_envAudioTimer >= _system->getMillis() || (_flags.gameID == GI_EOB1 && (_currentLevel == 0 || _currentLevel > 3)))
-			continue;
+		if (_envAudioTimer < _system->getMillis() && !(_flags.gameID == GI_EOB1 && (_flags.platform == Common::kPlatformAmiga || _currentLevel == 0 || _currentLevel > 3))) {
+			_envAudioTimer = _system->getMillis() + (rollDice(1, 10, 3) * 18 * _tickLength);
+			snd_processEnvironmentalSoundEffect(_flags.gameID == GI_EOB1 ? 30 : (rollDice(1, 2, -1) ? 27 : 28), _currentBlock + rollDice(1, 12, -1));
+		}
 
-		_envAudioTimer = _system->getMillis() + (rollDice(1, 10, 3) * 18 * _tickLength);
-		snd_processEnvironmentalSoundEffect(_flags.gameID == GI_EOB1 ? 30 : (rollDice(1, 2, -1) ? 27 : 28), _currentBlock + rollDice(1, 12, -1));
 		updateEnvironmentalSfx(0);
 		turnUndeadAuto();
 	}
@@ -1503,7 +1503,7 @@ void EoBCoreEngine::increasePartyExperience(int16 points) {
 void EoBCoreEngine::increaseCharacterExperience(int charIndex, int32 points) {
 	int cl = _characters[charIndex].cClass;
 	points /= _numLevelsPerClass[cl];
-
+	
 	for (int i = 0; i < 3; i++) {
 		if (getCharacterClassType(cl, i) == -1)
 			continue;


Commit: 379df2b9e3cc85e825c74bf12239adf1ed004b11
    https://github.com/scummvm/scummvm/commit/379df2b9e3cc85e825c74bf12239adf1ed004b11
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:28+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix Cone of Cold spell sfx

Changed paths:
    engines/kyra/engine/magic_eob.cpp


diff --git a/engines/kyra/engine/magic_eob.cpp b/engines/kyra/engine/magic_eob.cpp
index a0e01c3..35780f8 100644
--- a/engines/kyra/engine/magic_eob.cpp
+++ b/engines/kyra/engine/magic_eob.cpp
@@ -1032,6 +1032,10 @@ void EoBCoreEngine::spellCallback_start_coneOfCold() {
 	_screen->setGfxParameters(0, 0, _screen->getPagePixel(2, 0, 0));
 	drawSceneShapes(7);
 	_screen->setCurPage(0);
+
+	if (_flags.gameID == GI_EOB1 && _flags.platform == Common::kPlatformAmiga)
+		snd_playSoundEffect(98);
+
 	disableSysTimer(2);
 	_screen->drawVortex(150, 50, 10, 1, 100, _coneOfColdGfxTbl, _coneOfColdGfxTblSize);
 	enableSysTimer(2);


Commit: ec640a069a76326ac4cd909bf69423f12d37c1e6
    https://github.com/scummvm/scummvm/commit/ec640a069a76326ac4cd909bf69423f12d37c1e6
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:28+01:00

Commit Message:
KYRA: (EOB1/Amiga) - fix Amiga cps decompression

Changed paths:
    engines/kyra/graphics/screen.cpp
    engines/kyra/graphics/screen.h
    engines/kyra/sound/sound_amiga_eob.cpp


diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp
index 2a5e511..44b6fad 100644
--- a/engines/kyra/graphics/screen.cpp
+++ b/engines/kyra/graphics/screen.cpp
@@ -2364,12 +2364,12 @@ uint16 Screen::decodeEGAGetCode(const uint8 *&pos, uint8 &nib) {
 	return res;
 }
 
-void Screen::decodeFrame3(const uint8 *src, uint8 *dst, uint32 size) {
+void Screen::decodeFrame3(const uint8 *src, uint8 *dst, uint32 size, bool isAmiga) {
 	const uint8 *dstEnd = dst + size;
 	while (dst < dstEnd) {
 		int8 code = *src++;
 		if (code == 0) {
-			uint16 sz = READ_BE_UINT16(src);
+			uint16 sz = isAmiga ? READ_LE_UINT16(src) : READ_BE_UINT16(src);
 			src += 2;
 			memset(dst, *src++, sz);
 			dst += sz;
@@ -3258,7 +3258,7 @@ void Screen::loadBitmap(const char *filename, int tempPage, int dstPage, Palette
 		Screen::decodeFrame1(srcPtr, dstData, imgSize);
 		break;
 	case 3:
-		Screen::decodeFrame3(srcPtr, dstData, imgSize);
+		Screen::decodeFrame3(srcPtr, dstData, imgSize, _isAmiga);
 		break;
 	case 4:
 		Screen::decodeFrame4(srcPtr, dstData, imgSize);
diff --git a/engines/kyra/graphics/screen.h b/engines/kyra/graphics/screen.h
index 23bce62..5a746a0 100644
--- a/engines/kyra/graphics/screen.h
+++ b/engines/kyra/graphics/screen.h
@@ -630,7 +630,7 @@ public:
 	static void decodeFrame1(const uint8 *src, uint8 *dst, uint32 size);
 	static uint16 decodeEGAGetCode(const uint8 *&pos, uint8 &nib);
 
-	static void decodeFrame3(const uint8 *src, uint8 *dst, uint32 size);
+	static void decodeFrame3(const uint8 *src, uint8 *dst, uint32 size, bool isAmiga);
 	static uint decodeFrame4(const uint8 *src, uint8 *dst, uint32 dstSize);
 	static void decodeFrameDelta(uint8 *dst, const uint8 *src, bool noXor = false);
 	static void decodeFrameDeltaPage(uint8 *dst, const uint8 *src, const int pitch, bool noXor);
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
index 8007724..82f2512 100644
--- a/engines/kyra/sound/sound_amiga_eob.cpp
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -120,7 +120,7 @@ void SoundAmiga_EoB::loadSoundFile(Common::String file) {
 		assert(readSize == outSize);
 		memcpy(buf, _fileBuffer, outSize);
 	} else if (cmp == 3) {			
-		Screen::decodeFrame3(_fileBuffer, buf, outSize);
+		Screen::decodeFrame3(_fileBuffer, buf, outSize, true);
 	} else if (cmp == 4) {
 		Screen::decodeFrame4(_fileBuffer, buf, outSize);
 	} else {
@@ -142,6 +142,8 @@ void SoundAmiga_EoB::playTrack(uint8 track) {
 				newSound = "NEWINTRO1.SMUS";
 			else if (track == 20)
 				newSound = "CHARGEN1.SMUS";
+		} else if (_currentResourceSet == kMusicFinale) {
+			newSound = "FINALE.SMUS";
 		}
 	} else if (_vm->game() == GI_EOB2) {
 		


Commit: 25c72ba346042e2c77e780f81a0128bfe59f5a04
    https://github.com/scummvm/scummvm/commit/25c72ba346042e2c77e780f81a0128bfe59f5a04
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:28+01:00

Commit Message:
KYRA: (EOB1/Amiga) - implement ending sequence

The Amiga version actually has a real ending sequence (unlike the PC version).

Changed paths:
    engines/kyra/engine/eob.h
    engines/kyra/sequence/sequences_eob.cpp


diff --git a/engines/kyra/engine/eob.h b/engines/kyra/engine/eob.h
index d0a1c01..de98a91 100644
--- a/engines/kyra/engine/eob.h
+++ b/engines/kyra/engine/eob.h
@@ -32,6 +32,7 @@ namespace Kyra {
 class EoBEngine : public EoBCoreEngine {
 friend class GUI_EoB;
 friend class EoBIntroPlayer;
+friend class EoBAmigaFinalePlayer;
 public:
 	EoBEngine(OSystem *system, const GameFlags &flags);
 	~EoBEngine();
@@ -56,6 +57,8 @@ private:
 	void seq_playFinale();
 	void seq_xdeath();
 
+	void boxMorphTransition(int targetDestX, int targetDestY, int targetFinalX, int targetFinalY, int targetSrcX, int targetSrcY, int targetFinalW, int targetFinalH, int originX1, int originY1, int originW, int originH, int fillColor = -1);
+
 	const char *const *_finBonusStrings;
 
 	// characters
diff --git a/engines/kyra/sequence/sequences_eob.cpp b/engines/kyra/sequence/sequences_eob.cpp
index a0b10e3..5961070 100644
--- a/engines/kyra/sequence/sequences_eob.cpp
+++ b/engines/kyra/sequence/sequences_eob.cpp
@@ -52,7 +52,6 @@ private:
 
 	void loadAndSetPalette(const char *filename);
 	void copyBlurRegion(int x1, int y1, int x2, int y2, int w, int h, int step);
-	void boxMorphTransition(int targetDestX, int targetDestY, int targetFinalX, int targetFinalY, int targetSrcX, int targetSrcY, int targetFinalW, int targetFinalH, int originX1, int originY1, int originW, int originH);
 	void whirlTransition();
 
 	EoBEngine *_vm;
@@ -83,6 +82,40 @@ private:
 	const uint8 _fillColor2;
 };
 
+class EoBAmigaFinalePlayer {
+public:
+	EoBAmigaFinalePlayer(EoBEngine *vm, Screen_EoB *screen);
+	~EoBAmigaFinalePlayer();
+
+	void start();
+
+private:
+	void entry();
+	void delivery();
+	void inspection();
+	void surprise();
+	void congratulation();
+
+	void animateCouncil1(int numFrames, int skipFrame);
+	void animateCouncil2(int numFrames, int skipFrame, bool withSpeechAnim);
+	void playDialogue(int line, bool withAnim);
+
+	uint8 **_textShapes;
+	uint8 *_councilAnimData1;
+	uint8 *_councilAnimData2;
+	
+	const uint8 *_councilAnimData3;
+	const uint8 *_councilAnimData4;
+	const uint8 *_eyesAnimData;	
+	const int16 *_handsAnimData;
+	const uint8 *_textFrameDuration;
+
+	int _animCurFrame;
+
+	EoBEngine *_vm;
+	Screen_EoB *_screen;
+};
+
 EoBIntroPlayer::EoBIntroPlayer(EoBEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen), 
 	_fillColor1(vm->gameFlags().platform == Common::kPlatformAmiga ? 19 : 12), _fillColor2(vm->gameFlags().platform == Common::kPlatformAmiga ? 10 : 157) {
 	int temp = 0;
@@ -536,7 +569,7 @@ void EoBIntroPlayer::hands() {
 	_screen->fillRect(0, 0, 191, 63, _fillColor2, 2);
 	_screen->drawShape(2, shp1, 0, 4, 0);
 	_screen->drawShape(2, shp2, 151, 4, 0);
-	boxMorphTransition(25, 8, 18, 4, 3, 0, 21, 8, 6, 0, 28, 23);
+	_vm->boxMorphTransition(25, 8, 18, 4, 3, 0, 21, 8, 6, 0, 28, 23);
 	_screen->copyRegion(0, 128, 0, 176, 320, 16, 6, 0, Screen::CR_NO_P_CHECK);
 
 	_screen->updateScreen();
@@ -568,7 +601,7 @@ void EoBIntroPlayer::hands() {
 	_screen->fillRect(0, 0, 135, 63, _fillColor2);
 	_screen->drawShape(2, shp1, 32, -80, 0);
 	_screen->drawShape(2, shp2, 40, -16, 0);
-	boxMorphTransition(18, 16, 10, 12, 0, 0, 17, 8, 17, 3, 25, 10);
+	_vm->boxMorphTransition(18, 16, 10, 12, 0, 0, 17, 8, 17, 3, 25, 10);
 	_vm->delay(15 * _vm->_tickLength);
 
 	for (int i = -80; i <= 0 && !_vm->shouldQuit() && !_vm->skipFlag(); i += 4) {
@@ -607,7 +640,7 @@ void EoBIntroPlayer::hands() {
 	_screen->fillRect(0, 0, 143, 95, _fillColor2);
 	_screen->drawShape(2, shp1, -56, -56, 0);
 	_screen->drawShape(2, shp2, 52, 49, 0);
-	boxMorphTransition(9, 6, 0, 0, 0, 0, 18, 12, 8, 11, 21, 10);
+	_vm->boxMorphTransition(9, 6, 0, 0, 0, 0, 18, 12, 8, 11, 21, 10);
 	_vm->delay(15 * _vm->_tickLength);
 	_vm->snd_playSoundEffect(11);
 
@@ -633,7 +666,7 @@ void EoBIntroPlayer::hands() {
 	_screen->setCurPage(2);
 	_screen->fillRect(0, 0, 87, 112, _fillColor2);
 	_screen->drawShape(2, shp2, 0, 90, 0);
-	boxMorphTransition(20, 13, 15, 6, 0, 0, 11, 14, 0, 0, 24, 16);
+	_vm->boxMorphTransition(20, 13, 15, 6, 0, 0, 11, 14, 0, 0, 24, 16);
 	_vm->delay(15 * _vm->_tickLength);
 
 	int dy = 90;
@@ -950,63 +983,6 @@ void EoBIntroPlayer::copyBlurRegion(int x1, int y1, int x2, int y2, int w, int h
 	}
 }
 
-void EoBIntroPlayer::boxMorphTransition(int targetDestX, int targetDestY, int targetFinalX, int targetFinalY, int targetSrcX, int targetSrcY, int targetFinalW, int targetFinalH, int originX1, int originY1, int originW, int originH) {
-	int originX2 = originX1 + originW;
-	int originY2 = originY1 + originH;
-	if (originY2 > 21)
-		originY2 = 21;
-
-	int w = 1;
-	int h = 1;
-	for (bool runloop = true; runloop && !_vm->shouldQuit() && !_vm->skipFlag();) {
-		uint32 end = _vm->_system->getMillis() + _vm->_tickLength;
-		_screen->copyRegion(targetSrcX << 3, targetSrcY << 3, targetDestX << 3, targetDestY << 3, w << 3, h << 3, 2, 0, Screen::CR_NO_P_CHECK);
-		if (originX1 < targetDestX)
-			_screen->copyRegion(312, 0, originX1 << 3, 0, 8, 176, 0, 0, Screen::CR_NO_P_CHECK);
-		if (originY1 < targetDestY)
-			_screen->copyRegion(0, 192, 0, originY1 << 3, 320, 8, 0, 0, Screen::CR_NO_P_CHECK);
-		if ((targetFinalX + targetFinalW) <= originX2)
-			_screen->copyRegion(312, 0, originX2 << 3, 0, 8, 176, 0, 0, Screen::CR_NO_P_CHECK);
-		if ((targetFinalY + targetFinalH) <= originY2)
-			_screen->copyRegion(0, 192, 0, originY2 << 3, 320, 8, 0, 0, Screen::CR_NO_P_CHECK);
-
-		if (!(targetDestX != targetFinalX || targetDestY != targetFinalY || w != targetFinalW || h != targetFinalH || originX1 < targetFinalX || originY1 < targetFinalY || (targetFinalX + targetFinalW) < originX2 || (targetFinalY + targetFinalH) < originY2))
-			runloop = false;
-
-		int v = targetFinalX - targetDestX;
-		v = (v < 0) ? -1 : ((v > 0) ? 1 : 0);
-		targetDestX += v;
-		v = targetFinalY - targetDestY;
-		v = (v < 0) ? -1 : ((v > 0) ? 1 : 0);
-		targetDestY += v;
-
-		if (w != targetFinalW)
-			w += 2;
-		if (w > targetFinalW)
-			w = targetFinalW;
-
-		if (h != targetFinalH)
-			h += 2;
-		if (h > targetFinalH)
-			h = targetFinalH;
-
-		if (++originX1 > targetFinalX)
-			originX1 = targetFinalX;
-
-		if (++originY1 > targetFinalY)
-			originY1 = targetFinalY;
-
-		if ((targetFinalX + targetFinalW) < originX2)
-			originX2--;
-
-		if ((targetFinalY + targetFinalH) < originY2)
-			originY2--;
-
-		_screen->updateScreen();
-		_vm->delayUntil(end);
-	}
-}
-
 void EoBIntroPlayer::whirlTransition() {
 	if (_vm->gameFlags().platform == Common::kPlatformAmiga) {
 		_screen->fadeToBlack(48);
@@ -1032,6 +1008,404 @@ void EoBIntroPlayer::whirlTransition() {
 	}
 }
 
+EoBAmigaFinalePlayer::EoBAmigaFinalePlayer(EoBEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen) {
+	_animCurFrame = 0;
+	int size = 0;
+	_textShapes = new uint8*[10];
+	memset(_textShapes, 0, sizeof(uint8*) * 10);
+	_councilAnimData1 = new uint8[78];
+	memcpy(_councilAnimData1, _vm->staticres()->loadRawData(kEoB1FinaleCouncilAnim1, size), 78);
+	_councilAnimData2 = new uint8[78];
+	memcpy(_councilAnimData2, _vm->staticres()->loadRawData(kEoB1FinaleCouncilAnim2, size), 78);
+	_councilAnimData3 = _vm->staticres()->loadRawData(kEoB1FinaleCouncilAnim3, size);
+	_councilAnimData4 = _vm->staticres()->loadRawData(kEoB1FinaleCouncilAnim4, size);
+	_eyesAnimData = _vm->staticres()->loadRawData(kEoB1FinaleEyesAnim, size);
+	_handsAnimData = (const int16*)_vm->staticres()->loadRawDataBe16(kEoB1FinaleHandsAnim, size);
+	_textFrameDuration = _vm->staticres()->loadRawData(kEoB1FinaleTextDuration, size);;
+}
+
+EoBAmigaFinalePlayer::~EoBAmigaFinalePlayer() {
+	for (int i = 0; i < 10; ++i)
+		delete[] _textShapes[i];
+	delete[] _textShapes;
+	delete[] _councilAnimData1;
+	delete[] _councilAnimData2;
+}
+
+void EoBAmigaFinalePlayer::start() {
+	_screen->hideMouse();
+	uint32 tick = _vm->_system->getMillis() + 80 * _vm->_tickLength;
+
+	_screen->clearPage(0);
+	_screen->clearPage(2);
+	_screen->loadShapeSetBitmap("TEXT2", 5, 3);
+	for (int i = 0; i < 10; ++i)
+		_textShapes[i] = _screen->encodeShape(0, i << 4, 40, 15);
+	_screen->clearPage(2);
+
+	_screen->loadBitmap("COUNCILA.CPS", 2, 4, 0);
+	_screen->loadBitmap("COUNCILB.CPS", 2, 6, 0);
+
+	_vm->delayUntil(tick);
+	_vm->_eventList.clear();
+	_vm->_allowSkip = true;
+
+	_vm->sound()->playTrack(0);
+
+	entry();
+	delivery();
+	inspection();
+	surprise();
+	congratulation();
+
+	_screen->fadeToBlack();
+}
+
+void EoBAmigaFinalePlayer::entry() {
+	static uint8 textMode[] = { 1, 1, 0, 1, 1, 0 };
+	if (_vm->shouldQuit() || _vm->skipFlag())
+		return;
+
+	_screen->setScreenPalette(_screen->getPalette(0));
+	_screen->copyRegion(0, 0, 0, 0, 320, 72, 4, 2, Screen::CR_NO_P_CHECK);
+	_screen->copyRegion(0, 0, 0, 80, 320, 72, 2, 2, Screen::CR_NO_P_CHECK);
+
+	for (int i = 1; i < 21 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		_screen->copyRegion((20 - i) << 3, 80, (20 - i) << 3, 48, i << 4, 72, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->updateScreen();
+		_vm->delay(2 * _vm->_tickLength);
+	}
+
+	for (int i = 0; i < 15 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		animateCouncil1(2, -1);
+		_screen->updateScreen();
+		_vm->delay(4 * _vm->_tickLength);
+	}
+
+	for (int i = 0; i < 65 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		animateCouncil1(_vm->_rnd.getRandomNumberRng(1, 3), -1);
+		_screen->updateScreen();
+		_vm->delay(4 * _vm->_tickLength);
+
+		if (i == 45 || i == 47) {
+			animateCouncil1(99, -1);
+			_screen->updateScreen();
+		}
+
+		if (i % 16 == 0)
+			playDialogue(i >> 4, textMode[i >> 4]);
+	}
+}
+
+void EoBAmigaFinalePlayer::delivery() {
+	if (_vm->shouldQuit() || _vm->skipFlag())
+		return;
+
+	_screen->setCurPage(4);
+	uint8 *shp = _screen->encodeShape(0, 72, 3, 32, true);
+
+	for (int i = 0; i < 5 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		static const uint8 y[5] = { 152,  139,  131,  129,  127 };
+		_screen->copyRegion(120, 30, 120, 110, 56, 42, 2, 2, Screen::CR_NO_P_CHECK);
+		_screen->drawShape(2, shp, 153, y[i], 0);
+		_screen->copyRegion(120, 110, 120, 78, 56, 42, 2, 0, Screen::CR_NO_P_CHECK);
+		animateCouncil1(2, -1);
+		_screen->updateScreen();
+		_vm->delay(4 * _vm->_tickLength);
+	}
+
+	for (int i = 0; i < 6 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		_screen->copyRegion(120, 30, 120, 110, 64, 42, 2, 2, Screen::CR_NO_P_CHECK);
+		_screen->copyRegion((i * 5 + 3) << 3, 72, 144, 120, 48, 32, 4, 2, Screen::CR_NO_P_CHECK);
+		_screen->copyRegion(120, 110, 120, 78, 64, 42, 2, 0, Screen::CR_NO_P_CHECK);
+		animateCouncil1(2, -1);
+		_screen->updateScreen();
+		_vm->delay(4 * _vm->_tickLength);
+	}
+
+	for (int i = 0; i < 5 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		animateCouncil2(5, 2, false);
+		animateCouncil1(2, -1);
+		_screen->updateScreen();
+		_vm->delay(4 * _vm->_tickLength);
+	}
+
+	delete[] shp;
+}
+
+void EoBAmigaFinalePlayer::inspection() {
+	if (_vm->shouldQuit() || _vm->skipFlag())
+		return;
+
+	uint8 *shp[5];
+	memset(shp, 0, sizeof(shp));
+	
+	_screen->fillRect(0, 170, 319, 186, 31, 0);
+	_screen->clearPage(2);
+
+	_screen->setCurPage(6);
+	shp[0] = _screen->encodeShape(0, 0, 8, 40, true);
+	_screen->drawShape(2, shp[0], 96, 24, 0, 0);
+	_screen->drawShape(2, shp[0], 160, 24, 0, 1);
+	delete[] shp[0];
+
+	_screen->fillRect(0, 48, 9, 120, 31, 0);
+	_screen->fillRect(312, 48, 319, 120, 31, 0);
+
+	_vm->boxMorphTransition(18, 6, 12, 3, 12, 3, 16, 5, 1, 5, 39, 10, 31);
+
+	for (int i = 0; i < 5; ++i)
+		shp[i] = _screen->encodeShape((i << 2) + 8, 0, 4, 24, true);
+
+	_vm->delay(10 * _vm->_tickLength);
+
+	for (int i = 2; i < 81 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		_screen->copyRegion(192, 56, 96, 160 - i, 128, i, 6, 0, Screen::CR_NO_P_CHECK);
+		_screen->updateScreen();
+		_vm->delay(_vm->_tickLength);
+		if (i == 40)
+			playDialogue(5, false);
+	}
+
+	for (int i = 0; _eyesAnimData[i] != 0xFF && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		if (_eyesAnimData[i] == 15 || _eyesAnimData[i] == 40) {
+			_vm->delay(_eyesAnimData[i] * _vm->_tickLength);
+			continue;
+		}
+
+		_screen->drawShape(2, shp[_eyesAnimData[i]], 112, 32, 0, 0);
+		_screen->drawShape(2, shp[_eyesAnimData[i]], 176, 32, 0, 1);
+		_screen->copyRegion(112, 32, 112, 32, 96, 24, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->updateScreen();
+
+		_vm->delay(_vm->_tickLength);	
+	}
+
+	for (int i = 0; i < 5; ++i)
+		delete[] shp[i];
+}
+
+void EoBAmigaFinalePlayer::surprise() {
+	if (_vm->shouldQuit() || _vm->skipFlag())
+		return;
+
+	_screen->copyRegion(0, 0, 0, 0, 320, 72, 4, 2, Screen::CR_NO_P_CHECK);
+	_screen->copyRegion(0, 0, 0, 80, 320, 72, 2, 2, Screen::CR_NO_P_CHECK);
+	_screen->copyRegion(224, 96, 144, 144, 40, 8, 4, 2, Screen::CR_NO_P_CHECK);
+
+	for (int i = 0; i < 4; ++i) {
+		const uint8 *crds = &_councilAnimData4[i * 6];
+		_screen->copyRegion(crds[0] << 3, crds[1], crds[4] << 3, crds[5], crds[2] << 3, crds[3], 4, 2, Screen::CR_NO_P_CHECK);
+	}
+
+	_vm->boxMorphTransition(0, 9, 0, 6, 0, 10, 40, 9, 12, 3, 16, 21, 31);
+
+	for (int i = 0; i < 15 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		animateCouncil1(4, 2);
+		animateCouncil2(6, -1, false);
+		_screen->updateScreen();
+		_vm->delay(4 * _vm->_tickLength);
+	}
+
+	animateCouncil2(98, 2, true);
+	_vm->delay(10 * _vm->_tickLength);
+	playDialogue(6, true);
+	_vm->delay(60 * _vm->_tickLength);
+
+	_screen->fadeToBlack(16);
+	_screen->clearPage(0);
+}
+
+void EoBAmigaFinalePlayer::congratulation() {
+	if (_vm->shouldQuit() || _vm->skipFlag())
+		return;
+
+	uint8 *shp[3];
+	memset(shp, 0, sizeof(shp));
+
+	_screen->setCurPage(6);
+	shp[0] = _screen->encodeShape(12, 24, 12, 64, true);
+	shp[1] = _screen->encodeShape(12, 88, 12, 72, true);
+	shp[2] = _screen->encodeShape(24, 136, 15, 64, true);
+	
+	_screen->clearPage(2);
+	_screen->fadeFromBlack(1);
+
+	playDialogue(7, false);
+
+	for (int i = 1; i < 13 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		_screen->copyRegion((12 - i) << 3, 40, (26 - i) << 3, 24, i << 3, 120, 6, 0, Screen::CR_NO_P_CHECK);
+		_screen->updateScreen();
+		_vm->delay(2 * _vm->_tickLength);
+	}
+
+	_vm->delay(75 * _vm->_tickLength);
+	_screen->fadeToBlack(32);
+	_screen->clearPage(0);
+	_screen->fadeFromBlack(1);
+
+	for (int i = 0; i < 10 && !_vm->skipFlag() && !_vm->shouldQuit(); i += 2) {
+		_screen->drawShape(2, shp[0], _handsAnimData[i], _handsAnimData[i + 1], 0);
+		_screen->copyRegion(0, 50, 0, 50, 320, 90, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->clearPage(2);
+		_screen->updateScreen();
+		_vm->delay(_vm->_tickLength);
+	}
+
+	playDialogue(8, false);
+	_screen->updateScreen();
+	_vm->delay(50 * _vm->_tickLength);
+
+	for (int i = 10; i < 18 && !_vm->skipFlag() && !_vm->shouldQuit(); i += 2) {
+		_screen->drawShape(2, shp[1], _handsAnimData[i], _handsAnimData[i + 1], 0);
+		_screen->drawShape(2, shp[0], _handsAnimData[8], _handsAnimData[9], 0);
+		_screen->copyRegion(0, 50, 0, 50, 320, 90, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->clearPage(2);
+		_screen->updateScreen();
+		_vm->delay(_vm->_tickLength);
+	}
+
+	for (int i = 18; i < 24 && !_vm->skipFlag() && !_vm->shouldQuit(); i += 2) {
+		_screen->drawShape(2, shp[2], _handsAnimData[i], _handsAnimData[i + 1], 0);
+		_screen->copyRegion(0, 50, 0, 50, 320, 90, 2, 0, Screen::CR_NO_P_CHECK);
+		_screen->clearPage(2);
+		_screen->updateScreen();
+		_vm->delay(2 * _vm->_tickLength);
+	}
+
+	for (int i = 0; i < 3 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+		for (int ii = 0; ii < 12 && !_vm->skipFlag() && !_vm->shouldQuit(); ii += 4) {
+			_screen->drawShape(2, shp[2], 91, ii + 51, 0);
+			_screen->copyRegion(0, 50, 0, 50, 320, 90, 2, 0, Screen::CR_NO_P_CHECK);
+			_screen->clearPage(2);
+			_screen->updateScreen();
+			_vm->delay(25);
+		}
+		for (int ii = 12; ii > 0 && !_vm->skipFlag() && !_vm->shouldQuit(); ii -= 4) {
+			_screen->drawShape(2, shp[2], 91, ii + 51, 0);
+			_screen->copyRegion(0, 50, 0, 50, 320, 90, 2, 0, Screen::CR_NO_P_CHECK);
+			_screen->clearPage(2);
+			_screen->updateScreen();
+			_vm->delay(25);
+		}
+	}
+
+	for (int i = 0; i < 3; ++i)
+		delete[] shp[i];
+
+	_vm->delay(40 * _vm->_tickLength);
+	_screen->fadeToBlack(48);
+	_screen->clearPage(0);
+	playDialogue(9, false);
+	_screen->fadeFromBlack(48);
+
+	while (!_vm->skipFlag() && !_vm->shouldQuit()) {
+		_vm->updateInput();
+		_vm->delay(10);
+	}
+
+	_screen->fadeToBlack(48);
+}
+
+void EoBAmigaFinalePlayer::animateCouncil1(int numFrames, int skipFrame) {
+	int frame = 5;
+	int subFrame = 0;
+	int subFrameAlt = 2;
+	
+	if (numFrames == 99) {
+		subFrame = _animCurFrame ? 6 : 0;
+		_animCurFrame ^= 1;
+		const uint8 *crds = &_councilAnimData3[subFrame];
+		_screen->copyRegion(crds[0] << 3, crds[1], crds[4] << 3, crds[5], crds[2] << 3, crds[3], 4, 0, Screen::CR_NO_P_CHECK);
+
+	} else {
+		for (int i = 0; i < numFrames; ++i) {
+			if (i) {
+				frame = _vm->_rnd.getRandomNumberRng(0, 200);
+				frame = (frame <= 32) ? frame >> 3 : -1;
+				subFrameAlt = 1;
+			}
+
+			if (frame == -1 || frame == skipFrame)
+				continue;
+
+			if (subFrameAlt == _councilAnimData1[frame * 13 + 12]) {
+				_councilAnimData1[frame * 13 + 12] = 0;
+				subFrame = 6;
+			} else {
+				_councilAnimData1[frame * 13 + 12]++;
+				subFrame = 0;
+			}
+	
+			const uint8 *crds = &_councilAnimData1[frame * 13 + subFrame];
+			_screen->copyRegion(crds[0] << 3, crds[1], crds[4] << 3, crds[5], crds[2] << 3, crds[3], 4, 0, Screen::CR_NO_P_CHECK);
+		}
+	}
+}
+
+void EoBAmigaFinalePlayer::animateCouncil2(int numFrames, int skipFrame, bool withSpeechAnim) {
+	if (numFrames == 98) {
+		uint8 frames[6];
+		for (int i = 0; i < 6; ++i)
+			frames[i] = i;
+
+		for (int i = 0; i < 6; ++i)
+			SWAP(frames[i], frames[_vm->_rnd.getRandomNumberRng(0, 5)]);
+
+		for (int i = 0; i < 6 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) {
+			if (frames[i] == skipFrame)
+				continue;
+			
+			uint8 *crds = &_councilAnimData2[frames[i] * 13];
+			crds[12] = 0;
+			_screen->copyRegion(crds[0] << 3, crds[1], crds[4] << 3, crds[5], crds[2] << 3, crds[3], 4, 0, Screen::CR_NO_P_CHECK);
+			
+			if (withSpeechAnim)
+				animateCouncil1(2, -1);
+
+			_screen->updateScreen();
+			_vm->delay(3 * _vm->_tickLength);
+		}
+	} else {
+		for (int i = 0; i < numFrames; ++i) {
+			int frame = _vm->_rnd.getRandomNumberRng(0, 250);
+			frame = (frame <= 40) ? frame >> 3 : -1;
+
+			if (frame == -1 || frame == skipFrame)
+				continue;
+
+			const uint8 *crds = &_councilAnimData2[frame * 13 + _councilAnimData2[frame * 13 + 12] * 6];
+			_councilAnimData2[frame * 13 + 12] ^= 1;
+			_screen->copyRegion(crds[0] << 3, crds[1], crds[4] << 3, crds[5], crds[2] << 3, crds[3], 4, 0, Screen::CR_NO_P_CHECK);
+		}
+	}
+}
+
+void EoBAmigaFinalePlayer::playDialogue(int line, bool withAnim) {
+	static const uint8 crds[] = { 0x03, 0x68, 0x05, 0x68 };
+	_screen->fillRect(0, 170, 319, 186, 31, 0);
+
+	if (withAnim) {
+		_screen->drawShape(0, _textShapes[line], 0, 170);
+		const uint8 *len = &_textFrameDuration[line * 17];
+		int offs = 2;
+
+		for (int i = 0; len[i] != 0x7F && !_vm->skipFlag(); ++i) {
+			if (len[i] == 0x7E)
+				continue;
+			offs ^= 2;
+			_screen->copyRegion(crds[offs] << 3, crds[offs + 1], 152, 72, 16, 8, 4, 0, Screen::CR_NO_P_CHECK);
+			animateCouncil1(2, 2);
+			_screen->updateScreen();
+			_vm->delay(len[i] * _vm->_tickLength);
+		}
+		_screen->copyRegion(crds[2] << 3, crds[3], 152, 72, 16, 8, 4, 0, Screen::CR_NO_P_CHECK);
+
+	} else {
+		_screen->drawShape(0, _textShapes[line], 0, line == 9 ? 92 : 170);
+	}	
+}
+
 int EoBEngine::mainMenu() {
 	int menuChoice = _menuChoiceInit;
 	_menuChoiceInit = 0;
@@ -1169,6 +1543,9 @@ void EoBEngine::seq_playFinale() {
 
 	_txt->printDialogueText(Common::String::format(_finBonusStrings[2], password).c_str(), true);
 	_screen->fadeToBlack();
+
+	if (_flags.platform == Common::kPlatformAmiga)
+		EoBAmigaFinalePlayer(this, _screen).start();
 }
 
 void EoBEngine::seq_xdeath() {
@@ -1229,6 +1606,68 @@ void EoBEngine::seq_xdeath() {
 	gui_drawAllCharPortraitsWithStats();
 }
 
+void EoBEngine::boxMorphTransition(int targetDestX, int targetDestY, int targetFinalX, int targetFinalY, int targetSrcX, int targetSrcY, int targetFinalW, int targetFinalH, int originX1, int originY1, int originW, int originH, int fillColor) {
+	int originX2 = originX1 + originW;
+	int originY2 = originY1 + originH;
+	if (originY2 > 21)
+		originY2 = 21;
+
+	if (fillColor != -1) {
+		_screen->fillRect(0, 170, 319, 186, fillColor, 0);
+		_screen->fillRect(0, 170, 319, 186, fillColor, 2);
+	}
+
+	int w = 1;
+	int h = 1;
+	for (bool runloop = true; runloop && !shouldQuit() && !skipFlag();) {
+		uint32 end = _system->getMillis() + _tickLength;
+		_screen->copyRegion(targetSrcX << 3, targetSrcY << 3, targetDestX << 3, targetDestY << 3, w << 3, h << 3, 2, 0, Screen::CR_NO_P_CHECK);
+		if (originX1 < targetDestX)
+			_screen->copyRegion(312, 0, originX1 << 3, 0, 8, 176, 0, 0, Screen::CR_NO_P_CHECK);
+		if (originY1 < targetDestY)
+			_screen->copyRegion(0, 192, 0, originY1 << 3, 320, 8, 0, 0, Screen::CR_NO_P_CHECK);
+		if ((targetFinalX + targetFinalW) <= originX2)
+			_screen->copyRegion(312, 0, originX2 << 3, 0, 8, 176, 0, 0, Screen::CR_NO_P_CHECK);
+		if ((targetFinalY + targetFinalH) <= originY2)
+			_screen->copyRegion(0, 192, 0, originY2 << 3, 320, 8, 0, 0, Screen::CR_NO_P_CHECK);
+
+		if (!(targetDestX != targetFinalX || targetDestY != targetFinalY || w != targetFinalW || h != targetFinalH || originX1 < targetFinalX || originY1 < targetFinalY || (targetFinalX + targetFinalW) < originX2 || (targetFinalY + targetFinalH) < originY2))
+			runloop = false;
+
+		int v = targetFinalX - targetDestX;
+		v = (v < 0) ? -1 : ((v > 0) ? 1 : 0);
+		targetDestX += v;
+		v = targetFinalY - targetDestY;
+		v = (v < 0) ? -1 : ((v > 0) ? 1 : 0);
+		targetDestY += v;
+
+		if (w != targetFinalW)
+			w += 2;
+		if (w > targetFinalW)
+			w = targetFinalW;
+
+		if (h != targetFinalH)
+			h += 2;
+		if (h > targetFinalH)
+			h = targetFinalH;
+
+		if (++originX1 > targetFinalX)
+			originX1 = targetFinalX;
+
+		if (++originY1 > targetFinalY)
+			originY1 = targetFinalY;
+
+		if ((targetFinalX + targetFinalW) < originX2)
+			originX2--;
+
+		if ((targetFinalY + targetFinalH) < originY2)
+			originY2--;
+
+		_screen->updateScreen();
+		delayUntil(end);
+	}
+}
+
 } // End of namespace Kyra
 
 #endif // ENABLE_EOB


Commit: bf17c9f33e48b4e091ba85b1f6868cc518839191
    https://github.com/scummvm/scummvm/commit/bf17c9f33e48b4e091ba85b1f6868cc518839191
Author: athrxx (athrxx at scummvm.org)
Date: 2019-03-06T20:48:29+01:00

Commit Message:
KYRA: update NEWS file

Changed paths:
    NEWS


diff --git a/NEWS b/NEWS
index 396707f..32ff5e7 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,11 @@ For a more comprehensive changelog of the latest experimental code, see:
    - Fixed playtime not being restored when loading a savegame.
    - Fixed a bug that leads to enormous memory consumption in scene 22.
 
+ Kyra:
+   - Added support for the Amiga version of Eye of the Beholder.
+   - Added support for the FM-Towns version of Eye of the Beholder II.
+   - Several bug fixes.
+
  MOHAWK:
    - Added a main menu for the 25th anniversary release of Myst ME.
    - Repurposed the landing menu as a main menu for the 25th anniversary





More information about the Scummvm-git-logs mailing list