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
This commit is contained in:
fgsfds 2020-05-22 00:27:51 +03:00
parent 1298cd6017
commit aaf6eab582
3 changed files with 54 additions and 31 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;