diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index e68dc8ccb9..91e32d4258 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -753,7 +753,11 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_ static uint ShowAdditionalText(int left, int right, int y, EngineID engine) { uint16 callback = GetVehicleCallback(CBID_VEHICLE_ADDITIONAL_TEXT, 0, 0, engine, NULL); - if (callback == CALLBACK_FAILED) return y; + if (callback == CALLBACK_FAILED || callback == 0x400) return y; + if (callback > 0x400) { + ErrorUnknownCallbackResult(Engine::Get(engine)->GetGRFID(), CBID_VEHICLE_ADDITIONAL_TEXT, callback); + return y; + } StartTextRefStackUsage(6); uint result = DrawStringMultiLine(left, right, y, INT32_MAX, GetGRFStringID(Engine::Get(engine)->GetGRFID(), 0xD000 + callback), TC_BLACK); diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index d991c5c70e..1ea3967fd4 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -73,7 +73,10 @@ static void GetCargoSuffix(uint cargo, CargoSuffixType cst, const Industry *ind, suffix[0] = '\0'; if (HasBit(indspec->callback_mask, CBM_IND_CARGO_SUFFIX)) { uint16 callback = GetIndustryCallback(CBID_INDUSTRY_CARGO_SUFFIX, 0, (cst << 8) | cargo, const_cast(ind), ind_type, (cst != CST_FUND) ? ind->location.tile : INVALID_TILE); - if (GB(callback, 0, 8) != 0xFF) { + if (callback == CALLBACK_FAILED || callback == 0x400) return; + if (callback > 0x400) { + ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_CARGO_SUFFIX, callback); + } else if (indspec->grf_prop.grffile->grf_version >= 8 || GB(callback, 0, 8) != 0xFF) { StartTextRefStackUsage(6); GetString(suffix, GetGRFStringID(indspec->grf_prop.grffile->grfid, 0xD000 + callback), suffix_last); StopTextRefStackUsage(); @@ -455,12 +458,16 @@ public: str = STR_NULL; if (HasBit(indsp->callback_mask, CBM_IND_FUND_MORE_TEXT)) { uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_FUND_MORE_TEXT, 0, 0, NULL, this->selected_type, INVALID_TILE); - if (callback_res != CALLBACK_FAILED) { // Did it fail? - str = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res); // No. here's the new string - if (str != STR_UNDEFINED) { - StartTextRefStackUsage(6); - DrawStringMultiLine(left, right, y, bottom, str, TC_YELLOW); - StopTextRefStackUsage(); + if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { + if (callback_res > 0x400) { + ErrorUnknownCallbackResult(indsp->grf_prop.grffile->grfid, CBID_INDUSTRY_FUND_MORE_TEXT, callback_res); + } else { + str = GetGRFStringID(indsp->grf_prop.grffile->grfid, 0xD000 + callback_res); // No. here's the new string + if (str != STR_UNDEFINED) { + StartTextRefStackUsage(6); + DrawStringMultiLine(left, right, y, bottom, str, TC_YELLOW); + StopTextRefStackUsage(); + } } } } @@ -783,17 +790,21 @@ public: /* Get the extra message for the GUI */ if (HasBit(ind->callback_mask, CBM_IND_WINDOW_MORE_TEXT)) { uint16 callback_res = GetIndustryCallback(CBID_INDUSTRY_WINDOW_MORE_TEXT, 0, 0, i, i->type, i->location.tile); - if (callback_res != CALLBACK_FAILED) { - StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res); - if (message != STR_NULL && message != STR_UNDEFINED) { - y += WD_PAR_VSEP_WIDE; + if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { + if (callback_res > 0x400) { + ErrorUnknownCallbackResult(ind->grf_prop.grffile->grfid, CBID_INDUSTRY_WINDOW_MORE_TEXT, callback_res); + } else { + StringID message = GetGRFStringID(ind->grf_prop.grffile->grfid, 0xD000 + callback_res); + if (message != STR_NULL && message != STR_UNDEFINED) { + y += WD_PAR_VSEP_WIDE; - StartTextRefStackUsage(6); - /* Use all the available space left from where we stand up to the - * end of the window. We ALSO enlarge the window if needed, so we - * can 'go' wild with the bottom of the window. */ - y = DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, UINT16_MAX, message, TC_BLACK); - StopTextRefStackUsage(); + StartTextRefStackUsage(6); + /* Use all the available space left from where we stand up to the + * end of the window. We ALSO enlarge the window if needed, so we + * can 'go' wild with the bottom of the window. */ + y = DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, y, UINT16_MAX, message, TC_BLACK); + StopTextRefStackUsage(); + } } } } diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index 05e54ab230..9137bf8657 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -273,7 +273,12 @@ StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callb object.callback = (CallbackID)callback; group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], &object); - if (group == NULL) return STR_UNDEFINED; + uint16 cb_res = (group != NULL) ? group->GetCallbackResult() : CALLBACK_FAILED; + if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED; + if (cb_res > 0x400) { + ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res); + return STR_UNDEFINED; + } - return GetGRFStringID(as->grf_prop.grffile->grfid, 0xD000 + group->GetCallbackResult()); + return GetGRFStringID(as->grf_prop.grffile->grfid, 0xD000 + cb_res); } diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index 6d81676dea..2f49c51c76 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -480,17 +480,24 @@ uint32 GetCompanyInfo(CompanyID owner, const Livery *l) CommandCost GetErrorMessageFromLocationCallbackResult(uint16 cb_res, uint32 grfid, StringID default_error) { CommandCost res; - switch (cb_res) { - case 0x400: return res; // No error. - case 0x401: res = CommandCost(default_error); break; - case 0x402: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST); break; - case 0x403: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT); break; - case 0x404: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE); break; - case 0x405: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE); break; - case 0x406: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_SEA); break; - case 0x407: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_CANAL); break; - case 0x408: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_RIVER); break; - default: res = CommandCost(GetGRFStringID(grfid, 0xD000 + cb_res)); break; + + if (cb_res < 0x400) { + res = CommandCost(GetGRFStringID(grfid, 0xD000 + cb_res)); + } else { + switch (cb_res) { + case 0x400: return res; // No error. + + default: // unknown reason -> default error + case 0x401: res = CommandCost(default_error); break; + + case 0x402: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST); break; + case 0x403: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT); break; + case 0x404: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE); break; + case 0x405: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE); break; + case 0x406: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_SEA); break; + case 0x407: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_CANAL); break; + case 0x408: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_RIVER); break; + } } /* Copy some parameters from the registers to the error message text ref. stack */ diff --git a/src/object_gui.cpp b/src/object_gui.cpp index a1bbf33750..6b89c4784f 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -233,19 +233,23 @@ public: /* Get the extra message for the GUI */ if (HasBit(spec->callback_mask, CBM_OBJ_FUND_MORE_TEXT)) { uint16 callback_res = GetObjectCallback(CBID_OBJECT_FUND_MORE_TEXT, 0, 0, spec, NULL, INVALID_TILE, _selected_object_view); - if (callback_res != CALLBACK_FAILED) { - StringID message = GetGRFStringID(spec->grf_prop.grffile->grfid, 0xD000 + callback_res); - if (message != STR_NULL && message != STR_UNDEFINED) { - StartTextRefStackUsage(6); - /* Use all the available space left from where we stand up to the - * end of the window. We ALSO enlarge the window if needed, so we - * can 'go' wild with the bottom of the window. */ - int y = DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, message, TC_ORANGE) - r.top; - StopTextRefStackUsage(); - if (y > this->info_height) { - BuildObjectWindow *bow = const_cast(this); - bow->info_height = y + 2; - bow->ReInit(); + if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { + if (callback_res > 0x400) { + ErrorUnknownCallbackResult(spec->grf_prop.grffile->grfid, CBID_OBJECT_FUND_MORE_TEXT, callback_res); + } else { + StringID message = GetGRFStringID(spec->grf_prop.grffile->grfid, 0xD000 + callback_res); + if (message != STR_NULL && message != STR_UNDEFINED) { + StartTextRefStackUsage(6); + /* Use all the available space left from where we stand up to the + * end of the window. We ALSO enlarge the window if needed, so we + * can 'go' wild with the bottom of the window. */ + int y = DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, message, TC_ORANGE) - r.top; + StopTextRefStackUsage(); + if (y > this->info_height) { + BuildObjectWindow *bow = const_cast(this); + bow->info_height = y + 2; + bow->ReInit(); + } } } } diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 9fde9163ac..eb741923b3 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -650,10 +650,14 @@ static void GetTileDesc_Town(TileIndex tile, TileDesc *td) td->str = hs->building_name; uint16 callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, house_completed ? 1 : 0, 0, house, Town::GetByTile(tile), tile); - if (callback_res != CALLBACK_FAILED) { - StringID new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, 0xD000 + callback_res); - if (new_name != STR_NULL && new_name != STR_UNDEFINED) { - td->str = new_name; + if (callback_res != CALLBACK_FAILED && callback_res != 0x400) { + if (callback_res > 0x400) { + ErrorUnknownCallbackResult(hs->grf_prop.grffile->grfid, CBID_HOUSE_CUSTOM_NAME, callback_res); + } else { + StringID new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, 0xD000 + callback_res); + if (new_name != STR_NULL && new_name != STR_UNDEFINED) { + td->str = new_name; + } } } diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 7f06d6adba..3bcfcc64ac 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -976,8 +976,26 @@ static CommandCost CheckTrainAttachment(Train *t) /* A failing callback means everything is okay */ StringID error = STR_NULL; - if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; - if (callback < 0xFD) error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback); + if (t->GetGRF()->grf_version < 8) { + if (callback == 0xFD) error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; + if (callback < 0xFD) error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback); + if (callback >= 0x100) ErrorUnknownCallbackResult(head->GetGRFID(), CBID_TRAIN_ALLOW_WAGON_ATTACH, callback); + } else { + if (callback < 0x400) { + error = GetGRFStringID(head->GetGRFID(), 0xD000 + callback); + } else { + switch (callback) { + case 0x400: // allow + case 0x401: // allow if railtypes match (always the case for OpenTTD) + break; + + default: // unknown reason -> disallow + case 0x402: // disallow attaching + error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; + break; + } + } + } if (error != STR_NULL) return_cmd_error(error); } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index a237b19416..089fb0ec4d 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -491,12 +491,30 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, default: return CMD_ERROR; } - /* Check if this vehicle can be started/stopped. The callback will fail or - * return 0xFF if it can. */ - uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v); - if (callback != CALLBACK_FAILED && GB(callback, 0, 8) != 0xFF && HasBit(p2, 0)) { - StringID error = GetGRFStringID(v->GetGRFID(), 0xD000 + callback); - return_cmd_error(error); + if (HasBit(p2, 0)) { + /* Check if this vehicle can be started/stopped. Failure means 'allow'. */ + uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v); + StringID error = STR_NULL; + if (callback != CALLBACK_FAILED) { + if (v->GetGRF()->grf_version < 8) { + /* 8 bit result 0xFF means 'allow' */ + if (callback < 0x400 && GB(callback, 0, 8) != 0xFF) error = GetGRFStringID(v->GetGRFID(), 0xD000 + callback); + } else { + if (callback < 0x400) { + error = GetGRFStringID(v->GetGRFID(), 0xD000 + callback); + } else { + switch (callback) { + case 0x400: // allow + break; + + default: // unknown reason -> disallow + error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES; + break; + } + } + } + } + if (error != STR_NULL) return_cmd_error(error); } if (flags & DC_EXEC) { diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index abd1e3317e..cbf6e1c08c 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -253,7 +253,10 @@ byte GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_t v_for->InvalidateNewGRFCache(); uint16 callback = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v_for->engine_type, v_for); - if (callback == 0xFF) callback = CALLBACK_FAILED; + if (callback != CALLBACK_FAILED) { + if (callback > 0x400) ErrorUnknownCallbackResult(v_for->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, callback); + if (callback >= 0x400 || (v_for->GetGRF()->grf_version < 8 && callback == 0xFF)) callback = CALLBACK_FAILED; + } if (callback == CALLBACK_FAILED) break; if (GetCargoSubtypeText(v_for) != expected_string) continue; @@ -332,7 +335,7 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], int sel, u /* Get the cargo name. */ SetDParam(0, CargoSpec::Get(refit.cargo)->name); /* If the callback succeeded, draw the cargo suffix. */ - if (refit.value != CALLBACK_FAILED) { + if (refit.value != CALLBACK_FAILED && refit.value < 0x400) { SetDParam(1, GetGRFStringID(refit.engine->GetGRFID(), 0xD000 + refit.value)); DrawString(r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, y, STR_JUST_STRING_SPACE_STRING, colour); } else { @@ -427,7 +430,10 @@ struct RefitWindow : public Window { v->InvalidateNewGRFCache(); uint16 callback = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v); - if (callback == 0xFF) callback = CALLBACK_FAILED; + if (callback != CALLBACK_FAILED) { + if (callback > 0x400) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, callback); + if (callback >= 0x400 || (v->GetGRF()->grf_version < 8 && callback == 0xFF)) callback = CALLBACK_FAILED; + } if (refit_cyc != 0 && callback == CALLBACK_FAILED) break; RefitOption option; @@ -983,6 +989,10 @@ StringID GetCargoSubtypeText(const Vehicle *v) { if (HasBit(EngInfo(v->engine_type)->callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) { uint16 cb = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v); + if (cb != CALLBACK_FAILED) { + if (cb > 0x400) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, cb); + if (cb >= 0x400 || (v->GetGRF()->grf_version < 8 && cb == 0xFF)) cb = CALLBACK_FAILED; + } if (cb != CALLBACK_FAILED) { return GetGRFStringID(v->GetGRFID(), 0xD000 + cb); }