(svn r11943) -Codechange: add and use a simple structure to support small stacks by allocating it on the heap or pushing a few kB of data onto the stack when there is a large stack.
authorrubidium
Tue, 22 Jan 2008 12:09:12 +0000
changeset 8872 dd23eb1922b6
parent 8871 08e81cca0a66
child 8873 99dee7eb17e0
(svn r11943) -Codechange: add and use a simple structure to support small stacks by allocating it on the heap or pushing a few kB of data onto the stack when there is a large stack.
src/core/alloc_func.hpp
src/misc.cpp
--- a/src/core/alloc_func.hpp	Tue Jan 22 08:47:30 2008 +0000
+++ b/src/core/alloc_func.hpp	Tue Jan 22 12:09:12 2008 +0000
@@ -81,4 +81,35 @@
 	return t_ptr;
 }
 
+/**
+ * A small 'wrapper' for allocations that can be done on most OSes on the
+ * stack, but are just too large to fit in the stack on devices with a small
+ * stack such as the NDS.
+ * So when it is possible a stack allocation is made, otherwise a heap
+ * allocation is made and this is freed once the struct goes out of scope.
+ * @param T      the type to make the allocation for
+ * @param length the amount of items to allocate
+ */
+template <typename T, size_t length>
+struct SmallStackSafeStackAlloc {
+#if !defined(__NDS__)
+	/** Storing the data on the stack */
+	T data[length];
+#else
+	/** Storing it on the heap */
+	T *data;
+
+	/** Allocating the memory */
+	SmallStackSafeStackAlloc() : data(MallocT<T>(length)) {}
+	/** And freeing when it goes out of scope */
+	~SmallStackSafeStackAlloc() { free(data); }
+#endif
+
+	/**
+	 * Gets a pointer to the data stored in this wrapper.
+	 * @return the pointer.
+	 */
+	operator T* () { return data; }
+};
+
 #endif /* ALLOC_FUNC_HPP */
--- a/src/misc.cpp	Tue Jan 22 08:47:30 2008 +0000
+++ b/src/misc.cpp	Tue Jan 22 12:09:12 2008 +0000
@@ -25,6 +25,7 @@
 #include "texteff.hpp"
 #include "string_func.h"
 #include "gfx_func.h"
+#include "core/alloc_func.hpp"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -260,196 +261,161 @@
 	AllocateMap(_map_dim_x, _map_dim_y);
 }
 
+enum {
+	MAP_SL_BUF_SIZE = 4096
+};
+
 static void Load_MAPT()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf), SLE_UINT8);
-		for (j = 0; j != lengthof(buf); j++) _m[i++].type_height = buf[j];
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].type_height = buf[j];
 	}
 }
 
 static void Save_MAPT()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].type_height;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].type_height;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
 
 static void Load_MAP1()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf), SLE_UINT8);
-		for (j = 0; j != lengthof(buf); j++) _m[i++].m1 = buf[j];
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m1 = buf[j];
 	}
 }
 
 static void Save_MAP1()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m1;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m1;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
 
 static void Load_MAP2()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		uint16 buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf),
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE,
 			/* In those versions the m2 was 8 bits */
 			CheckSavegameVersion(5) ? SLE_FILE_U8 | SLE_VAR_U16 : SLE_UINT16
 		);
-		for (j = 0; j != lengthof(buf); j++) _m[i++].m2 = buf[j];
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m2 = buf[j];
 	}
 }
 
 static void Save_MAP2()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<uint16, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	SlSetLength(size * sizeof(_m[0].m2));
-	for (i = 0; i != size;) {
-		uint16 buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m2;
-		SlArray(buf, lengthof(buf), SLE_UINT16);
+	SlSetLength(size * sizeof(uint16));
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m2;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT16);
 	}
 }
 
 static void Load_MAP3()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf), SLE_UINT8);
-		for (j = 0; j != lengthof(buf); j++) _m[i++].m3 = buf[j];
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m3 = buf[j];
 	}
 }
 
 static void Save_MAP3()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m3;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m3;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
 
 static void Load_MAP4()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf), SLE_UINT8);
-		for (j = 0; j != lengthof(buf); j++) _m[i++].m4 = buf[j];
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m4 = buf[j];
 	}
 }
 
 static void Save_MAP4()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m4;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m4;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
 
 static void Load_MAP5()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf), SLE_UINT8);
-		for (j = 0; j != lengthof(buf); j++) _m[i++].m5 = buf[j];
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m5 = buf[j];
 	}
 }
 
 static void Save_MAP5()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		byte buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m5;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m5;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
 
 static void Load_MAP6()
 {
-	/* Still available for loading old games */
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	if (CheckSavegameVersion(42)) {
-		for (i = 0; i != size;) {
-			uint8 buf[1024];
-			uint j;
-
-			SlArray(buf, lengthof(buf), SLE_UINT8);
-			for (j = 0; j != lengthof(buf); j++) {
+		for (TileIndex i = 0; i != size;) {
+			/* 1024, otherwise we overflow on 64x64 maps! */
+			SlArray(buf, 1024, SLE_UINT8);
+			for (uint j = 0; j != 1024; j++) {
 				_m[i++].m6 = GB(buf[j], 0, 2);
 				_m[i++].m6 = GB(buf[j], 2, 2);
 				_m[i++].m6 = GB(buf[j], 4, 2);
@@ -457,57 +423,45 @@
 			}
 		}
 	} else {
-		for (i = 0; i != size;) {
-			byte buf[4096];
-			uint j;
-
-			SlArray(buf, lengthof(buf), SLE_UINT8);
-			for (j = 0; j != lengthof(buf); j++) _m[i++].m6 = buf[j];
+		for (TileIndex i = 0; i != size;) {
+			SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+			for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _m[i++].m6 = buf[j];
 		}
 	}
 }
 
 static void Save_MAP6()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		uint8 buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m6;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _m[i++].m6;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }
 
 static void Load_MAP7()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
-	for (i = 0; i != size;) {
-		uint8 buf[4096];
-		uint j;
-
-		SlArray(buf, lengthof(buf), SLE_UINT8);
-		for (j = 0; j != lengthof(buf); j++) _me[i++].m7 = buf[j];
+	for (TileIndex i = 0; i != size;) {
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) _me[i++].m7 = buf[j];
 	}
 }
 
 static void Save_MAP7()
 {
-	uint size = MapSize();
-	uint i;
+	SmallStackSafeStackAlloc<byte, MAP_SL_BUF_SIZE> buf;
+	TileIndex size = MapSize();
 
 	SlSetLength(size);
-	for (i = 0; i != size;) {
-		uint8 buf[4096];
-		uint j;
-
-		for (j = 0; j != lengthof(buf); j++) buf[j] = _me[i++].m7;
-		SlArray(buf, lengthof(buf), SLE_UINT8);
+	for (TileIndex i = 0; i != size;) {
+		for (uint j = 0; j != MAP_SL_BUF_SIZE; j++) buf[j] = _me[i++].m7;
+		SlArray(buf, MAP_SL_BUF_SIZE, SLE_UINT8);
 	}
 }