(svn r16394) -Codechange: move (NewGRF) cache variables into a separate struct so (some vehicle related) NewGRF cache 'desyncs' can be tested easier.

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
rubidium 15 years ago
parent da5661a0c8
commit 6237fe1462

@ -45,7 +45,7 @@
case VEH_ROAD: { case VEH_ROAD: {
uint total_length = 0; uint total_length = 0;
for (const Vehicle *u = v; u != NULL; u = u->Next()) { for (const Vehicle *u = v; u != NULL; u = u->Next()) {
total_length += ((RoadVehicle*)u)->cached_veh_length; total_length += ((RoadVehicle*)u)->rcache.cached_veh_length;
} }
return total_length; return total_length;
} }

@ -83,6 +83,11 @@ void AircraftNextAirportPos_and_Order(Aircraft *v);
void SetAircraftPosition(Aircraft *v, int x, int y, int z); void SetAircraftPosition(Aircraft *v, int x, int y, int z);
byte GetAircraftFlyingAltitude(const Aircraft *v); byte GetAircraftFlyingAltitude(const Aircraft *v);
/** Cached oftenly queried (NewGRF) values */
struct AircraftCache {
uint16 cached_max_speed; ///< Cached maximum speed of the aircraft.
};
/** /**
* This class 'wraps' Vehicle; you do not actually instantiate this class. * This class 'wraps' Vehicle; you do not actually instantiate this class.
* You create a Vehicle using AllocateVehicle, so it is added to the pool * You create a Vehicle using AllocateVehicle, so it is added to the pool
@ -92,8 +97,9 @@ byte GetAircraftFlyingAltitude(const Aircraft *v);
* As side-effect the vehicle type is set correctly. * As side-effect the vehicle type is set correctly.
*/ */
struct Aircraft : public Vehicle { struct Aircraft : public Vehicle {
AircraftCache acache; ///< Cache of often used calculated values
uint16 crashed_counter; uint16 crashed_counter;
uint16 cached_max_speed;
byte pos; byte pos;
byte previous_pos; byte previous_pos;
StationID targetairport; StationID targetairport;

@ -757,9 +757,9 @@ void UpdateAircraftCache(Aircraft *v)
/* Convert from original units to (approx) km/h */ /* Convert from original units to (approx) km/h */
max_speed = (max_speed * 129) / 10; max_speed = (max_speed * 129) / 10;
v->cached_max_speed = max_speed; v->acache.cached_max_speed = max_speed;
} else { } else {
v->cached_max_speed = 0xFFFF; v->acache.cached_max_speed = 0xFFFF;
} }
} }
@ -791,9 +791,9 @@ static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE,
* and take-off speeds being too low. */ * and take-off speeds being too low. */
speed_limit *= _settings_game.vehicle.plane_speed; speed_limit *= _settings_game.vehicle.plane_speed;
if (v->cached_max_speed < speed_limit) { if (v->acache.cached_max_speed < speed_limit) {
if (v->cur_speed < speed_limit) hard_limit = false; if (v->cur_speed < speed_limit) hard_limit = false;
speed_limit = v->cached_max_speed; speed_limit = v->acache.cached_max_speed;
} }
speed_limit = min(speed_limit, v->max_speed); speed_limit = min(speed_limit, v->max_speed);

@ -334,8 +334,8 @@ void AddArticulatedParts(Vehicle *first, VehicleType type)
RoadVehicle *rv = new RoadVehicle(); RoadVehicle *rv = new RoadVehicle();
rv->subtype = 0; rv->subtype = 0;
previous->SetNext(u); previous->SetNext(u);
rv->first_engine = front->engine_type; rv->rcache.first_engine = front->engine_type;
rv->cached_veh_length = 8; // Callback is called when the consist is finished rv->rcache.cached_veh_length = 8; // Callback is called when the consist is finished
rv->state = RVSB_IN_DEPOT; rv->state = RVSB_IN_DEPOT;
rv->roadtype = front->roadtype; rv->roadtype = front->roadtype;

@ -518,7 +518,7 @@ struct DepotWindow : Window {
break; break;
case VEH_ROAD: case VEH_ROAD:
_cursor.short_vehicle_offset = 16 - ((RoadVehicle *)v)->cached_veh_length * 2; _cursor.short_vehicle_offset = 16 - ((RoadVehicle *)v)->rcache.cached_veh_length * 2;
break; break;
default: default:

@ -122,7 +122,7 @@ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1,
/* Company colour data is indirectly cached. */ /* Company colour data is indirectly cached. */
Vehicle *v; Vehicle *v;
FOR_ALL_VEHICLES(v) { FOR_ALL_VEHICLES(v) {
if (v->owner == _current_company) v->cache_valid = 0; if (v->owner == _current_company) v->vcache.cache_valid = 0;
} }
} }
return CommandCost(); return CommandCost();

@ -436,7 +436,7 @@ static uint8 LiveryHelper(EngineID engine, const Vehicle *v)
} else if (v->type == VEH_TRAIN) { } else if (v->type == VEH_TRAIN) {
l = GetEngineLivery(v->engine_type, v->owner, ((Train *)v)->tcache.first_engine, v); l = GetEngineLivery(v->engine_type, v->owner, ((Train *)v)->tcache.first_engine, v);
} else if (v->type == VEH_ROAD) { } else if (v->type == VEH_ROAD) {
l = GetEngineLivery(v->engine_type, v->owner, ((RoadVehicle *)v)->first_engine, v); l = GetEngineLivery(v->engine_type, v->owner, ((RoadVehicle *)v)->rcache.first_engine, v);
} else { } else {
l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v); l = GetEngineLivery(v->engine_type, v->owner, INVALID_ENGINE, v);
} }
@ -506,21 +506,21 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
return GetEngineGRFID(v->engine_type); return GetEngineGRFID(v->engine_type);
case 0x40: // Get length of consist case 0x40: // Get length of consist
if (!HasBit(v->cache_valid, 0)) { if (!HasBit(v->vcache.cache_valid, 0)) {
v->cached_var40 = PositionHelper(v, false); v->vcache.cached_var40 = PositionHelper(v, false);
SetBit(v->cache_valid, 0); SetBit(v->vcache.cache_valid, 0);
} }
return v->cached_var40; return v->vcache.cached_var40;
case 0x41: // Get length of same consecutive wagons case 0x41: // Get length of same consecutive wagons
if (!HasBit(v->cache_valid, 1)) { if (!HasBit(v->vcache.cache_valid, 1)) {
v->cached_var41 = PositionHelper(v, true); v->vcache.cached_var41 = PositionHelper(v, true);
SetBit(v->cache_valid, 1); SetBit(v->vcache.cache_valid, 1);
} }
return v->cached_var41; return v->vcache.cached_var41;
case 0x42: // Consist cargo information case 0x42: // Consist cargo information
if (!HasBit(v->cache_valid, 2)) { if (!HasBit(v->vcache.cache_valid, 2)) {
const Vehicle *u; const Vehicle *u;
byte cargo_classes = 0; byte cargo_classes = 0;
CargoID common_cargo_best = CT_INVALID; CargoID common_cargo_best = CT_INVALID;
@ -570,17 +570,17 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
} }
uint8 common_bitnum = (common_cargo_type == CT_INVALID ? 0xFF : GetCargo(common_cargo_type)->bitnum); uint8 common_bitnum = (common_cargo_type == CT_INVALID ? 0xFF : GetCargo(common_cargo_type)->bitnum);
v->cached_var42 = cargo_classes | (common_bitnum << 8) | (common_subtype << 16) | (user_def_data << 24); v->vcache.cached_var42 = cargo_classes | (common_bitnum << 8) | (common_subtype << 16) | (user_def_data << 24);
SetBit(v->cache_valid, 2); SetBit(v->vcache.cache_valid, 2);
} }
return v->cached_var42; return v->vcache.cached_var42;
case 0x43: // Company information case 0x43: // Company information
if (!HasBit(v->cache_valid, 3)) { if (!HasBit(v->vcache.cache_valid, 3)) {
v->cached_var43 = v->owner | (Company::Get(v->owner)->is_ai ? 0x10000 : 0) | (LiveryHelper(v->engine_type, v) << 24); v->vcache.cached_var43 = v->owner | (Company::Get(v->owner)->is_ai ? 0x10000 : 0) | (LiveryHelper(v->engine_type, v) << 24);
SetBit(v->cache_valid, 3); SetBit(v->vcache.cache_valid, 3);
} }
return v->cached_var43; return v->vcache.cached_var43;
case 0x44: // Aircraft information case 0x44: // Aircraft information
if (v->type != VEH_AIRCRAFT) return UINT_MAX; if (v->type != VEH_AIRCRAFT) return UINT_MAX;
@ -889,7 +889,7 @@ static const SpriteGroup *GetVehicleSpriteGroup(EngineID engine, const Vehicle *
group = use_cache ? ((Train *)v)->tcache.cached_override : GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, ((Train *)v)->tcache.first_engine); group = use_cache ? ((Train *)v)->tcache.cached_override : GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, ((Train *)v)->tcache.first_engine);
if (group != NULL) return group; if (group != NULL) return group;
} else if (v->type == VEH_ROAD) { } else if (v->type == VEH_ROAD) {
group = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, ((RoadVehicle *)v)->first_engine); group = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, ((RoadVehicle *)v)->rcache.first_engine);
if (group != NULL) return group; if (group != NULL) return group;
} }
} }

@ -1119,8 +1119,11 @@ void StateGameLoop()
switch (v->type) { switch (v->type) {
case VEH_ROAD: { case VEH_ROAD: {
extern byte GetRoadVehLength(const RoadVehicle *v); RoadVehicle *rv = (RoadVehicle *)v;
if (GetRoadVehLength((RoadVehicle *)v) != ((RoadVehicle *)v)->cached_veh_length) { RoadVehicleCache cache = rv->rcache;
RoadVehUpdateCache(rv);
if (memcmp(&cache, &rv->rcache, sizeof(RoadVehicleCache)) != 0) {
DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber); DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
} }
} break; } break;
@ -1149,9 +1152,10 @@ void StateGameLoop()
case VEH_AIRCRAFT: { case VEH_AIRCRAFT: {
Aircraft *a = (Aircraft *)v; Aircraft *a = (Aircraft *)v;
uint speed = a->cached_max_speed; AircraftCache cache = a->acache;
UpdateAircraftCache(a); UpdateAircraftCache(a);
if (speed != a->cached_max_speed) {
if (memcmp(&cache, &a->acache, sizeof(AircraftCache)) != 0) {
DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber); DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i\n", v->index, (int)v->owner, v->unitnumber);
} }
} break; } break;

@ -109,6 +109,11 @@ byte GetRoadVehLength(const RoadVehicle *v);
void RoadVehUpdateCache(RoadVehicle *v); void RoadVehUpdateCache(RoadVehicle *v);
/** Cached oftenly queried (NewGRF) values */
struct RoadVehicleCache {
byte cached_veh_length;
EngineID first_engine;
};
/** /**
* This class 'wraps' Vehicle; you do not actually instantiate this class. * This class 'wraps' Vehicle; you do not actually instantiate this class.
@ -119,6 +124,7 @@ void RoadVehUpdateCache(RoadVehicle *v);
* As side-effect the vehicle type is set correctly. * As side-effect the vehicle type is set correctly.
*/ */
struct RoadVehicle : public Vehicle { struct RoadVehicle : public Vehicle {
RoadVehicleCache rcache; ///< Cache of often used calculated values
byte state; ///< @see RoadVehicleStates byte state; ///< @see RoadVehicleStates
byte frame; byte frame;
uint16 blocked_ctr; uint16 blocked_ctr;
@ -128,8 +134,6 @@ struct RoadVehicle : public Vehicle {
byte reverse_ctr; byte reverse_ctr;
struct RoadStop *slot; struct RoadStop *slot;
byte slot_age; byte slot_age;
EngineID first_engine;
byte cached_veh_length;
RoadType roadtype; RoadType roadtype;
RoadTypes compatible_roadtypes; RoadTypes compatible_roadtypes;

@ -142,10 +142,10 @@ void RoadVehUpdateCache(RoadVehicle *v)
assert(u->First() == v); assert(u->First() == v);
/* Update the 'first engine' */ /* Update the 'first engine' */
u->first_engine = (v == u) ? INVALID_ENGINE : v->engine_type; u->rcache.first_engine = (v == u) ? INVALID_ENGINE : v->engine_type;
/* Update the length of the vehicle. */ /* Update the length of the vehicle. */
u->cached_veh_length = GetRoadVehLength(u); u->rcache.cached_veh_length = GetRoadVehLength(u);
/* Invalidate the vehicle colour map */ /* Invalidate the vehicle colour map */
u->colourmap = PAL_NONE; u->colourmap = PAL_NONE;
@ -244,7 +244,7 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
v->roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; v->roadtype = HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
v->compatible_roadtypes = RoadTypeToRoadTypes(v->roadtype); v->compatible_roadtypes = RoadTypeToRoadTypes(v->roadtype);
v->cached_veh_length = 8; v->rcache.cached_veh_length = 8;
v->vehicle_flags = 0; v->vehicle_flags = 0;
if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
@ -255,7 +255,7 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
/* Call various callbacks after the whole consist has been constructed */ /* Call various callbacks after the whole consist has been constructed */
for (RoadVehicle *u = v; u != NULL; u = u->Next()) { for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
u->cached_veh_length = GetRoadVehLength(u); u->rcache.cached_veh_length = GetRoadVehLength(u);
/* Cargo capacity is zero if and only if the vehicle cannot carry anything */ /* Cargo capacity is zero if and only if the vehicle cannot carry anything */
if (u->cargo_cap != 0) u->cargo_cap = GetVehicleProperty(u, 0x0F, u->cargo_cap); if (u->cargo_cap != 0) u->cargo_cap = GetVehicleProperty(u, 0x0F, u->cargo_cap);
} }
@ -1582,7 +1582,7 @@ again:
* it's on a depot tile, check if it's time to activate the next vehicle in * it's on a depot tile, check if it's time to activate the next vehicle in
* the chain yet. */ * the chain yet. */
if (v->Next() != NULL && IsRoadDepotTile(v->tile)) { if (v->Next() != NULL && IsRoadDepotTile(v->tile)) {
if (v->frame == v->cached_veh_length + RVC_DEPOT_START_FRAME) { if (v->frame == v->rcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
RoadVehLeaveDepot(v->Next(), false); RoadVehLeaveDepot(v->Next(), false);
} }
} }

@ -130,7 +130,7 @@ void DrawRoadVehImage(const Vehicle *v, int x, int y, VehicleID selection, int c
int highlight_w = 0; int highlight_w = 0;
for (int dx = 0; v != NULL && dx < max_length ; v = v->Next()) { for (int dx = 0; v != NULL && dx < max_length ; v = v->Next()) {
int width = ((RoadVehicle *)v)->cached_veh_length; int width = ((RoadVehicle *)v)->rcache.cached_veh_length;
if (dx + width > 0 && dx <= max_length) { if (dx + width > 0 && dx <= max_length) {
SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);

@ -253,7 +253,7 @@ void AfterLoadVehicles(bool part_of_load)
if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID; if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID;
v->first = NULL; v->first = NULL;
if (v->type == VEH_TRAIN) ((Train *)v)->tcache.first_engine = INVALID_ENGINE; if (v->type == VEH_TRAIN) ((Train *)v)->tcache.first_engine = INVALID_ENGINE;
if (v->type == VEH_ROAD) ((RoadVehicle *)v)->first_engine = INVALID_ENGINE; if (v->type == VEH_ROAD) ((RoadVehicle *)v)->rcache.first_engine = INVALID_ENGINE;
v->cargo.InvalidateCache(); v->cargo.InvalidateCache();
} }

@ -241,13 +241,13 @@ void TrainConsistChanged(Train *v, bool same_length)
/* Set user defined data to its default value */ /* Set user defined data to its default value */
u->tcache.user_def_data = rvi_u->user_def_data; u->tcache.user_def_data = rvi_u->user_def_data;
u->cache_valid = 0; u->vcache.cache_valid = 0;
} }
for (Train *u = v; u != NULL; u = u->Next()) { for (Train *u = v; u != NULL; u = u->Next()) {
/* Update user defined data (must be done before other properties) */ /* Update user defined data (must be done before other properties) */
u->tcache.user_def_data = GetVehicleProperty(u, 0x25, u->tcache.user_def_data); u->tcache.user_def_data = GetVehicleProperty(u, 0x25, u->tcache.user_def_data);
u->cache_valid = 0; u->vcache.cache_valid = 0;
} }
for (Train *u = v; u != NULL; u = u->Next()) { for (Train *u = v; u != NULL; u = u->Next()) {
@ -333,7 +333,7 @@ void TrainConsistChanged(Train *v, bool same_length)
if (!same_length) u->tcache.cached_veh_length = veh_len; if (!same_length) u->tcache.cached_veh_length = veh_len;
v->tcache.cached_total_length += u->tcache.cached_veh_length; v->tcache.cached_total_length += u->tcache.cached_veh_length;
u->cache_valid = 0; u->vcache.cache_valid = 0;
} }
/* store consist weight/max speed in cache */ /* store consist weight/max speed in cache */

@ -1426,7 +1426,7 @@ SpriteID GetVehiclePalette(const Vehicle *v)
if (v->type == VEH_TRAIN) { if (v->type == VEH_TRAIN) {
return GetEngineColourMap(v->engine_type, v->owner, ((Train *)v)->tcache.first_engine, v); return GetEngineColourMap(v->engine_type, v->owner, ((Train *)v)->tcache.first_engine, v);
} else if (v->type == VEH_ROAD) { } else if (v->type == VEH_ROAD) {
return GetEngineColourMap(v->engine_type, v->owner, ((RoadVehicle *)v)->first_engine, v); return GetEngineColourMap(v->engine_type, v->owner, ((RoadVehicle *)v)->rcache.first_engine, v);
} }
return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v); return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);

@ -43,6 +43,15 @@ enum VehicleFlags {
VF_AUTOFILL_PRES_WAIT_TIME, ///< Whether non-destructive auto-fill should preserve waiting times VF_AUTOFILL_PRES_WAIT_TIME, ///< Whether non-destructive auto-fill should preserve waiting times
}; };
/** Cached oftenly queried (NewGRF) values */
struct VehicleCache {
uint8 cache_valid; ///< Whether the caches are valid
uint32 cached_var40; ///< Cache for NewGRF var 40
uint32 cached_var41; ///< Cache for NewGRF var 41
uint32 cached_var42; ///< Cache for NewGRF var 42
uint32 cached_var43; ///< Cache for NewGRF var 43
};
typedef Pool<Vehicle, VehicleID, 512, 64000> VehiclePool; typedef Pool<Vehicle, VehicleID, 512, 64000> VehiclePool;
extern VehiclePool _vehicle_pool; extern VehiclePool _vehicle_pool;
@ -170,12 +179,7 @@ public:
byte subtype; ///< subtype (Filled with values from EffectVehicles/TrainSubTypes/AircraftSubTypes) byte subtype; ///< subtype (Filled with values from EffectVehicles/TrainSubTypes/AircraftSubTypes)
/* cached oftenly queried NewGRF values */ VehicleCache vcache; ///< Cache of often used calculated values
uint8 cache_valid; ///< Whether the caches are valid
uint32 cached_var40; ///< Cache for NewGRF var 40
uint32 cached_var41; ///< Cache for NewGRF var 41
uint32 cached_var42; ///< Cache for NewGRF var 42
uint32 cached_var43; ///< Cache for NewGRF var 43
/** Create a new vehicle */ /** Create a new vehicle */
Vehicle(); Vehicle();

@ -641,8 +641,8 @@ static int CDECL VehicleLengthSorter(const Vehicle * const *a, const Vehicle * c
case VEH_ROAD: { case VEH_ROAD: {
const RoadVehicle *u; const RoadVehicle *u;
for (u = (RoadVehicle *)*a; u != NULL; u = u->Next()) r += u->cached_veh_length; for (u = (RoadVehicle *)*a; u != NULL; u = u->Next()) r += u->rcache.cached_veh_length;
for (u = (RoadVehicle *)*b; u != NULL; u = u->Next()) r -= u->cached_veh_length; for (u = (RoadVehicle *)*b; u != NULL; u = u->Next()) r -= u->rcache.cached_veh_length;
} break; } break;
default: NOT_REACHED(); default: NOT_REACHED();

Loading…
Cancel
Save