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") --FIXME: ASAP: Implement return " " 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 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(".", 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 <= h 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 + linex)|0 local wy = (ty + y + i - 1)|0 tbuffer[wy] = tbuffer[wy] or (" "):rep(utf8.len(line)) write("\x1b[4" .. bg .. "m") write("\x1b[3" .. fg .. "m") write("\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) 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 + linex)|0 local wy = (ty + y + i - 1)|0 tbuffer[wy] = tbuffer[wy] or (" "):rep(utf8.len(line)) write("\x1b[4" .. bg .. "m") write("\x1b[3" .. fg .. "m") write("\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) 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 <= h 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 termutils.init() write("\x1b[?25l") --Disable cursor local w, h = gpu.getResolution() _height = h prepareBuffers(w, h) gpu.setForeground(0xFFFFFF) gpu.setBackground(0x000000) 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 end return textgpu