From aaf6eab582b7f1642effcb3de519e963a989fb9c Mon Sep 17 00:00:00 2001 From: fgsfds Date: Fri, 22 May 2020 00:27:51 +0300 Subject: [PATCH] fix text rendering on JP and (maybe) EU also cache converted IA1 characters so it wouldn't reconvert them every goddamn time they're rendered --- include/macros.h | 16 +++++++++++ src/game/ingame_menu.c | 62 +++++++++++++++++++++++++----------------- src/game/save_file.c | 7 +---- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/include/macros.h b/include/macros.h index bcace7fb..478d6ce2 100644 --- a/include/macros.h +++ b/include/macros.h @@ -51,4 +51,20 @@ #define PHYSICAL_TO_VIRTUAL(addr) ((uintptr_t)(addr)) #define VIRTUAL_TO_PHYSICAL2(addr) ((void *)(addr)) +// Byteswap macros +#define BSWAP16(x) \ + ( (((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00) ) +#define BSWAP32(x) \ + ( (((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \ + (((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) ) + +// Convenience macros for endian conversions +#if IS_BIG_ENDIAN +#define BE_TO_HOST16(x) (x) +#define BE_TO_HOST32(x) (x) +#else +#define BE_TO_HOST16(x) BSWAP16(x) +#define BE_TO_HOST32(x) BSWAP32(x) +#endif + #endif diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 4ef6ecf8..8661568e 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -19,6 +19,7 @@ #include "print.h" #include "engine/math_util.h" #include "course_table.h" +#include "macros.h" #include "pc/cheats.h" #ifdef BETTERCAMERA #include "bettercamera.h" @@ -127,6 +128,16 @@ u8 gMenuHoldKeyIndex = 0; u8 gMenuHoldKeyTimer = 0; s32 gDialogResponse = 0; +#if defined(VERSION_JP) || defined(VERSION_SH) || defined(VERSION_EU) +#ifdef VERSION_EU +#define CHCACHE_BUFLEN (8 * 8) // EU only converts 8x8 characters +#else +#define CHCACHE_BUFLEN (8 * 16) // JP only converts 8x16 or 16x8 characters +#endif +// stores char data unpacked from ia1 to ia8 or ia1 to ia4 +// so that it won't be reconverted every time a character is rendered +static struct CachedChar { u8 used; u8 data[CHCACHE_BUFLEN]; } charCache[256]; +#endif // VERSION void create_dl_identity_matrix(void) { Mtx *matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); @@ -206,23 +217,19 @@ void create_dl_ortho_matrix(void) { gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(matrix), G_MTX_PROJECTION | G_MTX_MUL | G_MTX_NOPUSH) } -static u8 *alloc_ia8_text_from_i1(u16 *in, s16 width, s16 height) { +#if defined(VERSION_JP) || defined(VERSION_SH) +static inline void alloc_ia8_text_from_i1(u8 *out, u16 *in, s16 width, s16 height) { s32 inPos; u16 bitMask; - u8 *out; + u16 inWord; s16 outPos = 0; - out = alloc_display_list((u32) width * (u32) height); - - if (out == NULL) { - return NULL; - } - for (inPos = 0; inPos < (width * height) / 16; inPos++) { + inWord = BE_TO_HOST16(in[inPos]); bitMask = 0x8000; while (bitMask != 0) { - if (in[inPos] & bitMask) { + if (inWord & bitMask) { out[outPos] = 0xFF; } else { out[outPos] = 0x00; @@ -232,10 +239,17 @@ static u8 *alloc_ia8_text_from_i1(u16 *in, s16 width, s16 height) { outPos++; } } - - return out; } +static inline u8 *convert_ia8_char(u8 c, u16 *tex, s16 w, s16 h) { + if (!charCache[c].used) { + charCache[c].used = 1; + alloc_ia8_text_from_i1(charCache[c].data, tex, w, h); + } + return charCache[c].data; +} +#endif + void render_generic_char(u8 c) { void **fontLUT; void *packedTexture; @@ -247,7 +261,7 @@ void render_generic_char(u8 c) { packedTexture = segmented_to_virtual(fontLUT[c]); #if defined(VERSION_JP) || defined(VERSION_SH) - unpackedTexture = alloc_ia8_text_from_i1(packedTexture, 8, 16); + unpackedTexture = convert_ia8_char(c, packedTexture, 8, 16); gDPPipeSync(gDisplayListHead++); gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_8b, 1, VIRTUAL_TO_PHYSICAL(unpackedTexture)); @@ -265,20 +279,12 @@ void render_generic_char(u8 c) { } #ifdef VERSION_EU -u8 *alloc_ia4_tex_from_i1(u8 *in, s16 width, s16 height) { +static inline void alloc_ia4_tex_from_i1(u8 *out, u8 *in, s16 width, s16 height) { u32 size = (u32) width * (u32) height; - u8 *out; s32 inPos; - s16 outPos; + s16 outPos = 0; u8 bitMask; - outPos = 0; - out = (u8 *) alloc_display_list(size); - - if (out == NULL) { - return NULL; - } - for (inPos = 0; inPos < (width * height) / 4; inPos++) { bitMask = 0x80; while (bitMask != 0) { @@ -289,8 +295,14 @@ u8 *alloc_ia4_tex_from_i1(u8 *in, s16 width, s16 height) { outPos++; } } +} - return out; +static inline u8 *convert_ia4_char(u8 c, u8 *tex, s16 w, s16 h) { + if (!charCache[c].used) { + charCache[c].used = 1; + alloc_ia4_tex_from_i1(charCache[c].data, tex, w, h); + } + return charCache[c].data; } void render_generic_char_at_pos(s16 xPos, s16 yPos, u8 c) { @@ -300,7 +312,7 @@ void render_generic_char_at_pos(s16 xPos, s16 yPos, u8 c) { fontLUT = segmented_to_virtual(main_font_lut); packedTexture = segmented_to_virtual(fontLUT[c]); - unpackedTexture = alloc_ia4_tex_from_i1(packedTexture, 8, 8); + unpackedTexture = convert_ia4_char(c, packedTexture, 8, 8); gDPPipeSync(gDisplayListHead++); gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, VIRTUAL_TO_PHYSICAL(unpackedTexture)); @@ -1025,7 +1037,7 @@ void render_generic_dialog_char_at_pos(struct DialogEntry *dialog, s16 x, s16 y, fontLUT = segmented_to_virtual(main_font_lut); packedTexture = segmented_to_virtual(fontLUT[c]); - unpackedTexture = alloc_ia4_tex_from_i1(packedTexture, 8, 8); + unpackedTexture = convert_ia4_char(c, packedTexture, 8, 8); gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, VIRTUAL_TO_PHYSICAL(unpackedTexture)); gSPDisplayList(gDisplayListHead++, dl_ia_text_tex_settings); diff --git a/src/game/save_file.c b/src/game/save_file.c index d7899314..9facaf3c 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -11,17 +11,12 @@ #include "level_table.h" #include "course_table.h" #include "thread6.h" +#include "macros.h" #include "pc/ini.h" #define MENU_DATA_MAGIC 0x4849 #define SAVE_FILE_MAGIC 0x4441 -#define BSWAP16(x) \ - ( (((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00) ) -#define BSWAP32(x) \ - ( (((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \ - (((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000) ) - STATIC_ASSERT(sizeof(struct SaveBuffer) == EEPROM_SIZE, "eeprom buffer size must match"); extern struct SaveBuffer gSaveBuffer;