diff --git a/docs/landscape.html b/docs/landscape.html
index 7908582461..43ef7e8cea 100644
--- a/docs/landscape.html
+++ b/docs/landscape.html
@@ -1620,7 +1620,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 6019651f3b..75167ef076 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 4614fe00ec..0aaf661cb4 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -60,6 +60,7 @@
#include "../disaster_vehicle.h"
#include "../tracerestrict.h"
#include "../tunnel_map.h"
+#include "../bridge_signal_map.h"
#include "saveload_internal.h"
@@ -3375,6 +3376,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);
+ }
+ }
+ }
if (SlXvIsFeatureMissing(XSLFI_CUSTOM_BRIDGE_HEADS)) {
/* ensure that previously unused custom bridge-head bits are cleared */
diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp
index 4ee13e9457..4608337144 100644
--- a/src/saveload/extended_ver_sl.cpp
+++ b/src/saveload/extended_ver_sl.cpp
@@ -56,7 +56,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", NULL, NULL, NULL },
{ XSLFI_TIMETABLES_START_TICKS, XSCF_NULL, 2, 2, "timetable_start_ticks", NULL, NULL, NULL },
{ XSLFI_TOWN_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 2, 2, "town_cargo_adj", NULL, NULL, NULL },
- { 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" },
{ XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 6, 6, "improved_breakdowns", NULL, NULL, NULL },
{ XSLFI_TT_WAIT_IN_DEPOT, XSCF_NULL, 1, 1, "tt_wait_in_depot", NULL, NULL, NULL },
{ XSLFI_AUTO_TIMETABLE, XSCF_NULL, 4, 4, "auto_timetables", NULL, NULL, NULL },