(svn r10006) -Fix (FS#362): allow different signal types on one tile
authorglx
Thu, 31 May 2007 21:21:04 +0000
changeset 7266 4b75e7b9fa91
parent 7265 74148c363f9d
child 7267 f49300df3842
(svn r10006) -Fix (FS#362): allow different signal types on one tile
docs/landscape.html
docs/landscape_grid.html
src/lang/english.txt
src/npf.cpp
src/openttd.cpp
src/rail_cmd.cpp
src/rail_map.h
src/saveload.cpp
src/yapf/yapf_costrail.hpp
--- a/docs/landscape.html	Thu May 31 19:13:41 2007 +0000
+++ b/docs/landscape.html	Thu May 31 21:21:04 2007 +0000
@@ -355,9 +355,9 @@
     </li>
     <li>m5 bit 6 set = with signals:
      <ul>
-      <li>m2 bits 7..4: bit clear = signal shows red; same bits as in m3</li>
-      <li>m2 bit 2: set = semaphore signals, clear = light signals </li>
-      <li>m2 bits 1..0 : type of signal
+      <li>m4 bits 7..4: bit clear = signal shows red; same bits as in m3</li>
+      <li>m2 bit 2 <i>(6)</i>: set = semaphore signals, clear = light signals <i>(lower and right tracks)</i></li>
+      <li>m2 bits 1..0 <i>(5..4)</i>: type of signal <i>(lower and right tracks)</i>
        <table>
          <tr>
           <td nowrap="nowrap" valign="top"><tt>00</tt>: </td>
--- a/docs/landscape_grid.html	Thu May 31 19:13:41 2007 +0000
+++ b/docs/landscape_grid.html	Thu May 31 21:21:04 2007 +0000
@@ -88,9 +88,9 @@
       <td class="caption">rail</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
+      <td class="bits"><span class="free">OOOO OOOO O</span>XXX <span class="free">O</span>XXX</td>
       <td class="bits">XXXX XXXX</td>
-      <td class="bits"><span class="free">OOOO O</span>XXX</td>
+      <td class="bits">XXXX XXXX</td>
       <td class="bits">XXXX XXXX</td>
       <td class="bits">XX<span class="free">OO OO</span>XX</td>
       <td class="bits"><span class="free">OOOO OOOO</span></td>
--- a/src/lang/english.txt	Thu May 31 19:13:41 2007 +0000
+++ b/src/lang/english.txt	Thu May 31 21:21:04 2007 +0000
@@ -1590,6 +1590,12 @@
 STR_RAILROAD_TRACK_WITH_PRESIGNALS                              :Railway track with pre-signals
 STR_RAILROAD_TRACK_WITH_EXITSIGNALS                             :Railway track with exit-signals
 STR_RAILROAD_TRACK_WITH_COMBOSIGNALS                            :Railway track with combo-signals
+STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS                       :Railway track with normal and pre-signals
+STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS                      :Railway track with normal and exit-signals
+STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS                     :Railway track with normal and combo-signals
+STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS                         :Railway track with pre- and exit-signals
+STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS                        :Railway track with pre- and combo-signals
+STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS                       :Railway track with exit- and combo-signals
 STR_MUST_REMOVE_RAILWAY_STATION_FIRST                           :{WHITE}Must remove railway station first
 
 
--- a/src/npf.cpp	Thu May 31 19:13:41 2007 +0000
+++ b/src/npf.cpp	Thu May 31 21:21:04 2007 +0000
@@ -357,7 +357,7 @@
 				 * encounter, if it is red */
 
 				/* Is this a presignal exit or combo? */
-				SignalType sigtype = GetSignalType(tile);
+				SignalType sigtype = GetSignalType(tile, TrackdirToTrack(trackdir));
 				if (sigtype == SIGTYPE_EXIT || sigtype == SIGTYPE_COMBO) {
 					/* Penalise exit and combo signals differently (heavier) */
 					cost += _patches.npf_rail_firstred_exit_penalty;
--- a/src/openttd.cpp	Thu May 31 19:13:41 2007 +0000
+++ b/src/openttd.cpp	Thu May 31 21:21:04 2007 +0000
@@ -1664,10 +1664,10 @@
 				case MP_RAILWAY:
 					if (HasSignals(t)) {
 						/* convert PBS signals to combo-signals */
-						if (HASBIT(_m[t].m2, 2)) SetSignalType(t, SIGTYPE_COMBO);
+						if (HASBIT(_m[t].m2, 2)) SetSignalType(t, TRACK_X, SIGTYPE_COMBO);
 
 						/* move the signal variant back */
-						SetSignalVariant(t, HASBIT(_m[t].m2, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
+						SetSignalVariant(t, TRACK_X, HASBIT(_m[t].m2, 3) ? SIG_SEMAPHORE : SIG_ELECTRIC);
 						CLRBIT(_m[t].m2, 3);
 					}
 
@@ -2001,6 +2001,18 @@
 		_opt.diff.number_towns++;
 	}
 
+	if (CheckSavegameVersion(64)) {
+		/* copy the signal type/variant and move signal states bits */
+		for (TileIndex t = 0; t < map_size; t++) {
+			if (IsTileType(t, MP_RAILWAY) && HasSignals(t)) {
+				SetSignalStates(t, GB(_m[t].m2, 4, 4));
+				SetSignalVariant(t, INVALID_TRACK, GetSignalVariant(t, TRACK_X));
+				SetSignalType(t, INVALID_TRACK, GetSignalType(t, TRACK_X));
+				CLRBIT(_m[t].m2, 7);
+			}
+		}
+	}
+
 	/* Recalculate */
 	Group *g;
 	FOR_ALL_GROUPS(g) {
--- a/src/rail_cmd.cpp	Thu May 31 19:13:41 2007 +0000
+++ b/src/rail_cmd.cpp	Thu May 31 21:21:04 2007 +0000
@@ -692,7 +692,7 @@
 		/* build new signals */
 		cost = _price.build_signals;
 	} else {
-		if (p2 != 0 && sigvar != GetSignalVariant(tile)) {
+		if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) {
 			/* convert signals <-> semaphores */
 			cost = _price.build_signals + _price.remove_signals;
 		} else {
@@ -707,20 +707,22 @@
 			SetHasSignals(tile, true);
 			SetSignalStates(tile, 0xF); // all signals are on
 			SetPresentSignals(tile, 0); // no signals built by default
-			SetSignalType(tile, SIGTYPE_NORMAL);
-			SetSignalVariant(tile, sigvar);
+			SetSignalType(tile, track, SIGTYPE_NORMAL);
+			SetSignalVariant(tile, track, sigvar);
 		}
 
 		if (p2 == 0) {
 			if (!HasSignalOnTrack(tile, track)) {
 				/* build new signals */
 				SetPresentSignals(tile, GetPresentSignals(tile) | SignalOnTrack(track));
+				SetSignalType(tile, track, SIGTYPE_NORMAL);
+				SetSignalVariant(tile, track, sigvar);
 			} else {
 				if (pre_signal) {
 					/* cycle between normal -> pre -> exit -> combo -> ... */
-					SignalType type = GetSignalType(tile);
+					SignalType type = GetSignalType(tile, track);
 
-					SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
+					SetSignalType(tile, track, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
 				} else {
 					CycleSignalSide(tile, track);
 				}
@@ -729,7 +731,7 @@
 			/* If CmdBuildManySignals is called with copying signals, just copy the
 			 * direction of the first signal given as parameter by CmdBuildManySignals */
 			SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | (p2 & SignalOnTrack(track)));
-			SetSignalVariant(tile, sigvar);
+			SetSignalVariant(tile, track, sigvar);
 		}
 
 		MarkTileDirtyByTile(tile);
@@ -787,7 +789,7 @@
 		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
 
 		/* copy signal/semaphores style (independent of CTRL) */
-		semaphores = GetSignalVariant(tile) != SIG_ELECTRIC;
+		semaphores = GetSignalVariant(tile, track) != SIG_ELECTRIC;
 	} else { // no signals exist, drag a two-way signal stretch
 		signals = SignalOnTrack(track);
 	}
@@ -879,7 +881,7 @@
 		if (GetPresentSignals(tile) == 0) {
 			SetSignalStates(tile, 0);
 			SetHasSignals(tile, false);
-			SetSignalVariant(tile, SIG_ELECTRIC); // remove any possible semaphores
+			SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores
 		}
 
 		SetSignalsOnBothDir(tile, track);
@@ -1090,7 +1092,7 @@
 
 #include "table/track_land.h"
 
-static void DrawSingleSignal(TileIndex tile, byte condition, uint image, uint pos)
+static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos)
 {
 	bool side = (_opt.road_side != 0) && _patches.signal_side;
 	static const Point SignalPositions[2][12] = {
@@ -1127,10 +1129,10 @@
 	/* _signal_base is set by our NewGRF Action 5 loader. If it is 0 then we
 	 * just draw the standard signals, else we get the offset from _signal_base
 	 * and draw that sprite. All the signal sprites are loaded sequentially. */
-	if (_signal_base == 0 || (GetSignalType(tile) == 0 && GetSignalVariant(tile) == SIG_ELECTRIC)) {
-		sprite = SignalBase[side][GetSignalVariant(tile)][GetSignalType(tile)] + image + condition;
+	if (_signal_base == 0 || (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC)) {
+		sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition;
 	} else {
-		sprite = _signal_base + (GetSignalType(tile) - 1) * 16 + GetSignalVariant(tile) * 64 + image + condition;
+		sprite = _signal_base + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition;
 	}
 
 	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, 10, GetSlopeZ(x,y));
@@ -1300,33 +1302,33 @@
 
 static void DrawSignals(TileIndex tile, TrackBits rails)
 {
-#define MAYBE_DRAW_SIGNAL(x,y,z) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, GetSingleSignalState(tile, x), y - 0x4FB, z)
+#define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z)
 
 	if (!(rails & TRACK_BIT_Y)) {
 		if (!(rails & TRACK_BIT_X)) {
 			if (rails & TRACK_BIT_LEFT) {
-				MAYBE_DRAW_SIGNAL(2, 0x509, 0);
-				MAYBE_DRAW_SIGNAL(3, 0x507, 1);
+				MAYBE_DRAW_SIGNAL(2, 0x509, 0, TRACK_LEFT);
+				MAYBE_DRAW_SIGNAL(3, 0x507, 1, TRACK_LEFT);
 			}
 			if (rails & TRACK_BIT_RIGHT) {
-				MAYBE_DRAW_SIGNAL(0, 0x509, 2);
-				MAYBE_DRAW_SIGNAL(1, 0x507, 3);
+				MAYBE_DRAW_SIGNAL(0, 0x509, 2, TRACK_RIGHT);
+				MAYBE_DRAW_SIGNAL(1, 0x507, 3, TRACK_RIGHT);
 			}
 			if (rails & TRACK_BIT_UPPER) {
-				MAYBE_DRAW_SIGNAL(3, 0x505, 4);
-				MAYBE_DRAW_SIGNAL(2, 0x503, 5);
+				MAYBE_DRAW_SIGNAL(3, 0x505, 4, TRACK_UPPER);
+				MAYBE_DRAW_SIGNAL(2, 0x503, 5, TRACK_UPPER);
 			}
 			if (rails & TRACK_BIT_LOWER) {
-				MAYBE_DRAW_SIGNAL(1, 0x505, 6);
-				MAYBE_DRAW_SIGNAL(0, 0x503, 7);
+				MAYBE_DRAW_SIGNAL(1, 0x505, 6, TRACK_LOWER);
+				MAYBE_DRAW_SIGNAL(0, 0x503, 7, TRACK_LOWER);
 			}
 		} else {
-			MAYBE_DRAW_SIGNAL(3, 0x4FB, 8);
-			MAYBE_DRAW_SIGNAL(2, 0x4FD, 9);
+			MAYBE_DRAW_SIGNAL(3, 0x4FB, 8, TRACK_X);
+			MAYBE_DRAW_SIGNAL(2, 0x4FD, 9, TRACK_X);
 		}
 	} else {
-		MAYBE_DRAW_SIGNAL(3, 0x4FF, 10);
-		MAYBE_DRAW_SIGNAL(2, 0x501, 11);
+		MAYBE_DRAW_SIGNAL(3, 0x4FF, 10, TRACK_Y);
+		MAYBE_DRAW_SIGNAL(2, 0x501, 11, TRACK_Y);
 	}
 }
 
@@ -1510,11 +1512,12 @@
 static bool SetSignalsEnumProc(TileIndex tile, void* data, Trackdir trackdir, uint length, byte* state)
 {
 	SetSignalsData* ssd = (SetSignalsData*)data;
+	Track track = TrackdirToTrack(trackdir);
 
 	if (!IsTileType(tile, MP_RAILWAY)) return false;
 
 	/* the tile has signals? */
-	if (HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) {
+	if (HasSignalOnTrack(tile, track)) {
 		if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
 			/* yes, add the signal to the list of signals */
 			if (ssd->cur != NUM_SSD_ENTRY) {
@@ -1524,10 +1527,10 @@
 			}
 
 			/* remember if this block has a presignal. */
-			ssd->has_presignal |= IsPresignalEntry(tile);
+			ssd->has_presignal |= IsPresignalEntry(tile, track);
 		}
 
-		if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile)) {
+		if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile, track)) {
 			/* this is an exit signal that points out from the segment */
 			ssd->presignal_exits++;
 			if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED)
@@ -1666,13 +1669,14 @@
 		TileIndex tile = ssd->tile[i];
 		byte bit = SignalAgainstTrackdir(ssd->bit[i]);
 		uint signals = GetSignalStates(tile);
+		Track track = TrackdirToTrack(ssd->bit[i]);
 
 		/* presignals don't turn green if there is at least one presignal exit and none are free */
-		if (IsPresignalEntry(tile)) {
+		if (IsPresignalEntry(tile, track)) {
 			int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free;
 
 			/* subtract for dual combo signals so they don't count themselves */
-			if (IsPresignalExit(tile) && HasSignalOnTrackdir(tile, ssd->bit[i])) {
+			if (IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, ssd->bit[i])) {
 				ex--;
 				if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--;
 			}
@@ -1692,7 +1696,7 @@
 		}
 
 		/* Update signals on the other side of this exit-combo signal; it changed. */
-		if (IsPresignalExit(tile)) {
+		if (IsPresignalExit(tile, track)) {
 			if (ssd->cur_stack != NUM_SSD_STACK) {
 				ssd->next_tile[ssd->cur_stack] = tile;
 				ssd->next_dir[ssd->cur_stack] = _dir_from_track[ssd->bit[i]];
@@ -1970,14 +1974,34 @@
 			break;
 
 		case RAIL_TILE_SIGNALS: {
-			const StringID signal_type[] = {
-				STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS,
-				STR_RAILROAD_TRACK_WITH_PRESIGNALS,
-				STR_RAILROAD_TRACK_WITH_EXITSIGNALS,
-				STR_RAILROAD_TRACK_WITH_COMBOSIGNALS
+			const StringID signal_type[4][4] = {
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS,
+					STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS,
+					STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS
+				},
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRESIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS
+				},
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS
+				},
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS,
+					STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS,
+					STR_RAILROAD_TRACK_WITH_COMBOSIGNALS
+				}
 			};
 
-			td->str = signal_type[GetSignalType(tile)];
+			td->str = signal_type[GetSignalType(tile, TRACK_UPPER)][GetSignalType(tile, TRACK_LOWER)];
 			break;
 		}
 
--- a/src/rail_map.h	Thu May 31 19:13:41 2007 +0000
+++ b/src/rail_map.h	Thu May 31 21:21:04 2007 +0000
@@ -207,33 +207,35 @@
 	SIGTYPE_COMBO   = 3  ///< presignal inter-block
 };
 
-static inline SignalType GetSignalType(TileIndex t)
-{
-	assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
-	return (SignalType)GB(_m[t].m2, 0, 2);
-}
-
-static inline void SetSignalType(TileIndex t, SignalType s)
+static inline SignalType GetSignalType(TileIndex t, Track track)
 {
 	assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
-	SB(_m[t].m2, 0, 2, s);
+	byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0;
+	return (SignalType)GB(_m[t].m2, pos, 2);
 }
 
-static inline bool IsPresignalEntry(TileIndex t)
+static inline void SetSignalType(TileIndex t, Track track, SignalType s)
 {
-	return GetSignalType(t) == SIGTYPE_ENTRY || GetSignalType(t) == SIGTYPE_COMBO;
+	assert(GetRailTileType(t) == RAIL_TILE_SIGNALS);
+	byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0;
+	SB(_m[t].m2, pos, 2, s);
+	if (track == INVALID_TRACK) SB(_m[t].m2, 4, 2, s);
 }
 
-static inline bool IsPresignalExit(TileIndex t)
+static inline bool IsPresignalEntry(TileIndex t, Track track)
 {
-	return GetSignalType(t) == SIGTYPE_EXIT || GetSignalType(t) == SIGTYPE_COMBO;
+	return GetSignalType(t, track) == SIGTYPE_ENTRY || GetSignalType(t, track) == SIGTYPE_COMBO;
+}
+
+static inline bool IsPresignalExit(TileIndex t, Track track)
+{
+	return GetSignalType(t, track) == SIGTYPE_EXIT || GetSignalType(t, track) == SIGTYPE_COMBO;
 }
 
 static inline void CycleSignalSide(TileIndex t, Track track)
 {
 	byte sig;
-	byte pos = 6;
-	if (track == TRACK_LOWER || track == TRACK_RIGHT) pos = 4;
+	byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 6;
 
 	sig = GB(_m[t].m3, pos, 2);
 	if (--sig == 0) sig = 3;
@@ -246,14 +248,17 @@
 	SIG_SEMAPHORE = 1  ///< Old-fashioned semaphore signal
 };
 
-static inline SignalVariant GetSignalVariant(TileIndex t)
+static inline SignalVariant GetSignalVariant(TileIndex t, Track track)
 {
-	return (SignalVariant)GB(_m[t].m2, 2, 1);
+	byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 6 : 2;
+	return (SignalVariant)GB(_m[t].m2, pos, 1);
 }
 
-static inline void SetSignalVariant(TileIndex t, SignalVariant v)
+static inline void SetSignalVariant(TileIndex t, Track track, SignalVariant v)
 {
-	SB(_m[t].m2, 2, 1, v);
+	byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 6 : 2;
+	SB(_m[t].m2, pos, 1, v);
+	if (track == INVALID_TRACK) SB(_m[t].m2, 6, 1, v);
 }
 
 /** These are states in which a signal can be. Currently these are only two, so
@@ -272,7 +277,7 @@
  */
 static inline void SetSignalStates(TileIndex tile, uint state)
 {
-	SB(_m[tile].m2, 4, 4, state);
+	SB(_m[tile].m4, 4, 4, state);
 }
 
 /**
@@ -282,7 +287,7 @@
  */
 static inline uint GetSignalStates(TileIndex tile)
 {
-	return GB(_m[tile].m2, 4, 4);
+	return GB(_m[tile].m4, 4, 4);
 }
 
 /**
--- a/src/saveload.cpp	Thu May 31 19:13:41 2007 +0000
+++ b/src/saveload.cpp	Thu May 31 21:21:04 2007 +0000
@@ -29,7 +29,7 @@
 #include <setjmp.h>
 #include <list>
 
-extern const uint16 SAVEGAME_VERSION = 63;
+extern const uint16 SAVEGAME_VERSION = 64;
 uint16 _sl_version;       ///< the major savegame version identifier
 byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 
--- a/src/yapf/yapf_costrail.hpp	Thu May 31 19:13:41 2007 +0000
+++ b/src/yapf/yapf_costrail.hpp	Thu May 31 21:21:04 2007 +0000
@@ -121,7 +121,7 @@
 						Yapf().m_stopped_on_first_two_way_signal = true;
 						return -1;
 					}
-					SignalType sig_type = GetSignalType(tile);
+					SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir));
 					n.m_last_red_signal_type = sig_type;
 					n.flags_u.flags_s.m_last_signal_was_red = true;