# HG changeset patch # User peter1138 # Date 1172182191 0 # Node ID 5cf0c6849eee16d7141198f251dc4f2674f28375 # Parent c1f929f6b1a5d81204cbb8ed2cefc3f4c635a99c (svn r8849) -Codechange: Replace hardcoded global/climate cargo mapping tables with dynamically generated data. Change associated code to use new functions. diff --git a/projects/openttd.vcproj b/projects/openttd.vcproj --- a/projects/openttd.vcproj +++ b/projects/openttd.vcproj @@ -914,9 +914,6 @@ RelativePath=".\..\src\newgrf.cpp"> - - - - diff --git a/source.list b/source.list --- a/source.list +++ b/source.list @@ -275,7 +275,6 @@ # NewGRF newgrf.cpp -newgrf_cargo.cpp newgrf_config.cpp newgrf_engine.cpp newgrf_sound.cpp diff --git a/src/cargotype.cpp b/src/cargotype.cpp --- a/src/cargotype.cpp +++ b/src/cargotype.cpp @@ -14,6 +14,12 @@ static const byte INVALID_CARGO = 0xFF; +/* Quick mapping from cargo type 'bitnums' to real cargo IDs */ +static CargoID _cargo_bitnum_map[32]; + +/* Bitmask of cargo type 'bitnums' availabe */ +uint32 _cargo_mask; + void SetupCargoForClimate(LandscapeID l) { @@ -23,6 +29,9 @@ memset(_cargo, 0, sizeof(_cargo)); for (CargoID i = 0; i < lengthof(_cargo); i++) _cargo[i].bitnum = INVALID_CARGO; + memset(_cargo_bitnum_map, CT_INVALID, sizeof(_cargo_bitnum_map)); + _cargo_mask = 0; + for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) { CargoLabel cl = _default_climate_cargo[l][i]; @@ -31,6 +40,13 @@ for (uint j = 0; j < lengthof(_default_cargo); j++) { if (_default_cargo[j].label == cl) { _cargo[i] = _default_cargo[j]; + + /* Populate the bitnum map and masks */ + byte bitnum = _cargo[i].bitnum; + if (bitnum < lengthof(_cargo_bitnum_map)) { + _cargo_bitnum_map[bitnum] = i; + SETBIT(_cargo_mask, bitnum); + } break; } } @@ -44,3 +60,10 @@ return &_cargo[c]; } + +CargoID GetCargoIDByBitnum(byte bitnum) +{ + assert(bitnum < lengthof(_cargo_bitnum_map)); + assert(_cargo_bitnum_map[bitnum] != CT_INVALID); + return _cargo_bitnum_map[bitnum]; +} diff --git a/src/cargotype.h b/src/cargotype.h --- a/src/cargotype.h +++ b/src/cargotype.h @@ -34,9 +34,15 @@ } CargoSpec; +extern uint32 _cargo_mask; + + /* Set up the default cargo types for the given landscape type */ void SetupCargoForClimate(LandscapeID l); /* Retrieve cargo details for the given cargo ID */ const CargoSpec *GetCargo(CargoID c); +/* Get the cargo ID of a cargo bitnum */ +CargoID GetCargoIDByBitnum(byte bitnum); + #endif /* CARGOTYPE_H */ diff --git a/src/newgrf.cpp b/src/newgrf.cpp --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -3658,9 +3658,10 @@ if (cargo_allowed[engine] != 0) { // Build up the list of cargo types from the set cargo classes. - for (i = 0; i < lengthof(cargo_classes); i++) { - if (HASBIT(cargo_allowed[engine], i)) mask |= cargo_classes[i]; - if (HASBIT(cargo_disallowed[engine], i)) not_mask |= cargo_classes[i]; + for (i = 0; i < NUM_CARGO; i++) { + const CargoSpec *cs = GetCargo(i); + if (cargo_allowed[engine] & cs->classes) SETBIT(mask, cs->bitnum); + if (cargo_disallowed[engine] & cs->classes) SETBIT(not_mask, cs->bitnum); } } else { // Don't apply default refit mask to wagons or engines with no capacity @@ -3673,7 +3674,7 @@ xor_mask = _default_refitmasks[GetEngine(engine)->type]; } } - _engine_info[engine].refit_mask = ((mask & ~not_mask) ^ xor_mask) & _landscape_global_cargo_mask[_opt.landscape]; + _engine_info[engine].refit_mask = ((mask & ~not_mask) ^ xor_mask) & _cargo_mask; } } diff --git a/src/newgrf_cargo.cpp b/src/newgrf_cargo.cpp deleted file mode 100644 --- a/src/newgrf_cargo.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* $Id$ */ - -#include "stdafx.h" -#include "openttd.h" -#include "newgrf_cargo.h" - -/** TRANSLATE FROM LOCAL CARGO TO GLOBAL CARGO ID'S. - * This maps the per-landscape cargo ID's to globally unique cargo ID's usable ie. in - * the custom GRF files. It is basically just a transcribed table from TTDPatch's newgrf.txt. - */ -const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO] = { - /* LT_NORMAL */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_IRON_ORE, GC_STEEL, GC_VALUABLES, GC_PAPER_TEMP}, - /* LT_HILLY */ {GC_PASSENGERS, GC_COAL, GC_MAIL, GC_OIL, GC_LIVESTOCK, GC_GOODS, GC_GRAIN, GC_WOOD, GC_INVALID, GC_PAPER, GC_VALUABLES, GC_FOOD }, - /* LT_DESERT */ {GC_PASSENGERS, GC_RUBBER, GC_MAIL, GC_OIL, GC_FRUIT, GC_GOODS, GC_GRAIN, GC_WOOD, GC_COPPER_ORE, GC_WATER, GC_VALUABLES, GC_FOOD }, - /* LT_CANDY */ {GC_PASSENGERS, GC_SUGAR, GC_MAIL, GC_TOYS, GC_BATTERIES, GC_CANDY, GC_TOFFEE, GC_COLA, GC_COTTON_CANDY, GC_BUBBLES, GC_PLASTIC, GC_FIZZY_DRINKS }, - /** - * - GC_INVALID (255) means that cargo is not available for that climate - * - GC_PAPER_TEMP (27) is paper in temperate climate in TTDPatch - * Following can be renumbered: - * - GC_DEFAULT (29) is the defa ult cargo for the purpose of spritesets - * - GC_PURCHASE (30) is the purchase list image (the equivalent of 0xff) for the purpose of spritesets - */ -}; - -/** BEGIN --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/ -/** Map global cargo ID's to local-cargo ID's */ -const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID] = { - CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, /* 0- 7 */ - CT_IRON_ORE, CT_STEEL, CT_VALUABLES, CT_PAPER, CT_FOOD, CT_FRUIT, CT_COPPER_ORE, CT_WATER, /* 8-15 */ - CT_RUBBER, CT_SUGAR, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, /* 16-23 */ - CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, CT_PAPER /* unsup. */, CT_HILLY_UNUSED, /* 24-28 */ - CT_INVALID, CT_INVALID /* 29-30 */ -}; - -/** Bitmasked value where the global cargo ID is available in landscape - * 0: LT_NORMAL, 1: LT_HILLY, 2: LT_DESERT, 3: LT_CANDY */ -#define MC(cargo) (1 << cargo) -const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE] = -{ /* LT_NORMAL: temperate */ - MC(GC_PASSENGERS) | MC(GC_COAL) | MC(GC_MAIL) | MC(GC_OIL) | MC(GC_LIVESTOCK) | MC(GC_GOODS) | MC(GC_GRAIN) | MC(GC_WOOD) | MC(GC_IRON_ORE) | MC(GC_STEEL) | MC(GC_VALUABLES), - /* LT_HILLY: arctic */ - MC(GC_PASSENGERS) | MC(GC_COAL) | MC(GC_MAIL) | MC(GC_OIL) | MC(GC_LIVESTOCK) | MC(GC_GOODS) | MC(GC_GRAIN) | MC(GC_WOOD) | MC(GC_VALUABLES) | MC(GC_PAPER) | MC(GC_FOOD), - /* LT_DESERT: rainforest/desert */ - MC(GC_PASSENGERS) | MC(GC_MAIL) | MC(GC_OIL) | MC(GC_GOODS) | MC(GC_GRAIN) | MC(GC_WOOD) | MC(GC_VALUABLES) | MC(GC_FOOD) | MC(GC_FRUIT) | MC(GC_COPPER_ORE) | MC(GC_WATER) | MC(GC_RUBBER), - /* LT_CANDY: toyland */ - MC(GC_PASSENGERS) | MC(GC_MAIL) | MC(GC_SUGAR) | MC(GC_TOYS) | MC(GC_BATTERIES) | MC(GC_CANDY) | MC(GC_TOFFEE) | MC(GC_COLA) | MC(GC_COTTON_CANDY) | MC(GC_BUBBLES) | MC(GC_PLASTIC) | MC(GC_FIZZY_DRINKS) -}; -/** END --- TRANSLATE FROM GLOBAL CARGO TO LOCAL CARGO ID'S **/ - -/** - * Bitmask of classes for cargo types. - */ -const uint32 cargo_classes[16] = { - /* Passengers */ MC(GC_PASSENGERS), - /* Mail */ MC(GC_MAIL), - /* Express */ MC(GC_GOODS) | MC(GC_FOOD) | MC(GC_CANDY), - /* Armoured */ MC(GC_VALUABLES), - /* Bulk */ MC(GC_COAL) | MC(GC_GRAIN) | MC(GC_IRON_ORE) | MC(GC_COPPER_ORE) | MC(GC_FRUIT) | MC(GC_SUGAR) | MC(GC_TOFFEE) | MC(GC_COTTON_CANDY), - /* Piece */ MC(GC_LIVESTOCK) | MC(GC_WOOD) | MC(GC_STEEL) | MC(GC_PAPER) | MC(GC_TOYS) | MC(GC_BATTERIES) | MC(GC_BUBBLES) | MC(GC_FIZZY_DRINKS), - /* Liquids */ MC(GC_OIL) | MC(GC_WATER) | MC(GC_RUBBER) | MC(GC_COLA) | MC(GC_PLASTIC), - /* Chilled */ MC(GC_FOOD) | MC(GC_FRUIT), - /* Undefined */ 0, 0, 0, 0, 0, 0, 0, 0 -}; -#undef MC - -/** - *there are 32 slots available per climate with newcargo.*/ -#define MAXSLOTS 32 diff --git a/src/newgrf_cargo.h b/src/newgrf_cargo.h --- a/src/newgrf_cargo.h +++ b/src/newgrf_cargo.h @@ -52,9 +52,4 @@ NUM_GLOBAL_CID = 32 }; -extern const CargoID _global_cargo_id[NUM_LANDSCAPE][NUM_CARGO]; -extern const uint32 _landscape_global_cargo_mask[NUM_LANDSCAPE]; -extern const CargoID _local_cargo_id_ctype[NUM_GLOBAL_CID]; -extern const uint32 cargo_classes[16]; - #endif /* NEWGRF_CARGO_H */ diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -539,10 +539,9 @@ const Vehicle *u; byte cargo_classes = 0; uint common_cargo_best = 0; - uint common_cargos[NUM_GLOBAL_CID]; + uint common_cargos[NUM_CARGO]; byte user_def_data = 0; - CargoID cargo; - CargoID common_cargo_type = GC_PASSENGERS; + CargoID common_cargo_type = CT_PASSENGERS; /* Reset our arrays */ memset(common_cargos, 0, sizeof(common_cargos)); @@ -550,18 +549,17 @@ for (u = v; u != NULL; u = u->next) { /* Skip empty engines */ if (u->cargo_cap == 0) continue; - /* Map from climate to global cargo ID */ - cargo = _global_cargo_id[_opt.landscape][u->cargo_type]; - cargo_classes |= GetCargo(cargo)->classes; - common_cargos[cargo]++; + + cargo_classes |= GetCargo(u->cargo_type)->classes; + common_cargos[u->cargo_type]++; user_def_data |= RailVehInfo(u->engine_type)->user_def_data; } /* Pick the most common cargo type */ - for (cargo = 0; cargo < NUM_GLOBAL_CID; cargo++) { + for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) { if (common_cargos[cargo] > common_cargo_best) { common_cargo_best = common_cargos[cargo]; - common_cargo_type = cargo; + common_cargo_type = GetCargo(cargo)->bitnum; } } @@ -608,10 +606,9 @@ * ww - cargo unit weight in 1/16 tons, same as cargo prop. 0F. * cccc - the cargo class value of the cargo transported by the vehicle. */ - CargoID cid = _global_cargo_id[_opt.landscape][v->cargo_type]; const CargoSpec *cs = GetCargo(v->cargo_type); - return (cs->classes << 16) | (cs->weight << 8) | cid; + return (cs->classes << 16) | (cs->weight << 8) | cs->bitnum; } case 0x48: return GetVehicleTypeInfo(v->engine_type); /* Vehicle Type Info */ @@ -823,7 +820,7 @@ if (v == NULL) { cargo = GC_PURCHASE; } else { - cargo = _global_cargo_id[_opt.landscape][v->cargo_type]; + cargo = GetCargo(v->cargo_type)->bitnum; assert(cargo != GC_INVALID); if (v->type == VEH_Train) { @@ -889,7 +886,7 @@ bool UsesWagonOverride(const Vehicle* v) { assert(v->type == VEH_Train); - return GetWagonOverrideSpriteSet(v->engine_type, _global_cargo_id[_opt.landscape][v->cargo_type], v->u.rail.first_engine) != NULL; + return GetWagonOverrideSpriteSet(v->engine_type, GetCargo(v->cargo_type)->bitnum, v->u.rail.first_engine) != NULL; } /** diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -18,6 +18,7 @@ #include "newgrf_spritegroup.h" #include "date.h" #include "helpers.hpp" +#include "cargotype.h" static StationClass station_classes[STAT_CLASS_MAX]; @@ -459,7 +460,7 @@ break; default: - cargo = GB(st->goods[_local_cargo_id_ctype[cargo_type]].waiting_acceptance, 0, 12); + cargo = GB(st->goods[GetCargoIDByBitnum(cargo_type)].waiting_acceptance, 0, 12); break; } @@ -511,15 +512,12 @@ /* No station, so we are in a purchase list */ ctype = GC_PURCHASE; } else { - CargoID cargo; - /* Pick the first cargo that we have waiting */ - for (cargo = 0; cargo < NUM_GLOBAL_CID; cargo++) { - CargoID lcid = _local_cargo_id_ctype[cargo]; - if (lcid != CT_INVALID && - object->u.station.statspec->spritegroup[cargo] != NULL && - GB(object->u.station.st->goods[lcid].waiting_acceptance, 0, 12) != 0) { - ctype = cargo; + for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) { + const CargoSpec *cs = GetCargo(cargo); + if (cs->bitnum != 0xFF && object->u.station.statspec->spritegroup[cs->bitnum] != NULL && + GB(object->u.station.st->goods[cargo].waiting_acceptance, 0, 12) != 0) { + ctype = cs->bitnum; break; } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -37,6 +37,7 @@ #include "newgrf_engine.h" #include "newgrf_sound.h" #include "helpers.hpp" +#include "cargotype.h" #define INVALID_COORD (-0x8000) #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6)) @@ -761,7 +762,7 @@ */ bool CanRefitTo(EngineID engine_type, CargoID cid_to) { - CargoID cid = _global_cargo_id[_opt_ptr->landscape][cid_to]; + CargoID cid = GetCargo(cid_to)->bitnum; return HASBIT(EngInfo(engine_type)->refit_mask, cid); } @@ -771,12 +772,11 @@ */ CargoID FindFirstRefittableCargo(EngineID engine_type) { - CargoID cid; uint32 refit_mask = EngInfo(engine_type)->refit_mask; if (refit_mask != 0) { - for (cid = CT_PASSENGERS; cid < NUM_CARGO; cid++) { - if (HASBIT(refit_mask, _global_cargo_id[_opt_ptr->landscape][cid])) return cid; + for (CargoID cid = CT_PASSENGERS; cid < NUM_CARGO; cid++) { + if (HASBIT(refit_mask, GetCargo(cid)->bitnum)) return cid; } } diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -202,7 +202,6 @@ uint i; do { - CargoID cid; uint32 cmask = EngInfo(u->engine_type)->refit_mask; byte callbackmask = EngInfo(u->engine_type)->callbackmask; @@ -210,14 +209,11 @@ if (u->cargo_cap == 0) continue; /* Loop through all cargos in the refit mask */ - for (cid = 0; cmask != 0 && num_lines < max_lines; cmask >>= 1, cid++) { - CargoID lcid; + for (CargoID cid = 0; cid != NUM_CARGO && num_lines < max_lines; cid++) { + const CargoSpec *cs = GetCargo(cid); /* Skip cargo type if it's not listed */ - if (!HASBIT(cmask, 0)) continue; - - lcid = _local_cargo_id_ctype[cid]; - if (lcid == CT_INVALID) continue; + if (!HASBIT(cmask, cs->bitnum)) continue; /* Check the vehicle's callback mask for cargo suffixes */ if (HASBIT(callbackmask, CBM_CARGO_SUFFIX)) { @@ -227,7 +223,7 @@ byte temp_subtype = u->cargo_subtype; byte refit_cyc; - u->cargo_type = lcid; + u->cargo_type = cid; for (refit_cyc = 0; refit_cyc < 16 && num_lines < max_lines; refit_cyc++) { bool duplicate = false; @@ -241,12 +237,12 @@ /* Check if this cargo and subtype combination are listed */ for (i = 0; i < num_lines && !duplicate; i++) { - if (refit[i].cargo == lcid && refit[i].value == callback) duplicate = true; + if (refit[i].cargo == cid && refit[i].value == callback) duplicate = true; } if (duplicate) continue; - refit[num_lines].cargo = lcid; + refit[num_lines].cargo = cid; refit[num_lines].subtype = refit_cyc; refit[num_lines].value = callback; refit[num_lines].engine = u->engine_type; @@ -261,11 +257,11 @@ bool duplicate = false; for (i = 0; i < num_lines && !duplicate; i++) { - if (refit[i].cargo == lcid && refit[i].value == CALLBACK_FAILED) duplicate = true; + if (refit[i].cargo == cid && refit[i].value == CALLBACK_FAILED) duplicate = true; } if (!duplicate) { - refit[num_lines].cargo = lcid; + refit[num_lines].cargo = cid; refit[num_lines].subtype = 0; refit[num_lines].value = CALLBACK_FAILED; refit[num_lines].engine = INVALID_ENGINE; @@ -497,7 +493,7 @@ /* List of cargo types of this engine */ uint32 cmask = EngInfo(engine)->refit_mask; /* List of cargo types available in this climate */ - uint32 lmask = _landscape_global_cargo_mask[_opt.landscape]; + uint32 lmask = _cargo_mask; char *b = _userstring; /* Draw nothing if the engine is not refittable */ @@ -509,8 +505,6 @@ /* Engine can be refitted to all types in this climate */ b = InlineString(b, STR_PURCHASE_INFO_ALL_TYPES); } else { - CargoID cid; - /* Check if we are able to refit to more cargo types and unable to. If * so, invert the cargo types to list those that we can't refit to. */ if (CountBits(cmask ^ lmask) < CountBits(cmask)) { @@ -518,12 +512,18 @@ b = InlineString(b, STR_PURCHASE_INFO_ALL_BUT); } + bool first = true; + /* Add each cargo type to the list */ - for (cid = 0; cmask != 0; cmask >>= 1, cid++) { - if (!HASBIT(cmask, 0)) continue; + for (CargoID cid = 0; cid < NUM_CARGO; cid++) { + const CargoSpec *cs = GetCargo(cid); + + if (!HASBIT(cmask, cs->bitnum)) continue; - b = InlineString(b, GetCargo(_local_cargo_id_ctype[cid])->name); - if (cmask > 1) b = strecpy(b, ", ", lastof(_userstring)); + if (!first) b = strecpy(b, ", ", lastof(_userstring)); + first = false; + + b = InlineString(b, GetCargo(cid)->name); } }