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" },
};
/**