From 7367dd1d597d34306d593019907dc3b2b8a2a077 Mon Sep 17 00:00:00 2001 From: ocawesome101 Date: Thu, 27 May 2021 21:30:42 -0400 Subject: [PATCH] textgpu: still mildly broken, but not crash-the-whole-fuckin-thing broken --- include/luares.h | 1 + src/lua/core/textgpu.lua | 169 +++++++------------ src/lua/core/textgpu_new.lua | 319 +++++++++++++++++++++++++++++++++++ 3 files changed, 383 insertions(+), 106 deletions(-) create mode 100644 src/lua/core/textgpu_new.lua diff --git a/include/luares.h b/include/luares.h index f754bac..33b8601 100644 --- a/include/luares.h +++ b/include/luares.h @@ -13,6 +13,7 @@ extern char lua_init[]; extern char lua_internet[]; extern char lua_sandbox[]; extern char lua_textgpu[]; +extern char lua_textgpu_new[]; extern char lua_textgpu_old[]; extern char lua_util_buffer[]; extern char lua_util_color[]; diff --git a/src/lua/core/textgpu.lua b/src/lua/core/textgpu.lua index 810a4e6..f33870b 100644 --- a/src/lua/core/textgpu.lua +++ b/src/lua/core/textgpu.lua @@ -1,38 +1,40 @@ local textgpu = {} +local mapping = {} + +-- generate the mapping + +local i = 0 +for g=0, 255, 0x24 do + for b=0, 255, 0x40 do + for r=0, 255, 0x33 do + mapping[tostring(i)] = (r * 0x10000) + (g * 0x100) + b + i = i + 1 + end + end +end + +--[[local nw = io.write +io.write = function(...) + nw(...) + io.flush() + native.sleep(20000) +end]]-- + local write = io.write local flush = io.flush -local background = 0x000000 -- "0" -local foreground = 0xFFFFFF -- "0" +local background = "\0" +local foreground = "\255" local tbuffer = {} local bbuffer = {} local fbuffer = {} -local palette = { - [0] = 0x0f0f0f, - 0x1e1e1e, - 0x2d2d2d, - 0x3c3c3c, - 0x4b4b4b, - 0x5a5a5a, - 0x696969, - 0x787878, - 0x878787, - 0x969696, - 0xa5a5a5, - 0xb4b4b4, - 0xc3c3c3, - 0xd2d2d2, - 0xe1e1e1, - 0xf0f0f0 -} - local function prepareBuffers(w, h) local tbline = (" "):rep(w) - local bbline = ("\0\0\0"):rep(w) -- ("0"):rep(w) - local fbline = ("\255\255\255"):rep(w) -- ("7"):rep(w) + local bbline = ("\0"):rep(w) + local fbline = ("\7"):rep(w) for i=1, h do tbuffer[i] = tbline bbuffer[i] = bbline @@ -40,28 +42,14 @@ local function prepareBuffers(w, h) end end -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 - 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) or "") - .. sub .. (usub(main, at + (utf8.len(sub) or 0))) + return usub(main, 1, at - 1) + .. sub .. usub(main, at + (utf8.len(sub) or 0)) end function textgpu.start() @@ -73,33 +61,25 @@ function textgpu.start() checkArg(1, color, "number") checkArg(2, isPaletteIndex, "boolean", "nil") if isPaletteIndex then - if color > 15 or color < 0 then - error("invalid palette index", 2) - end - return palette[color] + return --TODO: Maybe? end local old = background - background = color -- tostring(math.floor(modules.color.nearest(color, mapping))) - setBackground(background) - --write("\x1b[4" .. background .. "m") + background = tostring(math.floor(modules.color.nearest(color, mapping))) + write("\x1b[48;5;" .. background:byte() .. "m") flush() - return old -- mapping[old] + return mapping[old] end function gpu.setForeground(color, isPaletteIndex) checkArg(1, color, "number") checkArg(2, isPaletteIndex, "boolean", "nil") if isPaletteIndex then - if color < 0 or color > 15 then - error("invalid palette index", 2) - end - return palette[color] + return --TODO: Maybe? end local old = foreground - foreground = color -- tostring(math.floor(modules.color.nearest(color, mapping))) - setForeground(foreground) - --write("\x1b[3" .. foreground .. "m") + foreground = tostring(math.floor(modules.color.nearest(color, mapping))) + write("\x1b[38;5;" .. foreground:byte() .. "m") flush() - return old -- mapping[old] + return mapping[old] end function gpu.getBackground() return mapping[background], false @@ -107,27 +87,20 @@ function textgpu.start() function gpu.getForeground() return mapping[foreground], false end - function gpu.getPaletteColor(index) - if index < 0 or index > 15 then - error("invalid palette index", 2) - end - return palette[index] + function gpu.getPaletteColor() + return nil end - function gpu.setPaletteColor(index, value) - if index < 0 or index > 15 then - error("invalid palette index", 2) - end - palette[index] = value - return true + function gpu.setPaletteColor() + return nil end function gpu.maxDepth() - return 4 + return 3 end function gpu.setDepth() - return true + return false end function gpu.getDepth() - return 4 + return 3 end function gpu.maxResolution() return termutils.getSize() @@ -152,9 +125,7 @@ function textgpu.start() checkArg(1, x, "number") checkArg(2, y, "number") - 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") + 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") @@ -169,10 +140,8 @@ function textgpu.start() return false end tbuffer[y] = insertString(tbuffer[y], value, x) - 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) + 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! @@ -197,14 +166,12 @@ function textgpu.start() 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*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) + 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] = string.pack(">I3", background):rep(w) - ftbuf[i] = string.pack(">I3", foreground):rep(w) + btbuf[i] = background:rep(w) + ftbuf[i] = foreground:rep(w) end end local bg = background @@ -214,10 +181,10 @@ function textgpu.start() local line, linex local lwrite = false for j=1, w do - if btbuf[i]:sub(j*3-2,j*3):unpack(">I3") ~= bg then + if btbuf[i]:sub(j,j) ~= bg then lwrite = true end - if ftbuf[i]:sub(j*3-2,j*3):unpack(">I3") ~= fg then + if ftbuf[i]:sub(j,j) ~= fg then lwrite = true end if not line then linex = j end @@ -226,19 +193,15 @@ function textgpu.start() local wx = (tx + x + linex - 1)|0 local wy = (ty + y + i - 1)|0 if tbuffer[wy] then - setBackground(bg) - setForeground(foreground) - --write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m - write("\x1b[" .. wy .. ";" .. wx .. "H" .. line) + write("\x1b[48;5;" .. bg:byte() .. "m\x1b[38;5;" .. fg:byte() .. "m\x1b[" .. wy + .. ";" .. wx .. "H" .. line) tbuffer[wy] = insertString(tbuffer[wy], line, wx) - 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) + 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*3-2,j*3):unpack(">I3") - fg = ftbuf[i]:sub(j*3-2,j*3):unpack(">I3") + bg = btbuf[i]:sub(j,j) + fg = ftbuf[i]:sub(j,j) line = nil linex = nil lwrite = false @@ -250,25 +213,19 @@ function textgpu.start() local wx = (tx + x + linex - 1)|0 local wy = (ty + y + i - 1)|0 if tbuffer[wy] then - setBackground(bg) - setForeground(fg) - --write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m - write("\x1b[" .. wy .. ";" .. wx .. "H" .. line) + write("\x1b[48;5;" .. bg:byte() .. "m\x1b[38;5;" .. fg:byte() .. "m\x1b[" .. wy + .. ";" .. wx .. "H" .. line) tbuffer[wy] = insertString(tbuffer[wy], line, wx) - 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) + 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 - setBackground(background) - setForeground(foreground) - --write("\x1b[4" .. background .. "m") - --write("\x1b[3" .. foreground .. "m") + write("\x1b[48;5;" .. background:byte() .. "m") + write("\x1b[38;5;" .. foreground:byte() .. "m") flush() return true end diff --git a/src/lua/core/textgpu_new.lua b/src/lua/core/textgpu_new.lua new file mode 100644 index 0000000..810a4e6 --- /dev/null +++ b/src/lua/core/textgpu_new.lua @@ -0,0 +1,319 @@ +local textgpu = {} + +local write = io.write +local flush = io.flush + +local background = 0x000000 -- "0" +local foreground = 0xFFFFFF -- "0" + +local tbuffer = {} +local bbuffer = {} +local fbuffer = {} + +local palette = { + [0] = 0x0f0f0f, + 0x1e1e1e, + 0x2d2d2d, + 0x3c3c3c, + 0x4b4b4b, + 0x5a5a5a, + 0x696969, + 0x787878, + 0x878787, + 0x969696, + 0xa5a5a5, + 0xb4b4b4, + 0xc3c3c3, + 0xd2d2d2, + 0xe1e1e1, + 0xf0f0f0 +} + +local function prepareBuffers(w, h) + local tbline = (" "):rep(w) + local bbline = ("\0\0\0"):rep(w) -- ("0"):rep(w) + local fbline = ("\255\255\255"):rep(w) -- ("7"):rep(w) + for i=1, h do + tbuffer[i] = tbline + bbuffer[i] = bbline + fbuffer[i] = fbline + end +end + +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 + +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) or "") + .. 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 + if color > 15 or color < 0 then + error("invalid palette index", 2) + end + return palette[color] + end + local old = background + background = color -- tostring(math.floor(modules.color.nearest(color, mapping))) + setBackground(background) + --write("\x1b[4" .. background .. "m") + flush() + return old -- mapping[old] + end + function gpu.setForeground(color, isPaletteIndex) + checkArg(1, color, "number") + checkArg(2, isPaletteIndex, "boolean", "nil") + if isPaletteIndex then + if color < 0 or color > 15 then + error("invalid palette index", 2) + end + return palette[color] + end + local old = foreground + foreground = color -- tostring(math.floor(modules.color.nearest(color, mapping))) + setForeground(foreground) + --write("\x1b[3" .. foreground .. "m") + flush() + return old -- mapping[old] + end + function gpu.getBackground() + return mapping[background], false + end + function gpu.getForeground() + return mapping[foreground], false + end + function gpu.getPaletteColor(index) + if index < 0 or index > 15 then + error("invalid palette index", 2) + end + return palette[index] + end + function gpu.setPaletteColor(index, value) + if index < 0 or index > 15 then + error("invalid palette index", 2) + end + palette[index] = value + return true + end + function gpu.maxDepth() + return 4 + end + function gpu.setDepth() + return true + end + function gpu.getDepth() + return 4 + 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), + fbuffer[y]:sub(x*3-2,x*3):unpack(">I3"), + bbuffer[y]:sub(x*3-2,x*3):unpack(">I3") + 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], + 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) + 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*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) + else + ttbuf[i] = (" "):rep(w) + btbuf[i] = string.pack(">I3", background):rep(w) + ftbuf[i] = string.pack(">I3", 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*3-2,j*3):unpack(">I3") ~= bg then + lwrite = true + end + if ftbuf[i]:sub(j*3-2,j*3):unpack(">I3") ~= 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 + setBackground(bg) + setForeground(foreground) + --write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m + write("\x1b[" .. wy .. ";" .. wx .. "H" .. line) + tbuffer[wy] = insertString(tbuffer[wy], line, wx) + 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) + end + + bg = btbuf[i]:sub(j*3-2,j*3):unpack(">I3") + fg = ftbuf[i]:sub(j*3-2,j*3):unpack(">I3") + 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 + setBackground(bg) + setForeground(fg) + --write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m + write("\x1b[" .. wy .. ";" .. wx .. "H" .. line) + tbuffer[wy] = insertString(tbuffer[wy], line, wx) + 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) + end + line = nil + linex = nil + lwrite = false + end + end + setBackground(background) + setForeground(foreground) + --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