diff --git a/src/cmd_helper.h b/src/cmd_helper.h index 1530beedb2..0b56fb7670 100644 --- a/src/cmd_helper.h +++ b/src/cmd_helper.h @@ -20,7 +20,8 @@ template static inline T Extract(U v) assert_tcompile(N == EnumPropsT::num_bits); assert_tcompile(S + N <= sizeof(U) * 8); assert_tcompile(EnumPropsT::end <= (1 << N)); - return (T)GB(v, S, N); + U masked = GB(v, S, N); + return IsInsideMM(masked, EnumPropsT::begin, EnumPropsT::end) ? (T)masked : EnumPropsT::invalid; } #endif diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index f738f07e08..93178dd804 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -15,6 +15,7 @@ #include "company_gui.h" #include "town.h" #include "news_func.h" +#include "cmd_helper.h" #include "command_func.h" #include "network/network.h" #include "network/network_func.h" @@ -898,14 +899,11 @@ CommandCost CmdSetCompanyManagerFace(TileIndex tile, DoCommandFlag flags, uint32 */ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - if (p2 >= 16) return CMD_ERROR; // max 16 colours - - Colours colour = (Colours)p2; - - LiveryScheme scheme = (LiveryScheme)GB(p1, 0, 8); + Colours colour = Extract(p2); + LiveryScheme scheme = Extract(p1); byte state = GB(p1, 8, 2); - if (scheme >= LS_END || state >= 3) return CMD_ERROR; + if (scheme >= LS_END || state >= 3 || colour == INVALID_COLOUR) return CMD_ERROR; Company *c = Company::Get(_current_company); diff --git a/src/gfx_type.h b/src/gfx_type.h index 8bb9c3ff47..167488766e 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -196,6 +196,7 @@ enum Colours { COLOUR_END, INVALID_COLOUR = 0xFF, }; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** Colour of the strings, see _string_colourmap in table/palettes.h or docs/ottd-colourtext-palette.png */ enum TextColour { diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index a8475a18ff..6585d5084a 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -10,6 +10,7 @@ /** @file group_cmd.cpp Handling of the engine groups */ #include "stdafx.h" +#include "cmd_helper.h" #include "command_func.h" #include "group.h" #include "train.h" @@ -82,7 +83,7 @@ void InitializeGroup() */ CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - VehicleType vt = (VehicleType)p1; + VehicleType vt = Extract(p1); if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR; if (!Group::CanAllocateItem()) return CMD_ERROR; @@ -258,13 +259,12 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - VehicleType type = (VehicleType)p2; - if (!Group::IsValidID(p1) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR; + VehicleType type = Extract(p2); + GroupID id_g = p1; + if (!Group::IsValidID(id_g) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR; if (flags & DC_EXEC) { Vehicle *v; - VehicleType type = (VehicleType)p2; - GroupID id_g = p1; /* Find the first front engine which belong to the group id_g * then add all shared vehicles of this front engine to the group id_g */ @@ -298,13 +298,13 @@ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 */ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Group *g = Group::GetIfValid(p1); - VehicleType type = (VehicleType)p2; + GroupID old_g = p1; + Group *g = Group::GetIfValid(old_g); + VehicleType type = Extract(p2); if (g == NULL || g->owner != _current_company || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR; if (flags & DC_EXEC) { - GroupID old_g = p1; Vehicle *v; /* Find each Vehicle that belongs to the group old_g and add it to the default group */ diff --git a/src/livery.h b/src/livery.h index 79309d517a..d34e4c47e3 100644 --- a/src/livery.h +++ b/src/livery.h @@ -55,6 +55,7 @@ enum LiveryScheme { }; DECLARE_POSTFIX_INCREMENT(LiveryScheme) +template <> struct EnumPropsT : MakeEnumPropsT {}; /* List of different livery classes, used only by the livery GUI. */ enum LiveryClass { diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 0ccf0924f7..9d803b7dff 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -27,6 +27,7 @@ enum StationClassID { STAT_CLASS_MAX = 32, ///< Maximum number of classes. }; typedef SimpleTinyEnumT StationClassIDByte; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** Allow incrementing of StationClassID variables */ DECLARE_POSTFIX_INCREMENT(StationClassID) diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 7bbcbb86b0..5f0fe41490 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" #include "debug.h" +#include "cmd_helper.h" #include "command_func.h" #include "company_func.h" #include "news_func.h" @@ -933,8 +934,8 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 { VehicleOrderID sel_ord = GB(p1, 16, 16); // XXX - automatically truncated to 8 bits. VehicleID veh = GB(p1, 0, 16); - ModifyOrderFlags mof = (ModifyOrderFlags)GB(p2, 0, 4); - uint16 data = GB(p2, 4, 11); + ModifyOrderFlags mof = Extract(p2); + uint16 data = GB(p2, 4, 11); if (mof >= MOF_END) return CMD_ERROR; diff --git a/src/order_type.h b/src/order_type.h index 8c66d22961..757603fcb8 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -149,6 +149,7 @@ enum ModifyOrderFlags { MOF_COND_DESTINATION,///< Change the destination of a conditional order. MOF_END }; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** * Depot action to switch to when doing a MOF_DEPOT_ACTION. diff --git a/src/rail.cpp b/src/rail.cpp index 663753e9f3..21ae806614 100644 --- a/src/rail.cpp +++ b/src/rail.cpp @@ -181,7 +181,7 @@ bool HasRailtypeAvail(const CompanyID company, const RailType railtype) bool ValParamRailtype(const RailType rail) { - return HasRailtypeAvail(_current_company, rail); + return rail < RAILTYPE_END && HasRailtypeAvail(_current_company, rail); } RailType GetBestRailtype(const CompanyID company) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index f90be41257..de9b2543d6 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -358,8 +358,8 @@ static inline bool ValParamTrackOrientation(Track track) */ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - RailType railtype = (RailType)p1; - Track track = (Track)p2; + RailType railtype = Extract(p1); + Track track = Extract(p2); CommandCost cost(EXPENSES_CONSTRUCTION); if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; @@ -499,11 +499,11 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Track track = (Track)p2; + Track track = Extract(p2); CommandCost cost(EXPENSES_CONSTRUCTION); bool crossing = false; - if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; + if (!ValParamTrackOrientation(track)) return CMD_ERROR; TrackBits trackbit = TrackToTrackBits(track); /* Need to read tile owner now because it may change when the rail is removed @@ -741,9 +741,9 @@ static CommandCost ValidateAutoDrag(Trackdir *trackdir, TileIndex start, TileInd static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { CommandCost total_cost(EXPENSES_CONSTRUCTION); - Track track = (Track)GB(p2, 4, 3); + Track track = Extract(p2); bool remove = HasBit(p2, 7); - RailType railtype = (RailType)GB(p2, 0, 4); + RailType railtype = Extract(p2); if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; if (p1 >= MapSize()) return CMD_ERROR; @@ -833,7 +833,8 @@ CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* check railtype and valid direction for depot (0 through 3), 4 in total */ - if (!ValParamRailtype((RailType)p1)) return CMD_ERROR; + RailType railtype = Extract(p1); + if (!ValParamRailtype(railtype)) return CMD_ERROR; Slope tileh = GetTileSlope(tile, NULL); @@ -865,7 +866,7 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u Depot *d = new Depot(tile); d->town_index = ClosestTownFromTile(tile, UINT_MAX)->index; - MakeRailDepot(tile, _current_company, d->index, dir, (RailType)p1); + MakeRailDepot(tile, _current_company, d->index, dir, railtype); MarkTileDirtyByTile(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_company); @@ -898,16 +899,17 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Track track = (Track)GB(p1, 0, 3); + Track track = Extract(p1); bool ctrl_pressed = HasBit(p1, 3); // was the CTRL button pressed SignalVariant sigvar = (ctrl_pressed ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; // the signal variant of the new signal - SignalType sigtype = (SignalType)GB(p1, 5, 3); // the signal type of the new signal + SignalType sigtype = Extract(p1); // the signal type of the new signal bool convert_signal = HasBit(p1, 8); // convert button pressed - SignalType cycle_start = (SignalType)GB(p1, 9, 3); - SignalType cycle_stop = (SignalType)GB(p1, 12, 3); + SignalType cycle_start = Extract(p1); + SignalType cycle_stop = Extract(p1); uint num_dir_cycle = GB(p1, 15, 2); if (sigtype > SIGTYPE_LAST) return CMD_ERROR; + if (cycle_start > cycle_stop || cycle_stop > SIGTYPE_LAST) return CMD_ERROR; /* You can only build signals on plain rail tiles, and the selected track must exist */ if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || @@ -1127,15 +1129,14 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin CommandCost total_cost(EXPENSES_CONSTRUCTION); TileIndex start_tile = tile; - Track track = (Track)GB(p2, 0, 3); + Track track = Extract(p2); bool mode = HasBit(p2, 3); bool semaphores = HasBit(p2, 4); bool remove = HasBit(p2, 5); bool autofill = HasBit(p2, 6); - Trackdir trackdir = TrackToTrackdir(track); byte signal_density = GB(p2, 24, 8); - if (p1 >= MapSize()) return CMD_ERROR; + if (p1 >= MapSize() || !ValParamTrackOrientation(track)) return CMD_ERROR; TileIndex end_tile = p1; if (signal_density == 0 || signal_density > 20) return CMD_ERROR; @@ -1145,6 +1146,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin * since the original amount will be too dense (shorter tracks) */ signal_density *= 2; + Trackdir trackdir = TrackToTrackdir(track); CommandCost ret = ValidateAutoDrag(&trackdir, tile, end_tile); if (ret.Failed()) return ret; @@ -1271,7 +1273,7 @@ CommandCost CmdBuildSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, */ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Track track = (Track)GB(p1, 0, 3); + Track track = Extract(p1); if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || @@ -1374,7 +1376,7 @@ static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data) */ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - RailType totype = (RailType)p2; + RailType totype = Extract(p2); if (!ValParamRailtype(totype)) return CMD_ERROR; if (p1 >= MapSize()) return CMD_ERROR; diff --git a/src/rail_type.h b/src/rail_type.h index 9b0b34e4b0..e93fd9f0fd 100644 --- a/src/rail_type.h +++ b/src/rail_type.h @@ -43,7 +43,7 @@ enum RailType { /** Allow incrementing of Track variables */ DECLARE_POSTFIX_INCREMENT(RailType) /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT RailTypeByte; /** diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 8f3832dc6e..10b9027142 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -469,10 +469,10 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 /* do not allow building 'zero' road bits, code wouldn't handle it */ if (pieces == ROAD_NONE) return CMD_ERROR; - RoadType rt = (RoadType)GB(p1, 4, 2); + RoadType rt = Extract(p1); if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; - DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2); + DisallowedRoadDirections toggle_drd = Extract(p1); Slope tileh = GetTileSlope(tile, NULL); @@ -726,7 +726,7 @@ CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p if (p1 >= MapSize()) return CMD_ERROR; TileIndex end_tile = p1; - RoadType rt = (RoadType)GB(p2, 3, 2); + RoadType rt = Extract(p2); if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; Axis axis = Extract(p2); @@ -818,7 +818,7 @@ CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 if (p1 >= MapSize()) return CMD_ERROR; TileIndex end_tile = p1; - RoadType rt = (RoadType)GB(p2, 3, 2); + RoadType rt = Extract(p2); if (!IsValidRoadType(rt)) return CMD_ERROR; Axis axis = Extract(p2); @@ -887,7 +887,7 @@ CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { DiagDirection dir = Extract(p1); - RoadType rt = (RoadType)GB(p1, 2, 2); + RoadType rt = Extract(p1); if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; diff --git a/src/road_map.h b/src/road_map.h index e5e738cb4b..ad5a1de4a9 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -168,6 +168,7 @@ enum DisallowedRoadDirections { DRD_END }; DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections) +template <> struct EnumPropsT : MakeEnumPropsT {}; /** * Gets the disallowed directions diff --git a/src/road_type.h b/src/road_type.h index be16c23152..7a3a2f9ae5 100644 --- a/src/road_type.h +++ b/src/road_type.h @@ -27,7 +27,7 @@ enum RoadType { INVALID_ROADTYPE = 0xFF ///< flag for invalid roadtype }; DECLARE_POSTFIX_INCREMENT(RoadType) -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** * The different roadtypes we support, but then a bitmask of them @@ -42,6 +42,7 @@ enum RoadTypes { INVALID_ROADTYPES = 0xFF ///< Invalid roadtypes }; DECLARE_ENUM_AS_BIT_SET(RoadTypes) +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef SimpleTinyEnumT RoadTypesByte; diff --git a/src/signal_type.h b/src/signal_type.h index 8c9c4bcfc2..5a8d564d2a 100644 --- a/src/signal_type.h +++ b/src/signal_type.h @@ -27,9 +27,12 @@ enum SignalType { SIGTYPE_COMBO = 3, ///< presignal inter-block SIGTYPE_PBS = 4, ///< normal pbs signal SIGTYPE_PBS_ONEWAY = 5, ///< no-entry signal + + SIGTYPE_END, SIGTYPE_LAST = SIGTYPE_PBS_ONEWAY, SIGTYPE_LAST_NOPBS = SIGTYPE_COMBO }; +template <> struct EnumPropsT : MakeEnumPropsT {}; #endif /* SIGNAL_TYPE_H */ diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 060b66bf61..13d16f962e 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1095,13 +1095,13 @@ CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* Unpack parameters */ - RailType rt = (RailType)GB(p1, 0, 4); + RailType rt = Extract(p1); Axis axis = Extract(p1); byte numtracks = GB(p1, 8, 8); byte plat_len = GB(p1, 16, 8); bool adjacent = HasBit(p1, 24); - StationClassID spec_class = (StationClassID)GB(p2, 0, 8); + StationClassID spec_class = Extract(p2); byte spec_index = GB(p2, 8, 8); StationID station_to_join = GB(p2, 16, 16); @@ -1112,7 +1112,7 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 if (!ValParamRailtype(rt)) return CMD_ERROR; /* Check if the given station class is valid */ - if ((uint)spec_class >= GetNumStationClasses()) return CMD_ERROR; + if ((uint)spec_class >= GetNumStationClasses() || spec_class == STAT_CLASS_WAYP) return CMD_ERROR; if (spec_index >= GetNumCustomStations(spec_class)) return CMD_ERROR; if (plat_len == 0 || numtracks == 0) return CMD_ERROR; @@ -1675,7 +1675,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin { bool type = HasBit(p2, 0); bool is_drive_through = HasBit(p2, 1); - RoadTypes rts = (RoadTypes)GB(p2, 2, 2); + RoadTypes rts = Extract(p2); StationID station_to_join = GB(p2, 16, 16); bool reuse = (station_to_join != NEW_STATION); if (!reuse) station_to_join = INVALID_STATION; @@ -1702,7 +1702,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Trams only have drive through stops */ if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR; - DiagDirection ddir = (DiagDirection)GB(p2, 6, 2); + DiagDirection ddir = Extract(p2); /* Safeguard the parameters. */ if (!IsValidDiagDirection(ddir)) return CMD_ERROR; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index c4f10b072b..a772030140 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -14,6 +14,7 @@ #include "road_cmd.h" #include "landscape.h" #include "viewport_func.h" +#include "cmd_helper.h" #include "command_func.h" #include "industry.h" #include "station_base.h" @@ -1518,9 +1519,9 @@ static bool IsUniqueTownName(const char *name) */ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - TownSize size = (TownSize)GB(p1, 0, 2); + TownSize size = Extract(p1); bool city = HasBit(p1, 2); - TownLayout layout = (TownLayout)GB(p1, 3, 3); + TownLayout layout = Extract(p1); TownNameParams par(_settings_game.game_creation.town_name); bool random = HasBit(p1, 6); uint32 townnameparts = p2; diff --git a/src/town_type.h b/src/town_type.h index 320653011c..93dcc1a3af 100644 --- a/src/town_type.h +++ b/src/town_type.h @@ -26,6 +26,7 @@ enum TownSize { TSZ_END, ///< Number of available town sizes. }; +template <> struct EnumPropsT : MakeEnumPropsT {}; enum { /* These refer to the maximums, so Appalling is -1000 to -400 @@ -89,6 +90,7 @@ enum TownLayout { NUM_TLS, ///< Number of town layouts }; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** It needs to be 8bits, because we save and load it as such */ typedef SimpleTinyEnumT TownLayoutByte; // typedefing-enumification of TownLayout diff --git a/src/transport_type.h b/src/transport_type.h index 71b452b5f5..65af9c75b3 100644 --- a/src/transport_type.h +++ b/src/transport_type.h @@ -30,5 +30,6 @@ enum TransportType { TRANSPORT_END, INVALID_TRANSPORT = 0xff, }; +template <> struct EnumPropsT : MakeEnumPropsT {}; #endif /* TRANSPORT_TYPE_H */ diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index aaa8b7e7f3..4e1d763fd8 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -17,6 +17,7 @@ #include "landscape.h" #include "unmovable_map.h" #include "viewport_func.h" +#include "cmd_helper.h" #include "command_func.h" #include "town.h" #include "variables.h" @@ -194,7 +195,7 @@ CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoC * @param p1 packed start tile coords (~ dx) * @param p2 various bitstuffed elements * - p2 = (bit 0- 7) - bridge type (hi bh) - * - p2 = (bit 8-14) - rail type or road types. + * - p2 = (bit 8-11) - rail type or road types. * - p2 = (bit 15-16) - transport type. * @param text unused * @return the cost of this operation or an error @@ -209,17 +210,17 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u if (p1 >= MapSize()) return CMD_ERROR; - TransportType transport_type = (TransportType)GB(p2, 15, 2); + TransportType transport_type = Extract(p2); /* type of bridge */ switch (transport_type) { case TRANSPORT_ROAD: - roadtypes = (RoadTypes)GB(p2, 8, 2); + roadtypes = Extract(p2); if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR; break; case TRANSPORT_RAIL: - railtype = (RailType)GB(p2, 8, 7); + railtype = Extract(p2); if (!ValParamRailtype(railtype)) return CMD_ERROR; break; @@ -490,19 +491,19 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - TransportType transport_type = (TransportType)GB(p1, 8, 2); + TransportType transport_type = Extract(p1); RailType railtype = INVALID_RAILTYPE; RoadTypes rts = ROADTYPES_NONE; _build_tunnel_endtile = 0; switch (transport_type) { case TRANSPORT_RAIL: - railtype = (RailType)GB(p1, 0, 4); + railtype = Extract(p1); if (!ValParamRailtype(railtype)) return CMD_ERROR; break; case TRANSPORT_ROAD: - rts = (RoadTypes)GB(p1, 0, 2); + rts = Extract(p1); if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR; break; diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 892d05c524..1d3963162a 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -13,6 +13,7 @@ #include "roadveh.h" #include "news_func.h" #include "airport.h" +#include "cmd_helper.h" #include "command_func.h" #include "company_func.h" #include "vehicle_gui.h" @@ -126,17 +127,19 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, * - bit 0-4 Vehicle type * - bit 5 false = start vehicles, true = stop vehicles * - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case - * - bit 8-11 Vehicle List Window type (ignored unless bit 1 is set) + * - bit 8-11 Vehicle List Window type (ignored unless bit 6 is set) * @param text unused * @return the cost of this operation or an error */ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; - VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5); + VehicleType vehicle_type = Extract(p2); bool start_stop = HasBit(p2, 5); bool vehicle_list_window = HasBit(p2, 6); + if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; + if (vehicle_list_window) { uint32 id = p1; uint16 window_type = p2 & VLW_MASK; @@ -180,9 +183,11 @@ CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 VehicleList list; CommandCost cost(EXPENSES_NEW_VEHICLES); - VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); + VehicleType vehicle_type = Extract(p1); uint sell_command = GetCmdSellVeh(vehicle_type); + if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; + /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, &list); @@ -214,8 +219,9 @@ CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 { VehicleList list; CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES); - VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); + VehicleType vehicle_type = Extract(p1); + if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; /* Get the list of vehicles in the depot */ diff --git a/src/vehicle_type.h b/src/vehicle_type.h index 900d54f99a..9ebe5ed697 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -28,6 +28,7 @@ enum VehicleType { VEH_INVALID = 0xFF, ///< Non-existing type of vehicle. }; DECLARE_POSTFIX_INCREMENT(VehicleType) +template <> struct EnumPropsT : MakeEnumPropsT {}; /** It needs to be 8bits, because we save and load it as such */ typedef SimpleTinyEnumT VehicleTypeByte; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 4b80d0cd4e..805f46d29c 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -291,7 +291,7 @@ CommandCost CmdBuildLock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 */ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - if (p1 >= MapSize()) return CMD_ERROR; + if (p1 >= MapSize() || p2 > 2) return CMD_ERROR; /* Outside of the editor you can only build canals, not oceans */ if (p2 != 0 && _game_mode != GM_EDITOR) return CMD_ERROR; diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 8771f27aaa..5e8ce29bde 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" +#include "cmd_helper.h" #include "command_func.h" #include "landscape.h" #include "bridge_map.h" @@ -215,12 +216,12 @@ extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* Unpack parameters */ - Axis axis = (Axis)GB(p1, 4, 1); + Axis axis = Extract(p1); byte width = GB(p1, 8, 8); byte height = GB(p1, 16, 8); bool adjacent = HasBit(p1, 24); - StationClassID spec_class = (StationClassID)GB(p2, 0, 8); + StationClassID spec_class = Extract(p2); byte spec_index = GB(p2, 8, 8); StationID station_to_join = GB(p2, 16, 16);