Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

7 changed files with 222 additions and 630 deletions

1
.gitignore vendored
View File

@ -8,4 +8,3 @@
/usereeprom.lua /usereeprom.lua
/run /run
/root* /root*
/musl-cross-make

View File

@ -13,7 +13,6 @@ extern char lua_init[];
extern char lua_internet[]; extern char lua_internet[];
extern char lua_sandbox[]; extern char lua_sandbox[];
extern char lua_textgpu[]; extern char lua_textgpu[];
extern char lua_textgpu_old[];
extern char lua_util_buffer[]; extern char lua_util_buffer[];
extern char lua_util_color[]; extern char lua_util_color[];
extern char lua_util_random[]; extern char lua_util_random[];

View File

@ -42,10 +42,6 @@ case "$1" in
TOOL=powerpc-linux-musl TOOL=powerpc-linux-musl
OUT=$TOOL OUT=$TOOL
;; ;;
i686 )
TOOL=i686-linux-musl
OUT=i686-linux-musl
;;
*) echo "Invalid target!" ; exit 1 *) echo "Invalid target!" ; exit 1
;; ;;
esac esac
@ -64,7 +60,7 @@ cd dependencies
if [ $2 = "libressl" ] || [ $# -lt 2 ]; then if [ $2 = "libressl" ] || [ $# -lt 2 ]; then
git clone --depth 1 https://github.com/libressl-portable/portable.git libressl git clone https://github.com/libressl-portable/portable.git libressl
cd libressl cd libressl
./autogen.sh ./autogen.sh
CFLAGS="-fdata-sections -ffunction-sections" ./configure --host=$TOOL CFLAGS="-fdata-sections -ffunction-sections" ./configure --host=$TOOL

View File

@ -31,7 +31,7 @@ function boot.boot()
gpu.setBackground(0x000000) gpu.setBackground(0x000000)
native.sleep(4000000) native.sleep(4000000)
while true do --[[NOTHING]] end os.exit(1)
end) end)
end end

View File

@ -62,30 +62,30 @@ local keymap = {
[0x60 + 0x01] = 0x1E, [0x60 + 0x01] = 0x1E,
[0x60 + 0x02] = 0x30, [0x60 + 0x02] = 0x30,
[0x60 + 0x03] = 0x2E, [0x60 + 0x04] = 0x2E,
[0x60 + 0x04] = 0x20, [0x60 + 0x05] = 0x20,
[0x60 + 0x05] = 0x12, [0x60 + 0x06] = 0x12,
[0x60 + 0x06] = 0x21, [0x60 + 0x07] = 0x21,
[0x60 + 0x07] = 0x22, [0x60 + 0x08] = 0x22,
[0x60 + 0x08] = 0x23, [0x60 + 0x09] = 0x23,
[0x60 + 0x09] = 0x17, [0x60 + 0x0A] = 0x17,
[0x60 + 0x0A] = 0x24, [0x60 + 0x0B] = 0x24,
[0x60 + 0x0B] = 0x25, [0x60 + 0x0C] = 0x25,
[0x60 + 0x0C] = 0x26, [0x60 + 0x0D] = 0x26,
[0x60 + 0x0D] = 0x32, [0x60 + 0x0E] = 0x32,
[0x60 + 0x0E] = 0x31, [0x60 + 0x0F] = 0x31,
[0x60 + 0x0F] = 0x18, [0x60 + 0x11] = 0x18,
[0x60 + 0x10] = 0x19, [0x60 + 0x12] = 0x19,
[0x60 + 0x11] = 0x10, [0x60 + 0x13] = 0x10,
[0x60 + 0x12] = 0x13, [0x60 + 0x14] = 0x13,
[0x60 + 0x13] = 0x1F, [0x60 + 0x15] = 0x1F,
[0x60 + 0x13] = 0x14, [0x60 + 0x16] = 0x14,
[0x60 + 0x14] = 0x16, [0x60 + 0x17] = 0x16,
[0x60 + 0x16] = 0x2F, [0x60 + 0x18] = 0x2F,
[0x60 + 0x17] = 0x11, [0x60 + 0x19] = 0x11,
[0x60 + 0x18] = 0x2D, [0x60 + 0x1A] = 0x2D,
[0x60 + 0x19] = 0x15, [0x60 + 0x1B] = 0x15,
[0x60 + 0x1A] = 0x2C, [0x60 + 0x1C] = 0x2C,
[13] = 28, --Return key [13] = 28, --Return key
[127] = 14, --backspace [127] = 14, --backspace
@ -97,88 +97,24 @@ local asciitr = {
[127] = 8, [127] = 8,
} }
local escmap = {
[65] = 200, -- up
[66] = 208, -- down
[67] = 205, -- right
[68] = 203, -- left
}
local inesc_down = false
local esc_down_ctrl = false
function computer.signalTransformers.key_down(s, a, ascii, key, user) function computer.signalTransformers.key_down(s, a, ascii, key, user)
if key ~= -1 then if key ~= -1 then
return s, a, ascii, key, user return s, a, ascii, key, user
end end
if ascii == 27 then
inesc_down = native.uptime()
return nil
elseif ascii < 27 and ascii ~= 8 and ascii ~= 13 and ascii ~= 9 then
signalQueue[#signalQueue + 1] = {s, a, 0, 29, user}
key = keymap[ascii + 96] or -1
elseif inesc_down then
if (ascii < 48 or ascii > 57) and ascii ~= 59 and ascii ~= 91 then
inesc_down = false
key = escmap[ascii] or 0
if not esc_down_ctrl then
--ascii = math.max(0, ascii - 96)
else
ascii = 0
end
esc_down_ctrl = false
elseif ascii == 91 then
esc_down_ctrl = true
elseif native.uptime() - inesc_down > 100 then -- 100ms timeout after {ESC}
return nil
else
esc_down_ctrl = false
inesc_down = false
end
end
return s, a, math.floor(asciitr[ascii] or ascii), keymap[ascii] or key, user return s, a, math.floor(asciitr[ascii] or ascii), keymap[ascii] or key, user
end end
local inesc_up = false
local esc_up_ctrl = false
function computer.signalTransformers.key_up(s, a, ascii, key, user) function computer.signalTransformers.key_up(s, a, ascii, key, user)
if key ~= -1 then if key ~= -1 then
return s, a, ascii, key, user return s, a, ascii, key, user
end end
if ascii == 27 then
inesc_up = native.uptime()
return nil
elseif ascii < 27 and ascii ~= 8 and ascii ~= 13 and ascii ~= 9 then
signalQueue[#signalQueue+1] = {s, a, 0, 29, user}
key = keymap[ascii + 96] or 0
elseif inesc_up then
if (ascii < 48 or ascii > 57) and ascii ~= 59 and ascii ~= 91 then
inesc_up = false
key = escmap[ascii] or 0
if not esc_up_ctrl then
--ascii = math.max(0, ascii - 96)
else
ascii = 0
end
esc_up_ctrl = false
elseif ascii == 91 then
esc_up_ctrl = true
elseif native.uptime() - inesc_up > 100 then -- 100ms timeout after {ESC}
return nil
else
esc_up_ctrl = false
inesc_up = false
end
end
return s, a, math.floor(asciitr[ascii] or ascii), keymap[ascii] or key, user return s, a, math.floor(asciitr[ascii] or ascii), keymap[ascii] or key, user
end end
----- -----
function api.pushSignal(s, ...) function api.pushSignal(s, ...)
local result = table.pack(computer.signalTransformers[s](s, ...)) signalQueue[#signalQueue + 1] = {computer.signalTransformers[s](s, ...)}
if result.n == 0 or not result[1] then return end
result.n = nil
signalQueue[#signalQueue + 1] = result
end end
function api.pullSignal(timeout) function api.pullSignal(timeout)

View File

@ -1,324 +1,257 @@
local textgpu = {} local textgpu = {}
local mapping = {} local mapping = {
local palette = {} ["0"] = 0x000000,
["1"] = 0xFF0000,
["2"] = 0x00FF00,
["3"] = 0xFFFF00,
["4"] = 0x0000FF,
["5"] = 0xFF00FF,
["6"] = 0x00FFFF,
["7"] = 0xFFFFFF,
}
-- generate color mapping --[[local nw = io.write
io.write = function(...)
for g=0, 255, 0x24 do nw(...)
for b=0, 256, 0x40 do io.flush()
for r=0, 255, 0x33 do native.sleep(20000)
mapping[#mapping+1] = (math.min(r, 255) * 0x10000) end]]--
+ (math.min(g, 255) * 0x100) + math.min(b, 255)
end
end
end
for i=0, 15, 1 do
mapping[#mapping+1] = (i+1) * 0x0f0f0f
palette[i] = (i+1) * 0x0f0f0f
end
local write = io.write local write = io.write
local flush = io.flush local flush = io.flush
local background = 1 local background = "0"
local foreground = 256 local foreground = "0"
local tbuffer = {} local tbuffer = {}
local bbuffer = {} local bbuffer = {}
local fbuffer = {} local fbuffer = {}
local function prep(w, h) local function prepareBuffers(w, h)
local tl = string.rep(" ", w) local tbline = (" "):rep(w)
local bb = string.rep("\0", w) local bbline = ("0"):rep(w)
local fb = string.rep("\255", w) local fbline = ("7"):rep(w)
for i=1, h do
for i=1, h, 1 do tbuffer[i] = tbline
tbuffer[i] = tl bbuffer[i] = bbline
bbuffer[i] = bb fbuffer[i] = fbline
fbuffer[i] = fb
end end
end end
local fg = 256 local usub
local bg = 1 local function insertString(main, sub, at)
local w, h = 1, 1 checkArg(1, main, "string")
checkArg(2, sub, "string")
checkArg(3, at, "number")
local function rgb(i) return usub(main, 1, at - 1)
return i>>16&0xFF, i>>8&0xFF, i&0xFF .. sub .. usub(main, at + (utf8.len(sub) or 0))
end
local unsub, fullRefresh
local function set(x, y, text, f, b, safe, noref)
if x > w or x < 1 or y > h or y < 1 or not tbuffer[y] then
if safe then
return
else
error("index out of bounds: " .. y, 3)
end
end
if not text then return end
f = f or fg
b = b or bg
local len = utf8.len(text)
if x + len > w then
--len = (x + len) - w
--text = unsub(text, 1, len)
end
tbuffer[y] = unsub(tbuffer[y], 1, x - 1) ..
text .. unsub(tbuffer[y], x + len)
if type(f) == "string" then
fbuffer[y] = fbuffer[y]:sub(1, x - 1) ..
f .. fbuffer[y]:sub(x + len)
else
if not noref then
local F = mapping[f]
local r, g, _b = rgb(F)
write("\27[38;2;", r, ";", g, ";", _b, "m")
end
fbuffer[y] = fbuffer[y]:sub(1, x - 1) ..
string.rep(string.char(f - 1), len) .. fbuffer[y]:sub(x + len)
end
if type(b) == "string" then
bbuffer[y] = bbuffer[y]:sub(1, x - 1) ..
b .. bbuffer[y]:sub(x + len)
else
if not noref then
local B = mapping[b]
local r, g, _b = rgb(B)
write("\27[48;2;", r, ";", g, ";", _b, "m")
end
bbuffer[y] = bbuffer[y]:sub(1, x - 1) ..
string.rep(string.char(b - 1), len) .. bbuffer[y]:sub(x + len)
end
-- clamp buffers
tbuffer[y] = unsub(tbuffer[y], 1, w)
fbuffer[y] = fbuffer[y]:sub(1, w)
bbuffer[y] = bbuffer[y]:sub(1, w)
if not noref then
write("\27[", y, ";", x, "H", text)
flush()
end
end
fullRefresh = function()
for i=1, h, 1 do
local text = tbuffer[i]
local fgt = fbuffer[i]
local bgt = bbuffer[i]
--native.log("UPDATE " .. i .. ": \"" .. text .. "\"")
local pb, pf
fgt = fgt:gsub("()(.)", function(n, fc)
local bc, tc = bgt:sub(n,n), text:sub(n,n)
local str = ""
if bc ~= pb then
pb = bc
local B = mapping[bc:byte() + 1]
str = str .. string.format("\27[48;2;%d;%d;%dm",
rgb(B))
end
if fc ~= pf then
pf = fc
local F = mapping[fc:byte() + 1]
str = str .. string.format("\27[38;2;%d;%d;%dm",
rgb(F))
end
str = str .. tc
return str
end)
write("\27[", i, ";1H", fgt)
end
flush()
end
local function get(x, y, len, safe)
if x < 1 or x > w or y < 1 or y > h then
if safe then
return
else
error("index out of bounds: " .. y, 3)
end
end
len = (len or 1) - 1
if x + len > w then
len = (x + len) - w
end
local text = unsub(tbuffer[y], x, x + len)
if len == 0 then
return text,
mapping[fbuffer[y]:sub(x, x):byte() + 1],
mapping[bbuffer[y]:sub(x, x):byte() + 1]
else
return text, fbuffer[y]:sub(x, x + len), bbuffer[y]:sub(x, x + len)
end
end end
function textgpu.start() function textgpu.start()
unsub = modules.sandbox.unicode.sub usub = modules.sandbox.unicode.sub
local _height = 0
local gpu = {} local gpu = {}
function gpu.bind() return false, "This is static bound gpu" end
function gpu.setForeground(color, ispalette) function gpu.setBackground(color, isPaletteIndex)
checkArg(1, color, "number") checkArg(1, color, "number")
checkArg(2, ispalette, "boolean", "nil") checkArg(2, isPaletteIndex, "boolean", "nil")
local ret = color if isPaletteIndex then
if ispalette then return --TODO: Maybe?
if not palette[color] then
error("invalid palette index", 2)
end end
color = palette[color] local old = background
background = tostring(math.floor(modules.color.nearest(color, mapping)))
write("\x1b[4" .. background .. "m")
flush()
return mapping[old]
end end
local index = math.floor(modules.color.nearest(color, mapping)) function gpu.setForeground(color, isPaletteIndex)
fg = index or fg
return ret, ispalette
end
function gpu.setBackground(color, ispalette)
checkArg(1, color, "number") checkArg(1, color, "number")
checkArg(2, ispalette, "boolean", "nil") checkArg(2, isPaletteIndex, "boolean", "nil")
local ret = color if isPaletteIndex then
if ispalette then return --TODO: Maybe?
if not palette[color] then
error("invalid palette index", 2)
end end
color = palette[color] local old = foreground
foreground = tostring(math.floor(modules.color.nearest(color, mapping)))
write("\x1b[3" .. foreground .. "m")
flush()
return mapping[old]
end end
local index = math.floor(modules.color.nearest(color, mapping))
bg = index or bg
return ret, ispalette
end
function gpu.setPaletteColor(c, v)
checkArg(1, c, "number")
checkArg(2, v, "number")
if not palette[c] then
error("invalid palette index", 2)
end
palette[c] = v
end
function gpu.getPaletteColor(c)
checkArg(1, c, "number")
if not palette[c] then
error("invalid palette index", 2)
end
return palette[c]
end
function gpu.getForeground()
return mapping[fg]
end
function gpu.getBackground() function gpu.getBackground()
return mapping[bg] return mapping[background], false
end end
function gpu.getForeground()
function gpu.getDepth() return mapping[foreground], false
return 4 end
function gpu.getPaletteColor()
return nil
end
function gpu.setPaletteColor()
return nil
end end
function gpu.maxDepth() function gpu.maxDepth()
return 4 return 3
end end
function gpu.setDepth() function gpu.setDepth()
return true return false
end
function gpu.getDepth()
return 3
end
function gpu.maxResolution()
return termutils.getSize()
end end
function gpu.getResolution() function gpu.getResolution()
return termutils.getSize() return termutils.getSize()
end end
function gpu.getViewport()
function gpu.setResolution() return termutils.getSize()
return false
end end
function gpu.setViewport(w, h)
gpu.maxResolution = gpu.getResolution checkArg(1, w, "number")
gpu.getViewport = gpu.getResolution checkArg(2, h, "number")
gpu.setViewport = gpu.setResolution return false, "Viewport not supported for this gpu"
function gpu.set(x, y, text, vert)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, text, "string")
checkArg(4, vert, "boolean", "nil")
vert = false
if vert then
local i = 1
local len = utf8.len(text)
while i <= len do
set(x, y + i - 1, unsub(text, i, i))
i = i + 1
end end
return true function gpu.setResolution(w, h)
else checkArg(1, w, "number")
set(x, y, text) checkArg(2, h, "number")
return true return false, "Non resizeable gpu"
end end
end
function gpu.get(x, y) function gpu.get(x, y)
checkArg(1, x, "number") checkArg(1, x, "number")
checkArg(2, y, "number") checkArg(2, y, "number")
return get(x, y)
end
function gpu.fill(x, y, W, H, c) return tbuffer[y]:sub(x,x), mapping[fbuffer[y]:sub(x,x)], mapping[bbuffer[y]:sub(x,x)]
checkArg(1, x, "number")
checkArg(1, y, "number")
checkArg(1, W, "number")
checkArg(1, H, "number")
checkArg(1, c, "string")
c = unsub(c, 1, 1)
if #c == 0 then return true end
local str = c:rep(W)
for i=1, H, 1 do
set(x, y + i - 1, str, nil, nil, true)
end end
return true function gpu.set(x, y, value, vertical)
end
function gpu.copy(x, y, W, H, xd, yd)
checkArg(1, x, "number") checkArg(1, x, "number")
checkArg(2, y, "number") checkArg(2, y, "number")
checkArg(3, W, "number") checkArg(3, value, "string")
checkArg(4, H, "number") checkArg(4, vertical, "boolean", "nil")
checkArg(5, xd, "number") x = math.floor(x)
checkArg(6, yd, "number") y = math.floor(y)
if xd == 0 and yd == 0 then return true end -- hah if not vertical then
local start, stop, step if not tbuffer[y] then
if yd < 0 then -- moving up - copy from the top down native.log("GPU Set failed: under buffer")
start, stop, step = y, y + H, 1 return false
else -- moving down - copy from the bottom up
start, stop, step = y + H, y, -1
end end
for i=start, stop, step do tbuffer[y] = insertString(tbuffer[y], value, x)
local str, fstr, bstr = get(x, i, W, true) bbuffer[y] = insertString(bbuffer[y], background:rep(utf8.len(value)), x)
--native.log("COPY " .. i .. " (" .. (str or "") .. ") to " .. (i + yd)) fbuffer[y] = insertString(fbuffer[y], foreground:rep(utf8.len(value)), x)
if str then-- and fstr and bstr then write("\x1b[" .. y .. ";" .. x .. "H" .. value)
set(x + xd, i + yd, str, fstr, bstr, true, true) else
--TODO: Buffers!
write("\x1b[" .. y .. ";" .. x .. "H")
value:gsub("([%z\1-\127\194-\244][\128-\191]*)", function(c)
write(c .. "\x1b[D\x1b[B")
end)
end
flush()
return true
end
function gpu.copy(x, y, w, h, tx, ty) --TODO: Check(check X multiple times)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, w, "number")
checkArg(4, h, "number")
checkArg(5, tx, "number")
checkArg(6, ty, "number")
local ttbuf = {}
local btbuf = {}
local ftbuf = {}
for i=1, h do
if i + y - 2 <= _height and i + y > 1 then
ttbuf[i] = tbuffer[y + i - 1] and usub(tbuffer[y + i - 1], x, x + w - 1) or (" "):rep(w)
btbuf[i] = bbuffer[y + i - 1] and bbuffer[y + i - 1]:sub(x, x + w - 1) or background:rep(w)
ftbuf[i] = fbuffer[y + i - 1] and fbuffer[y + i - 1]:sub(x, x + w - 1) or foreground:rep(w)
else
ttbuf[i] = (" "):rep(w)
btbuf[i] = background:rep(w)
ftbuf[i] = foreground:rep(w)
end
end
local bg = background
local fg = foreground
for i=1, h do
local line, linex
local lwrite = false
for j=1, w do
if btbuf[i]:sub(j,j) ~= bg then
lwrite = true
end
if ftbuf[i]:sub(j,j) ~= fg then
lwrite = true
end
if not line then linex = j end
line = (line or "")
if lwrite then
local wx = (tx + x + linex - 1)|0
local wy = (ty + y + i - 1)|0
if tbuffer[wy] then
write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m\x1b[" .. wy .. ";" .. wx .. "H" .. line)
tbuffer[wy] = insertString(tbuffer[wy], line, wx)
bbuffer[wy] = insertString(bbuffer[wy], bg:rep(utf8.len(line)), wx)
fbuffer[wy] = insertString(fbuffer[wy], fg:rep(utf8.len(line)), wx)
end
bg = btbuf[i]:sub(j,j)
fg = ftbuf[i]:sub(j,j)
line = nil
linex = nil
lwrite = false
end
if not line then linex = j end
line = (line or "") .. usub(ttbuf[i], j,j)
end
if line then
local wx = (tx + x + linex - 1)|0
local wy = (ty + y + i - 1)|0
if tbuffer[wy] then
write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m\x1b[" .. wy .. ";" .. wx .. "H" .. line)
tbuffer[wy] = insertString(tbuffer[wy], line, wx)
bbuffer[wy] = insertString(bbuffer[wy], bg:rep(utf8.len(line)), wx)
fbuffer[wy] = insertString(fbuffer[wy], fg:rep(utf8.len(line)), wx)
end
line = nil
linex = nil
lwrite = false
end
end
write("\x1b[4" .. background .. "m")
write("\x1b[3" .. foreground .. "m")
flush()
return true
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")
ch = usub(ch, 1, 1):rep(math.floor(w))
for i=1, h do
if i + y - 1 <= _height and i + y > 1 then
gpu.set(x, y + i - 1, ch)
end end
end end
fullRefresh()
return true return true
end end
local screenAddr local screenAddr
function gpu.getScreen() function gpu.getScreen()
return screenAddr return screenAddr
end end
function gpu.bind() --[[STUB]] end
if not termutils.init() then if not termutils.init() then
return nil, "Cannot initialize terminal based gpu" return nil, "Cannot initialize terminal based gpu"
end end
write("\x1b[?25l") --Disable cursor write("\x1b[?25l") --Disable cursor
local w, h = gpu.getResolution()
w, h = gpu.getResolution() _height = h
prep(w, h) prepareBuffers(w, h)
fullRefresh()
gpu.setForeground(0xFFFFFF) gpu.setForeground(0xFFFFFF)
gpu.setBackground(0x000000) gpu.setBackground(0x000000)

View File

@ -1,271 +0,0 @@
local textgpu = {}
local mapping = {
["0"] = 0x000000,
["1"] = 0xFF0000,
["2"] = 0x00FF00,
["3"] = 0xFFFF00,
["4"] = 0x0000FF,
["5"] = 0xFF00FF,
["6"] = 0x00FFFF,
["7"] = 0xFFFFFF,
}
--[[local nw = io.write
io.write = function(...)
nw(...)
io.flush()
native.sleep(20000)
end]]--
local write = io.write
local flush = io.flush
local background = "0"
local foreground = "0"
local tbuffer = {}
local bbuffer = {}
local fbuffer = {}
local function prepareBuffers(w, h)
local tbline = (" "):rep(w)
local bbline = ("0"):rep(w)
local fbline = ("7"):rep(w)
for i=1, h do
tbuffer[i] = tbline
bbuffer[i] = bbline
fbuffer[i] = fbline
end
end
local usub
local function insertString(main, sub, at)
checkArg(1, main, "string")
checkArg(2, sub, "string")
checkArg(3, at, "number")
return usub(main, 1, at - 1)
.. sub .. usub(main, at + (utf8.len(sub) or 0))
end
function textgpu.start()
usub = modules.sandbox.unicode.sub
local _height = 0
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
return --TODO: Maybe?
end
local old = background
background = tostring(math.floor(modules.color.nearest(color, mapping)))
write("\x1b[4" .. background .. "m")
flush()
return mapping[old]
end
function gpu.setForeground(color, isPaletteIndex)
checkArg(1, color, "number")
checkArg(2, isPaletteIndex, "boolean", "nil")
if isPaletteIndex then
return --TODO: Maybe?
end
local old = foreground
foreground = tostring(math.floor(modules.color.nearest(color, mapping)))
write("\x1b[3" .. foreground .. "m")
flush()
return mapping[old]
end
function gpu.getBackground()
return mapping[background], false
end
function gpu.getForeground()
return mapping[foreground], false
end
function gpu.getPaletteColor()
return nil
end
function gpu.setPaletteColor()
return nil
end
function gpu.maxDepth()
return 3
end
function gpu.setDepth()
return false
end
function gpu.getDepth()
return 3
end
function gpu.maxResolution()
return termutils.getSize()
end
function gpu.getResolution()
return termutils.getSize()
end
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
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")
return tbuffer[y]:sub(x,x), mapping[fbuffer[y]:sub(x,x)], mapping[bbuffer[y]:sub(x,x)]
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")
x = math.floor(x)
y = math.floor(y)
if not vertical then
if not tbuffer[y] then
native.log("GPU Set failed: under buffer")
return false
end
tbuffer[y] = insertString(tbuffer[y], value, x)
bbuffer[y] = insertString(bbuffer[y], background:rep(utf8.len(value)), x)
fbuffer[y] = insertString(fbuffer[y], foreground:rep(utf8.len(value)), x)
write("\x1b[" .. y .. ";" .. x .. "H" .. value)
else
--TODO: Buffers!
write("\x1b[" .. y .. ";" .. x .. "H")
value:gsub("([%z\1-\127\194-\244][\128-\191]*)", function(c)
write(c .. "\x1b[D\x1b[B")
end)
end
flush()
return true
end
function gpu.copy(x, y, w, h, tx, ty) --TODO: Check(check X multiple times)
checkArg(1, x, "number")
checkArg(2, y, "number")
checkArg(3, w, "number")
checkArg(4, h, "number")
checkArg(5, tx, "number")
checkArg(6, ty, "number")
local ttbuf = {}
local btbuf = {}
local ftbuf = {}
for i=1, h do
if i + y - 2 <= _height and i + y > 1 then
ttbuf[i] = tbuffer[y + i - 1] and usub(tbuffer[y + i - 1], x, x + w - 1) or (" "):rep(w)
btbuf[i] = bbuffer[y + i - 1] and bbuffer[y + i - 1]:sub(x, x + w - 1) or background:rep(w)
ftbuf[i] = fbuffer[y + i - 1] and fbuffer[y + i - 1]:sub(x, x + w - 1) or foreground:rep(w)
else
ttbuf[i] = (" "):rep(w)
btbuf[i] = background:rep(w)
ftbuf[i] = foreground:rep(w)
end
end
local bg = background
local fg = foreground
for i=1, h do
local line, linex
local lwrite = false
for j=1, w do
if btbuf[i]:sub(j,j) ~= bg then
lwrite = true
end
if ftbuf[i]:sub(j,j) ~= fg then
lwrite = true
end
if not line then linex = j end
line = (line or "")
if lwrite then
local wx = (tx + x + linex - 1)|0
local wy = (ty + y + i - 1)|0
if tbuffer[wy] then
write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m\x1b[" .. wy .. ";" .. wx .. "H" .. line)
tbuffer[wy] = insertString(tbuffer[wy], line, wx)
bbuffer[wy] = insertString(bbuffer[wy], bg:rep(utf8.len(line)), wx)
fbuffer[wy] = insertString(fbuffer[wy], fg:rep(utf8.len(line)), wx)
end
bg = btbuf[i]:sub(j,j)
fg = ftbuf[i]:sub(j,j)
line = nil
linex = nil
lwrite = false
end
if not line then linex = j end
line = (line or "") .. usub(ttbuf[i], j,j)
end
if line then
local wx = (tx + x + linex - 1)|0
local wy = (ty + y + i - 1)|0
if tbuffer[wy] then
write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m\x1b[" .. wy .. ";" .. wx .. "H" .. line)
tbuffer[wy] = insertString(tbuffer[wy], line, wx)
bbuffer[wy] = insertString(bbuffer[wy], bg:rep(utf8.len(line)), wx)
fbuffer[wy] = insertString(fbuffer[wy], fg:rep(utf8.len(line)), wx)
end
line = nil
linex = nil
lwrite = false
end
end
write("\x1b[4" .. background .. "m")
write("\x1b[3" .. foreground .. "m")
flush()
return true
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")
ch = usub(ch, 1, 1):rep(math.floor(w))
for i=1, h do
if i + y - 1 <= _height and i + y > 1 then
gpu.set(x, y + i - 1, ch)
end
end
return true
end
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
local w, h = gpu.getResolution()
_height = h
prepareBuffers(w, h)
gpu.setForeground(0xFFFFFF)
gpu.setBackground(0x000000)
local gpuaddr = modules.component.api.register(nil, "gpu", gpu)
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
modules.component.api.register("TODO:SetThisUuid", "keyboard", {})
deadhooks[#deadhooks + 1] = function()
write("\x1b[?25h\x1b[" .. ((h-1)|0) .. ";1H") --Enable cursor on quit
io.flush()
termutils.restore()
end
return gpuaddr
end
return textgpu