mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
7e96172391
A Japanese glyph advances by its width plus the window's letter spacing,
which a Latin one ignores (pokefirered/src/text.c:853): 1 for the normal
font (new_menu_helpers.c:413, the field message printer), 0 for the small
one (gFontInfos, new_menu_helpers.c:65). The engine already adds that
spacing, but only to a string carrying the {JPN} control code a ROM-
extracted one does; a mod's Japanese text has none, so its kana ran a pixel
tighter per character than on the cart. A glyph drawn from a Japanese sheet
now takes the window's spacing either way, and only once, falling back to
the message printer's spacing when the window sets none.
Name limits count characters (PLAYER_NAME_LENGTH, POKEMON_NAME_LENGTH), but
the start menu, the continue screen and the PC's hovered-mon panel cut names
with string.sub, in bytes. A kana is three bytes, so a five-kana species name
lost two characters in the PC and a Japanese player name was cut inside a
character. FrlgFont.truncate cuts by UTF-8 character, and those sites use it;
Latin names are cut as before, and an accented Latin name, whose accented
letters are two bytes, is no longer cut short either.
84 lines
5.0 KiB
Lua
84 lines
5.0 KiB
Lua
#!/usr/bin/env luajit
|
||
-- The US FireRed cart keeps its Japanese fonts (pokefirered/src/text.c:141,
|
||
-- :227); FrlgFont draws a Japanese character with them, numbered by the Japanese
|
||
-- block of pokefirered/charmap.txt, while Latin text keeps its own glyphs.
|
||
|
||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||
love = require("tests.love_stub")
|
||
|
||
local T = require("tests.harness")
|
||
local check = T.check
|
||
|
||
local FrlgFont = require("src.ui.game3.frlg_font")
|
||
local BASE = FrlgFont.JAPANESE_BASE
|
||
|
||
-- pokefirered/charmap.txt: あ..っ are 01-50, ア..ッ 51-A0
|
||
check(FrlgFont.glyphId("あ") == BASE + 0x01, "あ is the Japanese font's glyph 01")
|
||
check(FrlgFont.glyphId("っ") == BASE + 0x50, "っ closes the hiragana at 50")
|
||
check(FrlgFont.glyphId("ア") == BASE + 0x51, "ア opens the katakana at 51")
|
||
check(FrlgFont.glyphId("ッ") == BASE + 0xA0, "ッ closes them at A0")
|
||
check(FrlgFont.glyphId(" ") == BASE + 0x00, "the full-width space is glyph 00")
|
||
check(FrlgFont.glyphId("ー") == BASE + 0xAE, "ー is AE")
|
||
check(FrlgFont.glyphId("0") == BASE + 0xA1 and FrlgFont.glyphId("9") == BASE + 0xAA,
|
||
"full-width digits sit where the Latin digits do (A1-AA)")
|
||
check(FrlgFont.glyphId("P") == BASE + 0xCA and FrlgFont.glyphId("c") == BASE + 0xD7,
|
||
"full-width letters too (BB-EE)")
|
||
check(FrlgFont.glyphId("「") == BASE + 0xB3 and FrlgFont.glyphId("』") == BASE + 0xB2,
|
||
"and the Japanese quotes (B1-B4)")
|
||
check(FrlgFont.glyphId("A") == 0xBB and FrlgFont.glyphId("0") == 0xA1 and FrlgFont.glyphId("é") ~= nil
|
||
and FrlgFont.glyphId("é") < BASE, "Latin text keeps the Latin font")
|
||
|
||
-- pokefirered/src/text.c:853 a Japanese glyph advances by its width plus the
|
||
-- window's letter spacing: 1 for the normal font, whose width table gives most
|
||
-- kana 10px (text.c:1492; the small kana 9px), 0 for the small font's fixed 8px
|
||
-- (text.c:1391). With no extracted width table the normal font falls back to 10.
|
||
check(FrlgFont.advance(FrlgFont.glyphId("あ"), { small = true }) == 8, "a small-font kana advances 8px")
|
||
check(FrlgFont.measure("ポケモン") == 44, "four normal kana advance 44px (got " .. FrlgFont.measure("ポケモン") .. ")")
|
||
-- The spacing is added once: a ROM-extracted string carries the {JPN} control
|
||
-- code (0xFC 0x15) that the engine's own spacing already keys on.
|
||
local JPN = "\252\21"
|
||
check(FrlgFont.measure(JPN .. "ポケモン", { letterSpacing = 1 }) == 44,
|
||
"with the {JPN} code and a window spacing of 1, they still advance 44px (got "
|
||
.. FrlgFont.measure(JPN .. "ポケモン", { letterSpacing = 1 }) .. ")")
|
||
check(FrlgFont.measure("ポケモン", { letterSpacing = 0 }) == 40,
|
||
"and a window that asks for no spacing gets none (40px), the battle boxes' case")
|
||
check(FrlgFont.measure("POKEMON") == FrlgFont.measure("POKE") + FrlgFont.measure("MON"),
|
||
"Latin text keeps its own advance, with no letter spacing added")
|
||
|
||
-- A name limit counts characters, and a kana is three bytes.
|
||
check(FrlgFont.truncate("フシギダネ", 10) == "フシギダネ", "a five-kana name fits a ten-character limit")
|
||
check(FrlgFont.truncate("フシギダネ", 3) == "フシギ", "and is cut between characters, never inside one")
|
||
check(FrlgFont.truncate("BULBASAUR", 7) == "BULBASA", "Latin names are cut as before")
|
||
|
||
-- pokefirered/include/constants/global.h PLAYER_NAME_LENGTH is 7 characters: the
|
||
-- continue screen keeps seven kana of the player's name, not seven bytes.
|
||
local Boot = require("src.ui.game3.boot")
|
||
local info = Boot.continueInfoFromSave({ name = "ながいなまえです", playTime = {} })
|
||
check(info and info.name == "ながいなまえで",
|
||
"the continue screen keeps a Japanese name's first seven kana (got " .. tostring(info and info.name) .. ")")
|
||
|
||
-- The extractor reads the glyphs the way DecompressGlyph_Normal/_Small lay them out.
|
||
local TextChromeExtract = require("src.import.gba.text_chrome_extract")
|
||
local bytes = {}
|
||
local rom = { get = function(_, off) return bytes[off] or 0 end }
|
||
-- normal glyph 9 (row 1, column 1): top-left tile at 0x207500 + 0x200 + 0x20,
|
||
-- bottom-right at +0x110. A 2bpp tile's first row is two bytes, pixel 0 in the
|
||
-- high bits of the second byte; 0x40 there sets pixel 0 to colour 1.
|
||
local g = 0x207500 + 0x200 + 0x20
|
||
bytes[g + 1] = 0x40
|
||
bytes[g + 0x110 + 1] = 0x40
|
||
local sheet = TextChromeExtract.extractJapaneseNormal(rom)
|
||
local function alpha(rgba, w, x, y) return rgba:byte((y * w + x) * 4 + 4) end
|
||
check(alpha(sheet.fgRgba, 256, 9 * 16, 0) == 255, "normal glyph 9's top-left pixel comes from its top tile")
|
||
check(alpha(sheet.fgRgba, 256, 9 * 16 + 8, 8) == 255, "and its bottom-right quarter from 0x110 bytes on")
|
||
check(alpha(sheet.fgRgba, 256, 8 * 16, 0) == 0, "while glyph 8 stays empty")
|
||
-- small glyph 17 (row 1, column 1): top tile at 0x1EF100 + 0x200 + 0x10, bottom 0x100 on
|
||
local s = 0x1EF100 + 0x200 + 0x10
|
||
bytes[s + 1] = 0x40
|
||
bytes[s + 0x100 + 1] = 0x40
|
||
local small = TextChromeExtract.extractJapaneseSmall(rom)
|
||
check(alpha(small.fgRgba, 256, 1 * 16, 16) == 255 and alpha(small.fgRgba, 256, 1 * 16, 24) == 255,
|
||
"small glyph 17 is its top tile over the tile 0x100 bytes on")
|
||
|
||
T.finish("game3_japanese_font_test")
|