From 24a7ff86d407ac925256c715a08144bb877032c0 Mon Sep 17 00:00:00 2001 From: thibautbus <310327033+thibautbus@users.noreply.github.com> Date: Sat, 22 Aug 2026 20:10:13 +0200 Subject: [PATCH] Stop drawing invisible TTF text on Gold's palette-shaded screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chrome.printThrough (src/ui/gen2/Chrome.lua) runs a string through the GbcPalette shade-remap shader whenever a palette is given, so a screen whose background is not white -- the naming/keyboard screen, Diploma, Pokegear, Credits -- gets its text colour resolved from the same palette as everything else on it. The shader recovers a shade by reading the RED CHANNEL of an already-rasterized 2bpp tile pixel (src/render/GbcPalette.lua's SHADER_SOURCE), which assumes the texture underneath is one of the four flat GB shades. A TTF glyph is not: LÖVE's font rasterizer stores glyph coverage as alpha over a plain white texture and lets the current tint carry the ink colour, so that same red-channel read always comes back 1.0 -- shade 0 -- painting every TTF character the exact colour of the paper rect printThrough had just drawn behind it. Since a mod loads a TTF through src/core/Strings.lua's font registry precisely so a translation is not boxed into a handful of tile-page glyphs, every translation mod that ships one hit this: reported against a real Gold build where the naming screen's on-screen keyboard, Diploma and the Pokegear all went blank the moment the mod's TTF took over rendering (gen1recomp#1642). Gen 1 has no such shader, which is why the same mod draws fine there. A TTF glyph carries no discrete shade to recover in the first place, so skip the shader for one and tint it with the palette's own ink colour directly -- the same shade-3 entry the shader's `rgb = pal3` branch would have mapped a black tile pixel to. The switch is per GLYPH rather than per string: a TTF-mod build still keeps multi-byte charmap sequences (the naming screen's own / cells, the 'd/'l/'s ligatures) and anything a mod names in ttf.tiles on their ROM tiles (src/render/Font.lua's Font.split), so one call can mix both kinds of glyph, and a tile glyph drawn alongside a TTF one still needs the shader to pick up a mod's COLOR/rBGP settings correctly. --- src/ui/gen2/Chrome.lua | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/ui/gen2/Chrome.lua b/src/ui/gen2/Chrome.lua index 12f8a802..6a147077 100644 --- a/src/ui/gen2/Chrome.lua +++ b/src/ui/gen2/Chrome.lua @@ -138,11 +138,39 @@ function Chrome.printThrough(text, tx, ty, palette, invert) local paper = pal[1] or { 255, 255, 255 } love.graphics.setColor(paper[1] / 255, paper[2] / 255, paper[3] / 255, 1) love.graphics.rectangle("fill", tx * 8, ty * 8, width, 8) - love.graphics.setColor(1, 1, 1, 1) + -- Per glyph, not per string: a TTF-mod build still keeps the multi-byte + -- charmap sequences (the naming screen's /, the 'd/'l/'s ligatures) + -- and anything the mod names in ttf.tiles (Font.lua's own note on keeping + -- digits tile-based for column alignment) on their ROM tiles, so a string + -- can freely mix the two kinds of glyph. + local ink = pal[4] or { 0, 0, 0 } local previous = love.graphics.getShader() - GbcPalette.useRaw(pal) - Font.draw(text, tx * 8, ty * 8) - love.graphics.setShader(previous) + local shaded = false + local pen = tx * 8 + for _, code in ipairs(Font.encode(text)) do + if code >= Font.TTF_BASE then + -- The shader below recovers a shade from the RED CHANNEL of an already + -- flat-shaded 2bpp tile sheet -- exactly what a TTF glyph is not. + -- LÖVE's font rasterizer stores glyph coverage as alpha over a plain + -- white texture, which this shader reads back as shade 0 no matter how + -- solid the glyph looks, painting the character the SAME colour as the + -- paper rect just drawn above it: invisible (reported against a real + -- Gold build with a TTF translation mod active, gen1recomp#1642). A TTF + -- glyph has no discrete shade to recover in the first place, so skip + -- the shader for it and tint it with the palette's own ink colour + -- (shade 3, the same entry `rgb = pal3` would have mapped a black tile + -- pixel to) directly. + if shaded then love.graphics.setShader(previous); shaded = false end + love.graphics.setColor(ink[1] / 255, ink[2] / 255, ink[3] / 255, 1) + elseif not shaded then + love.graphics.setColor(1, 1, 1, 1) + GbcPalette.useRaw(pal) + shaded = true + end + Font.drawCode(code, pen, ty * 8) + pen = pen + Font.advanceOf(code) + end + if shaded then love.graphics.setShader(previous) end love.graphics.setColor(0, 0, 0, 1) return width end