From a9e6f8c3db1e1eff5ffee3ce7efd12d5f63654ae Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 29 Jul 2015 02:03:34 +0100 Subject: [PATCH] implement utf8, part 12 --- projects/openrct2.vcxproj | 1 + projects/openrct2.vcxproj.filters | 3 + src/drawing/drawing.h | 4 + src/drawing/scrolling_text.c | 161 ++++++++++++++++++++++++++++++ src/drawing/string.c | 82 ++++++--------- src/interface/viewport.c | 124 ----------------------- src/ride/track.c | 24 +++-- src/ride/track.h | 2 +- src/windows/error.c | 11 +- 9 files changed, 223 insertions(+), 189 deletions(-) create mode 100644 src/drawing/scrolling_text.c diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index efe3e09bcc..495391fc30 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -36,6 +36,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 5a8f3f4179..0c74f0bb5e 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -498,6 +498,9 @@ Source\Localisation + + Source\Drawing + diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 9ed88c96f1..cf0450d3d2 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -144,4 +144,8 @@ void redraw_rain(); // unknown void sub_681DE2(rct_drawpixelinfo *dpi, int x, int y, int image1, int image2); +// scrolling text +void scrolling_text_initialise_bitmaps(); +int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode); + #endif diff --git a/src/drawing/scrolling_text.c b/src/drawing/scrolling_text.c new file mode 100644 index 0000000000..188defc574 --- /dev/null +++ b/src/drawing/scrolling_text.c @@ -0,0 +1,161 @@ +#include "../addresses.h" +#include "../config.h" +#include "../localisation/localisation.h" +#include "drawing.h" + +/* size: 0xA12 */ +typedef struct { + rct_string_id string_id; // 0x00 + uint32 string_args_0; // 0x02 + uint32 string_args_1; // 0x06 + uint16 position; // 0x0A + uint16 mode; // 0x0C + uint32 id; // 0x0E + uint8 bitmap[64 * 8 * 5]; // 0x12 +} rct_draw_scroll_text; + +rct_draw_scroll_text *gDrawScrollTextList = RCT2_ADDRESS(RCT2_ADDRESS_DRAW_SCROLL_LIST, rct_draw_scroll_text); + +void scrolling_text_initialise_bitmaps() +{ + uint8 drawingSurface[64]; + rct_drawpixelinfo dpi = { + .bits = (char*)&drawingSurface, + .x = 0, + .y = 0, + .width = 8, + .height = 8, + .pitch = 0, + .zoom_level = 0 + }; + + + for (int i = 0; i < 224; i++) { + memset(drawingSurface, 0, sizeof(drawingSurface)); + gfx_draw_sprite(&dpi, i + 0x10D5, -1, 0, 0); + + for (int x = 0; x < 8; x++) { + uint8 val = 0; + for (int y = 0; y < 8; y++) { + val >>= 1; + if (dpi.bits[x + y * 8] == 1) { + val |= 0x80; + } + } + RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[i * 8 + x] = val; + } + + } +} + +/** + * + * rct2: 0x006C42D9 + */ +int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode) +{ + rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); + + if (dpi->zoom_level != 0) return 0x626; + + RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32)++; + + // Find the oldest scroll for use as the newest + uint32 oldestId = 0xFFFFFFFF; + uint8 scrollIndex = 0xFF; + rct_draw_scroll_text* oldestScroll = NULL; + for (int i = 0; i < 32; i++) { + rct_draw_scroll_text *scrollText = &gDrawScrollTextList[i]; + if (oldestId >= scrollText->id) { + oldestId = scrollText->id; + scrollIndex = i; + oldestScroll = scrollText; + } + + // If exact match return the matching index + if ( + scrollText->string_id == stringId && + scrollText->string_args_0 == RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) && + scrollText->string_args_1 == RCT2_GLOBAL(0x13CE956, uint32) && + scrollText->position == scroll && + scrollText->mode == scrollingMode + ) { + scrollText->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32); + return i + 0x606; + } + } + + // Setup scrolling text + rct_draw_scroll_text* scrollText = oldestScroll; + scrollText->string_id = stringId; + scrollText->string_args_0 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32); + scrollText->string_args_1 = RCT2_GLOBAL(0x13CE956, uint32); + scrollText->position = scroll; + scrollText->mode = scrollingMode; + scrollText->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32_t); + + uint8* scrollPixelPointer = scrollText->bitmap; + memset(scrollPixelPointer, 0, 320 * 8); + + // Convert string id back into a string for processing + utf8 scrollString[MAX_PATH]; + if (gConfigGeneral.upper_case_banners) + format_string_to_upper(scrollString, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + else + format_string(scrollString, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); + + // Setup character colour from ??? + uint32 character = RCT2_GLOBAL(0x13CE959, uint8); + int edi = character & 0x7F; + int offs = 0; + if (character >= 0x80) offs = 2; + uint8 characterColour = RCT2_ADDRESS(0x0141FC47, uint8)[offs + edi * 8]; + + sint16* scrollingModePositions = RCT2_ADDRESS(RCT2_ADDRESS_SCROLLING_MODE_POSITIONS, uint16_t*)[scrollingMode]; + uint8* formatResult = scrollString; + while (true) { + character = utf8_get_next(formatResult, &formatResult); + + // If at the end of the string loop back to the start + if (character == 0) { + formatResult = scrollString; + continue; + } + + // Set any change in colour + if (character <= FORMAT_COLOUR_CODE_END && character >= FORMAT_COLOUR_CODE_START){ + character -= FORMAT_COLOUR_CODE_START; + characterColour = RCT2_GLOBAL(0x009FF048, uint8*)[character * 4]; + continue; + } + + // If another type of control character ignore + if (character < 32) continue; + + // Convert to an indexable character + character = utf8_get_sprite_offset_for_codepoint(character); + + uint8 characterWidth = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH + 448, uint8)[character]; + uint8* characterBitmap = &(RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[character * 8]); + for (; characterWidth != 0; characterWidth--, characterBitmap++) { + // Skip any none displayed columns + if (scroll != 0){ + scroll--; + continue; + } + + sint16 scrollPosition = *scrollingModePositions; + if (scrollPosition == -1) return scrollIndex + 0x606; + if (scrollPosition > -1) { + uint8* dst = &scrollPixelPointer[scrollPosition]; + for (uint8 char_bitmap = *characterBitmap; char_bitmap != 0; char_bitmap >>= 1){ + if (char_bitmap & 1) *dst = characterColour; + + // Jump to next row + dst += 64; + } + } + scrollingModePositions++; + } + } +} \ No newline at end of file diff --git a/src/drawing/string.c b/src/drawing/string.c index 8c5a1f78e9..46c0e56b46 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -35,6 +35,16 @@ static int _ttfFontOffsetY = 0; static const int TTFFontSizes[] = { 7, 9, 11, 13 }; enum { + FONT_SIZE_TINY = 2, + FONT_SIZE_SMALL = 0, + FONT_SIZE_MEDIUM = 1, + FONT_SIZE_BIG = 3, + FONT_SIZE_COUNT = 4 +}; + +enum { + FONT_SPRITE_GLYPH_COUNT = 224, + FONT_SPRITE_BASE_TINY = 448, FONT_SPRITE_BASE_SMALL = 0, FONT_SPRITE_BASE_MEDIUM = 224, @@ -47,59 +57,30 @@ static uint8 *_spriteFontCharacterWidths = (uint8*)RCT2_ADDRESS_FONT_CHAR_WIDTH; * * rct2: 0x006C19AC */ -void gfx_load_character_widths(){ - - uint8* char_width_pointer = _spriteFontCharacterWidths; - for (int char_set_offset = 0; char_set_offset < 4*0xE0; char_set_offset+=0xE0){ - for (uint8 c = 0; c < 0xE0; c++, char_width_pointer++){ - rct_g1_element g1 = g1Elements[c + SPR_CHAR_START + char_set_offset]; - int width; - - if (char_set_offset == 0xE0*3) width = g1.width + 1; - else width = g1.width - 1; - - if (c >= (FORMAT_ARGUMENT_CODE_START - 0x20) && c < (FORMAT_COLOUR_CODE_END - 0x20)){ +void gfx_load_character_widths() +{ + uint8* pCharacterWidth = _spriteFontCharacterWidths; + for (int fontSize = 0; fontSize < FONT_SIZE_COUNT; fontSize++) { + int glyphOffset = fontSize * FONT_SPRITE_GLYPH_COUNT; + for (uint8 glyphIndex = 0; glyphIndex < FONT_SPRITE_GLYPH_COUNT; glyphIndex++) { + rct_g1_element g1 = g1Elements[glyphIndex + SPR_CHAR_START + glyphOffset]; + + int width = fontSize == FONT_SIZE_BIG ? g1.width + 1 : g1.width - 1; + if (glyphIndex >= (FORMAT_ARGUMENT_CODE_START - 32) && glyphIndex < (FORMAT_COLOUR_CODE_END - 32)) { width = 0; } - *char_width_pointer = (uint8)width; + *pCharacterWidth++ = (uint8)width; } - } - uint8 drawing_surface[0x40]; - rct_drawpixelinfo dpi = { - .bits = (char*)&drawing_surface, - .width = 8, - .height = 8, - .x = 0, - .y = 0, - .pitch = 0, - .zoom_level = 0}; + scrolling_text_initialise_bitmaps(); - - for (int i = 0; i < 0xE0; ++i){ - memset(drawing_surface, 0, sizeof(drawing_surface)); - gfx_draw_sprite(&dpi, i + 0x10D5, -1, 0, 0); - - for (int x = 0; x < 8; ++x){ - uint8 val = 0; - for (int y = 0; y < 8; ++y){ - val >>= 1; - if (dpi.bits[x + y * 8]==1){ - val |= 0x80; - } - } - RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[i * 8 + x] = val; - } - - } - - for (int i = 0; i < 0x20; ++i){ + for (int i = 0; i < 32; i++) { rct_g1_element* g1 = &g1Elements[0x606 + i]; - uint8* unknown_pointer = RCT2_ADDRESS(0x9C3852, uint8) + 0xa12 * i; + uint8* unknown_pointer = RCT2_ADDRESS(0x009C3852, uint8) + 0xA12 * i; g1->offset = unknown_pointer; - g1->width = 0x40; - g1->height = 0x28; + g1->width = 64; + g1->height = 40; *((uint16*)unknown_pointer) = 0xFFFF; *((uint32*)(unknown_pointer + 0x0E)) = 0; } @@ -782,7 +763,7 @@ bool ttf_initialise() } _ttfFontOffsetX = 1; - _ttfFontOffsetY = -3; + _ttfFontOffsetY = -2; _ttfInitialised = true; } return true; @@ -805,6 +786,7 @@ void ttf_dispose() } enum { + TEXT_DRAW_FLAG_INSET = 1 << 0, TEXT_DRAW_FLAG_OUTLINE = 1 << 1, TEXT_DRAW_FLAG_TTF = 1 << 30, TEXT_DRAW_FLAG_NO_DRAW = 1 << 31 @@ -920,8 +902,10 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te for (int xx = 0; xx < width; xx++) { if (*src != 0) { *dst = colour; - if (info->flags & TEXT_DRAW_FLAG_OUTLINE) { - *(dst + width + dstScanSkip + 1) = 0; + if (info->flags & TEXT_DRAW_FLAG_INSET) { + *(dst + width + dstScanSkip + 1) = info->palette[3]; + } else if (info->flags & TEXT_DRAW_FLAG_OUTLINE) { + *(dst + width + dstScanSkip + 1) = info->palette[3]; } } src++; @@ -953,7 +937,7 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t codepoint = utf8_get_next(text, &nextCh); switch (codepoint) { case FORMAT_MOVE_X: - info->x = info->startX + *nextCh++; + info->x = info->startX + (uint8)(*nextCh++); break; case FORMAT_ADJUST_PALETTE: { diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 90771a2bb2..ef6475f160 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -990,130 +990,6 @@ void sprite_paint_setup(uint16 eax, uint16 ecx){ } } -/* size: 0xA12 */ -typedef struct{ - rct_string_id string_id; // 0x00 - uint32 string_args_0; // 0x02 - uint32 string_args_1; // 0x06 - uint16 position; // 0x0A - uint16 mode; // 0x0C - uint32 id; // 0x0E - uint8 bitmap[64 * 8 * 5];// 0x12 -}rct_draw_scroll_text; - -/*rct2: 0x006C42D9*/ -int scrolling_text_setup(rct_string_id string_id, uint16 scroll, uint16 scrolling_mode) -{ - rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); - - if (dpi->zoom_level != 0) return 0x626; - - RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32)++; - - uint32 oldest_id = 0xFFFFFFFF; - uint8 scroll_index = 0xFF; - rct_draw_scroll_text* oldest_scroll = NULL; - - // Find the oldest scroll for use as the newest - for (int i = 0; i < 32; i++) - { - rct_draw_scroll_text* scroll_text = &RCT2_ADDRESS(RCT2_ADDRESS_DRAW_SCROLL_LIST, rct_draw_scroll_text)[i]; - if (oldest_id >= scroll_text->id){ - oldest_id = scroll_text->id; - scroll_index = i; - oldest_scroll = scroll_text; - } - - // If exact match return the matching index - if (scroll_text->string_id == string_id && - scroll_text->string_args_0 == RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) && - scroll_text->string_args_1 == RCT2_GLOBAL(0x13CE956, uint32) && - scroll_text->position == scroll && - scroll_text->mode == scrolling_mode){ - - scroll_text->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32); - return i + 0x606; - } - } - - // Setup scrolling text - - rct_draw_scroll_text* scroll_text = oldest_scroll; - scroll_text->string_id = string_id; - scroll_text->string_args_0 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32); - scroll_text->string_args_1 = RCT2_GLOBAL(0x13CE956, uint32); - scroll_text->position = scroll; - scroll_text->mode = scrolling_mode; - scroll_text->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32_t); - - uint8* scroll_pixel_pointer = scroll_text->bitmap; - memset(scroll_pixel_pointer, 0, 320 * 8); - - // Convert string id back into a string for processing - uint8 scroll_string[MAX_PATH]; - if(gConfigGeneral.upper_case_banners) - format_string_to_upper(scroll_string, string_id, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); - else - format_string(scroll_string, string_id, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); - - // Setup character colour from ??? - uint8 character = RCT2_GLOBAL(0x13CE959, uint8); - int edi = character & 0x7F; - int offs = 0; - if (character >= 0x80) offs = 2; - uint8 character_colour = RCT2_ADDRESS(0x0141FC47, uint8)[offs + edi * 8]; - - sint16* scrolling_mode_positions = RCT2_ADDRESS(RCT2_ADDRESS_SCROLLING_MODE_POSITIONS, uint16_t*)[scrolling_mode]; - uint8* format_result = scroll_string; - while (true) - { - character = *format_result++; - - // If at the end of the string loop back to the start - if (character == 0){ - format_result = scroll_string; - continue; - } - - // Set any change in colour - if (character <= FORMAT_COLOUR_CODE_END && character >= FORMAT_COLOUR_CODE_START){ - character -= FORMAT_COLOUR_CODE_START; - character_colour = RCT2_GLOBAL(0x9FF048, uint8*)[character * 4]; - continue; - } - - // If another type of control character ignore - if (character < 0x20) continue; - - // Convert to an indexable character - character -= 0x20; - - uint8 character_width = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH + 0x1C0, uint8)[character]; - uint8* character_bitmap = &(RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[character * 8]); - for (; character_width != 0;character_width--,character_bitmap++) - { - // Skip any none displayed columns - if (scroll != 0){ - scroll--; - continue; - } - - sint16 scroll_position = *scrolling_mode_positions; - if (scroll_position == -1) return scroll_index + 0x606; - if (scroll_position > -1) - { - uint8* dst = &scroll_pixel_pointer[scroll_position]; - for (uint8 char_bitmap = *character_bitmap; char_bitmap != 0; char_bitmap >>= 1){ - if (char_bitmap & 1) *dst = character_colour; - // Jump to next row - dst += 64; - } - } - scrolling_mode_positions++; - } - } -} - /* rct2: 0x006629BC * returns al * ebp : image_id diff --git a/src/ride/track.c b/src/ride/track.c index d8fe740f24..acb55157ec 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -3111,20 +3111,24 @@ rct_track_design *temp_track_get_info(char* path, uint8** preview) return trackDesign; } -void window_track_list_format_name(char *dst, const char *src, char colour, char quotes) +void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool quotes) { - if (colour != 0) - *dst++ = colour; + const utf8 *ch; + int codepoint; - if (quotes != 0) - *dst++ = FORMAT_OPENQUOTES; - - while (*src != '.' && *src != 0) { - *dst++ = *src++; + if (colour != 0) { + dst = utf8_write_codepoint(dst, colour); } - if (quotes != 0) - *dst++ = FORMAT_ENDQUOTES; + if (quotes) dst = utf8_write_codepoint(dst, FORMAT_OPENQUOTES); + + ch = src; + while ((codepoint = utf8_get_next(ch, &ch)) != 0) { + if (codepoint == '.') break; + dst = utf8_write_codepoint(dst, codepoint); + } + + if (quotes) dst = utf8_write_codepoint(dst, FORMAT_ENDQUOTES); *dst = 0; } diff --git a/src/ride/track.h b/src/ride/track.h index 241fad4a65..622aca98b3 100644 --- a/src/ride/track.h +++ b/src/ride/track.h @@ -512,7 +512,7 @@ int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b); int sub_6D01B3(uint8 bl, uint8 rideIndex, int x, int y, int z); int save_track_design(uint8 rideIndex); int install_track(char* source_path, char* dest_name); -void window_track_list_format_name(char *dst, const char *src, char colour, char quotes); +void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool quotes); void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void track_save_reset_scenery(); diff --git a/src/windows/error.c b/src/windows/error.c index 3a1b232952..90576f6b61 100644 --- a/src/windows/error.c +++ b/src/windows/error.c @@ -80,7 +80,8 @@ static uint16 _window_error_num_lines; */ void window_error_open(rct_string_id title, rct_string_id message) { - char *dst, *args; + utf8 *dst; + char *args; int numLines, fontHeight, x, y, width, height, maxY; rct_window *w; @@ -89,17 +90,17 @@ void window_error_open(rct_string_id title, rct_string_id message) args = (char*)0x0013CE952; // Format the title - *dst++ = FORMAT_BLACK; + dst = utf8_write_codepoint(dst, FORMAT_BLACK); if (title != (rct_string_id)STR_NONE) { format_string(dst, title, args); - dst += get_string_size(dst) - 1; + dst = get_string_end(dst); } // Format the message if (message != (rct_string_id)STR_NONE) { - *dst++ = FORMAT_NEWLINE; + dst = utf8_write_codepoint(dst, FORMAT_NEWLINE); format_string(dst, message, args); - dst += get_string_size(dst) - 1; + dst = get_string_end(dst); } log_verbose("show error, %s", _window_error_text + 1);