diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index c08c63c1d7..8b2e44754b 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3821,3 +3821,4 @@ STR_5481 :Themes STR_5482 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}1 minute STR_5483 :{BLACK}({COMMA16} weeks remaining) STR_5484 :{BLACK}({COMMA16} week remaining) +STR_5485 :{SMALLFONT}{STRING} diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 83f5fa864c..11f8199a9e 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -132,7 +132,7 @@ void draw_string_centred_raw(rct_drawpixelinfo *dpi, int x, int y, int numLines, void gfx_draw_string_right(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y); void draw_string_right_underline(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y); int string_get_height_raw(char *buffer); -void sub_6C1F57(rct_drawpixelinfo *dpi, int x, int y, int width, int colour, rct_string_id format, void *args, int ticks); +void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int y, int width, int colour, rct_string_id format, void *args, int ticks); bool ttf_initialise(); void ttf_dispose(); diff --git a/src/drawing/scrolling_text.c b/src/drawing/scrolling_text.c index 4b421b9e5d..378eca1b4c 100644 --- a/src/drawing/scrolling_text.c +++ b/src/drawing/scrolling_text.c @@ -107,6 +107,10 @@ static void scrolling_text_format(utf8 *dst, rct_draw_scroll_text *scrollText) /** * * rct2: 0x006C42D9 + * @param stringId (ax) + * @param scroll (cx) + * @param scrollingMode (bp) + * @returns ebx */ int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode) { diff --git a/src/drawing/string.c b/src/drawing/string.c index 2422155d54..30770addfa 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -707,18 +707,63 @@ int string_get_height_raw(char *buffer) * width : bp * ticks : ebp >> 16 */ -void sub_6C1F57(rct_drawpixelinfo *dpi, int x, int y, int width, int colour, rct_string_id format, void *args, int ticks) +void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int y, int width, int colour, rct_string_id format, void *args, int ticks) { - RCT2_CALLPROC_X( - 0x006C1F57, - colour, - format, - x, - y, - (int)args, - (int)dpi, - (width & 0xFFFF) | (ticks << 16) - ); + int numLines, fontSpriteBase, lineHeight, lineY; + utf8 *buffer = (utf8*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM; + gfx_draw_string(dpi, (char*)0x009C383D, colour, dpi->x, dpi->y); + format_string(buffer, format, args); + + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM; + gfx_wrap_string(buffer, width, &numLines, &fontSpriteBase); + switch (fontSpriteBase) { + case FONT_SPRITE_BASE_TINY: + lineHeight = 6; + break; + default: + case FONT_SPRITE_BASE_SMALL: + case FONT_SPRITE_BASE_MEDIUM: + lineHeight = 10; + break; + case FONT_SPRITE_BASE_BIG: + lineHeight = 18; + break; + } + + int numCharactersDrawn = 0; + int numCharactersToDraw = ticks; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; + lineY = y; + for (int line = 0; line <= numLines; line++) { + int halfWidth = gfx_get_string_width(buffer) / 2; + + utf8 *ch = buffer; + utf8 *nextCh; + int codepoint; + while ((codepoint = utf8_get_next(ch, &nextCh)) != 0) { + if (!utf8_is_format_code(codepoint)) { + numCharactersDrawn++; + if (numCharactersDrawn > numCharactersToDraw) { + *ch = 0; + break; + } + } + ch = nextCh; + } + + gfx_draw_string(dpi, buffer, 0xFE, x - halfWidth, lineY); + + if (numCharactersDrawn > numCharactersToDraw) { + break; + } + + buffer = get_string_end(buffer) + 1; + lineY += lineHeight; + } } static uint32 _ttf_surface_cache_hash(TTF_Font *font, const utf8 *text) diff --git a/src/hook.c b/src/hook.c index 26733d6b24..185d4680b5 100644 --- a/src/hook.c +++ b/src/hook.c @@ -25,11 +25,13 @@ void* g_hooktableaddress = 0; int g_hooktableoffset = 0; int g_maxhooks = 1000; -void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned) +void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister) { int i = 0; char data[100]; + registersreturned |= eaxDestinationRegister; + int registerssaved = 7; int n = registersreturned; for (; n; registerssaved--) { @@ -146,6 +148,39 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in // returnlocation: + switch (eaxDestinationRegister) { + case EBX: + // mov ebx, eax + data[i++] = 0x8B; + data[i++] = 0xD8; + break; + case ECX: + // mov ecx, eax + data[i++] = 0x8B; + data[i++] = 0xC8; + break; + case EDX: + // mov ecx, eax + data[i++] = 0x8B; + data[i++] = 0xD0; + break; + case ESI: + // mov ecx, eax + data[i++] = 0x8B; + data[i++] = 0xF0; + break; + case EDI: + // mov ecx, eax + data[i++] = 0x8B; + data[i++] = 0xF8; + break; + case EBP: + // mov ecx, eax + data[i++] = 0x8B; + data[i++] = 0xE8; + break; + } + data[i++] = 0x83; // sub esp, x data[i++] = 0xEC; data[i++] = (signed char)(stacksize * -4) - rargssize; @@ -177,7 +212,7 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0); } -void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned) +void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister) { if (!g_hooktableaddress) { g_hooktableaddress = VirtualAllocEx(GetCurrentProcess(), NULL, g_maxhooks * 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -192,6 +227,6 @@ void addhook(int address, int newaddress, int stacksize, int registerargs[], int *((int *)&data[i]) = hookaddress - address - i - 4; i += 4; data[i++] = 0xC3; // retn WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0); - hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned); + hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned, eaxDestinationRegister); g_hooktableoffset++; } \ No newline at end of file diff --git a/src/hook.h b/src/hook.h index fed10792f3..1e0628b95b 100644 --- a/src/hook.h +++ b/src/hook.h @@ -32,6 +32,6 @@ enum REGISTER_ARGS { END = 0 }; -void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned); +void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister); #endif \ No newline at end of file diff --git a/src/openrct2.c b/src/openrct2.c index 8177e3e830..04a2babcc9 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -188,11 +188,13 @@ bool openrct2_initialise() title_sequences_load_presets(); // Hooks to allow RCT2 to call OpenRCT2 functions instead - addhook(0x006E732D, (int)gfx_set_dirty_blocks, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0); // remove when all callers are decompiled - addhook(0x006E7499, (int)gfx_redraw_screen_rect, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0); // remove when 0x6E7FF3 is decompiled - addhook(0x006B752C, (int)ride_crash, 0, (int[]){ EDX, EBX, END }, 0); // remove when all callers are decompiled - addhook(0x0069A42F, (int)peep_window_state_update, 0, (int[]){ ESI, END }, 0); // remove when all callers are decompiled - addhook(0x006BB76E, (int)sound_play_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, EAX); // remove when all callers are decompiled + addhook(0x006E732D, (int)gfx_set_dirty_blocks, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0); // remove when all callers are decompiled + addhook(0x006E7499, (int)gfx_redraw_screen_rect, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0); // remove when 0x6E7FF3 is decompiled + addhook(0x006B752C, (int)ride_crash, 0, (int[]){ EDX, EBX, END }, 0, 0); // remove when all callers are decompiled + addhook(0x0069A42F, (int)peep_window_state_update, 0, (int[]){ ESI, END }, 0, 0); // remove when all callers are decompiled + addhook(0x006BB76E, (int)sound_play_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, EAX, 0); // remove when all callers are decompiled + addhook(0x006C42D9, (int)scrolling_text_setup, 0, (int[]){EAX, ECX, EBP, END}, 0, EBX); // remove when all callers are decompiled + addhook(0x006C2321, (int)gfx_get_string_width, 0, (int[]){ESI, END}, 0, ECX); // remove when all callers are decompiled if (!rct2_init()) return false; diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index 912af9919e..e21333a4cc 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -523,13 +523,12 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc ); // Text - stringId = 1926; - utf8 *buffer = (utf8*)0x009B5F2C; - memcpy(buffer, &newsItem->text, 256); + stringId = 5485; + utf8 *newsItemText = newsItem->text; x = w->x + (middleOutsetWidget->left + middleOutsetWidget->right) / 2; y = w->y + middleOutsetWidget->top + 11; width = middleOutsetWidget->right - middleOutsetWidget->left - 62; - sub_6C1F57(dpi, x, y, width, 14, stringId, NULL, newsItem->ticks); + gfx_draw_string_centred_wrapped_partial(dpi, x, y, width, 14, stringId, &newsItemText, newsItem->ticks); x = w->x + window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].left; y = w->y + window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].top;