diff --git a/docs/landscape.html b/docs/landscape.html index ededf0a3f0..b0501596a3 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -1567,7 +1567,7 @@
  • m6 bit 1: set = semaphore signals, clear = light signals
  • m6 bit 0: set = entrance signal shows green, clear = entrance signal shows red
  • m2 bit 15: for bridge entrances only: storage for visual red/green state of signals starting from 15 is allocated outside the map array
  • -
  • m2 bits 14..0: for bridge entrances only: for signals 0..14 on bridge, signal is visually red if corresponding bit in 0..14 is set
  • +
  • m2 bits 14..4: for bridge entrances only: for signals 0..10 on bridge, signal is visually red if corresponding bit in 4..14 is set
  • m5 bits 3..2: transport type diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index 91a3a246f6..3e0bff6b39 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -345,7 +345,7 @@ the array so you can quickly see what is used and what is not. -inherit- -inherit- -inherit- - PPPP PPPP PPPP PPPP + PPPP PPPP PPPP OOOO -inherit- -inherit- -inherit- diff --git a/src/bridge_map.cpp b/src/bridge_map.cpp index 7d155fed64..b59687629b 100644 --- a/src/bridge_map.cpp +++ b/src/bridge_map.cpp @@ -88,7 +88,7 @@ SignalState GetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 si const auto it = _long_bridge_signal_sim_map.find(t); if (it != _long_bridge_signal_sim_map.end()) { const LongBridgeSignalStorage &lbss = it->second; - uint16 offset = signal - 15; + uint16 offset = signal - BRIDGE_M2_SIGNAL_STATE_COUNT; uint16 slot = offset >> 6; uint16 bit = offset & 0x3F; if (slot >= lbss.signal_red_bits.size()) return SIGNAL_STATE_GREEN; @@ -101,32 +101,65 @@ SignalState GetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 si void SetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal, SignalState state) { LongBridgeSignalStorage &lbss = _long_bridge_signal_sim_map[t]; - uint16 offset = signal - 15; + uint16 offset = signal - BRIDGE_M2_SIGNAL_STATE_COUNT; uint16 slot = offset >> 6; uint16 bit = offset & 0x3F; if (slot >= lbss.signal_red_bits.size()) lbss.signal_red_bits.resize(slot + 1); SB(lbss.signal_red_bits[slot], bit, 1, (uint64) ((state == SIGNAL_STATE_RED) ? 1 : 0)); - _m[t].m2 |= 0x8000; + _m[t].m2 |= BRIDGE_M2_SIGNAL_STATE_EXT_FLAG; } void SetAllBridgeEntranceSimulatedSignalsGreenExtended(TileIndex t) { + SB(_m[t].m2, BRIDGE_M2_SIGNAL_STATE_OFFSET, BRIDGE_M2_SIGNAL_STATE_FIELD_SIZE, 0); auto it = _long_bridge_signal_sim_map.find(t); if (it != _long_bridge_signal_sim_map.end()) { LongBridgeSignalStorage &lbss = it->second; for (auto &it : lbss.signal_red_bits) { it = 0; } - _m[t].m2 = 0x8000; - } else { - _m[t].m2 = 0; + _m[t].m2 |= BRIDGE_M2_SIGNAL_STATE_EXT_FLAG; } } void ClearBridgeEntranceSimulatedSignalsExtended(TileIndex t) { _long_bridge_signal_sim_map.erase(t); - _m[t].m2 = 0; + SB(_m[t].m2, BRIDGE_M2_SIGNAL_STATE_OFFSET, BRIDGE_M2_SIGNAL_STATE_FIELD_SIZE, 0); +} + +void ShiftBridgeEntranceSimulatedSignalsExtended(TileIndex t, int shift, uint64 in) +{ + if (shift > 0) { + /* shift into array */ + LongBridgeSignalStorage *lbss = nullptr; + auto it = _long_bridge_signal_sim_map.find(t); + if (it != _long_bridge_signal_sim_map.end()) { + lbss = &(it->second); + } else if (in) { + lbss = &(_long_bridge_signal_sim_map[t]); + } else { + return; + } + const size_t orig_size = lbss->signal_red_bits.size(); + size_t i = orig_size; + auto insert_bits = [&](uint64 bits, size_t pos) { + if (bits) { + if (pos >= lbss->signal_red_bits.size()) lbss->signal_red_bits.resize(pos); + lbss->signal_red_bits[pos] |= bits; + } + }; + while (i) { + i--; + uint64 out = GB(lbss->signal_red_bits[i], 64 - shift, shift); + lbss->signal_red_bits[i] <<= shift; + insert_bits(out, i + 1); + } + insert_bits(in, 0); + } else if (shift < 0) { + /* not implemented yet */ + NOT_REACHED(); + } } void ClearBridgeSimulatedSignalMapping() diff --git a/src/bridge_signal_map.h b/src/bridge_signal_map.h index 3ab234cbe3..164bcec6ad 100644 --- a/src/bridge_signal_map.h +++ b/src/bridge_signal_map.h @@ -28,10 +28,17 @@ extern std::unordered_map _long_bridge_signa SignalState GetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal); +enum { + BRIDGE_M2_SIGNAL_STATE_COUNT = 11, + BRIDGE_M2_SIGNAL_STATE_FIELD_SIZE = 12, + BRIDGE_M2_SIGNAL_STATE_OFFSET = 4, + BRIDGE_M2_SIGNAL_STATE_EXT_FLAG = 0x8000, +}; + static inline SignalState GetBridgeEntranceSimulatedSignalState(TileIndex t, uint16 signal) { - if (signal < 15) { - return GB(_m[t].m2, signal, 1) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; + if (signal < BRIDGE_M2_SIGNAL_STATE_COUNT) { + return GB(_m[t].m2, signal + BRIDGE_M2_SIGNAL_STATE_OFFSET, 1) ? SIGNAL_STATE_RED : SIGNAL_STATE_GREEN; } else { return GetBridgeEntranceSimulatedSignalStateExtended(t, signal); } @@ -41,8 +48,8 @@ void SetBridgeEntranceSimulatedSignalStateExtended(TileIndex t, uint16 signal, S static inline void SetBridgeEntranceSimulatedSignalState(TileIndex t, uint16 signal, SignalState state) { - if (signal < 15) { - SB(_m[t].m2, signal, 1, (state == SIGNAL_STATE_RED) ? 1 : 0); + if (signal < BRIDGE_M2_SIGNAL_STATE_COUNT) { + SB(_m[t].m2, signal + BRIDGE_M2_SIGNAL_STATE_OFFSET, 1, (state == SIGNAL_STATE_RED) ? 1 : 0); } else { SetBridgeEntranceSimulatedSignalStateExtended(t, signal, state); } @@ -52,10 +59,10 @@ void SetAllBridgeEntranceSimulatedSignalsGreenExtended(TileIndex t); static inline void SetAllBridgeEntranceSimulatedSignalsGreen(TileIndex t) { - if (_m[t].m2 & 0x8000) { + if (_m[t].m2 & BRIDGE_M2_SIGNAL_STATE_EXT_FLAG) { SetAllBridgeEntranceSimulatedSignalsGreenExtended(t); } else { - _m[t].m2 = 0; + SB(_m[t].m2, BRIDGE_M2_SIGNAL_STATE_OFFSET, BRIDGE_M2_SIGNAL_STATE_FIELD_SIZE, 0); } } @@ -63,10 +70,10 @@ void ClearBridgeEntranceSimulatedSignalsExtended(TileIndex t); static inline void ClearBridgeEntranceSimulatedSignals(TileIndex t) { - if (_m[t].m2 & 0x8000) { + if (_m[t].m2 & BRIDGE_M2_SIGNAL_STATE_EXT_FLAG) { ClearBridgeEntranceSimulatedSignalsExtended(t); } else { - _m[t].m2 = 0; + SB(_m[t].m2, BRIDGE_M2_SIGNAL_STATE_OFFSET, BRIDGE_M2_SIGNAL_STATE_FIELD_SIZE, 0); } } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 95fc762047..bba09730d8 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -55,6 +55,7 @@ #include "../order_backup.h" #include "../error.h" #include "../disaster_vehicle.h" +#include "../bridge_signal_map.h" #include "saveload_internal.h" @@ -3013,6 +3014,17 @@ bool AfterLoadGame() } } } + if (SlXvIsFeaturePresent(XSLFI_SIG_TUNNEL_BRIDGE, 1, 6)) { + /* m2 signal state bit allocation has shrunk */ + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsBridge(t) && IsTunnelBridgeSignalSimulationEntrance(t)) { + extern void ShiftBridgeEntranceSimulatedSignalsExtended(TileIndex t, int shift, uint64 in); + const uint shift = 15 - BRIDGE_M2_SIGNAL_STATE_COUNT; + ShiftBridgeEntranceSimulatedSignalsExtended(t, shift, GB(_m[t].m2, BRIDGE_M2_SIGNAL_STATE_COUNT, shift)); + SB(_m[t].m2, 0, 15, GB(_m[t].m2, 0, 15) << shift); + } + } + } /* Station acceptance is some kind of cache */ if (IsSavegameVersionBefore(127)) { diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index d42b7b8b21..2ec676e889 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,7 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 6, 6, "signal_tunnel_bridge", NULL, NULL, "XBSS" }, + { XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 7, 7, "signal_tunnel_bridge", NULL, NULL, "XBSS" }, }; /**