(svn r10800) [NewGRF_ports] -Add: saving of FSMblockmaps. NewGRF_ports
authorrubidium
Sun, 05 Aug 2007 23:06:58 +0000
branchNewGRF_ports
changeset 6758 1545d187ab64
parent 6757 60662379acb5
child 6759 8801d6105885
(svn r10800) [NewGRF_ports] -Add: saving of FSMblockmaps.
src/fsmblockmap.cpp
src/fsmblockmap.h
src/saveload.h
src/station_cmd.cpp
src/vehicle.cpp
--- a/src/fsmblockmap.cpp	Sun Aug 05 17:30:37 2007 +0000
+++ b/src/fsmblockmap.cpp	Sun Aug 05 23:06:58 2007 +0000
@@ -15,6 +15,12 @@
 
 void FSMblockmap::PrintBlock(bool newline) const
 {
-	printf("%016" OTTD_PRINTF64 "x%016" OTTD_PRINTF64 "x", this->block_upper, this->block_lower);
+	printf("%016" OTTD_PRINTF64 "x%016" OTTD_PRINTF64 "x", this->GetUpper(), this->GetLower());
 	if (newline) printf("\n");
 }
+
+/* static */ void FSMblockmap::AssertOnWrongBlockOffset()
+{
+	FSMblockmap fsmb;
+	if ((void*)&fsmb != (void*)fsmb.blocks) NOT_REACHED();
+}
--- a/src/fsmblockmap.h	Sun Aug 05 17:30:37 2007 +0000
+++ b/src/fsmblockmap.h	Sun Aug 05 23:06:58 2007 +0000
@@ -20,96 +20,106 @@
  *
 */
 struct FSMblockmap {
-	public:
-		void inline ResetAll()
-		{
-			block_lower = 0x0000000000000000;
-			block_upper = 0x0000000000000000;
-		};
-
-		void Initialise(const byte *blocklist, int num_bytes)
-		{
-			ResetAll();
-			for (int i = 0; i < num_bytes; i++)
-			{
-				if (blocklist[i] < 64) {
-					block_lower |= GetBlockAsBits(blocklist[i]);
-				} else {
-					block_upper |= GetBlockAsBits(blocklist[i]);
-				}
-			}
-		}
-
-		uint64 inline GetLower() const
-		{
-			return block_lower;
-		}
-
-		uint64 inline GetUpper() const
-		{
-			return block_upper;
-		}
-
-		void inline ReserveBlocks(const FSMblockmap *blockmap)
-		{
-			/* OR with blockmap to reserve blocks */
-			block_lower |= blockmap->GetLower();
-			block_upper |= blockmap->GetUpper();
-		}
-
-		void inline ReleaseBlocks(const FSMblockmap *blockmap)
-		{
-			/* AND with ones-complement to clear set bits in blockmap from block_lower and block_upper */
-			block_lower &= ~blockmap->GetLower();
-			block_upper &= ~blockmap->GetUpper();
-		}
+public:
+	void inline ResetAll()
+	{
+		blocks[0] = 0x0000000000000000;
+		blocks[1] = 0x0000000000000000;
+	};
 
-		bool inline BlocksAreFree(const FSMblockmap *blockmap) const
-		{
-			uint64 test_lower = blockmap->GetLower();
-			uint64 test_upper = blockmap->GetUpper();
-
-			if ((~block_lower & test_lower) != test_lower)  return false;
-			if ((~block_upper & test_upper) != test_upper)  return false;
-
-			return true;
+	void Initialise(const byte *blocklist, int num_bytes)
+	{
+		ResetAll();
+		for (int i = 0; i < num_bytes; i++) {
+			blocks[(blocklist[i] < 64) ? 0 : 1] |= GetBlockAsBits(blocklist[i]);
 		}
-
-		bool inline HasBlocks(const FSMblockmap *blockmap) const
-		{
-			uint64 test_lower = blockmap->GetLower();
-			uint64 test_upper = blockmap->GetUpper();
-
-			if ((block_lower & test_lower) != test_lower)  return false;
-			if ((block_upper & test_upper) != test_upper)  return false;
-
-			return true;
-		}
+	}
 
-		bool inline HasBlock(byte blocknumber) const
-		{
-			FSMblockmap test_blockmap;
-			test_blockmap.Initialise(&blocknumber, 1);
-			return HasBlocks(&test_blockmap);
-		}
+	uint64 inline GetLower() const
+	{
+		return blocks[0];
+	}
 
-		//bool inline HasBlock(byte blocknumber)
-		//{
-		//	uint64 test_block = GetBlockAsBits(blocknumber);
-		//	if (blocknumber < 64) return ((block_lower & test_block) == test_block);
-		//	return ((block_upper & test_block) == test_block);
-		//}
+	uint64 inline GetUpper() const
+	{
+		return blocks[1];
+	}
 
-		bool inline IsNotZero(void) const
-		{
-			return ((block_lower != 0) || (block_upper != 0));
-		}
+	void inline ReserveBlocks(const FSMblockmap *blockmap)
+	{
+		/* OR with blockmap to reserve blocks */
+		blocks[0] |= blockmap->GetLower();
+		blocks[1] |= blockmap->GetUpper();
+	}
 
-		void PrintBlock(bool newline = true) const;
+	void inline ReleaseBlocks(const FSMblockmap *blockmap)
+	{
+		/* AND with ones-complement to clear set bits in blockmap from block_lower and block_upper */
+		blocks[0] &= ~blockmap->GetLower();
+		blocks[1] &= ~blockmap->GetUpper();
+	}
 
-	private:
-		uint64 block_lower;
-		uint64 block_upper;
+	bool inline BlocksAreFree(const FSMblockmap *blockmap) const
+	{
+		uint64 test_lower = blockmap->GetLower();
+		uint64 test_upper = blockmap->GetUpper();
+
+		if ((~blocks[0] & test_lower) != test_lower)  return false;
+		if ((~blocks[1] & test_upper) != test_upper)  return false;
+
+		return true;
+	}
+
+	bool inline HasBlocks(const FSMblockmap *blockmap) const
+	{
+		uint64 test_lower = blockmap->GetLower();
+		uint64 test_upper = blockmap->GetUpper();
+
+		if ((blocks[0] & test_lower) != test_lower)  return false;
+		if ((blocks[1] & test_upper) != test_upper)  return false;
+
+		return true;
+	}
+
+	bool inline HasBlock(byte blocknumber) const
+	{
+		FSMblockmap test_blockmap;
+		test_blockmap.Initialise(&blocknumber, 1);
+		return HasBlocks(&test_blockmap);
+	}
+
+	//bool inline HasBlock(byte blocknumber)
+	//{
+	//	uint64 test_block = GetBlockAsBits(blocknumber);
+	//	if (blocknumber < 64) return ((block_lower & test_block) == test_block);
+	//	return ((block_upper & test_block) == test_block);
+	//}
+
+	bool inline IsNotZero(void) const
+	{
+		return ((blocks[0] != 0) || (blocks[1] != 0));
+	}
+
+	void PrintBlock(bool newline = true) const;
+
+	/**
+	 * Needed for an ugly hack:
+	 *  - vehicles and stations need to store fsmblocks, so they use FSMBlock as container
+	 *  - this internals of the container should be protected, e.g. private (or protected) by C++
+	 *  - for saving/loading we need to pass pointer to objects
+	 *  -> so *if* the pointer to the FSMBlock is the same as the pointer to the blocks array
+	 *     encapsulated in the FSMBlock, we can just pass the FSMBlock as "offset".
+	 *     Normally we would then just add the offset of the blocks variable within the class
+	 *     but that is not possible because the variable is private. Furthermore we are not sure
+	 *     that this works on all platforms, we need to check whether the offset is actually 0.
+	 *     This cannot be done compile time, because the variable is private. So we need to write
+	 *     a function that does actually check the offset runtime and call it somewhere where it
+	 *     is always called but it should not be called often.
+	 */
+	static void AssertOnWrongBlockOffset();
+
+private:
+	uint64 blocks[2];
 };
 
 FSMblockmap* SetFSMSingleBlock(const byte *blocklist);
--- a/src/saveload.h	Sun Aug 05 17:30:37 2007 +0000
+++ b/src/saveload.h	Sun Aug 05 23:06:58 2007 +0000
@@ -213,15 +213,16 @@
 #define SLE_INCLUDE(base, variable, include_index) SLE_GENERAL(SL_INCLUDE, base, variable, 0, 0, include_index, 0)
 
 /* The same as the ones at the top, only the offset is given directly; used for unions */
-#define SLE_GENERALX(cmd, offset, type, param1, param2) {false, cmd, type, 0, param1, param2, (void*)(offset)}
-#define SLE_CONDVARX(offset, type, from, to) SLE_GENERALX(SL_VAR, offset, type, from, to)
-#define SLE_CONDREFX(offset, type, from, to) SLE_GENERALX(SL_REF, offset, type, from, to)
+#define SLE_GENERALX(cmd, offset, type, len, param1, param2) {false, cmd, type, len, param1, param2, (void*)(offset)}
+#define SLE_CONDVARX(offset, type, from, to) SLE_GENERALX(SL_VAR, offset, type, 0, from, to)
+#define SLE_CONDREFX(offset, type, from, to) SLE_GENERALX(SL_REF, offset, type, 0, from, to)
+#define SLE_CONDARRX(offset, type, length, from, to) SLE_GENERALX(SL_ARR, offset, type, length, from, to)
 
 #define SLE_VARX(offset, type) SLE_CONDVARX(offset, type, 0, SL_MAX_VERSION)
 #define SLE_REFX(offset, type) SLE_CONDREFX(offset, type, 0, SL_MAX_VERSION)
 
-#define SLE_WRITEBYTEX(offset, something) SLE_GENERALX(SL_WRITEBYTE, offset, 0, something, 0)
-#define SLE_INCLUDEX(offset, type) SLE_GENERALX(SL_INCLUDE, offset, type, 0, SL_MAX_VERSION)
+#define SLE_WRITEBYTEX(offset, something) SLE_GENERALX(SL_WRITEBYTE, offset, 0, 0, something, 0)
+#define SLE_INCLUDEX(offset, type) SLE_GENERALX(SL_INCLUDE, offset, type, 0, 0, SL_MAX_VERSION)
 
 /* End marker */
 #define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL}
--- a/src/station_cmd.cpp	Sun Aug 05 17:30:37 2007 +0000
+++ b/src/station_cmd.cpp	Sun Aug 05 23:06:58 2007 +0000
@@ -2917,6 +2917,8 @@
 
 	_station_tick_ctr = 0;
 
+	/* Check whether our &fsmblocks == &fsmblocks.blocks "hack" works */
+	FSMblockmap::AssertOnWrongBlockOffset();
 }
 
 
@@ -3008,7 +3010,8 @@
 
 	SLE_CONDVAR(Station, airport_flags,              SLE_VAR_U64 | SLE_FILE_U16,  0,  2),
 	SLE_CONDVAR(Station, airport_flags,              SLE_VAR_U64 | SLE_FILE_U32,  3, 45),
-	SLE_CONDVAR(Station, airport_flags,              SLE_UINT64,                 46, SL_MAX_VERSION),
+	SLE_CONDVAR(Station, airport_flags,              SLE_UINT64,                 46, 72),
+	SLE_CONDARR(Station, airport_flags,              SLE_UINT64, 2,              73, SL_MAX_VERSION),
 
 	SLE_CONDNULL(2, 0, 25), /* Ex last-vehicle */
 	SLE_CONDVAR(Station, last_vehicle_type,          SLE_UINT8,                  26, SL_MAX_VERSION),
--- a/src/vehicle.cpp	Sun Aug 05 17:30:37 2007 +0000
+++ b/src/vehicle.cpp	Sun Aug 05 23:06:58 2007 +0000
@@ -3018,6 +3018,8 @@
 
 	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, previous_pos),    SLE_UINT8,                 2, SL_MAX_VERSION),
 
+	SLE_CONDARRX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, owned_blocks),    SLE_UINT64, 2,            73, SL_MAX_VERSION),
+
 	/* reserve extra space in savegame here. (currently 15 bytes) */
 	SLE_CONDNULL(15,                                                                                      2, SL_MAX_VERSION),