diff options
Diffstat (limited to 'rail_cmd.c')
-rw-r--r-- | rail_cmd.c | 137 |
1 files changed, 101 insertions, 36 deletions
diff --git a/rail_cmd.c b/rail_cmd.c index a1340428b..796ba88fd 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -15,7 +15,9 @@ #include "station.h" #include "sprite.h" #include "depot.h" +#include "pbs.h" #include "waypoint.h" +#include "npf.h" #include "rail.h" extern uint16 _custom_sprites_base; @@ -757,10 +759,10 @@ int32 CmdBuildSingleSignal(int x, int y, uint32 flags, uint32 p1, uint32 p2) _map3_lo[tile] |= SignalOnTrack(track); } else { if (pre_signal) { - // cycle between normal -> pre -> exit -> combo -> ... - byte type = (GetSignalType(tile, track) + 1) & 0x03; - _map3_hi[tile] &= ~0x03; - _map3_hi[tile] |= type; + // cycle between normal -> pre -> exit -> combo -> pbs ->... + byte type = ((GetSignalType(tile, track) + 1) % 5); + _map3_hi[tile] &= ~0x07; + _map3_hi[tile] |= type ; } else { // cycle between two-way -> one-way -> one-way -> ... /* TODO: Rewrite switch into something more general */ @@ -1123,21 +1125,24 @@ static const SpriteID _signal_base_sprites[32] = { 0x1333, 0x1343, - 0x0, //PBS place, light signal - 0x0, //reserved for future use - 0x0, //reserved for future use - 0x0, //reserved for future use + // pbs signals + 0x1393, + 0x13A3, // not used (yet?) + 0x13B3, // not used (yet?) + 0x13C3, // not used (yet?) - // use semaphores instead of signals? + // semaphores 0x1353, 0x1363, 0x1373, 0x1383, - 0x0, //PBS place, semaphore - 0x0, //reserved for future use - 0x0, //reserved for future use - 0x0, //reserved for future use + // pbs semaphores + 0x13D3, + 0x13E3, // not used (yet?) + 0x13F3, // not used (yet?) + 0x1403, // not used (yet?) + // mirrored versions 0x4FB, @@ -1145,20 +1150,23 @@ static const SpriteID _signal_base_sprites[32] = { 0x1333, 0x1343, - 0x0, //PBS place, semaphore - 0x0, //reserved for future use - 0x0, //reserved for future use - 0x0, //reserved for future use - - 0x13C6, - 0x13D6, - 0x13E6, - 0x13F6, - - 0x0, //PBS place, semaphore - 0x0, //reserved for future use - 0x0, //reserved for future use - 0x0, //reserved for future use + // pbs signals + 0x1393, + 0x13A3, // not used (yet?) + 0x13B3, // not used (yet?) + 0x13C3, // not used (yet?) + + // semaphores + 0x1446, + 0x1456, + 0x1466, + 0x1476, + + // pbs semaphores + 0x14C6, + 0x14D6, // not used (yet?) + 0x14E6, // not used (yet?) + 0x14F6, // not used (yet?) }; // used to determine the side of the road for the signal @@ -1466,6 +1474,16 @@ static void DrawTile_Track(TileInfo *ti) if (m5 & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST]); } + if (_debug_pbs_level >= 1) { + byte pbs = PBSTileReserved(ti->tile); + if (pbs & TRACK_BIT_DIAG1) DrawGroundSprite(TrackSet[SINGLE_Y] | PALETTE_CRASH); + if (pbs & TRACK_BIT_DIAG2) DrawGroundSprite(TrackSet[SINGLE_X] | PALETTE_CRASH); + if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(TrackSet[SINGLE_NORTH] | PALETTE_CRASH); + if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(TrackSet[SINGLE_SOUTH] | PALETTE_CRASH); + if (pbs & TRACK_BIT_LEFT) DrawGroundSprite(TrackSet[SINGLE_WEST] | PALETTE_CRASH); + if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(TrackSet[SINGLE_EAST] | PALETTE_CRASH); + } + if (_display_opt & DO_FULL_DETAIL) { _detailed_track_proc[_map2[ti->tile] & RAIL_MAP2LO_GROUND_MASK](ti); } @@ -1575,6 +1593,16 @@ static void DrawTile_Track(TileInfo *ti) DrawGroundSprite(image); + if (_debug_pbs_level >= 1) { + byte pbs = PBSTileReserved(ti->tile); + if (pbs & TRACK_BIT_DIAG1) DrawGroundSprite((0x3ED + tracktype_offs) | PALETTE_CRASH); + if (pbs & TRACK_BIT_DIAG2) DrawGroundSprite((0x3EE + tracktype_offs) | PALETTE_CRASH); + if (pbs & TRACK_BIT_UPPER) DrawGroundSprite((0x3EF + tracktype_offs) | PALETTE_CRASH); + if (pbs & TRACK_BIT_LOWER) DrawGroundSprite((0x3F0 + tracktype_offs) | PALETTE_CRASH); + if (pbs & TRACK_BIT_LEFT) DrawGroundSprite((0x3F2 + tracktype_offs) | PALETTE_CRASH); + if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite((0x3F1 + tracktype_offs) | PALETTE_CRASH); + } + while ((image=drss->image) != 0) { DrawSpecialBuilding(image, type < 4 ? tracktype_offs : 0, ti, drss->subcoord_x, drss->subcoord_y, 0, @@ -1611,15 +1639,17 @@ void DrawTrainDepotSprite(int x, int y, int image, int railtype) } } -#define NUM_SSD_ENTRY 256 -#define NUM_SSD_STACK 32 - typedef struct SetSignalsData { int cur; int cur_stack; bool stop; bool has_presignal; + bool has_pbssignal; + // lowest 2 bits = amount of pbs signals in the block, clamped at 2 + // bit 2 = there is a pbs entry signal in this block + // bit 3 = there is a pbs exit signal in this block + // presignal info int presignal_exits; int presignal_exits_free; @@ -1628,6 +1658,10 @@ typedef struct SetSignalsData { byte bit[NUM_SSD_ENTRY]; TileIndex tile[NUM_SSD_ENTRY]; + int pbs_cur; + // these are used to keep track of all signals in the block + TileIndex pbs_tile[NUM_SSD_ENTRY]; + // these are used to keep track of the stack that modifies presignals recursively TileIndex next_tile[NUM_SSD_STACK]; byte next_dir[NUM_SSD_STACK]; @@ -1647,15 +1681,34 @@ static bool SetSignalsEnumProc(TileIndex tile, SetSignalsData *ssd, int track, u ssd->cur++; } + if (PBSIsPbsSignal(tile, ReverseTrackdir(track))) + SETBIT(ssd->has_pbssignal, 2); + // remember if this block has a presignal. ssd->has_presignal |= (_map3_hi[tile]&1); } - // is this an exit signal that points out from the segment? - if ((_map3_hi[tile]&2) && _map3_lo[tile]&_signals_table_other[track]) { - ssd->presignal_exits++; - if ((_map2[tile]&_signals_table_other[track]) != 0) - ssd->presignal_exits_free++; + if (PBSIsPbsSignal(tile, ReverseTrackdir(track)) || PBSIsPbsSignal(tile, track)) { + byte num = ssd->has_pbssignal & 3; + num = clamp(num + 1, 0, 2); + ssd->has_pbssignal &= ~3; + ssd->has_pbssignal |= num; + } + + if ((_map3_lo[tile] & _signals_table_both[track]) != 0) { + ssd->pbs_tile[ssd->pbs_cur] = tile; // remember the tile index + ssd->pbs_cur++; + } + + if (_map3_lo[tile]&_signals_table_other[track]) { + if (_map3_hi[tile]&2) { + // this is an exit signal that points out from the segment + ssd->presignal_exits++; + if ((_map2[tile]&_signals_table_other[track]) != 0) + ssd->presignal_exits_free++; + } + if (PBSIsPbsSignal(tile, track)) + SETBIT(ssd->has_pbssignal, 3); } return true; @@ -1792,6 +1845,15 @@ static void ChangeSignalStates(SetSignalsData *ssd) // there is at least one green exit signal OR // there are no exit signals in the segment + // convert the block to pbs, if needed + 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 + for(i=0; i!=ssd->pbs_cur; i++) { + TileIndex tile = ssd->pbs_tile[i]; + _map3_hi[tile] &= ~0x07; + _map3_hi[tile] |= 0x04; + MarkTileDirtyByTile(tile); + }; + // then mark the signals in the segment accordingly for(i=0; i!=ssd->cur; i++) { TileIndex tile = ssd->tile[i]; @@ -1852,8 +1914,9 @@ bool UpdateSignalsOnSegment(TileIndex tile, byte direction) for(;;) { // go through one segment and update all signals pointing into that segment. - ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0; + ssd.cur = ssd.pbs_cur = ssd.presignal_exits = ssd.presignal_exits_free = 0; ssd.has_presignal = false; + ssd.has_pbssignal = false; FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, (TPFEnumProc*)SetSignalsEnumProc, SetSignalsAfterProc, &ssd); ChangeSignalStates(&ssd); @@ -2162,6 +2225,8 @@ static uint32 VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y) } else if (_fractcoords_enter[dir] == fract_coord) { if (_enter_directions[dir] == v->direction) { /* enter the depot */ + if (v->next == NULL) + PBSClearTrack(v->tile, FIND_FIRST_BIT(v->u.rail.track)); v->u.rail.track = 0x80, v->vehstatus |= VS_HIDDEN; /* hide it */ v->direction ^= 4; |