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

OMGPizzaGuy noreply at scummvm.org
Wed Dec 7 23:02:30 UTC 2022


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

Summary:
2183e1bb0b ULTIMA8: Store minimap data for all maps and add to savegame
b7b3a66b10 ULTIMA8: Adjust minimap save to store array size similar to world maps
147b6cea04 ULTIMA8: Reduce minimap pixel format to RGB5551
2eed148582 ULTIMA8: Update minimap storage to use HashMap
a016f1497d ULTIMA8: Split minimap generation into a separate class from the gump
c0fc6f583e ULTIMA8: Crop saved minimap surfaces to non-black area.
559e954eda ULTIMA8: Small cleanup for finding minimap bounds
c6654065d2 ULTIMA8: Fix incorrect header define for minimap.h


Commit: 2183e1bb0b23106833105c8a6757ceb219048341
    https://github.com/scummvm/scummvm/commit/2183e1bb0b23106833105c8a6757ceb219048341
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Store minimap data for all maps and add to savegame

Changed paths:
    engines/ultima/ultima8/filesys/savegame.cpp
    engines/ultima/ultima8/gumps/minimap_gump.cpp
    engines/ultima/ultima8/gumps/minimap_gump.h


diff --git a/engines/ultima/ultima8/filesys/savegame.cpp b/engines/ultima/ultima8/filesys/savegame.cpp
index 3f18ec0a641..66dc429935d 100644
--- a/engines/ultima/ultima8/filesys/savegame.cpp
+++ b/engines/ultima/ultima8/filesys/savegame.cpp
@@ -25,7 +25,7 @@ namespace Ultima {
 namespace Ultima8 {
 
 #define SAVEGAME_IDENT MKTAG('V', 'M', 'U', '8')
-#define SAVEGAME_VERSION 5
+#define SAVEGAME_VERSION 6
 #define SAVEGAME_MIN_VERSION 2
 
 SavegameReader::SavegameReader(Common::SeekableReadStream *rs, bool metadataOnly) : _file(rs), _version(0) {
diff --git a/engines/ultima/ultima8/gumps/minimap_gump.cpp b/engines/ultima/ultima8/gumps/minimap_gump.cpp
index 9548216c440..5dc8ef72fb0 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.cpp
+++ b/engines/ultima/ultima8/gumps/minimap_gump.cpp
@@ -33,22 +33,21 @@ namespace Ultima8 {
 
 DEFINE_RUNTIME_CLASSTYPE_CODE(MiniMapGump)
 
-
-static const int MINMAPGUMP_SCALE = 8;
+#define MAX_NUM_MAPS 256
+#define MINMAPGUMP_SCALE 8
 
 MiniMapGump::MiniMapGump(int x, int y) :
 	Gump(x, y, MAP_NUM_CHUNKS * 2 + 2, MAP_NUM_CHUNKS * 2 + 2, 0,
-	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimap(), _lastMapNum(0), _ax(0), _ay(0) {
-	_minimap.create((MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), (MAP_NUM_CHUNKS * MINMAPGUMP_SCALE),
-		Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
+	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(MAX_NUM_MAPS), _format(4, 8, 8, 8, 8, 24, 16, 8, 0), _ax(0), _ay(0) {
 }
 
-MiniMapGump::MiniMapGump() : Gump(), _minimap(), _lastMapNum(0), _ax(0), _ay(0) {
-	_minimap.create((MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), (MAP_NUM_CHUNKS * MINMAPGUMP_SCALE),
-		Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
+MiniMapGump::MiniMapGump() : Gump(), _minimaps(MAX_NUM_MAPS), _format(4, 8, 8, 8, 8, 24, 16, 8, 0), _ax(0), _ay(0) {
 }
 
 MiniMapGump::~MiniMapGump(void) {
+	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+		_minimaps[i].free();
+	}
 }
 
 void MiniMapGump::run() {
@@ -58,11 +57,6 @@ void MiniMapGump::run() {
 	CurrentMap *currentmap = world->getCurrentMap();
 	int mapChunkSize = currentmap->getChunkSize();
 
-	if (currentmap->getNum() != _lastMapNum) {
-		_lastMapNum = currentmap->getNum();
-		_minimap.clear();
-	}
-
 	MainActor *actor = getMainActor();
 	if (!actor || actor->isDead())
 		return;
@@ -85,10 +79,15 @@ void MiniMapGump::run() {
 void MiniMapGump::update(CurrentMap *currentmap) {
 	int mapChunkSize = currentmap->getChunkSize();
 
+	Graphics::Surface &minimap = _minimaps[currentmap->getNum()];
+	if (minimap.w == 0 && minimap.h == 0) {
+		minimap.create((MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), (MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), _format);
+	}
+
 	// Draw into the map surface
-	for (int x = 0; x < _minimap.w; x++) {
-		for (int y = 0; y < _minimap.h; y++) {
-			uint32 val = _minimap.getPixel(x, y);
+	for (int x = 0; x < minimap.w; x++) {
+		for (int y = 0; y < minimap.h; y++) {
+			uint32 val = minimap.getPixel(x, y);
 			if (val == 0) {
 				int cx = x / MINMAPGUMP_SCALE;
 				int cy = y / MINMAPGUMP_SCALE;
@@ -101,7 +100,7 @@ void MiniMapGump::update(CurrentMap *currentmap) {
 					my += mapChunkSize / (MINMAPGUMP_SCALE * 2);
 
 					val = sampleAtPoint(currentmap, mx, my);
-					_minimap.setPixel(x, y, val);
+					minimap.setPixel(x, y, val);
 				}
 			}
 		}
@@ -114,12 +113,15 @@ void MiniMapGump::generate() {
 	// TODO - do not leave whole map fast after generation
 	currentmap->setWholeMapFast();
 
-	_minimap.clear();
+	Graphics::Surface &minimap = _minimaps[currentmap->getNum()];
+	minimap.free();
 	update(currentmap);
 }
 
 void MiniMapGump::clear() {
-	_minimap.clear();
+	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+		_minimaps[i].free();
+	}
 }
 
 void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
@@ -130,7 +132,7 @@ void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 	surf->Fill32(0xFFFFAF00, _dims.right - 1, 1, 1, _dims.height());
 
 	// Dimensions minus border
-	Rect dims = _dims;
+	Common::Rect dims(_dims.left, _dims.top, _dims.right, _dims.bottom);
 	dims.grow(-1);
 
 	// Fill the background
@@ -142,26 +144,29 @@ void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 	int dx = 1;
 	int dy = 1;
 
+	World *world = World::get_instance();
+	CurrentMap *currentmap = world->getCurrentMap();
+	Graphics::ManagedSurface minimap(&_minimaps[currentmap->getNum()], DisposeAfterUse::NO);
 	Common::Rect r(sx, sy, sx + dims.width(), sy + dims.height());
 
 	if (r.left < 0) {
 		dx -= r.left;
 		r.left = 0;
 	}
-	if (r.right > _minimap.w) {
-		r.right = _minimap.w;
+	if (r.right > minimap.w) {
+		r.right = minimap.w;
 	}
 
 	if (r.top < 0) {
 		dy -= r.top;
 		r.top = 0;
 	}
-	if (r.bottom > _minimap.h) {
-		r.bottom = _minimap.h;
+	if (r.bottom > minimap.h) {
+		r.bottom = minimap.h;
 	}
 
-	if (r.isValidRect()) {
-		surf->Blit(_minimap, r, dx, dy);
+	if (!r.isEmpty()) {
+		surf->Blit(minimap, r, dx, dy);
 	}
 
 	int32 ax = _ax - sx;
@@ -188,14 +193,13 @@ uint32 MiniMapGump::sampleAtPoint(CurrentMap *currentmap, int x, int y) {
 
 		if (val == 0) {
 			// set to avoid reprocessing
-			val = _minimap.format.RGBToColor(0x00, 0x00, 0x00);
+			val = _format.RGBToColor(0x00, 0x00, 0x00);
 		}
 	}
 	return val;
 }
 
-uint32 MiniMapGump::sampleAtPoint(const Item *item, int x, int y)
-{
+uint32 MiniMapGump::sampleAtPoint(const Item *item, int x, int y) {
 	int32 ix, iy, iz, idx, idy, idz;
 	item->getLocation(ix, iy, iz);
 	item->getFootpadWorld(idx, idy, idz);
@@ -253,7 +257,7 @@ uint32 MiniMapGump::sampleAtPoint(const Item *item, int x, int y)
 	}
 
 	if (c > 0) {
-		return _minimap.format.RGBToColor(RenderSurface::_gamma10toGamma22[r / c], RenderSurface::_gamma10toGamma22[g / c], RenderSurface::_gamma10toGamma22[b / c]);
+		return _format.RGBToColor(RenderSurface::_gamma10toGamma22[r / c], RenderSurface::_gamma10toGamma22[g / c], RenderSurface::_gamma10toGamma22[b / c]);
 	}
 
 	return 0;
@@ -261,15 +265,72 @@ uint32 MiniMapGump::sampleAtPoint(const Item *item, int x, int y)
 
 void MiniMapGump::saveData(Common::WriteStream *ws) {
 	Gump::saveData(ws);
+
+	// Serialize the PixelFormat
+	ws->writeByte(_format.bytesPerPixel);
+	ws->writeByte(_format.rLoss);
+	ws->writeByte(_format.gLoss);
+	ws->writeByte(_format.bLoss);
+	ws->writeByte(_format.aLoss);
+	ws->writeByte(_format.rShift);
+	ws->writeByte(_format.gShift);
+	ws->writeByte(_format.bShift);
+	ws->writeByte(_format.aShift);
+
+	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+		const Graphics::Surface &minimap = _minimaps[i];
+		ws->writeByte(i);
+		ws->writeUint16LE(minimap.w);
+		ws->writeUint16LE(minimap.h);
+		for (int y = 0; y < minimap.h; ++y) {
+			const uint32 *pixels = (const uint32 *)minimap.getBasePtr(0, y);
+			for (int x = 0; x < minimap.w; ++x) {
+				ws->writeUint32LE(*pixels++);
+			}
+		}
+	}
 }
 
 bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 	if (!Gump::loadData(rs, version))
 		return false;
 
-	_lastMapNum = 0;
-	_minimap.clear();
+	_ax = 0;
+	_ay = 0;
+
+	if (version >= 6) {
+		_format.bytesPerPixel = rs->readByte();
+		_format.rLoss = rs->readByte();
+		_format.gLoss = rs->readByte();
+		_format.bLoss = rs->readByte();
+		_format.aLoss = rs->readByte();
+		_format.rShift = rs->readByte();
+		_format.gShift = rs->readByte();
+		_format.bShift = rs->readByte();
+		_format.aShift = rs->readByte();
+
+		for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+			Graphics::Surface &minimap = _minimaps[i];
+			if (i != rs->readByte()) {
+				return false;
+			}
+
+			uint w = rs->readUint16LE();
+			uint h = rs->readUint16LE();
+			minimap.create(w, h, _format);
 
+			for (int y = 0; y < minimap.h; ++y) {
+				uint32 *pixels = (uint32 *)minimap.getBasePtr(0, y);
+				for (int x = 0; x < minimap.w; ++x) {
+					*pixels++ = rs->readUint32LE();
+				}
+			}
+		}
+	} else {
+		for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+			_minimaps[i].free();
+		}
+	}
 	return true;
 }
 
diff --git a/engines/ultima/ultima8/gumps/minimap_gump.h b/engines/ultima/ultima8/gumps/minimap_gump.h
index 3d9bb62395c..a8fd2c1da74 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.h
+++ b/engines/ultima/ultima8/gumps/minimap_gump.h
@@ -32,8 +32,8 @@ namespace Ultima8 {
 
 class MiniMapGump : public Gump {
 private:
-	Graphics::ManagedSurface _minimap;
-	unsigned int        _lastMapNum;
+	Common::Array<Graphics::Surface> _minimaps;
+	Graphics::PixelFormat _format;
 	int32 _ax, _ay;
 
 	void update(CurrentMap *map);


Commit: b7b3a66b10dd06c7fcc67abec33c3224c8d95c4e
    https://github.com/scummvm/scummvm/commit/b7b3a66b10dd06c7fcc67abec33c3224c8d95c4e
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Adjust minimap save to store array size similar to world maps

Changed paths:
    engines/ultima/ultima8/gumps/minimap_gump.cpp


diff --git a/engines/ultima/ultima8/gumps/minimap_gump.cpp b/engines/ultima/ultima8/gumps/minimap_gump.cpp
index 5dc8ef72fb0..e45bf2e961a 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.cpp
+++ b/engines/ultima/ultima8/gumps/minimap_gump.cpp
@@ -277,9 +277,9 @@ void MiniMapGump::saveData(Common::WriteStream *ws) {
 	ws->writeByte(_format.bShift);
 	ws->writeByte(_format.aShift);
 
+	ws->writeUint32LE(static_cast<uint32>(_minimaps.size()));
 	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
 		const Graphics::Surface &minimap = _minimaps[i];
-		ws->writeByte(i);
 		ws->writeUint16LE(minimap.w);
 		ws->writeUint16LE(minimap.h);
 		for (int y = 0; y < minimap.h; ++y) {
@@ -298,6 +298,10 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 	_ax = 0;
 	_ay = 0;
 
+	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+		_minimaps[i].free();
+	}
+	
 	if (version >= 6) {
 		_format.bytesPerPixel = rs->readByte();
 		_format.rLoss = rs->readByte();
@@ -309,11 +313,16 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 		_format.bShift = rs->readByte();
 		_format.aShift = rs->readByte();
 
-		for (unsigned int i = 0; i < _minimaps.size(); ++i) {
+		uint32 mapcount = rs->readUint32LE();
+
+		// Integrity check
+		if (mapcount > _minimaps.size()) {
+			warning("Invalid minimap count in save: %d.  Corrupt save?", mapcount);
+			return false;
+		}
+
+		for (unsigned int i = 0; i < mapcount; ++i) {
 			Graphics::Surface &minimap = _minimaps[i];
-			if (i != rs->readByte()) {
-				return false;
-			}
 
 			uint w = rs->readUint16LE();
 			uint h = rs->readUint16LE();
@@ -326,10 +335,6 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 				}
 			}
 		}
-	} else {
-		for (unsigned int i = 0; i < _minimaps.size(); ++i) {
-			_minimaps[i].free();
-		}
 	}
 	return true;
 }


Commit: 147b6cea0458dd5737bc8e59267bcede45373ebb
    https://github.com/scummvm/scummvm/commit/147b6cea0458dd5737bc8e59267bcede45373ebb
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Reduce minimap pixel format to RGB5551

Changed paths:
    engines/ultima/ultima8/gumps/minimap_gump.cpp


diff --git a/engines/ultima/ultima8/gumps/minimap_gump.cpp b/engines/ultima/ultima8/gumps/minimap_gump.cpp
index e45bf2e961a..de0cc1a3fa5 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.cpp
+++ b/engines/ultima/ultima8/gumps/minimap_gump.cpp
@@ -38,10 +38,10 @@ DEFINE_RUNTIME_CLASSTYPE_CODE(MiniMapGump)
 
 MiniMapGump::MiniMapGump(int x, int y) :
 	Gump(x, y, MAP_NUM_CHUNKS * 2 + 2, MAP_NUM_CHUNKS * 2 + 2, 0,
-	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(MAX_NUM_MAPS), _format(4, 8, 8, 8, 8, 24, 16, 8, 0), _ax(0), _ay(0) {
+	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(MAX_NUM_MAPS), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
 }
 
-MiniMapGump::MiniMapGump() : Gump(), _minimaps(MAX_NUM_MAPS), _format(4, 8, 8, 8, 8, 24, 16, 8, 0), _ax(0), _ay(0) {
+MiniMapGump::MiniMapGump() : Gump(), _minimaps(MAX_NUM_MAPS), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
 }
 
 MiniMapGump::~MiniMapGump(void) {
@@ -283,9 +283,9 @@ void MiniMapGump::saveData(Common::WriteStream *ws) {
 		ws->writeUint16LE(minimap.w);
 		ws->writeUint16LE(minimap.h);
 		for (int y = 0; y < minimap.h; ++y) {
-			const uint32 *pixels = (const uint32 *)minimap.getBasePtr(0, y);
+			const uint16 *pixels = (const uint16 *)minimap.getBasePtr(0, y);
 			for (int x = 0; x < minimap.w; ++x) {
-				ws->writeUint32LE(*pixels++);
+				ws->writeUint16LE(*pixels++);
 			}
 		}
 	}
@@ -329,9 +329,9 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 			minimap.create(w, h, _format);
 
 			for (int y = 0; y < minimap.h; ++y) {
-				uint32 *pixels = (uint32 *)minimap.getBasePtr(0, y);
+				uint16 *pixels = (uint16 *)minimap.getBasePtr(0, y);
 				for (int x = 0; x < minimap.w; ++x) {
-					*pixels++ = rs->readUint32LE();
+					*pixels++ = rs->readUint16LE();
 				}
 			}
 		}


Commit: 2eed1485821e7133a197997615327d7030815004
    https://github.com/scummvm/scummvm/commit/2eed1485821e7133a197997615327d7030815004
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Update minimap storage to use HashMap

Changed paths:
    engines/ultima/ultima8/gumps/minimap_gump.cpp
    engines/ultima/ultima8/gumps/minimap_gump.h


diff --git a/engines/ultima/ultima8/gumps/minimap_gump.cpp b/engines/ultima/ultima8/gumps/minimap_gump.cpp
index de0cc1a3fa5..42307565483 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.cpp
+++ b/engines/ultima/ultima8/gumps/minimap_gump.cpp
@@ -33,20 +33,20 @@ namespace Ultima8 {
 
 DEFINE_RUNTIME_CLASSTYPE_CODE(MiniMapGump)
 
-#define MAX_NUM_MAPS 256
 #define MINMAPGUMP_SCALE 8
 
 MiniMapGump::MiniMapGump(int x, int y) :
 	Gump(x, y, MAP_NUM_CHUNKS * 2 + 2, MAP_NUM_CHUNKS * 2 + 2, 0,
-	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(MAX_NUM_MAPS), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
+	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
 }
 
-MiniMapGump::MiniMapGump() : Gump(), _minimaps(MAX_NUM_MAPS), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
+MiniMapGump::MiniMapGump() : Gump(), _minimaps(), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
 }
 
 MiniMapGump::~MiniMapGump(void) {
-	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
-		_minimaps[i].free();
+	Common::HashMap<uint32, Graphics::Surface>::iterator iter;
+	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
+		iter->_value.free();
 	}
 }
 
@@ -119,8 +119,9 @@ void MiniMapGump::generate() {
 }
 
 void MiniMapGump::clear() {
-	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
-		_minimaps[i].free();
+	Common::HashMap<uint32, Graphics::Surface>::iterator iter;
+	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
+		iter->_value.free();
 	}
 }
 
@@ -278,8 +279,10 @@ void MiniMapGump::saveData(Common::WriteStream *ws) {
 	ws->writeByte(_format.aShift);
 
 	ws->writeUint32LE(static_cast<uint32>(_minimaps.size()));
-	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
-		const Graphics::Surface &minimap = _minimaps[i];
+	Common::HashMap<uint32, Graphics::Surface>::const_iterator iter;
+	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
+		const Graphics::Surface &minimap = iter->_value;
+		ws->writeUint32LE(iter->_key);
 		ws->writeUint16LE(minimap.w);
 		ws->writeUint16LE(minimap.h);
 		for (int y = 0; y < minimap.h; ++y) {
@@ -298,8 +301,9 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 	_ax = 0;
 	_ay = 0;
 
-	for (unsigned int i = 0; i < _minimaps.size(); ++i) {
-		_minimaps[i].free();
+	Common::HashMap<uint32, Graphics::Surface>::iterator iter;
+	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
+		iter->_value.free();
 	}
 	
 	if (version >= 6) {
@@ -313,16 +317,15 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 		_format.bShift = rs->readByte();
 		_format.aShift = rs->readByte();
 
-		uint32 mapcount = rs->readUint32LE();
-
-		// Integrity check
-		if (mapcount > _minimaps.size()) {
-			warning("Invalid minimap count in save: %d.  Corrupt save?", mapcount);
+		if (_format.bytesPerPixel == 2) {
+			error("unsupported minimap texture format %d bpp", _format.bytesPerPixel);
 			return false;
 		}
 
-		for (unsigned int i = 0; i < mapcount; ++i) {
-			Graphics::Surface &minimap = _minimaps[i];
+		uint32 mapcount = rs->readUint32LE();
+		for (uint32 i = 0; i < mapcount; ++i) {
+			uint32 key = rs->readUint32LE();
+			Graphics::Surface &minimap = _minimaps[key];
 
 			uint w = rs->readUint16LE();
 			uint h = rs->readUint16LE();
diff --git a/engines/ultima/ultima8/gumps/minimap_gump.h b/engines/ultima/ultima8/gumps/minimap_gump.h
index a8fd2c1da74..b3b5edcf0bd 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.h
+++ b/engines/ultima/ultima8/gumps/minimap_gump.h
@@ -32,7 +32,7 @@ namespace Ultima8 {
 
 class MiniMapGump : public Gump {
 private:
-	Common::Array<Graphics::Surface> _minimaps;
+	Common::HashMap<uint32, Graphics::Surface> _minimaps;
 	Graphics::PixelFormat _format;
 	int32 _ax, _ay;
 


Commit: a016f1497d88fa0ba49fdbffbcfa12e22d36eeb7
    https://github.com/scummvm/scummvm/commit/a016f1497d88fa0ba49fdbffbcfa12e22d36eeb7
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Split minimap generation into a separate class from the gump

Changed paths:
  A engines/ultima/ultima8/world/minimap.cpp
  A engines/ultima/ultima8/world/minimap.h
    engines/ultima/module.mk
    engines/ultima/ultima8/gumps/minimap_gump.cpp
    engines/ultima/ultima8/gumps/minimap_gump.h
    engines/ultima/ultima8/misc/debugger.cpp


diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index c1db87ee13b..ef4975bda08 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -535,6 +535,7 @@ MODULE_OBJS := \
 	ultima8/world/item_sorter.o \
 	ultima8/world/map.o \
 	ultima8/world/map_glob.o \
+	ultima8/world/minimap.o \
 	ultima8/world/missile_tracker.o \
 	ultima8/world/monster_egg.o \
 	ultima8/world/snap_process.o \
diff --git a/engines/ultima/ultima8/gumps/minimap_gump.cpp b/engines/ultima/ultima8/gumps/minimap_gump.cpp
index 42307565483..0e13b5da8d5 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.cpp
+++ b/engines/ultima/ultima8/gumps/minimap_gump.cpp
@@ -20,12 +20,11 @@
  */
 
 #include "ultima/ultima8/gumps/minimap_gump.h"
+#include "ultima/ultima8/world/minimap.h"
+#include "ultima/ultima8/world/current_map.h"
 #include "ultima/ultima8/world/world.h"
-#include "ultima/ultima8/graphics/shape.h"
-#include "ultima/ultima8/graphics/shape_frame.h"
 #include "ultima/ultima8/world/actors/main_actor.h"
 #include "ultima/ultima8/graphics/render_surface.h"
-#include "ultima/ultima8/graphics/palette.h"
 #include "ultima/ultima8/world/get_object.h"
 
 namespace Ultima {
@@ -33,20 +32,18 @@ namespace Ultima8 {
 
 DEFINE_RUNTIME_CLASSTYPE_CODE(MiniMapGump)
 
-#define MINMAPGUMP_SCALE 8
-
 MiniMapGump::MiniMapGump(int x, int y) :
 	Gump(x, y, MAP_NUM_CHUNKS * 2 + 2, MAP_NUM_CHUNKS * 2 + 2, 0,
-	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
+	     FLAG_DRAGGABLE, LAYER_NORMAL), _minimaps(), _ax(0), _ay(0) {
 }
 
-MiniMapGump::MiniMapGump() : Gump(), _minimaps(), _format(2, 5, 5, 5, 1, 11, 6, 1, 0), _ax(0), _ay(0) {
+MiniMapGump::MiniMapGump() : Gump(), _minimaps(), _ax(0), _ay(0) {
 }
 
 MiniMapGump::~MiniMapGump(void) {
-	Common::HashMap<uint32, Graphics::Surface>::iterator iter;
+	Common::HashMap<uint32, MiniMap *>::iterator iter;
 	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
-		iter->_value.free();
+		delete iter->_value;
 	}
 }
 
@@ -74,37 +71,14 @@ void MiniMapGump::run() {
 	_ax = ax;
 	_ay = ay;
 
-	update(currentmap);
-}
-void MiniMapGump::update(CurrentMap *currentmap) {
-	int mapChunkSize = currentmap->getChunkSize();
-
-	Graphics::Surface &minimap = _minimaps[currentmap->getNum()];
-	if (minimap.w == 0 && minimap.h == 0) {
-		minimap.create((MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), (MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), _format);
-	}
+	uint32 mapNum = currentmap->getNum();
 
-	// Draw into the map surface
-	for (int x = 0; x < minimap.w; x++) {
-		for (int y = 0; y < minimap.h; y++) {
-			uint32 val = minimap.getPixel(x, y);
-			if (val == 0) {
-				int cx = x / MINMAPGUMP_SCALE;
-				int cy = y / MINMAPGUMP_SCALE;
-				if (currentmap->isChunkFast(cx, cy)) {
-					int mx = (x * mapChunkSize) / MINMAPGUMP_SCALE;
-					int my = (y * mapChunkSize) / MINMAPGUMP_SCALE;
-
-					// Offset produces nicer samples but may need altering
-					mx += mapChunkSize / (MINMAPGUMP_SCALE * 2);
-					my += mapChunkSize / (MINMAPGUMP_SCALE * 2);
-
-					val = sampleAtPoint(currentmap, mx, my);
-					minimap.setPixel(x, y, val);
-				}
-			}
-		}
+	MiniMap *minimap = _minimaps[mapNum];
+	if (!minimap) {
+		minimap = new MiniMap(mapNum);
+		_minimaps[mapNum] = minimap;
 	}
+	minimap->update(currentmap);
 }
 
 void MiniMapGump::generate() {
@@ -113,16 +87,22 @@ void MiniMapGump::generate() {
 	// TODO - do not leave whole map fast after generation
 	currentmap->setWholeMapFast();
 
-	Graphics::Surface &minimap = _minimaps[currentmap->getNum()];
-	minimap.free();
-	update(currentmap);
+	uint32 mapNum = currentmap->getNum();
+
+	MiniMap *minimap = _minimaps[mapNum];
+	if (!minimap) {
+		minimap = new MiniMap(mapNum);
+		_minimaps[mapNum] = minimap;
+	}
+	minimap->update(currentmap);
 }
 
 void MiniMapGump::clear() {
-	Common::HashMap<uint32, Graphics::Surface>::iterator iter;
+	Common::HashMap<uint32, MiniMap *>::iterator iter;
 	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
-		iter->_value.free();
+		delete iter->_value;
 	}
+	_minimaps.clear();
 }
 
 void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
@@ -147,27 +127,28 @@ void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 
 	World *world = World::get_instance();
 	CurrentMap *currentmap = world->getCurrentMap();
-	Graphics::ManagedSurface minimap(&_minimaps[currentmap->getNum()], DisposeAfterUse::NO);
+	MiniMap *minimap = _minimaps[currentmap->getNum()];
+	Graphics::ManagedSurface ms(minimap->getSurface(), DisposeAfterUse::NO);
 	Common::Rect r(sx, sy, sx + dims.width(), sy + dims.height());
 
 	if (r.left < 0) {
 		dx -= r.left;
 		r.left = 0;
 	}
-	if (r.right > minimap.w) {
-		r.right = minimap.w;
+	if (r.right > ms.w) {
+		r.right = ms.w;
 	}
 
 	if (r.top < 0) {
 		dy -= r.top;
 		r.top = 0;
 	}
-	if (r.bottom > minimap.h) {
-		r.bottom = minimap.h;
+	if (r.bottom > ms.h) {
+		r.bottom = ms.h;
 	}
 
 	if (!r.isEmpty()) {
-		surf->Blit(minimap, r, dx, dy);
+		surf->Blit(ms, r, dx, dy);
 	}
 
 	int32 ax = _ax - sx;
@@ -180,117 +161,15 @@ void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 	surf->Fill32(0xFFFFFF00, 1 + ax + 0, 1 + ay + 1, 1, 2);
 }
 
-uint32 MiniMapGump::sampleAtPoint(CurrentMap *currentmap, int x, int y) {
-	uint32 val = 0;
-	const Item *item = currentmap->traceTopItem(x, y, 1 << 15, -1, 0, ShapeInfo::SI_ROOF | ShapeInfo::SI_OCCL | ShapeInfo::SI_LAND | ShapeInfo::SI_SEA);
-	if (item) {
-		val = sampleAtPoint(item, x, y);
-		if (val == 0) {
-			item = currentmap->traceTopItem(x, y, 1 << 15, -1, item->getObjId(), ShapeInfo::SI_ROOF | ShapeInfo::SI_OCCL | ShapeInfo::SI_LAND | ShapeInfo::SI_SEA);
-			if (item) {
-				val = sampleAtPoint(item, x, y);
-			}
-		}
-
-		if (val == 0) {
-			// set to avoid reprocessing
-			val = _format.RGBToColor(0x00, 0x00, 0x00);
-		}
-	}
-	return val;
-}
-
-uint32 MiniMapGump::sampleAtPoint(const Item *item, int x, int y) {
-	int32 ix, iy, iz, idx, idy, idz;
-	item->getLocation(ix, iy, iz);
-	item->getFootpadWorld(idx, idy, idz);
-
-	ix -= x;
-	iy -= y;
-
-	const Shape *sh = item->getShapeObject();
-	if (!sh)
-		return 0;
-
-	const ShapeFrame *frame = sh->getFrame(item->getFrame());
-	if (!frame)
-		return 0;
-
-	const Palette *pal = sh->getPalette();
-	if (!pal)
-		return 0;
-
-	if (item->canDrag())
-		return 0;
-
-	// Screenspace bounding box bottom x_ coord (RNB x_ coord)
-	int sx = (ix - iy) / 4;
-	// Screenspace bounding box bottom extent  (RNB y_ coord)
-	int sy = (ix + iy) / 8 + idz;
-
-	int w = 2;
-	int h = 2;
-
-	// Ensure sample is in bounds of frame
-	if (frame->_xoff - sx < 0)
-		sx = frame->_xoff;
-	else if (frame->_xoff - sx >= frame->_width - w)
-		sx = frame->_xoff - frame->_width + w;
-
-	if (frame->_yoff - sy < 0)
-		sy = frame->_yoff;
-	else if (frame->_yoff - sy >= frame->_height - h)
-		sy = frame->_yoff - frame->_height + h;
-
-	uint16 r = 0, g = 0, b = 0, c = 0;
-
-	for (int j = 0; j < w; j++) {
-		for (int i = 0; i < h; i++) {
-			if (!frame->hasPoint(i - sx, j - sy)) continue;
-
-			byte r2, g2, b2;
-			UNPACK_RGB8(pal->_native_untransformed[frame->getPixelAtPoint(i - sx, j - sy)], r2, g2, b2);
-			r += RenderSurface::_gamma22toGamma10[r2];
-			g += RenderSurface::_gamma22toGamma10[g2];
-			b += RenderSurface::_gamma22toGamma10[b2];
-			c++;
-		}
-	}
-
-	if (c > 0) {
-		return _format.RGBToColor(RenderSurface::_gamma10toGamma22[r / c], RenderSurface::_gamma10toGamma22[g / c], RenderSurface::_gamma10toGamma22[b / c]);
-	}
-
-	return 0;
-}
-
 void MiniMapGump::saveData(Common::WriteStream *ws) {
 	Gump::saveData(ws);
 
-	// Serialize the PixelFormat
-	ws->writeByte(_format.bytesPerPixel);
-	ws->writeByte(_format.rLoss);
-	ws->writeByte(_format.gLoss);
-	ws->writeByte(_format.bLoss);
-	ws->writeByte(_format.aLoss);
-	ws->writeByte(_format.rShift);
-	ws->writeByte(_format.gShift);
-	ws->writeByte(_format.bShift);
-	ws->writeByte(_format.aShift);
-
 	ws->writeUint32LE(static_cast<uint32>(_minimaps.size()));
-	Common::HashMap<uint32, Graphics::Surface>::const_iterator iter;
+	Common::HashMap<uint32, MiniMap *>::const_iterator iter;
 	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
-		const Graphics::Surface &minimap = iter->_value;
+		const MiniMap *minimap = iter->_value;
 		ws->writeUint32LE(iter->_key);
-		ws->writeUint16LE(minimap.w);
-		ws->writeUint16LE(minimap.h);
-		for (int y = 0; y < minimap.h; ++y) {
-			const uint16 *pixels = (const uint16 *)minimap.getBasePtr(0, y);
-			for (int x = 0; x < minimap.w; ++x) {
-				ws->writeUint16LE(*pixels++);
-			}
-		}
+		minimap->save(ws);
 	}
 }
 
@@ -301,42 +180,16 @@ bool MiniMapGump::loadData(Common::ReadStream *rs, uint32 version) {
 	_ax = 0;
 	_ay = 0;
 
-	Common::HashMap<uint32, Graphics::Surface>::iterator iter;
-	for (iter = _minimaps.begin(); iter != _minimaps.end(); ++iter) {
-		iter->_value.free();
-	}
-	
-	if (version >= 6) {
-		_format.bytesPerPixel = rs->readByte();
-		_format.rLoss = rs->readByte();
-		_format.gLoss = rs->readByte();
-		_format.bLoss = rs->readByte();
-		_format.aLoss = rs->readByte();
-		_format.rShift = rs->readByte();
-		_format.gShift = rs->readByte();
-		_format.bShift = rs->readByte();
-		_format.aShift = rs->readByte();
-
-		if (_format.bytesPerPixel == 2) {
-			error("unsupported minimap texture format %d bpp", _format.bytesPerPixel);
-			return false;
-		}
+	clear();
 
+	if (version >= 6) {
 		uint32 mapcount = rs->readUint32LE();
 		for (uint32 i = 0; i < mapcount; ++i) {
-			uint32 key = rs->readUint32LE();
-			Graphics::Surface &minimap = _minimaps[key];
-
-			uint w = rs->readUint16LE();
-			uint h = rs->readUint16LE();
-			minimap.create(w, h, _format);
-
-			for (int y = 0; y < minimap.h; ++y) {
-				uint16 *pixels = (uint16 *)minimap.getBasePtr(0, y);
-				for (int x = 0; x < minimap.w; ++x) {
-					*pixels++ = rs->readUint16LE();
-				}
-			}
+			uint32 mapNum = rs->readUint32LE();
+			MiniMap *minimap = new MiniMap(mapNum);
+			if (!minimap->load(rs, version))
+				return false;
+			_minimaps[mapNum] = minimap;
 		}
 	}
 	return true;
diff --git a/engines/ultima/ultima8/gumps/minimap_gump.h b/engines/ultima/ultima8/gumps/minimap_gump.h
index b3b5edcf0bd..1e70956cd29 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.h
+++ b/engines/ultima/ultima8/gumps/minimap_gump.h
@@ -23,22 +23,18 @@
 #define ULTIMA8_GUMPS_MINIMAPGUMP_H
 
 #include "ultima/ultima8/gumps/gump.h"
-#include "ultima/ultima8/world/current_map.h"
 #include "ultima/ultima8/misc/classtype.h"
-#include "graphics/managed_surface.h"
 
 namespace Ultima {
 namespace Ultima8 {
 
+class MiniMap;
+
 class MiniMapGump : public Gump {
 private:
-	Common::HashMap<uint32, Graphics::Surface> _minimaps;
-	Graphics::PixelFormat _format;
+	Common::HashMap<uint32, MiniMap *> _minimaps;
 	int32 _ax, _ay;
 
-	void update(CurrentMap *map);
-	uint32 sampleAtPoint(CurrentMap *map, int x, int y);
-	uint32 sampleAtPoint(const Item *item, int x, int y);
 public:
 	ENABLE_RUNTIME_CLASSTYPE()
 
diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index d1cf0d772d8..394c8f04790 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -42,6 +42,7 @@
 #include "ultima/ultima8/misc/util.h"
 #include "ultima/ultima8/usecode/uc_machine.h"
 #include "ultima/ultima8/usecode/bit_set.h"
+#include "ultima/ultima8/world/current_map.h"
 #include "ultima/ultima8/world/world.h"
 #include "ultima/ultima8/world/camera_process.h"
 #include "ultima/ultima8/world/get_object.h"
diff --git a/engines/ultima/ultima8/world/minimap.cpp b/engines/ultima/ultima8/world/minimap.cpp
new file mode 100644
index 00000000000..17b4d28e14c
--- /dev/null
+++ b/engines/ultima/ultima8/world/minimap.cpp
@@ -0,0 +1,212 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/stream.h"
+
+#include "ultima/ultima8/world/minimap.h"
+#include "ultima/ultima8/world/current_map.h"
+#include "ultima/ultima8/world/item.h"
+#include "ultima/ultima8/graphics/render_surface.h"
+#include "ultima/ultima8/graphics/shape.h"
+#include "ultima/ultima8/graphics/shape_frame.h"
+#include "ultima/ultima8/graphics/palette.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+MiniMap::MiniMap(uint32 mapNum) : _mapNum(mapNum), _surface() {
+	_surface.create((MAP_NUM_CHUNKS * MINMAPGUMP_SCALE), (MAP_NUM_CHUNKS * MINMAPGUMP_SCALE),
+					Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
+}
+
+MiniMap::~MiniMap() {
+	_surface.free();
+}
+
+void MiniMap::update(CurrentMap *currentmap) {
+	int mapChunkSize = currentmap->getChunkSize();
+
+	// Draw into the map surface
+	for (int x = 0; x < _surface.w; x++) {
+		for (int y = 0; y < _surface.h; y++) {
+			uint32 val = _surface.getPixel(x, y);
+			if (val == 0) {
+				int cx = x / MINMAPGUMP_SCALE;
+				int cy = y / MINMAPGUMP_SCALE;
+				if (currentmap->isChunkFast(cx, cy)) {
+					int mx = (x * mapChunkSize) / MINMAPGUMP_SCALE;
+					int my = (y * mapChunkSize) / MINMAPGUMP_SCALE;
+
+					// Offset produces nicer samples but may need altering
+					mx += mapChunkSize / (MINMAPGUMP_SCALE * 2);
+					my += mapChunkSize / (MINMAPGUMP_SCALE * 2);
+
+					val = sampleAtPoint(currentmap, mx, my);
+					_surface.setPixel(x, y, val);
+				}
+			}
+		}
+	}
+}
+
+uint32 MiniMap::sampleAtPoint(CurrentMap *currentmap, int x, int y) {
+	uint32 val = 0;
+	const Item *item = currentmap->traceTopItem(x, y, 1 << 15, -1, 0, ShapeInfo::SI_ROOF | ShapeInfo::SI_OCCL | ShapeInfo::SI_LAND | ShapeInfo::SI_SEA);
+	if (item) {
+		val = sampleAtPoint(item, x, y);
+		if (val == 0) {
+			item = currentmap->traceTopItem(x, y, 1 << 15, -1, item->getObjId(), ShapeInfo::SI_ROOF | ShapeInfo::SI_OCCL | ShapeInfo::SI_LAND | ShapeInfo::SI_SEA);
+			if (item) {
+				val = sampleAtPoint(item, x, y);
+			}
+		}
+
+		if (val == 0) {
+			// set to avoid reprocessing
+			val = _surface.format.RGBToColor(0x00, 0x00, 0x00);
+		}
+	}
+	return val;
+}
+
+uint32 MiniMap::sampleAtPoint(const Item *item, int x, int y) {
+	int32 ix, iy, iz, idx, idy, idz;
+	item->getLocation(ix, iy, iz);
+	item->getFootpadWorld(idx, idy, idz);
+
+	ix -= x;
+	iy -= y;
+
+	const Shape *sh = item->getShapeObject();
+	if (!sh)
+		return 0;
+
+	const ShapeFrame *frame = sh->getFrame(item->getFrame());
+	if (!frame)
+		return 0;
+
+	const Palette *pal = sh->getPalette();
+	if (!pal)
+		return 0;
+
+	if (item->canDrag())
+		return 0;
+
+	// Screenspace bounding box bottom x_ coord (RNB x_ coord)
+	int sx = (ix - iy) / 4;
+	// Screenspace bounding box bottom extent  (RNB y_ coord)
+	int sy = (ix + iy) / 8 + idz;
+
+	int w = 2;
+	int h = 2;
+
+	// Ensure sample is in bounds of frame
+	if (frame->_xoff - sx < 0)
+		sx = frame->_xoff;
+	else if (frame->_xoff - sx >= frame->_width - w)
+		sx = frame->_xoff - frame->_width + w;
+
+	if (frame->_yoff - sy < 0)
+		sy = frame->_yoff;
+	else if (frame->_yoff - sy >= frame->_height - h)
+		sy = frame->_yoff - frame->_height + h;
+
+	uint16 r = 0, g = 0, b = 0, c = 0;
+
+	for (int j = 0; j < w; j++) {
+		for (int i = 0; i < h; i++) {
+			if (!frame->hasPoint(i - sx, j - sy))
+				continue;
+
+			byte r2, g2, b2;
+			UNPACK_RGB8(pal->_native_untransformed[frame->getPixelAtPoint(i - sx, j - sy)], r2, g2, b2);
+			r += RenderSurface::_gamma22toGamma10[r2];
+			g += RenderSurface::_gamma22toGamma10[g2];
+			b += RenderSurface::_gamma22toGamma10[b2];
+			c++;
+		}
+	}
+
+	if (c > 0) {
+		return _surface.format.RGBToColor(RenderSurface::_gamma10toGamma22[r / c], RenderSurface::_gamma10toGamma22[g / c], RenderSurface::_gamma10toGamma22[b / c]);
+	}
+
+	return 0;
+}
+
+bool MiniMap::load(Common::ReadStream *rs, uint32 version) {
+	//_mapNum = rs->readUint32LE();
+	uint w = rs->readUint16LE();
+	uint h = rs->readUint16LE();
+
+	Graphics::PixelFormat format;
+	format.bytesPerPixel = rs->readByte();
+	format.rLoss = rs->readByte();
+	format.gLoss = rs->readByte();
+	format.bLoss = rs->readByte();
+	format.aLoss = rs->readByte();
+	format.rShift = rs->readByte();
+	format.gShift = rs->readByte();
+	format.bShift = rs->readByte();
+	format.aShift = rs->readByte();
+
+	if (format.bytesPerPixel != 2) {
+		error("unsupported minimap texture format %d bpp", format.bytesPerPixel);
+		return false;
+	}
+
+	_surface.create(w, h, format);
+	for (int y = 0; y < _surface.h; ++y) {
+		uint16 *pixels = (uint16 *)_surface.getBasePtr(0, y);
+		for (int x = 0; x < _surface.w; ++x) {
+			*pixels++ = rs->readUint16LE();
+		}
+	}
+	return true;
+}
+
+void MiniMap::save(Common::WriteStream *ws) const {
+	//ws->writeUint32LE(_mapNum);
+	ws->writeUint16LE(_surface.w);
+	ws->writeUint16LE(_surface.h);
+
+	// Serialize the PixelFormat
+	ws->writeByte(_surface.format.bytesPerPixel);
+	ws->writeByte(_surface.format.rLoss);
+	ws->writeByte(_surface.format.gLoss);
+	ws->writeByte(_surface.format.bLoss);
+	ws->writeByte(_surface.format.aLoss);
+	ws->writeByte(_surface.format.rShift);
+	ws->writeByte(_surface.format.gShift);
+	ws->writeByte(_surface.format.bShift);
+	ws->writeByte(_surface.format.aShift);
+
+	// Serialize the pixel data
+	for (int y = 0; y < _surface.h; ++y) {
+		const uint16 *pixels = (const uint16 *)_surface.getBasePtr(0, y);
+		for (int x = 0; x < _surface.w; ++x) {
+			ws->writeUint16LE(*pixels++);
+		}
+	}
+}
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/minimap.h b/engines/ultima/ultima8/world/minimap.h
new file mode 100644
index 00000000000..9648a665530
--- /dev/null
+++ b/engines/ultima/ultima8/world/minimap.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ultima/ultima8/misc/common_types.h"
+#include "graphics/surface.h"
+
+#ifndef ULTIMA8_WORLD_MAP_H
+#define ULTIMA8_WORLD_MAP_H
+
+namespace Ultima {
+namespace Ultima8 {
+
+class CurrentMap;
+class Item;
+
+#define MINMAPGUMP_SCALE 8
+
+class MiniMap {
+private:
+	uint32 _mapNum;
+	Graphics::Surface _surface;
+
+	uint32 sampleAtPoint(CurrentMap *map, int x, int y);
+	uint32 sampleAtPoint(const Item *item, int x, int y);
+
+public:
+	MiniMap(uint32 mapNum);
+	~MiniMap();
+
+	void update(CurrentMap *map);
+
+	uint32 getMapNum() const { return _mapNum; }
+	Graphics::Surface *getSurface() { return &_surface; }
+
+	bool load(Common::ReadStream *rs, uint32 version);
+	void save(Common::WriteStream *ws) const;
+};
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
+
+#endif


Commit: c0fc6f583ed1487b04810f20ed6c43eefbcac554
    https://github.com/scummvm/scummvm/commit/c0fc6f583ed1487b04810f20ed6c43eefbcac554
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Crop saved minimap surfaces to non-black area.

Changed paths:
    engines/ultima/ultima8/gumps/minimap_gump.cpp
    engines/ultima/ultima8/world/minimap.cpp
    engines/ultima/ultima8/world/minimap.h


diff --git a/engines/ultima/ultima8/gumps/minimap_gump.cpp b/engines/ultima/ultima8/gumps/minimap_gump.cpp
index 0e13b5da8d5..47bba5dfecd 100644
--- a/engines/ultima/ultima8/gumps/minimap_gump.cpp
+++ b/engines/ultima/ultima8/gumps/minimap_gump.cpp
@@ -127,7 +127,14 @@ void MiniMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 
 	World *world = World::get_instance();
 	CurrentMap *currentmap = world->getCurrentMap();
-	MiniMap *minimap = _minimaps[currentmap->getNum()];
+	uint32 mapNum = currentmap->getNum();
+
+	MiniMap *minimap = _minimaps[mapNum];
+	if (!minimap) {
+		minimap = new MiniMap(mapNum);
+		_minimaps[mapNum] = minimap;
+	}
+
 	Graphics::ManagedSurface ms(minimap->getSurface(), DisposeAfterUse::NO);
 	Common::Rect r(sx, sy, sx + dims.width(), sy + dims.height());
 
diff --git a/engines/ultima/ultima8/world/minimap.cpp b/engines/ultima/ultima8/world/minimap.cpp
index 17b4d28e14c..8b2482f12fb 100644
--- a/engines/ultima/ultima8/world/minimap.cpp
+++ b/engines/ultima/ultima8/world/minimap.cpp
@@ -152,10 +152,76 @@ uint32 MiniMap::sampleAtPoint(const Item *item, int x, int y) {
 	return 0;
 }
 
+const Common::Rect MiniMap::getCropBounds() const {
+	Common::Rect bounds;
+	uint32 mask = _surface.format.ARGBToColor(0x00, 0xFF, 0xFF, 0xFF);
+
+	// Get top & initial rect
+	bool found = false;
+	for (int y = 0; !found && y < _surface.h; y++) {
+		for (int x = 0; !found && x < _surface.w; x++) {
+			uint32 val = _surface.getPixel(x, y);
+			if ((val & mask) != 0) {
+				bounds.top = y;
+				bounds.bottom = y + 1;
+				bounds.left = x;
+				bounds.right = x + 1;
+				found = true;
+			}
+		}
+	}
+
+	// Get bottom & extend left / right
+	found = false;
+	for (int y = _surface.h - 1; !found && y > bounds.top; y--) {
+		for (int x = 0; !found && x < _surface.w; x++) {
+			uint32 val = _surface.getPixel(x, y);
+			if ((val & mask) != 0) {
+				bounds.bottom = y + 1;
+				if (x < bounds.left)
+					bounds.left = x;
+				if (x > bounds.right)
+					bounds.right = x + 1;
+				found = true;
+			}
+		}
+	}
+
+	// Get left
+	found = false;
+	for (int x = 0; !found && x < bounds.left; x++) {
+		for (int y = bounds.top; !found && y < bounds.bottom; y++) {
+			uint32 val = _surface.getPixel(x, y);
+			if ((val & mask) != 0) {
+				bounds.left = x;
+				found = true;
+			}
+		}
+	}
+
+	// Get right
+	found = false;
+	for (int x = _surface.w - 1; !found && x > bounds.right; x--) {
+		for (int y = bounds.top; !found && y < bounds.bottom; y++) {
+			uint32 val = _surface.getPixel(x, y);
+			if ((val & mask) != 0) {
+				bounds.right = x + 1;
+				found = true;
+			}
+		}
+	}
+
+	return bounds;
+}
+
 bool MiniMap::load(Common::ReadStream *rs, uint32 version) {
 	//_mapNum = rs->readUint32LE();
-	uint w = rs->readUint16LE();
-	uint h = rs->readUint16LE();
+
+	Common::Rect bounds;
+	bounds.left = rs->readUint16LE();
+	bounds.top = rs->readUint16LE();
+	bounds.right = rs->readUint16LE();
+	bounds.bottom = rs->readUint16LE();
 
 	Graphics::PixelFormat format;
 	format.bytesPerPixel = rs->readByte();
@@ -173,10 +239,12 @@ bool MiniMap::load(Common::ReadStream *rs, uint32 version) {
 		return false;
 	}
 
+	uint16 w = _surface.w;
+	uint16 h = _surface.h;
 	_surface.create(w, h, format);
-	for (int y = 0; y < _surface.h; ++y) {
-		uint16 *pixels = (uint16 *)_surface.getBasePtr(0, y);
-		for (int x = 0; x < _surface.w; ++x) {
+	for (int y = bounds.top; y < bounds.bottom; ++y) {
+		uint16 *pixels = (uint16 *)_surface.getBasePtr(bounds.left, y);
+		for (int x = bounds.left; x < bounds.right; ++x) {
 			*pixels++ = rs->readUint16LE();
 		}
 	}
@@ -185,8 +253,12 @@ bool MiniMap::load(Common::ReadStream *rs, uint32 version) {
 
 void MiniMap::save(Common::WriteStream *ws) const {
 	//ws->writeUint32LE(_mapNum);
-	ws->writeUint16LE(_surface.w);
-	ws->writeUint16LE(_surface.h);
+
+	Common::Rect bounds = getCropBounds();
+	ws->writeUint16LE(bounds.left);
+	ws->writeUint16LE(bounds.top);
+	ws->writeUint16LE(bounds.right);
+	ws->writeUint16LE(bounds.bottom);
 
 	// Serialize the PixelFormat
 	ws->writeByte(_surface.format.bytesPerPixel);
@@ -200,9 +272,9 @@ void MiniMap::save(Common::WriteStream *ws) const {
 	ws->writeByte(_surface.format.aShift);
 
 	// Serialize the pixel data
-	for (int y = 0; y < _surface.h; ++y) {
-		const uint16 *pixels = (const uint16 *)_surface.getBasePtr(0, y);
-		for (int x = 0; x < _surface.w; ++x) {
+	for (int y = bounds.top; y < bounds.bottom; ++y) {
+		const uint16 *pixels = (const uint16 *)_surface.getBasePtr(bounds.left, y);
+		for (int x = bounds.left; x < bounds.right; ++x) {
 			ws->writeUint16LE(*pixels++);
 		}
 	}
diff --git a/engines/ultima/ultima8/world/minimap.h b/engines/ultima/ultima8/world/minimap.h
index 9648a665530..226865992d2 100644
--- a/engines/ultima/ultima8/world/minimap.h
+++ b/engines/ultima/ultima8/world/minimap.h
@@ -41,6 +41,7 @@ private:
 	uint32 sampleAtPoint(CurrentMap *map, int x, int y);
 	uint32 sampleAtPoint(const Item *item, int x, int y);
 
+	const Common::Rect getCropBounds() const;
 public:
 	MiniMap(uint32 mapNum);
 	~MiniMap();


Commit: 559e954eda7813f257c3b84604cc722b81bf0b2c
    https://github.com/scummvm/scummvm/commit/559e954eda7813f257c3b84604cc722b81bf0b2c
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Small cleanup for finding minimap bounds

Changed paths:
    engines/ultima/ultima8/world/minimap.cpp


diff --git a/engines/ultima/ultima8/world/minimap.cpp b/engines/ultima/ultima8/world/minimap.cpp
index 8b2482f12fb..6adc096cd55 100644
--- a/engines/ultima/ultima8/world/minimap.cpp
+++ b/engines/ultima/ultima8/world/minimap.cpp
@@ -153,60 +153,61 @@ uint32 MiniMap::sampleAtPoint(const Item *item, int x, int y) {
 }
 
 const Common::Rect MiniMap::getCropBounds() const {
-	Common::Rect bounds;
+	Common::Rect bounds(_surface.w, _surface.h);
 	uint32 mask = _surface.format.ARGBToColor(0x00, 0xFF, 0xFF, 0xFF);
 
-	// Get top & initial rect
-	bool found = false;
-	for (int y = 0; !found && y < _surface.h; y++) {
-		for (int x = 0; !found && x < _surface.w; x++) {
+	// Get left
+	for (int x = bounds.left; x < bounds.right; x++) {
+		for (int y = bounds.top; y < bounds.bottom; y++) {
 			uint32 val = _surface.getPixel(x, y);
 			if ((val & mask) != 0) {
-				bounds.top = y;
-				bounds.bottom = y + 1;
 				bounds.left = x;
-				bounds.right = x + 1;
-				found = true;
+
+				// end loops
+				x = bounds.right;
+				y = bounds.bottom;
 			}
 		}
 	}
 
-	// Get bottom & extend left / right
-	found = false;
-	for (int y = _surface.h - 1; !found && y > bounds.top; y--) {
-		for (int x = 0; !found && x < _surface.w; x++) {
+	// Get top
+	for (int y = bounds.top; y < bounds.bottom; y++) {
+		for (int x = bounds.left; x < bounds.right; x++) {
 			uint32 val = _surface.getPixel(x, y);
 			if ((val & mask) != 0) {
-				bounds.bottom = y + 1;
-				if (x < bounds.left)
-					bounds.left = x;
-				if (x > bounds.right)
-					bounds.right = x + 1;
-				found = true;
+				bounds.top = y;
+
+				// end loops
+				x = bounds.right;
+				y = bounds.bottom;
 			}
 		}
 	}
 
-	// Get left
-	found = false;
-	for (int x = 0; !found && x < bounds.left; x++) {
-		for (int y = bounds.top; !found && y < bounds.bottom; y++) {
+	// Get right
+	for (int x = bounds.right - 1; x > bounds.left; x--) {
+		for (int y = bounds.bottom - 1; y > bounds.top; y--) {
 			uint32 val = _surface.getPixel(x, y);
 			if ((val & mask) != 0) {
-				bounds.left = x;
-				found = true;
+				bounds.right = x + 1;
+
+				// end loops
+				x = bounds.left;
+				y = bounds.top;
 			}
 		}
 	}
 
-	// Get right
-	found = false;
-	for (int x = _surface.w - 1; !found && x > bounds.right; x--) {
-		for (int y = bounds.top; !found && y < bounds.bottom; y++) {
+	// Get bottom
+	for (int y = bounds.bottom - 1; y > bounds.top; y--) {
+		for (int x = bounds.right - 1; x > bounds.left; x--) {
 			uint32 val = _surface.getPixel(x, y);
 			if ((val & mask) != 0) {
-				bounds.right = x + 1;
-				found = true;
+				bounds.bottom = y + 1;
+
+				// end loops
+				x = bounds.left;
+				y = bounds.top;
 			}
 		}
 	}


Commit: c6654065d2f268365469a0fb0d62d191d90cc455
    https://github.com/scummvm/scummvm/commit/c6654065d2f268365469a0fb0d62d191d90cc455
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2022-12-07T17:02:23-06:00

Commit Message:
ULTIMA8: Fix incorrect header define for minimap.h

Changed paths:
    engines/ultima/ultima8/world/minimap.h


diff --git a/engines/ultima/ultima8/world/minimap.h b/engines/ultima/ultima8/world/minimap.h
index 226865992d2..bfb90844d72 100644
--- a/engines/ultima/ultima8/world/minimap.h
+++ b/engines/ultima/ultima8/world/minimap.h
@@ -22,8 +22,8 @@
 #include "ultima/ultima8/misc/common_types.h"
 #include "graphics/surface.h"
 
-#ifndef ULTIMA8_WORLD_MAP_H
-#define ULTIMA8_WORLD_MAP_H
+#ifndef ULTIMA8_WORLD_MINIMAP_H
+#define ULTIMA8_WORLD_MINIMAP_H
 
 namespace Ultima {
 namespace Ultima8 {




More information about the Scummvm-git-logs mailing list