From 795c01cab55ae2cf70fe7c17d9dc531192fe5528 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Mon, 27 Jul 2015 01:09:24 +0100 Subject: [PATCH] implement utf8, part 5 --- src/config.c | 1 + src/drawing/string.c | 40 +++-- src/interface/widget.c | 7 - src/localisation/language.c | 220 ++++++++++++++++++++----- src/localisation/language.h | 7 + src/localisation/localisation.c | 8 + src/localisation/localisation.h | 1 + src/windows/editor_object_selection.c | 5 +- src/windows/editor_objective_options.c | 2 +- src/windows/themes.c | 2 +- 10 files changed, 222 insertions(+), 71 deletions(-) diff --git a/src/config.c b/src/config.c index eed5bd3de9..a2de18bdfb 100644 --- a/src/config.c +++ b/src/config.c @@ -138,6 +138,7 @@ config_enum_definition _languageEnum[] = { { "sv-SE", LANGUAGE_SWEDISH }, { "it-IT", LANGUAGE_ITALIAN }, { "pt-BR", LANGUAGE_PORTUGUESE_BR }, + { "zh-Hant", LANGUAGE_CHINESE_TRADITIONAL }, END_OF_ENUM }; diff --git a/src/drawing/string.c b/src/drawing/string.c index 5b412382e8..5e2dc7e470 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -933,7 +933,7 @@ bool ttf_initialise() } } - _ttfFontOffsetX = 0; + _ttfFontOffsetX = 1; _ttfFontOffsetY = -3; _ttfInitialised = true; } @@ -972,22 +972,27 @@ typedef struct { uint16 font_sprite_base; } text_draw_info; +static void ttf_draw_character_sprite(rct_drawpixelinfo *dpi, int codepoint, text_draw_info *info) +{ + uint32 charOffset = info->font_sprite_base + utf8_get_sprite_offset_for_codepoint(codepoint); + int charWidth = _spriteFontCharacterWidths[charOffset] & 0xFF; + + if (!(info->flags & TEXT_DRAW_FLAG_NO_DRAW)) { + RCT2_GLOBAL(0x009ABDA4, uint8*) = (uint8*)&info->palette; + RCT2_GLOBAL(0x00EDF81C, uint32) = (IMAGE_TYPE_USE_PALETTE << 28); + gfx_draw_sprite_palette_set(dpi, SPR_CHAR_START + ((IMAGE_TYPE_USE_PALETTE << 28) | charOffset), info->x, info->y, info->palette, NULL); + } + + info->x += charWidth; +} + static void ttf_draw_string_raw_sprite(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info) { const utf8 *ch = text; int codepoint; while (!utf8_is_format_code(codepoint = utf8_get_next(ch, &ch))) { - uint32 charOffset = info->font_sprite_base + utf8_get_sprite_offset_for_codepoint(codepoint); - int charWidth = _spriteFontCharacterWidths[charOffset] & 0xFF; - - if (!(info->flags & TEXT_DRAW_FLAG_NO_DRAW)) { - RCT2_GLOBAL(0x009ABDA4, uint8*) = (uint8*)&info->palette; - RCT2_GLOBAL(0x00EDF81C, uint32) = (IMAGE_TYPE_USE_PALETTE << 28); - gfx_draw_sprite_palette_set(dpi, SPR_CHAR_START + ((IMAGE_TYPE_USE_PALETTE << 28) | charOffset), info->x, info->y, info->palette, NULL); - } - - info->x += charWidth; + ttf_draw_character_sprite(dpi, codepoint, info); }; } @@ -1206,7 +1211,11 @@ static const utf8 *ttf_process_glyph_run(rct_drawpixelinfo *dpi, const utf8 *tex const utf8 *lastCh; int codepoint; + bool isTTF = info->flags & TEXT_DRAW_FLAG_TTF; while (!utf8_is_format_code(codepoint = utf8_get_next(ch, &lastCh))) { + if (isTTF && utf8_should_use_sprite_for_codepoint(codepoint)) { + break; + } ch = lastCh; } if (codepoint == 0) { @@ -1233,9 +1242,8 @@ static void ttf_process_string(rct_drawpixelinfo *dpi, const utf8 *text, text_dr if (utf8_is_format_code(codepoint)) { ch = ttf_process_format_code(dpi, ch, info); } else if (isTTF && utf8_should_use_sprite_for_codepoint(codepoint)) { - info->flags &= ~TEXT_DRAW_FLAG_TTF; - ch = ttf_process_glyph_run(dpi, ch, info); - info->flags |= TEXT_DRAW_FLAG_TTF; + ttf_draw_character_sprite(dpi, codepoint, info); + ch = nextCh; } else { ch = ttf_process_glyph_run(dpi, ch, info); } @@ -1246,9 +1254,9 @@ static void ttf_process_initial_colour(int colour, text_draw_info *info) { if (colour != 254 && colour != 255) { info->flags &= ~(1 | 2 | 4 | 8); - if (info->font_sprite_base < 0) { + if ((sint16)info->font_sprite_base < 0) { info->flags |= 4; - if (info->font_sprite_base != -1) { + if ((sint16)info->font_sprite_base != -1) { info->flags |= 8; } info->font_sprite_base = 224; diff --git a/src/interface/widget.c b/src/interface/widget.c index e94b6d232e..3a060a548a 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -725,8 +725,6 @@ static void widget_closebox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg gfx_draw_string_centred_clipped(dpi, widget->image, (void*)0x013CE952, colour, l, t, widget->right - widget->left - 2); } -static const utf8 CheckBoxMarkString[] = { 0xE2, 0x9C, 0x93, 0x00 }; - /** * * rct2: 0x006EBAD9 @@ -850,11 +848,6 @@ static void widget_scroll_draw(rct_drawpixelinfo *dpi, rct_window *w, int widget window_event_scroll_paint_call(w, &scroll_dpi, scrollIndex); } -static const utf8 BlackUpArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xB2, 0x00 }; -static const utf8 BlackDownArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xBC, 0x00 }; -static const utf8 BlackLeftArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0x80, 0x00 }; -static const utf8 BlackRightArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xB6, 0x00 }; - static void widget_hscrollbar_draw(rct_drawpixelinfo *dpi, rct_scroll *scroll, int l, int t, int r, int b, int colour) { colour &= 0x7F; diff --git a/src/localisation/language.c b/src/localisation/language.c index 4f891fd02e..56eff314bf 100644 --- a/src/localisation/language.c +++ b/src/localisation/language.c @@ -33,20 +33,38 @@ typedef struct { char *string_data; } language_data; +enum { + RCT2_LANGUAGE_ID_ENGLISH_UK, + RCT2_LANGUAGE_ID_ENGLISH_US, + RCT2_LANGUAGE_ID_FRENCH, + RCT2_LANGUAGE_ID_GERMAN, + RCT2_LANGUAGE_ID_SPANISH, + RCT2_LANGUAGE_ID_ITALIAN, + RCT2_LANGUAGE_ID_DUTCH, + RCT2_LANGUAGE_ID_SWEDISH, + RCT2_LANGUAGE_ID_8, + RCT2_LANGUAGE_ID_KOREAN, + RCT2_LANGUAGE_ID_CHINESE_TRADITIONAL, + RCT2_LANGUAGE_ID_CHINESE_SIMPLIFIED, + RCT2_LANGUAGE_ID_12, + RCT2_LANGUAGE_ID_PORTUGESE, + RCT2_LANGUAGE_ID_END = 255 +}; + const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = { - { "", "", "", "", FONT_OPENRCT2_SPRITE }, // LANGUAGE_UNDEFINED - { "en-GB", "English (UK)", "English (UK)", "english_uk", FONT_OPENRCT2_SPRITE }, // LANGUAGE_ENGLISH_UK - { "en-US", "English (US)", "English (US)", "english_us", FONT_OPENRCT2_SPRITE }, // LANGUAGE_ENGLISH_US - { "de-DE", "German", "Deutsch", "german", FONT_OPENRCT2_SPRITE }, // LANGUAGE_GERMAN - { "nl-NL", "Dutch", "Nederlands", "dutch", FONT_OPENRCT2_SPRITE }, // LANGUAGE_DUTCH - { "fr-FR", "French", "Fran\xC3\xA7" "ais", "french", FONT_OPENRCT2_SPRITE }, // LANGUAGE_FRENCH - { "hu-HU", "Hungarian", "Magyar", "hungarian", FONT_OPENRCT2_SPRITE }, // LANGUAGE_HUNGARIAN - { "pl-PL", "Polish", "Polski", "polish", FONT_OPENRCT2_SPRITE }, // LANGUAGE_POLISH - { "es-ES", "Spanish", "Espa\xC3\xB1ol", "spanish_sp", FONT_OPENRCT2_SPRITE }, // LANGUAGE_SPANISH - { "sv-SE", "Swedish", "Svenska", "swedish", FONT_OPENRCT2_SPRITE }, // LANGUAGE_SWEDISH - { "it-IT", "Italian", "Italiano", "italian", FONT_OPENRCT2_SPRITE }, // LANGUAGE_ITALIAN - { "pt-BR", "Portuguese (BR)", "Portug\xC3\xAAs (BR)", "portuguese_br", FONT_OPENRCT2_SPRITE }, // LANGUAGE_PORTUGUESE_BR - { "zh-Hant", "Chinese (Traditional)", "Chinese (Traditional)", "chinese_traditional", "msjh.ttc" }, // LANGUAGE_CHINESE_TRADITIONAL + { "", "", "", "", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_UNDEFINED + { "en-GB", "English (UK)", "English (UK)", "english_uk", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_ENGLISH_UK + { "en-US", "English (US)", "English (US)", "english_us", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_US }, // LANGUAGE_ENGLISH_US + { "de-DE", "German", "Deutsch", "german", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_GERMAN }, // LANGUAGE_GERMAN + { "nl-NL", "Dutch", "Nederlands", "dutch", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_DUTCH }, // LANGUAGE_DUTCH + { "fr-FR", "French", "Fran\xC3\xA7" "ais", "french", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_FRENCH }, // LANGUAGE_FRENCH + { "hu-HU", "Hungarian", "Magyar", "hungarian", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_HUNGARIAN + { "pl-PL", "Polish", "Polski", "polish", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_POLISH + { "es-ES", "Spanish", "Espa\xC3\xB1ol", "spanish_sp", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_SPANISH }, // LANGUAGE_SPANISH + { "sv-SE", "Swedish", "Svenska", "swedish", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_SWEDISH }, // LANGUAGE_SWEDISH + { "it-IT", "Italian", "Italiano", "italian", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ITALIAN }, // LANGUAGE_ITALIAN + { "pt-BR", "Portuguese (BR)", "Portug\xC3\xAAs (BR)", "portuguese_br", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_PORTUGESE }, // LANGUAGE_PORTUGUESE_BR + { "zh-Hant", "Chinese (Traditional)", "Chinese (Traditional)", "chinese_traditional", "msjh.ttc", RCT2_LANGUAGE_ID_CHINESE_TRADITIONAL }, // LANGUAGE_CHINESE_TRADITIONAL }; int gCurrentLanguage = LANGUAGE_UNDEFINED; @@ -58,6 +76,12 @@ language_data _languageCurrent = { 0 }; const char **_languageOriginal = (char**)0x009BF2D4; +const utf8 BlackUpArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xB2, 0x00 }; +const utf8 BlackDownArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xBC, 0x00 }; +const utf8 BlackLeftArrowString[] = { 0xC2, 0x8E, 0xE2, 0x97, 0x80, 0x00 }; +const utf8 BlackRightArrowString[] = { 0xC2, 0x8E, 0xE2, 0x96, 0xB6, 0x00 }; +const utf8 CheckBoxMarkString[] = { 0xE2, 0x9C, 0x93, 0x00 }; + static int language_open_file(const char *filename, language_data *language); static void language_close(language_data *language); @@ -299,56 +323,141 @@ static void language_close(language_data *language) } const int OpenRCT2LangIdToObjectLangId[] = { - 0, 0, 1, 3, 6, 2, 0, 0, 4, 7, 5, 13 + 0, + 0, + 1, + 3, + 6, + 2, + 0, + 0, + 4, + 7, + 5, + 13 }; +#define STEX_BASE_STRING_ID 3447 +#define NONSTEX_BASE_STRING_ID 3463 +#define MAX_OBJECT_CACHED_STRINGS 2048 + /* rct2: 0x0098DA16 */ uint16 ObjectTypeStringTableCount[] = { 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 }; +utf8 *_cachedObjectStrings[MAX_OBJECT_CACHED_STRINGS] = { NULL }; + +void utf8_trim_string(utf8 *text) +{ + utf8 *src = text; + utf8 *dst = text; + utf8 *last = text; + int codepoint; + + // Trim left + while ((codepoint = utf8_get_next(src, &src)) != 0) { + if (codepoint != ' ') { + dst = utf8_write_codepoint(dst, codepoint); + last = dst; + break; + } + } + if (codepoint != 0) { + // Trim right + while ((codepoint = utf8_get_next(src, &src)) != 0) { + dst = utf8_write_codepoint(dst, codepoint); + if (codepoint != ' ') { + last = dst; + } + } + } + *last = 0; +} + +static utf8 *convert_multibyte_charset(const char *src) +{ + int reservedLength = (strlen(src) * 4) + 1; + utf8 *buffer = malloc(reservedLength); + utf8 *dst = buffer; + for (const uint8 *ch = src; *ch != 0;) { + if (*ch == 0xFF) { + ch++; + uint8 a = *ch++; + uint8 b = *ch++; + uint16 codepoint = (a << 8) | b; + dst = utf8_write_codepoint(dst, codepoint); + } else { + *dst++ = *ch++; + } + } + *dst++ = 0; + int actualLength = dst - buffer; + return realloc(buffer, actualLength); +} + +static bool rct2_language_is_multibyte_charset(int languageId) +{ + switch (languageId) { + case RCT2_LANGUAGE_ID_KOREAN: + case RCT2_LANGUAGE_ID_CHINESE_TRADITIONAL: + case RCT2_LANGUAGE_ID_CHINESE_SIMPLIFIED: + return true; + default: + return false; + } +} + /* rct2: 0x006A9E24*/ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/*ecx*/, int index/*ebx*/, int tableindex/*edx*/) { - char* pString = NULL; + uint8 languageId, chosenLanguageId; + char *pString = NULL; int result = 0; - while (true) - { - uint8_t language_code = *(*pStringTable)++; - - if (language_code == 0xFF) //end of string table - break; + bool isBlank; + + while ((languageId = *(*pStringTable)++) != RCT2_LANGUAGE_ID_END) { + isBlank = true; + + // Strings that are just ' ' are set as invalid langauges. + // But if there is no real string then it will set the string as + // the blank string + for (char *ch = *pStringTable; *ch != 0; ch++) { + if (!isblank(*ch)) { + isBlank = false; + break; + } + } + + if (isBlank) languageId = 0xFE; // This is the ideal situation. Language found - if (language_code == OpenRCT2LangIdToObjectLangId[gCurrentLanguage])//1) - { + if (languageId == LanguagesDescriptors[gCurrentLanguage].rct2_original_id) { + chosenLanguageId = languageId; pString = *pStringTable; result |= 1; } // Just in case always load english into pString - if (language_code == 0 && !(result & 1)) - { + if (languageId == RCT2_LANGUAGE_ID_ENGLISH_UK && !(result & 1)) { + chosenLanguageId = languageId; pString = *pStringTable; result |= 2; } // Failing that fall back to whatever is first string - if (!(result & 7)) - { + if (!(result & 7)) { + chosenLanguageId = languageId; pString = *pStringTable; - result |= 4; + if (!isBlank) result |= 4; } - // Skip over the actual string entry to get to the next - // entry + // Skip over the actual string entry to get to the next entry while (*(*pStringTable)++ != 0); } // If not scenario text - if (RCT2_GLOBAL(0x9ADAFC, uint8_t) == 0) - { - int stringid = 3463; - for (int i = 0; i < type; i++) - { + if (RCT2_GLOBAL(0x009ADAFC, uint8) == 0) { + int stringid = NONSTEX_BASE_STRING_ID; + for (int i = 0; i < type; i++) { int nrobjects = object_entry_group_counts[i]; int nrstringtables = ObjectTypeStringTableCount[i]; stringid += nrobjects * nrstringtables; @@ -358,23 +467,48 @@ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/ RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32) = stringid; stringid += tableindex; + // cache UTF-8 string + int cacheStringOffset = stringid - STEX_BASE_STRING_ID; + utf8 **cacheString = &_cachedObjectStrings[cacheStringOffset]; + if (*cacheString != NULL) { + free(*cacheString); + } + if (rct2_language_is_multibyte_charset(chosenLanguageId)) { + *cacheString = convert_multibyte_charset(pString); + } else { + *cacheString = win1252_to_utf8_alloc(pString); + } + utf8_trim_string(*cacheString); + //put pointer in stringtable if (_languageCurrent.num_strings > stringid) - _languageCurrent.strings[stringid] = pString; + _languageCurrent.strings[stringid] = *cacheString; // Until all string related functions are finished copy // to old array as well. - _languageOriginal[stringid] = pString; + _languageOriginal[stringid] = *cacheString; return stringid; - } - else - { - int stringid = 3447 + tableindex; + } else { + int stringid = STEX_BASE_STRING_ID + tableindex; + + // cache UTF-8 string + int cacheStringOffset = stringid - STEX_BASE_STRING_ID; + utf8 **cacheString = &_cachedObjectStrings[cacheStringOffset]; + if (*cacheString != NULL) { + free(*cacheString); + } + if (rct2_language_is_multibyte_charset(chosenLanguageId)) { + *cacheString = convert_multibyte_charset(pString); + } else { + *cacheString = win1252_to_utf8_alloc(pString); + } + utf8_trim_string(*cacheString); + //put pointer in stringtable if (_languageCurrent.num_strings > stringid) - _languageCurrent.strings[stringid] = pString; + _languageCurrent.strings[stringid] = *cacheString; // Until all string related functions are finished copy // to old array as well. - _languageOriginal[stringid] = pString; + _languageOriginal[stringid] = *cacheString; return stringid; } } diff --git a/src/localisation/language.h b/src/localisation/language.h index cc6ed220b8..2b8fcb5d1b 100644 --- a/src/localisation/language.h +++ b/src/localisation/language.h @@ -48,6 +48,7 @@ typedef struct { const utf8 *native_name; const utf8 *path; const utf8 *font; + uint8 rct2_original_id; } language_descriptor; extern const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT]; @@ -56,6 +57,12 @@ extern int gCurrentLanguage; extern bool gUseTrueTypeFont; extern const utf8 *gTrueTypeFontPath; +extern const utf8 BlackUpArrowString[]; +extern const utf8 BlackDownArrowString[]; +extern const utf8 BlackLeftArrowString[]; +extern const utf8 BlackRightArrowString[]; +extern const utf8 CheckBoxMarkString[]; + const char *language_get_string(rct_string_id id); int language_open(int id); void language_close_all(); diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index ae6d71882c..659eae6a28 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -833,6 +833,14 @@ int get_string_length(const utf8* text) return ch - text - 1; } +utf8 *win1252_to_utf8_alloc(const char *src) +{ + int reservedSpace = (strlen(src) * 4) + 1; + utf8 *result = malloc(reservedSpace); + int actualSpace = win1252_to_utf8(result, src, reservedSpace); + return (utf8*)realloc(result, actualSpace); +} + int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength) { utf16 stackBuffer[256]; diff --git a/src/localisation/localisation.h b/src/localisation/localisation.h index 238931da6e..e6c31049cf 100644 --- a/src/localisation/localisation.h +++ b/src/localisation/localisation.h @@ -42,6 +42,7 @@ rct_string_id user_string_allocate(int base, const char *text); void user_string_free(rct_string_id id); bool is_user_string_id(rct_string_id stringId); +utf8 *win1252_to_utf8_alloc(const char *src); int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength); #define MAX_USER_STRINGS 1024 diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 0aa9843f4d..26e05f526e 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -1439,14 +1439,13 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi if (*listItem->flags & (OBJECT_SELECTION_FLAG_IN_USE | OBJECT_SELECTION_FLAG_REQUIRED | OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED)) colour2 |= 0x40; - gfx_draw_string(dpi, (char*)0x009DED72, colour2, x, y); + gfx_draw_string(dpi, (char*)CheckBoxMarkString, colour2, x, y); } x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 15; char *bufferWithColour = (char*)0x0141ED68; - char *buffer = bufferWithColour + 1; - bufferWithColour[0] = colour; + char *buffer = utf8_write_codepoint(bufferWithColour, colour); if (*listItem->flags & OBJECT_SELECTION_FLAG_6) { colour = w->colours[1] & 0x7F; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1; diff --git a/src/windows/editor_objective_options.c b/src/windows/editor_objective_options.c index f9524e77f9..480ba6b44d 100644 --- a/src/windows/editor_objective_options.c +++ b/src/windows/editor_objective_options.c @@ -1200,7 +1200,7 @@ static void window_editor_objective_options_rides_scrollpaint(rct_window *w, rct ride = GET_RIDE(i); if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) { RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = stringId == 1193 ? 0xFFFE : 0xFFFF; - gfx_draw_string(dpi, (char*)0x009DED72, w->colours[1] & 0x7F, 2, y); + gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1] & 0x7F, 2, y); } // Ride name diff --git a/src/windows/themes.c b/src/windows/themes.c index 9984df3f22..11e2a8aee4 100644 --- a/src/windows/themes.c +++ b/src/windows/themes.c @@ -881,7 +881,7 @@ void window_themes_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scroll gfx_fill_rect_inset(dpi, _button_offset_x + 12 * j, y + _check_offset_y, _button_offset_x + 12 * j + 9, y + _check_offset_y + 10, w->colours[1], 0xE0); if (get_colour_scheme_tab_by_index(i)->colours[j] & 0x80) { RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1; - gfx_draw_string(dpi, (char*)0x009DED72, w->colours[1] & 0x7F, _button_offset_x + 12 * j, y + _check_offset_y); + gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1] & 0x7F, _button_offset_x + 12 * j, y + _check_offset_y); } }