[Scummvm-cvs-logs] SF.net SVN: scummvm: [20652] scummvm/trunk/engines/sword2

eriktorbjorn at users.sourceforge.net eriktorbjorn at users.sourceforge.net
Sun Feb 12 11:40:01 CET 2006


Revision: 20652
Author:   eriktorbjorn
Date:     2006-02-12 11:38:26 -0800 (Sun, 12 Feb 2006)
ViewCVS:  http://svn.sourceforge.net/scummvm?rev=20652&view=rev

Log Message:
-----------
Oops. Forgot to tell SVN to actually *move* the files. I'll get the hang of it
eventually.

Added Paths:
-----------
    scummvm/trunk/engines/sword2/saveload.cpp
    scummvm/trunk/engines/sword2/saveload.h
    scummvm/trunk/engines/sword2/screen.cpp
    scummvm/trunk/engines/sword2/screen.h

Removed Paths:
-------------
    scummvm/trunk/engines/sword2/build_display.cpp
    scummvm/trunk/engines/sword2/build_display.h
    scummvm/trunk/engines/sword2/save_rest.cpp
    scummvm/trunk/engines/sword2/save_rest.h
Deleted: scummvm/trunk/engines/sword2/build_display.cpp
===================================================================
--- scummvm/trunk/engines/sword2/build_display.cpp	2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/build_display.cpp	2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,1070 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2006 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-// ---------------------------------------------------------------------------
-// BUILD_DISPLAY.CPP	like the old spr_engi but slightly more aptly named
-// ---------------------------------------------------------------------------
-
-#include "common/stdafx.h"
-#include "common/system.h"
-
-#include "sword2/sword2.h"
-#include "sword2/console.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/maketext.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-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();
-
-		// should be reset to zero at start of each screen change
-		_largestLayerArea = 0;
-		_largestSpriteArea = 0;
-	}
-
-	// Does this ever happen?
-	if (!_thisScreen.background_layer_id)
-		return;
-
-	// there is a valid screen to run
-
-	setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
-	_vm->_mouse->animateMouse();
-	startRenderCycle();
-
-	byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
-
-	MultiScreenHeader screenLayerTable;
-
-	screenLayerTable.read(file + ResHeader::size());
-
-	// Render at least one frame, but if the screen is scrolling, and if
-	// there is time left, we will render extra frames to smooth out the
-	// scrolling.
-
-	do {
-		// first background parallax + related anims
-		if (screenLayerTable.bg_parallax[0]) {
-			renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0);
-			drawBackPar0Frames();
-		}
-
-		// second background parallax + related anims
-		if (screenLayerTable.bg_parallax[1]) {
-			renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1);
-			drawBackPar1Frames();
-		}
-
-		// normal backround layer (just the one!)
-		renderParallax(_vm->fetchBackgroundLayer(file), 2);
-
-		// sprites & layers
-		drawBackFrames();	// background sprites
-		drawSortFrames(file);	// sorted sprites & layers
-		drawForeFrames();	// foreground sprites
-
-		// first foreground parallax + related anims
-
-		if (screenLayerTable.fg_parallax[0]) {
-			renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3);
-			drawForePar0Frames();
-		}
-
-		// second foreground parallax + related anims
-
-		if (screenLayerTable.fg_parallax[1]) {
-			renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4);
-			drawForePar1Frames();
-		}
-
-		_vm->_debugger->drawDebugGraphics();
-		_vm->_fontRenderer->printTextBlocs();
-		_vm->_mouse->processMenu();
-
-		updateDisplay();
-
-		_frameCount++;
-		if (_vm->getMillis() > _cycleTime) {
-			_fps = _frameCount;
-			_frameCount = 0;
-			_cycleTime = _vm->getMillis() + 1000;
-		}
-	} while (!endRenderCycle());
-
-	_vm->_resman->closeResource(_thisScreen.background_layer_id);
-}
-
-/**
- * Fades down and displays a message on the screen.
- * @param text The message
- * @param time The number of seconds to display the message, or 0 to display it
- *             until the user clicks the mouse or presses a key.
- */
-
-void Screen::displayMsg(byte *text, int time) {
-	byte pal[256 * 4];
-	byte oldPal[256 * 4];
-
-	debug(2, "DisplayMsg: %s", text);
-
-	if (getFadeStatus() != RDFADE_BLACK) {
-		fadeDown();
-		waitForFade();
-	}
-
-	_vm->_mouse->setMouse(0);
-	_vm->_mouse->setLuggage(0);
-	_vm->_mouse->closeMenuImmediately();
-
-	clearScene();
-
-	byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);
-
-	FrameHeader frame;
-
-	frame.read(text_spr);
-
-	SpriteInfo spriteInfo;
-
-	spriteInfo.x = _screenWide / 2 - frame.width / 2;
-	if (!time)
-		spriteInfo.y = _screenDeep / 2 - frame.height / 2 - MENUDEEP;
-	else
-		spriteInfo.y = 400 - frame.height;
-	spriteInfo.w = frame.width;
-	spriteInfo.h = frame.height;
-	spriteInfo.scale = 0;
-	spriteInfo.scaledWidth = 0;
-	spriteInfo.scaledHeight	= 0;
-	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
-	spriteInfo.blend = 0;
-	spriteInfo.data = text_spr + FrameHeader::size();
-	spriteInfo.colourTable = 0;
-
-	uint32 rv = drawSprite(&spriteInfo);
-	if (rv)
-		error("Driver Error %.8x (in DisplayMsg)", rv);
-
-	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;
-
-	setPalette(0, 256, pal, RDPAL_FADE);
-	fadeUp();
-	free(text_spr);
-	waitForFade();
-
-	if (time > 0) {
-		uint32 targetTime = _vm->getMillis() + (time * 1000);
-		_vm->sleepUntil(targetTime);
-	} else {
-		while (!_vm->_quit) {
-			MouseEvent *me = _vm->mouseEvent();
-			if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
-				break;
-
-			if (_vm->keyboardEvent())
-				break;
-
-			updateDisplay();
-			_vm->_system->delayMillis(50);
-		}
-	}
-
-	fadeDown();
-	waitForFade();
-	clearScene();
-	setPalette(0, 256, oldPal, RDPAL_FADE);
-	fadeUp();
-}
-
-void Screen::drawBackPar0Frames() {
-	// frame attached to 1st background parallax
-	for (uint i = 0; i < _curBgp0; i++)
-		processImage(&_bgp0List[i]);
-}
-
-void Screen::drawBackPar1Frames() {
-	// frame attached to 2nd background parallax
-	for (uint i = 0; i < _curBgp1; i++)
-		processImage(&_bgp1List[i]);
-}
-
-void Screen::drawBackFrames() {
-	// background sprite, fixed to main background
-	for (uint i = 0; i < _curBack; i++)
-		processImage(&_backList[i]);
-}
-
-void Screen::drawSortFrames(byte *file) {
-	uint i, j;
-
-	// Sort the sort list. Used to be a separate function, but it was only
-	// called once, right before calling drawSortFrames().
-
-	if (_curSort > 1) {
-		for (i = 0; i < _curSort - 1; i++) {
-			for (j = 0; j < _curSort - 1; j++) {
-				if (_sortList[_sortOrder[j]].sort_y > _sortList[_sortOrder[j + 1]].sort_y) {
-					SWAP(_sortOrder[j], _sortOrder[j + 1]);
-				}
-			}
-		}
-	}
-
-	// Draw the sorted frames - layers, shrinkers & normal flat sprites
-
-	for (i = 0; i < _curSort; i++) {
-		if (_sortList[_sortOrder[i]].layer_number) {
-			// it's a layer - minus 1 for true layer number
-			// we need to know from the BuildUnit because the
-			// layers will have been sorted in random order
-			processLayer(file, _sortList[_sortOrder[i]].layer_number - 1);
-		} else {
-			// it's a sprite
-			processImage(&_sortList[_sortOrder[i]]);
-		}
-	}
-}
-
-void Screen::drawForeFrames() {
-	// foreground sprite, fixed to main background
-	for (uint i = 0; i < _curFore; i++)
-		processImage(&_foreList[i]);
-}
-
-void Screen::drawForePar0Frames() {
-	// frame attached to 1st foreground parallax
-	for (uint i = 0; i < _curFgp0; i++)
-		processImage(&_fgp0List[i]);
-}
-
-void Screen::drawForePar1Frames() {
-	// frame attached to 2nd foreground parallax
-	for (uint i = 0; i < _curFgp1; i++)
-		processImage(&_fgp1List[i]);
-}
-
-void Screen::processLayer(byte *file, uint32 layer_number) {
-	LayerHeader layer_head;
-
-	layer_head.read(_vm->fetchLayerHeader(file, layer_number));
-
- 	SpriteInfo spriteInfo;
-
-	spriteInfo.x = layer_head.x;
-	spriteInfo.y = layer_head.y;
-	spriteInfo.w = layer_head.width;
-	spriteInfo.scale = 0;
-	spriteInfo.scaledWidth = 0;
-	spriteInfo.scaledHeight = 0;
-	spriteInfo.h = layer_head.height;
-	spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST;
-	spriteInfo.blend = 0;
-	spriteInfo.data = file + ResHeader::size() + layer_head.offset;
-	spriteInfo.colourTable = 0;
-
-	// check for largest layer for debug info
-
-	uint32 current_layer_area = layer_head.width * layer_head.height;
-
-	if (current_layer_area > _largestLayerArea) {
-		byte buf[NAME_LEN];
-
-		_largestLayerArea = current_layer_area;
-		sprintf(_largestLayerInfo,
-			"largest layer:  %s layer(%d) is %dx%d",
-			_vm->_resman->fetchName(_thisScreen.background_layer_id, buf),
-			layer_number, layer_head.width, layer_head.height);
-	}
-
-	uint32 rv = drawSprite(&spriteInfo);
-	if (rv)
-		error("Driver Error %.8x in processLayer(%d)", rv, layer_number);
-}
-
-void Screen::processImage(BuildUnit *build_unit) {
-	byte *file = _vm->_resman->openResource(build_unit->anim_resource);
-	byte *colTablePtr = NULL;
-
-	byte *frame = _vm->fetchFrameHeader(file, build_unit->anim_pc);
-
-	AnimHeader anim_head;
-	CdtEntry cdt_entry;
-	FrameHeader frame_head;
-
-	anim_head.read(_vm->fetchAnimHeader(file));
-	cdt_entry.read(_vm->fetchCdtEntry(file, build_unit->anim_pc));
-	frame_head.read(frame);
-
-	// so that 0-colour is transparent
-	uint32 spriteType = RDSPR_TRANS;
-
-	if (anim_head.blend)
-		spriteType |= RDSPR_BLEND;
-
-	// if the frame is to be flipped (only really applicable to frames
-	// using offsets)
-	if (cdt_entry.frameType & FRAME_FLIPPED)
-		spriteType |= RDSPR_FLIP;
-
-	if (cdt_entry.frameType & FRAME_256_FAST) {
-		// scaling, shading & blending don't work with RLE256FAST
-		// but the same compression can be decompressed using the
-		// RLE256 routines!
-
-		// NOTE: If this restriction refers to drawSprite(), I don't
-		// think we have it any more. But I'm not sure.
-
-		if (build_unit->scale || anim_head.blend || build_unit->shadingFlag)
-			spriteType |= RDSPR_RLE256;
-		else
-			spriteType |= RDSPR_RLE256FAST;
-	} else {
-		switch (anim_head.runTimeComp) {
-		case NONE:
-			spriteType |= RDSPR_NOCOMPRESSION;
-			break;
-		case RLE256:
-			spriteType |= RDSPR_RLE256;
-			break;
-		case RLE16:
-			spriteType |= RDSPR_RLE16;
-			// points to just after last cdt_entry, ie.
-			// start of colour table
-			colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size();
-			break;
-		}
-	}
-
-	// if we want this frame to be affected by the shading mask,
-	// add the status bit
-	if (build_unit->shadingFlag)
-		spriteType |= RDSPR_SHADOW;
-
-	SpriteInfo spriteInfo;
-
-	spriteInfo.x = build_unit->x;
-	spriteInfo.y = build_unit->y;
-	spriteInfo.w = frame_head.width;
-	spriteInfo.h = frame_head.height;
-	spriteInfo.scale = build_unit->scale;
-	spriteInfo.scaledWidth = build_unit->scaled_width;
-	spriteInfo.scaledHeight	= build_unit->scaled_height;
-	spriteInfo.type = spriteType;
-	spriteInfo.blend = anim_head.blend;
-	// points to just after frame header, ie. start of sprite data
-	spriteInfo.data = frame + FrameHeader::size();
-	spriteInfo.colourTable = colTablePtr;
-
-	// check for largest layer for debug info
-	uint32 current_sprite_area = frame_head.width * frame_head.height;
-
-	if (current_sprite_area > _largestSpriteArea) {
-		byte buf[NAME_LEN];
-
-		_largestSpriteArea = current_sprite_area;
-		sprintf(_largestSpriteInfo,
-			"largest sprite: %s frame(%d) is %dx%d",
-			_vm->_resman->fetchName(build_unit->anim_resource, buf),
-			build_unit->anim_pc,
-			frame_head.width,
-			frame_head.height);
-	}
-
-	if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) { // see anims.cpp
-		// bring the anim into the visible screen
-		// but leave extra pixel at edge for box
-		if (spriteInfo.x + spriteInfo.scaledWidth >= 639)
-			spriteInfo.x = 639 - spriteInfo.scaledWidth;
-
-		if (spriteInfo.y + spriteInfo.scaledHeight >= 399)
-			spriteInfo.y = 399 - spriteInfo.scaledHeight;
-
-		if (spriteInfo.x < 1)
-			spriteInfo.x = 1;
-
-		if (spriteInfo.y < 1)
-			spriteInfo.y = 1;
-
-		// create box to surround sprite - just outside sprite box
-		_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 = drawSprite(&spriteInfo);
-	if (rv) {
-		byte buf[NAME_LEN];
-
-		error("Driver Error %.8x with sprite %s (%d) in processImage",
-			rv,
-			_vm->_resman->fetchName(build_unit->anim_resource, buf),
-			build_unit->anim_resource);
-	}
-
-	// release the anim resource
-	_vm->_resman->closeResource(build_unit->anim_resource);
-}
-
-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
-
-	_curBgp0 = 0;
-	_curBgp1 = 0;
-	_curBack = 0;
-	// beginning of sort list is setup with the special sort layers
-	_curSort = _thisScreen.number_of_layers;
-	_curFore = 0;
-	_curFgp0 = 0;
-	_curFgp1 = 0;
-
-	if (_curSort) {
-		// there are some layers - so rebuild the sort order list
-		for (uint i = 0; i < _curSort; i++)
-			_sortOrder[i] = i;
-	}
-}
-
-void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit) {
-	ObjectGraphic obGraph(ob_graph);
-	ObjectMega obMega(ob_mega);
-
-	assert(obGraph.getAnimResource());
-
-	byte *file = _vm->_resman->openResource(obGraph.getAnimResource());
-
-	AnimHeader anim_head;
-	CdtEntry cdt_entry;
-	FrameHeader frame_head;
-
-	anim_head.read(_vm->fetchAnimHeader(file));
-	cdt_entry.read(_vm->fetchCdtEntry(file, obGraph.getAnimPc()));
-	frame_head.read(_vm->fetchFrameHeader(file, obGraph.getAnimPc()));
-
-	// update player graphic details for on-screen debug info
-	if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
-		_vm->_debugger->_graphType = obGraph.getType();
-		_vm->_debugger->_graphAnimRes = obGraph.getAnimResource();
-		// counting 1st frame as 'frame 1'
-		_vm->_debugger->_graphAnimPc = obGraph.getAnimPc() + 1;
-		_vm->_debugger->_graphNoFrames = anim_head.noAnimFrames;
-	}
-
-	// fill in the BuildUnit structure for this frame
-
- 	build_unit->anim_resource = obGraph.getAnimResource();
-	build_unit->anim_pc = obGraph.getAnimPc();
-	build_unit->layer_number = 0;
-
-	// Affected by shading mask?
-	if (obGraph.getType() & SHADED_SPRITE)
-		build_unit->shadingFlag = true;
-	else
-		build_unit->shadingFlag = false;
-
-	// Check if this frame has offsets ie. this is a scalable mega frame
-
-	int scale = 0;
-
-	if (cdt_entry.frameType & FRAME_OFFSET) {
-		scale = obMega.calcScale();
-
-		// calc final render coordinates (top-left of sprite), based
-		// on feet coords & scaled offsets
-
-		// add scaled offsets to feet coords
-		build_unit->x = obMega.getFeetX() + (cdt_entry.x * scale) / 256;
-		build_unit->y = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
-
-		// Work out new width and height. Always divide by 256 after
-		// everything else, to maintain accurary
-		build_unit->scaled_width = ((scale * frame_head.width) / 256);
-		build_unit->scaled_height = ((scale * frame_head.height) / 256);
-	} else {
-		// It's a non-scaling anim. Get render coords for sprite, from cdt
-		build_unit->x = cdt_entry.x;
-		build_unit->y = cdt_entry.y;
-
-		// Get width and height
-		build_unit->scaled_width = frame_head.width;
-		build_unit->scaled_height = frame_head.height;
-	}
-
-	// either 0 or required scale, depending on whether 'scale' computed
-	build_unit->scale = scale;
-
-	// calc the bottom y-coord for sorting purposes
-	build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1;
-
-	if (ob_mouse) {
-		// passed a mouse structure, so add to the _mouseList
-		_vm->_mouse->registerMouse(ob_mouse, build_unit);
-
-	}
-
-	_vm->_resman->closeResource(obGraph.getAnimResource());
-}
-
-void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega) {
-	ObjectGraphic obGraph(ob_graph);
-
-	// check low word for sprite type
-	switch (obGraph.getType() & 0x0000ffff) {
-	case BGP0_SPRITE:
-		assert(_curBgp0 < MAX_bgp0_sprites);
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]);
-		_curBgp0++;
-		break;
-	case BGP1_SPRITE:
-		assert(_curBgp1 < MAX_bgp1_sprites);
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp1List[_curBgp1]);
-		_curBgp1++;
-		break;
-	case BACK_SPRITE:
-		assert(_curBack < MAX_back_sprites);
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_backList[_curBack]);
-		_curBack++;
-		break;
-	case SORT_SPRITE:
-		assert(_curSort < MAX_sort_sprites);
-		_sortOrder[_curSort] = _curSort;
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_sortList[_curSort]);
-		_curSort++;
-		break;
-	case FORE_SPRITE:
-		assert(_curFore < MAX_fore_sprites);
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_foreList[_curFore]);
-		_curFore++;
-		break;
-	case FGP0_SPRITE:
-		assert(_curFgp0 < MAX_fgp0_sprites);
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp0List[_curFgp0]);
-		_curFgp0++;
-		break;
-	case FGP1_SPRITE:
-		assert(_curFgp1 < MAX_fgp1_sprites);
-		registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp1List[_curFgp1]);
-		_curFgp1++;
-		break;
-	default:
-		// NO_SPRITE no registering!
-		break;
-	}
-}
-
-// FIXME:
-//
-// The original credits used a different font. I think it's stored in the
-// font.clu file, but I don't know how to interpret it.
-//
-// The original used the entire screen. This version cuts off the top and
-// bottom of the screen, because that's where the menus would usually be.
-//
-// The original had some sort of smoke effect at the bottom of the screen.
-
-enum {
-	LINE_LEFT,
-	LINE_CENTER,
-	LINE_RIGHT
-};
-
-struct CreditsLine {
-	char *str;
-	byte type;
-	int top;
-	int height;
-	byte *sprite;
-
-	CreditsLine() {
-		str = NULL;
-		sprite = NULL;
-	};
-
-	~CreditsLine() {
-		free(str);
-		free(sprite);
-		str = NULL;
-		sprite = NULL;
-	}
-};
-
-#define CREDITS_FONT_HEIGHT 25
-#define CREDITS_LINE_SPACING 20
-
-void Screen::rollCredits() {
-	uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();
-
-	// Prepare for the credits by fading down, stoping the music, etc.
-
-	_vm->_mouse->setMouse(0);
-
-	_vm->_sound->muteFx(true);
-	_vm->_sound->muteSpeech(true);
-
-	waitForFade();
-	fadeDown();
-	waitForFade();
-
-	_vm->_mouse->closeMenuImmediately();
-
-	// There are three files which I believe are involved in showing the
-	// credits:
-	//
-	// credits.bmp  - The "Smacker" logo, stored as follows:
-	//
-	//     width     2 bytes, little endian
-	//     height    2 bytes, little endian
-	//     palette   3 * 256 bytes
-	//     data      width * height bytes
-	//
-	//     Note that the maximum colour component in the palette is 0x3F.
-	//     This is the same resolution as the _paletteMatch table. I doubt
-	//     that this is a coincidence, but let's use the image palette
-	//     directly anyway, just to be safe.
-	//
-	// credits.clu  - The credits text
-	//
-	//     This is simply a text file with CRLF line endings.
-	//     '^' is not shown, but used to mark the center of the line.
-	//     '@' is used as a placeholder for the "Smacker" logo. At least
-	//     when it appears alone.
-	//     Remaining lines are centered.
-	//     The German version also contains character code 9 for no
-	//     apparent reason. We ignore them.
-	//
-	// fonts.clu    - The credits font?
-	//
-	//     FIXME: At this time I don't know how to interpret fonts.clu. For
-	//     now, let's just the standard speech font instead.
-
-	SpriteInfo spriteInfo;
-	Common::File f;
-	int i;
-
-	// Read the "Smacker" logo
-
-	uint16 logoWidth = 0;
-	uint16 logoHeight = 0;
-	byte *logoData = NULL;
-	byte palette[256 * 4];
-
-	if (f.open("credits.bmp")) {
-		logoWidth = f.readUint16LE();
-		logoHeight = f.readUint16LE();
-
-		for (i = 0; i < 256; i++) {
-			palette[i * 4 + 0] = f.readByte() << 2;
-			palette[i * 4 + 1] = f.readByte() << 2;
-			palette[i * 4 + 2] = f.readByte() << 2;
-			palette[i * 4 + 3] = 0;
-		}
-
-		logoData = (byte *)malloc(logoWidth * logoHeight);
-
-		f.read(logoData, logoWidth * logoHeight);
-		f.close();
-	} else {
-		warning("Can't find credits.bmp");
-		memset(palette, 0, sizeof(palette));
-		palette[14 * 4 + 0] = 252;
-		palette[14 * 4 + 1] = 252;
-		palette[14 * 4 + 2] = 252;
-		palette[14 * 4 + 3] = 0;
-	}
-
-	setPalette(0, 256, palette, RDPAL_INSTANT);
-
-	// Read the credits text
-
-	Common::Array<CreditsLine *> creditsLines;
-
-	int lineCount = 0;
-	int lineTop = 400;
-	int paragraphStart = 0;
-	bool hasCenterMark = false;
-
-	if (!f.open("credits.clu")) {
-		warning("Can't find credits.clu");
-		return;
-	}
-
-	while (1) {
-		char buffer[80];
-		char *line = f.readLine(buffer, sizeof(buffer));
-
-		if (!line || *line == 0) {
-			if (!hasCenterMark) {
-				for (i = paragraphStart; i < lineCount; i++)
-					creditsLines[i]->type = LINE_CENTER;
-			}
-			paragraphStart = lineCount;
-			hasCenterMark = false;
-			if (paragraphStart == lineCount)
-				lineTop += CREDITS_LINE_SPACING;
-
-			if (!line)
-				break;
-
-			continue;
-		}
-
-		// The German credits contains character code 9. We don't want
-		// the credits to show the 'dud' symbol, so we replace them
-		// with spaces.
-
-		for (char *ptr = line; *ptr; ptr++) {
-			if (*ptr < 32)
-				*ptr = 32;
-		}
-
-		char *center_mark = strchr(line, '^');
-
-		if (center_mark) {
-			// The current paragraph has at least one center mark.
-			hasCenterMark = true;
-
-			if (center_mark != line) {
-				creditsLines.push_back(new CreditsLine);
-
-				// The center mark is somewhere inside the
-				// line. Split it into left and right side.
-				*center_mark = 0;
-
-				creditsLines[lineCount]->top = lineTop;
-				creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
-				creditsLines[lineCount]->type = LINE_LEFT;
-				creditsLines[lineCount]->str = strdup(line);
-
-				lineCount++;
-				*center_mark = '^';
-			}
-
-			line = center_mark;
-		}
-
-		creditsLines.push_back(new CreditsLine);
-
-		creditsLines[lineCount]->top = lineTop;
-
-		if (*line == '^') {
-			creditsLines[lineCount]->type = LINE_RIGHT;
-			line++;
-		} else
-			creditsLines[lineCount]->type = LINE_LEFT;
-
-		if (strcmp(line, "@") == 0) {
-			creditsLines[lineCount]->height = logoHeight;
-			lineTop += logoHeight;
-		} else {
-			creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
-			lineTop += CREDITS_LINE_SPACING;
-		}
-
-		creditsLines[lineCount]->str = strdup(line);
-		lineCount++;
-	}
-
-	f.close();
-
-	// We could easily add some ScummVM stuff to the credits, if we wanted
-	// to. On the other hand, anyone with the attention span to actually
-	// read all the credits probably already knows. :-)
-
-	// Start the music and roll the credits
-
-	// The credits music (which can also be heard briefly in the "carib"
-	// cutscene) is played once.
-
-	_vm->_sound->streamCompMusic(309, false);
-
-	clearScene();
-	fadeUp(0);
-
-	spriteInfo.scale = 0;
-	spriteInfo.scaledWidth = 0;
-	spriteInfo.scaledHeight = 0;
-	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
-	spriteInfo.blend = 0;
-
-	int startLine = 0;
-	int scrollPos = 0;
-
-	bool abortCredits = false;
-
-	int scrollSteps = lineTop + CREDITS_FONT_HEIGHT;
-	uint32 musicStart = _vm->getMillis();
-
-	// Ideally the music should last just a tiny bit longer than the
-	// credits. Note that musicTimeRemaining() will return 0 if the music
-	// is muted, so we need a sensible fallback for that case.
-
-	uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);
-
-	while (scrollPos < scrollSteps && !_vm->_quit) {
-		clearScene();
-
-		for (i = startLine; i < lineCount; i++) {
-			if (!creditsLines[i])
-				continue;
-
-			// Free any sprites that have scrolled off the screen
-
-			if (creditsLines[i]->top + creditsLines[i]->height < scrollPos) {
-				debug(2, "Freeing line %d: '%s'", i, creditsLines[i]->str);
-
-				delete creditsLines[i];
-				creditsLines[i] = NULL;
-
-				startLine = i + 1;
-			} else if (creditsLines[i]->top < scrollPos + 400) {
-				if (!creditsLines[i]->sprite) {
-					debug(2, "Creating line %d: '%s'", i, creditsLines[i]->str);
-					creditsLines[i]->sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i]->str, 600, 14, _vm->_speechFontId, 0);
-				}
-
-				FrameHeader frame;
-
-				frame.read(creditsLines[i]->sprite);
-
-				spriteInfo.y = creditsLines[i]->top - scrollPos;
-				spriteInfo.w = frame.width;
-				spriteInfo.h = frame.height;
-				spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size();
-
-				switch (creditsLines[i]->type) {
-				case LINE_LEFT:
-					spriteInfo.x = RENDERWIDE / 2 - 5 - frame.width;
-					break;
-				case LINE_RIGHT:
-					spriteInfo.x = RENDERWIDE / 2 + 5;
-					break;
-				case LINE_CENTER:
-					if (strcmp(creditsLines[i]->str, "@") == 0) {
-						spriteInfo.data = logoData;
-						spriteInfo.x = (RENDERWIDE - logoWidth) / 2;
-						spriteInfo.w = logoWidth;
-						spriteInfo.h = logoHeight;
-					} else
-						spriteInfo.x = (RENDERWIDE - frame.width) / 2;
-					break;
-				}
-
-				if (spriteInfo.data)
-					drawSprite(&spriteInfo);
-			} else
-				break;
-		}
-
-		updateDisplay();
-
-		KeyboardEvent *ke = _vm->keyboardEvent();
-
-		if (ke && ke->keycode == 27) {
-			if (!abortCredits) {
-				abortCredits = true;
-				fadeDown();
-			}
-		}
-
-		if (abortCredits && getFadeStatus() == RDFADE_BLACK)
-			break;
-
-		_vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps);
-		scrollPos++;
-	}
-
-	// We're done. Clean up and try to put everything back where it was
-	// before the credits.
-
-	for (i = 0; i < lineCount; i++) {
-		delete creditsLines[i];
-	}
-
-	free(logoData);
-
-	if (!abortCredits) {
-		fadeDown();
-
-		// The music should either have stopped or be about to stop, so
-		// wait for it to really happen.
-
-		while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
-			updateDisplay(false);
-			_vm->_system->delayMillis(100);
-		}
-	}
-
-	if (_vm->_quit)
-		return;
-
-	waitForFade();
-
-	_vm->_sound->muteFx(false);
-	_vm->_sound->muteSpeech(false);
-
-	if (loopingMusicId)
-		_vm->_sound->streamCompMusic(loopingMusicId, true);
-	else
-		_vm->_sound->stopMusic(false);
-
-	if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
-		_vm->_mouse->setMouse(NORMAL_MOUSE_ID);
-
-	if (_vm->_logic->readVar(DEAD))
-		_vm->_mouse->buildSystemMenu();
-}
-
-// This image used to be shown by CacheNewCluster() while copying a data file
-// from the CD to the hard disk. ScummVM doesn't do that, so the image is never
-// shown. It'd be nice if we could do something useful with it some day...
-
-void Screen::splashScreen() {
-	byte *bgfile = _vm->_resman->openResource(2950);
-
-	initialiseBackgroundLayer(NULL);
-	initialiseBackgroundLayer(NULL);
-	initialiseBackgroundLayer(_vm->fetchBackgroundLayer(bgfile));
-	initialiseBackgroundLayer(NULL);
-	initialiseBackgroundLayer(NULL);
-
-	setPalette(0, 256, _vm->fetchPalette(bgfile), RDPAL_FADE);
-	renderParallax(_vm->fetchBackgroundLayer(bgfile), 2);
-
-	closeBackgroundLayer();
-
-	byte *loadingBar = _vm->_resman->openResource(2951);
-	byte *frame = _vm->fetchFrameHeader(loadingBar, 0);
-
-	AnimHeader animHead;
-	CdtEntry cdt;
-	FrameHeader frame_head;
-
-	animHead.read(_vm->fetchAnimHeader(loadingBar));
-	cdt.read(_vm->fetchCdtEntry(loadingBar, 0));
-	frame_head.read(_vm->fetchFrameHeader(loadingBar, 0));
-
-	SpriteInfo barSprite;
-
-	barSprite.x = cdt.x;
-	barSprite.y = cdt.y;
-	barSprite.w = frame_head.width;
-	barSprite.h = frame_head.height;
-	barSprite.scale = 0;
-	barSprite.scaledWidth = 0;
-	barSprite.scaledHeight = 0;
-	barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS;
-	barSprite.blend = 0;
-	barSprite.colourTable = 0;
-	barSprite.data = frame + FrameHeader::size();
-
-	drawSprite(&barSprite);
-
-	fadeUp();
-	waitForFade();
-
-	for (int i = 0; i < animHead.noAnimFrames; i++) {
-		frame = _vm->fetchFrameHeader(loadingBar, i);
-		barSprite.data = frame + FrameHeader::size();
-		drawSprite(&barSprite);
-		updateDisplay();
-		_vm->_system->delayMillis(30);
-	}
-
-	_vm->_resman->closeResource(2951);
-
-	fadeDown();
-	waitForFade();
-}
-
-} // End of namespace Sword2

Deleted: scummvm/trunk/engines/sword2/build_display.h
===================================================================
--- scummvm/trunk/engines/sword2/build_display.h	2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/build_display.h	2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,441 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2006 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-#ifndef	_BUILD_DISPLAY
-#define	_BUILD_DISPLAY
-
-#include "common/rect.h"
-#include "common/stream.h"
-
-#define MAX_bgp0_sprites 6
-#define MAX_bgp1_sprites 6
-#define MAX_back_sprites 30
-#define MAX_sort_sprites 30
-#define MAX_fore_sprites 30
-#define MAX_fgp0_sprites 6
-#define MAX_fgp1_sprites 6
-
-#define PALTABLESIZE     (64 * 64 * 64)
-
-#define BLOCKWIDTH       64
-#define BLOCKHEIGHT      64
-#define MAXLAYERS        5
-
-#define MENUDEEP         40
-#define RENDERWIDE       640
-#define RENDERDEEP       (480 - (MENUDEEP * 2))
-
-// 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 {
-
-class Sword2Engine;
-
-// Sprite defines
-
-enum {
-	// This is the low byte part of the sprite type.
-
-	RDSPR_TRANS			= 0x0001,
-	RDSPR_BLEND			= 0x0004,
-	RDSPR_FLIP			= 0x0008,
-	RDSPR_SHADOW			= 0x0010,
-	RDSPR_DISPLAYALIGN		= 0x0020,
-	RDSPR_NOCOMPRESSION		= 0x0040,
-	RDSPR_EDGEBLEND			= 0x0080,	// Unused
-
-	// This is the high byte part of the sprite type, which defines what
-	// type of compression is used. Unless RDSPR_NOCOMPRESSION is set.
-
-	RDSPR_RLE16			= 0x0000,
-	RDSPR_RLE256			= 0x0100,
-	RDSPR_RLE256FAST		= 0x0200
-};
-
-// Fading defines
-
-enum {
-	RDFADE_NONE,
-	RDFADE_UP,
-	RDFADE_DOWN,
-	RDFADE_BLACK
-};
-
-// Palette defines
-
-enum {
-	RDPAL_FADE,
-	RDPAL_INSTANT
-};
-
-// Blitting FX defines
-
-enum {
-	RDBLTFX_SPRITEBLEND		= 0x01,
-	RDBLTFX_SHADOWBLEND		= 0x02,
-	RDBLTFX_EDGEBLEND		= 0x04
-};
-
-// 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;
-};
-
-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;
-};
-
-struct Parallax {
-	uint16 w;
-	uint16 h;
-
-	// The dimensions are followed by an offset table, but we don't know in
-	// advance how big it is. See initializeBackgroundLayer().
-
-	static const int size() {
-		return 4;
-	}
-
-	void read(byte *addr) {
-		Common::MemoryReadStream readS(addr, size());
-
-		w = readS.readUint16LE();
-		h = readS.readUint16LE();
-	}
-
-	void write(byte *addr) {
-		Common::MemoryWriteStream writeS(addr, size());
-
-		writeS.writeUint16LE(w);
-		writeS.writeUint16LE(h);
-	}
-};
-
-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(byte *ob_mouse, byte *ob_graph, byte *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(byte *ptr, 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(byte *parallax);
-	void closeBackgroundLayer();
-
-	void initialiseRenderCycle();
-
-	void initBackground(int32 res, int32 new_palette);
-	void registerFrame(byte *ob_mouse, byte *ob_graph, byte *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(int x, int y, uint8 colour);
-	void drawLine(int x0, int y0, int x1, int y1, uint8 colour);
-
-#ifdef BACKEND_8BIT
-	void plotYUV(byte *lut, int width, int height, byte *const *dat);
-#endif
-
-	void rollCredits();
-	void splashScreen();
-};
-
-} // End of namespace Sword2
-
-#endif

Deleted: scummvm/trunk/engines/sword2/save_rest.cpp
===================================================================
--- scummvm/trunk/engines/sword2/save_rest.cpp	2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/save_rest.cpp	2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,414 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2006 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-// ---------------------------------------------------------------------------
-// SAVE_REST.CPP	save, restore & restart functions
-//
-// James 05feb97
-//
-// "Jesus Saves", but could he Restore or Restart? He can now...
-//
-// ---------------------------------------------------------------------------
-
-#include "common/stdafx.h"
-#include "common/savefile.h"
-#include "sword2/sword2.h"
-#include "sword2/defs.h"
-#include "sword2/logic.h"
-#include "sword2/mouse.h"
-#include "sword2/resman.h"
-#include "sword2/sound.h"
-
-namespace Sword2 {
-
-// A savegame consists of a header and the global variables
-
-// Max length of a savegame filename
-#define	MAX_FILENAME_LEN 128
-
-/**
- * Calculate size of required savegame buffer
- */
-
-uint32 Sword2Engine::findBufferSize() {
-	// Size of savegame header + size of global variables
-	return 212 + _resman->fetchLen(1);
-}
-
-/**
- * Save the game.
- */
-
-uint32 Sword2Engine::saveGame(uint16 slotNo, byte *desc) {
-	char description[SAVE_DESCRIPTION_LEN];
-	uint32 bufferSize = findBufferSize();
-	byte *saveBuffer = (byte *)malloc(bufferSize);
-	ScreenInfo *screenInfo = _screen->getScreenInfo();
-
-	memset(description, 0, sizeof(description));
-	strncpy(description, (char *)desc, SAVE_DESCRIPTION_LEN - 1);
-
-	Common::MemoryWriteStream writeS(saveBuffer, bufferSize);
-
-	byte *globalVars = _resman->openResource(1);
-	byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
-
-	// Script no. 7 - 'george_savedata_request' calls fnPassPlayerSaveData
-	_logic->runResScript(CUR_PLAYER_ID, 7);
-
-	writeS.writeUint32LE(0);	// Checksum
-	writeS.write(description, SAVE_DESCRIPTION_LEN);
-	writeS.writeUint32LE(_resman->fetchLen(1));
-	writeS.writeUint32LE(screenInfo->background_layer_id);
-	writeS.writeUint32LE(_logic->getRunList());
-	writeS.writeUint32LE(screenInfo->feet_x);
-	writeS.writeUint32LE(screenInfo->feet_y);
-	writeS.writeUint32LE(_sound->getLoopingMusicId());
-	writeS.write(objectHub, ObjectHub::size());
-	writeS.write(_logic->_saveLogic, ObjectLogic::size());
-	writeS.write(_logic->_saveGraphic, ObjectGraphic::size());
-	writeS.write(_logic->_saveMega, ObjectMega::size());
-	writeS.write(globalVars, _resman->fetchLen(1));
-
-	WRITE_LE_UINT32(saveBuffer, calcChecksum(saveBuffer + 4, bufferSize - 4));
-
-	_resman->closeResource(CUR_PLAYER_ID);
-	_resman->closeResource(1);
-
-	uint32 errorCode = saveData(slotNo, saveBuffer, bufferSize);
-
-	free(saveBuffer);
-
-	if (errorCode != SR_OK) {
-		uint32 textId;
-
-		switch (errorCode) {
-		case SR_ERR_FILEOPEN:
-			textId = TEXT_SAVE_CANT_OPEN;
-			break;
-		default:
-			textId = TEXT_SAVE_FAILED;
-			break;
-		}
-
-		_screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
-	}
-
-	return errorCode;
-}
-
-uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
-	char saveFileName[MAX_FILENAME_LEN];
-
-	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
-	Common::OutSaveFile *out;
-
-	if (!(out = _saveFileMan->openForSaving(saveFileName))) {
-		return SR_ERR_FILEOPEN;
-	}
-
-	out->write(buffer, bufferSize);
-	out->flush();
-
-	if (!out->ioFailed()) {
-		delete out;
-		return SR_OK;
-	}
-
-	delete out;
-	return SR_ERR_WRITEFAIL;
-}
-
-/**
- * Restore the game.
- */
-
-uint32 Sword2Engine::restoreGame(uint16 slotNo) {
-	uint32 bufferSize = findBufferSize();
-	byte *saveBufferMem = (byte *)malloc(bufferSize);
-
-	uint32 errorCode = restoreData(slotNo, saveBufferMem, bufferSize);
-
-	// If it was read in successfully, then restore the game from the
-	// buffer & free the buffer. Note that restoreFromBuffer() frees the
-	// buffer in order to clear it from memory before loading in the new
-	// screen and runlist, so we only need to free it in case of failure.
-
-	if (errorCode == SR_OK)
-		errorCode = restoreFromBuffer(saveBufferMem, bufferSize);
-	else
-		free(saveBufferMem);
-
-	if (errorCode != SR_OK) {
-		uint32 textId;
-
-		switch (errorCode) {
-		case SR_ERR_FILEOPEN:
-			textId = TEXT_RESTORE_CANT_OPEN;
-			break;
-		case SR_ERR_INCOMPATIBLE:
-			textId = TEXT_RESTORE_INCOMPATIBLE;
-			break;
-		default:
-			textId = TEXT_RESTORE_FAILED;
-			break;
-		}
-
-		_screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
-	} else {
-		// Prime system with a game cycle
-
-		// Reset the graphic 'BuildUnit' list before a new logic list
-		// (see fnRegisterFrame)
-		_screen->resetRenderLists();
-
-		// Reset the mouse hot-spot list. See fnRegisterMouse()
-		// and fnRegisterFrame()
-		_mouse->resetMouseList();
-
-		if (_logic->processSession())
-			error("restore 1st cycle failed??");
-	}
-
-	// Force the game engine to pick a cursor. This appears to be needed
-	// when using the -x command-line option to restore a game.
-	_mouse->setMouseTouching(1);
-	return errorCode;
-}
-
-uint32 Sword2Engine::restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
-	char saveFileName[MAX_FILENAME_LEN];
-
-	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
-	Common::InSaveFile *in;
-
-	if (!(in = _saveFileMan->openForLoading(saveFileName))) {
-		// error: couldn't open file
-		return SR_ERR_FILEOPEN;
-	}
-
-	// Read savegame into the buffer
-	uint32 itemsRead = in->read(buffer, bufferSize);
-
-	delete in;
-
-	if (itemsRead != bufferSize) {
-		// We didn't get all of it. At the moment we have no way of
-		// knowing why, so assume that it's an incompatible savegame.
-
-		return SR_ERR_INCOMPATIBLE;
-	}
-
-	return SR_OK;
-}
-
-uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
-	Common::MemoryReadStream readS(buffer, size);
-
-	// Calc checksum & check that aginst the value stored in the header
-
-	if (readS.readUint32LE() != calcChecksum(buffer + 4, size - 4)) {
-		free(buffer);
-		return SR_ERR_INCOMPATIBLE;
-	}
-
-	readS.seek(SAVE_DESCRIPTION_LEN, SEEK_CUR);
-
-	// Check savegame against length of current global variables resource
-	// This would most probably be trapped by the checksum test anyway,
-	// but it doesn't do any harm to check this as well.
-
-	// Historical note: During development, earlier savegames would often
-	// be shorter than the current expected length.
-
-	if (readS.readUint32LE() != _resman->fetchLen(1)) {
-		free(buffer);
-		return SR_ERR_INCOMPATIBLE;
-	}
-
-	byte *globalVars = _resman->openResource(1);
-	byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
-
-	uint32 screenId = readS.readUint32LE();
-	uint32 runListId = readS.readUint32LE();
-	uint32 feetX = readS.readUint32LE();
-	uint32 feetY = readS.readUint32LE();
-	uint32 musicId = readS.readUint32LE();
-
-	// Trash all resources from memory except player object & global vars
-	_resman->killAll(false);
-	_logic->resetKillList();
-
-	readS.read(objectHub, ObjectHub::size());
-	readS.read(_logic->_saveLogic, ObjectLogic::size());
-	readS.read(_logic->_saveGraphic, ObjectGraphic::size());
-	readS.read(_logic->_saveMega, ObjectMega::size());
-
-	// Fill out the player object structures from the savegame structures.
-	// Also run the appropriate scripts to set up George's anim tables and
-	// walkdata, and Nico's anim tables.
-
-	// Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
-	_logic->runResScript(CUR_PLAYER_ID, 8);
-
-	// Script no. 14 - 'set_up_nico_anim_tables'
-	_logic->runResScript(CUR_PLAYER_ID, 14);
-
-	// Which megaset was the player at the time of saving?
-	ObjectMega obMega(_logic->_saveMega);
-
-	uint32 scriptNo = 0;
-
-	switch (obMega.getMegasetRes()) {
-	case 36:		// GeoMega:
-		scriptNo = 9;	// script no.9	- 'player_is_george'
-		break;
-	case 2003:		// GeoMegaB:
-		scriptNo = 13;	// script no.13 - 'player_is_georgeB'
-		break;
-	case 1366:		// NicMegaA:
-		scriptNo = 11;	// script no.11 - 'player_is_nicoA'
-		break;
-	case 1437:		// NicMegaB:
-		scriptNo = 12;	// script no.12 - 'player_is_nicoB'
-		break;
-	case 1575:		// NicMegaC:
-		scriptNo = 10;	// script no.10 - 'player_is_nicoC'
-		break;
-	}
-
-	_logic->runResScript(CUR_PLAYER_ID, scriptNo);
-
-	// Copy variables from savegame buffer to memory
-	readS.read(globalVars, _resman->fetchLen(1));
-
-	_resman->closeResource(CUR_PLAYER_ID);
- 	_resman->closeResource(1);
-
-	free(buffer);
-
-	int32 pars[2];
-
-	pars[0] = screenId;
-	pars[1] = 1;
-	_logic->fnInitBackground(pars);
-
-	ScreenInfo *screenInfo = _screen->getScreenInfo();
-
-	// So palette not restored immediately after control panel - we want to
-	// fade up instead!
-	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.
-
-	screenInfo->feet_x = feetX;
-	screenInfo->feet_y = feetY;
-
-	// Start the new run list
-	_logic->expressChangeSession(runListId);
-
-	// Force in the new scroll position, so unsightly scroll-catch-up does
-	// not occur when screen first draws after returning from restore panel
-
-	// Set the screen record of player position - ready for setScrolling()
-
-	screenInfo->player_feet_x = obMega.getFeetX();
-	screenInfo->player_feet_y = obMega.getFeetY();
-
-	// if this screen is wide, recompute the scroll offsets now
-	if (screenInfo->scroll_flag)
-		_screen->setScrolling();
-
-	// Any music required will be started after we've returned from
-	// restoreControl() - see systemMenuMouse() in mouse.cpp!
-
-	// Restart any looping music. Originally this was - and still is - done
-	// in systemMenuMouse(), but with ScummVM we have other ways of
-	// restoring savegames so it's easier to put it here as well.
-
-	if (musicId) {
-		pars[0] = musicId;
-		pars[1] = FX_LOOP;
-		_logic->fnPlayMusic(pars);
-	} else
-		_logic->fnStopMusic(NULL);
-
-	return SR_OK;
-}
-
-/**
- * Get the description of a savegame
- */
-
-uint32 Sword2Engine::getSaveDescription(uint16 slotNo, byte *description) {
-	char saveFileName[MAX_FILENAME_LEN];
-
-	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
-	Common::InSaveFile *in;
-
-	if (!(in = _saveFileMan->openForLoading(saveFileName))) {
-		return SR_ERR_FILEOPEN;
-	}
-
-	in->readUint32LE();
-	in->read(description, SAVE_DESCRIPTION_LEN);
-
-	delete in;
-	return SR_OK;
-}
-
-bool Sword2Engine::saveExists() {
-	for (int i = 0; i <= 99; i++)
-		if (saveExists(i))
-			return true;
-	return false;
-}
-
-bool Sword2Engine::saveExists(uint16 slotNo) {
-	char saveFileName[MAX_FILENAME_LEN];
-
-	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
-
-	Common::InSaveFile *in;
-
-	if (!(in = _saveFileMan->openForLoading(saveFileName))) {
-		return false;
-	}
-
-	delete in;
-	return true;
-}
-
-uint32 Sword2Engine::calcChecksum(byte *buffer, uint32 size) {
-	uint32 total = 0;
-
-	for (uint32 pos = 0; pos < size; pos++)
-		total += buffer[pos];
-
-	return total;
-}
-
-} // End of namespace Sword2

Deleted: scummvm/trunk/engines/sword2/save_rest.h
===================================================================
--- scummvm/trunk/engines/sword2/save_rest.h	2006-02-12 19:33:45 UTC (rev 20651)
+++ scummvm/trunk/engines/sword2/save_rest.h	2006-02-12 19:38:26 UTC (rev 20652)
@@ -1,47 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2006 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- */
-
-#ifndef	SAVE_REST_H
-#define	SAVE_REST_H
-
-namespace Sword2 {
-
-#define	SAVE_DESCRIPTION_LEN	64
-
-// Save & Restore error codes
-
-enum {
-	SR_OK,			// No worries
-	SR_ERR_FILEOPEN,	// Can't open file - Couldn't create file for
-				// saving, or couldn't find file for loading.
-	SR_ERR_INCOMPATIBLE,	// (Restore) Incompatible savegame data.
-				// Savegame file is obsolete. (Won't happen
-				// after development stops)
-	SR_ERR_READFAIL,	// (Restore) Failed on reading savegame file -
-				// Something screwed up during the read
-	SR_ERR_WRITEFAIL	// (Save) Failed on writing savegame file -
-				// Something screwed up during the write -
-				// could be hard-drive full..?
-};
-
-} // End of namespace Sword2
-
-#endif

Copied: scummvm/trunk/engines/sword2/saveload.cpp (from rev 20651, scummvm/trunk/engines/sword2/save_rest.cpp)
===================================================================
--- scummvm/trunk/engines/sword2/saveload.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sword2/saveload.cpp	2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,414 @@
+/* Copyright (C) 1994-1998 Revolution Software Ltd.
+ * Copyright (C) 2003-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+// ---------------------------------------------------------------------------
+// SAVE_REST.CPP	save, restore & restart functions
+//
+// James 05feb97
+//
+// "Jesus Saves", but could he Restore or Restart? He can now...
+//
+// ---------------------------------------------------------------------------
+
+#include "common/stdafx.h"
+#include "common/savefile.h"
+#include "sword2/sword2.h"
+#include "sword2/defs.h"
+#include "sword2/logic.h"
+#include "sword2/mouse.h"
+#include "sword2/resman.h"
+#include "sword2/sound.h"
+
+namespace Sword2 {
+
+// A savegame consists of a header and the global variables
+
+// Max length of a savegame filename
+#define	MAX_FILENAME_LEN 128
+
+/**
+ * Calculate size of required savegame buffer
+ */
+
+uint32 Sword2Engine::findBufferSize() {
+	// Size of savegame header + size of global variables
+	return 212 + _resman->fetchLen(1);
+}
+
+/**
+ * Save the game.
+ */
+
+uint32 Sword2Engine::saveGame(uint16 slotNo, byte *desc) {
+	char description[SAVE_DESCRIPTION_LEN];
+	uint32 bufferSize = findBufferSize();
+	byte *saveBuffer = (byte *)malloc(bufferSize);
+	ScreenInfo *screenInfo = _screen->getScreenInfo();
+
+	memset(description, 0, sizeof(description));
+	strncpy(description, (char *)desc, SAVE_DESCRIPTION_LEN - 1);
+
+	Common::MemoryWriteStream writeS(saveBuffer, bufferSize);
+
+	byte *globalVars = _resman->openResource(1);
+	byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
+
+	// Script no. 7 - 'george_savedata_request' calls fnPassPlayerSaveData
+	_logic->runResScript(CUR_PLAYER_ID, 7);
+
+	writeS.writeUint32LE(0);	// Checksum
+	writeS.write(description, SAVE_DESCRIPTION_LEN);
+	writeS.writeUint32LE(_resman->fetchLen(1));
+	writeS.writeUint32LE(screenInfo->background_layer_id);
+	writeS.writeUint32LE(_logic->getRunList());
+	writeS.writeUint32LE(screenInfo->feet_x);
+	writeS.writeUint32LE(screenInfo->feet_y);
+	writeS.writeUint32LE(_sound->getLoopingMusicId());
+	writeS.write(objectHub, ObjectHub::size());
+	writeS.write(_logic->_saveLogic, ObjectLogic::size());
+	writeS.write(_logic->_saveGraphic, ObjectGraphic::size());
+	writeS.write(_logic->_saveMega, ObjectMega::size());
+	writeS.write(globalVars, _resman->fetchLen(1));
+
+	WRITE_LE_UINT32(saveBuffer, calcChecksum(saveBuffer + 4, bufferSize - 4));
+
+	_resman->closeResource(CUR_PLAYER_ID);
+	_resman->closeResource(1);
+
+	uint32 errorCode = saveData(slotNo, saveBuffer, bufferSize);
+
+	free(saveBuffer);
+
+	if (errorCode != SR_OK) {
+		uint32 textId;
+
+		switch (errorCode) {
+		case SR_ERR_FILEOPEN:
+			textId = TEXT_SAVE_CANT_OPEN;
+			break;
+		default:
+			textId = TEXT_SAVE_FAILED;
+			break;
+		}
+
+		_screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+	}
+
+	return errorCode;
+}
+
+uint32 Sword2Engine::saveData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
+	char saveFileName[MAX_FILENAME_LEN];
+
+	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+	Common::OutSaveFile *out;
+
+	if (!(out = _saveFileMan->openForSaving(saveFileName))) {
+		return SR_ERR_FILEOPEN;
+	}
+
+	out->write(buffer, bufferSize);
+	out->flush();
+
+	if (!out->ioFailed()) {
+		delete out;
+		return SR_OK;
+	}
+
+	delete out;
+	return SR_ERR_WRITEFAIL;
+}
+
+/**
+ * Restore the game.
+ */
+
+uint32 Sword2Engine::restoreGame(uint16 slotNo) {
+	uint32 bufferSize = findBufferSize();
+	byte *saveBufferMem = (byte *)malloc(bufferSize);
+
+	uint32 errorCode = restoreData(slotNo, saveBufferMem, bufferSize);
+
+	// If it was read in successfully, then restore the game from the
+	// buffer & free the buffer. Note that restoreFromBuffer() frees the
+	// buffer in order to clear it from memory before loading in the new
+	// screen and runlist, so we only need to free it in case of failure.
+
+	if (errorCode == SR_OK)
+		errorCode = restoreFromBuffer(saveBufferMem, bufferSize);
+	else
+		free(saveBufferMem);
+
+	if (errorCode != SR_OK) {
+		uint32 textId;
+
+		switch (errorCode) {
+		case SR_ERR_FILEOPEN:
+			textId = TEXT_RESTORE_CANT_OPEN;
+			break;
+		case SR_ERR_INCOMPATIBLE:
+			textId = TEXT_RESTORE_INCOMPATIBLE;
+			break;
+		default:
+			textId = TEXT_RESTORE_FAILED;
+			break;
+		}
+
+		_screen->displayMsg(fetchTextLine(_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+	} else {
+		// Prime system with a game cycle
+
+		// Reset the graphic 'BuildUnit' list before a new logic list
+		// (see fnRegisterFrame)
+		_screen->resetRenderLists();
+
+		// Reset the mouse hot-spot list. See fnRegisterMouse()
+		// and fnRegisterFrame()
+		_mouse->resetMouseList();
+
+		if (_logic->processSession())
+			error("restore 1st cycle failed??");
+	}
+
+	// Force the game engine to pick a cursor. This appears to be needed
+	// when using the -x command-line option to restore a game.
+	_mouse->setMouseTouching(1);
+	return errorCode;
+}
+
+uint32 Sword2Engine::restoreData(uint16 slotNo, byte *buffer, uint32 bufferSize) {
+	char saveFileName[MAX_FILENAME_LEN];
+
+	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+	Common::InSaveFile *in;
+
+	if (!(in = _saveFileMan->openForLoading(saveFileName))) {
+		// error: couldn't open file
+		return SR_ERR_FILEOPEN;
+	}
+
+	// Read savegame into the buffer
+	uint32 itemsRead = in->read(buffer, bufferSize);
+
+	delete in;
+
+	if (itemsRead != bufferSize) {
+		// We didn't get all of it. At the moment we have no way of
+		// knowing why, so assume that it's an incompatible savegame.
+
+		return SR_ERR_INCOMPATIBLE;
+	}
+
+	return SR_OK;
+}
+
+uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
+	Common::MemoryReadStream readS(buffer, size);
+
+	// Calc checksum & check that aginst the value stored in the header
+
+	if (readS.readUint32LE() != calcChecksum(buffer + 4, size - 4)) {
+		free(buffer);
+		return SR_ERR_INCOMPATIBLE;
+	}
+
+	readS.seek(SAVE_DESCRIPTION_LEN, SEEK_CUR);
+
+	// Check savegame against length of current global variables resource
+	// This would most probably be trapped by the checksum test anyway,
+	// but it doesn't do any harm to check this as well.
+
+	// Historical note: During development, earlier savegames would often
+	// be shorter than the current expected length.
+
+	if (readS.readUint32LE() != _resman->fetchLen(1)) {
+		free(buffer);
+		return SR_ERR_INCOMPATIBLE;
+	}
+
+	byte *globalVars = _resman->openResource(1);
+	byte *objectHub = _resman->openResource(CUR_PLAYER_ID) + ResHeader::size();
+
+	uint32 screenId = readS.readUint32LE();
+	uint32 runListId = readS.readUint32LE();
+	uint32 feetX = readS.readUint32LE();
+	uint32 feetY = readS.readUint32LE();
+	uint32 musicId = readS.readUint32LE();
+
+	// Trash all resources from memory except player object & global vars
+	_resman->killAll(false);
+	_logic->resetKillList();
+
+	readS.read(objectHub, ObjectHub::size());
+	readS.read(_logic->_saveLogic, ObjectLogic::size());
+	readS.read(_logic->_saveGraphic, ObjectGraphic::size());
+	readS.read(_logic->_saveMega, ObjectMega::size());
+
+	// Fill out the player object structures from the savegame structures.
+	// Also run the appropriate scripts to set up George's anim tables and
+	// walkdata, and Nico's anim tables.
+
+	// Script no. 8 - 'george_savedata_return' calls fnGetPlayerSaveData
+	_logic->runResScript(CUR_PLAYER_ID, 8);
+
+	// Script no. 14 - 'set_up_nico_anim_tables'
+	_logic->runResScript(CUR_PLAYER_ID, 14);
+
+	// Which megaset was the player at the time of saving?
+	ObjectMega obMega(_logic->_saveMega);
+
+	uint32 scriptNo = 0;
+
+	switch (obMega.getMegasetRes()) {
+	case 36:		// GeoMega:
+		scriptNo = 9;	// script no.9	- 'player_is_george'
+		break;
+	case 2003:		// GeoMegaB:
+		scriptNo = 13;	// script no.13 - 'player_is_georgeB'
+		break;
+	case 1366:		// NicMegaA:
+		scriptNo = 11;	// script no.11 - 'player_is_nicoA'
+		break;
+	case 1437:		// NicMegaB:
+		scriptNo = 12;	// script no.12 - 'player_is_nicoB'
+		break;
+	case 1575:		// NicMegaC:
+		scriptNo = 10;	// script no.10 - 'player_is_nicoC'
+		break;
+	}
+
+	_logic->runResScript(CUR_PLAYER_ID, scriptNo);
+
+	// Copy variables from savegame buffer to memory
+	readS.read(globalVars, _resman->fetchLen(1));
+
+	_resman->closeResource(CUR_PLAYER_ID);
+ 	_resman->closeResource(1);
+
+	free(buffer);
+
+	int32 pars[2];
+
+	pars[0] = screenId;
+	pars[1] = 1;
+	_logic->fnInitBackground(pars);
+
+	ScreenInfo *screenInfo = _screen->getScreenInfo();
+
+	// So palette not restored immediately after control panel - we want to
+	// fade up instead!
+	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.
+
+	screenInfo->feet_x = feetX;
+	screenInfo->feet_y = feetY;
+
+	// Start the new run list
+	_logic->expressChangeSession(runListId);
+
+	// Force in the new scroll position, so unsightly scroll-catch-up does
+	// not occur when screen first draws after returning from restore panel
+
+	// Set the screen record of player position - ready for setScrolling()
+
+	screenInfo->player_feet_x = obMega.getFeetX();
+	screenInfo->player_feet_y = obMega.getFeetY();
+
+	// if this screen is wide, recompute the scroll offsets now
+	if (screenInfo->scroll_flag)
+		_screen->setScrolling();
+
+	// Any music required will be started after we've returned from
+	// restoreControl() - see systemMenuMouse() in mouse.cpp!
+
+	// Restart any looping music. Originally this was - and still is - done
+	// in systemMenuMouse(), but with ScummVM we have other ways of
+	// restoring savegames so it's easier to put it here as well.
+
+	if (musicId) {
+		pars[0] = musicId;
+		pars[1] = FX_LOOP;
+		_logic->fnPlayMusic(pars);
+	} else
+		_logic->fnStopMusic(NULL);
+
+	return SR_OK;
+}
+
+/**
+ * Get the description of a savegame
+ */
+
+uint32 Sword2Engine::getSaveDescription(uint16 slotNo, byte *description) {
+	char saveFileName[MAX_FILENAME_LEN];
+
+	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+	Common::InSaveFile *in;
+
+	if (!(in = _saveFileMan->openForLoading(saveFileName))) {
+		return SR_ERR_FILEOPEN;
+	}
+
+	in->readUint32LE();
+	in->read(description, SAVE_DESCRIPTION_LEN);
+
+	delete in;
+	return SR_OK;
+}
+
+bool Sword2Engine::saveExists() {
+	for (int i = 0; i <= 99; i++)
+		if (saveExists(i))
+			return true;
+	return false;
+}
+
+bool Sword2Engine::saveExists(uint16 slotNo) {
+	char saveFileName[MAX_FILENAME_LEN];
+
+	sprintf(saveFileName, "%s.%.3d", _targetName.c_str(), slotNo);
+
+	Common::InSaveFile *in;
+
+	if (!(in = _saveFileMan->openForLoading(saveFileName))) {
+		return false;
+	}
+
+	delete in;
+	return true;
+}
+
+uint32 Sword2Engine::calcChecksum(byte *buffer, uint32 size) {
+	uint32 total = 0;
+
+	for (uint32 pos = 0; pos < size; pos++)
+		total += buffer[pos];
+
+	return total;
+}
+
+} // End of namespace Sword2

Copied: scummvm/trunk/engines/sword2/saveload.h (from rev 20651, scummvm/trunk/engines/sword2/save_rest.h)
===================================================================
--- scummvm/trunk/engines/sword2/saveload.h	                        (rev 0)
+++ scummvm/trunk/engines/sword2/saveload.h	2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,47 @@
+/* Copyright (C) 1994-1998 Revolution Software Ltd.
+ * Copyright (C) 2003-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef	SAVE_REST_H
+#define	SAVE_REST_H
+
+namespace Sword2 {
+
+#define	SAVE_DESCRIPTION_LEN	64
+
+// Save & Restore error codes
+
+enum {
+	SR_OK,			// No worries
+	SR_ERR_FILEOPEN,	// Can't open file - Couldn't create file for
+				// saving, or couldn't find file for loading.
+	SR_ERR_INCOMPATIBLE,	// (Restore) Incompatible savegame data.
+				// Savegame file is obsolete. (Won't happen
+				// after development stops)
+	SR_ERR_READFAIL,	// (Restore) Failed on reading savegame file -
+				// Something screwed up during the read
+	SR_ERR_WRITEFAIL	// (Save) Failed on writing savegame file -
+				// Something screwed up during the write -
+				// could be hard-drive full..?
+};
+
+} // End of namespace Sword2
+
+#endif

Copied: scummvm/trunk/engines/sword2/screen.cpp (from rev 20651, scummvm/trunk/engines/sword2/build_display.cpp)
===================================================================
--- scummvm/trunk/engines/sword2/screen.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sword2/screen.cpp	2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,1070 @@
+/* Copyright (C) 1994-1998 Revolution Software Ltd.
+ * Copyright (C) 2003-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+// ---------------------------------------------------------------------------
+// BUILD_DISPLAY.CPP	like the old spr_engi but slightly more aptly named
+// ---------------------------------------------------------------------------
+
+#include "common/stdafx.h"
+#include "common/system.h"
+
+#include "sword2/sword2.h"
+#include "sword2/console.h"
+#include "sword2/defs.h"
+#include "sword2/logic.h"
+#include "sword2/maketext.h"
+#include "sword2/mouse.h"
+#include "sword2/resman.h"
+#include "sword2/sound.h"
+
+namespace Sword2 {
+
+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();
+
+		// should be reset to zero at start of each screen change
+		_largestLayerArea = 0;
+		_largestSpriteArea = 0;
+	}
+
+	// Does this ever happen?
+	if (!_thisScreen.background_layer_id)
+		return;
+
+	// there is a valid screen to run
+
+	setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
+	_vm->_mouse->animateMouse();
+	startRenderCycle();
+
+	byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
+
+	MultiScreenHeader screenLayerTable;
+
+	screenLayerTable.read(file + ResHeader::size());
+
+	// Render at least one frame, but if the screen is scrolling, and if
+	// there is time left, we will render extra frames to smooth out the
+	// scrolling.
+
+	do {
+		// first background parallax + related anims
+		if (screenLayerTable.bg_parallax[0]) {
+			renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0);
+			drawBackPar0Frames();
+		}
+
+		// second background parallax + related anims
+		if (screenLayerTable.bg_parallax[1]) {
+			renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1);
+			drawBackPar1Frames();
+		}
+
+		// normal backround layer (just the one!)
+		renderParallax(_vm->fetchBackgroundLayer(file), 2);
+
+		// sprites & layers
+		drawBackFrames();	// background sprites
+		drawSortFrames(file);	// sorted sprites & layers
+		drawForeFrames();	// foreground sprites
+
+		// first foreground parallax + related anims
+
+		if (screenLayerTable.fg_parallax[0]) {
+			renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3);
+			drawForePar0Frames();
+		}
+
+		// second foreground parallax + related anims
+
+		if (screenLayerTable.fg_parallax[1]) {
+			renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4);
+			drawForePar1Frames();
+		}
+
+		_vm->_debugger->drawDebugGraphics();
+		_vm->_fontRenderer->printTextBlocs();
+		_vm->_mouse->processMenu();
+
+		updateDisplay();
+
+		_frameCount++;
+		if (_vm->getMillis() > _cycleTime) {
+			_fps = _frameCount;
+			_frameCount = 0;
+			_cycleTime = _vm->getMillis() + 1000;
+		}
+	} while (!endRenderCycle());
+
+	_vm->_resman->closeResource(_thisScreen.background_layer_id);
+}
+
+/**
+ * Fades down and displays a message on the screen.
+ * @param text The message
+ * @param time The number of seconds to display the message, or 0 to display it
+ *             until the user clicks the mouse or presses a key.
+ */
+
+void Screen::displayMsg(byte *text, int time) {
+	byte pal[256 * 4];
+	byte oldPal[256 * 4];
+
+	debug(2, "DisplayMsg: %s", text);
+
+	if (getFadeStatus() != RDFADE_BLACK) {
+		fadeDown();
+		waitForFade();
+	}
+
+	_vm->_mouse->setMouse(0);
+	_vm->_mouse->setLuggage(0);
+	_vm->_mouse->closeMenuImmediately();
+
+	clearScene();
+
+	byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);
+
+	FrameHeader frame;
+
+	frame.read(text_spr);
+
+	SpriteInfo spriteInfo;
+
+	spriteInfo.x = _screenWide / 2 - frame.width / 2;
+	if (!time)
+		spriteInfo.y = _screenDeep / 2 - frame.height / 2 - MENUDEEP;
+	else
+		spriteInfo.y = 400 - frame.height;
+	spriteInfo.w = frame.width;
+	spriteInfo.h = frame.height;
+	spriteInfo.scale = 0;
+	spriteInfo.scaledWidth = 0;
+	spriteInfo.scaledHeight	= 0;
+	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
+	spriteInfo.blend = 0;
+	spriteInfo.data = text_spr + FrameHeader::size();
+	spriteInfo.colourTable = 0;
+
+	uint32 rv = drawSprite(&spriteInfo);
+	if (rv)
+		error("Driver Error %.8x (in DisplayMsg)", rv);
+
+	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;
+
+	setPalette(0, 256, pal, RDPAL_FADE);
+	fadeUp();
+	free(text_spr);
+	waitForFade();
+
+	if (time > 0) {
+		uint32 targetTime = _vm->getMillis() + (time * 1000);
+		_vm->sleepUntil(targetTime);
+	} else {
+		while (!_vm->_quit) {
+			MouseEvent *me = _vm->mouseEvent();
+			if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
+				break;
+
+			if (_vm->keyboardEvent())
+				break;
+
+			updateDisplay();
+			_vm->_system->delayMillis(50);
+		}
+	}
+
+	fadeDown();
+	waitForFade();
+	clearScene();
+	setPalette(0, 256, oldPal, RDPAL_FADE);
+	fadeUp();
+}
+
+void Screen::drawBackPar0Frames() {
+	// frame attached to 1st background parallax
+	for (uint i = 0; i < _curBgp0; i++)
+		processImage(&_bgp0List[i]);
+}
+
+void Screen::drawBackPar1Frames() {
+	// frame attached to 2nd background parallax
+	for (uint i = 0; i < _curBgp1; i++)
+		processImage(&_bgp1List[i]);
+}
+
+void Screen::drawBackFrames() {
+	// background sprite, fixed to main background
+	for (uint i = 0; i < _curBack; i++)
+		processImage(&_backList[i]);
+}
+
+void Screen::drawSortFrames(byte *file) {
+	uint i, j;
+
+	// Sort the sort list. Used to be a separate function, but it was only
+	// called once, right before calling drawSortFrames().
+
+	if (_curSort > 1) {
+		for (i = 0; i < _curSort - 1; i++) {
+			for (j = 0; j < _curSort - 1; j++) {
+				if (_sortList[_sortOrder[j]].sort_y > _sortList[_sortOrder[j + 1]].sort_y) {
+					SWAP(_sortOrder[j], _sortOrder[j + 1]);
+				}
+			}
+		}
+	}
+
+	// Draw the sorted frames - layers, shrinkers & normal flat sprites
+
+	for (i = 0; i < _curSort; i++) {
+		if (_sortList[_sortOrder[i]].layer_number) {
+			// it's a layer - minus 1 for true layer number
+			// we need to know from the BuildUnit because the
+			// layers will have been sorted in random order
+			processLayer(file, _sortList[_sortOrder[i]].layer_number - 1);
+		} else {
+			// it's a sprite
+			processImage(&_sortList[_sortOrder[i]]);
+		}
+	}
+}
+
+void Screen::drawForeFrames() {
+	// foreground sprite, fixed to main background
+	for (uint i = 0; i < _curFore; i++)
+		processImage(&_foreList[i]);
+}
+
+void Screen::drawForePar0Frames() {
+	// frame attached to 1st foreground parallax
+	for (uint i = 0; i < _curFgp0; i++)
+		processImage(&_fgp0List[i]);
+}
+
+void Screen::drawForePar1Frames() {
+	// frame attached to 2nd foreground parallax
+	for (uint i = 0; i < _curFgp1; i++)
+		processImage(&_fgp1List[i]);
+}
+
+void Screen::processLayer(byte *file, uint32 layer_number) {
+	LayerHeader layer_head;
+
+	layer_head.read(_vm->fetchLayerHeader(file, layer_number));
+
+ 	SpriteInfo spriteInfo;
+
+	spriteInfo.x = layer_head.x;
+	spriteInfo.y = layer_head.y;
+	spriteInfo.w = layer_head.width;
+	spriteInfo.scale = 0;
+	spriteInfo.scaledWidth = 0;
+	spriteInfo.scaledHeight = 0;
+	spriteInfo.h = layer_head.height;
+	spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST;
+	spriteInfo.blend = 0;
+	spriteInfo.data = file + ResHeader::size() + layer_head.offset;
+	spriteInfo.colourTable = 0;
+
+	// check for largest layer for debug info
+
+	uint32 current_layer_area = layer_head.width * layer_head.height;
+
+	if (current_layer_area > _largestLayerArea) {
+		byte buf[NAME_LEN];
+
+		_largestLayerArea = current_layer_area;
+		sprintf(_largestLayerInfo,
+			"largest layer:  %s layer(%d) is %dx%d",
+			_vm->_resman->fetchName(_thisScreen.background_layer_id, buf),
+			layer_number, layer_head.width, layer_head.height);
+	}
+
+	uint32 rv = drawSprite(&spriteInfo);
+	if (rv)
+		error("Driver Error %.8x in processLayer(%d)", rv, layer_number);
+}
+
+void Screen::processImage(BuildUnit *build_unit) {
+	byte *file = _vm->_resman->openResource(build_unit->anim_resource);
+	byte *colTablePtr = NULL;
+
+	byte *frame = _vm->fetchFrameHeader(file, build_unit->anim_pc);
+
+	AnimHeader anim_head;
+	CdtEntry cdt_entry;
+	FrameHeader frame_head;
+
+	anim_head.read(_vm->fetchAnimHeader(file));
+	cdt_entry.read(_vm->fetchCdtEntry(file, build_unit->anim_pc));
+	frame_head.read(frame);
+
+	// so that 0-colour is transparent
+	uint32 spriteType = RDSPR_TRANS;
+
+	if (anim_head.blend)
+		spriteType |= RDSPR_BLEND;
+
+	// if the frame is to be flipped (only really applicable to frames
+	// using offsets)
+	if (cdt_entry.frameType & FRAME_FLIPPED)
+		spriteType |= RDSPR_FLIP;
+
+	if (cdt_entry.frameType & FRAME_256_FAST) {
+		// scaling, shading & blending don't work with RLE256FAST
+		// but the same compression can be decompressed using the
+		// RLE256 routines!
+
+		// NOTE: If this restriction refers to drawSprite(), I don't
+		// think we have it any more. But I'm not sure.
+
+		if (build_unit->scale || anim_head.blend || build_unit->shadingFlag)
+			spriteType |= RDSPR_RLE256;
+		else
+			spriteType |= RDSPR_RLE256FAST;
+	} else {
+		switch (anim_head.runTimeComp) {
+		case NONE:
+			spriteType |= RDSPR_NOCOMPRESSION;
+			break;
+		case RLE256:
+			spriteType |= RDSPR_RLE256;
+			break;
+		case RLE16:
+			spriteType |= RDSPR_RLE16;
+			// points to just after last cdt_entry, ie.
+			// start of colour table
+			colTablePtr = _vm->fetchAnimHeader(file) + AnimHeader::size() + anim_head.noAnimFrames * CdtEntry::size();
+			break;
+		}
+	}
+
+	// if we want this frame to be affected by the shading mask,
+	// add the status bit
+	if (build_unit->shadingFlag)
+		spriteType |= RDSPR_SHADOW;
+
+	SpriteInfo spriteInfo;
+
+	spriteInfo.x = build_unit->x;
+	spriteInfo.y = build_unit->y;
+	spriteInfo.w = frame_head.width;
+	spriteInfo.h = frame_head.height;
+	spriteInfo.scale = build_unit->scale;
+	spriteInfo.scaledWidth = build_unit->scaled_width;
+	spriteInfo.scaledHeight	= build_unit->scaled_height;
+	spriteInfo.type = spriteType;
+	spriteInfo.blend = anim_head.blend;
+	// points to just after frame header, ie. start of sprite data
+	spriteInfo.data = frame + FrameHeader::size();
+	spriteInfo.colourTable = colTablePtr;
+
+	// check for largest layer for debug info
+	uint32 current_sprite_area = frame_head.width * frame_head.height;
+
+	if (current_sprite_area > _largestSpriteArea) {
+		byte buf[NAME_LEN];
+
+		_largestSpriteArea = current_sprite_area;
+		sprintf(_largestSpriteInfo,
+			"largest sprite: %s frame(%d) is %dx%d",
+			_vm->_resman->fetchName(build_unit->anim_resource, buf),
+			build_unit->anim_pc,
+			frame_head.width,
+			frame_head.height);
+	}
+
+	if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) { // see anims.cpp
+		// bring the anim into the visible screen
+		// but leave extra pixel at edge for box
+		if (spriteInfo.x + spriteInfo.scaledWidth >= 639)
+			spriteInfo.x = 639 - spriteInfo.scaledWidth;
+
+		if (spriteInfo.y + spriteInfo.scaledHeight >= 399)
+			spriteInfo.y = 399 - spriteInfo.scaledHeight;
+
+		if (spriteInfo.x < 1)
+			spriteInfo.x = 1;
+
+		if (spriteInfo.y < 1)
+			spriteInfo.y = 1;
+
+		// create box to surround sprite - just outside sprite box
+		_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 = drawSprite(&spriteInfo);
+	if (rv) {
+		byte buf[NAME_LEN];
+
+		error("Driver Error %.8x with sprite %s (%d) in processImage",
+			rv,
+			_vm->_resman->fetchName(build_unit->anim_resource, buf),
+			build_unit->anim_resource);
+	}
+
+	// release the anim resource
+	_vm->_resman->closeResource(build_unit->anim_resource);
+}
+
+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
+
+	_curBgp0 = 0;
+	_curBgp1 = 0;
+	_curBack = 0;
+	// beginning of sort list is setup with the special sort layers
+	_curSort = _thisScreen.number_of_layers;
+	_curFore = 0;
+	_curFgp0 = 0;
+	_curFgp1 = 0;
+
+	if (_curSort) {
+		// there are some layers - so rebuild the sort order list
+		for (uint i = 0; i < _curSort; i++)
+			_sortOrder[i] = i;
+	}
+}
+
+void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega, BuildUnit *build_unit) {
+	ObjectGraphic obGraph(ob_graph);
+	ObjectMega obMega(ob_mega);
+
+	assert(obGraph.getAnimResource());
+
+	byte *file = _vm->_resman->openResource(obGraph.getAnimResource());
+
+	AnimHeader anim_head;
+	CdtEntry cdt_entry;
+	FrameHeader frame_head;
+
+	anim_head.read(_vm->fetchAnimHeader(file));
+	cdt_entry.read(_vm->fetchCdtEntry(file, obGraph.getAnimPc()));
+	frame_head.read(_vm->fetchFrameHeader(file, obGraph.getAnimPc()));
+
+	// update player graphic details for on-screen debug info
+	if (_vm->_logic->readVar(ID) == CUR_PLAYER_ID) {
+		_vm->_debugger->_graphType = obGraph.getType();
+		_vm->_debugger->_graphAnimRes = obGraph.getAnimResource();
+		// counting 1st frame as 'frame 1'
+		_vm->_debugger->_graphAnimPc = obGraph.getAnimPc() + 1;
+		_vm->_debugger->_graphNoFrames = anim_head.noAnimFrames;
+	}
+
+	// fill in the BuildUnit structure for this frame
+
+ 	build_unit->anim_resource = obGraph.getAnimResource();
+	build_unit->anim_pc = obGraph.getAnimPc();
+	build_unit->layer_number = 0;
+
+	// Affected by shading mask?
+	if (obGraph.getType() & SHADED_SPRITE)
+		build_unit->shadingFlag = true;
+	else
+		build_unit->shadingFlag = false;
+
+	// Check if this frame has offsets ie. this is a scalable mega frame
+
+	int scale = 0;
+
+	if (cdt_entry.frameType & FRAME_OFFSET) {
+		scale = obMega.calcScale();
+
+		// calc final render coordinates (top-left of sprite), based
+		// on feet coords & scaled offsets
+
+		// add scaled offsets to feet coords
+		build_unit->x = obMega.getFeetX() + (cdt_entry.x * scale) / 256;
+		build_unit->y = obMega.getFeetY() + (cdt_entry.y * scale) / 256;
+
+		// Work out new width and height. Always divide by 256 after
+		// everything else, to maintain accurary
+		build_unit->scaled_width = ((scale * frame_head.width) / 256);
+		build_unit->scaled_height = ((scale * frame_head.height) / 256);
+	} else {
+		// It's a non-scaling anim. Get render coords for sprite, from cdt
+		build_unit->x = cdt_entry.x;
+		build_unit->y = cdt_entry.y;
+
+		// Get width and height
+		build_unit->scaled_width = frame_head.width;
+		build_unit->scaled_height = frame_head.height;
+	}
+
+	// either 0 or required scale, depending on whether 'scale' computed
+	build_unit->scale = scale;
+
+	// calc the bottom y-coord for sorting purposes
+	build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1;
+
+	if (ob_mouse) {
+		// passed a mouse structure, so add to the _mouseList
+		_vm->_mouse->registerMouse(ob_mouse, build_unit);
+
+	}
+
+	_vm->_resman->closeResource(obGraph.getAnimResource());
+}
+
+void Screen::registerFrame(byte *ob_mouse, byte *ob_graph, byte *ob_mega) {
+	ObjectGraphic obGraph(ob_graph);
+
+	// check low word for sprite type
+	switch (obGraph.getType() & 0x0000ffff) {
+	case BGP0_SPRITE:
+		assert(_curBgp0 < MAX_bgp0_sprites);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]);
+		_curBgp0++;
+		break;
+	case BGP1_SPRITE:
+		assert(_curBgp1 < MAX_bgp1_sprites);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp1List[_curBgp1]);
+		_curBgp1++;
+		break;
+	case BACK_SPRITE:
+		assert(_curBack < MAX_back_sprites);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_backList[_curBack]);
+		_curBack++;
+		break;
+	case SORT_SPRITE:
+		assert(_curSort < MAX_sort_sprites);
+		_sortOrder[_curSort] = _curSort;
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_sortList[_curSort]);
+		_curSort++;
+		break;
+	case FORE_SPRITE:
+		assert(_curFore < MAX_fore_sprites);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_foreList[_curFore]);
+		_curFore++;
+		break;
+	case FGP0_SPRITE:
+		assert(_curFgp0 < MAX_fgp0_sprites);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp0List[_curFgp0]);
+		_curFgp0++;
+		break;
+	case FGP1_SPRITE:
+		assert(_curFgp1 < MAX_fgp1_sprites);
+		registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp1List[_curFgp1]);
+		_curFgp1++;
+		break;
+	default:
+		// NO_SPRITE no registering!
+		break;
+	}
+}
+
+// FIXME:
+//
+// The original credits used a different font. I think it's stored in the
+// font.clu file, but I don't know how to interpret it.
+//
+// The original used the entire screen. This version cuts off the top and
+// bottom of the screen, because that's where the menus would usually be.
+//
+// The original had some sort of smoke effect at the bottom of the screen.
+
+enum {
+	LINE_LEFT,
+	LINE_CENTER,
+	LINE_RIGHT
+};
+
+struct CreditsLine {
+	char *str;
+	byte type;
+	int top;
+	int height;
+	byte *sprite;
+
+	CreditsLine() {
+		str = NULL;
+		sprite = NULL;
+	};
+
+	~CreditsLine() {
+		free(str);
+		free(sprite);
+		str = NULL;
+		sprite = NULL;
+	}
+};
+
+#define CREDITS_FONT_HEIGHT 25
+#define CREDITS_LINE_SPACING 20
+
+void Screen::rollCredits() {
+	uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();
+
+	// Prepare for the credits by fading down, stoping the music, etc.
+
+	_vm->_mouse->setMouse(0);
+
+	_vm->_sound->muteFx(true);
+	_vm->_sound->muteSpeech(true);
+
+	waitForFade();
+	fadeDown();
+	waitForFade();
+
+	_vm->_mouse->closeMenuImmediately();
+
+	// There are three files which I believe are involved in showing the
+	// credits:
+	//
+	// credits.bmp  - The "Smacker" logo, stored as follows:
+	//
+	//     width     2 bytes, little endian
+	//     height    2 bytes, little endian
+	//     palette   3 * 256 bytes
+	//     data      width * height bytes
+	//
+	//     Note that the maximum colour component in the palette is 0x3F.
+	//     This is the same resolution as the _paletteMatch table. I doubt
+	//     that this is a coincidence, but let's use the image palette
+	//     directly anyway, just to be safe.
+	//
+	// credits.clu  - The credits text
+	//
+	//     This is simply a text file with CRLF line endings.
+	//     '^' is not shown, but used to mark the center of the line.
+	//     '@' is used as a placeholder for the "Smacker" logo. At least
+	//     when it appears alone.
+	//     Remaining lines are centered.
+	//     The German version also contains character code 9 for no
+	//     apparent reason. We ignore them.
+	//
+	// fonts.clu    - The credits font?
+	//
+	//     FIXME: At this time I don't know how to interpret fonts.clu. For
+	//     now, let's just the standard speech font instead.
+
+	SpriteInfo spriteInfo;
+	Common::File f;
+	int i;
+
+	// Read the "Smacker" logo
+
+	uint16 logoWidth = 0;
+	uint16 logoHeight = 0;
+	byte *logoData = NULL;
+	byte palette[256 * 4];
+
+	if (f.open("credits.bmp")) {
+		logoWidth = f.readUint16LE();
+		logoHeight = f.readUint16LE();
+
+		for (i = 0; i < 256; i++) {
+			palette[i * 4 + 0] = f.readByte() << 2;
+			palette[i * 4 + 1] = f.readByte() << 2;
+			palette[i * 4 + 2] = f.readByte() << 2;
+			palette[i * 4 + 3] = 0;
+		}
+
+		logoData = (byte *)malloc(logoWidth * logoHeight);
+
+		f.read(logoData, logoWidth * logoHeight);
+		f.close();
+	} else {
+		warning("Can't find credits.bmp");
+		memset(palette, 0, sizeof(palette));
+		palette[14 * 4 + 0] = 252;
+		palette[14 * 4 + 1] = 252;
+		palette[14 * 4 + 2] = 252;
+		palette[14 * 4 + 3] = 0;
+	}
+
+	setPalette(0, 256, palette, RDPAL_INSTANT);
+
+	// Read the credits text
+
+	Common::Array<CreditsLine *> creditsLines;
+
+	int lineCount = 0;
+	int lineTop = 400;
+	int paragraphStart = 0;
+	bool hasCenterMark = false;
+
+	if (!f.open("credits.clu")) {
+		warning("Can't find credits.clu");
+		return;
+	}
+
+	while (1) {
+		char buffer[80];
+		char *line = f.readLine(buffer, sizeof(buffer));
+
+		if (!line || *line == 0) {
+			if (!hasCenterMark) {
+				for (i = paragraphStart; i < lineCount; i++)
+					creditsLines[i]->type = LINE_CENTER;
+			}
+			paragraphStart = lineCount;
+			hasCenterMark = false;
+			if (paragraphStart == lineCount)
+				lineTop += CREDITS_LINE_SPACING;
+
+			if (!line)
+				break;
+
+			continue;
+		}
+
+		// The German credits contains character code 9. We don't want
+		// the credits to show the 'dud' symbol, so we replace them
+		// with spaces.
+
+		for (char *ptr = line; *ptr; ptr++) {
+			if (*ptr < 32)
+				*ptr = 32;
+		}
+
+		char *center_mark = strchr(line, '^');
+
+		if (center_mark) {
+			// The current paragraph has at least one center mark.
+			hasCenterMark = true;
+
+			if (center_mark != line) {
+				creditsLines.push_back(new CreditsLine);
+
+				// The center mark is somewhere inside the
+				// line. Split it into left and right side.
+				*center_mark = 0;
+
+				creditsLines[lineCount]->top = lineTop;
+				creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
+				creditsLines[lineCount]->type = LINE_LEFT;
+				creditsLines[lineCount]->str = strdup(line);
+
+				lineCount++;
+				*center_mark = '^';
+			}
+
+			line = center_mark;
+		}
+
+		creditsLines.push_back(new CreditsLine);
+
+		creditsLines[lineCount]->top = lineTop;
+
+		if (*line == '^') {
+			creditsLines[lineCount]->type = LINE_RIGHT;
+			line++;
+		} else
+			creditsLines[lineCount]->type = LINE_LEFT;
+
+		if (strcmp(line, "@") == 0) {
+			creditsLines[lineCount]->height = logoHeight;
+			lineTop += logoHeight;
+		} else {
+			creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
+			lineTop += CREDITS_LINE_SPACING;
+		}
+
+		creditsLines[lineCount]->str = strdup(line);
+		lineCount++;
+	}
+
+	f.close();
+
+	// We could easily add some ScummVM stuff to the credits, if we wanted
+	// to. On the other hand, anyone with the attention span to actually
+	// read all the credits probably already knows. :-)
+
+	// Start the music and roll the credits
+
+	// The credits music (which can also be heard briefly in the "carib"
+	// cutscene) is played once.
+
+	_vm->_sound->streamCompMusic(309, false);
+
+	clearScene();
+	fadeUp(0);
+
+	spriteInfo.scale = 0;
+	spriteInfo.scaledWidth = 0;
+	spriteInfo.scaledHeight = 0;
+	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
+	spriteInfo.blend = 0;
+
+	int startLine = 0;
+	int scrollPos = 0;
+
+	bool abortCredits = false;
+
+	int scrollSteps = lineTop + CREDITS_FONT_HEIGHT;
+	uint32 musicStart = _vm->getMillis();
+
+	// Ideally the music should last just a tiny bit longer than the
+	// credits. Note that musicTimeRemaining() will return 0 if the music
+	// is muted, so we need a sensible fallback for that case.
+
+	uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);
+
+	while (scrollPos < scrollSteps && !_vm->_quit) {
+		clearScene();
+
+		for (i = startLine; i < lineCount; i++) {
+			if (!creditsLines[i])
+				continue;
+
+			// Free any sprites that have scrolled off the screen
+
+			if (creditsLines[i]->top + creditsLines[i]->height < scrollPos) {
+				debug(2, "Freeing line %d: '%s'", i, creditsLines[i]->str);
+
+				delete creditsLines[i];
+				creditsLines[i] = NULL;
+
+				startLine = i + 1;
+			} else if (creditsLines[i]->top < scrollPos + 400) {
+				if (!creditsLines[i]->sprite) {
+					debug(2, "Creating line %d: '%s'", i, creditsLines[i]->str);
+					creditsLines[i]->sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i]->str, 600, 14, _vm->_speechFontId, 0);
+				}
+
+				FrameHeader frame;
+
+				frame.read(creditsLines[i]->sprite);
+
+				spriteInfo.y = creditsLines[i]->top - scrollPos;
+				spriteInfo.w = frame.width;
+				spriteInfo.h = frame.height;
+				spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size();
+
+				switch (creditsLines[i]->type) {
+				case LINE_LEFT:
+					spriteInfo.x = RENDERWIDE / 2 - 5 - frame.width;
+					break;
+				case LINE_RIGHT:
+					spriteInfo.x = RENDERWIDE / 2 + 5;
+					break;
+				case LINE_CENTER:
+					if (strcmp(creditsLines[i]->str, "@") == 0) {
+						spriteInfo.data = logoData;
+						spriteInfo.x = (RENDERWIDE - logoWidth) / 2;
+						spriteInfo.w = logoWidth;
+						spriteInfo.h = logoHeight;
+					} else
+						spriteInfo.x = (RENDERWIDE - frame.width) / 2;
+					break;
+				}
+
+				if (spriteInfo.data)
+					drawSprite(&spriteInfo);
+			} else
+				break;
+		}
+
+		updateDisplay();
+
+		KeyboardEvent *ke = _vm->keyboardEvent();
+
+		if (ke && ke->keycode == 27) {
+			if (!abortCredits) {
+				abortCredits = true;
+				fadeDown();
+			}
+		}
+
+		if (abortCredits && getFadeStatus() == RDFADE_BLACK)
+			break;
+
+		_vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps);
+		scrollPos++;
+	}
+
+	// We're done. Clean up and try to put everything back where it was
+	// before the credits.
+
+	for (i = 0; i < lineCount; i++) {
+		delete creditsLines[i];
+	}
+
+	free(logoData);
+
+	if (!abortCredits) {
+		fadeDown();
+
+		// The music should either have stopped or be about to stop, so
+		// wait for it to really happen.
+
+		while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
+			updateDisplay(false);
+			_vm->_system->delayMillis(100);
+		}
+	}
+
+	if (_vm->_quit)
+		return;
+
+	waitForFade();
+
+	_vm->_sound->muteFx(false);
+	_vm->_sound->muteSpeech(false);
+
+	if (loopingMusicId)
+		_vm->_sound->streamCompMusic(loopingMusicId, true);
+	else
+		_vm->_sound->stopMusic(false);
+
+	if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
+		_vm->_mouse->setMouse(NORMAL_MOUSE_ID);
+
+	if (_vm->_logic->readVar(DEAD))
+		_vm->_mouse->buildSystemMenu();
+}
+
+// This image used to be shown by CacheNewCluster() while copying a data file
+// from the CD to the hard disk. ScummVM doesn't do that, so the image is never
+// shown. It'd be nice if we could do something useful with it some day...
+
+void Screen::splashScreen() {
+	byte *bgfile = _vm->_resman->openResource(2950);
+
+	initialiseBackgroundLayer(NULL);
+	initialiseBackgroundLayer(NULL);
+	initialiseBackgroundLayer(_vm->fetchBackgroundLayer(bgfile));
+	initialiseBackgroundLayer(NULL);
+	initialiseBackgroundLayer(NULL);
+
+	setPalette(0, 256, _vm->fetchPalette(bgfile), RDPAL_FADE);
+	renderParallax(_vm->fetchBackgroundLayer(bgfile), 2);
+
+	closeBackgroundLayer();
+
+	byte *loadingBar = _vm->_resman->openResource(2951);
+	byte *frame = _vm->fetchFrameHeader(loadingBar, 0);
+
+	AnimHeader animHead;
+	CdtEntry cdt;
+	FrameHeader frame_head;
+
+	animHead.read(_vm->fetchAnimHeader(loadingBar));
+	cdt.read(_vm->fetchCdtEntry(loadingBar, 0));
+	frame_head.read(_vm->fetchFrameHeader(loadingBar, 0));
+
+	SpriteInfo barSprite;
+
+	barSprite.x = cdt.x;
+	barSprite.y = cdt.y;
+	barSprite.w = frame_head.width;
+	barSprite.h = frame_head.height;
+	barSprite.scale = 0;
+	barSprite.scaledWidth = 0;
+	barSprite.scaledHeight = 0;
+	barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS;
+	barSprite.blend = 0;
+	barSprite.colourTable = 0;
+	barSprite.data = frame + FrameHeader::size();
+
+	drawSprite(&barSprite);
+
+	fadeUp();
+	waitForFade();
+
+	for (int i = 0; i < animHead.noAnimFrames; i++) {
+		frame = _vm->fetchFrameHeader(loadingBar, i);
+		barSprite.data = frame + FrameHeader::size();
+		drawSprite(&barSprite);
+		updateDisplay();
+		_vm->_system->delayMillis(30);
+	}
+
+	_vm->_resman->closeResource(2951);
+
+	fadeDown();
+	waitForFade();
+}
+
+} // End of namespace Sword2

Copied: scummvm/trunk/engines/sword2/screen.h (from rev 20651, scummvm/trunk/engines/sword2/build_display.h)
===================================================================
--- scummvm/trunk/engines/sword2/screen.h	                        (rev 0)
+++ scummvm/trunk/engines/sword2/screen.h	2006-02-12 19:38:26 UTC (rev 20652)
@@ -0,0 +1,441 @@
+/* Copyright (C) 1994-1998 Revolution Software Ltd.
+ * Copyright (C) 2003-2006 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef	_BUILD_DISPLAY
+#define	_BUILD_DISPLAY
+
+#include "common/rect.h"
+#include "common/stream.h"
+
+#define MAX_bgp0_sprites 6
+#define MAX_bgp1_sprites 6
+#define MAX_back_sprites 30
+#define MAX_sort_sprites 30
+#define MAX_fore_sprites 30
+#define MAX_fgp0_sprites 6
+#define MAX_fgp1_sprites 6
+
+#define PALTABLESIZE     (64 * 64 * 64)
+
+#define BLOCKWIDTH       64
+#define BLOCKHEIGHT      64
+#define MAXLAYERS        5
+
+#define MENUDEEP         40
+#define RENDERWIDE       640
+#define RENDERDEEP       (480 - (MENUDEEP * 2))
+
+// 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 {
+
+class Sword2Engine;
+
+// Sprite defines
+
+enum {
+	// This is the low byte part of the sprite type.
+
+	RDSPR_TRANS			= 0x0001,
+	RDSPR_BLEND			= 0x0004,
+	RDSPR_FLIP			= 0x0008,
+	RDSPR_SHADOW			= 0x0010,
+	RDSPR_DISPLAYALIGN		= 0x0020,
+	RDSPR_NOCOMPRESSION		= 0x0040,
+	RDSPR_EDGEBLEND			= 0x0080,	// Unused
+
+	// This is the high byte part of the sprite type, which defines what
+	// type of compression is used. Unless RDSPR_NOCOMPRESSION is set.
+
+	RDSPR_RLE16			= 0x0000,
+	RDSPR_RLE256			= 0x0100,
+	RDSPR_RLE256FAST		= 0x0200
+};
+
+// Fading defines
+
+enum {
+	RDFADE_NONE,
+	RDFADE_UP,
+	RDFADE_DOWN,
+	RDFADE_BLACK
+};
+
+// Palette defines
+
+enum {
+	RDPAL_FADE,
+	RDPAL_INSTANT
+};
+
+// Blitting FX defines
+
+enum {
+	RDBLTFX_SPRITEBLEND		= 0x01,
+	RDBLTFX_SHADOWBLEND		= 0x02,
+	RDBLTFX_EDGEBLEND		= 0x04
+};
+
+// 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;
+};
+
+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 buildDisplay()
+	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;
+};
+
+struct Parallax {
+	uint16 w;
+	uint16 h;
+
+	// The dimensions are followed by an offset table, but we don't know in
+	// advance how big it is. See initializeBackgroundLayer().
+
+	static const int size() {
+		return 4;
+	}
+
+	void read(byte *addr) {
+		Common::MemoryReadStream readS(addr, size());
+
+		w = readS.readUint16LE();
+		h = readS.readUint16LE();
+	}
+
+	void write(byte *addr) {
+		Common::MemoryWriteStream writeS(addr, size());
+
+		writeS.writeUint16LE(w);
+		writeS.writeUint16LE(h);
+	}
+};
+
+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(byte *ob_mouse, byte *ob_graph, byte *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(byte *ptr, 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(byte *parallax);
+	void closeBackgroundLayer();
+
+	void initialiseRenderCycle();
+
+	void initBackground(int32 res, int32 new_palette);
+	void registerFrame(byte *ob_mouse, byte *ob_graph, byte *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(int x, int y, uint8 colour);
+	void drawLine(int x0, int y0, int x1, int y1, uint8 colour);
+
+#ifdef BACKEND_8BIT
+	void plotYUV(byte *lut, int width, int height, byte *const *dat);
+#endif
+
+	void rollCredits();
+	void splashScreen();
+};
+
+} // End of namespace Sword2
+
+#endif







More information about the Scummvm-git-logs mailing list