[Scummvm-cvs-logs] CVS: scummvm/sword2 anims.cpp,1.67,1.68 build_display.cpp,1.69,1.70 build_display.h,1.14,1.15 console.cpp,1.52,1.53 controls.cpp,1.84,1.85 controls.h,1.16,1.17 debug.cpp,1.47,1.48 debug.h,1.14,1.15 function.cpp,1.76,1.77 icons.cpp,1.40,1.41 layers.cpp,1.34,1.35 layers.h,1.12,1.13 logic.cpp,1.50,1.51 logic.h,1.41,1.42 maketext.cpp,1.46,1.47 mouse.cpp,1.65,1.66 mouse.h,1.15,1.16 resman.cpp,1.105,1.106 router.cpp,1.45,1.46 save_rest.cpp,1.65,1.66 scroll.cpp,1.22,1.23 sound.cpp,1.53,1.54 sound.h,1.15,1.16 speech.cpp,1.70,1.71 sword2.cpp,1.133,1.134 sword2.h,1.75,1.76 walker.cpp,1.44,1.45

Torbjörn Andersson eriktorbjorn at users.sourceforge.net
Sat Feb 19 06:04:42 CET 2005


Update of /cvsroot/scummvm/scummvm/sword2
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20780

Modified Files:
	anims.cpp build_display.cpp build_display.h console.cpp 
	controls.cpp controls.h debug.cpp debug.h function.cpp 
	icons.cpp layers.cpp layers.h logic.cpp logic.h maketext.cpp 
	mouse.cpp mouse.h resman.cpp router.cpp save_rest.cpp 
	scroll.cpp sound.cpp sound.h speech.cpp sword2.cpp sword2.h 
	walker.cpp 
Log Message:
This is the second part of the BS2 restructuring. There are two new
classes: Screen and Mouse. Screen handles most of the drawing, except the
mouse cursor and in-game menus.

The old Graphics class is no more.

I've also fixed some "reverse stereo" regressions from the first part of
the restructuring.

I'm not sure what the next step will be, but hopefully it will be smaller
than this one was.


Index: anims.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/anims.cpp,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- anims.cpp	28 Jan 2005 16:33:07 -0000	1.67
+++ anims.cpp	19 Feb 2005 14:02:09 -0000	1.68
@@ -26,8 +26,10 @@
 
 #include "common/stdafx.h"
 #include "common/file.h"
+
 #include "sword2/sword2.h"
 #include "sword2/defs.h"
+#include "sword2/build_display.h"
 #include "sword2/controls.h"
 #include "sword2/interpreter.h"
 #include "sword2/logic.h"
@@ -36,7 +38,6 @@
 #include "sword2/resman.h"
 #include "sword2/sound.h"
 #include "sword2/driver/animation.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 

Index: build_display.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/build_display.cpp,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -d -r1.69 -r1.70
--- build_display.cpp	28 Jan 2005 16:33:08 -0000	1.69
+++ build_display.cpp	19 Feb 2005 14:02:09 -0000	1.70
@@ -24,19 +24,77 @@
 
 #include "common/stdafx.h"
 #include "common/system.h"
+
 #include "sword2/sword2.h"
 #include "sword2/console.h"
 #include "sword2/defs.h"
-#include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
-#include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
-void Sword2Engine::buildDisplay(void) {
+Screen::Screen(Sword2Engine *vm, int16 width, int16 height) {
+	_vm = vm;
+
+	_dirtyGrid = _buffer = NULL;
+
+	_vm->_system->initSize(width, height);
+
+	_screenWide = width;
+	_screenDeep = height;
+
+	_gridWide = width / CELLWIDE;
+	_gridDeep = height / CELLDEEP;
+
+	if ((width % CELLWIDE) || (height % CELLDEEP))
+		error("Bad cell size");
+
+	_dirtyGrid = (byte *) calloc(_gridWide, _gridDeep);
+	if (!_dirtyGrid)
+		error("Could not initialise dirty grid");
+
+	_buffer = (byte *) malloc(width * height);
+	if (!_buffer)
+		error("Could not initialise display");
+
+	for (int i = 0; i < ARRAYSIZE(_blockSurfaces); i++)
+		_blockSurfaces[i] = NULL;
+
+	_lightMask = NULL;
+	_needFullRedraw = false;
+
+	memset(&_thisScreen, 0, sizeof(_thisScreen));
+
+	_fps = 0;
+	_frameCount = 0;
+	_cycleTime = 0;
+
+	_lastPaletteRes = 0;
+
+	_scrollFraction = 16;
+
+	_largestLayerArea = 0;
+	_largestSpriteArea = 0;
+
+	strcpy(_largestLayerInfo,  "largest layer:  none registered");
+	strcpy(_largestSpriteInfo, "largest sprite: none registered");
+
+	_fadeStatus = RDFADE_NONE;
+	_renderAverageTime = 60;
+
+	_layer = 0;
+}
+
+Screen::~Screen() {
+	free(_buffer);
+	free(_dirtyGrid);
+	closeBackgroundLayer();
+	free(_lightMask);
+}
+
+void Screen::buildDisplay() {
 	if (_thisScreen.new_palette) {
 		// start the layer palette fading up
 		startNewPalette();
@@ -52,11 +110,11 @@
 
 	// there is a valid screen to run
 
-	_graphics->setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
-	_graphics->animateMouse();
-	_graphics->startRenderCycle();
+	setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
+	_vm->_mouse->animateMouse();
+	startRenderCycle();
 
-	byte *file = _resman->openResource(_thisScreen.background_layer_id);
+	byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
 	MultiScreenHeader *screenLayerTable = (MultiScreenHeader *) (file + sizeof(StandardHeader));
 
 	// Render at least one frame, but if the screen is scrolling, and if
@@ -66,18 +124,18 @@
 	do {
 		// first background parallax + related anims
 		if (screenLayerTable->bg_parallax[0]) {
-			_graphics->renderParallax(fetchBackgroundParallaxLayer(file, 0), 0);
+			renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0);
 			drawBackPar0Frames();
 		}
 
 		// second background parallax + related anims
 		if (screenLayerTable->bg_parallax[1]) {
-			_graphics->renderParallax(fetchBackgroundParallaxLayer(file, 1), 1);
+			renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1);
 			drawBackPar1Frames();
 		}
 
 		// normal backround layer (just the one!)
-		_graphics->renderParallax(fetchBackgroundLayer(file), 2);
+		renderParallax(_vm->fetchBackgroundLayer(file), 2);
 
 		// sprites & layers
 		drawBackFrames();	// background sprites
@@ -87,32 +145,32 @@
 		// first foreground parallax + related anims
 
 		if (screenLayerTable->fg_parallax[0]) {
-			_graphics->renderParallax(fetchForegroundParallaxLayer(file, 0), 3);
+			renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3);
 			drawForePar0Frames();
 		}
 
 		// second foreground parallax + related anims
 
 		if (screenLayerTable->fg_parallax[1]) {
-			_graphics->renderParallax(fetchForegroundParallaxLayer(file, 1), 4);
+			renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4);
 			drawForePar1Frames();
 		}
 
-		_debugger->drawDebugGraphics();
-		_fontRenderer->printTextBlocs();
-		_graphics->processMenu();
+		_vm->_debugger->drawDebugGraphics();
+		_vm->_fontRenderer->printTextBlocs();
+		_vm->_mouse->processMenu();
 
-		_graphics->updateDisplay();
+		updateDisplay();
 
 		_frameCount++;
-		if (getMillis() > _cycleTime) {
+		if (_vm->getMillis() > _cycleTime) {
 			_fps = _frameCount;
 			_frameCount = 0;
-			_cycleTime = getMillis() + 1000;
+			_cycleTime = _vm->getMillis() + 1000;
 		}
-	} while (!_graphics->endRenderCycle());
+	} while (!endRenderCycle());
 
-	_resman->closeResource(_thisScreen.background_layer_id);
+	_vm->_resman->closeResource(_thisScreen.background_layer_id);
 }
 
 /**
@@ -122,31 +180,31 @@
  *             until the user clicks the mouse or presses a key.
  */
 
-void Sword2Engine::displayMsg(byte *text, int time) {
+void Screen::displayMsg(byte *text, int time) {
 	byte pal[256 * 4];
 	byte oldPal[256 * 4];
 
 	debug(2, "DisplayMsg: %s", text);
 	
-	if (_graphics->getFadeStatus() != RDFADE_BLACK) {
-		_graphics->fadeDown();
-		_graphics->waitForFade();
+	if (getFadeStatus() != RDFADE_BLACK) {
+		fadeDown();
+		waitForFade();
 	}
 
-	setMouse(0);
-	setLuggage(0);
+	_vm->_mouse->setMouse(0);
+	_vm->_mouse->setLuggage(0);
+	_vm->_mouse->closeMenuImmediately();
 
-	_graphics->closeMenuImmediately();
-	_graphics->clearScene();
+	clearScene();
 
-	byte *text_spr = _fontRenderer->makeTextSprite(text, 640, 187, _speechFontId);
+	byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);
 	FrameHeader *frame = (FrameHeader *) text_spr;
 
 	SpriteInfo spriteInfo;
 
-	spriteInfo.x = _graphics->_screenWide / 2 - frame->width / 2;
+	spriteInfo.x = _screenWide / 2 - frame->width / 2;
 	if (!time)
-		spriteInfo.y = _graphics->_screenDeep / 2 - frame->height / 2 - RDMENU_MENUDEEP;
+		spriteInfo.y = _screenDeep / 2 - frame->height / 2 - RDMENU_MENUDEEP;
 	else
 		spriteInfo.y = 400 - frame->height;
 	spriteInfo.w = frame->width;
@@ -159,65 +217,65 @@
 	spriteInfo.data = text_spr + sizeof(FrameHeader);
 	spriteInfo.colourTable = 0;
 
-	uint32 rv = _graphics->drawSprite(&spriteInfo);
+	uint32 rv = drawSprite(&spriteInfo);
 	if (rv)
 		error("Driver Error %.8x (in DisplayMsg)", rv);
 
-	memcpy(oldPal, _graphics->_palette, sizeof(oldPal));
+	memcpy(oldPal, _palette, sizeof(oldPal));
 	memset(pal, 0, sizeof(pal));
 
 	pal[187 * 4 + 0] = 255;
 	pal[187 * 4 + 1] = 255;
 	pal[187 * 4 + 2] = 255;
 
-	_graphics->setPalette(0, 256, pal, RDPAL_FADE);
-	_graphics->fadeUp();
+	setPalette(0, 256, pal, RDPAL_FADE);
+	fadeUp();
 	free(text_spr);
-	_graphics->waitForFade();
+	waitForFade();
 
 	if (time > 0) {
-		uint32 targetTime = getMillis() + (time * 1000);
-		sleepUntil(targetTime);
+		uint32 targetTime = _vm->getMillis() + (time * 1000);
+		_vm->sleepUntil(targetTime);
 	} else {
-		while (!_quit) {
-			MouseEvent *me = mouseEvent();
+		while (!_vm->_quit) {
+			MouseEvent *me = _vm->mouseEvent();
 			if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
 				break;
 
-			if (keyboardEvent())
+			if (_vm->keyboardEvent())
 				break;
 
-			_graphics->updateDisplay();
-			_system->delayMillis(50);
+			updateDisplay();
+			_vm->_system->delayMillis(50);
 		}
 	}
 
-	_graphics->fadeDown();
-	_graphics->waitForFade();
-	_graphics->clearScene();
-	_graphics->setPalette(0, 256, oldPal, RDPAL_FADE);
-	_graphics->fadeUp();
+	fadeDown();
+	waitForFade();
+	clearScene();
+	setPalette(0, 256, oldPal, RDPAL_FADE);
+	fadeUp();
 }
 
-void Sword2Engine::drawBackPar0Frames(void) {
+void Screen::drawBackPar0Frames() {
 	// frame attached to 1st background parallax
 	for (uint i = 0; i < _curBgp0; i++)
 		processImage(&_bgp0List[i]);
 }
 
-void Sword2Engine::drawBackPar1Frames(void) {
+void Screen::drawBackPar1Frames() {
 	// frame attached to 2nd background parallax
 	for (uint i = 0; i < _curBgp1; i++)
 		processImage(&_bgp1List[i]);
 }
 
-void Sword2Engine::drawBackFrames(void) {
+void Screen::drawBackFrames() {
 	// background sprite, fixed to main background
 	for (uint i = 0; i < _curBack; i++)
 		processImage(&_backList[i]);
 }
 
-void Sword2Engine::drawSortFrames(byte *file) {
+void Screen::drawSortFrames(byte *file) {
 	uint i, j;
 
 	// Sort the sort list. Used to be a separate function, but it was only
@@ -248,26 +306,26 @@
 	}
 }
 
-void Sword2Engine::drawForeFrames(void) {
+void Screen::drawForeFrames() {
 	// foreground sprite, fixed to main background
 	for (uint i = 0; i < _curFore; i++)
 		processImage(&_foreList[i]);
 }
 
-void Sword2Engine::drawForePar0Frames(void) {
+void Screen::drawForePar0Frames() {
 	// frame attached to 1st foreground parallax
 	for (uint i = 0; i < _curFgp0; i++)
 		processImage(&_fgp0List[i]);
 }
 
-void Sword2Engine::drawForePar1Frames(void) {
+void Screen::drawForePar1Frames() {
 	// frame attached to 2nd foreground parallax
 	for (uint i = 0; i < _curFgp1; i++)
 		processImage(&_fgp1List[i]);
 }
 
-void Sword2Engine::processLayer(byte *file, uint32 layer_number) {
-	LayerHeader *layer_head = fetchLayerHeader(file, layer_number);
+void Screen::processLayer(byte *file, uint32 layer_number) {
+	LayerHeader *layer_head = _vm->fetchLayerHeader(file, layer_number);
 
  	SpriteInfo spriteInfo;
 
@@ -293,22 +351,22 @@
 		_largestLayerArea = current_layer_area;
 		sprintf(_largestLayerInfo,
 			"largest layer:  %s layer(%d) is %dx%d",
-			fetchObjectName(_thisScreen.background_layer_id, buf),
+			_vm->fetchObjectName(_thisScreen.background_layer_id, buf),
 			layer_number, layer_head->width, layer_head->height);
 	}
 
-	uint32 rv = _graphics->drawSprite(&spriteInfo);
+	uint32 rv = drawSprite(&spriteInfo);
 	if (rv)
 		error("Driver Error %.8x in processLayer(%d)", rv, layer_number);
 }
 
-void Sword2Engine::processImage(BuildUnit *build_unit) {
-	byte *file = _resman->openResource(build_unit->anim_resource);
+void Screen::processImage(BuildUnit *build_unit) {
+	byte *file = _vm->_resman->openResource(build_unit->anim_resource);
 	byte *colTablePtr = NULL;
 
-	AnimHeader *anim_head = fetchAnimHeader(file);
-	CdtEntry *cdt_entry = fetchCdtEntry(file, build_unit->anim_pc);
-	FrameHeader *frame_head = fetchFrameHeader(file, build_unit->anim_pc);
+	AnimHeader *anim_head = _vm->fetchAnimHeader(file);
+	CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, build_unit->anim_pc);
+	FrameHeader *frame_head = _vm->fetchFrameHeader(file, build_unit->anim_pc);
 
 	// so that 0-colour is transparent
 	uint32 spriteType = RDSPR_TRANS;
@@ -379,7 +437,7 @@
 		_largestSpriteArea = current_sprite_area;
 		sprintf(_largestSpriteInfo,
 			"largest sprite: %s frame(%d) is %dx%d",
-			fetchObjectName(build_unit->anim_resource, buf),
+			_vm->fetchObjectName(build_unit->anim_resource, buf),
 			build_unit->anim_pc,
 			frame_head->width,
 			frame_head->height);
@@ -401,26 +459,27 @@
 			spriteInfo.y = 1;
 
 		// create box to surround sprite - just outside sprite box
-		_debugger->_rectX1 = spriteInfo.x - 1;
-		_debugger->_rectY1 = spriteInfo.y - 1;
-		_debugger->_rectX2 = spriteInfo.x + spriteInfo.scaledWidth;
-		_debugger->_rectY2 = spriteInfo.y + spriteInfo.scaledHeight;
+		_vm->_debugger->_rectX1 = spriteInfo.x - 1;
+		_vm->_debugger->_rectY1 = spriteInfo.y - 1;
+		_vm->_debugger->_rectX2 = spriteInfo.x + spriteInfo.scaledWidth;
+		_vm->_debugger->_rectY2 = spriteInfo.y + spriteInfo.scaledHeight;
 	}
 
-	uint32 rv = _graphics->drawSprite(&spriteInfo);
+	uint32 rv = drawSprite(&spriteInfo);
 	if (rv) {
 		byte buf[NAME_LEN];
 
 		error("Driver Error %.8x with sprite %s (%d) in processImage",
-			rv, fetchObjectName(build_unit->anim_resource, buf),
+			rv,
+			_vm->fetchObjectName(build_unit->anim_resource, buf),
 			build_unit->anim_resource);
 	}
 
 	// release the anim resource
-	_resman->closeResource(build_unit->anim_resource);
+	_vm->_resman->closeResource(build_unit->anim_resource);
 }
 
-void Sword2Engine::resetRenderLists(void) {
+void Screen::resetRenderLists() {
 	// reset the sort lists - do this before a logic loop
 	// takes into account the fact that the start of the list is pre-built
 	// with the special sortable layers
@@ -441,28 +500,22 @@
 	}
 }
 
-void Sword2Engine::registerFrame(int32 *params, BuildUnit *build_unit) {
-	// params: 0 pointer to mouse structure or NULL for no write to mouse
-	//           list (non-zero means write sprite-shape to mouse list)
-	//         1 pointer to graphic structure
-	//         2 pointer to mega structure
-
-	ObjectGraphic *ob_graph = (ObjectGraphic *) _memory->decodePtr(params[1]);
+void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega, BuildUnit *build_unit) {
 	assert(ob_graph->anim_resource);
 
-	byte *file = _resman->openResource(ob_graph->anim_resource);
+	byte *file = _vm->_resman->openResource(ob_graph->anim_resource);
 
-	AnimHeader *anim_head = fetchAnimHeader(file);
-	CdtEntry *cdt_entry = fetchCdtEntry(file, ob_graph->anim_pc);
-	FrameHeader *frame_head = fetchFrameHeader(file, ob_graph->anim_pc);
+	AnimHeader *anim_head = _vm->fetchAnimHeader(file);
+	CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, ob_graph->anim_pc);
+	FrameHeader *frame_head = _vm->fetchFrameHeader(file, ob_graph->anim_pc);
 
 	// update player graphic details for on-screen debug info
 	if (Logic::_scriptVars[ID] == CUR_PLAYER_ID) {
-		_debugger->_playerGraphic.type = ob_graph->type;
-		_debugger->_playerGraphic.anim_resource = ob_graph->anim_resource;
+		_vm->_debugger->_playerGraphic.type = ob_graph->type;
+		_vm->_debugger->_playerGraphic.anim_resource = ob_graph->anim_resource;
 		// counting 1st frame as 'frame 1'
-		_debugger->_playerGraphic.anim_pc = ob_graph->anim_pc + 1;
-		_debugger->_playerGraphicNoFrames = anim_head->noAnimFrames;
+		_vm->_debugger->_playerGraphic.anim_pc = ob_graph->anim_pc + 1;
+		_vm->_debugger->_playerGraphicNoFrames = anim_head->noAnimFrames;
 	}
 
 	// fill in the BuildUnit structure for this frame
@@ -482,9 +535,7 @@
 	int scale = 0;
 
 	if (cdt_entry->frameType & FRAME_OFFSET) {
-		ObjectMega *ob_mega = (ObjectMega *) _memory->decodePtr(params[2]);
-
-		// calc scale at which to print the sprite, based on feet
+		// Calc scale at which to print the sprite, based on feet
 		// y-coord & scaling constants (NB. 'scale' is actually
 		// 256 * true_scale, to maintain accuracy)
 
@@ -519,184 +570,58 @@
 	// calc the bottom y-coord for sorting purposes
 	build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1;
 
-	if (params[0]) {
+	if (ob_mouse) {
 		// passed a mouse structure, so add to the _mouseList
-		ObjectMouse *ob_mouse = (ObjectMouse *) _memory->decodePtr(params[0]);
-
-		if (ob_mouse->pointer) {
-			assert(_curMouse < TOTAL_mouse_list);
-
-			_mouseList[_curMouse].x1 = build_unit->x;
-			_mouseList[_curMouse].y1 = build_unit->y;
-			_mouseList[_curMouse].x2 = build_unit->x + build_unit->scaled_width;
-			_mouseList[_curMouse].y2 = build_unit->y + build_unit->scaled_height;
-
- 			_mouseList[_curMouse].priority = ob_mouse->priority;
-			_mouseList[_curMouse].pointer = ob_mouse->pointer;
-
-			// check if pointer text field is set due to previous
-			// object using this slot (ie. not correct for this
-			// one)
-
-			// if 'pointer_text' field is set, but the 'id' field
-			// isn't same is current id then we don't want this
-			// "left over" pointer text
-
-			if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
-				_mouseList[_curMouse].pointer_text = 0;
-
-			_mouseList[_curMouse].id = Logic::_scriptVars[ID];
-			// not using sprite as detection mask
-			_mouseList[_curMouse].anim_resource = 0;
-			_mouseList[_curMouse].anim_pc = 0;
+		_vm->_mouse->registerMouse(ob_mouse, build_unit);
 
-			_curMouse++;
-		}
 	}
 
-	_resman->closeResource(ob_graph->anim_resource);
+	_vm->_resman->closeResource(ob_graph->anim_resource);
 }
 
-int32 Sword2Engine::registerFrame(int32 *params) {
-	ObjectGraphic *ob_graph = (ObjectGraphic *) _memory->decodePtr(params[1]);
-
+void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega) {
 	// check low word for sprite type
 	switch (ob_graph->type & 0x0000ffff) {
 	case BGP0_SPRITE:
 		assert(_curBgp0 < MAX_bgp0_sprites);
-		registerFrame(params, &_bgp0List[_curBgp0]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]);
 		_curBgp0++;
 		break;
 	case BGP1_SPRITE:
 		assert(_curBgp1 < MAX_bgp1_sprites);
-		registerFrame(params, &_bgp1List[_curBgp1]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp1List[_curBgp1]);
 		_curBgp1++;
 		break;
 	case BACK_SPRITE:
 		assert(_curBack < MAX_back_sprites);
-		registerFrame(params, &_backList[_curBack]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_backList[_curBack]);
 		_curBack++;
 		break;
 	case SORT_SPRITE:
 		assert(_curSort < MAX_sort_sprites);
 		_sortOrder[_curSort] = _curSort;
-		registerFrame(params, &_sortList[_curSort]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_sortList[_curSort]);
 		_curSort++;
 		break;
 	case FORE_SPRITE:
 		assert(_curFore < MAX_fore_sprites);
-		registerFrame(params, &_foreList[_curFore]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_foreList[_curFore]);
 		_curFore++;
 		break;
 	case FGP0_SPRITE:
 		assert(_curFgp0 < MAX_fgp0_sprites);
-		registerFrame(params, &_fgp0List[_curFgp0]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp0List[_curFgp0]);
 		_curFgp0++;
 		break;
 	case FGP1_SPRITE:
 		assert(_curFgp1 < MAX_fgp1_sprites);
-		registerFrame(params, &_fgp1List[_curFgp1]);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp1List[_curFgp1]);
 		_curFgp1++;
 		break;
 	default:
 		// NO_SPRITE no registering!
 		break;
 	}
-
-	return IR_CONT;
-}
-
-/**
- * Start layer palette fading up
- */
-
-void Sword2Engine::startNewPalette(void) {
-	// if the screen is still fading down then wait for black - could
-	// happen when everythings cached into a large memory model
-	_graphics->waitForFade();
-
-	byte *screenFile = _resman->openResource(_thisScreen.background_layer_id);
-
-	_graphics->updatePaletteMatchTable((byte *) fetchPaletteMatchTable(screenFile));
-	_graphics->setPalette(0, 256, fetchPalette(screenFile), RDPAL_FADE);
-
-	// indicating that it's a screen palette
-	_lastPaletteRes = 0;
-
-  	_resman->closeResource(_thisScreen.background_layer_id);
-	_graphics->fadeUp();
- 	_thisScreen.new_palette = 0;
-}
-
-void Sword2Engine::setFullPalette(int32 palRes) {
-	// fudge for hut interior
-	// - unpausing should restore last palette as normal (could be screen
-	// palette or 'dark_palette_13')
-	// - but restoring the screen palette after 'dark_palette_13' should
-	// now work properly too!
-
-	// "Hut interior" refers to the watchman's hut in Marseille, and this
-	// is apparently needed for the palette to be restored properly when
-	// you turn the light off. (I didn't even notice the light switch!)
-
-	if (Logic::_scriptVars[LOCATION] == 13) {
-		// unpausing
-		if (palRes == -1) {
-			// restore whatever palette was last set (screen
-			// palette or 'dark_palette_13')
-			palRes = _lastPaletteRes;
-		}
-	} else {
-		// check if we're just restoring the current screen palette
-		// because we might actually need to use a separate palette
-		// file anyway eg. for pausing & unpausing during the eclipse
-
-		// unpausing (fudged for location 13)
- 		if (palRes == -1) {
-			// we really meant '0'
-			palRes = 0;
-		}
-
-		if (palRes == 0 && _lastPaletteRes)
-			palRes = _lastPaletteRes;
-	}
-
-	// If non-zero, set palette to this separate palette file. Otherwise,
-	// set palette to current screen palette.
-
-	byte *file;
-
-	if (palRes) {
-		file = _resman->openResource(palRes);
-
-		StandardHeader *head = (StandardHeader *) file;
-		assert(head->fileType == PALETTE_FILE);
-
-		file += sizeof(StandardHeader);
-
-		// always set colour 0 to black because most background screen
-		// palettes have a bright colour 0 although it should come out
-		// as black in the game!
-
-		file[0] = 0;
-		file[1] = 0;
-		file[2] = 0;
-		file[3] = 0;
-
-		_graphics->setPalette(0, 256, file, RDPAL_INSTANT);
-	  	_resman->closeResource(palRes);
-	} else {
-		if (_thisScreen.background_layer_id) {
-			file = _resman->openResource(_thisScreen.background_layer_id);
-			_graphics->updatePaletteMatchTable(fetchPaletteMatchTable(file));
-			_graphics->setPalette(0, 256, fetchPalette(file), RDPAL_INSTANT);
-	  		_resman->closeResource(_thisScreen.background_layer_id);
-		} else
-			error("setFullPalette(0) called, but no current screen available!");
-	}
-
-	if (palRes != CONTROL_PANEL_PALETTE)
-		_lastPaletteRes = palRes;
 }
 
 } // End of namespace Sword2

Index: build_display.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/build_display.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- build_display.h	17 Jan 2005 10:57:10 -0000	1.14
+++ build_display.h	19 Feb 2005 14:02:10 -0000	1.15
@@ -21,6 +21,8 @@
 #ifndef	_BUILD_DISPLAY
 #define	_BUILD_DISPLAY
 
+#include "common/rect.h"
+
 #define MAX_bgp0_sprites 6
 #define MAX_bgp1_sprites 6
 #define MAX_back_sprites 30
@@ -29,7 +31,341 @@
 #define MAX_fgp0_sprites 6
 #define MAX_fgp1_sprites 6
 
+#define PALTABLESIZE     (64 * 64 * 64)
+
+#define BLOCKWIDTH       64
+#define BLOCKHEIGHT      64
+#define MAXLAYERS        5
+
+// Maximum scaled size of a sprite
+#define SCALE_MAXWIDTH   512
+#define SCALE_MAXHEIGHT  512
+
+// Dirty grid cell size
+#define CELLWIDE         10
+#define CELLDEEP         20
+
 namespace Sword2 {
+
+struct ObjectMouse;
+struct ObjectGraphic;
+struct ObjectMega;
+
+// Structure filled out by each object to register its graphic printing
+// requrements
+
+struct BuildUnit {
+	int16 x;
+	int16 y;
+	uint16 scaled_width;
+	uint16 scaled_height;
+	int16 sort_y;
+	uint32 anim_resource;
+	uint16 anim_pc;
+
+	// Denotes a scaling sprite at print time - and holds the scaling value
+	// for the shrink routine
+
+	uint16 scale;
+
+	// Non-zero means this item is a layer - retrieve from background layer
+	// and send to special renderer
+
+	uint16 layer_number;
+
+	// True means we want this frame to be affected by the shading mask
+
+	bool shadingFlag;
+};
+
+enum {
+	MOUSE_normal		= 0,	// normal in game
+	MOUSE_menu		= 1,	// menu chooser
+	MOUSE_drag		= 2,	// dragging luggage
+	MOUSE_system_menu	= 3,	// system menu chooser
+	MOUSE_holding		= 4	// special
+};
+
+struct ScreenInfo {
+	uint16 scroll_offset_x;		// Position x
+	uint16 scroll_offset_y;		// Position y
+	uint16 max_scroll_offset_x;	// Calc'ed in fnInitBackground
+	uint16 max_scroll_offset_y;
+	int16 player_feet_x;		// Feet coordinates to use - cant just
+	int16 player_feet_y;		// fetch the player compact anymore
+	int16 feet_x;			// Special offset-to-player position -
+	int16 feet_y;			// tweek as desired - always set in
+					// screen manager object startup
+	uint16 screen_wide;		// Size of background layer - hence
+	uint16 screen_deep;		// size of back buffer itself (Paul
+					// actually malloc's it)
+	uint32 background_layer_id;	// Id of the normal background layer
+					// from the header of the main
+					// background layer
+	uint16 number_of_layers;
+	uint8 new_palette;		// Set to non zero to start the
+					// palette held within layer file
+					// fading up after a build_display
+	uint8 scroll_flag;		// Scroll mode 0 off 1 on
+	bool mask_flag;			// Using shading mask
+};
+
+// The SpriteInfo structure is used to tell the driver96 code what attributes
+// are linked to a sprite for drawing.  These include position, scaling and
+// compression.
+
+struct SpriteInfo {
+	int16 x;		// coords for top-left of sprite
+	int16 y;
+	uint16 w;		// dimensions of sprite (before scaling)
+	uint16 h;
+	uint16 scale;		// scale at which to draw, given in 256ths ['0' or '256' MEANS DON'T SCALE]
+	uint16 scaledWidth;	// new dimensions (we calc these for the mouse area, so may as well pass to you to save time)
+	uint16 scaledHeight;	//
+	uint16 type;		// mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc
+	uint16 blend;		// holds the blending values.
+	byte *data;		// pointer to the sprite data
+	byte *colourTable;	// pointer to 16-byte colour table, only applicable to 16-col compression type
+};
+
+struct BlockSurface {
+	byte data[BLOCKWIDTH * BLOCKHEIGHT];
+	bool transparent;
+};
+
+class Screen {
+private:
+	Sword2Engine *_vm;
+
+	// _thisScreen describes the current back buffer and its in-game scroll
+	// positions, etc.
+
+	ScreenInfo _thisScreen;
+
+	int32 _renderCaps;
+	int8 _renderLevel;
+
+	byte *_buffer;
+	byte *_lightMask;
+
+	// Game screen metrics
+	int16 _screenWide;
+	int16 _screenDeep;
+
+	bool _needFullRedraw;
+
+	// Scroll variables.  _scrollX and _scrollY hold the current scroll
+	// position, and _scrollXTarget and _scrollYTarget are the target
+	// position for the end of the game cycle.
+
+	int16 _scrollX;
+	int16 _scrollY;
+
+	int16 _scrollXTarget;
+	int16 _scrollYTarget;
+	int16 _scrollXOld;
+	int16 _scrollYOld;
+
+	int16 _parallaxScrollX;	// current x offset to link a sprite to the
+				// parallax layer
+	int16 _parallaxScrollY;	// current y offset to link a sprite to the
+				// parallax layer
+	int16 _locationWide;
+	int16 _locationDeep;
+
+	// Dirty grid handling
+	byte *_dirtyGrid;
+
+	uint16 _gridWide;
+	uint16 _gridDeep;
+
+	byte _palette[256 * 4];
+	byte _paletteMatch[PALTABLESIZE];
+
+	uint8 _fadeStatus;
+	int32 _fadeStartTime;
+	int32 _fadeTotalTime;
+
+	// 'frames per second' counting stuff
+	uint32 _fps;
+	uint32 _cycleTime;
+	uint32 _frameCount;
+
+	int32 _initialTime;
+	int32 _startTime;
+	int32 _totalTime;
+	int32 _renderAverageTime;
+	int32 _framesPerGameCycle;
+	bool _renderTooSlow;
+
+	void startNewPalette();
+
+	void resetRenderEngine();
+
+	void startRenderCycle();
+	bool endRenderCycle();
+
+	// Holds the order of the sort list, i.e. the list stays static and we
+	// sort this array.
+
+	uint16 _sortOrder[MAX_sort_sprites];
+
+	BuildUnit _bgp0List[MAX_bgp0_sprites];
+	BuildUnit _bgp1List[MAX_bgp1_sprites];
+	BuildUnit _backList[MAX_back_sprites];
+	BuildUnit _sortList[MAX_sort_sprites];
+	BuildUnit _foreList[MAX_fore_sprites];
+	BuildUnit _fgp0List[MAX_fgp0_sprites];
+	BuildUnit _fgp1List[MAX_fgp1_sprites];
+
+	uint32 _curBgp0;
+	uint32 _curBgp1;
+	uint32 _curBack;
+	uint32 _curSort;
+	uint32 _curFore;
+	uint32 _curFgp0;
+	uint32 _curFgp1;
+
+	void drawBackPar0Frames();
+	void drawBackPar1Frames();
+	void drawBackFrames();
+	void drawSortFrames(byte *file);
+	void drawForeFrames();
+	void drawForePar0Frames();
+	void drawForePar1Frames();
+
+	void processLayer(byte *file, uint32 layer_number);
+	void processImage(BuildUnit *build_unit);
+
+	uint8 _scrollFraction;
+
+	// Last palette used - so that we can restore the correct one after a
+	// pause (which dims the screen) and it's not always the main screen
+	// palette that we want, eg. during the eclipse
+
+	// This flag gets set in startNewPalette() and setFullPalette()
+
+	uint32 _lastPaletteRes;
+
+	// Debugging stuff
+	uint32 _largestLayerArea;
+	uint32 _largestSpriteArea;
+	char _largestLayerInfo[128];
+	char _largestSpriteInfo[128];
+
+	void registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega, BuildUnit *build_unit);
+
+	void mirrorSprite(byte *dst, byte *src, int16 w, int16 h);
+	int32 decompressRLE256(byte *dst, byte *src, int32 decompSize);
+	void unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable);
+	int32 decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable);
+	void renderParallax(Parallax *p, int16 layer);
+
+	void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1);
+
+	uint8 _xBlocks[MAXLAYERS];
+	uint8 _yBlocks[MAXLAYERS];
+
+	// An array of sub-blocks, one for each of the parallax layers.
+
+	BlockSurface **_blockSurfaces[MAXLAYERS];
+
+	uint16 _xScale[SCALE_MAXWIDTH];
+	uint16 _yScale[SCALE_MAXHEIGHT];
+
+	void blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect);
+
+	uint16 _layer;
+
+public:
+	Screen(Sword2Engine *vm, int16 width, int16 height);
+	~Screen();
+
+	int8 getRenderLevel();
+	void setRenderLevel(int8 level);
+
+	byte *getScreen() { return _buffer; }
+	byte *getPalette() { return _palette; }
+	ScreenInfo *getScreenInfo() { return &_thisScreen; }
+
+	int16 getScreenWide() { return _screenWide; }
+	int16 getScreenDeep() { return _screenDeep; }
+
+	uint32 getCurBgp0() { return _curBgp0; }
+	uint32 getCurBgp1() { return _curBgp1; }
+	uint32 getCurBack() { return _curBack; }
+	uint32 getCurSort() { return _curSort; }
+	uint32 getCurFore() { return _curFore; }
+	uint32 getCurFgp0() { return _curFgp0; }
+	uint32 getCurFgp1() { return _curFgp1; }
+
+	uint32 getFps() { return _fps; }
+
+	uint32 getLargestLayerArea() { return _largestLayerArea; }
+	uint32 getLargestSpriteArea() { return _largestSpriteArea; }
+	char *getLargestLayerInfo() { return _largestLayerInfo; }
+	char *getLargestSpriteInfo() { return _largestSpriteInfo; }
+
+	void setNeedFullRedraw();
+
+	void clearScene();
+
+	void resetRenderLists();
+
+	void setLocationMetrics(uint16 w, uint16 h);
+	int32 initialiseBackgroundLayer(Parallax *p);
+	void closeBackgroundLayer();
+
+	void initialiseRenderCycle();
+
+	void initBackground(int32 res, int32 new_palette);
+	void registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega);
+
+	void setScrollFraction(uint8 f) { _scrollFraction = f; }
+	void setScrollTarget(int16 x, int16 y);
+	void setScrolling();
+
+	void setFullPalette(int32 palRes);
+	void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow);
+	uint8 quickMatch(uint8 r, uint8 g, uint8 b);
+	int32 fadeUp(float time = 0.75);
+	int32 fadeDown(float time = 0.75);
+	uint8 getFadeStatus();
+	void dimPalette();
+	void waitForFade();
+	void fadeServer();
+
+	void updateDisplay(bool redrawScene = true);
+
+	void displayMsg(byte *text, int time);
+
+	int32 createSurface(SpriteInfo *s, byte **surface);
+	void drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect = NULL);
+	void deleteSurface(byte *surface);
+	int32 drawSprite(SpriteInfo *s);
+
+	void scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth,
+		uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
+		uint16 srcHeight);
+	void scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth,
+		uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
+		uint16 srcHeight, byte *backbuf);
+
+	void updateRect(Common::Rect *r);
+
+	int32 openLightMask(SpriteInfo *s);
+	int32 closeLightMask();
+
+	void buildDisplay();
+
+	void plotPoint(int16 x, int16 y, uint8 colour);
+	void drawLine(int16 x1, int16 y1, int16 x2, int16 y2, uint8 colour);
+#ifdef BACKEND_8BIT
+	void plotYUV(byte *lut, int width, int height, byte *const *dat);
+#endif
+
+};
+
 } // End of namespace Sword2
 
 #endif

Index: console.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/console.cpp,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- console.cpp	28 Jan 2005 16:33:08 -0000	1.52
+++ console.cpp	19 Feb 2005 14:02:10 -0000	1.53
@@ -25,9 +25,9 @@
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
 
 #include "common/debugger.cpp"
 
@@ -144,9 +144,9 @@
 		_vm->_sound->unpauseMusic();
 	}
 
-	if (_vm->_graphics) {
+	if (_vm->_mouse) {
 		// Restore old mouse cursor
-		_vm->_graphics->drawMouse();
+		_vm->_mouse->drawMouse();
 	}
 }
 
@@ -219,7 +219,7 @@
 	}
 
 	_vm->conStart(atoi(argv[1]));
-	_vm->_graphics->setPalette(187, 1, pal, RDPAL_INSTANT);
+	_vm->_screen->setPalette(187, 1, pal, RDPAL_INSTANT);
 	return true;
 }
 

Index: controls.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/controls.cpp,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -d -r1.84 -r1.85
--- controls.cpp	8 Feb 2005 08:32:48 -0000	1.84
+++ controls.cpp	19 Feb 2005 14:02:10 -0000	1.85
@@ -22,14 +22,15 @@
 #include "common/rect.h"
 #include "common/config-manager.h"
 #include "common/system.h"
+
 #include "sword2/sword2.h"
 #include "sword2/controls.h"
 #include "sword2/defs.h"
 #include "sword2/logic.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
 #include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
 
 #define	MAX_STRING_LEN		64	// 20 was too low; better to be safe ;)
 #define CHARACTER_OVERLAP	 2	// overlap characters by 3 pixels
@@ -176,7 +177,7 @@
 		sprite.data = (byte *) (head + 1);
 		sprite.w = head->width;
 		sprite.h = head->height;
-		_gui->_vm->_graphics->createSurface(&sprite, &_glyph[i]._data);
+		_gui->_vm->_screen->createSurface(&sprite, &_glyph[i]._data);
 		_glyph[i]._width = head->width;
 		_glyph[i]._height = head->height;
 	}
@@ -186,7 +187,7 @@
 
 FontRendererGui::~FontRendererGui() {
 	for (int i = 0; i < SIZE_OF_CHAR_SET; i++)
-		_gui->_vm->_graphics->deleteSurface(_glyph[i]._data);
+		_gui->_vm->_screen->deleteSurface(_glyph[i]._data);
 }
 
 void FontRendererGui::fetchText(uint32 textId, byte *buf) {
@@ -255,7 +256,7 @@
 			sprite.w = getCharWidth(text[i]);
 			sprite.h = getCharHeight(text[i]);
 
-			_gui->_vm->_graphics->drawSurface(&sprite, _glyph[text[i] - 32]._data);
+			_gui->_vm->_screen->drawSurface(&sprite, _glyph[text[i] - 32]._data);
 
 			sprite.x += (getCharWidth(text[i]) - CHARACTER_OVERLAP);
 		}
@@ -275,14 +276,14 @@
 
 Dialog::Dialog(Gui *gui)
 	: _numWidgets(0), _finish(false), _result(0), _gui(gui) {
-	_gui->_vm->setFullPalette(CONTROL_PANEL_PALETTE);
-	_gui->_vm->_graphics->clearScene();
+	_gui->_vm->_screen->setFullPalette(CONTROL_PANEL_PALETTE);
+	_gui->_vm->_screen->clearScene();
 
 	// HACK: Since the dialogs don't do normal scene updates we need to
 	// trigger a full redraw manually.
 
-	_gui->_vm->_graphics->setNeedFullRedraw();
-	_gui->_vm->_graphics->updateDisplay();
+	_gui->_vm->_screen->setNeedFullRedraw();
+	_gui->_vm->_screen->updateDisplay();
 }
 
 Dialog::~Dialog() {
@@ -296,7 +297,7 @@
 }
 
 void Dialog::paint() {
-	_gui->_vm->_graphics->clearScene();
+	_gui->_vm->_screen->clearScene();
 	for (int i = 0; i < _numWidgets; i++)
 		_widgets[i]->paint();
 }
@@ -313,16 +314,19 @@
 
 	paint();
 
-	int16 oldMouseX = -1;
-	int16 oldMouseY = -1;
+	int oldMouseX = -1;
+	int oldMouseY = -1;
 
 	while (!_finish) {
 		// So that the menu icons will reach their full size
-		_gui->_vm->_graphics->processMenu();
-		_gui->_vm->_graphics->updateDisplay(false);
+		_gui->_vm->_mouse->processMenu();
+		_gui->_vm->_screen->updateDisplay(false);
 
-		int16 newMouseX = _gui->_vm->_mouseX;
-		int16 newMouseY = _gui->_vm->_mouseY + 40;
+		int newMouseX, newMouseY;
+
+		_gui->_vm->_mouse->getPos(newMouseX, newMouseY);
+
+		newMouseY += 40;
 
 		MouseEvent *me = _gui->_vm->mouseEvent();
 		KeyboardEvent *ke = _gui->_vm->keyboardEvent();
@@ -429,7 +433,7 @@
 Widget::~Widget() {
 	for (int i = 0; i < _numStates; i++) {
 		if (_surfaces[i]._original)
-			_parent->_gui->_vm->_graphics->deleteSurface(_surfaces[i]._surface);
+			_parent->_gui->_vm->_screen->deleteSurface(_surfaces[i]._surface);
 	}
 	free(_sprites);
 	free(_surfaces);
@@ -484,7 +488,7 @@
 	// Points to just after frame header, ie. start of sprite data
 	_sprites[state].data = (byte *) (frame_head + 1);
 
-	_parent->_gui->_vm->_graphics->createSurface(&_sprites[state], &_surfaces[state]._surface);
+	_parent->_gui->_vm->_screen->createSurface(&_sprites[state], &_surfaces[state]._surface);
 	_surfaces[state]._original = true;
 
 	// Release the anim resource
@@ -537,7 +541,7 @@
 }
 
 void Widget::paint(Common::Rect *clipRect) {
-	_parent->_gui->_vm->_graphics->drawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect);
+	_parent->_gui->_vm->_screen->drawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect);
 }
 
 /**
@@ -940,7 +944,7 @@
 
 		_objectLabelsSwitch->setValue(_gui->_pointerTextSelected);
 		_subtitlesSwitch->setValue(_gui->_subtitles);
-		_reverseStereoSwitch->setValue(_gui->_stereoReversed);
+		_reverseStereoSwitch->setValue(_gui->_vm->_sound->isReverseStereo());
 		_musicSwitch->setValue(!_gui->_vm->_sound->isMusicMute());
 		_speechSwitch->setValue(!_gui->_vm->_sound->isSpeechMute());
 		_fxSwitch->setValue(!_gui->_vm->_sound->isFxMute());
@@ -949,8 +953,8 @@
 		_speechSlider->setValue(_mixer->getVolumeForSoundType(SoundMixer::kSpeechAudioDataType));
 		_fxSlider->setValue(_mixer->getVolumeForSoundType(SoundMixer::kSFXAudioDataType));
 
-		_gfxSlider->setValue(_gui->_vm->_graphics->getRenderLevel());
-		_gfxPreview->setState(_gui->_vm->_graphics->getRenderLevel());
+		_gfxSlider->setValue(_gui->_vm->_screen->getRenderLevel());
+		_gfxPreview->setState(_gui->_vm->_screen->getRenderLevel());
 	}
 
 	~OptionsDialog() {
@@ -1020,12 +1024,12 @@
 		} else if (widget == _okButton) {
 			_gui->_subtitles = _subtitlesSwitch->getValue();
 			_gui->_pointerTextSelected = _objectLabelsSwitch->getValue();
-			_gui->_stereoReversed = _reverseStereoSwitch->getValue();
 
 			// Apply the changes
 			_gui->_vm->_sound->muteMusic(!_musicSwitch->getValue());
 			_gui->_vm->_sound->muteSpeech(!_speechSwitch->getValue());
 			_gui->_vm->_sound->muteFx(!_fxSwitch->getValue());
+			_gui->_vm->_sound->setReverseStereo(_reverseStereoSwitch->getValue());
 			_mixer->setVolumeForSoundType(SoundMixer::kMusicAudioDataType, _musicSlider->getValue());
 			_mixer->setVolumeForSoundType(SoundMixer::kSpeechAudioDataType, _speechSlider->getValue());
 			_mixer->setVolumeForSoundType(SoundMixer::kSFXAudioDataType, _fxSlider->getValue());
@@ -1449,7 +1453,7 @@
 					break;
 				}
 
-				_gui->_vm->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+				_gui->_vm->_screen->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
 				result = 0;
 			}
 		} else {
@@ -1470,18 +1474,18 @@
 					break;
 				}
 
-				_gui->_vm->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+				_gui->_vm->_screen->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
 				result = 0;
 			} else {
 				// Prime system with a game cycle
 
 				// Reset the graphic 'BuildUnit' list before a
 				// new logic list (see fnRegisterFrame)
-				_gui->_vm->resetRenderLists();
+				_gui->_vm->_screen->resetRenderLists();
 
 				// Reset the mouse hot-spot list (see
 				// fnRegisterMouse and fnRegisterFrame)
-				_gui->_vm->resetMouseList();
+				_gui->_vm->_mouse->resetMouseList();
 
 				if (_gui->_vm->_logic->processSession())
 					error("restore 1st cycle failed??");
@@ -1504,7 +1508,6 @@
 void Gui::readOptionSettings(void) {
 	_subtitles = ConfMan.getBool("subtitles");
 	_pointerTextSelected = ConfMan.getBool("object_labels");
-	_stereoReversed = ConfMan.getBool("reverse_stereo");
 
 	updateGraphicsLevel((uint8) ConfMan.getInt("gfx_details"));
 
@@ -1514,6 +1517,7 @@
 	_vm->_sound->muteMusic(ConfMan.getBool("music_mute"));
 	_vm->_sound->muteSpeech(ConfMan.getBool("speech_mute"));
 	_vm->_sound->muteFx(ConfMan.getBool("sfx_mute"));
+	_vm->_sound->setReverseStereo(ConfMan.getBool("reverse_stereo"));
 }
 
 void Gui::writeOptionSettings(void) {
@@ -1523,10 +1527,10 @@
 	ConfMan.set("music_mute", _vm->_sound->isMusicMute());
 	ConfMan.set("speech_mute", _vm->_sound->isSpeechMute());
 	ConfMan.set("sfx_mute", _vm->_sound->isFxMute());
-	ConfMan.set("gfx_details", _vm->_graphics->getRenderLevel());
+	ConfMan.set("gfx_details", _vm->_screen->getRenderLevel());
 	ConfMan.set("subtitles", _subtitles);
 	ConfMan.set("object_labels", _pointerTextSelected);
-	ConfMan.set("reverse_stereo", _stereoReversed);
+	ConfMan.set("reverse_stereo", _vm->_sound->isReverseStereo());
 
 	ConfMan.flushToDisk();
 }
@@ -1574,6 +1578,7 @@
 }
 
 void Gui::restartControl(void) {
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 	uint32 temp_demo_flag;
 
 	MiniDialog restartDialog(this, 149618693);
@@ -1581,7 +1586,7 @@
 	if (!restartDialog.run())
 		return;
 
-	_vm->_graphics->closeMenuImmediately();
+	_vm->_mouse->closeMenuImmediately();
 
 	// Restart the game. To do this, we must...
 
@@ -1613,25 +1618,25 @@
 
 	// Reset the graphic 'BuildUnit' list before a new logic list
 	// (see fnRegisterFrame)
-	_vm->resetRenderLists();
+	_vm->_screen->resetRenderLists();
 
 	// Reset the mouse hot-spot list (see fnRegisterMouse and
 	// fnRegisterFrame)
-	_vm->resetMouseList();
+	_vm->_mouse->resetMouseList();
 
-	_vm->_graphics->closeMenuImmediately();
+	_vm->_mouse->closeMenuImmediately();
 
 	// FOR THE DEMO - FORCE THE SCROLLING TO BE RESET!
 	// - this is taken from fnInitBackground
 	// switch on scrolling (2 means first time on screen)
-	_vm->_thisScreen.scroll_flag = 2;
+	screenInfo->scroll_flag = 2;
 
 	if (_vm->_logic->processSession())
 		error("restart 1st cycle failed??");
 
 	// So palette not restored immediately after control panel - we want
 	// to fade up instead!
-	_vm->_thisScreen.new_palette = 99;
+	screenInfo->new_palette = 99;
 }
 
 void Gui::optionControl(void) {
@@ -1647,7 +1652,7 @@
 	else if (newLevel > 3)
 		newLevel = 3;
 
-	_vm->_graphics->setRenderLevel(newLevel);
+	_vm->_screen->setRenderLevel(newLevel);
 
 	// update our global variable - which needs to be checked when dimming
 	// the palette in PauseGame() in sword2.cpp (since palette-matching

Index: controls.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/controls.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- controls.h	17 Jan 2005 10:57:10 -0000	1.16
+++ controls.h	19 Feb 2005 14:02:10 -0000	1.17
@@ -33,7 +33,6 @@
 	uint8 _currentGraphicsLevel;
 
 	bool _subtitles;
-	bool _stereoReversed;
 	bool _pointerTextSelected;
 
 	Gui(Sword2Engine *vm);

Index: debug.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/debug.cpp,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- debug.cpp	17 Jan 2005 10:57:10 -0000	1.47
+++ debug.cpp	19 Feb 2005 14:02:10 -0000	1.48
@@ -25,9 +25,9 @@
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
@@ -63,20 +63,24 @@
 	int32 showVarPos;
 	int32 varNo;
 
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
 	// clear the array of text block numbers for the debug text
 	clearDebugTextBlocks();
 
 	// mouse coords
-/*
 	// print mouse coords beside mouse-marker, if it's being displayed
-	if (displayMouseMarker) {
-		sprintf(buf, "%d,%d", mousex + _thisScreen.scroll_offset_x, mousey + _thisScreen.scroll_offset_y);
-		if (mousex>560)
-			makeDebugTextBlock(buf, mousex - 50, mousey - 15);
+	if (_displayMouseMarker) {
+		int mouseX, mouseY;
+
+		_vm->_mouse->getPos(mouseX, mouseY);
+
+		sprintf(buf, "%d,%d", mouseX + screenInfo->scroll_offset_x, mouseY + screenInfo->scroll_offset_y);
+		if (mouseX > 560)
+			makeDebugTextBlock(buf, mouseX - 50, mouseY - 15);
 		else
-			makeDebugTextBlock(buf, mousex + 5, mousey - 15);
+			makeDebugTextBlock(buf, mouseX + 5, mouseY - 15);
 	}
-*/
 
 	// mouse area coords
 
@@ -186,16 +190,22 @@
 
  		makeDebugTextBlock(buf, 0, 15);
 
-		if (_vm->_mouseTouching)
+		uint32 mouseTouching = _vm->_mouse->getMouseTouching();
+
+		int mouseX, mouseY;
+
+		_vm->_mouse->getPos(mouseX, mouseY);
+
+		if (mouseTouching)
 			sprintf(buf, "mouse %d,%d (id %d: %s)",
-				_vm->_mouseX + _vm->_thisScreen.scroll_offset_x,
-				_vm->_mouseY + _vm->_thisScreen.scroll_offset_y,
-				_vm->_mouseTouching,
-				_vm->fetchObjectName(_vm->_mouseTouching, name));
+				mouseX + screenInfo->scroll_offset_x,
+				mouseY + screenInfo->scroll_offset_y,
+				mouseTouching,
+				_vm->fetchObjectName(mouseTouching, name));
 		else
 			sprintf(buf, "mouse %d,%d (not touching)",
-				_vm->_mouseX + _vm->_thisScreen.scroll_offset_x,
-				_vm->_mouseY + _vm->_thisScreen.scroll_offset_y);
+				mouseX + screenInfo->scroll_offset_x,
+				mouseY + screenInfo->scroll_offset_y);
 
 		makeDebugTextBlock(buf, 0, 30);
 
@@ -204,23 +214,23 @@
 
 		if (_playerGraphic.anim_resource)
 			sprintf(buf, "player %d,%d %s (%d) #%d/%d",
-				_vm->_thisScreen.player_feet_x,
-				_vm->_thisScreen.player_feet_y,
+				screenInfo->player_feet_x,
+				screenInfo->player_feet_y,
 				_vm->fetchObjectName(_playerGraphic.anim_resource, name),
 				_playerGraphic.anim_resource,
 				_playerGraphic.anim_pc,
 				_playerGraphicNoFrames);
 		else
 			sprintf(buf, "player %d,%d --- %d",
-				_vm->_thisScreen.player_feet_x,
-				_vm->_thisScreen.player_feet_y,
+				screenInfo->player_feet_x,
+				screenInfo->player_feet_y,
 				_playerGraphic.anim_pc);
 
 		makeDebugTextBlock(buf, 0, 45);
 
  		// frames-per-second counter
 
-		sprintf(buf, "fps %d", _vm->_fps);
+		sprintf(buf, "fps %d", _vm->_screen->getFps());
 		makeDebugTextBlock(buf, 440, 0);
 
  		// location number
@@ -240,32 +250,32 @@
 
 		// sprite list usage
 
-		sprintf(buf, "bgp0: %d/%d", _vm->_curBgp0, MAX_bgp0_sprites);
+		sprintf(buf, "bgp0: %d/%d", _vm->_screen->getCurBgp0(), MAX_bgp0_sprites);
 		makeDebugTextBlock(buf, 560, 0);
 
-		sprintf(buf, "bgp1: %d/%d", _vm->_curBgp1, MAX_bgp1_sprites);
+		sprintf(buf, "bgp1: %d/%d", _vm->_screen->getCurBgp1(), MAX_bgp1_sprites);
 		makeDebugTextBlock(buf, 560, 15);
 
-		sprintf(buf, "back: %d/%d", _vm->_curBack, MAX_back_sprites);
+		sprintf(buf, "back: %d/%d", _vm->_screen->getCurBack(), MAX_back_sprites);
 		makeDebugTextBlock(buf, 560, 30);
 
-		sprintf(buf, "sort: %d/%d", _vm->_curSort, MAX_sort_sprites);
+		sprintf(buf, "sort: %d/%d", _vm->_screen->getCurSort(), MAX_sort_sprites);
 		makeDebugTextBlock(buf, 560, 45);
 
-		sprintf(buf, "fore: %d/%d", _vm->_curFore, MAX_fore_sprites);
+		sprintf(buf, "fore: %d/%d", _vm->_screen->getCurFore(), MAX_fore_sprites);
 		makeDebugTextBlock(buf, 560, 60);
 
-		sprintf(buf, "fgp0: %d/%d", _vm->_curFgp0, MAX_fgp0_sprites);
+		sprintf(buf, "fgp0: %d/%d", _vm->_screen->getCurFgp0(), MAX_fgp0_sprites);
 		makeDebugTextBlock(buf, 560, 75);
 
-		sprintf(buf, "fgp1: %d/%d", _vm->_curFgp1, MAX_fgp1_sprites);
+		sprintf(buf, "fgp1: %d/%d", _vm->_screen->getCurFgp1(), MAX_fgp1_sprites);
 		makeDebugTextBlock(buf, 560, 90);
 
 		// largest layer & sprite
 
 		// NB. Strings already constructed in Build_display.cpp
-		makeDebugTextBlock(_vm->_largestLayerInfo, 0, 60);
-		makeDebugTextBlock(_vm->_largestSpriteInfo, 0, 75);
+		makeDebugTextBlock(_vm->_screen->getLargestLayerInfo(), 0, 60);
+		makeDebugTextBlock(_vm->_screen->getLargestSpriteInfo(), 0, 75);
 
 		// "waiting for person" indicator - set form fnTheyDo and
 		// fnTheyDoWeWait
@@ -303,6 +313,7 @@
 }
 
 void Debugger::drawDebugGraphics(void) {
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 	// walk-grid
 
 	if (_displayWalkGrid)
@@ -311,12 +322,17 @@
 	// player feet coord marker
 
 	if (_displayPlayerMarker)
-		plotCrossHair(_vm->_thisScreen.player_feet_x, _vm->_thisScreen.player_feet_y, 215);
+		plotCrossHair(screenInfo->player_feet_x, screenInfo->player_feet_y, 215);
 
 	// mouse marker & coords
 
-	if (_displayMouseMarker)
-		plotCrossHair(_vm->_mouseX + _vm->_thisScreen.scroll_offset_x, _vm->_mouseY + _vm->_thisScreen.scroll_offset_y, 215);
+	if (_displayMouseMarker) {
+		int mouseX, mouseY;
+
+		_vm->_mouse->getPos(mouseX, mouseY);
+
+		plotCrossHair(mouseX + screenInfo->scroll_offset_x, mouseY + screenInfo->scroll_offset_y, 215);
+	}
 
    	// mouse area rectangle / sprite box rectangle when testing anims
 
@@ -332,29 +348,30 @@
 }
 
 void Debugger::plotCrossHair(int16 x, int16 y, uint8 pen) {
-	_vm->_graphics->plotPoint(x, y, pen);
+	_vm->_screen->plotPoint(x, y, pen);
 
-	_vm->_graphics->drawLine(x - 2, y, x - 5, y, pen);
-	_vm->_graphics->drawLine(x + 2, y, x + 5, y, pen);
+	_vm->_screen->drawLine(x - 2, y, x - 5, y, pen);
+	_vm->_screen->drawLine(x + 2, y, x + 5, y, pen);
 
-	_vm->_graphics->drawLine(x, y - 2, x, y - 5, pen);
-	_vm->_graphics->drawLine(x, y + 2, x, y + 5, pen);
+	_vm->_screen->drawLine(x, y - 2, x, y - 5, pen);
+	_vm->_screen->drawLine(x, y + 2, x, y + 5, pen);
 }
 
 void Debugger::drawRect(int16 x1, int16 y1, int16 x2, int16 y2, uint8 pen) {
-	_vm->_graphics->drawLine(x1, y1, x2, y1, pen);	// top edge
-	_vm->_graphics->drawLine(x1, y2, x2, y2, pen);	// bottom edge
-	_vm->_graphics->drawLine(x1, y1, x1, y2, pen);	// left edge
-	_vm->_graphics->drawLine(x2, y1, x2, y2, pen);	// right edge
+	_vm->_screen->drawLine(x1, y1, x2, y1, pen);	// top edge
+	_vm->_screen->drawLine(x1, y2, x2, y2, pen);	// bottom edge
+	_vm->_screen->drawLine(x1, y1, x1, y2, pen);	// left edge
+	_vm->_screen->drawLine(x2, y1, x2, y2, pen);	// right edge
 }
 
 void Debugger::printCurrentInfo(void) {
 	// prints general stuff about the screen, etc.
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
-	if (_vm->_thisScreen.background_layer_id) {
-		DebugPrintf("background layer id %d\n", _vm->_thisScreen.background_layer_id);
-		DebugPrintf("%d wide, %d high\n", _vm->_thisScreen.screen_wide, _vm->_thisScreen.screen_deep);
-		DebugPrintf("%d normal layers\n", _vm->_thisScreen.number_of_layers);
+	if (screenInfo->background_layer_id) {
+		DebugPrintf("background layer id %d\n", screenInfo->background_layer_id);
+		DebugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep);
+		DebugPrintf("%d normal layers\n", screenInfo->number_of_layers);
 
 		_vm->_logic->examineRunList();
 	} else

Index: debug.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/debug.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- debug.h	17 Jan 2005 10:57:10 -0000	1.14
+++ debug.h	19 Feb 2005 14:02:11 -0000	1.15
@@ -22,7 +22,7 @@
 #define D_DEBUG
 
 // FIXME: I don't know how large this constant used to be
-#define MAX_DEBUG_TEXTS 50
+#define MAX_DEBUG_TEXTS 55
 
 #define MAX_SHOWVARS 15
 

Index: function.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/function.cpp,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -d -r1.76 -r1.77
--- function.cpp	8 Feb 2005 08:32:49 -0000	1.76
+++ function.cpp	19 Feb 2005 14:02:11 -0000	1.77
@@ -21,19 +21,21 @@
 #include "common/stdafx.h"
 #include "common/file.h"
 #include "common/system.h"
+
 #include "sword2/sword2.h"
 #include "sword2/defs.h"
+#include "sword2/build_display.h"
 #include "sword2/console.h"
 #include "sword2/controls.h"
 #include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
 #include "sword2/sound.h"
 #include "sword2/driver/animation.h"
-#include "sword2/driver/d_draw.h"
 #include "sword2/driver/render.h"
 
 namespace Sword2 {
@@ -65,7 +67,8 @@
 	// params:	0 res id of normal background layer - cannot be 0
 	//		1 1 yes 0 no for a new palette
 
-	return _vm->initBackground(params[0], params[1]);
+	_vm->_screen->initBackground(params[0], params[1]);
+	return IR_CONT;
 }
 
 /**
@@ -106,7 +109,9 @@
 	// params:	0 pointer to ObjectMouse or 0 for no write to mouse
 	//		  list
 
-	_vm->registerMouse((ObjectMouse *) _vm->_memory->decodePtr(params[0]));
+	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+
+	_vm->_mouse->registerMouse(ob_mouse, NULL);
 	return IR_CONT;
 }
 
@@ -244,15 +249,15 @@
 
 		for (i = 0; i < _scriptVars[IN_SUBJECT]; i++) {
 			icon = _vm->_resman->openResource(_subjectList[i].res) + sizeof(StandardHeader) + RDMENU_ICONWIDE * RDMENU_ICONDEEP;
-			_vm->_graphics->setMenuIcon(RDMENU_BOTTOM, i, icon);
+			_vm->_mouse->setMenuIcon(RDMENU_BOTTOM, i, icon);
 			_vm->_resman->closeResource(_subjectList[i].res);
 		}
 
 		for (; i < 15; i++)
-			_vm->_graphics->setMenuIcon(RDMENU_BOTTOM, (uint8) i, NULL);
+			_vm->_mouse->setMenuIcon(RDMENU_BOTTOM, (uint8) i, NULL);
 
-		_vm->_graphics->showMenu(RDMENU_BOTTOM);
-		_vm->setMouse(NORMAL_MOUSE_ID);
+		_vm->_mouse->showMenu(RDMENU_BOTTOM);
+		_vm->_mouse->setMouse(NORMAL_MOUSE_ID);
 		_choosing = true;
 		return IR_REPEAT;
 	}
@@ -261,13 +266,16 @@
 	// about left clicks.
 
 	MouseEvent *me = _vm->mouseEvent();
+	int mouseX, mouseY;
 
-	if (!me || !(me->buttons & RD_LEFTBUTTONDOWN) || _vm->_mouseY < 400)
+	_vm->_mouse->getPos(mouseX, mouseY);
+
+	if (!me || !(me->buttons & RD_LEFTBUTTONDOWN) || mouseY < 400)
 		return IR_REPEAT;
 
 	// Check for click on a menu.
 
-	int hit = _vm->menuClick(_scriptVars[IN_SUBJECT]);
+	int hit = _vm->_mouse->menuClick(_scriptVars[IN_SUBJECT]);
 	if (hit < 0)
 		return IR_REPEAT;
 
@@ -276,7 +284,7 @@
 	for (i = 0; i < _scriptVars[IN_SUBJECT]; i++) {
 		if ((int) i != hit) {
 			icon = _vm->_resman->openResource(_subjectList[i].res) + sizeof(StandardHeader);
-			_vm->_graphics->setMenuIcon(RDMENU_BOTTOM, i, icon);
+			_vm->_mouse->setMenuIcon(RDMENU_BOTTOM, i, icon);
 			_vm->_resman->closeResource(_subjectList[i].res);
 		}
 	}
@@ -288,7 +296,7 @@
 
 	_choosing = false;
 	_scriptVars[IN_SUBJECT] = 0;
-	_vm->setMouse(0);
+	_vm->_mouse->setMouse(0);
 
 	return IR_CONT | (_subjectList[hit].ref << 3);
 }
@@ -371,7 +379,7 @@
 
 		// Walk is about to start, so set the mega's graphic resource
 		ob_graph->anim_resource = ob_mega->megaset_res;
-	} else if (_scriptVars[EXIT_FADING] && _vm->_graphics->getFadeStatus() == RDFADE_BLACK) {
+	} else if (_scriptVars[EXIT_FADING] && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
 		// Double clicked an exit so quit the walk when screen is black
 		// ok, thats it - back to script and change screen
 
@@ -687,8 +695,9 @@
 
 int32 Logic::fnAddMenuObject(int32 *params) {
 	// params:	0 pointer to a MenuObject structure to copy down
+	MenuObject *menuObject = (MenuObject *) _vm->_memory->decodePtr(params[0]);
 
-	_vm->addMenuObject((MenuObject *) _vm->_memory->decodePtr(params[0]));
+	_vm->_mouse->addMenuObject(menuObject);
 	return IR_CONT;
 }
 
@@ -704,12 +713,7 @@
 int32 Logic::fnStartConversation(int32 *params) {
 	// params:	none
 
-	if (_scriptVars[TALK_FLAG] == 0) {
-		// See fnChooser & speech scripts
-		_scriptVars[CHOOSER_COUNT_FLAG] = 0;
-	}
-
-	fnNoHuman(params);
+	_vm->_mouse->startConversation();
 	return IR_CONT;
 }
 
@@ -720,16 +724,7 @@
 int32 Logic::fnEndConversation(int32 *params) {
 	// params:	none
 
-	_vm->_graphics->hideMenu(RDMENU_BOTTOM);
-
-	if (_vm->_mouseY > 399) {
-		// Will wait for cursor to move off the bottom menu
-		_vm->_mouseMode = MOUSE_holding;
-	}
-
-	// In case DC forgets
-	_scriptVars[TALK_FLAG] = 0;
-
+	_vm->_mouse->endConversation();
 	return IR_CONT;
 }
 
@@ -789,7 +784,12 @@
 	//		1 pointer to graphic structure
 	//		2 pointer to mega structure or NULL if not a mega
 
-	return _vm->registerFrame(params);
+	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+	ObjectGraphic *ob_graph = (ObjectGraphic *) _vm->_memory->decodePtr(params[1]);
+	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
+
+	_vm->_screen->registerFrame(ob_mouse, ob_graph, ob_mega);
+	return IR_CONT;
 }
 
 int32 Logic::fnNoSprite(int32 *params) {
@@ -824,15 +824,16 @@
 	// params:	0 pointer to mega structure
 
 	ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[0]);
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
-	_vm->_thisScreen.player_feet_x = ob_mega->feet_x;
-	_vm->_thisScreen.player_feet_y = ob_mega->feet_y;
+	screenInfo->player_feet_x = ob_mega->feet_x;
+	screenInfo->player_feet_y = ob_mega->feet_y;
 
 	// for the script
 	_scriptVars[PLAYER_FEET_X] = ob_mega->feet_x;
 	_scriptVars[PLAYER_FEET_Y] = ob_mega->feet_y;
 	_scriptVars[PLAYER_CUR_DIR] = ob_mega->current_dir;
-	_scriptVars[SCROLL_OFFSET_X] = _vm->_thisScreen.scroll_offset_x;
+	_scriptVars[SCROLL_OFFSET_X] = screenInfo->scroll_offset_x;
 
 	debug(5, "fnUpdatePlayerStats: %d %d", ob_mega->feet_x, ob_mega->feet_y);
 
@@ -856,13 +857,14 @@
 	// params:	0 pointer to object's mouse structure
 
  	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// floor is always lowest priority
 
 	ob_mouse->x1 = 0;
 	ob_mouse->y1 = 0;
-	ob_mouse->x2 = _vm->_thisScreen.screen_wide - 1;
-	ob_mouse->y2 = _vm->_thisScreen.screen_deep - 1;
+	ob_mouse->x2 = screenInfo->screen_wide - 1;
+	ob_mouse->y2 = screenInfo->screen_deep - 1;
 	ob_mouse->priority = 9;
 	ob_mouse->pointer = NORMAL_MOUSE_ID;
 	return IR_CONT;
@@ -939,95 +941,14 @@
 int32 Logic::fnNoHuman(int32 *params) {
 	// params:	none
 
-	_vm->noHuman();
-	_vm->clearPointerText();
-
-	// must be normal mouse situation or a largely neutral situation -
-	// special menus use noHuman
-
-	// dont hide menu in conversations
-	if (_scriptVars[TALK_FLAG] == 0)
-		_vm->_graphics->hideMenu(RDMENU_BOTTOM);
-
-	if (_vm->_mouseMode == MOUSE_system_menu) {
-		// close menu
-		_vm->_mouseMode = MOUSE_normal;
-		_vm->_graphics->hideMenu(RDMENU_TOP);
-	}
-
+	_vm->_mouse->noHuman();
 	return IR_CONT;
 }
 
 int32 Logic::fnAddHuman(int32 *params) {
 	// params:	none
 
-	// for logic scripts
-	_scriptVars[MOUSE_AVAILABLE] = 1;
-
-	// off
-	if (_vm->_mouseStatus) {
-		_vm->_mouseStatus = false;	// on
-		_vm->_mouseTouching = 1;	// forces engine to choose a cursor
-	}
-
-	// clear this to reset no-second-click system
-	_scriptVars[CLICKED_ID] = 0;
-
-	// this is now done outside the OBJECT_HELD check in case it's set to
-	// zero before now!
-
-	// unlock the mouse from possible large object lock situtations - see
-	// syphon in rm 3
-
-	_vm->_mouseModeLocked = false;
-
-	if (_scriptVars[OBJECT_HELD]) {
-		// was dragging something around
-		// need to clear this again
-		_scriptVars[OBJECT_HELD] = 0;
-
-		// and these may also need clearing, just in case
-		_vm->_examiningMenuIcon = false;
-		Logic::_scriptVars[COMBINE_BASE] = 0;
-
-		_vm->setLuggage(0);
-	}
-
-	// if mouse is over menu area
-	if (_vm->_mouseY > 399) {
-		if (_vm->_mouseMode != MOUSE_holding) {
-			// VITAL - reset things & rebuild the menu
-			_vm->_mouseMode = MOUSE_normal;
-			_vm->setMouse(NORMAL_MOUSE_ID);
-		} else
-			_vm->setMouse(NORMAL_MOUSE_ID);
-	}
-
-	// enabled/disabled from console; status printed with on-screen debug
-	// info
-
-	if (_vm->_debugger->_testingSnR) {
-		uint8 black[4] = {   0,  0,    0,   0 };
-		uint8 white[4] = { 255, 255, 255,   0 };
-
-		// testing logic scripts by simulating an instant Save &
-		// Restore
-
-		_vm->_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
-
-		// stops all fx & clears the queue - eg. when leaving a
-		// location
-
-		_vm->_sound->clearFxQueue();
-
-		// Trash all object resources so they load in fresh & restart
-		// their logic scripts
-
-		_vm->_resman->killAllObjects(false);
-
-		_vm->_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
-	}
-
+	_vm->_mouse->addHuman();
 	return IR_CONT;
 }
 
@@ -1265,8 +1186,8 @@
 
 	// params:	none
 
-	if (_vm->_graphics->getFadeStatus() == RDFADE_NONE)
-		_vm->_graphics->fadeDown();
+	if (_vm->_screen->getFadeStatus() == RDFADE_NONE)
+		_vm->_screen->fadeDown();
 
 	return IR_CONT;
 }
@@ -1562,9 +1483,13 @@
 	// Ok, all is running along smoothly - but a click means stop
 	// unnaturally
 
+	int mouseX, mouseY;
+
+	_vm->_mouse->getPos(mouseX, mouseY);
+
 	// So that we can go to the options panel while text & speech is
 	// being tested
-	if (_scriptVars[SYSTEM_TESTING_TEXT] == 0 || _vm->_mouseY > 0) {
+	if (_scriptVars[SYSTEM_TESTING_TEXT] == 0 || mouseY > 0) {
 		MouseEvent *me = _vm->mouseEvent();
 
 		// Note that we now have TWO click-delays - one for LEFT
@@ -2299,8 +2224,10 @@
 	// feet_x & feet_y refer to the physical screen coords where the
 	// system will try to maintain George's feet
 
-	_vm->_thisScreen.feet_x = params[0];
-	_vm->_thisScreen.feet_y = params[1];
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+	screenInfo->feet_x = params[0];
+	screenInfo->feet_y = params[1];
 	return IR_CONT;
 }
 
@@ -2350,16 +2277,17 @@
 	// params:	0 pointer to object's mouse structure
 
  	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// Highest priority
 
 	ob_mouse->x1 = 0;
 	ob_mouse->y1 = 0;
-	ob_mouse->x2 = _vm->_thisScreen.scroll_offset_x + SCROLL_MOUSE_WIDTH;
-	ob_mouse->y2 = _vm->_thisScreen.screen_deep - 1;
+	ob_mouse->x2 = screenInfo->scroll_offset_x + SCROLL_MOUSE_WIDTH;
+	ob_mouse->y2 = screenInfo->screen_deep - 1;
 	ob_mouse->priority = 0;
 
-	if (_vm->_thisScreen.scroll_offset_x > 0) {
+	if (screenInfo->scroll_offset_x > 0) {
 		// not fully scrolled to the left
 		ob_mouse->pointer = SCROLL_LEFT_MOUSE_ID;
 	} else {
@@ -2374,16 +2302,17 @@
 	// params:	0 pointer to object's mouse structure
 
 	ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// Highest priority
 
-	ob_mouse->x1 = _vm->_thisScreen.scroll_offset_x + _vm->_graphics->_screenWide - SCROLL_MOUSE_WIDTH;
+	ob_mouse->x1 = screenInfo->scroll_offset_x + _vm->_screen->getScreenWide() - SCROLL_MOUSE_WIDTH;
 	ob_mouse->y1 = 0;
-	ob_mouse->x2 = _vm->_thisScreen.screen_wide - 1;
-	ob_mouse->y2 = _vm->_thisScreen.screen_deep - 1;
+	ob_mouse->x2 = screenInfo->screen_wide - 1;
+	ob_mouse->y2 = screenInfo->screen_deep - 1;
 	ob_mouse->priority = 0;
 
-	if (_vm->_thisScreen.scroll_offset_x < _vm->_thisScreen.max_scroll_offset_x) {
+	if (screenInfo->scroll_offset_x < screenInfo->max_scroll_offset_x) {
 		// not fully scrolled to the right
 		ob_mouse->pointer = SCROLL_RIGHT_MOUSE_ID;
 	} else {
@@ -2405,19 +2334,19 @@
 	// what colour?
 	switch (params[0]) {
 	case BLACK:
-		_vm->_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
 		break;
 	case WHITE:
-		_vm->_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
 		break;
 	case RED:
-		_vm->_graphics->setPalette(0, 1, red, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, red, RDPAL_INSTANT);
 		break;
 	case GREEN:
-		_vm->_graphics->setPalette(0, 1, green, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, green, RDPAL_INSTANT);
 		break;
 	case BLUE:
-		_vm->_graphics->setPalette(0, 1, blue, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, blue, RDPAL_INSTANT);
 		break;
 	}
 #endif
@@ -2450,25 +2379,25 @@
 	// what colour?
 	switch (params[0]) {
 	case WHITE:
-		_vm->_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
 		break;
 	case RED:
-		_vm->_graphics->setPalette(0, 1, red, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, red, RDPAL_INSTANT);
 		break;
 	case GREEN:
-		_vm->_graphics->setPalette(0, 1, green, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, green, RDPAL_INSTANT);
 		break;
 	case BLUE:
-		_vm->_graphics->setPalette(0, 1, blue, RDPAL_INSTANT);
+		_vm->_screen->setPalette(0, 1, blue, RDPAL_INSTANT);
 		break;
 	}
 
 	// There used to be a busy-wait loop here, so I don't know how long
 	// the delay was meant to be. Probably doesn't matter much.
 
-	_vm->_graphics->updateDisplay();
+	_vm->_screen->updateDisplay();
 	_vm->_system->delayMillis(250);
-	_vm->_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
+	_vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
 #endif
 
 	return IR_CONT;
@@ -2736,14 +2665,14 @@
 	// now clear the screen in case the Sequence was quitted (using ESC)
 	// rather than fading down to black
 
-	_vm->_graphics->clearScene();
+	_vm->_screen->clearScene();
 
 	// zero the entire palette in case we're about to fade up!
 
 	byte pal[4 * 256];
 
 	memset(pal, 0, sizeof(pal));
-	_vm->_graphics->setPalette(0, 256, pal, RDPAL_INSTANT);
+	_vm->_screen->setPalette(0, 256, pal, RDPAL_INSTANT);
 
 	debug(5, "fnPlaySequence FINISHED");
 	return IR_CONT;
@@ -2764,10 +2693,10 @@
 int32 Logic::fnFadeUp(int32 *params) {
 	// params:	none
 
-	_vm->_graphics->waitForFade();
+	_vm->_screen->waitForFade();
 
-	if (_vm->_graphics->getFadeStatus() == RDFADE_BLACK)
-		_vm->_graphics->fadeUp();
+	if (_vm->_screen->getFadeStatus() == RDFADE_BLACK)
+		_vm->_screen->fadeUp();
 
 	return IR_CONT;
 }
@@ -2785,7 +2714,7 @@
 	// +2 to skip the encoded text number in the first 2 chars; 3 is
 	// duration in seconds
 
-	_vm->displayMsg(_vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text) + 2, 3);
+	_vm->_screen->displayMsg(_vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text) + 2, 3);
 	_vm->_resman->closeResource(text_res);
 
 	return IR_CONT;
@@ -2793,14 +2722,9 @@
 
 int32 Logic::fnSetObjectHeld(int32 *params) {
 	// params:	0 luggage icon to set
+	uint32 res = (uint32) params[0];
 
-	_vm->setLuggage(params[0]);
-
-	_scriptVars[OBJECT_HELD] = params[0];
-	_vm->_currentLuggageResource = params[0];
-
-	// mode locked - no menu available
-	_vm->_mouseModeLocked = true;
+	_vm->_mouse->setObjectHeld(res);
 	return IR_CONT;
 }
 
@@ -2824,6 +2748,8 @@
 
 	// params:	none
 
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
 	int32 size;
 	uint32 *globals;
 
@@ -2846,7 +2772,7 @@
 	// - this is taken from fnInitBackground
 
 	// switch on scrolling (2 means first time on screen)
-	_vm->_thisScreen.scroll_flag = 2;
+	screenInfo->scroll_flag = 2;
 
 	return IR_CONT;
 }
@@ -2855,7 +2781,7 @@
 	// params:	0 resource number of palette file, or 0 if it's to be
 	//		  the palette from the current screen
 
-	_vm->setFullPalette(params[0]);
+	_vm->_screen->setFullPalette(params[0]);
 	return IR_CONT;
 }
 
@@ -2866,13 +2792,7 @@
 int32 Logic::fnRegisterPointerText(int32 *params) {
 	// params:	0 local id of text line to use as pointer text
 
-	assert(_vm->_curMouse < TOTAL_mouse_list);
-
-	// current object id - used for checking pointer_text when mouse area
-	// registered (in fnRegisterMouse and fnRegisterFrame)
-
-	_vm->_mouseList[_vm->_curMouse].id = _scriptVars[ID];
-	_vm->_mouseList[_vm->_curMouse].pointer_text = params[0];
+	_vm->_mouse->registerPointerText(params[0]);
 	return IR_CONT;
 }
 
@@ -2940,18 +2860,9 @@
 	// params:	0 threshold delay in seconds, ie. what we want to
 	//		  check the actual delay against
 
-	uint32 threshold = params[0] * 12;	// in game cycles
-
-	// if the actual delay is at or above the given threshold
-	if (_vm->_playerActivityDelay >= threshold) {
-		// reset activity delay counter, now that we've got a
-		// positive check
-
-		_vm->_playerActivityDelay = 0;
-		_scriptVars[RESULT] = 1;
-	} else
-		_scriptVars[RESULT] = 0;
+	uint32 seconds = (uint32) params[0];
 
+	_vm->_mouse->checkPlayerActivity(seconds);
 	return IR_CONT;
 }
 
@@ -2961,7 +2872,7 @@
 
 	// params:	none
 
-	_vm->_playerActivityDelay = 0;
+	_vm->_mouse->resetPlayerActivityDelay();
 	return IR_CONT;
 }
 
@@ -3005,6 +2916,7 @@
 #define CREDITS_LINE_SPACING 20
 
 int32 Logic::fnPlayCredits(int32 *params) {
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 	uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();
 
 	// This function just quits the game if this is the playable demo, ie.
@@ -3019,16 +2931,16 @@
 
 	// Prepare for the credits by fading down, stoping the music, etc.
 
-	_vm->setMouse(0);
+	_vm->_mouse->setMouse(0);
 
 	_vm->_sound->muteFx(true);
 	_vm->_sound->muteSpeech(true);
 
-	_vm->_graphics->waitForFade();
-	_vm->_graphics->fadeDown();
-	_vm->_graphics->waitForFade();
+	_vm->_screen->waitForFade();
+	_vm->_screen->fadeDown();
+	_vm->_screen->waitForFade();
 
-	_vm->_graphics->closeMenuImmediately();
+	_vm->_mouse->closeMenuImmediately();
 
 	// There are three files which I believe are involved in showing the
 	// credits:
@@ -3093,7 +3005,7 @@
 		palette[14 * 4 + 3] = 0;
 	}
 
-	_vm->_graphics->setPalette(0, 256, palette, RDPAL_INSTANT);
+	_vm->_screen->setPalette(0, 256, palette, RDPAL_INSTANT);
 
 	// Read the credits text
 
@@ -3206,8 +3118,8 @@
 	pars[1] = FX_SPOT;
 	fnPlayMusic(pars);
 
-	_vm->_graphics->clearScene();
-	_vm->_graphics->fadeUp(0);
+	_vm->_screen->clearScene();
+	_vm->_screen->fadeUp(0);
 
 	spriteInfo.scale = 0;
 	spriteInfo.scaledWidth = 0;
@@ -3232,7 +3144,7 @@
 	while (scrollPos < scrollSteps && !_vm->_quit) {
 		bool foundStartLine = false;
 
-		_vm->_graphics->clearScene();
+		_vm->_screen->clearScene();
 
 		for (i = startLine; i < lineCount; i++) {
 			// Free any sprites that have scrolled off the screen
@@ -3284,23 +3196,23 @@
 				}
 
 				if (spriteInfo.data)
-					_vm->_graphics->drawSprite(&spriteInfo);
+					_vm->_screen->drawSprite(&spriteInfo);
 			} else
 				break;
 		}
 
-		_vm->_graphics->updateDisplay();
+		_vm->_screen->updateDisplay();
 
 		KeyboardEvent *ke = _vm->keyboardEvent();
 
 		if (ke && ke->keycode == 27) {
 			if (!abortCredits) {
 				abortCredits = true;
-				_vm->_graphics->fadeDown();
+				_vm->_screen->fadeDown();
 			}
 		}
 
-		if (abortCredits && _vm->_graphics->getFadeStatus() == RDFADE_BLACK)
+		if (abortCredits && _vm->_screen->getFadeStatus() == RDFADE_BLACK)
 			break;
 
 		_vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps);
@@ -3325,7 +3237,7 @@
 		// wait for it to really happen.
 
 		while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
-			_vm->_graphics->updateDisplay(false);
+			_vm->_screen->updateDisplay(false);
 			_vm->_system->delayMillis(100);
 		}
 	}
@@ -3343,13 +3255,13 @@
 	} else
 		fnStopMusic(NULL);
 
-	_vm->_thisScreen.new_palette = 99;
+	screenInfo->new_palette = 99;
 
-	if (!_vm->_mouseStatus || _choosing)
-		_vm->setMouse(NORMAL_MOUSE_ID);
+	if (!_vm->_mouse->getMouseStatus() || _choosing)
+		_vm->_mouse->setMouse(NORMAL_MOUSE_ID);
 
 	if (_scriptVars[DEAD])
-		_vm->buildSystemMenu();
+		_vm->_mouse->buildSystemMenu();
 
 	return IR_CONT;
 }
@@ -3357,24 +3269,24 @@
 int32 Logic::fnSetScrollSpeedNormal(int32 *params) {
 	// params:	none
 
-	_vm->_scrollFraction = 16;
+	_vm->_screen->setScrollFraction(16);
 	return IR_CONT;
 }
 
 int32 Logic::fnSetScrollSpeedSlow(int32 *params) {
 	// params:	none
 
-	_vm->_scrollFraction = 32;
+	_vm->_screen->setScrollFraction(32);
 	return IR_CONT;
 }
 
-// called from speech scripts to remove the chooser bar when it's not
+// Called from speech scripts to remove the chooser bar when it's not
 // appropriate to keep it displayed
 
 int32 Logic::fnRemoveChooser(int32 *params) {
 	// params:	none
 
-	_vm->_graphics->hideMenu(RDMENU_BOTTOM);
+	_vm->_mouse->hideMenu(RDMENU_BOTTOM);
 	return IR_CONT;
 }
 
@@ -3413,34 +3325,27 @@
 }
 
 int32 Logic::fnRefreshInventory(int32 *params) {
-	// called from 'menu_look_or_combine' script in 'menu_master' object
+	// Called from 'menu_look_or_combine' script in 'menu_master' object
 	// to update the menu to display a combined object while George runs
 	// voice-over. Note that 'object_held' must be set to the graphic of
 	// the combined object
 
 	// params:	none
 
-	// can reset this now
-	_scriptVars[COMBINE_BASE] = 0;
-
-	// so that the icon in 'object_held' is coloured while the rest are
-	// grey
-	_vm->_examiningMenuIcon = true;
-	_vm->buildMenu();
-	_vm->_examiningMenuIcon = false;
-
+	_vm->_mouse->refreshInventory();
 	return IR_CONT;
 }
 
 int32 Logic::fnChangeShadows(int32 *params) {
 	// params:	none
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
 	// if last screen was using a shading mask (see below)
-	if (_vm->_thisScreen.mask_flag) {
-		uint32 rv = _vm->_graphics->closeLightMask();
+	if (screenInfo->mask_flag) {
+		uint32 rv = _vm->_screen->closeLightMask();
 		if (rv)
 			error("Driver Error %.8x", rv);
-		_vm->_thisScreen.mask_flag = false;
+		screenInfo->mask_flag = false;
 	}
 
 	return IR_CONT;

Index: icons.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/icons.cpp,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- icons.cpp	28 Jan 2005 16:33:09 -0000	1.40
+++ icons.cpp	19 Feb 2005 14:02:11 -0000	1.41
@@ -24,12 +24,12 @@
 #include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
-void Sword2Engine::addMenuObject(MenuObject *obj) {
+void Mouse::addMenuObject(MenuObject *obj) {
 	assert(_totalTemp < TOTAL_engine_pockets);
 	memcpy(&_tempList[_totalTemp], obj, sizeof(MenuObject));
 	_totalTemp++;
@@ -39,7 +39,7 @@
  * Create and start the inventory (bottom) menu
  */
 
-void Sword2Engine::buildMenu(void) {
+void Mouse::buildMenu() {
 	uint32 i, j;
 
 	// Clear the temporary inventory list, since we are going to build a
@@ -54,9 +54,9 @@
 	// register all carried menu objects.
 
 	uint32 null_pc = 0;
-	char *menuScript = (char *) _resman->openResource(MENU_MASTER_OBJECT);
-	_logic->runScript(menuScript, menuScript, &null_pc);
-	_resman->closeResource(MENU_MASTER_OBJECT);
+	char *menuScript = (char *) _vm->_resman->openResource(MENU_MASTER_OBJECT);
+	_vm->_logic->runScript(menuScript, menuScript, &null_pc);
+	_vm->_resman->closeResource(MENU_MASTER_OBJECT);
 
 	// Create a new master list based on the old master inventory list and
 	// the new temporary inventory list. The purpose of all this is, as
@@ -136,7 +136,7 @@
 				icon_coloured = (res != Logic::_scriptVars[OBJECT_HELD]);
 			}
 
-			icon = _resman->openResource(res) + sizeof(StandardHeader);
+			icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
 
 			// The coloured icon is stored directly after the
 			// greyed out one.
@@ -145,20 +145,20 @@
 				icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
 		}
 
-		_graphics->setMenuIcon(RDMENU_BOTTOM, i, icon);
+		setMenuIcon(RDMENU_BOTTOM, i, icon);
 
 		if (res)
-			_resman->closeResource(res);
+			_vm->_resman->closeResource(res);
 	}
 
-	_graphics->showMenu(RDMENU_BOTTOM);
+	showMenu(RDMENU_BOTTOM);
 }
 
 /**
  * Build a fresh system (top) menu.
  */
 
-void Sword2Engine::buildSystemMenu(void) {
+void Mouse::buildSystemMenu() {
 	uint32 icon_list[5] = {
 		OPTIONS_ICON,
 		QUIT_ICON,
@@ -171,7 +171,7 @@
 	// rest will grey out.
 
 	for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
-		byte *icon = _resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+		byte *icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
 		
 		// The only case when an icon is grayed is when the player
 		// is dead. Then SAVE is not available.
@@ -179,11 +179,11 @@
 		if (!Logic::_scriptVars[DEAD] || icon_list[i] != SAVE_ICON)
 			icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
 
-		_graphics->setMenuIcon(RDMENU_TOP, i, icon);
-		_resman->closeResource(icon_list[i]);
+		setMenuIcon(RDMENU_TOP, i, icon);
+		_vm->_resman->closeResource(icon_list[i]);
 	}
 
-	_graphics->showMenu(RDMENU_TOP);
+	showMenu(RDMENU_TOP);
 }
 
 } // End of namespace Sword2

Index: layers.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/layers.cpp,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- layers.cpp	28 Jan 2005 16:33:09 -0000	1.34
+++ layers.cpp	19 Feb 2005 14:02:11 -0000	1.35
@@ -28,11 +28,9 @@
 
 #include "common/stdafx.h"
 #include "sword2/sword2.h"
-#include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/resman.h"
 #include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
@@ -42,30 +40,30 @@
  * @param new_palette 1 for new palette, otherwise 0
  */
 
-int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
+void Screen::initBackground(int32 res, int32 new_palette) {
 	byte buf[NAME_LEN];
 	int i;
 
 	assert(res);
 
 	// The resources age every time a new room is entered.
-	_resman->passTime();
-	_resman->expireOldResources();
+	_vm->_resman->passTime();
+	_vm->_resman->expireOldResources();
 
-	_sound->clearFxQueue();
-	_graphics->waitForFade();
+	_vm->_sound->clearFxQueue();
+	waitForFade();
 
-	debug(1, "CHANGED TO LOCATION \"%s\"", fetchObjectName(res, buf));
+	debug(1, "CHANGED TO LOCATION \"%s\"", _vm->fetchObjectName(res, buf));
 
 	// if last screen was using a shading mask (see below)
 	if (_thisScreen.mask_flag) {
-		if (_graphics->closeLightMask() != RD_OK)
+		if (closeLightMask() != RD_OK)
 			error("Could not close light mask");
 	}
 
 	// Close the previous screen, if one is open
 	if (_thisScreen.background_layer_id)
-		_graphics->closeBackgroundLayer();
+		closeBackgroundLayer();
 
 	_thisScreen.background_layer_id = res;
 	_thisScreen.new_palette = new_palette;
@@ -74,8 +72,8 @@
 	// info/and set them up at the beginning of the sort list - why do it
 	// each cycle
 
-	byte *file = _resman->openResource(_thisScreen.background_layer_id);
-	ScreenHeader *screen_head = fetchScreenHeader(file);
+	byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
+	ScreenHeader *screen_head = _vm->fetchScreenHeader(file);
 
 	// set number of special sort layers
 	_thisScreen.number_of_layers = screen_head->noLayers;
@@ -85,12 +83,12 @@
 	debug(2, "layers=%d width=%d depth=%d", screen_head->noLayers, screen_head->width, screen_head->height);
 
 	// initialise the driver back buffer
-	_graphics->setLocationMetrics(screen_head->width, screen_head->height);
+	setLocationMetrics(screen_head->width, screen_head->height);
 
 	for (i = 0; i < screen_head->noLayers; i++) {
 		debug(3, "init layer %d", i);
 
-		LayerHeader *layer = fetchLayerHeader(file, i);
+		LayerHeader *layer = _vm->fetchLayerHeader(file, i);
 
 		// Add the layer to the sort list. We only provide just enough
 		// information so that it's clear that it's a layer, and where
@@ -104,7 +102,7 @@
 	_thisScreen.scroll_offset_x = 0;
 	_thisScreen.scroll_offset_y = 0;
 
-	if (screen_head->width > _graphics->_screenWide || screen_head->height > _graphics->_screenDeep) {
+	if (screen_head->width > _screenWide || screen_head->height > _screenDeep) {
 		// The layer is larger than the physical screen. Switch on
 		// scrolling. (2 means first time on screen)
 		_thisScreen.scroll_flag = 2;
@@ -115,14 +113,14 @@
 		// Calculate the maximum scroll offsets to prevent scrolling
 		// off the edge. The minimum offsets are both 0.
 
-		_thisScreen.max_scroll_offset_x = screen_head->width - _graphics->_screenWide;
-		_thisScreen.max_scroll_offset_y = screen_head->height - (_graphics->_screenDeep - (RDMENU_MENUDEEP * 2));
+		_thisScreen.max_scroll_offset_x = screen_head->width - _screenWide;
+		_thisScreen.max_scroll_offset_y = screen_head->height - (_screenDeep - (RDMENU_MENUDEEP * 2));
 	} else {
 		// The later fits on the phyiscal screen. Switch off scrolling.
 		_thisScreen.scroll_flag = 0;
 	}
 
-	_graphics->resetRenderEngine();
+	resetRenderEngine();
 
 	// These are the physical screen coords where the system will try to
 	// maintain George's actual feet coords.
@@ -146,10 +144,10 @@
 		spriteInfo.scaledHeight = 0;
 		spriteInfo.type = 0;
 		spriteInfo.blend = 0;
-		spriteInfo.data = fetchShadingMask(file);
+		spriteInfo.data = _vm->fetchShadingMask(file);
 		spriteInfo.colourTable = 0;
 
-		if (_graphics->openLightMask(&spriteInfo) != RD_OK)
+		if (openLightMask(&spriteInfo) != RD_OK)
 			error("Could not open light mask");
 
 		// so we know to close it later! (see above)
@@ -163,26 +161,25 @@
 
 	for (i = 0; i < 2; i++) {
 		if (screenLayerTable->bg_parallax[i])
-			_graphics->initialiseBackgroundLayer(fetchBackgroundParallaxLayer(file, i));
+			initialiseBackgroundLayer(_vm->fetchBackgroundParallaxLayer(file, i));
 		else
-			_graphics->initialiseBackgroundLayer(NULL);
+			initialiseBackgroundLayer(NULL);
 	}
 
 	// Normal backround layer
 
-	_graphics->initialiseBackgroundLayer(fetchBackgroundLayer(file));
+	initialiseBackgroundLayer(_vm->fetchBackgroundLayer(file));
 
 	// Foreground parallax layers
 
 	for (i = 0; i < 2; i++) {
 		if (screenLayerTable->fg_parallax[i])
-			_graphics->initialiseBackgroundLayer(fetchForegroundParallaxLayer(file, i));
+			initialiseBackgroundLayer(_vm->fetchForegroundParallaxLayer(file, i));
 		else
-			_graphics->initialiseBackgroundLayer(NULL);
+			initialiseBackgroundLayer(NULL);
 	}
 
-	_resman->closeResource(_thisScreen.background_layer_id);
-	return IR_CONT;
+	_vm->_resman->closeResource(_thisScreen.background_layer_id);
 }
 
 } // End of namespace Sword2

Index: layers.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/layers.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- layers.h	17 Jan 2005 10:57:10 -0000	1.12
+++ layers.h	19 Feb 2005 14:02:11 -0000	1.13
@@ -23,30 +23,6 @@
 
 namespace Sword2 {
 
-struct ScreenInfo {
-	uint16 scroll_offset_x;		// Position x
-	uint16 scroll_offset_y;		// Position y
-	uint16 max_scroll_offset_x;	// Calc'ed in fnInitBackground
-	uint16 max_scroll_offset_y;
-	int16 player_feet_x;		// Feet coordinates to use - cant just
-	int16 player_feet_y;		// fetch the player compact anymore
-	int16 feet_x;			// Special offset-to-player position -
-	int16 feet_y;			// tweek as desired - always set in
-					// screen manager object startup
-	uint16 screen_wide;		// Size of background layer - hence
-	uint16 screen_deep;		// size of back buffer itself (Paul
-					// actually malloc's it)
-	uint32 background_layer_id;	// Id of the normal background layer
-					// from the header of the main
-					// background layer
-	uint16 number_of_layers;
-	uint8 new_palette;		// Set to non zero to start the
-					// palette held within layer file
-					// fading up after a build_display
-	uint8 scroll_flag;		// Scroll mode 0 off 1 on
-	bool mask_flag;			// Using shading mask
-};
-
 } // End of namespace Sword2
 
 #endif

Index: logic.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/logic.cpp,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- logic.cpp	28 Jan 2005 16:33:10 -0000	1.50
+++ logic.cpp	19 Feb 2005 14:02:11 -0000	1.51
@@ -35,11 +35,10 @@
 namespace Sword2 {
 
 Logic::Logic(Sword2Engine *vm) :
-	_vm(vm), _kills(0), _smackerLeadOut(0), _sequenceTextLines(0),
-	_speechTime(0), _animId(0), _speechAnimType(0), _leftClickDelay(0),
-	_rightClickDelay(0), _defaultResponseId(0), _officialTextNumber(0),
-	_speechTextBlocNo(0),
-	_choosing(false) {
+	_vm(vm), _kills(0), _smackerLeadIn(0), _smackerLeadOut(0),
+	_sequenceTextLines(0), _speechTime(0), _animId(0), _speechAnimType(0),
+	_leftClickDelay(0), _rightClickDelay(0), _defaultResponseId(0),
+	_officialTextNumber(0),	_speechTextBlocNo(0), _choosing(false) {
 	_scriptVars = NULL;
 	memset(_subjectList, 0, sizeof(_subjectList));
 	memset(_eventList, 0, sizeof(_eventList));

Index: logic.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/logic.h,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- logic.h	28 Jan 2005 16:33:10 -0000	1.41
+++ logic.h	19 Feb 2005 14:02:11 -0000	1.42
@@ -27,6 +27,8 @@
 
 namespace Sword2 {
 
+struct MovieTextObject;
+
 #define MAX_events 10
 
 // There won't be many, will there? Probably 2 at most i reckon

Index: maketext.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/maketext.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- maketext.cpp	17 Jan 2005 10:57:10 -0000	1.46
+++ maketext.cpp	19 Feb 2005 14:02:11 -0000	1.47
@@ -43,7 +43,6 @@
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
 #include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
@@ -476,7 +475,7 @@
 			spriteInfo.data = _blocList[i].text_mem + sizeof(FrameHeader);
 			spriteInfo.colourTable = 0;
 
-			uint32 rv = _vm->_graphics->drawSprite(&spriteInfo);
+			uint32 rv = _vm->_screen->drawSprite(&spriteInfo);
 			if (rv)
 				error("Driver Error %.8x in printTextBlocs", rv);
 		}

Index: mouse.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/mouse.cpp,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- mouse.cpp	28 Jan 2005 16:33:10 -0000	1.65
+++ mouse.cpp	19 Feb 2005 14:02:11 -0000	1.66
@@ -27,13 +27,13 @@
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
-// pointer resource id's
+// Pointer resource id's
 
 enum {
 	CROSHAIR	= 18,
@@ -55,19 +55,132 @@
 	USE		= 3100
 };
 
+Mouse::Mouse(Sword2Engine *vm) {
+	_vm = vm;
+
+	setPos(0, 0);
+
+	_mouseTouching = 0;
+	_oldMouseTouching = 0;
+	_menuSelectedPos = 0;
+	_examiningMenuIcon = false;
+	_mousePointerRes = 0;
+	_mouseMode = 0;
+	_mouseStatus = false;
+	_mouseModeLocked = false;
+	_currentLuggageResource = 0;
+	_oldButton = 0;
+	_buttonClick = 0;
+	_pointerTextBlocNo = 0;
+	_playerActivityDelay = 0;
+	_realLuggageItem = 0;
+
+	_mouseSprite = NULL;
+	_mouseAnim = NULL;
+	_luggageAnim = NULL;
+
+	// For the menus
+	_totalTemp = 0;
+	memset(_tempList, 0, sizeof(_tempList));
+
+	_totalMasters = 0;
+	memset(_masterMenuList, 0, sizeof(_masterMenuList));
+	memset(_mouseList, 0, sizeof(_mouseList));
+
+	_iconCount = 0;
+
+	for (int i = 0; i < 2; i++) {
+		for (int j = 0; j < RDMENU_MAXPOCKETS; j++) {
+			_icons[i][j] = NULL;
+			_pocketStatus[i][j] = 0;
+		}
+
+		_menuStatus[i] = RDMENU_HIDDEN;
+	}
+}
+
+Mouse::~Mouse() {
+	free(_mouseAnim);
+	free(_luggageAnim);
+	for (int i = 0; i < 2; i++)
+		for (int j = 0; j < RDMENU_MAXPOCKETS; j++)
+			free(_icons[i][j]);
+}
+
+void Mouse::getPos(int &x, int &y) {
+	x = _pos.x;
+	y = _pos.y;
+}
+
+void Mouse::setPos(int x, int y) {
+	_pos.x = x;
+	_pos.y = y;
+}
+
 /**
  * Call at beginning of game loop
  */
 
-void Sword2Engine::resetMouseList(void) {
+void Mouse::resetMouseList() {
 	_curMouse = 1;
 }
 
+void Mouse::registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit) {
+	if (!ob_mouse->pointer)
+		return;
+
+	assert(_curMouse < TOTAL_mouse_list);
+
+	if (build_unit) {
+		_mouseList[_curMouse].x1 = build_unit->x;
+		_mouseList[_curMouse].y1 = build_unit->y;
+		_mouseList[_curMouse].x2 = build_unit->x + build_unit->scaled_width;
+		_mouseList[_curMouse].y2 = build_unit->y + build_unit->scaled_height;
+	} else {
+		_mouseList[_curMouse].x1 = ob_mouse->x1;
+		_mouseList[_curMouse].y1 = ob_mouse->y1;
+		_mouseList[_curMouse].x2 = ob_mouse->x2;
+		_mouseList[_curMouse].y2 = ob_mouse->y2;
+	}
+
+	_mouseList[_curMouse].priority = ob_mouse->priority;
+	_mouseList[_curMouse].pointer = ob_mouse->pointer;
+
+	// Check if pointer text field is set due to previous object using this
+	// slot (ie. not correct for this one)
+
+	// If 'pointer_text' field is set, but the 'id' field isn't same is
+	// current id then we don't want this "left over" pointer text
+
+	if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
+		_mouseList[_curMouse].pointer_text = 0;
+
+	// Get id from system variable 'id' which is correct for current object
+	_mouseList[_curMouse].id = Logic::_scriptVars[ID];
+
+	// Not using sprite as detection mask - this is only done from
+	// fnRegisterFrame()
+	_mouseList[_curMouse].anim_resource = 0;
+	_mouseList[_curMouse].anim_pc = 0;
+
+	_curMouse++;
+}
+
+void Mouse::registerPointerText(int32 text_id) {
+	assert(_curMouse < TOTAL_mouse_list);
+
+	// current object id - used for checking pointer_text when mouse area
+	// registered (in fnRegisterMouse and fnRegisterFrame)
+
+	_mouseList[_curMouse].id = Logic::_scriptVars[ID];
+	_mouseList[_curMouse].pointer_text = text_id;
+}
+
 /**
  * This function is called every game cycle.
  */
 
-void Sword2Engine::mouseEngine(void) {
+void Mouse::mouseEngine() {
 	monitorPlayerActivity();
 	clearPointerText();
 
@@ -109,7 +222,7 @@
 		systemMenuMouse();
 		break;
 	case MOUSE_holding:
-		if (_mouseY < 400) {
+		if (_pos.y < 400) {
 			_mouseMode = MOUSE_normal;
 			debug(5, "   releasing");
 		}
@@ -120,7 +233,7 @@
 }
 
 #if RIGHT_CLICK_CLEARS_LUGGAGE
-bool Sword2Engine::heldIsInInventory(void) {
+bool Mouse::heldIsInInventory() {
 	for (uint i = 0; i < _totalMasters; i++) {
 		if ((uint32) _masterMenuList[i].icon_resource == Logic::_scriptVars[OBJECT_HELD])
 			return true;
@@ -129,17 +242,17 @@
 }
 #endif
 
-int Sword2Engine::menuClick(int menu_items) {
-	if (_mouseX < RDMENU_ICONSTART)
+int Mouse::menuClick(int menu_items) {
+	if (_pos.x < RDMENU_ICONSTART)
 		return -1;
 
-	if (_mouseX > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
+	if (_pos.x > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
 		return -1;
 
-	return (_mouseX - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
+	return (_pos.x - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
 }
 
-void Sword2Engine::systemMenuMouse(void) {
+void Mouse::systemMenuMouse(void) {
 	uint32 safe_looping_music_id;
 	MouseEvent *me;
 	int hit;
@@ -156,20 +269,20 @@
 	// If the mouse is moved off the menu, close it. Unless the player is
 	// dead, in which case the menu should always be visible.
 
-	if (_mouseY > 0 && !Logic::_scriptVars[DEAD]) {
+	if (_pos.y > 0 && !Logic::_scriptVars[DEAD]) {
 		_mouseMode = MOUSE_normal;
-		_graphics->hideMenu(RDMENU_TOP);
+		hideMenu(RDMENU_TOP);
 		return;
 	}
 
 	// Check if the user left-clicks anywhere in the menu area.
 
-	me = mouseEvent();
+	me = _vm->mouseEvent();
 
 	if (!me || !(me->buttons & RD_LEFTBUTTONDOWN))
 		return;
 
-	if (_mouseY > 0)
+	if (_pos.y > 0)
 		return;
 
 	hit = menuClick(ARRAYSIZE(icon_list));
@@ -186,46 +299,46 @@
 
 	for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
 		if (i != hit) {
-			icon = _resman->openResource(icon_list[i]) + sizeof(StandardHeader);
-			_graphics->setMenuIcon(RDMENU_TOP, i, icon);
-			_resman->closeResource(icon_list[i]);
+			icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+			setMenuIcon(RDMENU_TOP, i, icon);
+			_vm->_resman->closeResource(icon_list[i]);
 		}
 	}
 
-	_sound->pauseFx();
+	_vm->_sound->pauseFx();
 
 	// NB. Need to keep a safe copy of '_loopingMusicId' for savegame & for
 	// playing when returning from control panels because control panel
 	// music will overwrite it!
 
-	safe_looping_music_id = _sound->getLoopingMusicId();
+	safe_looping_music_id = _vm->_sound->getLoopingMusicId();
 
 	pars[0] = 221;
 	pars[1] = FX_LOOP;
-	_logic->fnPlayMusic(pars);
+	_vm->_logic->fnPlayMusic(pars);
 
 	// HACK: Restore proper looping_music_id
-	_sound->setLoopingMusicId(safe_looping_music_id);
+	_vm->_sound->setLoopingMusicId(safe_looping_music_id);
 
-	_graphics->processMenu();
+	processMenu();
 
 	// call the relevant screen
 
 	switch (hit) {
 	case 0:
-		_gui->optionControl();
+		_vm->_gui->optionControl();
 		break;
 	case 1:
-		_gui->quitControl();
+		_vm->_gui->quitControl();
 		break;
 	case 2:
-		_gui->saveControl();
+		_vm->_gui->saveControl();
 		break;
 	case 3:
-		_gui->restoreControl();
+		_vm->_gui->restoreControl();
 		break;
 	case 4:
-		_gui->restartControl();
+		_vm->_gui->restartControl();
 		break;
 	}
 
@@ -233,7 +346,7 @@
 
 	if (!Logic::_scriptVars[DEAD]) {
 		_mouseMode = MOUSE_normal;
-		_graphics->hideMenu(RDMENU_TOP);
+		hideMenu(RDMENU_TOP);
 	} else {
 		setMouse(NORMAL_MOUSE_ID);
 		buildSystemMenu();
@@ -241,35 +354,37 @@
 
 	// Back to the game again
 
-	_graphics->processMenu();
+	processMenu();
 
 	// Reset game palette, but not after a successful restore or restart!
 	// See RestoreFromBuffer() in save_rest.cpp
 
-	if (_thisScreen.new_palette != 99) {
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+	if (screenInfo->new_palette != 99) {
 		// 0 means put back game screen palette; see build_display.cpp
-		setFullPalette(0);
+		_vm->_screen->setFullPalette(0);
 
 		// Stop the engine fading in the restored screens palette
-		_thisScreen.new_palette = 0;
+		screenInfo->new_palette = 0;
 	} else
-		_thisScreen.new_palette = 1;
+		screenInfo->new_palette = 1;
 
-	_sound->unpauseFx();
+	_vm->_sound->unpauseFx();
 
 	// If there was looping music before coming into the control panels
 	// then restart it! NB. If a game has been restored the music will be
 	// restarted twice, but this shouldn't cause any harm.
 
-	if (_sound->getLoopingMusicId()) {
-		pars[0] = _sound->getLoopingMusicId();
+	if (_vm->_sound->getLoopingMusicId()) {
+		pars[0] = _vm->_sound->getLoopingMusicId();
 		pars[1] = FX_LOOP;
-		_logic->fnPlayMusic(pars);
+		_vm->_logic->fnPlayMusic(pars);
 	} else
-		_logic->fnStopMusic(NULL);
+		_vm->_logic->fnStopMusic(NULL);
 }
 
-void Sword2Engine::dragMouse(void) {
+void Mouse::dragMouse(void) {
 	byte buf1[NAME_LEN], buf2[NAME_LEN];
 	MouseEvent *me;
 	int hit;
@@ -278,9 +393,9 @@
 	// objects in the scene, so if the mouse moves off the inventory menu,
 	// then close it.
 
-	if (_mouseY < 400) {
+	if (_pos.y < 400) {
 		_mouseMode = MOUSE_normal;
-		_graphics->hideMenu(RDMENU_BOTTOM);
+		hideMenu(RDMENU_BOTTOM);
 		return;
 	}
 
@@ -290,7 +405,7 @@
 
 	// Now do the normal click stuff
 
-	me = mouseEvent();
+	me = _vm->mouseEvent();
 
 	if (!me)
 		return;
@@ -327,24 +442,25 @@
 		Logic::_scriptVars[RIGHT_BUTTON] = 0;
 
 		// These might be required by the action script about to be run
+		ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
-		Logic::_scriptVars[MOUSE_X] = _mouseX + _thisScreen.scroll_offset_x;
-		Logic::_scriptVars[MOUSE_Y] = _mouseY + _thisScreen.scroll_offset_y;
+		Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
+		Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
 
 		// For scripts to know what's been clicked. First used for
 		// 'room_13_turning_script' in object 'biscuits_13'
 
 		Logic::_scriptVars[CLICKED_ID] = _mouseTouching;
 
-		_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+		_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
 
 		debug(2, "Used \"%s\" on \"%s\"",
-			fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
-			fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+			_vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+			_vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
 
 		// Hide menu - back to normal menu mode
 
-		_graphics->hideMenu(RDMENU_BOTTOM);
+		hideMenu(RDMENU_BOTTOM);
 		_mouseMode = MOUSE_normal;
 
 		return;
@@ -372,16 +488,16 @@
 		// Otherwise, combine the two icons
 
 		Logic::_scriptVars[COMBINE_BASE] = _masterMenuList[hit].icon_resource;
-		_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
+		_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
 
 		// Turn off mouse now, to prevent player trying to click
 		// elsewhere BUT leave the bottom menu open
 
-		noHuman();
+		hideMouse();
 
 		debug(2, "Used \"%s\" on \"%s\"",
-			fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
-			fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
+			_vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+			_vm->fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
 	}
 
 	// Refresh the menu
@@ -389,20 +505,20 @@
 	buildMenu();
 }
 
-void Sword2Engine::menuMouse(void) {
+void Mouse::menuMouse() {
 	byte buf[NAME_LEN];
 	MouseEvent *me;
 	int hit;
 
 	// If the mouse is moved off the menu, close it.
 
-	if (_mouseY < 400) {
+	if (_pos.y < 400) {
 		_mouseMode = MOUSE_normal;
-		_graphics->hideMenu(RDMENU_BOTTOM);
+		hideMenu(RDMENU_BOTTOM);
 		return;
 	}
 
-	me = mouseEvent();
+	me = _vm->mouseEvent();
 
 	if (!me)
 		return;
@@ -426,7 +542,7 @@
 
 		Logic::_scriptVars[EXIT_CLICK_ID] = 0;
 
-		_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
+		_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
 
 		// Refresh the menu
 
@@ -435,10 +551,10 @@
 		// Turn off mouse now, to prevent player trying to click
 		// elsewhere BUT leave the bottom menu open
 
-		noHuman();
+		hideMouse();
 
 		debug(2, "Right-click on \"%s\" icon",
-			fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+			_vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
 
 		return;
 	}
@@ -466,11 +582,11 @@
 		setLuggage(_masterMenuList[hit].luggage_resource);
 
 		debug(2, "Left-clicked on \"%s\" icon - switch to drag mode",
-			fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+			_vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
 	}
 }
 
-void Sword2Engine::normalMouse(void) {
+void Mouse::normalMouse(void) {
 	// The gane is playing and none of the menus are activated - but, we
 	// need to check if a menu is to start. Note, won't have luggage
 
@@ -480,7 +596,7 @@
 	// big-object menu lock situation, of if the player is dragging an
 	// object.
 
-	if (_mouseY < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
+	if (_pos.y < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
 		_mouseMode = MOUSE_system_menu;
 
 		if (_mouseTouching) {
@@ -499,7 +615,7 @@
 	// Check if the cursor has moved onto the inventory menu area. No
 	// inventory in big-object menu lock situation,
 
-	if (_mouseY > 399 && !_mouseModeLocked) {
+	if (_pos.y > 399 && !_mouseModeLocked) {
 		// If an object is being held, i.e. if the mouse cursor has a
 		// luggage, go to drag mode instead of menu mode, but the menu
 		// is still opened.
@@ -532,7 +648,7 @@
 
 	mouseOnOff();
 
-	me = mouseEvent();
+	me = _vm->mouseEvent();
 
 	if (!me)
 		return;
@@ -542,27 +658,29 @@
 	// For debugging. We can draw a rectangle on the screen and see its
 	// coordinates. This was probably used to help defining hit areas.
 
-	if (_debugger->_definingRectangles) {
-		if (_debugger->_draggingRectangle == 0) {
+	if (_vm->_debugger->_definingRectangles) {
+		ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+		if (_vm->_debugger->_draggingRectangle == 0) {
 			// Not yet dragging a rectangle, so need click to start
 
 			if (button_down) {
 				// set both (x1,y1) and (x2,y2) to this point
-				_debugger->_rectX1 = _debugger->_rectX2 = (uint32) _mouseX + _thisScreen.scroll_offset_x;
-				_debugger->_rectY1 = _debugger->_rectY2 = (uint32) _mouseY + _thisScreen.scroll_offset_y;
-				_debugger->_draggingRectangle = 1;
+				_vm->_debugger->_rectX1 = _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
+				_vm->_debugger->_rectY1 = _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
+				_vm->_debugger->_draggingRectangle = 1;
 			}
-		} else if (_debugger->_draggingRectangle == 1) {
+		} else if (_vm->_debugger->_draggingRectangle == 1) {
 			// currently dragging a rectangle - click means reset
 
 			if (button_down) {
 				// lock rectangle, so you can let go of mouse
 				// to type in the coords
-				_debugger->_draggingRectangle = 2;
+				_vm->_debugger->_draggingRectangle = 2;
 			} else {
 				// drag rectangle
-				_debugger->_rectX2 = (uint32) _mouseX + _thisScreen.scroll_offset_x;
-				_debugger->_rectY2 = (uint32) _mouseY + _thisScreen.scroll_offset_y;
+				_vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
+				_vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
 			}
 		} else {
 			// currently locked to avoid knocking out of place
@@ -570,7 +688,7 @@
 
 			if (button_down) {
 				// click means reset - back to start again
-				_debugger->_draggingRectangle = 0;
+				_vm->_debugger->_draggingRectangle = 0;
 			}
 		}
 
@@ -622,17 +740,18 @@
 	}
 
 	// These might be required by the action script about to be run
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
 
-	Logic::_scriptVars[MOUSE_X] = _mouseX + _thisScreen.scroll_offset_x;
-	Logic::_scriptVars[MOUSE_Y] = _mouseY + _thisScreen.scroll_offset_y;
+	Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
+	Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
 
 	if (_mouseTouching == Logic::_scriptVars[EXIT_CLICK_ID] && (me->buttons & RD_LEFTBUTTONDOWN)) {
 		// It's the exit double click situation. Let the existing
 		// interaction continue and start fading down. Switch the human
 		// off too
 
-		_logic->fnNoHuman(NULL);
-		_logic->fnFadeDown(NULL);
+		noHuman();
+		_vm->_logic->fnFadeDown(NULL);
 
 		// Tell the walker
 
@@ -669,24 +788,24 @@
 		if (_mouseTouching == 2773 && !Logic::_scriptVars[LEFT_BUTTON]) {
 			warning("Working around elevator script bug");
 		} else
-			_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+			_vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
 
 		byte buf1[NAME_LEN], buf2[NAME_LEN];
 
 		if (Logic::_scriptVars[OBJECT_HELD])
 			debug(2, "Used \"%s\" on \"%s\"",
-				fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
-				fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+				_vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+				_vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
 		else if (Logic::_scriptVars[LEFT_BUTTON])
 			debug(2, "Left-clicked on \"%s\"",
-				fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+				_vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
 		else	// RIGHT BUTTON
 			debug(2, "Right-clicked on \"%s\"",
-				fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+				_vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
 	}
 }
 
-void Sword2Engine::mouseOnOff(void) {
+void Mouse::mouseOnOff() {
 	// this handles the cursor graphic when moving on and off mouse areas
 	// it also handles the luggage thingy
 
@@ -698,7 +817,7 @@
 	// don't detect objects that are hidden behind the menu bars (ie. in
 	// the scrolled-off areas of the screen)
 
-	if (_mouseY < 0 || _mouseY > 399) {
+	if (_pos.y < 0 || _pos.y > 399) {
 		pointer_type = 0;
 		_mouseTouching = 0;
 	} else {
@@ -743,7 +862,7 @@
 		} else {
 			byte buf[NAME_LEN];
 
-			error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, fetchObjectName(_mouseTouching, buf));
+			error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, _vm->fetchObjectName(_mouseTouching, buf));
 		}
 	} else if (_oldMouseTouching && !_mouseTouching) {
 		// the cursor has moved off something - reset cursor to
@@ -783,55 +902,66 @@
 	// screens
 }
 
-void Sword2Engine::setMouse(uint32 res) {
+void Mouse::setMouse(uint32 res) {
 	// high level - whats the mouse - for the engine
 	_mousePointerRes = res;
 
 	if (res) {
-		byte *icon = _resman->openResource(res) + sizeof(StandardHeader);
-		uint32 len = _resman->fetchLen(res) - sizeof(StandardHeader);
+		byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+		uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
 
 		// don't pulse the normal pointer - just do the regular anim
 		// loop
 
 		if (res == NORMAL_MOUSE_ID)
-			_graphics->setMouseAnim(icon, len, RDMOUSE_NOFLASH);
+			setMouseAnim(icon, len, RDMOUSE_NOFLASH);
 		else
- 			_graphics->setMouseAnim(icon, len, RDMOUSE_FLASH);
+ 			setMouseAnim(icon, len, RDMOUSE_FLASH);
 
-		_resman->closeResource(res);
+		_vm->_resman->closeResource(res);
 	} else {
 		// blank cursor
-		_graphics->setMouseAnim(NULL, 0, 0);
+		setMouseAnim(NULL, 0, 0);
 	}
 }
 
-void Sword2Engine::setLuggage(uint32 res) {
+void Mouse::setLuggage(uint32 res) {
 	_realLuggageItem = res;
 
 	if (res) {
-		byte *icon = _resman->openResource(res) + sizeof(StandardHeader);
-		uint32 len = _resman->fetchLen(res) - sizeof(StandardHeader);
+		byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+		uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
 
-		_graphics->setLuggageAnim(icon, len);
-		_resman->closeResource(res);
+		setLuggageAnim(icon, len);
+		_vm->_resman->closeResource(res);
 	} else
-		_graphics->setLuggageAnim(NULL, 0);
+		setLuggageAnim(NULL, 0);
 }
 
-uint32 Sword2Engine::checkMouseList(void) {
-	// Number of priorities subject to implementation needs
+void Mouse::setObjectHeld(uint32 res) {
+	setLuggage(res);
+
+	Logic::_scriptVars[OBJECT_HELD] = res;
+	_currentLuggageResource = res;
+
+	// mode locked - no menu available
+	_mouseModeLocked = true;
+}
 
+uint32 Mouse::checkMouseList() {
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+	// Number of priorities subject to implementation needs
 	for (int priority = 0; priority < 10; priority++) {
 		for (uint i = 1; i < _curMouse; i++) {
 			// If the mouse pointer is over this
 			// mouse-detection-box
 
 			if (_mouseList[i].priority == priority &&
-			    _mouseX + _thisScreen.scroll_offset_x >= _mouseList[i].x1 &&
-			    _mouseX + _thisScreen.scroll_offset_x <= _mouseList[i].x2 &&
-			    _mouseY + _thisScreen.scroll_offset_y >= _mouseList[i].y1 &&
-			    _mouseY + _thisScreen.scroll_offset_y <= _mouseList[i].y2) {
+			    _pos.x + screenInfo->scroll_offset_x >= _mouseList[i].x1 &&
+			    _pos.x + screenInfo->scroll_offset_x <= _mouseList[i].x2 &&
+			    _pos.y + screenInfo->scroll_offset_y >= _mouseList[i].y1 &&
+			    _pos.y + screenInfo->scroll_offset_y <= _mouseList[i].y2) {
 				// Record id
 				_mouseTouching = _mouseList[i].id;
 
@@ -855,7 +985,7 @@
 #define POINTER_TEXT_WIDTH	640		// just in case!
 #define POINTER_TEXT_PEN	184		// white
 
-void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
+void Mouse::createPointerText(uint32 text_id, uint32 pointer_res) {
 	uint32 local_text;
 	uint32 text_res;
 	byte *text;
@@ -863,7 +993,7 @@
 	int16 xOffset, yOffset;
 	uint8 justification;
 
-	if (!_gui->_pointerTextSelected || !text_id)
+	if (!_vm->_gui->_pointerTextSelected || !text_id)
 		return;
 
 	// Check what the pointer is, to set offsets correctly for text
@@ -993,30 +1123,30 @@
 	local_text = text_id & 0xffff;
 
 	// open text file & get the line
-	text = fetchTextLine(_resman->openResource(text_res), local_text);
+	text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
 
 	// 'text+2' to skip the first 2 bytes which form the
 	// line reference number
 
-	_pointerTextBlocNo = _fontRenderer->buildNewBloc(
-		text + 2, _mouseX + xOffset,
-		_mouseY + yOffset,
+	_pointerTextBlocNo = _vm->_fontRenderer->buildNewBloc(
+		text + 2, _pos.x + xOffset,
+		_pos.y + yOffset,
 		POINTER_TEXT_WIDTH, POINTER_TEXT_PEN,
 		RDSPR_TRANS | RDSPR_DISPLAYALIGN,
-		_speechFontId, justification);
+		_vm->_speechFontId, justification);
 
 	// now ok to close the text file
-	_resman->closeResource(text_res);
+	_vm->_resman->closeResource(text_res);
 }
 
-void Sword2Engine::clearPointerText(void) {
+void Mouse::clearPointerText() {
 	if (_pointerTextBlocNo) {
-		_fontRenderer->killTextBloc(_pointerTextBlocNo);
+		_vm->_fontRenderer->killTextBloc(_pointerTextBlocNo);
 		_pointerTextBlocNo = 0;
 	}
 }
 
-void Sword2Engine::noHuman(void) {
+void Mouse::hideMouse() {
 	// leaves the menus open
 	// used by the system when clicking right on a menu item to examine
 	// it and when combining objects
@@ -1031,47 +1161,122 @@
 	setLuggage(0);
 }
 
-void Sword2Engine::registerMouse(ObjectMouse *ob_mouse) {
-	debug(5, "_curMouse = %d", _curMouse);
+void Mouse::noHuman() {
+	hideMouse();
+	clearPointerText();
 
-	if (!ob_mouse->pointer)
-		return;
+	// Must be normal mouse situation or a largely neutral situation -
+	// special menus use hideMouse()
 
-	assert(_curMouse < TOTAL_mouse_list);
+	// Don't hide menu in conversations
+	if (Logic::_scriptVars[TALK_FLAG] == 0)
+		hideMenu(RDMENU_BOTTOM);
 
-	_mouseList[_curMouse].x1 = ob_mouse->x1;
-	_mouseList[_curMouse].y1 = ob_mouse->y1;
-	_mouseList[_curMouse].x2 = ob_mouse->x2;
-	_mouseList[_curMouse].y2 = ob_mouse->y2;
+	if (_mouseMode == MOUSE_system_menu) {
+		// Close menu
+		_mouseMode = MOUSE_normal;
+		hideMenu(RDMENU_TOP);
+	}
+}
 
-	_mouseList[_curMouse].priority = ob_mouse->priority;
-	_mouseList[_curMouse].pointer = ob_mouse->pointer;
+void Mouse::addHuman() {
+	// For logic scripts
+	Logic::_scriptVars[MOUSE_AVAILABLE] = 1;
 
-	// Check if pointer text field is set due to previous object using this
-	// slot (ie. not correct for this one)
+	if (_mouseStatus) {
+		// Force engine to choose a cursor
+		_mouseStatus = false;
+		_mouseTouching = 1;
+	}
 
-	// If 'pointer_text' field is set, but the 'id' field isn't same is
-	// current id, then we don't want this "left over" pointer text
+	// Clear this to reset no-second-click system
+	Logic::_scriptVars[CLICKED_ID] = 0;
 
-	if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
-		_mouseList[_curMouse].pointer_text = 0;
+	// This is now done outside the OBJECT_HELD check in case it's set to
+	// zero before now!
 
-	// Get id from system variable 'id' which is correct for current object
+	// Unlock the mouse from possible large object lock situtations - see
+	// syphon in rm 3
 
-	_mouseList[_curMouse].id = Logic::_scriptVars[ID];
+	_mouseModeLocked = false;
 
-	// Not using sprite as mask - this is only done from fnRegisterFrame()
+	if (Logic::_scriptVars[OBJECT_HELD]) {
+		// Was dragging something around - need to clear this again
+		Logic::_scriptVars[OBJECT_HELD] = 0;
 
-	_mouseList[_curMouse].anim_resource = 0;
-	_mouseList[_curMouse].anim_pc = 0;
+		// And these may also need clearing, just in case
+		_examiningMenuIcon = false;
+		Logic::_scriptVars[COMBINE_BASE] = 0;
 
-	debug(5, "mouse id %d", _mouseList[_curMouse].id);
-	_curMouse++;
+		setLuggage(0);
+	}
+
+	// If mouse is over menu area
+	if (_pos.y > 399) {
+		if (_mouseMode != MOUSE_holding) {
+			// VITAL - reset things & rebuild the menu
+			_mouseMode = MOUSE_normal;
+		}
+		setMouse(NORMAL_MOUSE_ID);
+	}
+
+	// Enabled/disabled from console; status printed with on-screen debug
+	// info
+
+	if (_vm->_debugger->_testingSnR) {
+		uint8 black[4] = {   0,  0,    0,   0 };
+		uint8 white[4] = { 255, 255, 255,   0 };
+
+		// Testing logic scripts by simulating instant Save & Restore
+
+		_vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
+
+		// Stops all fx & clears the queue - eg. when leaving a room
+		_vm->_sound->clearFxQueue();
+
+		// Trash all object resources so they load in fresh & restart
+		// their logic scripts
+
+		_vm->_resman->killAllObjects(false);
+
+		_vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
+	}
 }
 
-void Sword2Engine::monitorPlayerActivity(void) {
+void Mouse::refreshInventory() {
+	// Can reset this now
+	Logic::_scriptVars[COMBINE_BASE] = 0;
+
+	// Cause 'object_held' icon to be greyed. The rest are coloured.
+	_examiningMenuIcon = true;
+	buildMenu();
+	_examiningMenuIcon = false;
+}
+
+void Mouse::startConversation() {
+	if (Logic::_scriptVars[TALK_FLAG] == 0) {
+		// See fnChooser & speech scripts
+		Logic::_scriptVars[CHOOSER_COUNT_FLAG] = 0;
+	}
+
+	noHuman();
+}
+
+void Mouse::endConversation() {
+	hideMenu(RDMENU_BOTTOM);
+
+	if (_pos.y > 399) {
+		// Will wait for cursor to move off the bottom menu
+		_mouseMode = MOUSE_holding;
+	}
+
+	// In case DC forgets
+	Logic::_scriptVars[TALK_FLAG] = 0;
+}
+
+void Mouse::monitorPlayerActivity() {
 	// if there is at least one mouse event outstanding
-	if (checkForMouseEvents()) {
+	if (_vm->checkForMouseEvents()) {
 		// reset activity delay counter
 		_playerActivityDelay = 0;
 	} else {
@@ -1080,4 +1285,33 @@
 	}
 }
 
+void Mouse::checkPlayerActivity(uint32 seconds) {
+	// Convert seconds to game cycles
+	uint32 threshold = seconds * 12;
+
+	// If the actual delay is at or above the given threshold, reset the
+	// activity delay counter now that we've got a positive check.
+
+	if (_playerActivityDelay >= threshold) {
+		_playerActivityDelay = 0;
+		Logic::_scriptVars[RESULT] = 1;
+	} else
+		Logic::_scriptVars[RESULT] = 0;
+}
+
+void Mouse::pauseGame() {
+	// Make the mouse cursor normal. This is the only place where we are
+	// allowed to clear the luggage this way.
+
+	clearPointerText();
+	setLuggageAnim(NULL, 0);
+	setMouse(0);
+	setMouseTouching(1);
+}
+
+void Mouse::unpauseGame() {
+	if (Logic::_scriptVars[OBJECT_HELD] && _realLuggageItem)
+		setLuggage(_realLuggageItem);
+}
+
 } // End of namespace Sword2

Index: mouse.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/mouse.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- mouse.h	17 Jan 2005 10:57:11 -0000	1.15
+++ mouse.h	19 Feb 2005 14:02:12 -0000	1.16
@@ -21,17 +21,30 @@
 #ifndef MOUSE_H
 #define MOUSE_H
 
-#define	TOTAL_mouse_list	50
+#define	TOTAL_mouse_list 50
 
 namespace Sword2 {
 
-enum {
-	MOUSE_normal		= 0,	// normal in game
-	MOUSE_menu		= 1,	// menu chooser
-	MOUSE_drag		= 2,	// dragging luggage
-	MOUSE_system_menu	= 3,	// system menu chooser
-	MOUSE_holding		= 4	// special
-};
+struct ObjectMouse;
+struct BuildUnit;
+
+#if !defined(__GNUC__)
+	#pragma START_PACK_STRUCTS
+#endif
+
+struct MouseAnim {
+	uint8 runTimeComp;	// type of runtime compression used for the
+				// frame data
+	uint8 noAnimFrames;	// number of frames in the anim
+	int8 xHotSpot;		
+	int8 yHotSpot;
+	uint8 mousew;
+	uint8 mouseh;
+} GCC_PACK;
+
+#if !defined(__GNUC__)
+	#pragma END_PACK_STRUCTS
+#endif
 
 // The MOUSE_holding mode is entered when the conversation menu is closed, and
 // exited when the mouse cursor moves off that menu area. I don't know why yet.
@@ -68,6 +81,136 @@
 	int32 pointer_text;
 };
 
+class Mouse {
+private:
+	Sword2Engine *_vm;
+
+	Common::Point _pos;
+
+	MouseUnit _mouseList[TOTAL_mouse_list];
+	uint32 _curMouse;
+
+	MenuObject _tempList[TOTAL_engine_pockets];
+	uint32 _totalTemp;
+
+	MenuObject _masterMenuList[TOTAL_engine_pockets];
+	uint32 _totalMasters;
+
+	uint8 _menuStatus[2];
+	byte *_icons[2][RDMENU_MAXPOCKETS];
+	uint8 _pocketStatus[2][RDMENU_MAXPOCKETS];
+
+	uint8 _iconCount;
+
+	// If it's NORMAL_MOUSE_ID (ie. normal pointer) then it's over a floor
+	// area (or hidden hot-zone)
+
+	uint32 _mousePointerRes;
+
+	struct MouseAnim *_mouseAnim;
+	struct MouseAnim *_luggageAnim;
+
+	uint8 _mouseFrame;
+	byte *_mouseSprite;
+	int32 *_mouseOffsets;
+	int32 *_luggageOffset;
+
+	uint32 _mouseMode;
+
+	bool _mouseStatus;		// Human 0 on/1 off
+	bool _mouseModeLocked;		// 0 not !0 mode cannot be changed from
+					// normal mouse to top menu (i.e. when
+					// carrying big objects)
+	uint32 _realLuggageItem;	// Last minute for pause mode
+	uint32 _currentLuggageResource;
+	uint32 _oldButton;		// For the re-click stuff - must be
+					// the same button you see
+	uint32 _buttonClick;
+	uint32 _pointerTextBlocNo;
+	uint32 _playerActivityDelay;	// Player activity delay counter
+
+	bool _examiningMenuIcon;
+
+	// Set by checkMouseList()
+	uint32 _mouseTouching;
+	uint32 _oldMouseTouching;
+
+	uint32 _menuSelectedPos;
+
+	void decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff = 0, int yOff = 0);
+
+	int32 setMouseAnim(byte *ma, int32 size, int32 mouseFlash);
+	int32 setLuggageAnim(byte *la, int32 size);
+
+	void clearIconArea(int menu, int pocket, Common::Rect *r);
+
+public:
+	Mouse(Sword2Engine *vm);
+	~Mouse();
+
+	void getPos(int &x, int &y);
+	void setPos(int x, int y);
+
+	bool getMouseStatus() { return _mouseStatus; }
+	uint32 getMouseTouching() { return _mouseTouching; }
+	void setMouseTouching(uint32 touching) { _mouseTouching = touching; }
+
+	void pauseGame();
+	void unpauseGame();
+
+	void setMouse(uint32 res);
+	void setLuggage(uint32 res);
+
+	void setObjectHeld(uint32 res);
+
+	void resetMouseList();
+
+	void registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit);
+	void registerPointerText(int32 text_id);
+
+	void createPointerText(uint32 text_id, uint32 pointer_res);
+	void clearPointerText();
+
+	void drawMouse();
+	int32 animateMouse();
+
+	void processMenu();
+
+	void addMenuObject(MenuObject *obj);
+	void buildMenu();
+	void buildSystemMenu();
+
+	int32 showMenu(uint8 menu);
+	int32 hideMenu(uint8 menu);
+	int32 setMenuIcon(uint8 menu, uint8 pocket, byte *icon);
+
+	void closeMenuImmediately();
+
+	void refreshInventory();
+
+	void startConversation();
+	void endConversation();
+
+	void hideMouse();
+	void noHuman();
+	void addHuman();
+
+	void resetPlayerActivityDelay() { _playerActivityDelay = 0; }
+	void monitorPlayerActivity();
+	void checkPlayerActivity(uint32 seconds);
+
+	void mouseOnOff();
+	uint32 checkMouseList();
+	void mouseEngine();
+
+	void normalMouse();
+	void menuMouse();
+	void dragMouse();
+	void systemMenuMouse();
+
+	int menuClick(int menu_items);
+};
+
 } // End of namespace Sword2
 
 #endif

Index: resman.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/resman.cpp,v
retrieving revision 1.105
retrieving revision 1.106
diff -u -d -r1.105 -r1.106
--- resman.cpp	8 Feb 2005 08:32:49 -0000	1.105
+++ resman.cpp	19 Feb 2005 14:02:12 -0000	1.106
@@ -28,7 +28,6 @@
 #include "sword2/resman.h"
 #include "sword2/router.h"
 #include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
 
 #define Debug_Printf _vm->_debugger->DebugPrintf
 
@@ -870,7 +869,7 @@
 	_vm->_sound->stopMusic(true);
 
 	textRes = openResource(2283);
-	_vm->displayMsg(_vm->fetchTextLine(textRes, 5 + cd) + 2, 0);
+	_vm->_screen->displayMsg(_vm->fetchTextLine(textRes, 5 + cd) + 2, 0);
 	closeResource(2283);
 
 	// The original code probably determined automagically when the correct

Index: router.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/router.cpp,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- router.cpp	17 Jan 2005 10:57:11 -0000	1.45
+++ router.cpp	19 Feb 2005 14:02:12 -0000	1.46
@@ -79,7 +79,6 @@
 #include "sword2/logic.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
@@ -2367,7 +2366,7 @@
 	// lines
 
 	for (i = 0; i < _nBars; i++)
-		_vm->_graphics->drawLine(_bars[i].x1, _bars[i].y1, _bars[i].x2, _bars[i].y2, 254);
+		_vm->_screen->drawLine(_bars[i].x1, _bars[i].y1, _bars[i].x2, _bars[i].y2, 254);
 
 	// nodes
 
@@ -2377,8 +2376,8 @@
 }
 
 void Router::plotCross(int16 x, int16 y, uint8 colour) {
-	_vm->_graphics->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
-	_vm->_graphics->drawLine(x + 1, y - 1, x - 1, y + 1, colour);	
+	_vm->_screen->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
+	_vm->_screen->drawLine(x + 1, y - 1, x - 1, y + 1, colour);	
 }
 
 void Router::loadWalkGrid(void) {

Index: save_rest.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/save_rest.cpp,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- save_rest.cpp	28 Jan 2005 16:33:11 -0000	1.65
+++ save_rest.cpp	19 Feb 2005 14:02:12 -0000	1.66
@@ -34,6 +34,7 @@
 #include "sword2/interpreter.h"
 #include "sword2/logic.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/sound.h"
 
@@ -115,13 +116,14 @@
 
 void Sword2Engine::fillSaveBuffer(byte *buffer, uint32 size, byte *desc) {
 	// Set up the _saveGameHeader. Checksum gets filled in last of all.
+	ScreenInfo *screenInfo = _screen->getScreenInfo();
 
 	strcpy(_saveGameHeader.description, (char *) desc);
 	_saveGameHeader.varLength = _resman->fetchLen(1);
-	_saveGameHeader.screenId = _thisScreen.background_layer_id;
+	_saveGameHeader.screenId = screenInfo->background_layer_id;
 	_saveGameHeader.runListId = _logic->getRunList();
-	_saveGameHeader.feet_x = _thisScreen.feet_x;
-	_saveGameHeader.feet_y	= _thisScreen.feet_y;
+	_saveGameHeader.feet_x = screenInfo->feet_x;
+	_saveGameHeader.feet_y	= screenInfo->feet_y;
 	_saveGameHeader.music_id = _sound->getLoopingMusicId();
 
 	memcpy(&_saveGameHeader.player_hub, _resman->openResource(CUR_PLAYER_ID) + sizeof(StandardHeader), sizeof(ObjectHub));
@@ -205,7 +207,7 @@
 
 	// Force the game engine to pick a cursor. This appears to be needed
 	// when using the -x command-line option to restore a game.
-	_mouseTouching = 1;
+	_mouse->setMouseTouching(1);
 	return errorCode;
 }
 
@@ -304,16 +306,18 @@
 	pars[1] = 1;
 	_logic->fnInitBackground(pars);
 
+	ScreenInfo *screenInfo = _screen->getScreenInfo();
+
 	// So palette not restored immediately after control panel - we want to
 	// fade up instead!
-	_thisScreen.new_palette = 99;
+	screenInfo->new_palette = 99;
 
 	// These need setting after the defaults get set in fnInitBackground.
 	// Remember that these can change through the game, so need saving &
 	// restoring too.
 
-	_thisScreen.feet_x = _saveGameHeader.feet_x;
-	_thisScreen.feet_y = _saveGameHeader.feet_y;
+	screenInfo->feet_x = _saveGameHeader.feet_x;
+	screenInfo->feet_y = _saveGameHeader.feet_y;
 
 	// Start the new run list
 	_logic->expressChangeSession(_saveGameHeader.runListId);
@@ -321,15 +325,14 @@
 	// Force in the new scroll position, so unsightly scroll-catch-up does
 	// not occur when screen first draws after returning from restore panel
 
-	// set '_thisScreen's record of player position
-	// - ready for setScrolling()
+	// Set the screen record of player position - ready for setScrolling()
 
-	_thisScreen.player_feet_x = _saveGameHeader.mega.feet_x;
-	_thisScreen.player_feet_y = _saveGameHeader.mega.feet_y;
+	screenInfo->player_feet_x = _saveGameHeader.mega.feet_x;
+	screenInfo->player_feet_y = _saveGameHeader.mega.feet_y;
 
 	// if this screen is wide, recompute the scroll offsets now
-	if (_thisScreen.scroll_flag)
-		setScrolling();
+	if (screenInfo->scroll_flag)
+		_screen->setScrolling();
 
 	// Any music required will be started after we've returned from
 	// restoreControl() - see systemMenuMouse() in mouse.cpp!

Index: scroll.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/scroll.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- scroll.cpp	28 Jan 2005 16:33:11 -0000	1.22
+++ scroll.cpp	19 Feb 2005 14:02:13 -0000	1.23
@@ -21,7 +21,6 @@
 #include "common/stdafx.h"
 #include "sword2/sword2.h"
 #include "sword2/defs.h"
-#include "sword2/interpreter.h"
 #include "sword2/logic.h"
 
 namespace Sword2 {
@@ -30,11 +29,22 @@
 #define MAX_SCROLL_DISTANCE 8
 
 /**
+ * Sets the scroll target position for the end of the game cycle. The driver
+ * will then automatically scroll as many times as it can to reach this
+ * position in the allotted time.
+ */
+
+void Screen::setScrollTarget(int16 sx, int16 sy) {
+	_scrollXTarget = sx;
+	_scrollYTarget = sy;
+}
+
+/**
  * If the room is larger than the physical screen, this function is called
  * every game cycle to update the scroll offsets.
  */
 
-void Sword2Engine::setScrolling(void) {
+void Screen::setScrolling() {
 	// Normally we aim to get George's feet at (320,250) from top left
 	// of screen window
 	// feet_x = 128 + 320

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sound.cpp,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- sound.cpp	8 Feb 2005 08:32:49 -0000	1.53
+++ sound.cpp	19 Feb 2005 14:02:13 -0000	1.54
@@ -82,6 +82,20 @@
 	}
 }
 
+void Sound::setReverseStereo(bool reverse) {
+	if (reverse != _reverseStereo) {
+		_reverseStereo = reverse;
+
+		for (int i = 0; i < FXQ_LENGTH; i++) {
+			if (!_fxQueue[i].resource)
+				continue;
+
+			_fxQueue[i].pan = -_fxQueue[i].pan;
+			_vm->_mixer->setChannelBalance(_fxQueue[i].handle, _fxQueue[i].pan);
+		}
+	}
+}
+
 /**
  * Stop all sounds, close their resources and clear the FX queue.
  */
@@ -190,6 +204,9 @@
 			volume = (volume * SoundMixer::kMaxChannelVolume) / 16;
 			pan = (pan * 127) / 16;
 
+			if (isReverseStereo())
+				pan = -pan;
+
 			_fxQueue[i].resource = res;
 			_fxQueue[i].data = data + sizeof(StandardHeader);
 			_fxQueue[i].len = len;

Index: sound.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sound.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- sound.h	8 Feb 2005 08:32:49 -0000	1.15
+++ sound.h	19 Feb 2005 14:02:13 -0000	1.16
@@ -197,7 +197,7 @@
 	void clearFxQueue();
 	void processFxQueue();
 
-	void setReverseStereo(bool reverse) { _reverseStereo = reverse; }
+	void setReverseStereo(bool reverse);
 	bool isReverseStereo() const { return _reverseStereo; }
 
 	void muteSpeech(bool mute);
@@ -228,7 +228,7 @@
 	int32 playFx(FxQueueEntry *fx);
 	int32 playFx(PlayingSoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, SoundMixer::SoundType soundType);
 	int32 stopFx(int32 i);
-	int32 setFxIdVolumePan(int32 id, int vol, int pan = -1);
+	int32 setFxIdVolumePan(int32 id, int vol, int pan = 255);
 
 	int32 getSpeechStatus();
 	int32 amISpeaking();

Index: speech.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/speech.cpp,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -d -r1.70 -r1.71
--- speech.cpp	28 Jan 2005 16:33:11 -0000	1.70
+++ speech.cpp	19 Feb 2005 14:02:13 -0000	1.71
@@ -30,7 +30,6 @@
 #include "sword2/maketext.h"
 #include "sword2/memory.h"
 #include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 
@@ -126,8 +125,10 @@
 			
 	// Adjust the text coords for RDSPR_DISPLAYALIGN
 
-	_textX -= _vm->_thisScreen.scroll_offset_x;
-	_textY -= _vm->_thisScreen.scroll_offset_y;
+	ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+	
+	_textX -= screenInfo->scroll_offset_x;
+	_textY -= screenInfo->scroll_offset_y;
 }
 
 /**

Index: sword2.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sword2.cpp,v
retrieving revision 1.133
retrieving revision 1.134
diff -u -d -r1.133 -r1.134
--- sword2.cpp	28 Jan 2005 16:33:12 -0000	1.133
+++ sword2.cpp	19 Feb 2005 14:02:13 -0000	1.134
@@ -36,9 +36,9 @@
 #include "sword2/logic.h"
 #include "sword2/maketext.h"
 #include "sword2/memory.h"
+#include "sword2/mouse.h"
 #include "sword2/resman.h"
 #include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
 
 #ifdef _WIN32_WCE
 extern bool isSmartphone(void);
@@ -121,60 +121,21 @@
 	_bootParam = ConfMan.getInt("boot_param");
 	_saveSlot = ConfMan.getInt("save_slot");
 
-	_debugger = NULL;
-	_graphics = NULL;
+	_memory = NULL;
+	_resman = NULL;
 	_sound = NULL;
-	_gui = NULL;
-	_fontRenderer = NULL;
+	_screen = NULL;
+	_mouse = NULL;
 	_logic = NULL;
-	_resman = NULL;
-	_memory = NULL;
+	_fontRenderer = NULL;
+	_gui = NULL;
+	_debugger = NULL;
 
 	_keyboardEvent.pending = false;
 	_mouseEvent.pending = false;
 
-	_lastPaletteRes = 0;
-
-	_largestLayerArea = 0;
-	_largestSpriteArea = 0;
-
-	strcpy(_largestLayerInfo,  "largest layer:  none registered");
-	strcpy(_largestSpriteInfo, "largest sprite: none registered");
-
-	_fps = 0;
-	_cycleTime = 0;
-	_frameCount = 0;
-
 	_wantSfxDebug = false;
 
-	// For the menus
-
-	_totalTemp = 0;
-	memset(_tempList, 0, sizeof(_tempList));
-
-	_totalMasters = 0;
-	memset(_masterMenuList, 0, sizeof(_masterMenuList));
-	memset(&_thisScreen, 0, sizeof(_thisScreen));
-	memset(_mouseList, 0, sizeof(_mouseList));
-
-	_mouseX = _mouseY = 0;
-	_mouseTouching = 0;
-	_oldMouseTouching = 0;
-	_menuSelectedPos = 0;
-	_examiningMenuIcon = false;
-	_mousePointerRes = 0;
-	_mouseMode = 0;
-	_mouseStatus = false;
-	_mouseModeLocked = false;
-	_currentLuggageResource = 0;
-	_oldButton = 0;
-	_buttonClick = 0;
-	_pointerTextBlocNo = 0;
-	_playerActivityDelay = 0;
-	_realLuggageItem = 0;
-
-	_scrollFraction = 16;
-
 #ifdef SWORD2_DEBUG
 	_stepOneCycle = false;
 	_renderSkip = false;
@@ -190,10 +151,11 @@
 
 Sword2Engine::~Sword2Engine() {
 	delete _debugger;
-	delete _graphics;
 	delete _sound;
 	delete _gui;
 	delete _fontRenderer;
+	delete _screen;
+	delete _mouse;
 	delete _logic;
 	delete _resman;
 	delete _memory;
@@ -233,7 +195,7 @@
 
 	_system->beginGFXTransaction();
 		initCommonGFX(detector);
-		_graphics = new Graphics(this, 640, 480);
+		_screen = new Screen(this, 640, 480);
 	_system->endGFXTransaction();
 
 	// Create the debugger as early as possible (but not before the
@@ -249,6 +211,7 @@
 	_fontRenderer = new FontRenderer(this);
 	_gui = new Gui(this);
 	_sound = new Sound(this);
+	_mouse = new Mouse(this);
 
 	// Setup mixer
 	if (!_mixer->isReady())
@@ -278,7 +241,7 @@
 		if (saveExists(_saveSlot))
 			restoreGame(_saveSlot);
 		else {
-			setMouse(NORMAL_MOUSE_ID);
+			_mouse->setMouse(NORMAL_MOUSE_ID);
 			if (!_gui->restoreControl())
 				startGame();
 		}
@@ -286,7 +249,7 @@
 		int32 pars[2] = { 221, FX_LOOP };
 		bool result;
 
-		setMouse(NORMAL_MOUSE_ID);
+		_mouse->setMouse(NORMAL_MOUSE_ID);
 		_logic->fnPlayMusic(pars);
 		result = _gui->startControl();
 
@@ -302,7 +265,7 @@
 	} else
 		startGame();
 
-	_graphics->initialiseRenderCycle();
+	_screen->initialiseRenderCycle();
 	
 	return 0;
 }
@@ -374,9 +337,9 @@
 		// display once every 4 game-cycles
 
 		if (!_renderSkip || (_gameCycle % 4) == 0)
-			buildDisplay();
+			_screen->buildDisplay();
 #else
-		buildDisplay();
+		_screen->buildDisplay();
 #endif
 	}
 	
@@ -433,8 +396,7 @@
 			break;
 		case OSystem::EVENT_MOUSEMOVE:
 			if (!(_eventFilter & RD_KEYDOWN)) {
-				_mouseX = event.mouse.x;
-				_mouseY = event.mouse.y - RDMENU_MENUDEEP;
+				_mouse->setPos(event.mouse.x, event.mouse.y - RDMENU_MENUDEEP);
 			}
 			break;
 		case OSystem::EVENT_LBUTTONDOWN:
@@ -493,8 +455,8 @@
 			// will fill thrm through fnRegisterFrame() and
 			// fnRegisterMouse().
 
-			resetRenderLists();
-			resetMouseList();
+			_screen->resetRenderLists();
+			_mouse->resetMouseList();
 
 			// Keep going as long as new lists keep getting put in
 			// - i.e. screen changes.
@@ -505,10 +467,12 @@
 	}
 
 	// If this screen is wide, recompute the scroll offsets every cycle
-	if (_thisScreen.scroll_flag)
-		setScrolling();
+	ScreenInfo *screenInfo = _screen->getScreenInfo();
 
-	mouseEngine();
+	if (screenInfo->scroll_flag)
+		_screen->setScrolling();
+
+	_mouse->mouseEngine();
 	_sound->processFxQueue();
 }
 
@@ -551,26 +515,19 @@
 	while (getMillis() < time) {
 		// Make sure menu animations and fades don't suffer, but don't
 		// redraw the entire scene.
-		_graphics->processMenu();
-		_graphics->updateDisplay(false);
+		_mouse->processMenu();
+		_screen->updateDisplay(false);
 		_system->delayMillis(10);
 	}
 }
 
 void Sword2Engine::pauseGame() {
 	// Don't allow Pause while screen fading or while black
-	if (_graphics->getFadeStatus() != RDFADE_NONE)
+	if (_screen->getFadeStatus() != RDFADE_NONE)
 		return;
 	
 	_sound->pauseAllSound();
-
-	// Make the mouse cursor normal. This is the only place where we are
-	// allowed to clear the luggage this way.
-
-	clearPointerText();
-	_graphics->setLuggageAnim(NULL, 0);
-	setMouse(0);
-	_mouseTouching = 1;
+	_mouse->pauseGame();
 
 	// If level at max, turn down because palette-matching won't work
 	// when dimmed
@@ -585,22 +542,20 @@
 	// dim the palette during the pause
 
 	if (!_stepOneCycle)
-		_graphics->dimPalette();
+		_screen->dimPalette();
 #else
-	_graphics->dimPalette();
+	_screen->dimPalette();
 #endif
 
 	_gamePaused = true;
 }
 
 void Sword2Engine::unpauseGame() {
-	if (Logic::_scriptVars[OBJECT_HELD] && _realLuggageItem)
-		setLuggage(_realLuggageItem);
-
+	_mouse->unpauseGame();
 	_sound->unpauseAllSound();
 
 	// Put back game screen palette; see build_display.cpp
-	setFullPalette(-1);
+	_screen->setFullPalette(-1);
 
 	// If graphics level at max, turn up again
 	if (_graphicsLevelFudged) {
@@ -611,8 +566,8 @@
 	_gamePaused = false;
 
 	// If mouse is about or we're in a chooser menu
-	if (!_mouseStatus || _logic->_choosing)
-		setMouse(NORMAL_MOUSE_ID);
+	if (!_mouse->getMouseStatus() || _logic->_choosing)
+		_mouse->setMouse(NORMAL_MOUSE_ID);
 }
 
 uint32 Sword2Engine::getMillis() {

Index: sword2.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/sword2.h,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -d -r1.75 -r1.76
--- sword2.h	28 Jan 2005 16:33:12 -0000	1.75
+++ sword2.h	19 Feb 2005 14:02:13 -0000	1.76
@@ -36,8 +36,6 @@
 #include "sword2/build_display.h"
 #include "sword2/header.h"
 #include "sword2/icons.h"
-#include "sword2/layers.h"
-#include "sword2/mouse.h"
 #include "sword2/object.h"
 #include "sword2/save_rest.h"
 
@@ -56,6 +54,8 @@
 class MemoryManager;
 class ResourceManager;
 class Sound;
+class Screen;
+class Mouse;
 class Graphics;
 class Logic;
 class FontRenderer;
@@ -96,67 +96,6 @@
 	uint32 _bootParam;
 	int32 _saveSlot;
 
-	// structure filled out by each object to register its graphic printing
-	// requrements
-
-	struct BuildUnit {
-		int16 x;
-		int16 y;
-		uint16 scaled_width;
-		uint16 scaled_height;
-		int16 sort_y;
-		uint32 anim_resource;
-		uint16 anim_pc;
-
-		// Denotes a scaling sprite at print time - and holds the
-		// scaling value for the shrink routine
-
-		uint16 scale;
-
-		// Non-zero means this item is a layer - retrieve from
-		// background layer and send to special renderer
-
-		uint16 layer_number;
-
-		// True means we want this frame to be affected by the shading
-		// mask
-
-		bool shadingFlag;
-	};
-
-	BuildUnit _bgp0List[MAX_bgp0_sprites];
-	BuildUnit _bgp1List[MAX_bgp1_sprites];
-	BuildUnit _backList[MAX_back_sprites];
-	BuildUnit _sortList[MAX_sort_sprites];
-	BuildUnit _foreList[MAX_fore_sprites];
-	BuildUnit _fgp0List[MAX_fgp0_sprites];
-	BuildUnit _fgp1List[MAX_fgp1_sprites];
-
-	// Holds the order of the sort list, i.e. the list stays static and we
-	// sort this array.
-
-	uint16 _sortOrder[MAX_sort_sprites];
-
-	// Last palette used - so that we can restore the correct one after a
-	// pause (which dims the screen) and it's not always the main screen
-	// palette that we want, eg. during the eclipse
-
-	// This flag gets set in startNewPalette() and setFullPalette()
-
-	uint32 _lastPaletteRes;
-
-	void drawBackPar0Frames();
-	void drawBackPar1Frames();
-	void drawBackFrames();
-	void drawSortFrames(byte *file);
-	void drawForeFrames();
-	void drawForePar0Frames();
-	void drawForePar1Frames();
-
-	void startNewPalette();
-	void processLayer(byte *file, uint32 layer_number);
-	void processImage(BuildUnit *build_unit);
-
 	void getPlayerStructures();
 	void putPlayerStructures();
 
@@ -168,12 +107,6 @@
 	void pauseGame();
 	void unpauseGame();
 
-	MenuObject _tempList[TOTAL_engine_pockets];
-	uint32 _totalTemp;
-
-	MenuObject _masterMenuList[TOTAL_engine_pockets];
-	uint32 _totalMasters;
-
 	uint32 _totalStartups;
 	uint32 _totalScreenManagers;
 	uint32 _startRes;
@@ -208,7 +141,8 @@
 	MemoryManager *_memory;
 	ResourceManager	*_resman;
 	Sound *_sound;
-	Graphics *_graphics;
+	Screen *_screen;
+	Mouse *_mouse;
 	Logic *_logic;
 	FontRenderer *_fontRenderer;
 	Gui *_gui;
@@ -221,9 +155,6 @@
 	uint32 _controlsFontId;
 	uint32 _redFontId;
 
-	int16 _mouseX;
-	int16 _mouseY;
-
 	uint32 setEventFilter(uint32 filter);
 
 	void parseEvents();
@@ -232,36 +163,6 @@
 	MouseEvent *mouseEvent();
 	KeyboardEvent *keyboardEvent();
 
-	void resetRenderLists();
-	void buildDisplay();
-	void displayMsg(byte *text, int time);
-	void setFullPalette(int32 palRes);
-
-	int32 registerFrame(int32 *params);
-	void registerFrame(int32 *params, BuildUnit *build_unit);
-
-	// The debugger wants to access these
-
-	uint32 _curBgp0;
-	uint32 _curBgp1;
-	uint32 _curBack;
-	uint32 _curSort;
-	uint32 _curFore;
-	uint32 _curFgp0;
-	uint32 _curFgp1;
-
-	// Debugging stuff
-
-	uint32 _largestLayerArea;
-	uint32 _largestSpriteArea;
-	char _largestLayerInfo[128];
-	char _largestSpriteInfo[128];
-
-	// 'frames per second' counting stuff
-	uint32 _fps;
-	uint32 _cycleTime;
-	uint32 _frameCount;
-
 	bool _wantSfxDebug;
 
 	int32 _gameCycle;
@@ -271,74 +172,10 @@
 	bool _stepOneCycle;
 #endif
 
-	int32 initBackground(int32 res, int32 new_palette);
-
 #if RIGHT_CLICK_CLEARS_LUGGAGE
 	bool heldIsInInventory();
 #endif
 
-	int menuClick(int menu_items);
-
-	void addMenuObject(MenuObject *obj);
-	void buildMenu();
-	void buildSystemMenu();
-
-	// _thisScreen describes the current back buffer and its in-game scroll
-	// positions, etc.
-
-	ScreenInfo _thisScreen;
-
-	uint32 _curMouse;
-	MouseUnit _mouseList[TOTAL_mouse_list];
-
-	// Set by checkMouseList()
-	uint32 _mouseTouching;
-	uint32 _oldMouseTouching;
-
-	uint32 _menuSelectedPos;
-
-	// If it's NORMAL_MOUSE_ID (ie. normal pointer) then it's over a floor
-	// area (or hidden hot-zone)
-
-	uint32 _mousePointerRes;
-
-	uint32 _mouseMode;
-	bool _examiningMenuIcon;
-
-	bool _mouseStatus;		// Human 0 on/1 off
-	bool _mouseModeLocked;		// 0 not !0 mode cannot be changed from
-					// normal mouse to top menu (i.e. when
-					// carrying big objects)
-	uint32 _realLuggageItem;	// Last minute for pause mode
-	uint32 _currentLuggageResource;
-	uint32 _oldButton;		// For the re-click stuff - must be
-					// the same button you see
-	uint32 _buttonClick;
-	uint32 _pointerTextBlocNo;
-	uint32 _playerActivityDelay;	// Player activity delay counter
-
-	void resetMouseList();
-
-	void normalMouse();
-	void menuMouse();
-	void dragMouse();
-	void systemMenuMouse();
-
-	void mouseOnOff();
-	uint32 checkMouseList();
-	void mouseEngine();
-
-	void setMouse(uint32 res);
-	void setLuggage(uint32 res);
-
-	void clearPointerText();
-
-	void createPointerText(uint32 text_id, uint32 pointer_res);
-	void monitorPlayerActivity();
-	void noHuman();
-
-	void registerMouse(ObjectMouse *ob_mouse);
-
 	byte *fetchPalette(byte *screenFile);
 	ScreenHeader *fetchScreenHeader(byte *screenFile);
 	LayerHeader *fetchLayerHeader(byte *screenFile, uint16 layerNo);
@@ -395,10 +232,6 @@
 	uint32 restoreFromBuffer(byte *buffer, uint32 size);
 	uint32 findBufferSize();
 
-	uint8 _scrollFraction;
-
-	void setScrolling();
-
 	bool _gamePaused;
 	bool _graphicsLevelFudged;
 

Index: walker.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword2/walker.cpp,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- walker.cpp	28 Jan 2005 16:33:12 -0000	1.44
+++ walker.cpp	19 Feb 2005 14:02:13 -0000	1.45
@@ -31,7 +31,6 @@
 #include "sword2/memory.h"
 #include "sword2/resman.h"
 #include "sword2/router.h"
-#include "sword2/driver/d_draw.h"
 
 namespace Sword2 {
 





More information about the Scummvm-git-logs mailing list