[Scummvm-cvs-logs] scummvm master -> f5a1b626b710c368e79ab27c13cf2be4ccdcb30f

dreammaster dreammaster at scummvm.org
Mon Jun 8 14:32:52 CEST 2015


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

Summary:
f5a1b626b7 SHERLOCK: Move Scalpel map code to ScalpelMap


Commit: f5a1b626b710c368e79ab27c13cf2be4ccdcb30f
    https://github.com/scummvm/scummvm/commit/f5a1b626b710c368e79ab27c13cf2be4ccdcb30f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2015-06-08T08:31:51-04:00

Commit Message:
SHERLOCK: Move Scalpel map code to ScalpelMap

Changed paths:
    engines/sherlock/map.cpp
    engines/sherlock/map.h
    engines/sherlock/objects.cpp
    engines/sherlock/people.cpp
    engines/sherlock/people.h
    engines/sherlock/scalpel/scalpel.cpp
    engines/sherlock/scalpel/scalpel_map.cpp
    engines/sherlock/scalpel/scalpel_map.h
    engines/sherlock/scalpel/scalpel_people.cpp
    engines/sherlock/scalpel/scalpel_people.h
    engines/sherlock/scalpel/scalpel_scene.cpp
    engines/sherlock/scalpel/scalpel_scene.h
    engines/sherlock/scalpel/scalpel_talk.cpp
    engines/sherlock/scene.cpp
    engines/sherlock/scene.h
    engines/sherlock/tattoo/tattoo_map.cpp
    engines/sherlock/tattoo/tattoo_map.h
    engines/sherlock/tattoo/tattoo_people.cpp
    engines/sherlock/tattoo/tattoo_people.h
    engines/sherlock/tattoo/tattoo_scene.cpp
    engines/sherlock/tattoo/tattoo_scene.h



diff --git a/engines/sherlock/map.cpp b/engines/sherlock/map.cpp
index 3f9c9f5..fbccaf2 100644
--- a/engines/sherlock/map.cpp
+++ b/engines/sherlock/map.cpp
@@ -28,31 +28,6 @@
 
 namespace Sherlock {
 
-MapPaths::MapPaths() {
-	_numLocations = 0;
-}
-
-void MapPaths::load(int numLocations, Common::SeekableReadStream &s) {
-	_numLocations = numLocations;
-	_paths.resize(_numLocations * _numLocations);
-
-	for (int idx = 0; idx < (numLocations * numLocations); ++idx) {
-		Common::Array<byte> &path = _paths[idx];
-		int v;
-
-		do {
-			v = s.readByte();
-			path.push_back(v);
-		} while (v && v < 254);
-	}
-}
-
-const byte *MapPaths::getPath(int srcLocation, int destLocation) {
-	return &_paths[srcLocation * _numLocations + destLocation][0];
-}
-
-/*----------------------------------------------------------------*/
-
 Map *Map::init(SherlockEngine *vm) {
 	if (vm->getGameID() == GType_SerratedScalpel)
 		return new Scalpel::ScalpelMap(vm);
@@ -60,506 +35,9 @@ Map *Map::init(SherlockEngine *vm) {
 		return new Tattoo::TattooMap(vm);
 }
 
-Map::Map(SherlockEngine *vm): _vm(vm), _topLine(g_system->getWidth(), 12, vm->getPlatform()) {
-	_active = false;
-	_mapCursors = nullptr;
-	_shapes = nullptr;
-	_iconShapes = nullptr;
-	_point = 0;
-	_placesShown = false;
-	_cursorIndex = -1;
-	_drawMap = false;
-	_overPos = Point32(130 * FIXED_INT_MULTIPLIER, 126 * FIXED_INT_MULTIPLIER);
-	_charPoint = 0;
-	_oldCharPoint = 0;
-	_frameChangeFlag = false;
-
-	// Initialise the initial walk sequence set
-	_walkSequences.resize(MAX_HOLMES_SEQUENCE);
-	for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
-		_walkSequences[idx]._sequences.resize(MAX_FRAME);
-		Common::fill(&_walkSequences[idx]._sequences[0], &_walkSequences[idx]._sequences[0] + MAX_FRAME, 0);
-	}
-
-	if (!_vm->isDemo())
-		loadData();
-}
-
-void Map::loadPoints(int count, const int *xList, const int *yList, const int *transList) {
-	for (int idx = 0; idx < count; ++idx, ++xList, ++yList, ++transList) {
-		_points.push_back(MapEntry(*xList, *yList, *transList));
-	}
-}
-
-void Map::loadSequences(int count, const byte *seq) {
-	for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME)
-		Common::copy(seq, seq + MAX_FRAME, &_walkSequences[idx]._sequences[0]);
-}
-
-void Map::loadData() {
-	// TODO: Remove this
-	if (_vm->getGameID() == GType_RoseTattoo)
-		return;
-
-	// Load the list of location names
-	Common::SeekableReadStream *txtStream = _vm->_res->load(
-		_vm->getGameID() == GType_SerratedScalpel ? "chess.txt" : "map.txt");
-
-	int streamSize = txtStream->size();
-	while (txtStream->pos() < streamSize) {
-		Common::String line;
-		char c;
-		while ((c = txtStream->readByte()) != '\0')
-			line += c;
-
-		_locationNames.push_back(line);
-	}
-
-	delete txtStream;
-
-	// Load the path data
-	Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth");
-
-	// Get routes between different locations on the map
-	_paths.load(31, *pathStream);
-
-	// Load in the co-ordinates that the paths refer to
-	_pathPoints.resize(208);
-	for (uint idx = 0; idx < _pathPoints.size(); ++idx) {
-		_pathPoints[idx].x = pathStream->readSint16LE();
-		_pathPoints[idx].y = pathStream->readSint16LE();
-	}
-
-	delete pathStream;
-}
-
-int Map::show() {
-	Events &events = *_vm->_events;
-	People &people = *_vm->_people;
-	Screen &screen = *_vm->_screen;
-	bool changed = false, exitFlag = false;
-	_active = true;
-
-	// Set font and custom cursor for the map
-	int oldFont = screen.fontNumber();
-	screen.setFont(0);
-
-	// Initial screen clear
-	screen._backBuffer1.clear();
-	screen.clear();
-
-	// Load the entire map
-	ImageFile bigMap("bigmap.vgs");
-	screen.setPalette(bigMap._palette);
-
-	// Load need sprites
-	setupSprites();
-
-	screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
-	screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-	screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
-	screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-
-	_drawMap = true;
-	_charPoint = -1;
-	_point = -1;
-	people[AL]._position = _lDrawnPos = _overPos;
-
-	// Show place icons
-	showPlaces();
-	saveTopLine();
-	_placesShown = true;
-
-	// Keep looping until either a location is picked, or the game is ended
-	while (!_vm->shouldQuit() && !exitFlag) {
-		events.pollEventsAndWait();
-		events.setButtonState();
-
-		// Keyboard handling
-		if (events.kbHit()) {
-			Common::KeyState keyState = events.getKey();
-
-			if (keyState.keycode == Common::KEYCODE_RETURN || keyState.keycode == Common::KEYCODE_SPACE) {
-				// Both space and enter simulate a mouse release
-				events._pressed = false;
-				events._released = true;
-				events._oldButtons = 0;
-			}
-		}
-
-		// Ignore scrolling attempts until the screen is drawn
-		if (!_drawMap) {
-			Common::Point pt = events.mousePos();
-
-			// Check for vertical map scrolling
-			if ((pt.y > (SHERLOCK_SCREEN_HEIGHT - 10) && _bigPos.y < 200) || (pt.y < 10 && _bigPos.y > 0)) {
-				if (pt.y > (SHERLOCK_SCREEN_HEIGHT - 10))
-					_bigPos.y += 10;
-				else
-					_bigPos.y -= 10;
-
-				changed = true;
-			}
-
-			// Check for horizontal map scrolling
-			if ((pt.x > (SHERLOCK_SCREEN_WIDTH - 10) && _bigPos.x < 315) || (pt.x < 10 && _bigPos.x > 0)) {
-				if (pt.x > (SHERLOCK_SCREEN_WIDTH - 10))
-					_bigPos.x += 15;
-				else
-					_bigPos.x -= 15;
-
-				changed = true;
-			}
-		}
-
-		if (changed) {
-			// Map has scrolled, so redraw new map view
-			changed = false;
-
-			screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
-			screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-			screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
-			screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
-
-			showPlaces();
-			_placesShown = false;
-
-			saveTopLine();
-			_savedPos.x = -1;
-			updateMap(true);
-		} else if (!_drawMap) {
-			if (!_placesShown) {
-				showPlaces();
-				_placesShown = true;
-			}
-
-			if (_cursorIndex == 0) {
-				Common::Point pt = events.mousePos();
-				highlightIcon(Common::Point(pt.x - 4 + _bigPos.x, pt.y + _bigPos.y));
-			}
-			updateMap(false);
-		}
-
-		if ((events._released || events._rightReleased) && _point != -1) {
-			if (people[AL]._walkCount == 0) {
-				people._walkDest = _points[_point] + Common::Point(4, 9);
-				_charPoint = _point;
-
-				// Start walking to selected location
-				walkTheStreets();
-
-				// Show wait cursor
-				_cursorIndex = 1;
-				events.setCursor((*_mapCursors)[_cursorIndex]._frame);
-			}
-		}
-
-		// Check if a scene has beeen selected and we've finished "moving" to it
-		if (people[AL]._walkCount == 0) {
-			if (_charPoint >= 1 && _charPoint < (int)_points.size())
-				exitFlag = true;
-		}
-
-		if (_drawMap) {
-			_drawMap = false;
-
-			if (screen._fadeStyle)
-				screen.randomTransition();
-			else
-				screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
-		}
-
-		// Wait for a frame
-		events.wait(1);
-	}
-
-	freeSprites();
-	_overPos = people[AL]._position;
-
-	// Reset font
-	screen.setFont(oldFont);
-
-	_active = false;
-	return _charPoint;
-}
-
-void Map::setupSprites() {
-	Events &events = *_vm->_events;
-	People &people = *_vm->_people;
-	Scene &scene = *_vm->_scene;
-	_savedPos.x = -1;
-
-	_mapCursors = new ImageFile("omouse.vgs");
-	_cursorIndex = 0;
-	events.setCursor((*_mapCursors)[_cursorIndex]._frame);
-
-	_shapes = new ImageFile("mapicon.vgs");
-	_iconShapes = new ImageFile("overicon.vgs");
-	_iconSave.create((*_shapes)[4]._width, (*_shapes)[4]._height, _vm->getPlatform());
-	Person &p = people[AL];
-	p._description = " ";
-	p._type = CHARACTER;
-	p._position = Common::Point(12400, 5000);
-	p._sequenceNumber = 0;
-	p._images = _shapes;
-	p._imageFrame = nullptr;
-	p._frameNumber = 0;
-	p._delta = Common::Point(0, 0);
-	p._oldSize = Common::Point(0, 0);
-	p._oldSize = Common::Point(0, 0);
-	p._misc = 0;
-	p._walkCount = 0;
-	p._allow = 0;
-	p._noShapeSize = Common::Point(0, 0);
-	p._goto = Common::Point(28000, 15000);
-	p._status = 0;
-	p._walkSequences = _walkSequences;
-	p.setImageFrame();
-	scene._bgShapes.clear();
-}
-
-void Map::freeSprites() {
-	delete _mapCursors;
-	delete _shapes;
-	delete _iconShapes;
-	_iconSave.free();
-}
-
-void Map::showPlaces() {
-	Screen &screen = *_vm->_screen;
-
-	for (uint idx = 0; idx < _points.size(); ++idx) {
-		const MapEntry &pt = _points[idx];
-
-		if (pt.x != 0 && pt.y != 0) {
-			if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH
-					&& pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) {
-				if (_vm->readFlags(idx)) {
-					screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate],
-						Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12));
-				}
-			}
-		}
-	}
-}
-
-void Map::saveTopLine() {
-	_topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
-}
-
-void Map::eraseTopLine() {
-	Screen &screen = *_vm->_screen;
-	screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
-	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
-}
-
-void Map::showPlaceName(int idx, bool highlighted) {
-	People &people = *_vm->_people;
-	Screen &screen = *_vm->_screen;
-
-	Common::String name = _locationNames[idx];
-	int width = screen.stringWidth(name);
-
-	if (!_cursorIndex) {
-		saveIcon(people[AL]._imageFrame, _lDrawnPos);
-
-		bool flipped = people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
-			|| people[AL]._sequenceNumber == MAP_UPLEFT;
-		screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, _lDrawnPos, flipped);
-	}
-
-	if (highlighted) {
-		int xp = (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(name)) / 2;
-		screen.gPrint(Common::Point(xp + 2, 2), 0, "%s", name.c_str());
-		screen.gPrint(Common::Point(xp + 1, 1), 0, "%s", name.c_str());
-		screen.gPrint(Common::Point(xp, 0), 12, "%s", name.c_str());
-
-		screen.slamArea(xp, 0, width + 2, 15);
-	}
-}
-
-void Map::updateMap(bool flushScreen) {
-	Events &events = *_vm->_events;
-	People &people = *_vm->_people;
-	Screen &screen = *_vm->_screen;
-	Common::Point osPos = _savedPos;
-	Common::Point osSize = _savedSize;
-	Common::Point hPos;
-
-	if (_cursorIndex >= 1) {
-		if (++_cursorIndex > (1 + 8))
-			_cursorIndex = 1;
-
-		events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]._frame);
-	}
-
-	if (!_drawMap && !flushScreen)
-		restoreIcon();
-	else
-		_savedPos.x = -1;
-
-	people[AL].adjustSprite();
-
-	_lDrawnPos.x = hPos.x = people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x;
-	_lDrawnPos.y = hPos.y = people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y;
-
-	// Draw the person icon
-	saveIcon(people[AL]._imageFrame, hPos);
-	if (people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
-			|| people[AL]._sequenceNumber == MAP_UPLEFT)
-		screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, true);
-	else
-		screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, false);
-
-	if (flushScreen) {
-		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
-	} else if (!_drawMap) {
-		if (hPos.x > 0 && hPos.y >= 0 && hPos.x < SHERLOCK_SCREEN_WIDTH && hPos.y < SHERLOCK_SCREEN_HEIGHT)
-			screen.flushImage(people[AL]._imageFrame, Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x,
-			people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y),
-			&people[AL]._oldPosition.x, &people[AL]._oldPosition.y, &people[AL]._oldSize.x, &people[AL]._oldSize.y);
-
-		if (osPos.x != -1)
-			screen.slamArea(osPos.x, osPos.y, osSize.x, osSize.y);
-	}
-}
-
-void Map::walkTheStreets() {
-	People &people = *_vm->_people;
-	Common::Array<Common::Point> tempPath;
-
-	// Get indexes into the path lists for the start and destination scenes
-	int start = _points[_oldCharPoint]._translate;
-	int dest = _points[_charPoint]._translate;
-
-	// Get pointer to start of path
-	const byte *path = _paths.getPath(start, dest);
-
-	// Add in destination position
-	people._walkTo.clear();
-	Common::Point destPos = people._walkDest;
-
-	// Check for any intermediate points between the two locations
-	if (path[0] || _charPoint > 50 || _oldCharPoint > 50) {
-		people[AL]._sequenceNumber = -1;
-
-		if (_charPoint == 51 || _oldCharPoint == 51) {
-			people.setWalking();
-		} else {
-			bool reversePath = false;
-
-			// Check for moving the path backwards or forwards
-			if (path[0] == 255) {
-				reversePath = true;
-				SWAP(start, dest);
-				path = _paths.getPath(start, dest);
-			}
-
-			do {
-				int idx = *path++;
-				tempPath.push_back(_pathPoints[idx - 1] + Common::Point(4, 4));
-			} while (*path != 254);
-
-			// Load up the path to use
-			people._walkTo.clear();
-
-			if (reversePath) {
-				for (int idx = (int)tempPath.size() - 1; idx >= 0; --idx)
-					people._walkTo.push(tempPath[idx]);
-			} else {
-				for (int idx = 0; idx < (int)tempPath.size(); ++idx)
-					people._walkTo.push(tempPath[idx]);
-			}
-
-			people._walkDest = people._walkTo.pop() + Common::Point(12, 6);
-			people.setWalking();
-		}
-	} else {
-		people[AL]._walkCount = 0;
-	}
-
-	// Store the final destination icon position
-	people._walkTo.push(destPos);
-}
-
-void Map::saveIcon(ImageFrame *src, const Common::Point &pt) {
-	Screen &screen = *_vm->_screen;
-	Common::Point size(src->_width, src->_height);
-	Common::Point pos = pt;
-
-	if (pos.x < 0) {
-		size.x += pos.x;
-		pos.x = 0;
-	}
-
-	if (pos.y < 0) {
-		size.y += pos.y;
-		pos.y = 0;
-	}
-
-	if ((pos.x + size.x) > SHERLOCK_SCREEN_WIDTH)
-		size.x -= (pos.x + size.x) - SHERLOCK_SCREEN_WIDTH;
-
-	if ((pos.y + size.y) > SHERLOCK_SCREEN_HEIGHT)
-		size.y -= (pos.y + size.y) - SHERLOCK_SCREEN_HEIGHT;
-
-	if (size.x < 1 || size.y < 1 || pos.x >= SHERLOCK_SCREEN_WIDTH || pos.y >= SHERLOCK_SCREEN_HEIGHT || _drawMap) {
-		// Flag as the area not needing to be saved
-		_savedPos.x = -1;
-		return;
-	}
-
-	assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
-	_iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
-		Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
-	_savedPos = pos;
-	_savedSize = size;
-}
-
-void Map::restoreIcon() {
-	Screen &screen = *_vm->_screen;
-
-	if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH
-			&& _savedPos.y < SHERLOCK_SCREEN_HEIGHT)
-		screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
-}
-
-void Map::highlightIcon(const Common::Point &pt) {
-	int oldPoint = _point;
-
-	// Iterate through the icon list
-	bool done = false;
-	for (int idx = 0; idx < (int)_points.size(); ++idx) {
-		const MapEntry &entry = _points[idx];
-
-		// Check whether the mouse is over a given icon
-		if (entry.x != 0 && entry.y != 0) {
-			if (Common::Rect(entry.x - 8, entry.y - 8, entry.x + 9, entry.y + 9).contains(pt)) {
-				done = true;
-
-				if (_point != idx && _vm->readFlags(idx)) {
-					// Changed to a new valid (visible) location
-					eraseTopLine();
-					showPlaceName(idx, true);
-					_point = idx;
-				}
-			}
-		}
-	}
-
-	if (!done) {
-		// No icon was highlighted
-		if (_point != -1) {
-			// No longer highlighting previously highlighted icon, so erase it
-			showPlaceName(_point, false);
-			eraseTopLine();
-		}
-
-		_point = -1;
-	} else if (oldPoint != -1 && oldPoint != _point) {
-		showPlaceName(oldPoint, false);
-		eraseTopLine();
-	}
+Map::Map(SherlockEngine *vm) : _vm(vm) {
+	_charPoint = _oldCharPoint = 0;
+	_active = _frameChangeFlag = false;
 }
 
 void Map::synchronize(Serializer &s) {
@@ -570,4 +48,5 @@ void Map::synchronize(Serializer &s) {
 	s.syncAsSint16LE(_oldCharPoint);
 }
 
+
 } // End of namespace Sherlock
diff --git a/engines/sherlock/map.h b/engines/sherlock/map.h
index d47edb2..2569e18 100644
--- a/engines/sherlock/map.h
+++ b/engines/sherlock/map.h
@@ -23,12 +23,6 @@
 #ifndef SHERLOCK_MAP_H
 #define SHERLOCK_MAP_H
 
-#include "common/scummsys.h"
-#include "common/array.h"
-#include "common/rect.h"
-#include "common/str.h"
-#include "common/str-array.h"
-#include "sherlock/surface.h"
 #include "sherlock/objects.h"
 #include "sherlock/saveload.h"
 
@@ -36,140 +30,24 @@ namespace Sherlock {
 
 class SherlockEngine;
 
-struct MapEntry : Common::Point {
-	int _translate;
-
-	MapEntry() : Common::Point(), _translate(-1) {}
-
-	MapEntry(int posX, int posY, int translate) : Common::Point(posX, posY), _translate(translate) {}
-};
-
-class MapPaths {
-private:
-	int _numLocations;
-	Common::Array< Common::Array<byte> > _paths;
-
-public:
-	MapPaths();
-
-	/**
-	 * Load the data for the paths between locations on the map
-	 */
-	void load(int numLocations, Common::SeekableReadStream &s);
-
-	/**
-	 * Get the path between two locations on the map
-	 */
-	const byte *getPath(int srcLocation, int destLocation);
-};
-
 class Map {
 protected:
 	SherlockEngine *_vm;
-	Common::Array<MapEntry> _points;	// Map locations for each scene
-	Common::StringArray _locationNames;
-	MapPaths _paths;
-	Common::Array<Common::Point> _pathPoints;
-	Common::Point _savedPos;
-	Common::Point _savedSize;
-	Surface _topLine;
-	ImageFile *_mapCursors;
-	ImageFile *_shapes;
-	ImageFile *_iconShapes;
-	WalkSequences _walkSequences;
-	Point32 _lDrawnPos;
-	int _point;
-	bool _placesShown;
-	int _cursorIndex;
-	bool _drawMap;
-	Surface _iconSave;
-protected:
-	Map(SherlockEngine *vm);
-
-	/**
-	 * Load data  needed for the map
-	 */
-	void loadData();
-
-	/**
-	 * Load and initialize all the sprites that are needed for the map display
-	 */
-	void setupSprites();
-
-	/**
-	 * Free the sprites and data used by the map
-	 */
-	void freeSprites();
-
-	/**
-	 * Draws an icon for every place that's currently known
-	 */
-	void showPlaces();
-
-	/**
-	 * Makes a copy of the top rows of the screen that are used to display location names
-	 */
-	void saveTopLine();
 
-	/**
-	 * Erases anything shown in the top line by restoring the previously saved original map background
-	 */
-	void eraseTopLine();
-
-	/**
-	 * Prints the name of the specified icon
-	 */
-	void showPlaceName(int idx, bool highlighted);
-
-	/**
-	 * Update all on-screen sprites to account for any scrolling of the map
-	 */
-	void updateMap(bool flushScreen);
-
-	/**
-	 * Handle moving icon for player from their previous location on the map to a destination location
-	 */
-	void walkTheStreets();
-
-	/**
-	 * Save the area under the player's icon
-	 */
-	void saveIcon(ImageFrame *src, const Common::Point &pt);
-
-	/**
-	 * Restore the area under the player's icon
-	 */
-	void restoreIcon();
-
-	/**
-	 * Handles highlighting map icons, showing their names
-	 */
-	void highlightIcon(const Common::Point &pt);
+	Map(SherlockEngine *vm);
 public:
-	bool _active;
 	Point32 _overPos;
 	Point32 _bigPos;
 	int _charPoint, _oldCharPoint;
+	bool _active;
 	bool _frameChangeFlag;
 public:
 	static Map *init(SherlockEngine *vm);
 
-	const MapEntry &operator[](int idx) { return _points[idx]; }
-
-	/**
-	 * Loads the list of points for locations on the map for each scene
-	 */
-	void loadPoints(int count, const int *xList, const int *yList, const int *transList);
-
-	/**
-	 * Load the sequence data for player icon animations
-	 */
-	void loadSequences(int count, const byte *seq);
-
 	/**
 	 * Show the map
 	 */
-	int show();
+	virtual int show() = 0;
 
 	/**
 	 * Synchronize the data for a savegame
diff --git a/engines/sherlock/objects.cpp b/engines/sherlock/objects.cpp
index 1e57d00..d27cbed 100644
--- a/engines/sherlock/objects.cpp
+++ b/engines/sherlock/objects.cpp
@@ -25,6 +25,7 @@
 #include "sherlock/objects.h"
 #include "sherlock/people.h"
 #include "sherlock/scene.h"
+#include "sherlock/scalpel/scalpel_map.h"
 #include "sherlock/scalpel/scalpel_people.h"
 
 namespace Sherlock {
@@ -1212,7 +1213,6 @@ void Object::setObjTalkSequence(int seq) {
 }
 
 int Object::checkNameForCodes(const Common::String &name, const char *const messages[]) {
-	Map &map = *_vm->_map;
 	People &people = *_vm->_people;
 	Scene &scene = *_vm->_scene;
 	Screen &screen = *_vm->_screen;
@@ -1257,9 +1257,12 @@ int Object::checkNameForCodes(const Common::String &name, const char *const mess
 			if (ch >= '0' && ch <= '9') {
 				scene._goToScene = atoi(name.c_str() + 1);
 
-				if (IS_SERRATED_SCALPEL && scene._goToScene < 97 && map[scene._goToScene].x) {
-					map._overPos.x = (map[scene._goToScene].x - 6) * FIXED_INT_MULTIPLIER;
-					map._overPos.y = (map[scene._goToScene].y + 9) * FIXED_INT_MULTIPLIER;
+				if (IS_SERRATED_SCALPEL && scene._goToScene < 97) {
+					Scalpel::ScalpelMap &map = *(Scalpel::ScalpelMap *)_vm->_map;
+					if (map[scene._goToScene].x) {
+						map._overPos.x = (map[scene._goToScene].x - 6) * FIXED_INT_MULTIPLIER;
+						map._overPos.y = (map[scene._goToScene].y + 9) * FIXED_INT_MULTIPLIER;
+					}
 				}
 
 				const char *p;
diff --git a/engines/sherlock/people.cpp b/engines/sherlock/people.cpp
index 9416ae9..143e532 100644
--- a/engines/sherlock/people.cpp
+++ b/engines/sherlock/people.cpp
@@ -425,56 +425,6 @@ assert(_player._position.y >= 10000);/***DEBUG****/
 		_player._frameNumber = oldFrame;
 }
 
-void People::gotoStand(Sprite &sprite) {
-	Map &map = *_vm->_map;
-	_walkTo.clear();
-	sprite._walkCount = 0;
-
-	switch (sprite._sequenceNumber) {
-	case Scalpel::WALK_UP:
-		sprite._sequenceNumber = Scalpel::STOP_UP;
-		break;
-	case Scalpel::WALK_DOWN:
-		sprite._sequenceNumber = Scalpel::STOP_DOWN;
-		break;
-	case Scalpel::TALK_LEFT:
-	case Scalpel::WALK_LEFT:
-		sprite._sequenceNumber = Scalpel::STOP_LEFT;
-		break;
-	case Scalpel::TALK_RIGHT:
-	case Scalpel::WALK_RIGHT:
-		sprite._sequenceNumber = Scalpel::STOP_RIGHT;
-		break;
-	case Scalpel::WALK_UPRIGHT:
-		sprite._sequenceNumber = Scalpel::STOP_UPRIGHT;
-		break;
-	case Scalpel::WALK_UPLEFT:
-		sprite._sequenceNumber = Scalpel::STOP_UPLEFT;
-		break;
-	case Scalpel::WALK_DOWNRIGHT:
-		sprite._sequenceNumber = Scalpel::STOP_DOWNRIGHT;
-		break;
-	case Scalpel::WALK_DOWNLEFT:
-		sprite._sequenceNumber = Scalpel::STOP_DOWNLEFT;
-		break;
-	default:
-		break;
-	}
-
-	// Only restart frame at 0 if the sequence number has changed
-	if (_oldWalkSequence != -1 || sprite._sequenceNumber == Scalpel::STOP_UP)
-		sprite._frameNumber = 0;
-
-	if (map._active) {
-		sprite._sequenceNumber = 0;
-		_player._position.x = (map[map._charPoint].x - 6) * FIXED_INT_MULTIPLIER;
-		_player._position.y = (map[map._charPoint].y + 10) * FIXED_INT_MULTIPLIER;
-	}
-
-	_oldWalkSequence = -1;
-	_allowWalkAbort = true;
-}
-
 void People::walkToCoords(const Point32 &destPos, int destDir) {
 	Events &events = *_vm->_events;
 	Scene &scene = *_vm->_scene;
diff --git a/engines/sherlock/people.h b/engines/sherlock/people.h
index c4abf39..c15248c 100644
--- a/engines/sherlock/people.h
+++ b/engines/sherlock/people.h
@@ -159,12 +159,6 @@ public:
 	void setWalking();
 
 	/**
-	 * Bring a moving character to a standing position. If the Scalpel chessboard
-	 * is being displayed, then the chraracter will always face down.
-	 */
-	void gotoStand(Sprite &sprite);
-
-	/**
 	 * Walk to the co-ordinates passed, and then face the given direction
 	 */
 	void walkToCoords(const Point32 &destPos, int destDir);
@@ -195,6 +189,12 @@ public:
 	 * Change the sequence of the scene background object associated with the current speaker.
 	 */
 	virtual void setTalkSequence(int speaker, int sequenceNum = 1) = 0;
+
+	/**
+	 * Bring a moving character to a standing position. If the Scalpel chessboard
+	 * is being displayed, then the chraracter will always face down.
+	 */
+	virtual void gotoStand(Sprite &sprite) = 0;
 };
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel.cpp b/engines/sherlock/scalpel/scalpel.cpp
index f6a6bc9..abca299 100644
--- a/engines/sherlock/scalpel/scalpel.cpp
+++ b/engines/sherlock/scalpel/scalpel.cpp
@@ -22,6 +22,7 @@
 
 #include "engines/util.h"
 #include "sherlock/scalpel/scalpel.h"
+#include "sherlock/scalpel/scalpel_map.h"
 #include "sherlock/scalpel/scalpel_people.h"
 #include "sherlock/scalpel/scalpel_scene.h"
 #include "sherlock/scalpel/tsage/logo.h"
@@ -205,9 +206,10 @@ void ScalpelEngine::initialize() {
 
 	if (!isDemo()) {
 		// Load the map co-ordinates for each scene and sequence data
-		_map->loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
-		_map->loadSequences(3, &MAP_SEQUENCES[0][0]);
-		_map->_oldCharPoint = BAKER_ST_EXTERIOR;
+		ScalpelMap &map = *(ScalpelMap *)_map;
+		map.loadPoints(NUM_PLACES, &MAP_X[0], &MAP_Y[0], &MAP_TRANSLATE[0]);
+		map.loadSequences(3, &MAP_SEQUENCES[0][0]);
+		map._oldCharPoint = BAKER_ST_EXTERIOR;
 	}
 
 	// Load the inventory
diff --git a/engines/sherlock/scalpel/scalpel_map.cpp b/engines/sherlock/scalpel/scalpel_map.cpp
index 5c45302..613587d 100644
--- a/engines/sherlock/scalpel/scalpel_map.cpp
+++ b/engines/sherlock/scalpel/scalpel_map.cpp
@@ -20,12 +20,540 @@
  *
  */
 
+#include "common/system.h"
 #include "sherlock/scalpel/scalpel_map.h"
+#include "sherlock/events.h"
+#include "sherlock/people.h"
+#include "sherlock/screen.h"
+#include "sherlock/sherlock.h"
 
 namespace Sherlock {
 
 namespace Scalpel {
 
+MapPaths::MapPaths() {
+	_numLocations = 0;
+}
+
+void MapPaths::load(int numLocations, Common::SeekableReadStream &s) {
+	_numLocations = numLocations;
+	_paths.resize(_numLocations * _numLocations);
+
+	for (int idx = 0; idx < (numLocations * numLocations); ++idx) {
+		Common::Array<byte> &path = _paths[idx];
+		int v;
+
+		do {
+			v = s.readByte();
+			path.push_back(v);
+		} while (v && v < 254);
+	}
+}
+
+const byte *MapPaths::getPath(int srcLocation, int destLocation) {
+	return &_paths[srcLocation * _numLocations + destLocation][0];
+}
+
+/*----------------------------------------------------------------*/
+
+ScalpelMap::ScalpelMap(SherlockEngine *vm): Map(vm), _topLine(g_system->getWidth(), 12, vm->getPlatform()) {
+	_mapCursors = nullptr;
+	_shapes = nullptr;
+	_iconShapes = nullptr;
+	_point = 0;
+	_placesShown = false;
+	_cursorIndex = -1;
+	_drawMap = false;
+	_overPos = Point32(130 * FIXED_INT_MULTIPLIER, 126 * FIXED_INT_MULTIPLIER);
+	_frameChangeFlag = false;
+
+	// Initialise the initial walk sequence set
+	_walkSequences.resize(MAX_HOLMES_SEQUENCE);
+	for (int idx = 0; idx < MAX_HOLMES_SEQUENCE; ++idx) {
+		_walkSequences[idx]._sequences.resize(MAX_FRAME);
+		Common::fill(&_walkSequences[idx]._sequences[0], &_walkSequences[idx]._sequences[0] + MAX_FRAME, 0);
+	}
+
+	if (!_vm->isDemo())
+		loadData();
+}
+
+void ScalpelMap::loadPoints(int count, const int *xList, const int *yList, const int *transList) {
+	for (int idx = 0; idx < count; ++idx, ++xList, ++yList, ++transList) {
+		_points.push_back(MapEntry(*xList, *yList, *transList));
+	}
+}
+
+void ScalpelMap::loadSequences(int count, const byte *seq) {
+	for (int idx = 0; idx < count; ++idx, seq += MAX_FRAME)
+		Common::copy(seq, seq + MAX_FRAME, &_walkSequences[idx]._sequences[0]);
+}
+
+void ScalpelMap::loadData() {
+	// TODO: Remove this
+	if (_vm->getGameID() == GType_RoseTattoo)
+		return;
+
+	// Load the list of location names
+	Common::SeekableReadStream *txtStream = _vm->_res->load(
+		_vm->getGameID() == GType_SerratedScalpel ? "chess.txt" : "map.txt");
+
+	int streamSize = txtStream->size();
+	while (txtStream->pos() < streamSize) {
+		Common::String line;
+		char c;
+		while ((c = txtStream->readByte()) != '\0')
+			line += c;
+
+		_locationNames.push_back(line);
+	}
+
+	delete txtStream;
+
+	// Load the path data
+	Common::SeekableReadStream *pathStream = _vm->_res->load("chess.pth");
+
+	// Get routes between different locations on the map
+	_paths.load(31, *pathStream);
+
+	// Load in the co-ordinates that the paths refer to
+	_pathPoints.resize(208);
+	for (uint idx = 0; idx < _pathPoints.size(); ++idx) {
+		_pathPoints[idx].x = pathStream->readSint16LE();
+		_pathPoints[idx].y = pathStream->readSint16LE();
+	}
+
+	delete pathStream;
+}
+
+int ScalpelMap::show() {
+	Events &events = *_vm->_events;
+	People &people = *_vm->_people;
+	Screen &screen = *_vm->_screen;
+	bool changed = false, exitFlag = false;
+	_active = true;
+
+	// Set font and custom cursor for the map
+	int oldFont = screen.fontNumber();
+	screen.setFont(0);
+
+	// Initial screen clear
+	screen._backBuffer1.clear();
+	screen.clear();
+
+	// Load the entire map
+	ImageFile bigMap("bigmap.vgs");
+	screen.setPalette(bigMap._palette);
+
+	// Load need sprites
+	setupSprites();
+
+	screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
+	screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+	screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+	screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+
+	_drawMap = true;
+	_charPoint = -1;
+	_point = -1;
+	people[AL]._position = _lDrawnPos = _overPos;
+
+	// Show place icons
+	showPlaces();
+	saveTopLine();
+	_placesShown = true;
+
+	// Keep looping until either a location is picked, or the game is ended
+	while (!_vm->shouldQuit() && !exitFlag) {
+		events.pollEventsAndWait();
+		events.setButtonState();
+
+		// Keyboard handling
+		if (events.kbHit()) {
+			Common::KeyState keyState = events.getKey();
+
+			if (keyState.keycode == Common::KEYCODE_RETURN || keyState.keycode == Common::KEYCODE_SPACE) {
+				// Both space and enter simulate a mouse release
+				events._pressed = false;
+				events._released = true;
+				events._oldButtons = 0;
+			}
+		}
+
+		// Ignore scrolling attempts until the screen is drawn
+		if (!_drawMap) {
+			Common::Point pt = events.mousePos();
+
+			// Check for vertical map scrolling
+			if ((pt.y > (SHERLOCK_SCREEN_HEIGHT - 10) && _bigPos.y < 200) || (pt.y < 10 && _bigPos.y > 0)) {
+				if (pt.y > (SHERLOCK_SCREEN_HEIGHT - 10))
+					_bigPos.y += 10;
+				else
+					_bigPos.y -= 10;
+
+				changed = true;
+			}
+
+			// Check for horizontal map scrolling
+			if ((pt.x > (SHERLOCK_SCREEN_WIDTH - 10) && _bigPos.x < 315) || (pt.x < 10 && _bigPos.x > 0)) {
+				if (pt.x > (SHERLOCK_SCREEN_WIDTH - 10))
+					_bigPos.x += 15;
+				else
+					_bigPos.x -= 15;
+
+				changed = true;
+			}
+		}
+
+		if (changed) {
+			// Map has scrolled, so redraw new map view
+			changed = false;
+
+			screen._backBuffer1.blitFrom(bigMap[0], Common::Point(-_bigPos.x, -_bigPos.y));
+			screen._backBuffer1.blitFrom(bigMap[1], Common::Point(-_bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+			screen._backBuffer1.blitFrom(bigMap[2], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, -_bigPos.y));
+			screen._backBuffer1.blitFrom(bigMap[3], Common::Point(SHERLOCK_SCREEN_WIDTH - _bigPos.x, SHERLOCK_SCREEN_HEIGHT - _bigPos.y));
+
+			showPlaces();
+			_placesShown = false;
+
+			saveTopLine();
+			_savedPos.x = -1;
+			updateMap(true);
+		} else if (!_drawMap) {
+			if (!_placesShown) {
+				showPlaces();
+				_placesShown = true;
+			}
+
+			if (_cursorIndex == 0) {
+				Common::Point pt = events.mousePos();
+				highlightIcon(Common::Point(pt.x - 4 + _bigPos.x, pt.y + _bigPos.y));
+			}
+			updateMap(false);
+		}
+
+		if ((events._released || events._rightReleased) && _point != -1) {
+			if (people[AL]._walkCount == 0) {
+				people._walkDest = _points[_point] + Common::Point(4, 9);
+				_charPoint = _point;
+
+				// Start walking to selected location
+				walkTheStreets();
+
+				// Show wait cursor
+				_cursorIndex = 1;
+				events.setCursor((*_mapCursors)[_cursorIndex]._frame);
+			}
+		}
+
+		// Check if a scene has beeen selected and we've finished "moving" to it
+		if (people[AL]._walkCount == 0) {
+			if (_charPoint >= 1 && _charPoint < (int)_points.size())
+				exitFlag = true;
+		}
+
+		if (_drawMap) {
+			_drawMap = false;
+
+			if (screen._fadeStyle)
+				screen.randomTransition();
+			else
+				screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+		}
+
+		// Wait for a frame
+		events.wait(1);
+	}
+
+	freeSprites();
+	_overPos = people[AL]._position;
+
+	// Reset font
+	screen.setFont(oldFont);
+
+	_active = false;
+	return _charPoint;
+}
+
+void ScalpelMap::setupSprites() {
+	Events &events = *_vm->_events;
+	People &people = *_vm->_people;
+	Scene &scene = *_vm->_scene;
+	_savedPos.x = -1;
+
+	_mapCursors = new ImageFile("omouse.vgs");
+	_cursorIndex = 0;
+	events.setCursor((*_mapCursors)[_cursorIndex]._frame);
+
+	_shapes = new ImageFile("mapicon.vgs");
+	_iconShapes = new ImageFile("overicon.vgs");
+	_iconSave.create((*_shapes)[4]._width, (*_shapes)[4]._height, _vm->getPlatform());
+	Person &p = people[AL];
+	p._description = " ";
+	p._type = CHARACTER;
+	p._position = Common::Point(12400, 5000);
+	p._sequenceNumber = 0;
+	p._images = _shapes;
+	p._imageFrame = nullptr;
+	p._frameNumber = 0;
+	p._delta = Common::Point(0, 0);
+	p._oldSize = Common::Point(0, 0);
+	p._oldSize = Common::Point(0, 0);
+	p._misc = 0;
+	p._walkCount = 0;
+	p._allow = 0;
+	p._noShapeSize = Common::Point(0, 0);
+	p._goto = Common::Point(28000, 15000);
+	p._status = 0;
+	p._walkSequences = _walkSequences;
+	p.setImageFrame();
+	scene._bgShapes.clear();
+}
+
+void ScalpelMap::freeSprites() {
+	delete _mapCursors;
+	delete _shapes;
+	delete _iconShapes;
+	_iconSave.free();
+}
+
+void ScalpelMap::showPlaces() {
+	Screen &screen = *_vm->_screen;
+
+	for (uint idx = 0; idx < _points.size(); ++idx) {
+		const MapEntry &pt = _points[idx];
+
+		if (pt.x != 0 && pt.y != 0) {
+			if (pt.x >= _bigPos.x && (pt.x - _bigPos.x) < SHERLOCK_SCREEN_WIDTH
+					&& pt.y >= _bigPos.y && (pt.y - _bigPos.y) < SHERLOCK_SCREEN_HEIGHT) {
+				if (_vm->readFlags(idx)) {
+					screen._backBuffer1.transBlitFrom((*_iconShapes)[pt._translate],
+						Common::Point(pt.x - _bigPos.x - 6, pt.y - _bigPos.y - 12));
+				}
+			}
+		}
+	}
+}
+
+void ScalpelMap::saveTopLine() {
+	_topLine.blitFrom(_vm->_screen->_backBuffer1, Common::Point(0, 0), Common::Rect(0, 0, SHERLOCK_SCREEN_WIDTH, 12));
+}
+
+void ScalpelMap::eraseTopLine() {
+	Screen &screen = *_vm->_screen;
+	screen._backBuffer1.blitFrom(_topLine, Common::Point(0, 0));
+	screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, _topLine.h());
+}
+
+void ScalpelMap::showPlaceName(int idx, bool highlighted) {
+	People &people = *_vm->_people;
+	Screen &screen = *_vm->_screen;
+
+	Common::String name = _locationNames[idx];
+	int width = screen.stringWidth(name);
+
+	if (!_cursorIndex) {
+		saveIcon(people[AL]._imageFrame, _lDrawnPos);
+
+		bool flipped = people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
+			|| people[AL]._sequenceNumber == MAP_UPLEFT;
+		screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, _lDrawnPos, flipped);
+	}
+
+	if (highlighted) {
+		int xp = (SHERLOCK_SCREEN_WIDTH - screen.stringWidth(name)) / 2;
+		screen.gPrint(Common::Point(xp + 2, 2), 0, "%s", name.c_str());
+		screen.gPrint(Common::Point(xp + 1, 1), 0, "%s", name.c_str());
+		screen.gPrint(Common::Point(xp, 0), 12, "%s", name.c_str());
+
+		screen.slamArea(xp, 0, width + 2, 15);
+	}
+}
+
+void ScalpelMap::updateMap(bool flushScreen) {
+	Events &events = *_vm->_events;
+	People &people = *_vm->_people;
+	Screen &screen = *_vm->_screen;
+	Common::Point osPos = _savedPos;
+	Common::Point osSize = _savedSize;
+	Common::Point hPos;
+
+	if (_cursorIndex >= 1) {
+		if (++_cursorIndex > (1 + 8))
+			_cursorIndex = 1;
+
+		events.setCursor((*_mapCursors)[(_cursorIndex + 1) / 2]._frame);
+	}
+
+	if (!_drawMap && !flushScreen)
+		restoreIcon();
+	else
+		_savedPos.x = -1;
+
+	people[AL].adjustSprite();
+
+	_lDrawnPos.x = hPos.x = people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x;
+	_lDrawnPos.y = hPos.y = people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y;
+
+	// Draw the person icon
+	saveIcon(people[AL]._imageFrame, hPos);
+	if (people[AL]._sequenceNumber == MAP_DOWNLEFT || people[AL]._sequenceNumber == MAP_LEFT
+			|| people[AL]._sequenceNumber == MAP_UPLEFT)
+		screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, true);
+	else
+		screen._backBuffer1.transBlitFrom(*people[AL]._imageFrame, hPos, false);
+
+	if (flushScreen) {
+		screen.slamArea(0, 0, SHERLOCK_SCREEN_WIDTH, SHERLOCK_SCREEN_HEIGHT);
+	} else if (!_drawMap) {
+		if (hPos.x > 0 && hPos.y >= 0 && hPos.x < SHERLOCK_SCREEN_WIDTH && hPos.y < SHERLOCK_SCREEN_HEIGHT)
+			screen.flushImage(people[AL]._imageFrame, Common::Point(people[AL]._position.x / FIXED_INT_MULTIPLIER - _bigPos.x,
+			people[AL]._position.y / FIXED_INT_MULTIPLIER - people[AL].frameHeight() - _bigPos.y),
+			&people[AL]._oldPosition.x, &people[AL]._oldPosition.y, &people[AL]._oldSize.x, &people[AL]._oldSize.y);
+
+		if (osPos.x != -1)
+			screen.slamArea(osPos.x, osPos.y, osSize.x, osSize.y);
+	}
+}
+
+void ScalpelMap::walkTheStreets() {
+	People &people = *_vm->_people;
+	Common::Array<Common::Point> tempPath;
+
+	// Get indexes into the path lists for the start and destination scenes
+	int start = _points[_oldCharPoint]._translate;
+	int dest = _points[_charPoint]._translate;
+
+	// Get pointer to start of path
+	const byte *path = _paths.getPath(start, dest);
+
+	// Add in destination position
+	people._walkTo.clear();
+	Common::Point destPos = people._walkDest;
+
+	// Check for any intermediate points between the two locations
+	if (path[0] || _charPoint > 50 || _oldCharPoint > 50) {
+		people[AL]._sequenceNumber = -1;
+
+		if (_charPoint == 51 || _oldCharPoint == 51) {
+			people.setWalking();
+		} else {
+			bool reversePath = false;
+
+			// Check for moving the path backwards or forwards
+			if (path[0] == 255) {
+				reversePath = true;
+				SWAP(start, dest);
+				path = _paths.getPath(start, dest);
+			}
+
+			do {
+				int idx = *path++;
+				tempPath.push_back(_pathPoints[idx - 1] + Common::Point(4, 4));
+			} while (*path != 254);
+
+			// Load up the path to use
+			people._walkTo.clear();
+
+			if (reversePath) {
+				for (int idx = (int)tempPath.size() - 1; idx >= 0; --idx)
+					people._walkTo.push(tempPath[idx]);
+			} else {
+				for (int idx = 0; idx < (int)tempPath.size(); ++idx)
+					people._walkTo.push(tempPath[idx]);
+			}
+
+			people._walkDest = people._walkTo.pop() + Common::Point(12, 6);
+			people.setWalking();
+		}
+	} else {
+		people[AL]._walkCount = 0;
+	}
+
+	// Store the final destination icon position
+	people._walkTo.push(destPos);
+}
+
+void ScalpelMap::saveIcon(ImageFrame *src, const Common::Point &pt) {
+	Screen &screen = *_vm->_screen;
+	Common::Point size(src->_width, src->_height);
+	Common::Point pos = pt;
+
+	if (pos.x < 0) {
+		size.x += pos.x;
+		pos.x = 0;
+	}
+
+	if (pos.y < 0) {
+		size.y += pos.y;
+		pos.y = 0;
+	}
+
+	if ((pos.x + size.x) > SHERLOCK_SCREEN_WIDTH)
+		size.x -= (pos.x + size.x) - SHERLOCK_SCREEN_WIDTH;
+
+	if ((pos.y + size.y) > SHERLOCK_SCREEN_HEIGHT)
+		size.y -= (pos.y + size.y) - SHERLOCK_SCREEN_HEIGHT;
+
+	if (size.x < 1 || size.y < 1 || pos.x >= SHERLOCK_SCREEN_WIDTH || pos.y >= SHERLOCK_SCREEN_HEIGHT || _drawMap) {
+		// Flag as the area not needing to be saved
+		_savedPos.x = -1;
+		return;
+	}
+
+	assert(size.x <= _iconSave.w() && size.y <= _iconSave.h());
+	_iconSave.blitFrom(screen._backBuffer1, Common::Point(0, 0),
+		Common::Rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y));
+	_savedPos = pos;
+	_savedSize = size;
+}
+
+void ScalpelMap::restoreIcon() {
+	Screen &screen = *_vm->_screen;
+
+	if (_savedPos.x >= 0 && _savedPos.y >= 0 && _savedPos.x <= SHERLOCK_SCREEN_WIDTH
+			&& _savedPos.y < SHERLOCK_SCREEN_HEIGHT)
+		screen._backBuffer1.blitFrom(_iconSave, _savedPos, Common::Rect(0, 0, _savedSize.x, _savedSize.y));
+}
+
+void ScalpelMap::highlightIcon(const Common::Point &pt) {
+	int oldPoint = _point;
+
+	// Iterate through the icon list
+	bool done = false;
+	for (int idx = 0; idx < (int)_points.size(); ++idx) {
+		const MapEntry &entry = _points[idx];
+
+		// Check whether the mouse is over a given icon
+		if (entry.x != 0 && entry.y != 0) {
+			if (Common::Rect(entry.x - 8, entry.y - 8, entry.x + 9, entry.y + 9).contains(pt)) {
+				done = true;
+
+				if (_point != idx && _vm->readFlags(idx)) {
+					// Changed to a new valid (visible) location
+					eraseTopLine();
+					showPlaceName(idx, true);
+					_point = idx;
+				}
+			}
+		}
+	}
+
+	if (!done) {
+		// No icon was highlighted
+		if (_point != -1) {
+			// No longer highlighting previously highlighted icon, so erase it
+			showPlaceName(_point, false);
+			eraseTopLine();
+		}
+
+		_point = -1;
+	} else if (oldPoint != -1 && oldPoint != _point) {
+		showPlaceName(oldPoint, false);
+		eraseTopLine();
+	}
+}
 
 } // End of namespace Scalpel
 
diff --git a/engines/sherlock/scalpel/scalpel_map.h b/engines/sherlock/scalpel/scalpel_map.h
index 4fb4142..e61375f 100644
--- a/engines/sherlock/scalpel/scalpel_map.h
+++ b/engines/sherlock/scalpel/scalpel_map.h
@@ -24,7 +24,12 @@
 #define SHERLOCK_SCALPEL_MAP_H
 
 #include "common/scummsys.h"
+#include "common/array.h"
+#include "common/rect.h"
+#include "common/str-array.h"
+#include "sherlock/surface.h"
 #include "sherlock/map.h"
+#include "sherlock/resources.h"
 
 namespace Sherlock {
 
@@ -32,9 +37,132 @@ class SherlockEngine;
 
 namespace Scalpel {
 
+
+struct MapEntry : Common::Point {
+	int _translate;
+
+	MapEntry() : Common::Point(), _translate(-1) {}
+
+	MapEntry(int posX, int posY, int translate) : Common::Point(posX, posY), _translate(translate) {}
+};
+
+class MapPaths {
+private:
+	int _numLocations;
+	Common::Array< Common::Array<byte> > _paths;
+
+public:
+	MapPaths();
+
+	/**
+	 * Load the data for the paths between locations on the map
+	 */
+	void load(int numLocations, Common::SeekableReadStream &s);
+
+	/**
+	 * Get the path between two locations on the map
+	 */
+	const byte *getPath(int srcLocation, int destLocation);
+};
+
 class ScalpelMap: public Map {
+private:
+	Common::Array<MapEntry> _points;	// Map locations for each scene
+	Common::StringArray _locationNames;
+	MapPaths _paths;
+	Common::Array<Common::Point> _pathPoints;
+	Common::Point _savedPos;
+	Common::Point _savedSize;
+	Surface _topLine;
+	ImageFile *_mapCursors;
+	ImageFile *_shapes;
+	ImageFile *_iconShapes;
+	WalkSequences _walkSequences;
+	Point32 _lDrawnPos;
+	int _point;
+	bool _placesShown;
+	int _cursorIndex;
+	bool _drawMap;
+	Surface _iconSave;
+protected:
+	/**
+	 * Load data  needed for the map
+	 */
+	void loadData();
+
+	/**
+	 * Load and initialize all the sprites that are needed for the map display
+	 */
+	void setupSprites();
+
+	/**
+	 * Free the sprites and data used by the map
+	 */
+	void freeSprites();
+
+	/**
+	 * Draws an icon for every place that's currently known
+	 */
+	void showPlaces();
+
+	/**
+	 * Makes a copy of the top rows of the screen that are used to display location names
+	 */
+	void saveTopLine();
+
+	/**
+	 * Erases anything shown in the top line by restoring the previously saved original map background
+	 */
+	void eraseTopLine();
+
+	/**
+	 * Prints the name of the specified icon
+	 */
+	void showPlaceName(int idx, bool highlighted);
+
+	/**
+	 * Update all on-screen sprites to account for any scrolling of the map
+	 */
+	void updateMap(bool flushScreen);
+
+	/**
+	 * Handle moving icon for player from their previous location on the map to a destination location
+	 */
+	void walkTheStreets();
+
+	/**
+	 * Save the area under the player's icon
+	 */
+	void saveIcon(ImageFrame *src, const Common::Point &pt);
+
+	/**
+	 * Restore the area under the player's icon
+	 */
+	void restoreIcon();
+
+	/**
+	 * Handles highlighting map icons, showing their names
+	 */
+	void highlightIcon(const Common::Point &pt);
 public:
-	ScalpelMap(SherlockEngine *vm) : Map(vm) {}
+	ScalpelMap(SherlockEngine *vm);
+
+	const MapEntry &operator[](int idx) { return _points[idx]; }
+
+	/**
+	 * Loads the list of points for locations on the map for each scene
+	 */
+	void loadPoints(int count, const int *xList, const int *yList, const int *transList);
+
+	/**
+	 * Load the sequence data for player icon animations
+	 */
+	void loadSequences(int count, const byte *seq);
+
+	/**
+	 * Show the map
+	 */
+	virtual int show();
 };
 
 } // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_people.cpp b/engines/sherlock/scalpel/scalpel_people.cpp
index 2b76eea..80e6061 100644
--- a/engines/sherlock/scalpel/scalpel_people.cpp
+++ b/engines/sherlock/scalpel/scalpel_people.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "sherlock/scalpel/scalpel_people.h"
+#include "sherlock/scalpel/scalpel_map.h"
 #include "sherlock/sherlock.h"
 
 namespace Sherlock {
@@ -86,7 +87,6 @@ void ScalpelPeople::setTalking(int speaker) {
 	}
 }
 
-
 void ScalpelPeople::synchronize(Serializer &s) {
 	s.syncAsByte(_holmesOn);
 	s.syncAsSint32LE(_player._position.x);
@@ -130,6 +130,57 @@ void ScalpelPeople::setTalkSequence(int speaker, int sequenceNum) {
 	}
 }
 
+void ScalpelPeople::gotoStand(Sprite &sprite) {
+	ScalpelMap &map = *(ScalpelMap *)_vm->_map;
+	_walkTo.clear();
+	sprite._walkCount = 0;
+
+	switch (sprite._sequenceNumber) {
+	case Scalpel::WALK_UP:
+		sprite._sequenceNumber = STOP_UP;
+		break;
+	case WALK_DOWN:
+		sprite._sequenceNumber = STOP_DOWN;
+		break;
+	case TALK_LEFT:
+	case WALK_LEFT:
+		sprite._sequenceNumber = STOP_LEFT;
+		break;
+	case TALK_RIGHT:
+	case WALK_RIGHT:
+		sprite._sequenceNumber = STOP_RIGHT;
+		break;
+	case WALK_UPRIGHT:
+		sprite._sequenceNumber = STOP_UPRIGHT;
+		break;
+	case WALK_UPLEFT:
+		sprite._sequenceNumber = STOP_UPLEFT;
+		break;
+	case WALK_DOWNRIGHT:
+		sprite._sequenceNumber = STOP_DOWNRIGHT;
+		break;
+	case WALK_DOWNLEFT:
+		sprite._sequenceNumber = STOP_DOWNLEFT;
+		break;
+	default:
+		break;
+	}
+
+	// Only restart frame at 0 if the sequence number has changed
+	if (_oldWalkSequence != -1 || sprite._sequenceNumber == Scalpel::STOP_UP)
+		sprite._frameNumber = 0;
+
+	if (map._active) {
+		sprite._sequenceNumber = 0;
+		_player._position.x = (map[map._charPoint].x - 6) * FIXED_INT_MULTIPLIER;
+		_player._position.y = (map[map._charPoint].y + 10) * FIXED_INT_MULTIPLIER;
+	}
+
+	_oldWalkSequence = -1;
+	_allowWalkAbort = true;
+}
+
+
 } // End of namespace Scalpel
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_people.h b/engines/sherlock/scalpel/scalpel_people.h
index 6981157..1f14cee 100644
--- a/engines/sherlock/scalpel/scalpel_people.h
+++ b/engines/sherlock/scalpel/scalpel_people.h
@@ -60,6 +60,12 @@ public:
 	 * Change the sequence of the scene background object associated with the specified speaker.
 	 */
 	virtual void setTalkSequence(int speaker, int sequenceNum = 1);
+
+	/**
+	 * Bring a moving character to a standing position. If the Scalpel chessboard
+	 * is being displayed, then the chraracter will always face down.
+	 */
+	virtual void gotoStand(Sprite &sprite);
 };
 
 } // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_scene.cpp b/engines/sherlock/scalpel/scalpel_scene.cpp
index e0ad3a7..95a58be 100644
--- a/engines/sherlock/scalpel/scalpel_scene.cpp
+++ b/engines/sherlock/scalpel/scalpel_scene.cpp
@@ -21,16 +21,34 @@
  */
 
 #include "sherlock/scalpel/scalpel_scene.h"
+#include "sherlock/scalpel/scalpel_map.h"
 #include "sherlock/scalpel/scalpel_people.h"
 #include "sherlock/scalpel/scalpel.h"
 #include "sherlock/events.h"
 #include "sherlock/people.h"
 #include "sherlock/screen.h"
+#include "sherlock/sherlock.h"
 
 namespace Sherlock {
 
 namespace Scalpel {
 
+bool ScalpelScene::loadScene(const Common::String &filename) {
+	ScalpelMap &map = *(ScalpelMap *)_vm->_map;
+	bool result = Scene::loadScene(filename);
+
+	if (!_vm->isDemo()) {
+		// Reset the previous map location and position on overhead map
+		map._oldCharPoint = _currentScene;
+
+		map._overPos.x = (map[_currentScene].x - 6) * FIXED_INT_MULTIPLIER;
+		map._overPos.y = (map[_currentScene].y + 9) * FIXED_INT_MULTIPLIER;
+
+	}
+
+	return result;
+}
+
 void ScalpelScene::drawAllShapes() {
 	People &people = *_vm->_people;
 	Screen &screen = *_vm->_screen;
@@ -467,6 +485,218 @@ void ScalpelScene::doBgAnim() {
 	}
 }
 
+int ScalpelScene::startCAnim(int cAnimNum, int playRate) {
+	Events &events = *_vm->_events;
+	ScalpelMap &map = *(ScalpelMap *)_vm->_map;
+	People &people = *_vm->_people;
+	Resources &res = *_vm->_res;
+	Talk &talk = *_vm->_talk;
+	UserInterface &ui = *_vm->_ui;
+	Point32 tpPos, walkPos;
+	int tpDir, walkDir;
+	int tFrames = 0;
+	int gotoCode = -1;
+
+	// Validation
+	if (cAnimNum >= (int)_cAnim.size())
+		// number out of bounds
+		return -1;
+	if (_canimShapes.size() >= 3 || playRate == 0)
+		// Too many active animations, or invalid play rate
+		return 0;
+
+	CAnim &cAnim = _cAnim[cAnimNum];
+	if (playRate < 0) {
+		// Reverse direction
+		walkPos = cAnim._teleportPos;
+		walkDir = cAnim._teleportDir;
+		tpPos = cAnim._goto;
+		tpDir = cAnim._gotoDir;
+	} else {
+		// Forward direction
+		walkPos = cAnim._goto;
+		walkDir = cAnim._gotoDir;
+		tpPos = cAnim._teleportPos;
+		tpDir = cAnim._teleportDir;
+	}
+
+	CursorId oldCursor = events.getCursor();
+	events.setCursor(WAIT);
+
+	if (walkPos.x != -1) {
+		// Holmes must walk to the walk point before the cAnimation is started
+		if (people[AL]._position != walkPos)
+			people.walkToCoords(walkPos, walkDir);
+	}
+
+	if (talk._talkToAbort)
+		return 1;
+
+	// Add new anim shape entry for displaying the animation
+	_canimShapes.push_back(Object());
+	Object &cObj = _canimShapes[_canimShapes.size() - 1];
+
+	// Copy the canimation into the bgShapes type canimation structure so it can be played
+	cObj._allow = cAnimNum + 1;				// Keep track of the parent structure
+	cObj._name = _cAnim[cAnimNum]._name;	// Copy name
+
+	// Remove any attempt to draw object frame
+	if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100)
+		cAnim._sequences[0] = 0;
+
+	cObj._sequences = cAnim._sequences;
+	cObj._images = nullptr;
+	cObj._position = cAnim._position;
+	cObj._delta = Common::Point(0, 0);
+	cObj._type = cAnim._type;
+	cObj._flags = cAnim._flags;
+
+	cObj._maxFrames = 0;
+	cObj._frameNumber = -1;
+	cObj._sequenceNumber = cAnimNum;
+	cObj._oldPosition = Common::Point(0, 0);
+	cObj._oldSize = Common::Point(0, 0);
+	cObj._goto = Common::Point(0, 0);
+	cObj._status = 0;
+	cObj._misc = 0;
+	cObj._imageFrame = nullptr;
+
+	if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) {
+		if (tpPos.x != -1)
+			people[AL]._type = REMOVE;
+
+		Common::String fname = cAnim._name + ".vgs";
+		if (!res.isInCache(fname)) {
+			// Set up RRM scene data
+			Common::SeekableReadStream *rrmStream = res.load(_rrmName);
+			rrmStream->seek(44 + cAnimNum * 4);
+			rrmStream->seek(rrmStream->readUint32LE());
+
+			// Load the canimation into the cache
+			Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) :
+				Resources::decompressLZ(*rrmStream, cAnim._size);
+			res.addToCache(fname, *imgStream);
+
+			delete imgStream;
+			delete rrmStream;
+		}
+
+		// Now load the resource as an image
+		cObj._images = new ImageFile(fname);
+		cObj._imageFrame = &(*cObj._images)[0];
+		cObj._maxFrames = cObj._images->size();
+
+		int frames = 0;
+		if (playRate < 0) {
+			// Reverse direction
+			// Count number of frames
+			while (cObj._sequences[frames] && frames < MAX_FRAME)
+				++frames;
+		} else {
+			// Forward direction
+			Object::_countCAnimFrames = true;
+
+			while (cObj._type == ACTIVE_BG_SHAPE) {
+				cObj.checkObject();
+				++frames;
+
+				if (frames >= 1000)
+					error("CAnim has infinite loop sequence");
+			}
+
+			if (frames > 1)
+				--frames;
+
+			Object::_countCAnimFrames = false;
+
+			cObj._type = cAnim._type;
+			cObj._frameNumber = -1;
+			cObj._position = cAnim._position;
+			cObj._delta = Common::Point(0, 0);
+		}
+
+		// Return if animation has no frames in it
+		if (frames == 0)
+			return -2;
+
+		++frames;
+		int repeat = ABS(playRate);
+		int dir;
+
+		if (playRate < 0) {
+			// Play in reverse
+			dir = -2;
+			cObj._frameNumber = frames - 3;
+		} else {
+			dir = 0;
+		}
+
+		tFrames = frames - 1;
+		int pauseFrame = (_cAnimFramePause) ? frames - _cAnimFramePause : -1;
+
+		while (--frames) {
+			if (frames == pauseFrame)
+				ui.printObjectDesc();
+
+			doBgAnim();
+
+			// Repeat same frame
+			int temp = repeat;
+			while (--temp > 0) {
+				cObj._frameNumber--;
+				doBgAnim();
+
+				if (_vm->shouldQuit())
+					return 0;
+			}
+
+			cObj._frameNumber += dir;
+		}
+
+		people[AL]._type = CHARACTER;
+	}
+
+	// Teleport to ending coordinates if necessary
+	if (tpPos.x != -1) {
+		people[AL]._position = tpPos;	// Place the player
+		people[AL]._sequenceNumber = tpDir;
+		people.gotoStand(people[AL]);
+	}
+
+	if (playRate < 0)
+		// Reverse direction - set to end sequence
+		cObj._frameNumber = tFrames - 1;
+
+	if (cObj._frameNumber <= 26)
+		gotoCode = cObj._sequences[cObj._frameNumber + 3];
+
+	// Unless anim shape has already been freed, set it to REMOVE so doBgAnim can free it
+	if (_canimShapes.indexOf(cObj) != -1)
+		cObj.checkObject();
+
+	if (gotoCode > 0 && !talk._talkToAbort) {
+		_goToScene = gotoCode;
+
+		if (_goToScene < 97 && map[_goToScene].x) {
+			map._overPos = map[_goToScene];
+		}
+	}
+
+	people.loadWalk();
+
+	if (tpPos.x != -1 && !talk._talkToAbort) {
+		// Teleport to ending coordinates
+		people[AL]._position = tpPos;
+		people[AL]._sequenceNumber = tpDir;
+
+		people.gotoStand(people[AL]);
+	}
+
+	events.setCursor(oldCursor);
+
+	return 1;
+}
+
 } // End of namespace Scalpel
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/scalpel/scalpel_scene.h b/engines/sherlock/scalpel/scalpel_scene.h
index 88c7581..f79892e 100644
--- a/engines/sherlock/scalpel/scalpel_scene.h
+++ b/engines/sherlock/scalpel/scalpel_scene.h
@@ -44,6 +44,17 @@ private:
 	void doBgAnimCheckCursor();
 protected:
 	/**
+	 * Loads the data associated for a given scene. The room resource file's format is:
+	 * BGHEADER: Holds an index for the rest of the file
+	 * STRUCTS:  The objects for the scene
+	 * IMAGES:   The graphic information for the structures
+	 *
+	 * The _misc field of the structures contains the number of the graphic image
+	 * that it should point to after loading; _misc is then set to 0.
+	 */
+	virtual bool loadScene(const Common::String &filename);
+
+	/**
 	 * Checks all the background shapes. If a background shape is animating,
 	 * it will flag it as needing to be drawn. If a non-animating shape is
 	 * colliding with another shape, it will also flag it as needing drawing
@@ -61,6 +72,16 @@ public:
 	 * Draw all objects and characters.
 	 */
 	virtual void doBgAnim();
+
+	/**
+	 * Attempt to start a canimation sequence. It will load the requisite graphics, and
+	 * then copy the canim object into the _canimShapes array to start the animation.
+	 *
+	 * @param cAnimNum		The canim object within the current scene
+	 * @param playRate		Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+	 *		A negative playRate can also be specified to play the animation in reverse
+	 */
+	virtual int startCAnim(int cAnimNum, int playRate);
 };
 
 } // End of namespace Scalpel
diff --git a/engines/sherlock/scalpel/scalpel_talk.cpp b/engines/sherlock/scalpel/scalpel_talk.cpp
index 217ed9b..3dc99c2 100644
--- a/engines/sherlock/scalpel/scalpel_talk.cpp
+++ b/engines/sherlock/scalpel/scalpel_talk.cpp
@@ -21,7 +21,9 @@
  */
 
 #include "sherlock/scalpel/scalpel_talk.h"
+#include "sherlock/scalpel/scalpel_map.h"
 #include "sherlock/scalpel/scalpel_people.h"
+#include "sherlock/scalpel/scalpel_scene.h"
 #include "sherlock/scalpel/scalpel_user_interface.h"
 #include "sherlock/sherlock.h"
 #include "sherlock/screen.h"
@@ -289,12 +291,12 @@ OpcodeReturn ScalpelTalk::cmdSwitchSpeaker(const byte *&str) {
 }
 
 OpcodeReturn ScalpelTalk::cmdGotoScene(const byte *&str) {
-	Map &map = *_vm->_map;
+	ScalpelMap &map = *(ScalpelMap *)_vm->_map;
 	People &people = *_vm->_people;
 	Scene &scene = *_vm->_scene;
 	scene._goToScene = str[1] - 1;
 
-	if (scene._goToScene != 100) {
+	if (scene._goToScene != OVERHEAD_MAP) {
 		// Not going to the map overview
 		map._oldCharPoint = scene._goToScene;
 		map._overPos.x = (map[scene._goToScene].x - 6) * FIXED_INT_MULTIPLIER;
diff --git a/engines/sherlock/scene.cpp b/engines/sherlock/scene.cpp
index c438874..9100d58 100644
--- a/engines/sherlock/scene.cpp
+++ b/engines/sherlock/scene.cpp
@@ -261,7 +261,6 @@ void Scene::freeScene() {
 
 bool Scene::loadScene(const Common::String &filename) {
 	Events &events = *_vm->_events;
-	Map &map = *_vm->_map;
 	Music &music = *_vm->_music;
 	People &people = *_vm->_people;
 	Resources &res = *_vm->_res;
@@ -629,17 +628,6 @@ bool Scene::loadScene(const Common::String &filename) {
 	_walkedInScene = false;
 	saves._justLoaded = false;
 
-	if (!_vm->isDemo()) {
-		// Reset the previous map location and position on overhead map
-		map._oldCharPoint = _currentScene;
-
-		if (IS_SERRATED_SCALPEL) {
-			map._overPos.x = (map[_currentScene].x - 6) * FIXED_INT_MULTIPLIER;
-			map._overPos.y = (map[_currentScene].y + 9) * FIXED_INT_MULTIPLIER;
-
-		}
-	}
-
 	events.clearEvents();
 	return flag;
 }
@@ -914,218 +902,6 @@ Exit *Scene::checkForExit(const Common::Rect &r) {
 	return nullptr;
 }
 
-int Scene::startCAnim(int cAnimNum, int playRate) {
-	Events &events = *_vm->_events;
-	Map &map = *_vm->_map;
-	People &people = *_vm->_people;
-	Resources &res = *_vm->_res;
-	Talk &talk = *_vm->_talk;
-	UserInterface &ui = *_vm->_ui;
-	Point32 tpPos, walkPos;
-	int tpDir, walkDir;
-	int tFrames = 0;
-	int gotoCode = -1;
-
-	// Validation
-	if (cAnimNum >= (int)_cAnim.size())
-		// number out of bounds
-		return -1;
-	if (_canimShapes.size() >= 3 || playRate == 0)
-		// Too many active animations, or invalid play rate
-		return 0;
-
-	CAnim &cAnim = _cAnim[cAnimNum];
-	if (playRate < 0) {
-		// Reverse direction
-		walkPos = cAnim._teleportPos;
-		walkDir = cAnim._teleportDir;
-		tpPos = cAnim._goto;
-		tpDir = cAnim._gotoDir;
-	} else {
-		// Forward direction
-		walkPos = cAnim._goto;
-		walkDir = cAnim._gotoDir;
-		tpPos = cAnim._teleportPos;
-		tpDir = cAnim._teleportDir;
-	}
-
-	CursorId oldCursor = events.getCursor();
-	events.setCursor(WAIT);
-
-	if (walkPos.x != -1) {
-		// Holmes must walk to the walk point before the cAnimation is started
-		if (people[AL]._position != walkPos)
-			people.walkToCoords(walkPos, walkDir);
-	}
-
-	if (talk._talkToAbort)
-		return 1;
-
-	// Add new anim shape entry for displaying the animation
-	_canimShapes.push_back(Object());
-	Object &cObj = _canimShapes[_canimShapes.size() - 1];
-
-	// Copy the canimation into the bgShapes type canimation structure so it can be played
-	cObj._allow = cAnimNum + 1;				// Keep track of the parent structure
-	cObj._name = _cAnim[cAnimNum]._name;	// Copy name
-
-	// Remove any attempt to draw object frame
-	if (cAnim._type == NO_SHAPE && cAnim._sequences[0] < 100)
-		cAnim._sequences[0] = 0;
-
-	cObj._sequences = cAnim._sequences;
-	cObj._images = nullptr;
-	cObj._position = cAnim._position;
-	cObj._delta = Common::Point(0, 0);
-	cObj._type = cAnim._type;
-	cObj._flags = cAnim._flags;
-
-	cObj._maxFrames = 0;
-	cObj._frameNumber = -1;
-	cObj._sequenceNumber = cAnimNum;
-	cObj._oldPosition = Common::Point(0, 0);
-	cObj._oldSize = Common::Point(0, 0);
-	cObj._goto = Common::Point(0, 0);
-	cObj._status = 0;
-	cObj._misc = 0;
-	cObj._imageFrame = nullptr;
-
-	if (cAnim._name.size() > 0 && cAnim._type != NO_SHAPE) {
-		if (tpPos.x != -1)
-			people[AL]._type = REMOVE;
-
-		Common::String fname = cAnim._name + ".vgs";
-		if (!res.isInCache(fname)) {
-			// Set up RRM scene data
-			Common::SeekableReadStream *rrmStream = res.load(_rrmName);
-			rrmStream->seek(44 + cAnimNum * 4);
-			rrmStream->seek(rrmStream->readUint32LE());
-
-			// Load the canimation into the cache
-			Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) :
-				Resources::decompressLZ(*rrmStream, cAnim._size);
-			res.addToCache(fname, *imgStream);
-
-			delete imgStream;
-			delete rrmStream;
-		}
-
-		// Now load the resource as an image
-		cObj._images = new ImageFile(fname);
-		cObj._imageFrame = &(*cObj._images)[0];
-		cObj._maxFrames = cObj._images->size();
-
-		int frames = 0;
-		if (playRate < 0) {
-			// Reverse direction
-			// Count number of frames
-			while (cObj._sequences[frames] && frames < MAX_FRAME)
-				++frames;
-		} else {
-			// Forward direction
-			Object::_countCAnimFrames = true;
-
-			while (cObj._type == ACTIVE_BG_SHAPE) {
-				cObj.checkObject();
-				++frames;
-
-				if (frames >= 1000)
-					error("CAnim has infinite loop sequence");
-			}
-
-			if (frames > 1)
-				--frames;
-
-			Object::_countCAnimFrames = false;
-
-			cObj._type = cAnim._type;
-			cObj._frameNumber = -1;
-			cObj._position = cAnim._position;
-			cObj._delta = Common::Point(0, 0);
-		}
-
-		// Return if animation has no frames in it
-		if (frames == 0)
-			return -2;
-
-		++frames;
-		int repeat = ABS(playRate);
-		int dir;
-
-		if (playRate < 0) {
-			// Play in reverse
-			dir = -2;
-			cObj._frameNumber = frames - 3;
-		} else {
-			dir = 0;
-		}
-
-		tFrames = frames - 1;
-		int pauseFrame = (_cAnimFramePause) ? frames - _cAnimFramePause : -1;
-
-		while (--frames) {
-			if (frames == pauseFrame)
-				ui.printObjectDesc();
-
-			doBgAnim();
-
-			// Repeat same frame
-			int temp = repeat;
-			while (--temp > 0) {
-				cObj._frameNumber--;
-				doBgAnim();
-
-				if (_vm->shouldQuit())
-					return 0;
-			}
-
-			cObj._frameNumber += dir;
-		}
-
-		people[AL]._type = CHARACTER;
-	}
-
-	// Teleport to ending coordinates if necessary
-	if (tpPos.x != -1) {
-		people[AL]._position = tpPos;	// Place the player
-		people[AL]._sequenceNumber = tpDir;
-		people.gotoStand(people[AL]);
-	}
-
-	if (playRate < 0)
-		// Reverse direction - set to end sequence
-		cObj._frameNumber = tFrames - 1;
-
-	if (cObj._frameNumber <= 26)
-		gotoCode = cObj._sequences[cObj._frameNumber + 3];
-
-	// Unless anim shape has already been freed, set it to REMOVE so doBgAnim can free it
-	if (_canimShapes.indexOf(cObj) != -1)
-		cObj.checkObject();
-
-	if (gotoCode > 0 && !talk._talkToAbort) {
-		_goToScene = gotoCode;
-
-		if (_goToScene < 97 && map[_goToScene].x) {
-			map._overPos = map[_goToScene];
-		}
-	}
-
-	people.loadWalk();
-
-	if (tpPos.x != -1 && !talk._talkToAbort) {
-		// Teleport to ending coordinates
-		people[AL]._position = tpPos;
-		people[AL]._sequenceNumber = tpDir;
-
-		people.gotoStand(people[AL]);
-	}
-
-	events.setCursor(oldCursor);
-
-	return 1;
-}
-
 int Scene::findBgShape(const Common::Rect &r) {
 	if (!_doBgAnimDone)
 		// New frame hasn't been drawn yet
diff --git a/engines/sherlock/scene.h b/engines/sherlock/scene.h
index 11fd1da..ab636f7 100644
--- a/engines/sherlock/scene.h
+++ b/engines/sherlock/scene.h
@@ -139,7 +139,6 @@ struct SceneTripEntry {
 
 class Scene {
 private:
-	Common::String _rrmName;
 	bool _loadingSavedGame;
 
 	/**
@@ -173,6 +172,7 @@ private:
 	void saveSceneStatus();
 protected:
 	SherlockEngine *_vm;
+	Common::String _rrmName;
 
 	/**
 	 * Loads the data associated for a given scene. The room resource file's format is:
@@ -260,16 +260,6 @@ public:
 	Exit *checkForExit(const Common::Rect &r);
 
 	/**
-	 * Attempt to start a canimation sequence. It will load the requisite graphics, and
-	 * then copy the canim object into the _canimShapes array to start the animation.
-	 *
-	 * @param cAnimNum		The canim object within the current scene
-	 * @param playRate		Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
-	 *		A negative playRate can also be specified to play the animation in reverse
-	 */
-	int startCAnim(int cAnimNum, int playRate);
-
-	/**
 	 * Scans through the object list to find one with a matching name, and will
 	 * call toggleHidden with all matches found. Returns the numer of matches found
 	 */
@@ -319,6 +309,16 @@ public:
 	 * to be drawn
 	 */
 	virtual void updateBackground();
+
+	/**
+	 * Attempt to start a canimation sequence. It will load the requisite graphics, and
+	 * then copy the canim object into the _canimShapes array to start the animation.
+	 *
+	 * @param cAnimNum		The canim object within the current scene
+	 * @param playRate		Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+	 *		A negative playRate can also be specified to play the animation in reverse
+	 */
+	virtual int startCAnim(int cAnimNum, int playRate) = 0;
 };
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_map.cpp b/engines/sherlock/tattoo/tattoo_map.cpp
index 9dd35a9..ced7ed9 100644
--- a/engines/sherlock/tattoo/tattoo_map.cpp
+++ b/engines/sherlock/tattoo/tattoo_map.cpp
@@ -26,6 +26,10 @@ namespace Sherlock {
 
 namespace Tattoo {
 
+int TattooMap::show() {
+	// TODO
+	return 61;
+}
 
 } // End of namespace Tattoo
 
diff --git a/engines/sherlock/tattoo/tattoo_map.h b/engines/sherlock/tattoo/tattoo_map.h
index 97a330a..15dd90e 100644
--- a/engines/sherlock/tattoo/tattoo_map.h
+++ b/engines/sherlock/tattoo/tattoo_map.h
@@ -35,6 +35,11 @@ namespace Tattoo {
 class TattooMap : public Map {
 public:
 	TattooMap(SherlockEngine *vm) : Map(vm) {}
+
+	/**
+	 * Show the map
+	 */
+	virtual int show();
 };
 
 } // End of namespace Tattoo
diff --git a/engines/sherlock/tattoo/tattoo_people.cpp b/engines/sherlock/tattoo/tattoo_people.cpp
index 6952c87..61f79c4 100644
--- a/engines/sherlock/tattoo/tattoo_people.cpp
+++ b/engines/sherlock/tattoo/tattoo_people.cpp
@@ -222,6 +222,10 @@ void TattooPeople::synchronize(Serializer &s) {
 	}
 }
 
+void TattooPeople::gotoStand(Sprite &sprite) {
+	error("TODO: gotoStand");
+}
+
 } // End of namespace Tattoo
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h
index c4f0bfd..e4216d0 100644
--- a/engines/sherlock/tattoo/tattoo_people.h
+++ b/engines/sherlock/tattoo/tattoo_people.h
@@ -96,6 +96,12 @@ public:
 	 * Change the sequence of the scene background object associated with the specified speaker.
 	 */
 	virtual void setTalkSequence(int speaker, int sequenceNum = 1);
+
+	/**
+	 * Bring a moving character to a standing position. If the Scalpel chessboard
+	 * is being displayed, then the chraracter will always face down.
+	 */
+	virtual void gotoStand(Sprite &sprite);
 };
 
 } // End of namespace Scalpel
diff --git a/engines/sherlock/tattoo/tattoo_scene.cpp b/engines/sherlock/tattoo/tattoo_scene.cpp
index 51e0eb1..6ef4d2f 100644
--- a/engines/sherlock/tattoo/tattoo_scene.cpp
+++ b/engines/sherlock/tattoo/tattoo_scene.cpp
@@ -770,6 +770,10 @@ void TattooScene::setupBGArea(const byte cMap[PALETTE_SIZE]) {
 	}
 }
 
+int TattooScene::startCAnim(int cAnimNum, int playRate) {
+	error("TODO: startCAnim");
+}
+
 } // End of namespace Tattoo
 
 } // End of namespace Sherlock
diff --git a/engines/sherlock/tattoo/tattoo_scene.h b/engines/sherlock/tattoo/tattoo_scene.h
index 78ab1e6..3c4a3cd 100644
--- a/engines/sherlock/tattoo/tattoo_scene.h
+++ b/engines/sherlock/tattoo/tattoo_scene.h
@@ -109,6 +109,15 @@ public:
 	 */
 	virtual void updateBackground();
 
+	/**
+	 * Attempt to start a canimation sequence. It will load the requisite graphics, and
+	 * then copy the canim object into the _canimShapes array to start the animation.
+	 *
+	 * @param cAnimNum		The canim object within the current scene
+	 * @param playRate		Play rate. 0 is invalid; 1=normal speed, 2=1/2 speed, etc.
+	 *		A negative playRate can also be specified to play the animation in reverse
+	 */
+	virtual int startCAnim(int cAnimNum, int playRate);
 };
 
 } // End of namespace Tattoo






More information about the Scummvm-git-logs mailing list