diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 70904f72e2..652235fb21 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -46,6 +46,7 @@ - Fix: Various de-synchronisation issues in multiplayer. - Fix: Cheats not supported in multiplayer. - Fix: [#1333] Rides never become safe again after a crash. +- Fix: [#1742] Non-ascii characters in scenario details not showing correctly. - Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug). - Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day. - Fix: [#2477] When opening the built-in load/save dialog, the list is not properly sorted. diff --git a/src/addresses.h b/src/addresses.h index bced7a06c6..bc235a15f4 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -463,6 +463,7 @@ #define RCT2_ADDRESS_SAVED_VIEW_X 0x0138869A #define RCT2_ADDRESS_SAVED_VIEW_Y 0x0138869C #define RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION 0x0138869E +#define RCT2_ADDRESS_SCENARIO_COMPLETED_BY 0x013587D8 #define RCT2_ADDRESS_RIDE_MEASUREMENTS 0x0138B60C #define RCT2_ADDRESS_GRASS_SCENERY_TILEPOS 0x013B0E70 diff --git a/src/game.c b/src/game.c index 498a8826a0..348ec38dcf 100644 --- a/src/game.c +++ b/src/game.c @@ -651,21 +651,44 @@ static void load_landscape() window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE, NULL); } +static void strncpy_terminated(char *dst, const char *src, size_t length) +{ + if (length > 0) { + strncpy(dst, src, length - 1); + dst[length - 1] = '\0'; + } +} + +static void utf8_to_rct2_self(char *buffer, size_t length) +{ + char tempBuffer[512]; + utf8_to_rct2(tempBuffer, buffer); + strncpy_terminated(buffer, tempBuffer, length); +} + +static void rct2_to_utf8_self(char *buffer, size_t length) +{ + char tempBuffer[512]; + rct2_to_utf8(tempBuffer, buffer); + strncpy_terminated(buffer, tempBuffer, length); +} + /** * Converts all the user strings and news item strings to UTF-8. */ void game_convert_strings_to_utf8() { - utf8 buffer[512]; + // Scenario details + rct2_to_utf8_self(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_COMPLETED_BY, char), 32); + rct2_to_utf8_self(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_NAME, char), 64); + rct2_to_utf8_self(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char), 256); // User strings for (int i = 0; i < MAX_USER_STRINGS; i++) { utf8 *userString = &gUserStrings[i * USER_STRING_MAX_LENGTH]; if (!str_is_null_or_empty(userString)) { - rct2_to_utf8(buffer, userString); - memcpy(userString, buffer, 31); - userString[31] = 0; + rct2_to_utf8_self(userString, 32); } } @@ -674,9 +697,7 @@ void game_convert_strings_to_utf8() rct_news_item *newsItem = news_item_get(i); if (!str_is_null_or_empty(newsItem->text)) { - rct2_to_utf8(buffer, newsItem->text); - memcpy(newsItem->text, buffer, 255); - newsItem->text[255] = 0; + rct2_to_utf8_self(newsItem->text, 256); } } } @@ -686,16 +707,17 @@ void game_convert_strings_to_utf8() */ void game_convert_strings_to_rct2(rct_s6_data *s6) { - char buffer[512]; + // Scenario details + utf8_to_rct2_self(s6->scenario_completed_name, sizeof(s6->scenario_completed_name)); + utf8_to_rct2_self(s6->scenario_name, sizeof(s6->scenario_name)); + utf8_to_rct2_self(s6->scenario_description, sizeof(s6->scenario_description)); // User strings for (int i = 0; i < MAX_USER_STRINGS; i++) { char *userString = &s6->custom_strings[i * USER_STRING_MAX_LENGTH]; if (!str_is_null_or_empty(userString)) { - utf8_to_rct2(buffer, userString); - memcpy(userString, buffer, 31); - userString[31] = 0; + utf8_to_rct2_self(userString, 32); } } @@ -704,9 +726,7 @@ void game_convert_strings_to_rct2(rct_s6_data *s6) rct_news_item *newsItem = &s6->news_items[i]; if (!str_is_null_or_empty(newsItem->text)) { - utf8_to_rct2(buffer, newsItem->text); - memcpy(newsItem->text, buffer, 255); - newsItem->text[255] = 0; + utf8_to_rct2_self(newsItem->text, 256); } } } diff --git a/src/scenario.c b/src/scenario.c index 206b4d1798..57ce97f77d 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -446,7 +446,7 @@ void scenario_success_submit_name(const char *name) money32 scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, money32); if (scenario->highscore->company_value == scenarioWinCompanyValue) { scenario->highscore->name = _strdup(name); - safe_strcpy((char*)0x013587D8, name, 32); + safe_strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_COMPLETED_BY, char), name, 32); scenario_scores_save(); } } diff --git a/src/scenario.h b/src/scenario.h index 61b7a5b794..4f2cc728e6 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -287,8 +287,7 @@ typedef struct { rct_research_item research_items[500]; uint16 word_01359208; char scenario_name[64]; - char scenario_description[255]; - uint8 byte_01359349; + char scenario_description[256]; uint8 current_interest_rate; uint8 pad_0135934B; uint32 dword_0135934C;