Last active
December 23, 2020 21:13
-
-
Save MCJack123/f6819e41a60402b8a73403542bb23820 to your computer and use it in GitHub Desktop.
CraftOS-PC Graphics Mode terminal (requires readBDFFont)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- WARNING: Render crashes are lethal and will 100% kill the computer | |
local loadBDF = require "readBDFFont" -- get from https://gist.github.com/MCJack123/3cbce89640923b3c42d4d0a0b8eaa7b2 | |
if term.setGraphicsMode == nil then error("This requires CraftOS-PC v1.2 or later.") end | |
local font, oldterm, gfxMode | |
local nativeTerm = term.native() | |
local oldSetGfx, oldGetGfx = term.setGraphicsMode, term.getGraphicsMode | |
local nativeWidth, nativeHeight = term.getSize() | |
nativeWidth = nativeWidth * 6 | |
nativeHeight = nativeHeight * 9 | |
local function log2(num) return math.floor(math.log10(num) / math.log10(2)) end | |
local function drawChar(x, y, ch, fg, bg, transparent) | |
x=x-1 | |
y=y-1 | |
if x * font.bounds.width > nativeWidth or y * font.bounds.height > nativeHeight or x < 0 or y < 0 then return end | |
local fch = font.chars[ch] | |
if fch == nil then fch = font.chars[' '] end | |
if transparent then | |
local heightDiff = (font.bounds.height + font.bounds.y) - fch.bounds.height + font.bounds.y - fch.bounds.y | |
for i,t in pairs(fch.bitmap) do if i <= font.bounds.height then for j,a in pairs(t) do if j <= font.bounds.width and a then | |
nativeTerm.setPixel(x*font.bounds.width+j-1, y*font.bounds.height+i+heightDiff-1, gfxMode == 2 and fg or log2(fg)) | |
end end end end | |
else | |
local pixelTable = {} | |
for i = 1, font.bounds.height do pixelTable[i] = string.char(bg):rep(font.bounds.width) end | |
local starty = (font.bounds.height - fch.bounds.height) - fch.bounds.y + font.bounds.y | |
for i = 1, fch.bounds.height do | |
if fch.bitmap[i] then | |
pixelTable[i+starty] = string.char(bg):rep(fch.bounds.x) | |
for j = 1, font.bounds.width-fch.bounds.x do | |
pixelTable[i+starty] = pixelTable[i+starty] .. string.char(fch.bitmap[i][j] and fg or bg) | |
end | |
end | |
end | |
local ypos = y*font.bounds.height+font.bounds.y | |
while ypos < 0 do | |
table.remove(pixelTable, 1) | |
ypos=ypos+1 | |
end | |
nativeTerm.drawPixels(x*font.bounds.width, ypos, pixelTable) | |
end | |
end | |
local file | |
if #({...}) > 0 then file = fs.open(shell.resolve(({...})[1]), "r") | |
else file = fs.open(shell.resolve("font.bdf"), "r") end | |
if file == nil then error("Could not find font!") end | |
font = loadBDF(file.readAll()) | |
file.close() | |
local backgroundColor = 15 | |
local textColor = 0 | |
local cursorX = 1 | |
local cursorY = 1 | |
local cursorBlink = true -- soon(tm) | |
local cursorShouldBlink = true | |
local cursorTimer = os.startTimer(0.5) | |
local width = math.floor(nativeWidth / font.bounds.width) | |
local height = math.floor(nativeHeight / font.bounds.height) | |
gfxMode = 0 | |
local termBuffer = {} | |
local colorBuffer = {} | |
for i = 1, height do | |
termBuffer[i] = {} | |
colorBuffer[i] = {} | |
for j = 1, width do | |
termBuffer[i][j] = " " | |
colorBuffer[i][j] = {textColor, backgroundColor} | |
end | |
end | |
local lastcx, lastcy = 1, 1 | |
local function redrawCursor() | |
if lastcx <= width and lastcy <= height then drawChar(lastcx, lastcy, termBuffer[lastcy][lastcx], colorBuffer[lastcy][lastcx][1], colorBuffer[lastcy][lastcx][2], false) end | |
if cursorX <= width and cursorY <= height and cursorBlink and cursorShouldBlink then drawChar(cursorX, cursorY, '_', 0, 15, true) end | |
lastcx, lastcy = cursorX, cursorY | |
end | |
local termObject = { | |
write = function(text) | |
if cursorY > height or cursorX > width then return end | |
for c in text:gmatch(".") do | |
termBuffer[cursorY][cursorX] = c | |
colorBuffer[cursorY][cursorX] = {textColor, backgroundColor} | |
drawChar(cursorX, cursorY, c, textColor, backgroundColor, false) | |
cursorX = cursorX + 1 | |
if cursorX > width then break end | |
end | |
redrawCursor() | |
end, | |
blit = function(text, fg, bg) | |
if #text ~= #fg or #fg ~= #bg then error("Arguments must be same length", 2) end | |
if cursorY > height or cursorX > width then return end | |
for i = 1, #text do | |
textColor = (("0123456789abcdef"):find(fg:sub(i, i)) or (textColor + 1)) - 1 | |
backgroundColor = (("0123456789abcdef"):find(bg:sub(i, i)) or (backgroundColor + 1)) - 1 | |
termBuffer[cursorY][cursorX] = text:sub(i, i) | |
colorBuffer[cursorY][cursorX] = {textColor, backgroundColor} | |
drawChar(cursorX, cursorY, text:sub(i, i), textColor, backgroundColor, false) | |
cursorX = cursorX + 1 | |
if cursorX > width then break end | |
end | |
redrawCursor() | |
end, | |
clear = function() | |
for i = 1, height do | |
termBuffer[i] = {} | |
colorBuffer[i] = {} | |
for j = 1, width do | |
termBuffer[i][j] = " " | |
colorBuffer[i][j] = {textColor, backgroundColor} | |
drawChar(j, i, " ", textColor, backgroundColor, false) | |
end | |
end | |
redrawCursor() | |
end, | |
clearLine = function() | |
if cursorY > height then return end | |
for j = 1, width do | |
termBuffer[cursorY][j] = " " | |
colorBuffer[cursorY][j] = {textColor, backgroundColor} | |
drawChar(j, cursorY, " ", textColor, backgroundColor, false) | |
end | |
redrawCursor() | |
end, | |
getCursorPos = function() return cursorX, cursorY end, | |
setCursorPos = function(x, y) cursorX, cursorY = x, y end, | |
getCursorBlink = function() return cursorShouldBlink end, | |
setCursorBlink = function(b) cursorShouldBlink = b; redrawCursor() end, | |
isColor = function() return true end, | |
isColour = function() return true end, | |
getSize = function() return width, height end, | |
scroll = function(n) | |
for _ = 1, n do | |
table.remove(termBuffer, 1) | |
table.remove(colorBuffer, 1) | |
local tr, cr = {}, {} | |
for j = 1, width do | |
tr[j] = " " | |
cr[j] = {textColor, backgroundColor} | |
end | |
table.insert(termBuffer, tr) | |
table.insert(colorBuffer, cr) | |
end | |
for y = 1, height do for x = 1, width do drawChar(x, y, termBuffer[y][x], colorBuffer[y][x][1], colorBuffer[y][x][2], false) end end | |
redrawCursor() | |
end, | |
setTextColor = function(c) textColor = log2(c) end, | |
setTextColour = function(c) textColor = log2(c) end, | |
getTextColor = function() return bit.blshift(1, textColor) end, | |
getTextColour = function() return bit.blshift(1, textColor) end, | |
setBackgroundColor = function(c) backgroundColor = log2(c) end, | |
setBackgroundColour = function(c) backgroundColor = log2(c) end, | |
getBackgroundColor = function() return bit.blshift(1, backgroundColor) end, | |
getBackgroundColour = function() return bit.blshift(1, backgroundColor) end, | |
getPaletteColor = nativeTerm.getPaletteColor, | |
getPaletteColour = nativeTerm.getPaletteColour, | |
setPaletteColor = nativeTerm.setPaletteColor, | |
setPaletteColour = nativeTerm.setPaletteColour, | |
nativePaletteColor = nativeTerm.nativePaletteColor, | |
nativePaletteColour = nativeTerm.nativePaletteColour, | |
screenshot = nativeTerm.screenshot, | |
} | |
term.setGraphicsMode(1) | |
term.clear() | |
oldterm = term.redirect(termObject) | |
term.setGraphicsMode = function(mode) | |
gfxMode = mode | |
term.clear() | |
if gfxMode == 2 then oldSetGfx(2) else oldSetGfx(1) end | |
if gfxMode == 0 then for y = 1, height do for x = 1, width do drawChar(x, y, termBuffer[y][x], colorBuffer[y][x][1], colorBuffer[y][x][2], false) end end end | |
end | |
term.getGraphicsMode = function() return gfxMode end | |
parallel.waitForAny(function() | |
while true do | |
local ev = {os.pullEvent()} | |
if ev[1] == "term_resize" then | |
local oldw, oldh = width, height | |
nativeWidth, nativeHeight = nativeTerm.getSize() | |
nativeWidth = nativeWidth * 6 | |
nativeHeight = nativeHeight * 9 | |
width = math.floor(nativeWidth / font.bounds.width) | |
height = math.floor(nativeHeight / font.bounds.height) | |
if height > oldh then | |
for i = oldh+1, height do | |
termBuffer[i] = {} | |
colorBuffer[i] = {} | |
for j = 1, oldw do | |
termBuffer[i][j] = ' ' | |
colorBuffer[i][j] = {textColor, backgroundColor} | |
end | |
end | |
elseif height < oldh then | |
for i = height+1, oldh do | |
termBuffer[i] = nil | |
colorBuffer[i] = nil | |
end | |
end | |
if width > oldw then | |
for i = 1, height do for j = oldw+1, width do | |
termBuffer[i][j] = ' ' | |
colorBuffer[i][j] = {textColor, backgroundColor} | |
end end | |
elseif width < oldw then | |
for i = 1, height do for j = width+1, oldw do | |
termBuffer[i][j] = nil | |
colorBuffer[i][j] = nil | |
end end | |
end | |
elseif ev[1] == "timer" and ev[2] == cursorTimer then | |
cursorBlink = not cursorBlink | |
cursorTimer = os.startTimer(0.5) | |
redrawCursor() | |
end | |
end | |
end, function() shell.run("/rom/programs/shell.lua") end) | |
term.setGraphicsMode = oldSetGfx | |
term.getGraphicsMode = oldGetGfx | |
term.redirect(oldterm) | |
term.setGraphicsMode(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment