Skip to content

Commit

Permalink
Enable GF move names by default
Browse files Browse the repository at this point in the history
Many names of moves are unofficial shortenings of names due to a 12
character limit in vanilla Emerald.

This change dynamically chooses the font to render move names in, based
on the amount of space available. It introduces FONT_NARROWER, a 3px on
average font to be able to fit long names into places where FONT_NARROW
isn't enough (e.g. the battle UI).

In contests, even FONT_NARROWER isn't sufficient to prevent clipping in
all cases. e.g. Stomping Tantrum clips. We have decided to accept that
cost to make the rest of the user experience better, but downstream
projects that don't like that trade-off can either a) alter the contest
UI, or b) set B_EXPANDED_MOVE_NAMES to FALSE.
  • Loading branch information
mrgriffin committed Mar 5, 2024
1 parent ac2e53d commit ef52486
Show file tree
Hide file tree
Showing 29 changed files with 298 additions and 43 deletions.
1 change: 1 addition & 0 deletions charmap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ FONT_NORMAL = FC 06 01
FONT_SHORT = FC 06 02
FONT_NARROW = FC 06 07
FONT_SMALL_NARROW = FC 06 08
FONT_NARROWER = FC 06 0A

@ colors

Expand Down
108 changes: 105 additions & 3 deletions gflib/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@ static u16 FontFunc_ShortCopy2(struct TextPrinter *);
static u16 FontFunc_ShortCopy3(struct TextPrinter *);
static u16 FontFunc_Narrow(struct TextPrinter *);
static u16 FontFunc_SmallNarrow(struct TextPrinter *);
static u16 FontFunc_Narrower(struct TextPrinter *);
static void DecompressGlyph_Small(u16, bool32);
static void DecompressGlyph_Normal(u16, bool32);
static void DecompressGlyph_Short(u16, bool32);
static void DecompressGlyph_Narrow(u16, bool32);
static void DecompressGlyph_SmallNarrow(u16, bool32);
static void DecompressGlyph_Bold(u16);
static void DecompressGlyph_Narrower(u16, bool32);
static u32 GetGlyphWidth_Small(u16, bool32);
static u32 GetGlyphWidth_Normal(u16, bool32);
static u32 GetGlyphWidth_Short(u16, bool32);
static u32 GetGlyphWidth_Narrow(u16, bool32);
static u32 GetGlyphWidth_SmallNarrow(u16, bool32);
static u32 GetGlyphWidth_Narrower(u16, bool32);

static EWRAM_DATA struct TextPrinter sTempTextPrinter = {0};
static EWRAM_DATA struct TextPrinter sTextPrinters[WINDOWS_MAX] = {0};
Expand Down Expand Up @@ -89,7 +92,8 @@ static const struct GlyphWidthFunc sGlyphWidthFuncs[] =
{ FONT_SHORT_COPY_3, GetGlyphWidth_Short },
{ FONT_BRAILLE, GetGlyphWidth_Braille },
{ FONT_NARROW, GetGlyphWidth_Narrow },
{ FONT_SMALL_NARROW, GetGlyphWidth_SmallNarrow }
{ FONT_SMALL_NARROW, GetGlyphWidth_SmallNarrow },
{ FONT_NARROWER, GetGlyphWidth_Narrower },
};

struct
Expand Down Expand Up @@ -217,7 +221,17 @@ static const struct FontInfo sFontInfos[] =
.fgColor = 1,
.bgColor = 2,
.shadowColor = 15,
}
},
[FONT_NARROWER] = {
.fontFunction = FontFunc_Narrower,
.maxLetterWidth = 5,
.maxLetterHeight = 16,
.letterSpacing = 0,
.lineSpacing = 0,
.fgColor = 2,
.bgColor = 1,
.shadowColor = 3,
},
};

static const u8 sMenuCursorDimensions[][2] =
Expand All @@ -231,7 +245,8 @@ static const u8 sMenuCursorDimensions[][2] =
[FONT_BRAILLE] = { 8, 16 },
[FONT_NARROW] = { 8, 15 },
[FONT_SMALL_NARROW] = { 8, 8 },
[FONT_BOLD] = {}
[FONT_BOLD] = {},
[FONT_NARROWER] = { 8, 15 },
};

static const u16 sFontBoldJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/bold.hwjpnfont");
Expand Down Expand Up @@ -813,6 +828,18 @@ static u16 FontFunc_SmallNarrow(struct TextPrinter *textPrinter)
return RenderText(textPrinter);
}

static u16 FontFunc_Narrower(struct TextPrinter *textPrinter)
{
struct TextPrinterSubStruct *subStruct = (struct TextPrinterSubStruct *)(&textPrinter->subStructFields);

if (subStruct->hasFontIdBeenSet == FALSE)
{
subStruct->fontId = FONT_NARROWER;
subStruct->hasFontIdBeenSet = TRUE;
}
return RenderText(textPrinter);
}

void TextPrinterInitDownArrowCounters(struct TextPrinter *textPrinter)
{
struct TextPrinterSubStruct *subStruct = (struct TextPrinterSubStruct *)(&textPrinter->subStructFields);
Expand Down Expand Up @@ -1250,6 +1277,9 @@ static u16 RenderText(struct TextPrinter *textPrinter)
case FONT_SMALL_NARROW:
DecompressGlyph_SmallNarrow(currChar, textPrinter->japanese);
break;
case FONT_NARROWER:
DecompressGlyph_Narrower(currChar, textPrinter->japanese);
break;
case FONT_BRAILLE:
break;
}
Expand Down Expand Up @@ -1832,6 +1862,48 @@ static u32 GetGlyphWidth_Small(u16 glyphId, bool32 isJapanese)
return gFontSmallLatinGlyphWidths[glyphId];
}

static void DecompressGlyph_Narrower(u16 glyphId, bool32 isJapanese)
{
const u16 *glyphs;

if (isJapanese == TRUE)
{
glyphs = gFontNormalJapaneseGlyphs + (0x100 * (glyphId >> 0x4)) + (0x8 * (glyphId % 0x10));
DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop);
DecompressGlyphTile(glyphs + 0x80, gCurGlyph.gfxBufferBottom);
gCurGlyph.width = 8;
gCurGlyph.height = 15;
}
else
{
glyphs = gFontNarrowerLatinGlyphs + (0x20 * glyphId);
gCurGlyph.width = gFontNarrowerLatinGlyphWidths[glyphId];

if (gCurGlyph.width <= 8)
{
DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop);
DecompressGlyphTile(glyphs + 0x10, gCurGlyph.gfxBufferBottom);
}
else
{
DecompressGlyphTile(glyphs, gCurGlyph.gfxBufferTop);
DecompressGlyphTile(glyphs + 0x8, gCurGlyph.gfxBufferTop + 8);
DecompressGlyphTile(glyphs + 0x10, gCurGlyph.gfxBufferBottom);
DecompressGlyphTile(glyphs + 0x18, gCurGlyph.gfxBufferBottom + 8);
}

gCurGlyph.height = 15;
}
}

static u32 GetGlyphWidth_Narrower(u16 glyphId, bool32 isJapanese)
{
if (isJapanese == TRUE)
return 8;
else
return gFontNarrowerLatinGlyphWidths[glyphId];
}

static void DecompressGlyph_Narrow(u16 glyphId, bool32 isJapanese)
{
const u16 *glyphs;
Expand Down Expand Up @@ -2012,3 +2084,33 @@ static void DecompressGlyph_Bold(u16 glyphId)
gCurGlyph.width = 8;
gCurGlyph.height = 12;
}

static const s8 sNarrowerFontIds[] =
{
[FONT_SMALL] = FONT_SMALL_NARROW,
[FONT_NORMAL] = FONT_NARROW,
[FONT_SHORT] = -1,
[FONT_SHORT_COPY_1] = -1,
[FONT_SHORT_COPY_2] = -1,
[FONT_SHORT_COPY_3] = -1,
[FONT_BRAILLE] = -1,
[FONT_NARROW] = FONT_NARROWER,
[FONT_SMALL_NARROW] = -1,
[FONT_BOLD] = -1,
[FONT_NARROWER] = -1,
};

// If the narrowest font ID doesn't fit the text, we still return that
// ID because clipping is better than crashing.
u32 GetFontIdToFit(const u8 *string, u32 fontId, u32 letterSpacing, u32 widthPx)
{
for (;;)
{
s32 narrowerFontId = sNarrowerFontIds[fontId];
if (narrowerFontId == -1)
return fontId;
if (GetStringWidth(fontId, string, letterSpacing) <= widthPx)
return fontId;
fontId = narrowerFontId;
}
}
3 changes: 3 additions & 0 deletions gflib/text.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum {
FONT_NARROW,
FONT_SMALL_NARROW, // Very similar to FONT_SMALL, some glyphs are narrower
FONT_BOLD, // JP glyph set only
FONT_NARROWER,
};

// Return values for font functions
Expand Down Expand Up @@ -190,4 +191,6 @@ u8 GetMenuCursorDimensionByFont(u8 fontId, u8 whichDimension);
u16 FontFunc_Braille(struct TextPrinter *textPrinter);
u32 GetGlyphWidth_Braille(u16 glyphId, bool32 isJapanese);

u32 GetFontIdToFit(const u8 *string, u32 widestFontId, u32 letterSpacing, u32 widthPx);

#endif // GUARD_TEXT_H
Binary file added graphics/fonts/latin_narrower.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions graphics_file_rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ $(FONTGFXDIR)/short.latfont: $(FONTGFXDIR)/latin_short.png
$(FONTGFXDIR)/narrow.latfont: $(FONTGFXDIR)/latin_narrow.png
$(GFX) $< $@

$(FONTGFXDIR)/narrower.latfont: $(FONTGFXDIR)/latin_narrower.png
$(GFX) $< $@

$(FONTGFXDIR)/small_narrow.latfont: $(FONTGFXDIR)/latin_small_narrow.png
$(GFX) $< $@

Expand Down
2 changes: 1 addition & 1 deletion include/config/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@
#define B_SHOW_TARGETS TRUE // If set to TRUE, all available targets, for moves hitting 2 or 3 Pokémon, will be shown before selecting a move.
#define B_SHOW_CATEGORY_ICON TRUE // If set to TRUE, it will show an icon in the summary showing the move's category.
#define B_HIDE_HEALTHBOX_IN_ANIMS TRUE // If set to TRUE, hides healthboxes during move animations.
#define B_EXPANDED_MOVE_NAMES FALSE // If set to TRUE, move names are increased from 12 characters to 16 characters.
#define B_EXPANDED_MOVE_NAMES TRUE // If set to FALSE, move names are decreased from 16 characters to 12 characters.
#define B_WAIT_TIME_MULTIPLIER 16 // This determines how long text pauses in battle last. Vanilla is 16. Lower values result in faster battles.
#define B_QUICK_MOVE_CURSOR_TO_RUN FALSE // If set to TRUE, pushing B in the battle options against a wild encounter will move the cursor to the run option

Expand Down
2 changes: 2 additions & 0 deletions include/fonts.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ extern const u16 gFontNarrowLatinGlyphs[];
extern const u8 gFontNarrowLatinGlyphWidths[];
extern const u16 gFontSmallNarrowLatinGlyphs[];
extern const u8 gFontSmallNarrowLatinGlyphWidths[];
extern const u8 gFontNarrowerLatinGlyphWidths[];
extern const u16 gFontNarrowerLatinGlyphs[];

#endif // GUARD_FONTS_H
3 changes: 2 additions & 1 deletion include/list_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ struct ListMenuTemplate
u8 lettersSpacing:3;
u8 itemVerticalPadding:3;
u8 scrollMultiple:2; // x40, x80 = xC0
u8 fontId:6; // x1, x2, x4, x8, x10, x20 = x3F
u8 fontId:5; // x1, x2, x4, x8, x10 = x1F
u8 fontIdMayNarrow:1;
u8 cursorKind:2; // x40, x80
};

Expand Down
9 changes: 9 additions & 0 deletions src/battle_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -3963,6 +3963,15 @@ void BattlePutTextOnWindow(const u8 *text, u8 windowId)
printerTemplate.bgColor = textInfo[windowId].bgColor;
printerTemplate.shadowColor = textInfo[windowId].shadowColor;

if (B_WIN_MOVE_NAME_1 <= windowId && windowId <= B_WIN_MOVE_NAME_4)
{
// 8 * 8 for the width of the window in tiles, and the width of
// a tile in pixels. We cannot check the actual width of the
// window because B_WIN_MOVE_NAME_1 and B_WIN_MOVE_NAME_3 are
// 16 wide for Z-move details.
printerTemplate.fontId = GetFontIdToFit(text, printerTemplate.fontId, printerTemplate.letterSpacing, 8 * 8);
}

if (printerTemplate.x == 0xFF)
{
u32 width = GetBattleWindowTemplatePixelWidth(gBattleScripting.windowsType, windowId);
Expand Down
4 changes: 3 additions & 1 deletion src/contest.c
Original file line number Diff line number Diff line change
Expand Up @@ -1636,7 +1636,9 @@ static void Task_ShowMoveSelectScreen(u8 taskId)
moveNameBuffer = StringCopy(moveNameBuffer, GetMoveName(move));

FillWindowPixelBuffer(i + MOVE_WINDOWS_START, PIXEL_FILL(0));
Contest_PrintTextToBg0WindowAt(i + MOVE_WINDOWS_START, moveName, 5, 1, FONT_NARROW);
// 5 + 7*8 because there are 7 tiles and about 5 extra pixels
// available.
Contest_PrintTextToBg0WindowAt(i + MOVE_WINDOWS_START, moveName, 5, 1, GetFontIdToFit(moveName, FONT_NARROW, 0, 5 + 7 * 8));
}

DrawMoveSelectArrow(eContest.playerMoveChoice);
Expand Down
36 changes: 36 additions & 0 deletions src/fonts.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,42 @@ ALIGNED(4) const u8 gFontNormalLatinGlyphWidths[] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3,
};

ALIGNED(4) const u16 gFontNarrowerLatinGlyphs[] = INCBIN_U16("graphics/fonts/narrower.latfont");
ALIGNED(4) const u8 gFontNarrowerLatinGlyphWidths[] = {
3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4,
8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3,
4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3,
3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4,
3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3,
4, 5, 6, 7, 4, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3,
5, 5, 5, 3, 3, 5, 5, 6, 3, 6, 6, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4,
4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4,
2, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8,
4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3,
10, 10, 10, 10, 8, 8, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3,
};

ALIGNED(4) const u16 gFontSmallJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/small.hwjpnfont");
ALIGNED(4) const u16 gFontNormalJapaneseGlyphs[] = INCBIN_U16("graphics/fonts/normal.hwjpnfont");

Expand Down
11 changes: 10 additions & 1 deletion src/item_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct ListBuffer1 {
};

struct ListBuffer2 {
u8 name[MAX_POCKET_ITEMS][ITEM_NAME_LENGTH + 10];
u8 name[MAX_POCKET_ITEMS][max(ITEM_NAME_LENGTH, MOVE_NAME_LENGTH + 3) + 10];
};

struct TempWallyBag {
Expand Down Expand Up @@ -905,10 +905,19 @@ static void LoadBagItemListBuffers(u8 pocketId)

static void GetItemName(u8 *dest, u16 itemId)
{
u32 fontId;
switch (gBagPosition.pocket)
{
case TMHM_POCKET:
StringCopy(gStringVar2, GetMoveName(ItemIdToBattleMoveId(itemId)));
fontId = GetFontIdToFit(gStringVar2, FONT_NARROW, 0, 7 + 8 * 8);
if (fontId != FONT_NARROW)
{
gStringVar2[0] = EXT_CTRL_CODE_BEGIN;
gStringVar2[1] = EXT_CTRL_CODE_FONT;
gStringVar2[2] = fontId;
StringCopy(&gStringVar2[3], GetMoveName(ItemIdToBattleMoveId(itemId)));
}
if (itemId >= ITEM_HM01)
{
// Get HM number
Expand Down
12 changes: 10 additions & 2 deletions src/list_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,13 +598,18 @@ static u8 ListMenuInitInternal(struct ListMenuTemplate *listMenuTemplate, u16 sc
static void ListMenuPrint(struct ListMenu *list, const u8 *str, u8 x, u8 y)
{
u8 colors[3];
u32 widthPx = (8 * gWindows[list->template.windowId].window.width) - x;

if (gListMenuOverride.enabled)
{
u32 fontId = gListMenuOverride.fontId;
if (list->template.fontIdMayNarrow)
fontId = GetFontIdToFit(str, fontId, gListMenuOverride.lettersSpacing, widthPx);
colors[0] = gListMenuOverride.fillValue;
colors[1] = gListMenuOverride.cursorPal;
colors[2] = gListMenuOverride.cursorShadowPal;
AddTextPrinterParameterized4(list->template.windowId,
gListMenuOverride.fontId,
fontId,
x, y,
gListMenuOverride.lettersSpacing,
0, colors, TEXT_SKIP_DRAW, str);
Expand All @@ -613,11 +618,14 @@ static void ListMenuPrint(struct ListMenu *list, const u8 *str, u8 x, u8 y)
}
else
{
u32 fontId = list->template.fontId;
if (list->template.fontIdMayNarrow)
fontId = GetFontIdToFit(str, fontId, list->template.lettersSpacing, widthPx);
colors[0] = list->template.fillValue;
colors[1] = list->template.cursorPal;
colors[2] = list->template.cursorShadowPal;
AddTextPrinterParameterized4(list->template.windowId,
list->template.fontId,
fontId,
x, y,
list->template.lettersSpacing,
0, colors, TEXT_SKIP_DRAW, str);
Expand Down
1 change: 1 addition & 0 deletions src/menu_specialized.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ static const struct ListMenuTemplate sMoveRelearnerMovesListTemplate =
.itemVerticalPadding = 0,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = FONT_NORMAL,
.fontIdMayNarrow = TRUE,
.cursorKind = CURSOR_BLACK_ARROW
};

Expand Down
Loading

0 comments on commit ef52486

Please sign in to comment.