rail_cmd.c
changeset 2008 c9d6585c96c8
parent 2007 b3bdf698ee26
child 2020 392890f32338
equal deleted inserted replaced
2007:b3bdf698ee26 2008:c9d6585c96c8
    13 #include "town.h"
    13 #include "town.h"
    14 #include "sound.h"
    14 #include "sound.h"
    15 #include "station.h"
    15 #include "station.h"
    16 #include "sprite.h"
    16 #include "sprite.h"
    17 #include "depot.h"
    17 #include "depot.h"
       
    18 #include "pbs.h"
    18 #include "waypoint.h"
    19 #include "waypoint.h"
       
    20 #include "npf.h"
    19 #include "rail.h"
    21 #include "rail.h"
    20 
    22 
    21 extern uint16 _custom_sprites_base;
    23 extern uint16 _custom_sprites_base;
    22 
    24 
    23 void ShowTrainDepotWindow(TileIndex tile);
    25 void ShowTrainDepotWindow(TileIndex tile);
   755 			if (!HasSignalOnTrack(tile, track)) {
   757 			if (!HasSignalOnTrack(tile, track)) {
   756 				// build new signals
   758 				// build new signals
   757 				_map3_lo[tile] |= SignalOnTrack(track);
   759 				_map3_lo[tile] |= SignalOnTrack(track);
   758 			} else {
   760 			} else {
   759 				if (pre_signal) {
   761 				if (pre_signal) {
   760 					// cycle between normal -> pre -> exit -> combo -> ...
   762 					// cycle between normal -> pre -> exit -> combo -> pbs ->...
   761 					byte type = (GetSignalType(tile, track) + 1) & 0x03;
   763 					byte type = ((GetSignalType(tile, track) + 1) % 5);
   762 					_map3_hi[tile] &= ~0x03;
   764 					_map3_hi[tile] &= ~0x07;
   763 					_map3_hi[tile] |= type;
   765 					_map3_hi[tile] |= type ;
   764 				} else {
   766 				} else {
   765 					// cycle between two-way -> one-way -> one-way -> ...
   767 					// cycle between two-way -> one-way -> one-way -> ...
   766 					/* TODO: Rewrite switch into something more general */
   768 					/* TODO: Rewrite switch into something more general */
   767 					switch (track) {
   769 					switch (track) {
   768 						case TRACK_LOWER:
   770 						case TRACK_LOWER:
  1121 	0x4FB,
  1123 	0x4FB,
  1122 	0x1323,
  1124 	0x1323,
  1123 	0x1333,
  1125 	0x1333,
  1124 	0x1343,
  1126 	0x1343,
  1125 
  1127 
  1126 	0x0,	//PBS place, light signal
  1128 	// pbs signals
  1127 	0x0,	//reserved for future use
  1129 	0x1393,
  1128 	0x0,	//reserved for future use
  1130 	0x13A3,  // not used (yet?)
  1129 	0x0,	//reserved for future use
  1131 	0x13B3,  // not used (yet?)
  1130 
  1132 	0x13C3,  // not used (yet?)
  1131 	// use semaphores instead of signals?
  1133 
       
  1134 	// semaphores
  1132 	0x1353,
  1135 	0x1353,
  1133 	0x1363,
  1136 	0x1363,
  1134 	0x1373,
  1137 	0x1373,
  1135 	0x1383,
  1138 	0x1383,
  1136 
  1139 
  1137 	0x0,	//PBS place, semaphore
  1140 	// pbs semaphores
  1138 	0x0,	//reserved for future use
  1141 	0x13D3,
  1139 	0x0,	//reserved for future use
  1142 	0x13E3,  // not used (yet?)
  1140 	0x0,	//reserved for future use
  1143 	0x13F3,  // not used (yet?)
       
  1144 	0x1403,  // not used (yet?)
       
  1145 
  1141 
  1146 
  1142 	// mirrored versions
  1147 	// mirrored versions
  1143 	0x4FB,
  1148 	0x4FB,
  1144 	0x1323,
  1149 	0x1323,
  1145 	0x1333,
  1150 	0x1333,
  1146 	0x1343,
  1151 	0x1343,
  1147 
  1152 
  1148 	0x0,	//PBS place, semaphore
  1153 	// pbs signals
  1149 	0x0,	//reserved for future use
  1154 	0x1393,
  1150 	0x0,	//reserved for future use
  1155 	0x13A3,  // not used (yet?)
  1151 	0x0,	//reserved for future use
  1156 	0x13B3,  // not used (yet?)
  1152 
  1157 	0x13C3,  // not used (yet?)
  1153 	0x13C6,
  1158 
  1154 	0x13D6,
  1159 	// semaphores
  1155 	0x13E6,
  1160 	0x1446,
  1156 	0x13F6,
  1161 	0x1456,
  1157 
  1162 	0x1466,
  1158 	0x0,	//PBS place, semaphore
  1163 	0x1476,
  1159 	0x0,	//reserved for future use
  1164 
  1160 	0x0,	//reserved for future use
  1165 	// pbs semaphores
  1161 	0x0,	//reserved for future use
  1166 	0x14C6,
       
  1167 	0x14D6,  // not used (yet?)
       
  1168 	0x14E6,  // not used (yet?)
       
  1169 	0x14F6,  // not used (yet?)
  1162 };
  1170 };
  1163 
  1171 
  1164 // used to determine the side of the road for the signal
  1172 // used to determine the side of the road for the signal
  1165 static const byte _signal_position[24] = {
  1173 static const byte _signal_position[24] = {
  1166 	/* original: left side position */
  1174 	/* original: left side position */
  1464 			if (m5 & TRACK_BIT_LOWER) DrawGroundSprite(TrackSet[SINGLE_SOUTH]);
  1472 			if (m5 & TRACK_BIT_LOWER) DrawGroundSprite(TrackSet[SINGLE_SOUTH]);
  1465 			if (m5 & TRACK_BIT_LEFT)  DrawGroundSprite(TrackSet[SINGLE_WEST]);
  1473 			if (m5 & TRACK_BIT_LEFT)  DrawGroundSprite(TrackSet[SINGLE_WEST]);
  1466 			if (m5 & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST]);
  1474 			if (m5 & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST]);
  1467 		}
  1475 		}
  1468 
  1476 
       
  1477 		if (_debug_pbs_level >= 1) {
       
  1478 			byte pbs = PBSTileReserved(ti->tile);
       
  1479 			if (pbs & TRACK_BIT_DIAG1) DrawGroundSprite(TrackSet[SINGLE_Y] | PALETTE_CRASH);
       
  1480 			if (pbs & TRACK_BIT_DIAG2) DrawGroundSprite(TrackSet[SINGLE_X] | PALETTE_CRASH);
       
  1481 			if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(TrackSet[SINGLE_NORTH] | PALETTE_CRASH);
       
  1482 			if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(TrackSet[SINGLE_SOUTH] | PALETTE_CRASH);
       
  1483 			if (pbs & TRACK_BIT_LEFT)  DrawGroundSprite(TrackSet[SINGLE_WEST] | PALETTE_CRASH);
       
  1484 			if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST] | PALETTE_CRASH);
       
  1485 		}
       
  1486 
  1469 		if (_display_opt & DO_FULL_DETAIL) {
  1487 		if (_display_opt & DO_FULL_DETAIL) {
  1470 			_detailed_track_proc[_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK](ti);
  1488 			_detailed_track_proc[_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK](ti);
  1471 		}
  1489 		}
  1472 
  1490 
  1473 		/* draw signals also? */
  1491 		/* draw signals also? */
  1573 				image = 4550; // flat ground
  1591 				image = 4550; // flat ground
  1574 		}
  1592 		}
  1575 
  1593 
  1576 		DrawGroundSprite(image);
  1594 		DrawGroundSprite(image);
  1577 
  1595 
       
  1596 		if (_debug_pbs_level >= 1) {
       
  1597 			byte pbs = PBSTileReserved(ti->tile);
       
  1598 			if (pbs & TRACK_BIT_DIAG1) DrawGroundSprite((0x3ED + tracktype_offs) | PALETTE_CRASH);
       
  1599 			if (pbs & TRACK_BIT_DIAG2) DrawGroundSprite((0x3EE + tracktype_offs) | PALETTE_CRASH);
       
  1600 			if (pbs & TRACK_BIT_UPPER) DrawGroundSprite((0x3EF + tracktype_offs) | PALETTE_CRASH);
       
  1601 			if (pbs & TRACK_BIT_LOWER) DrawGroundSprite((0x3F0 + tracktype_offs) | PALETTE_CRASH);
       
  1602 			if (pbs & TRACK_BIT_LEFT)  DrawGroundSprite((0x3F2 + tracktype_offs) | PALETTE_CRASH);
       
  1603 			if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite((0x3F1 + tracktype_offs) | PALETTE_CRASH);
       
  1604 		}
       
  1605 
  1578 		while ((image=drss->image) != 0) {
  1606 		while ((image=drss->image) != 0) {
  1579 			DrawSpecialBuilding(image, type < 4 ? tracktype_offs : 0, ti,
  1607 			DrawSpecialBuilding(image, type < 4 ? tracktype_offs : 0, ti,
  1580 			                    drss->subcoord_x, drss->subcoord_y, 0,
  1608 			                    drss->subcoord_x, drss->subcoord_y, 0,
  1581 			                    drss->width, drss->height, 0x17);
  1609 			                    drss->width, drss->height, 0x17);
  1582 			drss++;
  1610 			drss++;
  1609 		if (image & 0x8000) image |= ormod;
  1637 		if (image & 0x8000) image |= ormod;
  1610 		DrawSprite(image + railtype, x + pt.x, y + pt.y);
  1638 		DrawSprite(image + railtype, x + pt.x, y + pt.y);
  1611 	}
  1639 	}
  1612 }
  1640 }
  1613 
  1641 
  1614 #define NUM_SSD_ENTRY 256
       
  1615 #define NUM_SSD_STACK 32
       
  1616 
       
  1617 typedef struct SetSignalsData {
  1642 typedef struct SetSignalsData {
  1618 	int cur;
  1643 	int cur;
  1619 	int cur_stack;
  1644 	int cur_stack;
  1620 	bool stop;
  1645 	bool stop;
  1621 	bool has_presignal;
  1646 	bool has_presignal;
  1622 
  1647 
       
  1648 	bool has_pbssignal;
       
  1649 		// lowest 2 bits = amount of pbs signals in the block, clamped at 2
       
  1650 		// bit 2 = there is a pbs entry signal in this block
       
  1651 		// bit 3 = there is a pbs exit signal in this block
       
  1652 
  1623 	// presignal info
  1653 	// presignal info
  1624 	int presignal_exits;
  1654 	int presignal_exits;
  1625 	int presignal_exits_free;
  1655 	int presignal_exits_free;
  1626 
  1656 
  1627 	// these are used to keep track of the signals that change.
  1657 	// these are used to keep track of the signals that change.
  1628 	byte bit[NUM_SSD_ENTRY];
  1658 	byte bit[NUM_SSD_ENTRY];
  1629 	TileIndex tile[NUM_SSD_ENTRY];
  1659 	TileIndex tile[NUM_SSD_ENTRY];
       
  1660 
       
  1661 	int pbs_cur;
       
  1662 	// these are used to keep track of all signals in the block
       
  1663 	TileIndex pbs_tile[NUM_SSD_ENTRY];
  1630 
  1664 
  1631 	// these are used to keep track of the stack that modifies presignals recursively
  1665 	// these are used to keep track of the stack that modifies presignals recursively
  1632 	TileIndex next_tile[NUM_SSD_STACK];
  1666 	TileIndex next_tile[NUM_SSD_STACK];
  1633 	byte next_dir[NUM_SSD_STACK];
  1667 	byte next_dir[NUM_SSD_STACK];
  1634 
  1668 
  1645 					ssd->tile[ssd->cur] = tile; // remember the tile index
  1679 					ssd->tile[ssd->cur] = tile; // remember the tile index
  1646 					ssd->bit[ssd->cur] = track; // and the controlling bit number
  1680 					ssd->bit[ssd->cur] = track; // and the controlling bit number
  1647 					ssd->cur++;
  1681 					ssd->cur++;
  1648 				}
  1682 				}
  1649 
  1683 
       
  1684 			if (PBSIsPbsSignal(tile, ReverseTrackdir(track)))
       
  1685 				SETBIT(ssd->has_pbssignal, 2);
       
  1686 
  1650 				// remember if this block has a presignal.
  1687 				// remember if this block has a presignal.
  1651 				ssd->has_presignal |= (_map3_hi[tile]&1);
  1688 				ssd->has_presignal |= (_map3_hi[tile]&1);
  1652 			}
  1689 			}
  1653 
  1690 
  1654 			// is this an exit signal that points out from the segment?
  1691 			if (PBSIsPbsSignal(tile, ReverseTrackdir(track)) || PBSIsPbsSignal(tile, track)) {
  1655 			if ((_map3_hi[tile]&2) && _map3_lo[tile]&_signals_table_other[track]) {
  1692 				byte num = ssd->has_pbssignal & 3;
  1656 				ssd->presignal_exits++;
  1693 				num = clamp(num + 1, 0, 2);
  1657 				if ((_map2[tile]&_signals_table_other[track]) != 0)
  1694 				ssd->has_pbssignal &= ~3;
  1658 					ssd->presignal_exits_free++;
  1695 				ssd->has_pbssignal |= num;
       
  1696 			}
       
  1697 
       
  1698 			if ((_map3_lo[tile] & _signals_table_both[track]) != 0) {
       
  1699 				ssd->pbs_tile[ssd->pbs_cur] = tile; // remember the tile index
       
  1700 				ssd->pbs_cur++;
       
  1701 			}
       
  1702 
       
  1703 			if (_map3_lo[tile]&_signals_table_other[track]) {
       
  1704 				if (_map3_hi[tile]&2) {
       
  1705 					// this is an exit signal that points out from the segment
       
  1706 					ssd->presignal_exits++;
       
  1707 					if ((_map2[tile]&_signals_table_other[track]) != 0)
       
  1708 						ssd->presignal_exits_free++;
       
  1709 				}
       
  1710 				if (PBSIsPbsSignal(tile, track))
       
  1711 					SETBIT(ssd->has_pbssignal, 3);
  1659 			}
  1712 			}
  1660 
  1713 
  1661 			return true;
  1714 			return true;
  1662 		} else if (IsTileDepotType(tile, TRANSPORT_RAIL))
  1715 		} else if (IsTileDepotType(tile, TRANSPORT_RAIL))
  1663 			return true; // don't look further if the tile is a depot
  1716 			return true; // don't look further if the tile is a depot
  1790 	// the presignal is green if,
  1843 	// the presignal is green if,
  1791 	//   if no train is in the segment AND
  1844 	//   if no train is in the segment AND
  1792 	//   there is at least one green exit signal OR
  1845 	//   there is at least one green exit signal OR
  1793 	//   there are no exit signals in the segment
  1846 	//   there are no exit signals in the segment
  1794 
  1847 
       
  1848 	// convert the block to pbs, if needed
       
  1849 	if (_patches.auto_pbs_placement && !(ssd->stop) && (ssd->has_pbssignal == 0xE) && !ssd->has_presignal && (ssd->presignal_exits == 0)) // 0xE means at least 2 pbs signals, and at least 1 entry and 1 exit, see comments ssd->has_pbssignal
       
  1850 	for(i=0; i!=ssd->pbs_cur; i++) {
       
  1851 		TileIndex tile = ssd->pbs_tile[i];
       
  1852 		_map3_hi[tile] &= ~0x07;
       
  1853 		_map3_hi[tile] |= 0x04;
       
  1854 		MarkTileDirtyByTile(tile);
       
  1855 	};
       
  1856 
  1795 	// then mark the signals in the segment accordingly
  1857 	// then mark the signals in the segment accordingly
  1796 	for(i=0; i!=ssd->cur; i++) {
  1858 	for(i=0; i!=ssd->cur; i++) {
  1797 		TileIndex tile = ssd->tile[i];
  1859 		TileIndex tile = ssd->tile[i];
  1798 		byte bit = _signals_table[ssd->bit[i]];
  1860 		byte bit = _signals_table[ssd->bit[i]];
  1799 		uint16 m2 = _map2[tile];
  1861 		uint16 m2 = _map2[tile];
  1850 	ssd.cur_stack = 0;
  1912 	ssd.cur_stack = 0;
  1851 	direction>>=1;
  1913 	direction>>=1;
  1852 
  1914 
  1853 	for(;;) {
  1915 	for(;;) {
  1854 		// go through one segment and update all signals pointing into that segment.
  1916 		// go through one segment and update all signals pointing into that segment.
  1855 		ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
  1917 		ssd.cur = ssd.pbs_cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
  1856 		ssd.has_presignal = false;
  1918 		ssd.has_presignal = false;
       
  1919 		ssd.has_pbssignal = false;
  1857 
  1920 
  1858 		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, (TPFEnumProc*)SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
  1921 		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, (TPFEnumProc*)SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
  1859 		ChangeSignalStates(&ssd);
  1922 		ChangeSignalStates(&ssd);
  1860 
  1923 
  1861 		// remember the result only for the first iteration.
  1924 		// remember the result only for the first iteration.
  2160 		/* make sure a train is not entering the tile from behind */
  2223 		/* make sure a train is not entering the tile from behind */
  2161 		return 8;
  2224 		return 8;
  2162 	} else if (_fractcoords_enter[dir] == fract_coord) {
  2225 	} else if (_fractcoords_enter[dir] == fract_coord) {
  2163 		if (_enter_directions[dir] == v->direction) {
  2226 		if (_enter_directions[dir] == v->direction) {
  2164 			/* enter the depot */
  2227 			/* enter the depot */
       
  2228 			if (v->next == NULL)
       
  2229 				PBSClearTrack(v->tile, FIND_FIRST_BIT(v->u.rail.track));
  2165 			v->u.rail.track = 0x80,
  2230 			v->u.rail.track = 0x80,
  2166 			v->vehstatus |= VS_HIDDEN; /* hide it */
  2231 			v->vehstatus |= VS_HIDDEN; /* hide it */
  2167 			v->direction ^= 4;
  2232 			v->direction ^= 4;
  2168 			if (v->next == NULL)
  2233 			if (v->next == NULL)
  2169 				TrainEnterDepot(v, tile);
  2234 				TrainEnterDepot(v, tile);