1
0
Fork 0

Fix 51bd344f10: Incorrect translation table used for older NewGRFs. (#13131)

Incorrect logic was used to select the default translation table for older GRFs.
pull/13133/head
Peter Nelson 2024-11-29 07:46:08 +00:00 committed by GitHub
parent fe0afef36f
commit b6aece5b88
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 28 deletions

View File

@ -46,14 +46,14 @@ static std::vector<CargoLabel> _default_cargo_labels;
* This maps the original 12 cargo slots to their original label. If a climate dependent cargo is not present it will * This maps the original 12 cargo slots to their original label. If a climate dependent cargo is not present it will
* map to CT_INVALID. For default cargoes this ends up as a 1:1 mapping via climate slot -> label -> cargo ID. * map to CT_INVALID. For default cargoes this ends up as a 1:1 mapping via climate slot -> label -> cargo ID.
*/ */
static std::array<CargoLabel, 12> _v7_cargo_labels; static std::array<CargoLabel, 12> _climate_dependent_cargo_labels;
/** /**
* Default cargo translation for version 8+ NewGRFs. * Default cargo translation for version 8+ NewGRFs.
* This maps the 32 "bitnum" cargo slots to their original label. If a bitnum is not present it will * This maps the 32 "bitnum" cargo slots to their original label. If a bitnum is not present it will
* map to CT_INVALID. * map to CT_INVALID.
*/ */
static std::array<CargoLabel, 32> _v8_cargo_labels; static std::array<CargoLabel, 32> _climate_independent_cargo_labels;
/** /**
* Set up the default cargo types for the given landscape type. * Set up the default cargo types for the given landscape type.
@ -65,8 +65,8 @@ void SetupCargoForClimate(LandscapeID l)
_cargo_mask = 0; _cargo_mask = 0;
_default_cargo_labels.clear(); _default_cargo_labels.clear();
_v7_cargo_labels.fill(CT_INVALID); _climate_dependent_cargo_labels.fill(CT_INVALID);
_v8_cargo_labels.fill(CT_INVALID); _climate_independent_cargo_labels.fill(CT_INVALID);
/* Copy from default cargo by label or index. */ /* Copy from default cargo by label or index. */
auto insert = std::begin(CargoSpec::array); auto insert = std::begin(CargoSpec::array);
@ -94,8 +94,8 @@ void SetupCargoForClimate(LandscapeID l)
if (insert->IsValid()) { if (insert->IsValid()) {
SetBit(_cargo_mask, insert->Index()); SetBit(_cargo_mask, insert->Index());
_default_cargo_labels.push_back(insert->label); _default_cargo_labels.push_back(insert->label);
_v7_cargo_labels[insert->Index()] = insert->label; _climate_dependent_cargo_labels[insert->Index()] = insert->label;
_v8_cargo_labels[insert->bitnum] = insert->label; _climate_independent_cargo_labels[insert->bitnum] = insert->label;
} }
++insert; ++insert;
} }
@ -107,14 +107,21 @@ void SetupCargoForClimate(LandscapeID l)
} }
/** /**
* Get default cargo translation table for a NewGRF, used if the NewGRF does not provide its own. * Get default climate-dependent cargo translation table for a NewGRF, used if the NewGRF does not provide its own.
* @param grf_version GRF version of translation table.
* @return Default translation table for GRF version. * @return Default translation table for GRF version.
*/ */
std::span<const CargoLabel> GetDefaultCargoTranslationTable(uint8_t grf_version) std::span<const CargoLabel> GetClimateDependentCargoTranslationTable()
{ {
if (grf_version < 8) return _v7_cargo_labels; return _climate_dependent_cargo_labels;
return _v8_cargo_labels; }
/**
* Get default climate-independent cargo translation table for a NewGRF, used if the NewGRF does not provide its own.
* @return Default translation table for GRF version.
*/
std::span<const CargoLabel> GetClimateIndependentCargoTranslationTable()
{
return _climate_independent_cargo_labels;
} }
/** /**

View File

@ -5562,20 +5562,39 @@ static void NewSpriteGroup(ByteReader &buf)
_cur.spritegroups[setid] = act_group; _cur.spritegroups[setid] = act_group;
} }
/**
* Get the cargo translation table to use for the given GRF file.
* @param grffile GRF file.
* @returns Readonly cargo translation table to use.
*/
std::span<const CargoLabel> GetCargoTranslationTable(const GRFFile &grffile)
{
/* Always use the translation table if it's installed. */
if (!grffile.cargo_list.empty()) return grffile.cargo_list;
/* Pre-v7 use climate-dependent "slot" table. */
if (grffile.grf_version < 7) return GetClimateDependentCargoTranslationTable();
/* Otherwise use climate-independent "bitnum" table. */
return GetClimateIndependentCargoTranslationTable();
}
static CargoID TranslateCargo(uint8_t feature, uint8_t ctype) static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
{ {
/* Special cargo types for purchase list and stations */ /* Special cargo types for purchase list and stations */
if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return SpriteGroupCargo::SG_DEFAULT_NA; if ((feature == GSF_STATIONS || feature == GSF_ROADSTOPS) && ctype == 0xFE) return SpriteGroupCargo::SG_DEFAULT_NA;
if (ctype == 0xFF) return SpriteGroupCargo::SG_PURCHASE; if (ctype == 0xFF) return SpriteGroupCargo::SG_PURCHASE;
auto cargo_list = GetCargoTranslationTable(*_cur.grffile);
/* Check if the cargo type is out of bounds of the cargo translation table */ /* Check if the cargo type is out of bounds of the cargo translation table */
if (ctype >= _cur.grffile->cargo_list.size()) { if (ctype >= cargo_list.size()) {
GrfMsg(1, "TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (unsigned int)_cur.grffile->cargo_list.size() - 1); GrfMsg(1, "TranslateCargo: Cargo type {} out of range (max {}), skipping.", ctype, (unsigned int)_cur.grffile->cargo_list.size() - 1);
return INVALID_CARGO; return INVALID_CARGO;
} }
/* Look up the cargo label from the translation table */ /* Look up the cargo label from the translation table */
CargoLabel cl = _cur.grffile->cargo_list[ctype]; CargoLabel cl = cargo_list[ctype];
if (cl == CT_INVALID) { if (cl == CT_INVALID) {
GrfMsg(5, "TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype); GrfMsg(5, "TranslateCargo: Cargo type {} not available in this climate, skipping.", ctype);
return INVALID_CARGO; return INVALID_CARGO;
@ -7059,13 +7078,6 @@ static void GRFInfo(ByteReader &buf)
_cur.grffile->grf_version = version; _cur.grffile->grf_version = version;
_cur.grfconfig->status = _cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED; _cur.grfconfig->status = _cur.stage < GLS_RESERVE ? GCS_INITIALISED : GCS_ACTIVATED;
/* Install the default cargo translation table. */
if (_cur.stage < GLS_RESERVE && _cur.grffile->cargo_list.empty()) {
auto default_table = GetDefaultCargoTranslationTable(version);
_cur.grffile->cargo_list.assign(default_table.begin(), default_table.end());
GrfMsg(3, "GRFInfo: Installing default GRFv{} translation table for {:08X}", version, BSWAP32(grfid));
}
/* Do swap the GRFID for displaying purposes since people expect that */ /* Do swap the GRFID for displaying purposes since people expect that */
Debug(grf, 1, "GRFInfo: Loaded GRFv{} set {:08X} - {} (palette: {}, version: {})", version, BSWAP32(grfid), StrMakeValid(name), (_cur.grfconfig->palette & GRFP_USE_MASK) ? "Windows" : "DOS", _cur.grfconfig->version); Debug(grf, 1, "GRFInfo: Loaded GRFv{} set {:08X} - {} (palette: {}, version: {})", version, BSWAP32(grfid), StrMakeValid(name), (_cur.grfconfig->palette & GRFP_USE_MASK) ? "Windows" : "DOS", _cur.grfconfig->version);
} }
@ -8905,11 +8917,13 @@ static void BuildCargoTranslationMap()
{ {
_cur.grffile->cargo_map.fill(UINT8_MAX); _cur.grffile->cargo_map.fill(UINT8_MAX);
auto cargo_list = GetCargoTranslationTable(*_cur.grffile);
for (const CargoSpec *cs : CargoSpec::Iterate()) { for (const CargoSpec *cs : CargoSpec::Iterate()) {
if (!cs->IsValid()) continue; if (!cs->IsValid()) continue;
/* Check the translation table for this cargo's label */ /* Check the translation table for this cargo's label */
int idx = find_index(_cur.grffile->cargo_list, {cs->label}); int idx = find_index(cargo_list, cs->label);
if (idx >= 0) _cur.grffile->cargo_map[cs->Index()] = idx; if (idx >= 0) _cur.grffile->cargo_map[cs->Index()] = idx;
} }
} }

View File

@ -79,14 +79,17 @@ uint16_t GetCargoCallback(CallbackID callback, uint32_t param1, uint32_t param2,
*/ */
CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit) CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
{ {
/* We can't use GetCargoTranslationTable here as the usebit flag changes behviour. */
/* Pre-version 7 uses the bitnum lookup from (standard in v8) instead of climate dependent in some places.. */ /* Pre-version 7 uses the bitnum lookup from (standard in v8) instead of climate dependent in some places.. */
if (grffile->grf_version < 7 && usebit) { std::span<const CargoLabel> cargo_list;
auto default_table = GetDefaultCargoTranslationTable(8); if (grffile->grf_version < 7 && !usebit) {
if (cargo < default_table.size()) return GetCargoIDByLabel(default_table[cargo]); cargo_list = GetClimateDependentCargoTranslationTable();
return INVALID_CARGO; } else if (!grffile->cargo_list.empty()) {
cargo_list = grffile->cargo_list;
} else {
cargo_list = GetClimateIndependentCargoTranslationTable();
} }
/* Look in translation table. */ if (cargo < cargo_list.size()) return GetCargoIDByLabel(cargo_list[cargo]);
if (cargo < grffile->cargo_list.size()) return GetCargoIDByLabel(grffile->cargo_list[cargo]);
return INVALID_CARGO; return INVALID_CARGO;
} }

View File

@ -33,6 +33,7 @@ SpriteID GetCustomCargoSprite(const CargoSpec *cs);
uint16_t GetCargoCallback(CallbackID callback, uint32_t param1, uint32_t param2, const CargoSpec *cs); uint16_t GetCargoCallback(CallbackID callback, uint32_t param1, uint32_t param2, const CargoSpec *cs);
CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit = false); CargoID GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit = false);
std::span<const CargoLabel> GetDefaultCargoTranslationTable(uint8_t grf_version); std::span<const CargoLabel> GetClimateDependentCargoTranslationTable();
std::span<const CargoLabel> GetClimateIndependentCargoTranslationTable();
#endif /* NEWGRF_CARGO_H */ #endif /* NEWGRF_CARGO_H */