(svn r13549) [NewGRF_ports] -Change: Make recolouring of groundtile (0x0f80) specific to NewGRF_ports only.
Also base groundsprite on airport_tile of station. This prevents mixed colour groundtiles in an airport.
/* $Id$ */
/** @file FSMblockmap.h Definition of FSMblockmap class for use in state machines*/
#ifndef FSMBLOCKMAP_H
#define FSMBLOCKMAP_H
#include "stdafx.h"
uint64 inline GetBlockAsBits(byte blocknumber)
{
if (blocknumber == 0) return 0ULL;
if (blocknumber > 63) blocknumber -= 64;
uint64 result = 1ULL << blocknumber;
return result;
}
/**
* This class provides functions and internal storage for blockmaps used in Finite State Machine
*
*/
struct FSMblockmap {
public:
void inline ResetAll()
{
blocks[0] = 0x0000000000000000ULL;
blocks[1] = 0x0000000000000000ULL;
};
void inline SetAll()
{
blocks[0] = 0xFFFFFFFFFFFFFFFFULL;
blocks[1] = 0xFFFFFFFFFFFFFFFFULL;
};
void Initialise(const byte *blocklist, int num_bytes)
{
ResetAll();
for (int i = 0; i < num_bytes; i++) {
if (blocklist[i] == 0xFF) {
SetAll();
break;
}
blocks[(blocklist[i] < 64) ? 0 : 1] |= GetBlockAsBits(blocklist[i]);
}
}
uint64 inline GetLower() const
{
return blocks[0];
}
uint64 inline GetUpper() const
{
return blocks[1];
}
void inline BlockCopy(const FSMblockmap *blockmap)
{
blocks[0] = blockmap->GetLower();
blocks[1] = blockmap->GetUpper();
}
void inline ReserveBlocks(const FSMblockmap *blockmap)
{
/* OR with blockmap to reserve blocks */
blocks[0] |= blockmap->GetLower();
blocks[1] |= blockmap->GetUpper();
}
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();
}
void inline ReleaseOnlyOwnedBlocks(const FSMblockmap *blockmap, const FSMblockmap *owned_blockmap)
{
/* AND with ones-complement to clear set bits in blockmap from block_lower and block_upper */
blocks[0] &= ~(blockmap->GetLower() & owned_blockmap->GetLower());
blocks[1] &= ~(blockmap->GetUpper() & owned_blockmap->GetUpper());
}
void inline ReleaseLowerBlocks(const FSMblockmap *blockmap)
{
/* used to forget any existing terminal reservations */
blocks[0] &= ~blockmap->GetLower();
}
void inline ReleaseUpperBlocks(const FSMblockmap *blockmap)
{
/* used to forget any normal movemnt reservations */
blocks[1] &= ~blockmap->GetUpper();
}
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 CanReserveBlocks(const FSMblockmap *wantedblockmap, const FSMblockmap *targetblockmap) const
{
/* HasBlocks is a strict "have I got all the blocks? Yes/No". While useful in places
* sometimes you want to ask "ive got some blocks. can I get the rest?"
* This function does that.
* The first assignment calculates which bits you need, but dont already have.
* Then it tests whether the remaining bits are free in targetblockmap.
* If they are, then return true.
*/
uint64 test_lower = (blocks[0] ^ wantedblockmap->GetLower()) & wantedblockmap->GetLower();
uint64 test_upper = (blocks[1] ^ wantedblockmap->GetUpper()) & wantedblockmap->GetUpper();
if ((~targetblockmap->GetLower() & test_lower) != test_lower) return false;
if ((~targetblockmap->GetUpper() & 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);
#endif /* FSMBLOCKMAP_H */