2657 * B language-id see action 4, use 1F for built-in error messages |
2657 * B language-id see action 4, use 1F for built-in error messages |
2658 * B message-id message to show, see below |
2658 * B message-id message to show, see below |
2659 * S message for custom messages (message-id FF), text of the message |
2659 * S message for custom messages (message-id FF), text of the message |
2660 * not present for built-in messages. |
2660 * not present for built-in messages. |
2661 * V data additional data for built-in (or custom) messages |
2661 * V data additional data for built-in (or custom) messages |
2662 * B parnum see action 6, only used with built-in message 03 */ |
2662 * B parnum parameter numbers to be shown in the message (maximum of 2) */ |
2663 /* TODO: For now we just show the message, sometimes incomplete and never translated. */ |
2663 |
2664 |
2664 static const StringID msgstr[] = { |
2665 static const char *const msgstr[] = { |
2665 STR_NEWGRF_ERROR_VERSION_NUMBER, |
2666 "%sRequires at least pseudo-TTDPatch version %s.", |
2666 STR_NEWGRF_ERROR_DOS_OR_WINDOWS, |
2667 "%sThis file is for %s version of TTD.", |
2667 STR_NEWGRF_ERROR_UNSET_SWITCH, |
2668 "%sDesigned to be used with %s", |
2668 STR_NEWGRF_ERROR_INVALID_PARAMETER, |
2669 "%sInvalid parameter %s.", |
2669 STR_NEWGRF_ERROR_LOAD_BEFORE, |
2670 "%sMust be loaded before %s.", |
2670 STR_NEWGRF_ERROR_LOAD_AFTER |
2671 "%sMust be loaded after %s.", |
|
2672 "%s%s" |
|
2673 }; |
2671 }; |
2674 |
2672 |
2675 static const char *const sevstr[] = { |
2673 static const StringID sevstr[] = { |
2676 "", |
2674 STR_NEWGRF_ERROR_MSG_INFO, |
2677 "Warning: ", |
2675 STR_NEWGRF_ERROR_MSG_WARNING, |
2678 "Error: ", |
2676 STR_NEWGRF_ERROR_MSG_ERROR, |
2679 "Fatal: ", |
2677 STR_NEWGRF_ERROR_MSG_FATAL |
2680 }; |
2678 }; |
2681 |
2679 |
2682 if (!check_length(len, 6, "GRFError")) return; |
2680 /* AddGRFString expects the string to be referred to by an id in the newgrf |
|
2681 * file. Errors messages are never referred to however, so invent ids that |
|
2682 * are unlikely to be reached in a newgrf file so they don't overwrite |
|
2683 * anything else. */ |
|
2684 enum { |
|
2685 MESSAGE_STRING_ID = MAX_UVALUE(StringID) - 1, |
|
2686 MESSAGE_DATA_ID = MAX_UVALUE(StringID) |
|
2687 }; |
|
2688 |
|
2689 if (!check_length(len, 6, "GRFLoadError")) return; |
|
2690 |
|
2691 /* For now we can only show one message per newgrf file. */ |
|
2692 if (_cur_grfconfig->error != NULL) return; |
2683 |
2693 |
2684 buf++; /* Skip the action byte. */ |
2694 buf++; /* Skip the action byte. */ |
2685 byte severity = grf_load_byte(&buf); |
2695 byte severity = grf_load_byte(&buf); |
2686 buf++; /* TODO: Language id. */ |
2696 byte lang = grf_load_byte(&buf); |
2687 byte message_id = grf_load_byte(&buf); |
2697 byte message_id = grf_load_byte(&buf); |
2688 len -= 4; |
2698 len -= 4; |
2689 |
2699 |
2690 /* Skip the error until the activation stage unless bit 7 of the severity |
2700 /* Skip the error until the activation stage unless bit 7 of the severity |
2691 * is set. */ |
2701 * is set. */ |
2692 if (!HASBIT(severity, 7) && _cur_stage < GLS_ACTIVATION) { |
2702 if (!HASBIT(severity, 7) && _cur_stage < GLS_ACTIVATION) { |
2693 grfmsg(7, "Skipping non-fatal GRFError in stage 1"); |
2703 grfmsg(7, "Skipping non-fatal GRFLoadError in stage 1"); |
2694 return; |
2704 return; |
2695 } |
2705 } |
2696 CLRBIT(severity, 7); |
2706 CLRBIT(severity, 7); |
2697 |
2707 |
2698 if (severity >= lengthof(sevstr)) { |
2708 if (severity >= lengthof(sevstr)) { |
2699 grfmsg(7, "GRFError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity); |
2709 grfmsg(7, "GRFLoadError: Invalid severity id %d. Setting to 2 (non-fatal error).", severity); |
2700 severity = 2; |
2710 severity = 2; |
2701 } else if (severity == 3) { |
2711 } else if (severity == 3) { |
2702 /* This is a fatal error, so make sure the GRF is deactivated and no |
2712 /* This is a fatal error, so make sure the GRF is deactivated and no |
2703 * more of it gets loaded. */ |
2713 * more of it gets loaded. */ |
2704 SETBIT(_cur_grfconfig->flags, GCF_DISABLED); |
2714 SETBIT(_cur_grfconfig->flags, GCF_DISABLED); |
2706 |
2716 |
2707 _skip_sprites = -1; |
2717 _skip_sprites = -1; |
2708 } |
2718 } |
2709 |
2719 |
2710 if (message_id >= lengthof(msgstr) && message_id != 0xFF) { |
2720 if (message_id >= lengthof(msgstr) && message_id != 0xFF) { |
2711 grfmsg(7, "GRFError: Invalid message id."); |
2721 grfmsg(7, "GRFLoadError: Invalid message id."); |
2712 return; |
2722 return; |
2713 } |
2723 } |
2714 |
2724 |
2715 if (len <= 1) { |
2725 if (len <= 1) { |
2716 grfmsg(7, "GRFError: No message data supplied."); |
2726 grfmsg(7, "GRFLoadError: No message data supplied."); |
2717 return; |
2727 return; |
2718 } |
2728 } |
2719 |
2729 |
2720 char message[512]; |
2730 bool new_scheme = _cur_grffile->grf_version >= 7; |
2721 snprintf(message, lengthof(message), msgstr[(message_id == 0xFF) ? lengthof(msgstr) - 1 : message_id], sevstr[severity], grf_load_string(&buf, len)); |
2731 GRFError *error = CallocT<GRFError>(1); |
2722 |
2732 |
2723 if (_cur_grfconfig->error == NULL) { |
2733 error->severity = sevstr[severity]; |
2724 _cur_grfconfig->error = strdup(message); |
2734 |
2725 } |
2735 if (message_id == 0xFF) { |
2726 |
2736 /* This is a custom error message. */ |
2727 grfmsg(0, message); |
2737 const char *message = grf_load_string(&buf, len); |
|
2738 len -= (strlen(message) + 1); |
|
2739 |
|
2740 error->message = AddGRFString(_cur_grffile->grfid, MESSAGE_STRING_ID, lang, new_scheme, message, STR_UNDEFINED); |
|
2741 } else { |
|
2742 error->message = msgstr[message_id]; |
|
2743 } |
|
2744 |
|
2745 if (len > 0) { |
|
2746 const char *data = grf_load_string(&buf, len); |
|
2747 len -= (strlen(data) + 1); |
|
2748 |
|
2749 error->data = AddGRFString(_cur_grffile->grfid, MESSAGE_DATA_ID, lang, new_scheme, data, STR_UNDEFINED); |
|
2750 } |
|
2751 |
|
2752 /* Only two parameter numbers can be used in the string. */ |
|
2753 uint i = 0; |
|
2754 for (; i < 2 && len > 0; i++) { |
|
2755 error->param_number[i] = grf_load_byte(&buf); |
|
2756 len--; |
|
2757 } |
|
2758 error->num_params = i; |
|
2759 |
|
2760 _cur_grfconfig->error = error; |
2728 } |
2761 } |
2729 |
2762 |
2730 /* Action 0x0C */ |
2763 /* Action 0x0C */ |
2731 static void GRFComment(byte *buf, int len) |
2764 static void GRFComment(byte *buf, int len) |
2732 { |
2765 { |
3713 /* 0x06 */ { NULL, NULL, NULL, CfgApply, CfgApply, }, |
3746 /* 0x06 */ { NULL, NULL, NULL, CfgApply, CfgApply, }, |
3714 /* 0x07 */ { NULL, NULL, NULL, NULL, SkipIf, }, |
3747 /* 0x07 */ { NULL, NULL, NULL, NULL, SkipIf, }, |
3715 /* 0x08 */ { ScanInfo, NULL, NULL, GRFInfo, GRFInfo, }, |
3748 /* 0x08 */ { ScanInfo, NULL, NULL, GRFInfo, GRFInfo, }, |
3716 /* 0x09 */ { NULL, NULL, NULL, SkipIf, SkipIf, }, |
3749 /* 0x09 */ { NULL, NULL, NULL, SkipIf, SkipIf, }, |
3717 /* 0x0A */ { NULL, NULL, NULL, NULL, SpriteReplace, }, |
3750 /* 0x0A */ { NULL, NULL, NULL, NULL, SpriteReplace, }, |
3718 /* 0x0B */ { NULL, NULL, NULL, GRFError, GRFError, }, |
3751 /* 0x0B */ { NULL, NULL, NULL, GRFLoadError, GRFLoadError, }, |
3719 /* 0x0C */ { NULL, NULL, NULL, GRFComment, GRFComment, }, |
3752 /* 0x0C */ { NULL, NULL, NULL, GRFComment, GRFComment, }, |
3720 /* 0x0D */ { NULL, SafeParamSet, NULL, ParamSet, ParamSet, }, |
3753 /* 0x0D */ { NULL, SafeParamSet, NULL, ParamSet, ParamSet, }, |
3721 /* 0x0E */ { NULL, SafeGRFInhibit, NULL, GRFInhibit, GRFInhibit, }, |
3754 /* 0x0E */ { NULL, SafeGRFInhibit, NULL, GRFInhibit, GRFInhibit, }, |
3722 /* 0x0F */ { NULL, NULL, NULL, NULL, NULL, }, |
3755 /* 0x0F */ { NULL, NULL, NULL, NULL, NULL, }, |
3723 /* 0x10 */ { NULL, NULL, DefineGotoLabel, NULL, NULL, }, |
3756 /* 0x10 */ { NULL, NULL, DefineGotoLabel, NULL, NULL, }, |