From af5daaec70d64b419e02c42c1a121b3f72941131 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 29 Jul 2019 21:20:22 +0100 Subject: [PATCH] Fix importing and exporting of banner strings containing colour --- src/openrct2/rct1/S4Importer.cpp | 3 ++- src/openrct2/rct12/RCT12.cpp | 39 ++++++++++++++++++++++++++++++ src/openrct2/rct12/RCT12.h | 8 ++++++ src/openrct2/rct2/S6Exporter.cpp | 11 ++++++++- src/openrct2/rct2/S6Importer.cpp | 3 ++- src/openrct2/ride/Ride.cpp | 2 +- src/openrct2/world/TileElement.cpp | 2 +- 7 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 7f00ce6acd..ded3972144 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2906,7 +2906,8 @@ private: { const auto originalString = _s4.string_table[(stringId - USER_STRING_START) % 1024]; std::string_view originalStringView(originalString, USER_STRING_MAX_LENGTH); - return rct2_to_utf8(originalStringView, RCT2_LANGUAGE_ID_ENGLISH_UK); + auto withoutFormatCodes = RCT12::RemoveFormatCodes(originalStringView); + return rct2_to_utf8(withoutFormatCodes, RCT2_LANGUAGE_ID_ENGLISH_UK); } void FixLandOwnership() diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index e9d01d628c..ecc7ec3317 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -9,6 +9,7 @@ #include "RCT12.h" +#include "../localisation/Localisation.h" #include "../ride/Track.h" #include "../world/Footpath.h" #include "../world/SmallScenery.h" @@ -413,3 +414,41 @@ bool is_user_string_id(rct_string_id stringId) { return stringId >= 0x8000 && stringId < 0x9000; } + +std::string RCT12::RemoveFormatCodes(const std::string_view& s) +{ + constexpr auto RCT12_MULTIBYTE_PREFIX = (char)(uint8_t)0xFF; + + std::string result; + result.reserve(s.size()); + + // Append each character that is not a format code + for (size_t i = 0; i < s.size(); i++) + { + auto c = s[i]; + if (c == '\0') + { + break; + } + else if (c == RCT12_MULTIBYTE_PREFIX) + { + // Multi-byte, assume not a format code + result.push_back(c); + if (i + 1 < s.size()) + { + result.push_back(s[i + 1]); + } + if (i + 2 < s.size()) + { + result.push_back(s[i + 2]); + } + i += 2; + } + else if (!utf8_is_format_code(c)) + { + result.push_back(c); + } + } + + return result; +} diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index e41e8d773b..be0089df15 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -14,6 +14,9 @@ #include "../common.h" #include "../world/Location.hpp" +#include +#include + #define RCT12_MAX_RIDES_IN_PARK 255 #define RCT12_MAX_AWARDS 4 #define RCT12_MAX_NEWS_ITEMS 61 @@ -540,3 +543,8 @@ assert_struct_size(RCT12Banner, 8); #pragma pack(pop) bool is_user_string_id(rct_string_id stringId); + +namespace RCT12 +{ + std::string RemoveFormatCodes(const std::string_view& s); +} diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index 2b411dc446..28f3bd5f28 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -1253,7 +1253,16 @@ void S6Exporter::ExportBanner(RCT12Banner& dst, const Banner& src) dst.flags = src.flags; dst.string_idx = STR_DEFAULT_SIGN; - auto stringId = AllocateUserString(src.text); + + auto bannerText = src.text; + if (!(src.flags & BANNER_FLAG_IS_WALL) && !(src.flags & BANNER_FLAG_IS_LARGE_SCENERY)) + { + char codeBuffer[32]{}; + utf8_write_codepoint(codeBuffer, FORMAT_COLOUR_CODE_START + src.text_colour); + bannerText = codeBuffer + bannerText; + } + + auto stringId = AllocateUserString(bannerText); if (stringId != opt::nullopt) { dst.string_idx = *stringId; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 906349d2a5..214fe902b9 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1524,7 +1524,8 @@ public: { const auto originalString = _s6.custom_strings[(stringId - USER_STRING_START) % 1024]; std::string_view originalStringView(originalString, USER_STRING_MAX_LENGTH); - return rct2_to_utf8(originalStringView, RCT2_LANGUAGE_ID_ENGLISH_UK); + auto withoutFormatCodes = RCT12::RemoveFormatCodes(originalStringView); + return rct2_to_utf8(withoutFormatCodes, RCT2_LANGUAGE_ID_ENGLISH_UK); } }; diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index a3a108f49c..00340d19ef 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -872,7 +872,7 @@ void Ride::FormatStatusTo(void* argsV) const && race_winner != SPRITE_INDEX_NULL) { auto sprite = get_sprite(race_winner); - if (sprite != nullptr) + if (sprite != nullptr && sprite->IsPeep()) { auto peep = sprite->AsPeep(); set_format_arg_on(args, 0, rct_string_id, STR_RACE_WON_BY); diff --git a/src/openrct2/world/TileElement.cpp b/src/openrct2/world/TileElement.cpp index b0f2abf6d9..9e05815f5f 100644 --- a/src/openrct2/world/TileElement.cpp +++ b/src/openrct2/world/TileElement.cpp @@ -128,7 +128,7 @@ void tile_element_remove_banner_entry(TileElement* tileElement) if (banner != nullptr) { window_close_by_number(WC_BANNER, bannerIndex); - banner = {}; + *banner = {}; } }