[Scummvm-cvs-logs] SF.net SVN: scummvm:[39668] scummvm/trunk/engines/sci/engine/kpathing.cpp

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Tue Mar 24 16:17:27 CET 2009


Revision: 39668
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39668&view=rev
Author:   waltervn
Date:     2009-03-24 15:17:25 +0000 (Tue, 24 Mar 2009)

Log Message:
-----------
SCI: Added workaround for duplicate polygons being passed to kAvoidPath.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kpathing.cpp

Modified: scummvm/trunk/engines/sci/engine/kpathing.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-03-24 15:12:22 UTC (rev 39667)
+++ scummvm/trunk/engines/sci/engine/kpathing.cpp	2009-03-24 15:17:25 UTC (rev 39668)
@@ -40,7 +40,7 @@
 #define POLY_LAST_POINT 0x7777
 #define POLY_POINT_SIZE 4
 
-static void POLY_GET_POINT(byte *p, int i, Common::Point &pt) {
+static void POLY_GET_POINT(const byte *p, int i, Common::Point &pt) {
 	pt.x = (int16)READ_LE_UINT16((p) + (i) * POLY_POINT_SIZE);
 	pt.y = (int16)READ_LE_UINT16((p) + (i) * POLY_POINT_SIZE + 2);
 }
@@ -50,7 +50,7 @@
 	WRITE_LE_UINT16((p) + (i) * POLY_POINT_SIZE + 2, pt.y);
 }
 
-static void POLY_GET_POINT_REG_T(reg_t *p, int i, Common::Point &pt) {
+static void POLY_GET_POINT_REG_T(const reg_t *p, int i, Common::Point &pt) {
 	pt.x = KP_SINT((p)[(i) * 2]);
 	pt.y = KP_SINT((p)[(i) * 2 + 1]);
 }
@@ -240,7 +240,7 @@
 	Vertex **vertex_index;
 
 	// Visibility matrix
-	char *vis_matrix;
+	byte *vis_matrix;
 
 	// Total number of vertices
 	int vertices;
@@ -269,7 +269,7 @@
 static Vertex *vertex_cur;	// FIXME
 
 // Temporary hack to deal with points in reg_ts
-static bool polygon_is_reg_t(unsigned char *list, int size) {
+static bool polygon_is_reg_t(const byte *list, int size) {
 	// Check the first three reg_ts
 	for (int i = 0; i < (size < 3 ? size : 3); i++)
 		if ((((reg_t *) list) + i)->segment)
@@ -280,7 +280,7 @@
 	return true;
 }
 
-static Common::Point read_point(unsigned char *list, int is_reg_t, int offset) {
+static Common::Point read_point(const byte *list, int is_reg_t, int offset) {
 	Common::Point point;
 
 	if (!is_reg_t) {
@@ -292,6 +292,35 @@
 	return point;
 }
 
+/**
+ * Checks whether two polygons are equal
+ */
+static bool polygons_equal(EngineState *s, reg_t p1, reg_t p2)
+{
+	// Check for same type
+	if (KP_UINT(GET_SEL32(p1, type)) != KP_UINT(GET_SEL32(p2, type)))
+		return false;
+
+	int size = KP_UINT(GET_SEL32(p1, size));
+
+	// Check for same number of points
+	if (size != KP_UINT(GET_SEL32(p2, size)))
+		return false;
+
+	const byte *p1_points = kernel_dereference_bulk_pointer(s, GET_SEL32(p1, points), size * POLY_POINT_SIZE);
+	const byte *p2_points = kernel_dereference_bulk_pointer(s, GET_SEL32(p2, points), size * POLY_POINT_SIZE);
+	bool p1_is_reg_t = polygon_is_reg_t(p1_points, size);
+	bool p2_is_reg_t = polygon_is_reg_t(p2_points, size);
+
+	// Check for the same points
+	for (int i = 0; i < size; i++) {
+		if (read_point(p1_points, p1_is_reg_t, i) != read_point(p2_points, p2_is_reg_t, i))
+			return false;
+	}
+
+	return true;
+}
+
 static void draw_line(EngineState *s, Common::Point p1, Common::Point p2, int type) {
 	// Colors for polygon debugging.
 	// Green: Total access
@@ -340,7 +369,7 @@
 	int size = KP_UINT(GET_SEL32(polygon, size));
 	int type = KP_UINT(GET_SEL32(polygon, type));
 	Common::Point first, prev;
-	unsigned char *list = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE);
+	const byte *list = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE);
 	int is_reg_t = polygon_is_reg_t(list, size);
 	int i;
 
@@ -368,7 +397,7 @@
 	list = LOOKUP_LIST(poly_list);
 
 	if (!list) {
-		warning("Could not obtain polygon list");
+		warning("[avoidpath] Could not obtain polygon list");
 		return;
 	}
 
@@ -385,7 +414,7 @@
 	int size = KP_UINT(GET_SEL32(polygon, size));
 	int type = KP_UINT(GET_SEL32(polygon, type));
 	int i;
-	unsigned char *point_array = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE);
+	const byte *point_array = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE);
 	int is_reg_t = polygon_is_reg_t(point_array, size);
 	Common::Point point;
 
@@ -414,7 +443,7 @@
 	list = LOOKUP_LIST(poly_list);
 
 	if (!list) {
-		warning("Could not obtain polygon list");
+		warning("[avoidpath] Could not obtain polygon list");
 		return;
 	}
 
@@ -1159,7 +1188,7 @@
 	int i;
 	reg_t points = GET_SEL32(polygon, points);
 	int size = KP_UINT(GET_SEL32(polygon, size));
-	unsigned char *list = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE);
+	const byte *list = kernel_dereference_bulk_pointer(s, points, size * POLY_POINT_SIZE);
 	Polygon *poly = new Polygon(KP_UINT(GET_SEL32(polygon, type)));
 	int is_reg_t = polygon_is_reg_t(list, size);
 
@@ -1215,9 +1244,24 @@
 		Node *node = LOOKUP_NODE(list->first);
 
 		while (node) {
-			polygon = convert_polygon(s, node->value);
-			pf_s->polygons.push_front(polygon);
-			count += KP_UINT(GET_SEL32(node->value, size));
+			Node *dup = LOOKUP_NODE(list->first);
+
+			// Workaround for game bugs that put a polygon in the list more than once
+			while (dup != node) {
+				if (polygons_equal(s, node->value, dup->value)) {
+					warning("[avoidpath] Ignoring duplicate polygon");
+					break;
+				}
+				dup = LOOKUP_NODE(dup->succ);
+			}
+
+			if (dup == node) {
+				// Polygon is not a duplicate, so convert it
+				polygon = convert_polygon(s, node->value);
+				pf_s->polygons.push_front(polygon);
+				count += KP_UINT(GET_SEL32(node->value, size));
+			}
+
 			node = LOOKUP_NODE(node->succ);
 		}
 	}
@@ -1282,7 +1326,7 @@
 	pf_s->vertices = count;
 
 	// Allocate and clear visibility matrix
-	pf_s->vis_matrix = (char *)sci_calloc(pf_s->vertices * VIS_MATRIX_ROW_SIZE(pf_s->vertices), 1);
+	pf_s->vis_matrix = (byte *)sci_calloc(pf_s->vertices * VIS_MATRIX_ROW_SIZE(pf_s->vertices), 1);
 
 	return pf_s;
 }


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