feat(runtime): embed platform modules as bytecode

ui.lua and hints.lua are compiled to LUA_32BITS bytecode (matching the
firmware's Lua build) and linked into the binary. A new package.searchers
entry checks them as the fallback after the SD card, so a local
/.lua/lib/ui.lua still shadows the packaged one for debugging.

Bytecode is ~40% smaller than source and loads without parsing. A fresh
SD card with no make sdcard now has the platform available.
This commit is contained in:
2026-08-03 21:08:35 -04:00
parent 60ec720cdb
commit 6a9b082f97
10 changed files with 430 additions and 263 deletions
+25 -25
View File
@@ -4,42 +4,42 @@
local hints = {}
-- Reading order across the strip, so a device showing three of them still reads left to right.
local ORDER = {"back", "left", "up", "down", "right", "confirm"}
local ORDER = { "back", "left", "up", "down", "right", "confirm" }
local function available()
local roles = {}
if input and input.getButtons then
for _, role in ipairs(input.getButtons()) do roles[role] = true end
end
return roles
local roles = {}
if input and input.getButtons then
for _, role in ipairs(input.getButtons()) do roles[role] = true end
end
return roles
end
---Paints the labels this device can actually act on, and returns the height it used.
---@param actions table<string, string> Label per Button role; roles the device lacks are skipped.
---@param options table|nil `y`, `font`, `color`, and `background` overrides.
function hints.draw(actions, options)
options = options or {}
local font = options.font or gui.FONT_SMALL
local color = options.color or gui.color(0, 0, 0)
local background = options.background or gui.color(255, 255, 255)
local height = gui.getFontHeight(font) + 6
local y = options.y or (gui.getHeight() - height)
options = options or {}
local font = options.font or gui.FONT_SMALL
local color = options.color or gui.color(0, 0, 0)
local background = options.background or gui.color(255, 255, 255)
local height = gui.getFontHeight(font) + 6
local y = options.y or (gui.getHeight() - height)
local roles = available()
local labels = {}
for _, role in ipairs(ORDER) do
if roles[role] and actions[role] then labels[#labels + 1] = actions[role] end
end
local roles = available()
local labels = {}
for _, role in ipairs(ORDER) do
if roles[role] and actions[role] then labels[#labels + 1] = actions[role] end
end
gui.fillRect(0, y, gui.getWidth(), height, background)
if #labels == 0 then return height end
gui.fillRect(0, y, gui.getWidth(), height, background)
if #labels == 0 then return height end
local slot = gui.getWidth() // #labels
for index, label in ipairs(labels) do
local left = slot * (index - 1) + (slot - gui.getTextWidth(font, label)) // 2
gui.drawText(font, left, y + 3, label, color, gui.STYLE_NORMAL, background)
end
return height
local slot = gui.getWidth() // #labels
for index, label in ipairs(labels) do
local left = slot * (index - 1) + (slot - gui.getTextWidth(font, label)) // 2
gui.drawText(font, left, y + 3, label, color, gui.STYLE_NORMAL, background)
end
return height
end
return hints