(svn r10800) [NewGRF_ports] -Add: saving of FSMblockmaps.
--- 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),