diff --git a/data/dynos_misc.cpp b/data/dynos_misc.cpp index 44728de9c..c13964351 100644 --- a/data/dynos_misc.cpp +++ b/data/dynos_misc.cpp @@ -3,100 +3,6 @@ extern "C" { #include "game/scroll_targets.h" } -// -// String -// - -static const struct { const char *mStr; u8 mChar64; s32 mWidth; } sSm64CharMap[] = { - { "0", 0x00, 7 }, { "1", 0x01, 7 }, { "2", 0x02, 7 }, { "3", 0x03, 7 }, { "4", 0x04, 7 }, { "5", 0x05, 7 }, - { "6", 0x06, 7 }, { "7", 0x07, 7 }, { "8", 0x08, 7 }, { "9", 0x09, 7 }, { "A", 0x0A, 6 }, { "B", 0x0B, 6 }, - { "C", 0x0C, 6 }, { "D", 0x0D, 6 }, { "E", 0x0E, 6 }, { "F", 0x0F, 6 }, { "G", 0x10, 6 }, { "H", 0x11, 6 }, - { "I", 0x12, 5 }, { "J", 0x13, 6 }, { "K", 0x14, 6 }, { "L", 0x15, 5 }, { "M", 0x16, 8 }, { "N", 0x17, 8 }, - { "O", 0x18, 6 }, { "P", 0x19, 6 }, { "Q", 0x1A, 6 }, { "R", 0x1B, 6 }, { "S", 0x1C, 6 }, { "T", 0x1D, 5 }, - { "U", 0x1E, 6 }, { "V", 0x1F, 6 }, { "W", 0x20, 8 }, { "X", 0x21, 7 }, { "Y", 0x22, 6 }, { "Z", 0x23, 6 }, - { "a", 0x24, 6 }, { "b", 0x25, 5 }, { "c", 0x26, 5 }, { "d", 0x27, 6 }, { "e", 0x28, 5 }, { "f", 0x29, 5 }, - { "g", 0x2A, 6 }, { "h", 0x2B, 5 }, { "i", 0x2C, 4 }, { "j", 0x2D, 5 }, { "k", 0x2E, 5 }, { "l", 0x2F, 3 }, - { "m", 0x30, 7 }, { "n", 0x31, 5 }, { "o", 0x32, 5 }, { "p", 0x33, 5 }, { "q", 0x34, 6 }, { "r", 0x35, 5 }, - { "s", 0x36, 5 }, { "t", 0x37, 5 }, { "u", 0x38, 5 }, { "v", 0x39, 5 }, { "w", 0x3A, 7 }, { "x", 0x3B, 7 }, - { "y", 0x3C, 5 }, { "z", 0x3D, 5 }, { "\'", 0x3E, 4 }, { ".", 0x3F, 4 }, { "^", 0x50, 8 }, { "|", 0x51, 8 }, - { "<", 0x52, 8 }, { ">", 0x53, 8 }, { "[A]", 0x54, 7 }, { "[B]", 0x55, 7 }, { "[C]", 0x56, 6 }, { "[Z]", 0x57, 7 }, - { "[R]", 0x58, 7 }, { ",", 0x6F, 4 }, { " ", 0x9E, 5 }, { "-", 0x9F, 6 }, { "/", 0xD0, 10 }, { "[%]", 0xE0, 7 }, - { "(", 0xE1, 5 }, { ")(", 0xE2, 10 }, { ")", 0xE3, 5 }, { "+", 0xE4, 9 }, { "&", 0xE5, 8 }, { ":", 0xE6, 4 }, - { "!", 0xF2, 5 }, { "%", 0xF3, 7 }, { "?", 0xF4, 7 }, { "~", 0xF7, 8 }, { "$", 0xF9, 8 }, { "@", 0xFA, 10 }, - { "*", 0xFB, 6 }, { "=", 0xFD, 10 }, { "\n", 0xFE, 0 }, -}; - -static const char *DynOS_String_AddChar64(u8 *aStr64, const char *pStr, s32 &aIndex) { - for (const auto &c : sSm64CharMap) { - if (strstr(pStr, c.mStr) == pStr) { - aStr64[aIndex++] = c.mChar64; - return pStr + strlen(c.mStr); - } - } - - // Put a space by default - aStr64[aIndex++] = 0x9E; - return pStr + 1; -} - -u8 *DynOS_String_Convert(const char *aString, bool aHeapAlloc) { - - // Allocation - static u8 sStringBuffer[8][2048]; - static u32 sStringBufferIndex = 0; - u8 *_Str64; - if (aHeapAlloc) { - _Str64 = New(2048); - } else { - _Str64 = sStringBuffer[sStringBufferIndex]; - sStringBufferIndex = (sStringBufferIndex + 1) % 8; - } - - // Conversion - memset(_Str64, 0xFF, 2048); - const char *pStr = aString; - for (s32 i = 0; *pStr != 0 && i < 2047;) { - pStr = DynOS_String_AddChar64(_Str64, pStr, i); - } - return _Str64; -} - -u8 *DynOS_String_Decapitalize(u8 *aStr64) { - bool _WasSpace = true; - for (u8 *pStr64 = aStr64; *pStr64 != 0xFF; pStr64++) { - if (*pStr64 >= 10 && *pStr64 <= 35) { - if (_WasSpace) _WasSpace = false; - else *pStr64 += 26; - } else if (*pStr64 >= 63) { - _WasSpace = true; - } - } - return aStr64; -} - -s32 DynOS_String_Length(const u8 *aStr64) { - s32 _Length = 0; - for (; aStr64 && *aStr64 != 255; aStr64++, _Length++); - return _Length; -} - -s32 DynOS_String_WidthChar64(u8 aChar64) { - for (const auto &c : sSm64CharMap) { - if (c.mChar64 == aChar64) { - return c.mWidth; - } - } - return 0; -} - -s32 DynOS_String_Width(const u8 *aStr64) { - s32 _Width = 0; - for (; *aStr64 != 0xFF; aStr64++) { - _Width += DynOS_String_WidthChar64(*aStr64); - } - return _Width; -} - // // Scroll Targets // diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 6aed98165..637c099a2 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -448,86 +448,6 @@ void render_multi_text_string(s16 *xPos, s16 *yPos, s8 multiTextID) } #endif -u8 str_ascii_char_to_dialog(char c) { - switch (c) { - case '/': return 0xD0; - case '>': return 0x53; - case '<': return 0x52; - case '|': return 0x51; - case '^': return 0x50; - case '\n': return 0xFE; - case '$': return 0xF9; - case '~': return 0xF7; - case '?': return 0xF4; - case '%': return 0xF3; - case '!': return 0xF2; - case ':': return 0xE6; - case '&': return 0xE5; - case '+': return 0xE4; - case ')': return 0xE3; - case '(': return 0xE1; - case '-': return 0x9F; - case ' ': return 0x9E; - case ',': return 0x6F; - case '.': return 0x3F; - case '@': return 0xFA; - case '*': return 0xFB; - case '=': return 0xFD; - case '\'': return 0x3E; - case '\0': return DIALOG_CHAR_TERMINATOR; - default: return ((u8)c < 0xF0) ? ASCII_TO_DIALOG(c) : c; - } -} - -void str_ascii_to_dialog(const char* string, u8* dialog, u16 length) { - const char* c = string; - u8* d = dialog; - u16 converted = 0; - - while (*c != '\0' && converted < (length - 1)) { - if (!strncmp(c, "you", 3) && (c[3] < 'a' || c[3] > 'z')) { - *d = 0xD2; - c += 2; - } else if (!strncmp(c, "the", 3) && (c[3] < 'a' || c[3] > 'z')) { - *d = 0xD1; - c += 2; - } else if (!strncmp(c, "[R]", 3)) { - *d = 0x58; - c += 2; - } else if (!strncmp(c, "[Z]", 3)) { - *d = 0x57; - c += 2; - } else if (!strncmp(c, "[C]", 3)) { - *d = 0x56; - c += 2; - } else if (!strncmp(c, "[B]", 3)) { - *d = 0x55; - c += 2; - } else if (!strncmp(c, "[A]", 3)) { - *d = 0x54; - c += 2; - } else if (!strncmp(c, "[Z]", 3)) { - *d = 0x57; - c += 2; - } else if (!strncmp(c, ")(", 2)) { - *d = 0xE2; - c += 1; - } else if (!strncmp(c, "[%]", 3)) { - *d = 0xE0; - c += 2; - } else if (!strncmp(c, "★", 2)) { - *d = 0xFA; - c += 2; - } else { - *d = str_ascii_char_to_dialog(*c); - } - d++; - c++; - converted++; - } - *d = DIALOG_CHAR_TERMINATOR; -} - f32 get_generic_dialog_width(u8* dialog) { #ifdef VERSION_JP return 0; @@ -551,7 +471,7 @@ f32 get_generic_dialog_width(u8* dialog) { f32 get_generic_ascii_string_width(const char* ascii) { u8 dialog[256] = { DIALOG_CHAR_TERMINATOR }; - str_ascii_to_dialog(ascii, dialog, strlen(ascii)); + convert_string_ascii_to_sm64(dialog, ascii, false); return get_generic_dialog_width(dialog); } @@ -567,13 +487,13 @@ f32 get_generic_dialog_height(u8* dialog) { f32 get_generic_ascii_string_height(const char* ascii) { u8 dialog[256] = { DIALOG_CHAR_TERMINATOR }; - str_ascii_to_dialog(ascii, dialog, strlen(ascii)); + convert_string_ascii_to_sm64(dialog, ascii, false); return get_generic_dialog_height(dialog); } void print_generic_ascii_string(s16 x, s16 y, const char* ascii) { u8 dialog[256] = { DIALOG_CHAR_TERMINATOR }; - str_ascii_to_dialog(ascii, dialog, strlen(ascii)); + convert_string_ascii_to_sm64(dialog, ascii, false); print_generic_string(x, y, dialog); } @@ -2637,7 +2557,7 @@ void render_pause_camera_options(s16 x, s16 y, s8 *index, s16 xIndex) { void render_pause_course_options(s16 x, s16 y, s8 *index, s16 yIndex) { u8 TEXT_EXIT_TO_CASTLE[16] = { DIALOG_CHAR_TERMINATOR }; - str_ascii_to_dialog("EXIT TO CASTLE", TEXT_EXIT_TO_CASTLE, 15); + convert_string_ascii_to_sm64(TEXT_EXIT_TO_CASTLE, "EXIT TO CASTLE", false); #ifdef VERSION_EU u8 textContinue[][10] = { diff --git a/src/game/level_info.c b/src/game/level_info.c index 98aaeb962..1436f5518 100644 --- a/src/game/level_info.c +++ b/src/game/level_info.c @@ -40,7 +40,7 @@ const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[] = { { "z", 0x3D, 0 }, // Punctuation - { "...", 0xE6, 0 }, // ellipsis + { ":", 0xE6, 0 }, // colon { ")(", 0xE2, 0 }, // close-open parentheses { "<<", 0xF5, 0 }, // double quote open { ">>", 0xF6, 0 }, // double quote close @@ -67,16 +67,17 @@ const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[] = { { "[C]", 0x56, 0 }, // bold C { "[Z]", 0x57, 0 }, // bold Z { "[R]", 0x58, 0 }, // bold R - { "<->", 0xE4, 0 }, // left-right arrow + { "+", 0xE4, 0 }, // left-right arrow { "^", 0x50, 0 }, // up arrow { "|", 0x51, 0 }, // down arrow { "<", 0x52, 0 }, // left arrow { ">", 0x53, 0 }, // right arrow - { "+", 0xF9, 1 }, // coin - { "@", 0xFA, 1 }, // star filled + { "$", 0xF9, 1 }, // coin + { "★", 0xFA, 1 }, // star filled + { "@", 0xFA, 1 }, // star filled (both ★ and @ match 0xFA) { "*", 0xFB, 1 }, // multiply - { "•", 0xFC, 0 }, - { "$", 0xFD, 0 }, // star empty + { "•", 0xFC, 0 }, // interpunct (unused) + { "=", 0xFD, 0 }, // star empty { "\n", 0xFE, 1 }, // New line { NULL, 0xFF, 1 }, // Null terminator }; diff --git a/src/game/level_info.h b/src/game/level_info.h index 9ffb3afe9..a9dd52958 100644 --- a/src/game/level_info.h +++ b/src/game/level_info.h @@ -7,6 +7,8 @@ void **get_course_name_table(void); void **get_course_name_table_original(void); void **get_act_name_table(void); void **get_act_name_table_original(void); +void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu); +void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64); /* |description| Returns the name of the level corresponding to `courseNum`, `levelNum` and `areaIndex` as an ASCII (human readable) string. Set `charCase` to 1 to capitalize or -1 to decapitalize the returned string diff --git a/src/pc/lua/utils/smlua_text_utils.c b/src/pc/lua/utils/smlua_text_utils.c index 6c72f7ef0..c0aac16ae 100644 --- a/src/pc/lua/utils/smlua_text_utils.c +++ b/src/pc/lua/utils/smlua_text_utils.c @@ -21,7 +21,6 @@ static bool sReplacedDialog[DIALOG_COUNT] = { 0 }; #define INVALID_COURSE_NUM(courseNum) (smlua_level_util_get_info_from_course_num(courseNum) == NULL && !COURSE_IS_VALID_COURSE(courseNum)) extern const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[]; -void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64); static size_t measure_converted_sm64_string(const u8* str64) { size_t len = 0; @@ -146,9 +145,8 @@ void smlua_text_utils_shutdown(void) { } static u8* smlua_text_utils_convert(const char* str) { - s32 len = strlen(str); - u8* dialogStr = calloc(len + 2, sizeof(u8)); - str_ascii_to_dialog(str, dialogStr, len + 1); + u8* dialogStr = calloc(strlen(str) + 2, sizeof(u8)); + convert_string_ascii_to_sm64(dialogStr, str, false); return dialogStr; }