LuPPC/src/lua/core/textgpu.lua

320 lines
8.9 KiB
Lua
Raw Normal View History

2016-01-07 02:58:05 +11:00
local textgpu = {}
local write = io.write
local flush = io.flush
2016-01-14 11:10:04 +11:00
2021-05-28 11:18:10 +10:00
local background = 0x000000 -- "0"
local foreground = 0xFFFFFF -- "0"
2016-01-07 02:58:05 +11:00
2016-01-14 11:10:04 +11:00
local tbuffer = {}
local bbuffer = {}
local fbuffer = {}
2021-05-28 11:18:10 +10:00
local palette = {
[0] = 0x0f0f0f,
0x1e1e1e,
0x2d2d2d,
0x3c3c3c,
0x4b4b4b,
0x5a5a5a,
0x696969,
0x787878,
0x878787,
0x969696,
0xa5a5a5,
0xb4b4b4,
0xc3c3c3,
0xd2d2d2,
0xe1e1e1,
0xf0f0f0
}
2016-01-14 11:10:04 +11:00
local function prepareBuffers(w, h)
local tbline = (" "):rep(w)
2021-05-28 11:18:10 +10:00
local bbline = ("\0\0\0"):rep(w) -- ("0"):rep(w)
local fbline = ("\255\255\255"):rep(w) -- ("7"):rep(w)
2016-01-14 11:10:04 +11:00
for i=1, h do
tbuffer[i] = tbline
bbuffer[i] = bbline
fbuffer[i] = fbline
end
end
2021-05-28 11:18:10 +10:00
local function setForeground(c)
local r = c & 0xFF0000
local g = c & 0x00FF00
local b = c & 0x0000FF
io.write("\27[38;2;", r, ";", g, ";", b, "m")
end
local function setBackground(c)
local r = c & 0xFF0000
local g = c & 0x00FF00
local b = c & 0x0000FF
io.write("\27[48;2;", r, ";", g, ";", b, "m")
end
2016-01-21 09:18:02 +11:00
local usub
2016-01-14 11:10:04 +11:00
local function insertString(main, sub, at)
2016-01-21 09:18:02 +11:00
checkArg(1, main, "string")
checkArg(2, sub, "string")
checkArg(3, at, "number")
2016-02-10 03:42:11 +11:00
2021-05-28 11:18:10 +10:00
return (usub(main, 1, at - 1) or "")
.. sub .. (usub(main, at + (utf8.len(sub) or 0)))
2016-01-14 11:10:04 +11:00
end
2016-01-07 02:58:05 +11:00
function textgpu.start()
2016-01-21 09:18:02 +11:00
usub = modules.sandbox.unicode.sub
2016-02-10 03:42:11 +11:00
local _height = 0
2016-01-07 02:58:05 +11:00
local gpu = {}
function gpu.bind() return false, "This is static bound gpu" end
function gpu.setBackground(color, isPaletteIndex)
checkArg(1, color, "number")
checkArg(2, isPaletteIndex, "boolean", "nil")
if isPaletteIndex then
2021-05-28 11:18:10 +10:00
if color > 15 or color < 0 then
error("invalid palette index", 2)
end
return palette[color]
2016-01-07 02:58:05 +11:00
end
2016-01-16 05:58:26 +11:00
local old = background
2021-05-28 11:18:10 +10:00
background = color -- tostring(math.floor(modules.color.nearest(color, mapping)))
setBackground(background)
--write("\x1b[4" .. background .. "m")
flush()
2021-05-28 11:18:10 +10:00
return old -- mapping[old]
2016-01-07 02:58:05 +11:00
end
function gpu.setForeground(color, isPaletteIndex)
checkArg(1, color, "number")
checkArg(2, isPaletteIndex, "boolean", "nil")
if isPaletteIndex then
2021-05-28 11:18:10 +10:00
if color < 0 or color > 15 then
error("invalid palette index", 2)
end
return palette[color]
2016-01-07 02:58:05 +11:00
end
2016-01-15 08:44:49 +11:00
local old = foreground
2021-05-28 11:18:10 +10:00
foreground = color -- tostring(math.floor(modules.color.nearest(color, mapping)))
setForeground(foreground)
--write("\x1b[3" .. foreground .. "m")
flush()
2021-05-28 11:18:10 +10:00
return old -- mapping[old]
2016-01-07 02:58:05 +11:00
end
function gpu.getBackground()
return mapping[background], false
end
function gpu.getForeground()
return mapping[foreground], false
end
2021-05-28 11:18:10 +10:00
function gpu.getPaletteColor(index)
if index < 0 or index > 15 then
error("invalid palette index", 2)
end
return palette[index]
2016-01-07 02:58:05 +11:00
end
2021-05-28 11:18:10 +10:00
function gpu.setPaletteColor(index, value)
if index < 0 or index > 15 then
error("invalid palette index", 2)
end
palette[index] = value
return true
2016-01-07 02:58:05 +11:00
end
function gpu.maxDepth()
2021-05-28 11:18:10 +10:00
return 4
2016-01-07 02:58:05 +11:00
end
function gpu.setDepth()
2021-05-28 11:18:10 +10:00
return true
2016-01-07 02:58:05 +11:00
end
function gpu.getDepth()
2021-05-28 11:18:10 +10:00
return 4
2016-01-07 02:58:05 +11:00
end
function gpu.maxResolution()
return termutils.getSize()
end
function gpu.getResolution()
return termutils.getSize()
end
2016-01-15 08:44:49 +11:00
function gpu.getViewport()
return termutils.getSize()
end
function gpu.setViewport(w, h)
checkArg(1, w, "number")
checkArg(2, h, "number")
return false, "Viewport not supported for this gpu"
end
2016-01-07 02:58:05 +11:00
function gpu.setResolution(w, h)
checkArg(1, w, "number")
checkArg(2, h, "number")
return false, "Non resizeable gpu"
end
function gpu.get(x, y)
checkArg(1, x, "number")
checkArg(2, y, "number")
2016-08-18 06:40:11 +10:00
2021-05-28 11:18:10 +10:00
return tbuffer[y]:sub(x,x),
fbuffer[y]:sub(x*3-2,x*3):unpack(">I3"),
bbuffer[y]:sub(x*3-2,x*3):unpack(">I3")
2016-01-07 02:58:05 +11:00
end
function gpu.set(x, y, value, vertical)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, value, "string")
checkArg(4, vertical, "boolean", "nil")
2016-01-10 05:39:48 +11:00
x = math.floor(x)
y = math.floor(y)
2016-01-07 02:58:05 +11:00
if not vertical then
2016-01-21 09:18:02 +11:00
if not tbuffer[y] then
2016-02-10 08:55:26 +11:00
native.log("GPU Set failed: under buffer")
2016-01-21 09:18:02 +11:00
return false
end
2016-01-14 11:10:04 +11:00
tbuffer[y] = insertString(tbuffer[y], value, x)
2021-05-28 11:18:10 +10:00
bbuffer[y] = insertString(bbuffer[y],
string.pack(">I3", background):rep(utf8.len(value)), x*3-2)
fbuffer[y] = insertString(fbuffer[y],
string.pack(">I3", foreground):rep(utf8.len(value)), x*3-2)
write("\x1b[" .. y .. ";" .. x .. "H" .. value)
2016-01-07 02:58:05 +11:00
else
2016-01-21 09:18:02 +11:00
--TODO: Buffers!
write("\x1b[" .. y .. ";" .. x .. "H")
value:gsub("([%z\1-\127\194-\244][\128-\191]*)", function(c)
write(c .. "\x1b[D\x1b[B")
2016-01-07 02:58:05 +11:00
end)
end
flush()
2016-01-07 02:58:05 +11:00
return true
end
2016-01-14 11:10:04 +11:00
function gpu.copy(x, y, w, h, tx, ty) --TODO: Check(check X multiple times)
2016-01-07 02:58:05 +11:00
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, w, "number")
checkArg(4, h, "number")
checkArg(5, tx, "number")
checkArg(6, ty, "number")
2016-01-14 11:10:04 +11:00
local ttbuf = {}
local btbuf = {}
local ftbuf = {}
for i=1, h do
2016-02-10 08:55:26 +11:00
if i + y - 2 <= _height and i + y > 1 then
2016-02-10 03:42:11 +11:00
ttbuf[i] = tbuffer[y + i - 1] and usub(tbuffer[y + i - 1], x, x + w - 1) or (" "):rep(w)
2021-05-28 11:18:10 +10:00
btbuf[i] = bbuffer[y + i - 1] and
bbuffer[y + i - 1]:sub(x*3-2, (x + w - 1)*3) or string.pack(">I3", background):rep(w)
ftbuf[i] = fbuffer[y + i - 1] and
fbuffer[y + i - 1]:sub(x*3-2, (x + w - 1)*3) or string.pack(">I3", foreground):rep(w)
2016-02-10 03:42:11 +11:00
else
ttbuf[i] = (" "):rep(w)
2021-05-28 11:18:10 +10:00
btbuf[i] = string.pack(">I3", background):rep(w)
ftbuf[i] = string.pack(">I3", foreground):rep(w)
2016-02-10 03:42:11 +11:00
end
2016-01-14 11:10:04 +11:00
end
local bg = background
local fg = foreground
for i=1, h do
local line, linex
local lwrite = false
2016-01-14 11:10:04 +11:00
for j=1, w do
2021-05-28 11:18:10 +10:00
if btbuf[i]:sub(j*3-2,j*3):unpack(">I3") ~= bg then
lwrite = true
2016-01-14 11:10:04 +11:00
end
2021-05-28 11:18:10 +10:00
if ftbuf[i]:sub(j*3-2,j*3):unpack(">I3") ~= fg then
lwrite = true
2016-01-14 11:10:04 +11:00
end
if not line then linex = j end
2016-01-16 22:42:09 +11:00
line = (line or "")
if lwrite then
2016-02-10 08:55:26 +11:00
local wx = (tx + x + linex - 1)|0
2016-01-14 11:10:04 +11:00
local wy = (ty + y + i - 1)|0
2016-02-10 08:55:26 +11:00
if tbuffer[wy] then
2021-05-28 11:18:10 +10:00
setBackground(bg)
setForeground(foreground)
--write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m
write("\x1b[" .. wy .. ";" .. wx .. "H" .. line)
2016-02-10 08:55:26 +11:00
tbuffer[wy] = insertString(tbuffer[wy], line, wx)
2021-05-28 11:18:10 +10:00
bbuffer[wy] = insertString(bbuffer[wy],
string.pack(">I3", bg):rep(utf8.len(line)), wx*3-2)
fbuffer[wy] = insertString(fbuffer[wy],
string.pack(">I3", fg):rep(utf8.len(line)), wx*3-2)
2016-02-10 08:55:26 +11:00
end
2016-02-10 03:42:11 +11:00
2021-05-28 11:18:10 +10:00
bg = btbuf[i]:sub(j*3-2,j*3):unpack(">I3")
fg = ftbuf[i]:sub(j*3-2,j*3):unpack(">I3")
2016-01-14 11:10:04 +11:00
line = nil
linex = nil
lwrite = false
2016-01-14 11:10:04 +11:00
end
2016-01-16 22:42:09 +11:00
if not line then linex = j end
2016-02-10 03:42:11 +11:00
line = (line or "") .. usub(ttbuf[i], j,j)
2016-01-14 11:10:04 +11:00
end
if line then
2016-02-10 08:55:26 +11:00
local wx = (tx + x + linex - 1)|0
2016-01-14 11:10:04 +11:00
local wy = (ty + y + i - 1)|0
2016-02-10 08:55:26 +11:00
if tbuffer[wy] then
2021-05-28 11:18:10 +10:00
setBackground(bg)
setForeground(fg)
--write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m
write("\x1b[" .. wy .. ";" .. wx .. "H" .. line)
2016-02-10 08:55:26 +11:00
tbuffer[wy] = insertString(tbuffer[wy], line, wx)
2021-05-28 11:18:10 +10:00
bbuffer[wy] = insertString(bbuffer[wy],
string.pack(">I3", bg):rep(utf8.len(line)), wx*3-2)
fbuffer[wy] = insertString(fbuffer[wy],
string.pack(">I3", fg):rep(utf8.len(line)), wx*3-2)
2016-02-10 08:55:26 +11:00
end
2016-01-14 11:10:04 +11:00
line = nil
linex = nil
lwrite = false
2016-01-14 11:10:04 +11:00
end
end
2021-05-28 11:18:10 +10:00
setBackground(background)
setForeground(foreground)
--write("\x1b[4" .. background .. "m")
--write("\x1b[3" .. foreground .. "m")
flush()
2016-01-14 11:10:04 +11:00
return true
2016-01-07 02:58:05 +11:00
end
function gpu.fill(x, y, w, h, ch)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, w, "number")
checkArg(4, h, "number")
checkArg(5, ch, "string")
2016-02-10 03:42:11 +11:00
ch = usub(ch, 1, 1):rep(math.floor(w))
2016-01-07 02:58:05 +11:00
for i=1, h do
2016-02-10 08:55:26 +11:00
if i + y - 1 <= _height and i + y > 1 then
2016-02-10 03:42:11 +11:00
gpu.set(x, y + i - 1, ch)
end
2016-01-07 02:58:05 +11:00
end
return true
end
2016-01-20 04:25:09 +11:00
local screenAddr
function gpu.getScreen()
return screenAddr
end
if not termutils.init() then
return nil, "Cannot initialize terminal based gpu"
end
write("\x1b[?25l") --Disable cursor
2016-01-14 11:10:04 +11:00
local w, h = gpu.getResolution()
2016-02-10 03:42:11 +11:00
_height = h
2016-01-14 11:10:04 +11:00
prepareBuffers(w, h)
2016-01-07 02:58:05 +11:00
gpu.setForeground(0xFFFFFF)
gpu.setBackground(0x000000)
local gpuaddr = modules.component.api.register(nil, "gpu", gpu)
2016-01-20 04:25:09 +11:00
screenAddr = modules.component.api.register(nil, "screen", {getKeyboards = function() return {"TODO:SetThisUuid"} end}) --verry dummy screen, TODO: make it better, kbd uuid also in epoll.c
2016-01-16 22:42:09 +11:00
modules.component.api.register("TODO:SetThisUuid", "keyboard", {})
2016-01-10 05:39:48 +11:00
deadhooks[#deadhooks + 1] = function()
2016-02-10 03:42:11 +11:00
write("\x1b[?25h\x1b[" .. ((h-1)|0) .. ";1H") --Enable cursor on quit
io.flush()
termutils.restore()
2016-01-10 05:39:48 +11:00
end
return gpuaddr
2016-01-07 02:58:05 +11:00
end
2016-01-20 05:46:40 +11:00
return textgpu