mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-24 00:03:11 +01:00
implement utf8, part 15
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
41
src/hook.c
41
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++;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user