[Scummvm-cvs-logs] SF.net SVN: scummvm:[45437] scummvm/trunk/engines/scumm

Kirben at users.sourceforge.net Kirben at users.sourceforge.net
Tue Oct 27 12:32:33 CET 2009


Revision: 45437
          http://scummvm.svn.sourceforge.net/scummvm/?rev=45437&view=rev
Author:   Kirben
Date:     2009-10-27 11:32:33 +0000 (Tue, 27 Oct 2009)

Log Message:
-----------
Add patch #2846425 - MM C64: walkbox fixed, with minor changes.

Modified Paths:
--------------
    scummvm/trunk/engines/scumm/boxes.cpp
    scummvm/trunk/engines/scumm/scumm.h
    scummvm/trunk/engines/scumm/scumm_v0.h

Modified: scummvm/trunk/engines/scumm/boxes.cpp
===================================================================
--- scummvm/trunk/engines/scumm/boxes.cpp	2009-10-27 09:44:13 UTC (rev 45436)
+++ scummvm/trunk/engines/scumm/boxes.cpp	2009-10-27 11:32:33 UTC (rev 45437)
@@ -26,6 +26,7 @@
 #include "scumm/scumm.h"
 #include "scumm/actor.h"
 #include "scumm/boxes.h"
+#include "scumm/scumm_v0.h"
 #include "scumm/scumm_v6.h"
 #include "scumm/util.h"
 
@@ -712,20 +713,19 @@
 	boxm = getBoxMatrixBaseAddr();
 
 	if (_game.version == 0) {
-		// Skip up to the matrix data for box 'from'
-		for (i = 0; i < from; i++) {
-			while (*boxm != 0xFF)
-				boxm++;
-			boxm++;
-		}
+		// calculate shortest paths
+		byte *itineraryMatrix = (byte *)malloc(numOfBoxes * numOfBoxes);
+		calcItineraryMatrix(itineraryMatrix, numOfBoxes);
 
-		// Now search for the entry for box 'to'
-		while (boxm[0] != 0xFF) {
-			if (boxm[0] == to)
-				dest = (int8)boxm[0];
-			boxm++;
-		}
+		dest = to;
+		do {
+			dest = itineraryMatrix[numOfBoxes * from + dest];
+		} while (dest != Actor::kInvalidBox && !areBoxesNeighbours(from, dest));
 
+		if (dest == Actor::kInvalidBox)
+			dest = -1;
+
+		free(itineraryMatrix);
 		return dest;
 	} else if (_game.version <= 2) {
 		// The v2 box matrix is a real matrix with numOfBoxes rows and columns.
@@ -932,7 +932,7 @@
 	for (i = 0; i < num; i++) {
 		printf("%2d: ", i);
 		for (j = 0; j < num; j++) {
-			int val = matrix[i * 64 + j];
+			int val = matrix[i * num + j];
 			if (val == Actor::kInvalidBox)
 				printf(" ? ");
 			else
@@ -943,17 +943,18 @@
 }
 #endif
 
-void ScummEngine::createBoxMatrix() {
-	int num, i, j, k;
-	byte *adjacentMatrix, *itineraryMatrix;
+/**
+ * Computes shortest paths and stores them in the itinerary matrix.
+ * Parameter "num" holds the number of rows (= number of columns).
+ */
+void ScummEngine::calcItineraryMatrix(byte *itineraryMatrix, int num) {
+	int i, j, k;
+	byte *adjacentMatrix;
 
-	// The total number of boxes
-	num = getNumBoxes();
-	assert(num <= 64);
+	const uint8 boxSize = (_game.version == 0) ? num : 64;
 
 	// Allocate the adjacent & itinerary matrices
-	adjacentMatrix = (byte *)malloc(64 * 64);
-	itineraryMatrix = (byte *)malloc(64 * 64);
+	adjacentMatrix = (byte *)malloc(boxSize * boxSize);
 
 	// Initialise the adjacent matrix: each box has distance 0 to itself,
 	// and distance 1 to its direct neighbors. Initially, it has distance
@@ -961,14 +962,14 @@
 	for (i = 0; i < num; i++) {
 		for (j = 0; j < num; j++) {
 			if (i == j) {
-				adjacentMatrix[i * 64 + j] = 0;
-				itineraryMatrix[i * 64 + j] = j;
+				adjacentMatrix[i * boxSize + j] = 0;
+				itineraryMatrix[i * boxSize + j] = j;
 			} else if (areBoxesNeighbours(i, j)) {
-				adjacentMatrix[i * 64 + j] = 1;
-				itineraryMatrix[i * 64 + j] = j;
+				adjacentMatrix[i * boxSize + j] = 1;
+				itineraryMatrix[i * boxSize + j] = j;
 			} else {
-				adjacentMatrix[i * 64 + j] = 255;
-				itineraryMatrix[i * 64 + j] = Actor::kInvalidBox;
+				adjacentMatrix[i * boxSize + j] = 255;
+				itineraryMatrix[i * boxSize + j] = Actor::kInvalidBox;
 			}
 		}
 	}
@@ -984,17 +985,32 @@
 			for (j = 0; j < num; j++) {
 				if (i == j)
 					continue;
-				byte distIK = adjacentMatrix[64 * i + k];
-				byte distKJ = adjacentMatrix[64 * k + j];
-				if (adjacentMatrix[64 * i + j] > distIK + distKJ) {
-					adjacentMatrix[64 * i + j] = distIK + distKJ;
-					itineraryMatrix[64 * i + j] = itineraryMatrix[64 * i + k];
+				byte distIK = adjacentMatrix[boxSize * i + k];
+				byte distKJ = adjacentMatrix[boxSize * k + j];
+				if (adjacentMatrix[boxSize * i + j] > distIK + distKJ) {
+					adjacentMatrix[boxSize * i + j] = distIK + distKJ;
+					itineraryMatrix[boxSize * i + j] = itineraryMatrix[boxSize * i + k];
 				}
 			}
 		}
 
 	}
 
+	free(adjacentMatrix);
+}
+
+void ScummEngine::createBoxMatrix() {
+	int num, i, j;
+
+	// The total number of boxes
+	num = getNumBoxes();
+
+	const uint8 boxSize = (_game.version == 0) ? num : 64;
+
+	// calculate shortest paths
+	byte *itineraryMatrix = (byte *)malloc(boxSize * boxSize);
+	calcItineraryMatrix(itineraryMatrix, num);
+
 	// "Compress" the distance matrix into the box matrix format used
 	// by the engine. The format is like this:
 	// For each box (from 0 to num) there is first a byte with value 0xFF,
@@ -1015,10 +1031,10 @@
 	for (i = 0; i < num; i++) {
 		addToMatrix(0xFF);
 		for (j = 0; j < num; j++) {
-			byte itinerary = itineraryMatrix[64 * i + j];
+			byte itinerary = itineraryMatrix[boxSize * i + j];
 			if (itinerary != Actor::kInvalidBox) {
 				addToMatrix(j);
-				while (j < num - 1 && itinerary == itineraryMatrix[64 * i + (j + 1)])
+				while (j < num - 1 && itinerary == itineraryMatrix[boxSize * i + (j + 1)])
 					j++;
 				addToMatrix(j);
 				addToMatrix(itinerary);
@@ -1035,7 +1051,6 @@
 	printMatrix(getBoxMatrixBaseAddr(), num);
 #endif
 
-	free(adjacentMatrix);
 	free(itineraryMatrix);
 }
 
@@ -1137,6 +1152,41 @@
 	return false;
 }
 
+bool ScummEngine_v0::areBoxesNeighbours(int box1nr, int box2nr) {
+	int i;
+	const int numOfBoxes = getNumBoxes();
+	const byte *boxm;
+
+	assert(box1nr < numOfBoxes);
+	assert(box2nr < numOfBoxes);
+
+	boxm = getBoxMatrixBaseAddr();
+	// TODO: what are the first bytes for (mostly 0)?
+	boxm += 4;
+
+	// For each box, the matrix contains an arbitrary number
+	// of box indices that are linked with the box (neighbors).
+	// Each list is separated by 0xFF (|).
+	// E.g. "1 | 0 3 | 3 | 1 2" means:
+	//   0 -> 1, 1 -> 0/3, 2 -> 3, 3 -> 1/2
+
+	// Skip up to the matrix data for box 'box1nr'
+	for (i = 0; i < box1nr; i++) {
+		while (*boxm != 0xFF)
+			boxm++;
+		boxm++;
+	}
+
+	// Now search for the entry for box 'box2nr'
+	while (boxm[0] != 0xFF) {
+		if (boxm[0] == box2nr)
+			return true;
+		boxm++;
+	}
+
+	return false;
+}
+
 void Actor_v3::findPathTowardsOld(byte box1, byte box2, byte finalBox, Common::Point &p2, Common::Point &p3) {
 	Common::Point gateA[2];
 	Common::Point gateB[2];

Modified: scummvm/trunk/engines/scumm/scumm.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm.h	2009-10-27 09:44:13 UTC (rev 45436)
+++ scummvm/trunk/engines/scumm/scumm.h	2009-10-27 11:32:33 UTC (rev 45437)
@@ -1181,8 +1181,9 @@
 	void setBoxScaleSlot(int box, int slot);
 	void convertScaleTableToScaleSlot(int slot);
 
+	void calcItineraryMatrix(byte *itineraryMatrix, int num);
 	void createBoxMatrix();
-	bool areBoxesNeighbours(int i, int j);
+	virtual bool areBoxesNeighbours(int i, int j);
 
 	/* String class */
 public:

Modified: scummvm/trunk/engines/scumm/scumm_v0.h
===================================================================
--- scummvm/trunk/engines/scumm/scumm_v0.h	2009-10-27 09:44:13 UTC (rev 45436)
+++ scummvm/trunk/engines/scumm/scumm_v0.h	2009-10-27 11:32:33 UTC (rev 45437)
@@ -96,6 +96,8 @@
 
 	virtual void resetSentence(bool walking = false);
 
+	virtual bool areBoxesNeighbours(int box1nr, int box2nr);
+
 	/* Version C64 script opcodes */
 	void o_stopCurrentScript();
 	void o_loadSound();


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list