# HG changeset patch # User rubidium # Date 1186355218 0 # Node ID 1545d187ab6429919e975ac857a60f2544e2f571 # Parent 60662379acb575b2865cf69b119d698bc7f7c3ba (svn r10800) [NewGRF_ports] -Add: saving of FSMblockmaps. diff -r 60662379acb5 -r 1545d187ab64 src/fsmblockmap.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(); +} diff -r 60662379acb5 -r 1545d187ab64 src/fsmblockmap.h --- 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); diff -r 60662379acb5 -r 1545d187ab64 src/saveload.h --- 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} diff -r 60662379acb5 -r 1545d187ab64 src/station_cmd.cpp --- 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), diff -r 60662379acb5 -r 1545d187ab64 src/vehicle.cpp --- 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),