diff --git a/src/lang/english.txt b/src/lang/english.txt index ba05d0bfd5..bb18a758c8 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2896,12 +2896,22 @@ STR_NEWGRF_APPLY_CHANGES :{BLACK}Apply ch STR_NEWGRF_SET_PARAMETERS :{BLACK}Set parameters STR_NEWGRF_TIP :{BLACK}A list of all the Newgrf sets that you have installed. Click a set to change the settings STR_NEWGRF_NO_FILES_INSTALLED :{BLACK}There are currently no newgrf files installed! Please refer to the manual for instructions on installing new graphics -STR_NEWGRF_ERROR_MSG :{RED}{STRING} STR_NEWGRF_FILENAME :{BLACK}Filename: {SILVER}{STRING} STR_NEWGRF_GRF_ID :{BLACK}GRF ID: {SILVER}{STRING} STR_NEWGRF_MD5SUM :{BLACK}MD5sum: {SILVER}{STRING} STR_NEWGRF_CONFIRMATION_TEXT :{YELLOW}You are about to make changes to a running game; this can crash OpenTTD.{}Are you absolutely sure about this? +STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING} +STR_NEWGRF_ERROR_MSG_WARNING :{RED}Warning: {SILVER}{STRING} +STR_NEWGRF_ERROR_MSG_ERROR :{RED}Error: {SILVER}{STRING} +STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SILVER}{STRING} +STR_NEWGRF_ERROR_VERSION_NUMBER :{STRING} will not work with the TTDPatch version reported by OpenTTD. +STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{STRING} is for the {STRING} version of TTD. +STR_NEWGRF_ERROR_UNSET_SWITCH :{STRING} is designed to be used with {STRING} +STR_NEWGRF_ERROR_INVALID_PARAMETER :Invalid parameter for {STRING}: parameter {STRING} ({NUM}) +STR_NEWGRF_ERROR_LOAD_BEFORE :{STRING} must be loaded before {STRING}. +STR_NEWGRF_ERROR_LOAD_AFTER :{STRING} must be loaded after {STRING}. + STR_NEWGRF_ADD :{BLACK}Add STR_NEWGRF_ADD_TIP :{BLACK}Add a NewGRF file to the list STR_NEWGRF_REMOVE :{BLACK}Remove diff --git a/src/newgrf.cpp b/src/newgrf.cpp index bffb587495..12e794543d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2644,7 +2644,7 @@ static void SpriteReplace(byte *buf, int len) } /* Action 0x0B */ -static void GRFError(byte *buf, int len) +static void GRFLoadError(byte *buf, int len) { /* <0B> [ 00] [] 00 [] * @@ -2659,44 +2659,54 @@ static void GRFError(byte *buf, int len) * S message for custom messages (message-id FF), text of the message * not present for built-in messages. * V data additional data for built-in (or custom) messages - * B parnum see action 6, only used with built-in message 03 */ - /* TODO: For now we just show the message, sometimes incomplete and never translated. */ + * B parnum parameter numbers to be shown in the message (maximum of 2) */ - static const char *const msgstr[] = { - "%sRequires at least pseudo-TTDPatch version %s.", - "%sThis file is for %s version of TTD.", - "%sDesigned to be used with %s", - "%sInvalid parameter %s.", - "%sMust be loaded before %s.", - "%sMust be loaded after %s.", - "%s%s" + static const StringID msgstr[] = { + STR_NEWGRF_ERROR_VERSION_NUMBER, + STR_NEWGRF_ERROR_DOS_OR_WINDOWS, + STR_NEWGRF_ERROR_UNSET_SWITCH, + STR_NEWGRF_ERROR_INVALID_PARAMETER, + STR_NEWGRF_ERROR_LOAD_BEFORE, + STR_NEWGRF_ERROR_LOAD_AFTER }; - static const char *const sevstr[] = { - "", - "Warning: ", - "Error: ", - "Fatal: ", + static const StringID sevstr[] = { + STR_NEWGRF_ERROR_MSG_INFO, + STR_NEWGRF_ERROR_MSG_WARNING, + STR_NEWGRF_ERROR_MSG_ERROR, + STR_NEWGRF_ERROR_MSG_FATAL }; - if (!check_length(len, 6, "GRFError")) return; + /* AddGRFString expects the string to be referred to by an id in the newgrf + * file. Errors messages are never referred to however, so invent ids that + * are unlikely to be reached in a newgrf file so they don't overwrite + * anything else. */ + enum { + MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1, + MESSAGE_DATA_ID = MAX_UVALUE(StringID) + }; + + if (!check_length(len, 6, "GRFLoadError")) return; + + /* For now we can only show one message per newgrf file. */ + if (_cur_grfconfig->error != NULL) return; buf++; /* Skip the action byte. */ byte severity = grf_load_byte(&buf); - buf++; /* TODO: Language id. */ + byte lang = grf_load_byte(&buf); byte message_id = grf_load_byte(&buf); len -= 4; /* Skip the error until the activation stage unless bit 7 of the severity * is set. */ if (!HASBIT(severity, 7) && _cur_stage < GLS_ACTIVATION) { - grfmsg(7, "Skipping non-fatal GRFError in stage 1"); + grfmsg(7, "Skipping non-fatal GRFLoadError in stage 1"); return; } CLRBIT(severity, 7); if (severity >= lengthof(sevstr)) { - grfmsg(7, "GRFError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity); + grfmsg(7, "GRFLoadError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity); severity = 2; } else if (severity == 3) { /* This is a fatal error, so make sure the GRF is deactivated and no @@ -2708,23 +2718,46 @@ static void GRFError(byte *buf, int len) } if (message_id >= lengthof(msgstr) && message_id != 0xFF) { - grfmsg(7, "GRFError: Invalid message id."); + grfmsg(7, "GRFLoadError: Invalid message id."); return; } if (len <= 1) { - grfmsg(7, "GRFError: No message data supplied."); + grfmsg(7, "GRFLoadError: No message data supplied."); return; } - char message[512]; - snprintf(message, lengthof(message), msgstr[(message_id == 0xFF) ? lengthof(msgstr) - 1 : message_id], sevstr[severity], grf_load_string(&buf, len)); + bool new_scheme = _cur_grffile->grf_version >= 7; + GRFError *error = CallocT(1); - if (_cur_grfconfig->error == NULL) { - _cur_grfconfig->error = strdup(message); + error->severity = sevstr[severity]; + + if (message_id == 0xFF) { + /* This is a custom error message. */ + const char *message = grf_load_string(&buf, len); + len -= (strlen(message) + 1); + + error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED); + } else { + error->message = msgstr[message_id]; } - grfmsg(0, message); + if (len > 0) { + const char *data = grf_load_string(&buf, len); + len -= (strlen(data) + 1); + + error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED); + } + + /* Only two parameter numbers can be used in the string. */ + uint i = 0; + for (; i < 2 && len > 0; i++) { + error->param_number[i] = grf_load_byte(&buf); + len--; + } + error->num_params = i; + + _cur_grfconfig->error = error; } /* Action 0x0C */ @@ -3715,7 +3748,7 @@ static void DecodeSpecialSprite(uint num, GrfLoadingStage stage) /* 0x08 */ { ScanInfo, NULL, NULL, GRFInfo, GRFInfo, }, /* 0x09 */ { NULL, NULL, NULL, SkipIf, SkipIf, }, /* 0x0A */ { NULL, NULL, NULL, NULL, SpriteReplace, }, - /* 0x0B */ { NULL, NULL, NULL, GRFError, GRFError, }, + /* 0x0B */ { NULL, NULL, NULL, GRFLoadError, GRFLoadError, }, /* 0x0C */ { NULL, NULL, NULL, GRFComment, GRFComment, }, /* 0x0D */ { NULL, SafeParamSet, NULL, ParamSet, ParamSet, }, /* 0x0E */ { NULL, SafeGRFInhibit, NULL, GRFInhibit, GRFInhibit, }, diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index 70d5da9ec1..1fc53fe6ad 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -124,7 +124,10 @@ GRFConfig **CopyGRFConfigList(GRFConfig **dst, const GRFConfig *src) if (src->filename != NULL) c->filename = strdup(src->filename); if (src->name != NULL) c->name = strdup(src->name); if (src->info != NULL) c->info = strdup(src->info); - if (src->error != NULL) c->error = strdup(src->error); + if (src->error != NULL) { + c->error = CallocT(1); + memcpy(c->error, src->error, sizeof(GRFError)); + } *dst = c; dst = &c->next; diff --git a/src/newgrf_config.h b/src/newgrf_config.h index f0bb773a4f..94be7ee349 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -3,6 +3,8 @@ #ifndef NEWGRF_CONFIG_H #define NEWGRF_CONFIG_H +#include "openttd.h" + /* GRF config bit flags */ typedef enum { GCF_DISABLED, ///< GRF file is disabled @@ -20,11 +22,19 @@ typedef struct GRFIdentifier { uint8 md5sum[16]; } GRF; +typedef struct GRFError { + StringID message; + StringID data; + StringID severity; + uint8 num_params; + uint8 param_number[2]; +} GRFError; + typedef struct GRFConfig : public GRFIdentifier { char *filename; char *name; char *info; - char *error; + GRFError *error; uint8 flags; uint32 param[0x80]; diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index c418786b29..6d5a78b897 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -11,6 +11,7 @@ #include "table/sprites.h" #include "newgrf.h" #include "newgrf_config.h" +#include "strings.h" #include "helpers.hpp" @@ -44,8 +45,22 @@ static void ShowNewGRFInfo(const GRFConfig *c, uint x, uint y, uint w, bool show char buff[256]; if (c->error != NULL) { - SetDParamStr(0, c->error); - y += DrawStringMultiLine(x, y, STR_NEWGRF_ERROR_MSG, w); + SetDParamStr(0, c->filename); + SetDParam(1, c->error->data); + for (uint i = 0; i < c->error->num_params; i++) { + uint32 param = 0; + byte param_number = c->error->param_number[i]; + + if (param_number < c->num_params) param = c->param[param_number]; + + SetDParam(2 + i, param); + } + + char message[512]; + GetString(message, c->error->message, lastof(message)); + + SetDParamStr(0, message); + y += DrawStringMultiLine(x, y, c->error->severity, w); } /* Draw filename or not if it is not known (GRF sent over internet) */