From f68605ffea24282ae9ffc7a0619e9b3a16755eff Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Thu, 9 Apr 2020 15:44:23 +1000 Subject: [PATCH] added a better replacement VT100 emulator --- module/nvt100.lua | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++ module/vt-task.lua | 2 +- 2 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 module/nvt100.lua diff --git a/module/nvt100.lua b/module/nvt100.lua new file mode 100644 index 0000000..e128e99 --- /dev/null +++ b/module/nvt100.lua @@ -0,0 +1,142 @@ +function vt100emu(gpu) -- takes GPU component proxy *gpu* and returns a function to write to it in a manner like an ANSI terminal + local colours = {0x0,0xFF0000,0x00FF00,0xFFFF00,0x0000FF,0xFF00FF,0x00B6FF,0xFFFFFF} + local mx, my = gpu.maxResolution() + local cx, cy = 1, 1 + local pc = " " + local lc = "" + local mode = 0 -- 0 normal, 1 escape, 2 command + local lw = true + local sx, sy = 1,1 + local cs = "" + local bg, fg = 0, 0xFFFFFF + + -- setup + gpu.setResolution(mx,my) + gpu.fill(1,1,mx,my," ") + local function checkCursor() + if cx > mx and lw then + cx, cy = 1, cy+1 + end + if cy > my then + gpu.copy(1,2,mx,my-1,0,-1) + gpu.fill(1,my,mx,1," ") + cy=my + end + if cy < 1 then cy = 1 end + if cx < 1 then cx = 1 end + end + + local function termwrite(s) + dprint("attempting termwrite") + dprint("writing "..tostring(s)) + local wb = "" + local function flushwb() + dprint("flush") + while wb:len() > 0 do + dprint("flushing "..tostring(wb:len()).." chars: "..tostring(wb)) + checkCursor() + local wl = wb:sub(1,mx-cx+1) + wb = wb:sub(wl:len()+1) + gpu.set(cx, cy, wl) + cx = cx + wl:len() + end + end + local rs = "" + s=s:gsub("\8","\27[D") + pc = gpu.get(cx,cy) + gpu.setForeground(fg) + gpu.setBackground(bg) + gpu.set(cx,cy,pc) + for cc in s:gmatch(".") do + if mode == 0 then + if string.byte(cc) > 31 and string.byte(cc) < 128 then -- probably printable + wb = wb .. cc + elseif cc == "\n" then + flushwb() + cx,cy = 1, cy+1 + elseif cc == "\t" then + cx = 8*((cx+9)//8) + elseif cc == "\27" then + flushwb() + mode = 1 + end + elseif mode == 1 then + if cc == "[" then + dprint("entering escape code mode") + mode = 2 + else + mode = 0 + end + elseif mode == 2 then + if cc:match("[%d;]") then + cs = cs .. cc + else + mode = 0 + dprint("command: "..tostring(cc)) + local tA = {} + for s in cs:gmatch("%d+") do + tA[#tA+1] = tonumber(s) + dprint("arg: "..tostring(s)) + end + if cc == "H" then + cx, cy = tA[1] or 1, tA[2] or 1 + elseif cc == "A" then + cy = cy - (tA[1] or 1) + elseif cc == "B" then + cy = cy + (tA[1] or 1) + elseif cc == "C" then + cx = cx + (tA[1] or 1) + elseif cc == "D" then + cx = cx - (tA[1] or 1) + elseif cc == "s" then + sx, sy = cx, cy + elseif cc == "u" then + cx, cy = sx, sy + elseif cc == "n" and tA[1] == 6 then + rs = string.format("%s\27[%d;%dR",rs,cx,cy) + elseif cc == "K" and tA[1] == 1 then + gpu.fill(1,cy,cx,1," ") + elseif cc == "K" and tA[1] == 2 then + gpu.fill(cx,cy,mx,1," ") + elseif cc == "K" then + gpu.fill(1,cy,mx,1," ") + elseif cc == "J" and tA[1] == 1 then + gpu.fill(1,1,mx,cy," ") + elseif cc == "J" and tA[1] == 2 then + gpu.full(1,1,mx,my," ") + cx, cy = 1, 1 + elseif cc == "J" then + gpu.fill(1,cy,mx,my," ") + elseif cc == "m" then + for _,num in ipairs(tA) do + if num == 0 then + fg,bg = 0xFFFFFF,0 + elseif num == 7 then + local nfg,nbg = bg, fg + fg, bg = nfg, nbg + elseif num > 29 and num < 38 then + fg = colours[num-29] + elseif num > 39 and num < 48 then + bg = colours[num-39] + end + end + gpu.setForeground(fg) + gpu.setBackground(bg) + end + cs = "" + checkCursor() + end + end + end + flushwb() + pc = gpu.get(cx,cy) + gpu.setForeground(bg) + gpu.setBackground(fg) + gpu.set(cx,cy,pc) + gpu.setForeground(fg) + gpu.setBackground(bg) + return rs + end + + return termwrite +end diff --git a/module/vt-task.lua b/module/vt-task.lua index ded07d4..0631eef 100644 --- a/module/vt-task.lua +++ b/module/vt-task.lua @@ -1,5 +1,5 @@ do ---#include "module/vt100.lua" +--#include "module/nvt100.lua" function vtemu(gpua,scra) -- creates a process to handle the GPU and screen address combination *gpua*/*scra*. Returns read, write and "close" functions. local gpu = component.proxy(gpua) gpu.bind(scra)