Index: source.list =================================================================== --- source.list (revision 17618) +++ source.list (working copy) @@ -61,6 +61,7 @@ #end settings.cpp signal.cpp +signalex.cpp signs.cpp sound.cpp spritecache.cpp @@ -251,6 +252,8 @@ ship.h signal_func.h signal_type.h +signalex_base.h +signalex_type.h signs_base.h signs_func.h signs_type.h @@ -466,6 +469,7 @@ saveload/saveload.cpp saveload/saveload.h saveload/saveload_internal.h +saveload/signalex_sl.cpp saveload/signs_sl.cpp saveload/station_sl.cpp saveload/strings_sl.cpp @@ -766,6 +770,7 @@ rail_map.h road_map.cpp road_map.h +signalex_map.h station_map.h tile_map.h town_map.h Index: src/misc.cpp =================================================================== --- src/misc.cpp (revision 17618) +++ src/misc.cpp (working copy) @@ -59,6 +59,7 @@ void InitializeCheats(); void InitializeNPF(); void InitializeOldNames(); +void InitializeSignalEx(); void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings) { @@ -108,6 +109,7 @@ InitializeCargoPackets(); InitializeIndustries(); InitializeBuildingCounts(); + InitializeSignalEx(); InitializeNPF(); Index: src/openttd.cpp =================================================================== --- src/openttd.cpp (revision 17618) +++ src/openttd.cpp (working copy) @@ -63,6 +63,7 @@ #include "thread/thread.h" #include "station_base.h" #include "crashlog.h" +#include "signalex_base.h" #include "newgrf_commons.h" @@ -345,6 +346,7 @@ _cargopacket_pool.CleanPool(); _engine_pool.CleanPool(); _company_pool.CleanPool(); + _signalex_pool.CleanPool(); free(_config_file); Index: src/rail_cmd.cpp =================================================================== --- src/rail_cmd.cpp (revision 17618) +++ src/rail_cmd.cpp (working copy) @@ -35,6 +35,7 @@ #include "functions.h" #include "elrail_func.h" #include "town.h" +#include "signalex_base.h" #include "table/strings.h" #include "table/railtypes.h" @@ -971,6 +972,13 @@ uint mask = GetPresentSignals(tile) & SignalOnTrack(track); SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((HasBit(GetRailReservationTrackBits(tile), track) ? UINT_MAX : 0) & mask)); } + + /* at this point the tile has a signal. If it's an extended signal, update it */ + if(HasExtendedSignals(tile)) { SignalEx::UpdateFromTile(tile); } +#ifdef _ALL_SIGNALS_EXTENDED + else { SignalEx::Update(SignalEx::Create(tile)); } +#endif + MarkTileDirtyByTile(tile); AddTrackToSignalBuffer(tile, track, _current_company); YapfNotifyTrackLayoutChange(tile, track); @@ -1220,9 +1228,15 @@ /* removed last signal from tile? */ if (GetPresentSignals(tile) == 0) { + /* destroy the extended signal if the tile has one */ + if(HasExtendedSignals(tile)) { + SignalEx::Destroy(tile); // perform before the tile type is changed from RAIL_TILE_SIGNALS + } SetSignalStates(tile, 0); SetHasSignals(tile, false); SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores + } else { + SignalEx::UpdateFromTile(tile); // inform SignalEx object its tile signals have been updated } AddTrackToSignalBuffer(tile, track, GetTileOwner(tile)); Index: src/rail_map.h =================================================================== --- src/rail_map.h (revision 17618) +++ src/rail_map.h (working copy) @@ -17,66 +17,12 @@ #include "signal_func.h" #include "direction_func.h" #include "track_func.h" -#include "tile_map.h" #include "signal_type.h" +#include "rail_map_base.h" +#include "signalex_base.h" -/** Different types of Rail-related tiles */ -enum RailTileType { - RAIL_TILE_NORMAL = 0, ///< Normal rail tile without signals - RAIL_TILE_SIGNALS = 1, ///< Normal rail tile with signals - RAIL_TILE_DEPOT = 3, ///< Depot (one entrance) -}; - /** - * Returns the RailTileType (normal with or without signals, - * waypoint or depot). - * @param t the tile to get the information from - * @pre IsTileType(t, MP_RAILWAY) - * @return the RailTileType - */ -static inline RailTileType GetRailTileType(TileIndex t) -{ - assert(IsTileType(t, MP_RAILWAY)); - return (RailTileType)GB(_m[t].m5, 6, 2); -} - -/** - * Returns whether this is plain rails, with or without signals. Iow, if this - * tiles RailTileType is RAIL_TILE_NORMAL or RAIL_TILE_SIGNALS. - * @param t the tile to get the information from - * @pre IsTileType(t, MP_RAILWAY) - * @return true if and only if the tile is normal rail (with or without signals) - */ -static inline bool IsPlainRail(TileIndex t) -{ - RailTileType rtt = GetRailTileType(t); - return rtt == RAIL_TILE_NORMAL || rtt == RAIL_TILE_SIGNALS; -} - -/** - * Checks whether the tile is a rail tile or rail tile with signals. - * @param t the tile to get the information from - * @return true if and only if the tile is normal rail (with or without signals) - */ -static inline bool IsPlainRailTile(TileIndex t) -{ - return IsTileType(t, MP_RAILWAY) && IsPlainRail(t); -} - - -/** - * Checks if a rail tile has signals. - * @param t the tile to get the information from - * @pre IsTileType(t, MP_RAILWAY) - * @return true if and only if the tile has signals - */ -static inline bool HasSignals(TileIndex t) -{ - return GetRailTileType(t) == RAIL_TILE_SIGNALS; -} - -/** * Add/remove the 'has signal' bit from the RailTileType * @param tile the tile to add/remove the signals to/from * @param signals whether the rail tile should have signals or not @@ -186,7 +132,6 @@ return DiagDirToDiagTrack(GetRailDepotDirection(t)); } - /** * Returns the reserved track bits of the tile * @pre IsPlainRailTile(t) @@ -196,10 +141,12 @@ static inline TrackBits GetRailReservationTrackBits(TileIndex t) { assert(IsPlainRailTile(t)); - byte track_b = GB(_m[t].m2, 8, 3); + + uint16 &m2_ref = (HasExtendedSignals(t) ? _signalex_pool.Get(_m[t].m2)->m2 : _m[t].m2); + byte track_b = GB(m2_ref, 8, 3); Track track = (Track)(track_b - 1); // map array saves Track+1 if (track_b == 0) return TRACK_BIT_NONE; - return (TrackBits)(TrackToTrackBits(track) | (HasBit(_m[t].m2, 11) ? TrackToTrackBits(TrackToOppositeTrack(track)) : 0)); + return (TrackBits)(TrackToTrackBits(track) | (HasBit(m2_ref, 11) ? TrackToTrackBits(TrackToOppositeTrack(track)) : 0)); } /** @@ -213,9 +160,10 @@ assert(IsPlainRailTile(t)); assert(b != INVALID_TRACK_BIT); assert(!TracksOverlap(b)); + uint16 &m2_ref = (HasExtendedSignals(t) ? _signalex_pool.Get(_m[t].m2)->m2 : _m[t].m2); Track track = RemoveFirstTrack(&b); - SB(_m[t].m2, 8, 3, track == INVALID_TRACK ? 0 : track+1); - SB(_m[t].m2, 11, 1, (byte)(b != TRACK_BIT_NONE)); + SB(m2_ref, 8, 3, track == INVALID_TRACK ? 0 : track+1); + SB(m2_ref, 11, 1, (byte)(b != TRACK_BIT_NONE)); } /** @@ -295,16 +243,20 @@ static inline SignalType GetSignalType(TileIndex t, Track track) { assert(GetRailTileType(t) == RAIL_TILE_SIGNALS); + + uint16 &m2_ref = (HasExtendedSignals(t) ? _signalex_pool.Get(_m[t].m2)->m2 : _m[t].m2); byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0; - return (SignalType)GB(_m[t].m2, pos, 3); + return (SignalType)GB(m2_ref, pos, 3); } static inline void SetSignalType(TileIndex t, Track track, SignalType s) { assert(GetRailTileType(t) == RAIL_TILE_SIGNALS); + byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0; - SB(_m[t].m2, pos, 3, s); - if (track == INVALID_TRACK) SB(_m[t].m2, 4, 3, s); + uint16 &m2_ref = (HasExtendedSignals(t) ? _signalex_pool.Get(_m[t].m2)->m2 : _m[t].m2); + SB(m2_ref, pos, 3, s); + if (track == INVALID_TRACK) SB(m2_ref, 4, 3, s); } static inline bool IsPresignalEntry(TileIndex t, Track track) @@ -336,14 +288,16 @@ static inline SignalVariant GetSignalVariant(TileIndex t, Track track) { byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3; - return (SignalVariant)GB(_m[t].m2, pos, 1); + uint16 &m2_ref = (HasExtendedSignals(t) ? _signalex_pool.Get(_m[t].m2)->m2 : _m[t].m2); + return (SignalVariant)GB(m2_ref, pos, 1); } static inline void SetSignalVariant(TileIndex t, Track track, SignalVariant v) { byte pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3; - SB(_m[t].m2, pos, 1, v); - if (track == INVALID_TRACK) SB(_m[t].m2, 7, 1, v); + uint16 &m2_ref = (HasExtendedSignals(t) ? _signalex_pool.Get(_m[t].m2)->m2 : _m[t].m2); + SB(m2_ref, pos, 1, v); + if (track == INVALID_TRACK) SB(m2_ref, 7, 1, v); } /** These are states in which a signal can be. Currently these are only two, so Index: src/rail_map_base.h =================================================================== --- src/rail_map_base.h (revision 0) +++ src/rail_map_base.h (revision 0) @@ -0,0 +1,63 @@ +/** @file rail_map.h Hides the direct accesses to the map array with map accessors */ + +#ifndef RAIL_MAP_PREHEADER_H +#define RAIL_MAP_PREHEADER_H + +#include "tile_map.h" + +/** Different types of Rail-related tiles */ +enum RailTileType { + RAIL_TILE_NORMAL = 0, ///< Normal rail tile without signals + RAIL_TILE_SIGNALS = 1, ///< Normal rail tile with signals + RAIL_TILE_DEPOT = 3, ///< Depot (one entrance) +}; + +/** + * Returns the RailTileType (normal with or without signals, + * waypoint or depot). + * @param t the tile to get the information from + * @pre IsTileType(t, MP_RAILWAY) + * @return the RailTileType + */ +static inline RailTileType GetRailTileType(TileIndex t) +{ + assert(IsTileType(t, MP_RAILWAY)); + return (RailTileType)GB(_m[t].m5, 6, 2); +} + +/** + * Returns whether this is plain rails, with or without signals. Iow, if this + * tiles RailTileType is RAIL_TILE_NORMAL or RAIL_TILE_SIGNALS. + * @param t the tile to get the information from + * @pre IsTileType(t, MP_RAILWAY) + * @return true if and only if the tile is normal rail (with or without signals) + */ +static inline bool IsPlainRail(TileIndex t) +{ + RailTileType rtt = GetRailTileType(t); + return rtt == RAIL_TILE_NORMAL || rtt == RAIL_TILE_SIGNALS; +} + +/** + * Checks whether the tile is a rail tile or rail tile with signals. + * @param t the tile to get the information from + * @return true if and only if the tile is normal rail (with or without signals) + */ +static inline bool IsPlainRailTile(TileIndex t) +{ + return IsTileType(t, MP_RAILWAY) && IsPlainRail(t); +} + + +/** + * Checks if a rail tile has signals. + * @param t the tile to get the information from + * @pre IsTileType(t, MP_RAILWAY) + * @return true if and only if the tile has signals + */ +static inline bool HasSignals(TileIndex t) +{ + return GetRailTileType(t) == RAIL_TILE_SIGNALS; +} + +#endif /* RAIL_MAP_PREHEADER_H */ \ No newline at end of file Index: src/saveload/afterload.cpp =================================================================== --- src/saveload/afterload.cpp (revision 17618) +++ src/saveload/afterload.cpp (working copy) @@ -42,6 +42,7 @@ #include "../animated_tile_func.h" #include "../subsidy_base.h" #include "../subsidy_func.h" +#include "../signalex_base.h" #include "table/strings.h" @@ -1959,6 +1960,18 @@ } } + /** + *Clear flag bit used by signalex from the RAIL_TILE_SIGNALS signals on older save game versions + *@todo actually needed? + */ + if (CheckSavegameVersion(128)) { + for (TileIndex t = 0; t < map_size; t++) { + if(IsTileType(t, MP_RAILWAY)) + if(GetRailTileType(t) == RAIL_TILE_SIGNALS) + SetHasExtendedSignals(t,false); + } + } + AfterLoadLabelMaps(); GamelogPrintDebug(1); Index: src/saveload/saveload.cpp =================================================================== --- src/saveload/saveload.cpp (revision 17618) +++ src/saveload/saveload.cpp (working copy) @@ -48,7 +48,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 127; +extern const uint16 SAVEGAME_VERSION = 128; SavegameType _savegame_type; ///< type of savegame we are loading @@ -1446,6 +1446,7 @@ extern const ChunkHandler _cargopacket_chunk_handlers[]; extern const ChunkHandler _autoreplace_chunk_handlers[]; extern const ChunkHandler _labelmaps_chunk_handlers[]; +extern const ChunkHandler _signalex_chunk_handlers[]; static const ChunkHandler * const _chunk_handlers[] = { _gamelog_chunk_handlers, @@ -1473,6 +1474,7 @@ _cargopacket_chunk_handlers, _autoreplace_chunk_handlers, _labelmaps_chunk_handlers, + _signalex_chunk_handlers, NULL, }; Index: src/saveload/signalex_sl.cpp =================================================================== --- src/saveload/signalex_sl.cpp (revision 0) +++ src/saveload/signalex_sl.cpp (revision 0) @@ -0,0 +1,37 @@ +/** @file signalex_sl.cpp Code handling saving and loading of extended signals */ + +#include "../stdafx.h" +#include "saveload_internal.h" +#include "../signalex_base.h" +#include + +static const SaveLoad _signalex_desc[] = { + SLE_VAR(SignalEx, m2, SLE_UINT16), + SLE_VAR(SignalEx, f, SLE_UINT32), + SLE_VAR(SignalEx, t, SLE_UINT32), + SLE_END() +}; + +static void Save_SGEX() +{ + SignalEx *s; + + FOR_ALL_SIGNALEX(s) { + SlSetArrayIndex(s->index); + SlObject(s, _signalex_desc); + } +} + +static void Load_SGEX() +{ + int index; + + while ((index = SlIterateArray()) != -1) { + SignalEx *s = new (index) SignalEx(); + SlObject(s, _signalex_desc); + } +} + +extern const ChunkHandler _signalex_chunk_handlers[] = { + { 'SGEX', Save_SGEX, Load_SGEX, NULL, CH_ARRAY | CH_LAST}, +}; Index: src/signalex.cpp =================================================================== --- src/signalex.cpp (revision 0) +++ src/signalex.cpp (revision 0) @@ -0,0 +1,64 @@ +/** @file signalex.cpp Base for all extended signal handling. */ + +#include "stdafx.h" +#include "debug.h" +#include "core/pool_func.hpp" +#include "signalex_base.h" +#include "rail_map.h" + +SignalExPool _signalex_pool("SignalEx"); +INSTANTIATE_POOL_METHODS(SignalEx) + +SignalEx::SignalEx() : f(0), t(0) +{ +} +SignalEx::SignalEx(TileIndex t) : f(0), t(t) +{ +} +SignalEx::~SignalEx() +{ +} + +SignalEx* SignalEx::Create(TileIndex t) +{ + /* Ensure tile has signals */ + assert(GetRailTileType(t) == RAIL_TILE_SIGNALS); + /* Ensure tile doesn't already have signalsEx */ + assert(!HasExtendedSignals(t)); + + SignalEx* sx = new SignalEx(t); + SignalExID id = sx->index; + + sx->m2 = _m[t].m2; + _m[t].m2 = (uint16)id; + + SetHasExtendedSignals(t, true); + //SignalExMap::SetID(t, id); + + return sx; +} + +void SignalEx::Destroy(TileIndex t) +{ + /* Ensure tile has signalsEx */ + assert(HasExtendedSignals(t)); + + SignalEx* sx = SignalEx::GetByID(_m[t].m2); + + _m[t].m2 = sx->m2; + + //SignalExMap::SetID(t, 0); + SetHasExtendedSignals(t, false); + + delete sx; +} + +void SignalEx::Update(SignalEx* sx) +{ + //Add in update routines for extensions, signal checks etc. +} + +void InitializeSignalEx() +{ + _signalex_pool.CleanPool(); +} Index: src/signalex_base.h =================================================================== --- src/signalex_base.h (revision 0) +++ src/signalex_base.h (revision 0) @@ -0,0 +1,115 @@ +/** @file signalex_base.h Types, classes and variables related to extended signals. */ + +#ifndef SIGNALEXTENDED_BASE_H +#define SIGNALEXTENDED_BASE_H + +#ifdef _DEBUG + #define _ALL_SIGNALS_EXTENDED +#endif + +#include "core\bitmath_func.hpp" +#include "core/pool_type.hpp" +#include "signal_type.h" +#include "signalex_type.h" +#include "signalex_map.h" + +typedef Pool SignalExPool; +extern SignalExPool _signalex_pool; + +/** + * Defines signal extentions for a single tile. + * Stores additional information for signal extensions + * seperatly from the tile array. All 4 posible signals + * can have seperate extensions. All extensions can be + * active at the same time. + * + * flags - @see SignalExFeature + * flags: bit 7-0: Features in use for signal 0, + * flags: bit 15-8: Features in use for signal 1 + * flags: bit 23-16: Features in use for signal 2 + * flags: bit 32-24: Features in use for signal 3 + * + * @warning Update the SaveLoad if adding variables to SignalEx. @see saveload\signalex_sl.cpp + */ +struct SignalEx : SignalExPool::PoolItem<&_signalex_pool> { + uint16 m2; ///< the working m2 variable for the tile + uint32 f; ///< specifies what features are in-use for each signal. + TileIndex t; ///< the tile location of this signalex (for reverse lookup) + +private: + friend SignalExPool; + friend void Load_SGEX(); + + /** + * Forbidden to create or destroy SignalEx objects directly. + * To create extended signals for a tile use Create(t) or + * Destroy(t) to remove them. Loading and Pool management + * are exceptions. + */ + SignalEx(); + SignalEx(TileIndex t); + ~SignalEx(); + +public: + /** Get the SignalEx object from the pool using its ID + */ + static FORCEINLINE SignalEx* GetByID(SignalExID id){ + return _signalex_pool.Get(id); + } + + /** Get the SignalEx object from the pool using a TileIndex + * @pre: SignalExMap::IsEnabled(t) + */ + static FORCEINLINE SignalEx* GetByTile(TileIndex t){ + assert(HasExtendedSignals(t)); + return _signalex_pool.Get(_m[t].m2); + } + + /** Update the SignalEx object bound to a given a tile + * @param t - the tile to look up + * @pre SignalExMap::IsEnabled(t) + */ + static FORCEINLINE void UpdateFromTile(TileIndex t){ + /* Ensure tile has signalsEx */ + assert(HasExtendedSignals(t)); + SignalEx::Update(SignalEx::GetByTile(t)); + } + + /** + * Instantiates a SignalEx object for a given tile + * Enables SignalEx on the tile and stores the + * SignalExID in the tile as well. + * + * @param t - tile index to create SignalEx for + * @return pointer to the new SignalEx object; + * + * @pre GetRailTileType(t) == RAIL_TILE_SIGNALS + * @pre !SignalExMap::IsEnabled(t) + */ + static SignalEx* Create(TileIndex t); + + /** + * Destroys a SignalEx object for a given tile. + * Disables SignalEx on the tile and clears the + * SignalExID from the tile as well. Called automatically + * just prior to the removal of the last signal from a tile. + * @param t - tile index to remove SignalEx from + * @pre SignalExMap::IsEnabled(t) + */ + static void Destroy(TileIndex t); + + /** + * Update a SignalEx object after a tile alteration. + * When the arrangment of signals on a tile is altered, + * this function is called. Will not be called if the tile + * loses all its signals. + * @param sx - the SignalEx object to update. + * @pre SignalExMap::IsEnabled(t) + */ + static void Update(SignalEx* sx); +}; + +#define FOR_ALL_SIGNALEX_FROM(var, start) FOR_ALL_ITEMS_FROM(SignalEx, signalex_index, var, start) +#define FOR_ALL_SIGNALEX(var) FOR_ALL_SIGNALEX_FROM(var, 0) + +#endif /* SIGNALEXTENDED_BASE_H */ Index: src/signalex_map.h =================================================================== --- src/signalex_map.h (revision 0) +++ src/signalex_map.h (revision 0) @@ -0,0 +1,33 @@ +/** @file signalex_map.h Hides the direct accesses to the map array with map accessors */ + +#ifndef SIGNALEXTENDED_MAP_H +#define SIGNALEXTENDED_MAP_H + +#include "signalex_type.h" +#include "rail_map_base.h" + +/** + * Checks if a rail tile has extended signals. + * @param t the tile to get the information from + * @pre IsTileType(t, MP_RAILWAY) + * @return true if and only if the tile has signals and has extended signals + */ +static inline bool HasExtendedSignals(TileIndex t) +{ + return HasSignals(t) && HasBit(_m[t].m6, 2); +} + +/** + * Add/remove the 'has signal' bit from the RailTileType + * @param tile the tile to add/remove the signals to/from + * @param signals whether the rail tile should have signals or not + * @pre IsPlainRailTile(tile) + */ +static inline void SetHasExtendedSignals(TileIndex t, bool extended) +{ + assert(HasSignals(t)); + SB(_m[t].m6, 2, 1, extended); +} + + +#endif /* SIGNALEXTENDED_MAP_H */ Index: src/signalex_type.h =================================================================== --- src/signalex_type.h (revision 0) +++ src/signalex_type.h (revision 0) @@ -0,0 +1,38 @@ +/** @file signalex_type.h Types related to extended signal information, restrictions and logic. */ + +#ifndef SIGNALEXTENDED_TYPE_H +#define SIGNALEXTENDED_TYPE_H + +typedef uint16 SignalExID; + +struct SignalEx; + +/** + * SignalEx Feature Enums + * defines to check what additional features are + * currently enabled for the individual signals (all 4) + */ +enum SignalExFeature { + SIGEXF_EXTENDED = 1<<0, ///< The signal has extensions + SIGEXF_ASPECTS = 1<<1, ///< Signal can define multi-aspects + SIGEXF_THEATRES = 1<<2, ///< Signal can define theatres/routes + SIGEXF_PROGRAMMED = 1<<3, ///< Signal can be programmed +}; + +/** + * Extension: Multi-Aspect Signal States (place-holder) + * Defines various warning states for signals, which can be different + * to the actual Signal states (at least for now). + */ +enum SignalExAspects{ + SIGEXA_DANGER = 0, ///< Train should not pass + SIGEXA_CAUTION1 = 1, ///< Can pass, next signal is SIGEXT_DANGER + SIGEXA_CAUTION2 = 2, ///< Can pass, next signal is SIGEXT_CAUTION1 + SIGEXA_DIVERGE1 = 3, ///< Can pass, path divergence after next signal + SIGEXA_DIVERGE2 = 4, ///< Can pass, next signal is SIGEXT_DIVERGE1 + SIGEXA_CLEAR = 5, ///< Can pass + SIGEXA_CALLON = 6, ///< Can pass to couple to a consist + SIGEXA_SHUNT = 7, ///< Can pass for shunting +}; + +#endif /* SIGNALEXTENDED_TYPE_H */