2016-01-07 02:58:05 +11:00
local textgpu = { }
2016-01-18 06:07:51 +11:00
local write = io.write
local flush = io.flush
2016-01-14 11:10:04 +11:00
2021-05-28 11:18:10 +10:00
local background = 0x000000 -- "0"
local foreground = 0xFFFFFF -- "0"
2016-01-07 02:58:05 +11:00
2016-01-14 11:10:04 +11:00
local tbuffer = { }
local bbuffer = { }
local fbuffer = { }
2021-05-28 11:18:10 +10:00
local palette = {
[ 0 ] = 0x0f0f0f ,
0x1e1e1e ,
0x2d2d2d ,
0x3c3c3c ,
0x4b4b4b ,
0x5a5a5a ,
0x696969 ,
0x787878 ,
0x878787 ,
0x969696 ,
0xa5a5a5 ,
0xb4b4b4 ,
0xc3c3c3 ,
0xd2d2d2 ,
0xe1e1e1 ,
0xf0f0f0
}
2016-01-14 11:10:04 +11:00
local function prepareBuffers ( w , h )
local tbline = ( " " ) : rep ( w )
2021-05-28 11:18:10 +10:00
local bbline = ( " \0 \0 \0 " ) : rep ( w ) -- ("0"):rep(w)
local fbline = ( " \255 \255 \255 " ) : rep ( w ) -- ("7"):rep(w)
2016-01-14 11:10:04 +11:00
for i = 1 , h do
tbuffer [ i ] = tbline
bbuffer [ i ] = bbline
fbuffer [ i ] = fbline
end
end
2021-05-28 11:18:10 +10:00
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
2016-01-21 09:18:02 +11:00
local usub
2016-01-14 11:10:04 +11:00
local function insertString ( main , sub , at )
2016-01-21 09:18:02 +11:00
checkArg ( 1 , main , " string " )
checkArg ( 2 , sub , " string " )
checkArg ( 3 , at , " number " )
2016-02-10 03:42:11 +11:00
2021-05-28 11:18:10 +10:00
return ( usub ( main , 1 , at - 1 ) or " " )
.. sub .. ( usub ( main , at + ( utf8.len ( sub ) or 0 ) ) )
2016-01-14 11:10:04 +11:00
end
2016-01-07 02:58:05 +11:00
function textgpu . start ( )
2016-01-21 09:18:02 +11:00
usub = modules.sandbox . unicode.sub
2016-02-10 03:42:11 +11:00
local _height = 0
2016-01-07 02:58:05 +11:00
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
2021-05-28 11:18:10 +10:00
if color > 15 or color < 0 then
error ( " invalid palette index " , 2 )
end
return palette [ color ]
2016-01-07 02:58:05 +11:00
end
2016-01-16 05:58:26 +11:00
local old = background
2021-05-28 11:18:10 +10:00
background = color -- tostring(math.floor(modules.color.nearest(color, mapping)))
setBackground ( background )
--write("\x1b[4" .. background .. "m")
2016-01-18 06:07:51 +11:00
flush ( )
2021-05-28 11:18:10 +10:00
return old -- mapping[old]
2016-01-07 02:58:05 +11:00
end
function gpu . setForeground ( color , isPaletteIndex )
checkArg ( 1 , color , " number " )
checkArg ( 2 , isPaletteIndex , " boolean " , " nil " )
if isPaletteIndex then
2021-05-28 11:18:10 +10:00
if color < 0 or color > 15 then
error ( " invalid palette index " , 2 )
end
return palette [ color ]
2016-01-07 02:58:05 +11:00
end
2016-01-15 08:44:49 +11:00
local old = foreground
2021-05-28 11:18:10 +10:00
foreground = color -- tostring(math.floor(modules.color.nearest(color, mapping)))
setForeground ( foreground )
--write("\x1b[3" .. foreground .. "m")
2016-01-18 06:07:51 +11:00
flush ( )
2021-05-28 11:18:10 +10:00
return old -- mapping[old]
2016-01-07 02:58:05 +11:00
end
function gpu . getBackground ( )
return mapping [ background ] , false
end
function gpu . getForeground ( )
return mapping [ foreground ] , false
end
2021-05-28 11:18:10 +10:00
function gpu . getPaletteColor ( index )
if index < 0 or index > 15 then
error ( " invalid palette index " , 2 )
end
return palette [ index ]
2016-01-07 02:58:05 +11:00
end
2021-05-28 11:18:10 +10:00
function gpu . setPaletteColor ( index , value )
if index < 0 or index > 15 then
error ( " invalid palette index " , 2 )
end
palette [ index ] = value
return true
2016-01-07 02:58:05 +11:00
end
function gpu . maxDepth ( )
2021-05-28 11:18:10 +10:00
return 4
2016-01-07 02:58:05 +11:00
end
function gpu . setDepth ( )
2021-05-28 11:18:10 +10:00
return true
2016-01-07 02:58:05 +11:00
end
function gpu . getDepth ( )
2021-05-28 11:18:10 +10:00
return 4
2016-01-07 02:58:05 +11:00
end
function gpu . maxResolution ( )
return termutils.getSize ( )
end
function gpu . getResolution ( )
return termutils.getSize ( )
end
2016-01-15 08:44:49 +11:00
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
2016-01-07 02:58:05 +11:00
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 " )
2016-08-18 06:40:11 +10:00
2021-05-28 11:18:10 +10:00
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 " )
2016-01-07 02:58:05 +11:00
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 " )
2016-01-10 05:39:48 +11:00
x = math.floor ( x )
y = math.floor ( y )
2016-01-07 02:58:05 +11:00
if not vertical then
2016-01-21 09:18:02 +11:00
if not tbuffer [ y ] then
2016-02-10 08:55:26 +11:00
native.log ( " GPU Set failed: under buffer " )
2016-01-21 09:18:02 +11:00
return false
end
2016-01-14 11:10:04 +11:00
tbuffer [ y ] = insertString ( tbuffer [ y ] , value , x )
2021-05-28 11:18:10 +10:00
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 )
2016-01-18 06:07:51 +11:00
write ( " \x1b [ " .. y .. " ; " .. x .. " H " .. value )
2016-01-07 02:58:05 +11:00
else
2016-01-21 09:18:02 +11:00
--TODO: Buffers!
2016-01-18 06:07:51 +11:00
write ( " \x1b [ " .. y .. " ; " .. x .. " H " )
2016-03-12 11:00:11 +11:00
value : gsub ( " ([%z \1 - \127 \194 - \244 ][ \128 - \191 ]*) " , function ( c )
2016-01-18 06:07:51 +11:00
write ( c .. " \x1b [D \x1b [B " )
2016-01-07 02:58:05 +11:00
end )
end
2016-01-18 06:07:51 +11:00
flush ( )
2016-01-07 02:58:05 +11:00
return true
end
2016-01-14 11:10:04 +11:00
function gpu . copy ( x , y , w , h , tx , ty ) --TODO: Check(check X multiple times)
2016-01-07 02:58:05 +11:00
checkArg ( 1 , x , " number " )
checkArg ( 2 , y , " number " )
checkArg ( 3 , w , " number " )
checkArg ( 4 , h , " number " )
checkArg ( 5 , tx , " number " )
checkArg ( 6 , ty , " number " )
2016-01-14 11:10:04 +11:00
local ttbuf = { }
local btbuf = { }
local ftbuf = { }
for i = 1 , h do
2016-02-10 08:55:26 +11:00
if i + y - 2 <= _height and i + y > 1 then
2016-02-10 03:42:11 +11:00
ttbuf [ i ] = tbuffer [ y + i - 1 ] and usub ( tbuffer [ y + i - 1 ] , x , x + w - 1 ) or ( " " ) : rep ( w )
2021-05-28 11:18:10 +10:00
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 )
2016-02-10 03:42:11 +11:00
else
ttbuf [ i ] = ( " " ) : rep ( w )
2021-05-28 11:18:10 +10:00
btbuf [ i ] = string.pack ( " >I3 " , background ) : rep ( w )
ftbuf [ i ] = string.pack ( " >I3 " , foreground ) : rep ( w )
2016-02-10 03:42:11 +11:00
end
2016-01-14 11:10:04 +11:00
end
local bg = background
local fg = foreground
for i = 1 , h do
local line , linex
2016-01-18 06:07:51 +11:00
local lwrite = false
2016-01-14 11:10:04 +11:00
for j = 1 , w do
2021-05-28 11:18:10 +10:00
if btbuf [ i ] : sub ( j * 3 - 2 , j * 3 ) : unpack ( " >I3 " ) ~= bg then
2016-01-18 06:07:51 +11:00
lwrite = true
2016-01-14 11:10:04 +11:00
end
2021-05-28 11:18:10 +10:00
if ftbuf [ i ] : sub ( j * 3 - 2 , j * 3 ) : unpack ( " >I3 " ) ~= fg then
2016-01-18 06:07:51 +11:00
lwrite = true
2016-01-14 11:10:04 +11:00
end
if not line then linex = j end
2016-01-16 22:42:09 +11:00
line = ( line or " " )
2016-01-18 06:07:51 +11:00
if lwrite then
2016-02-10 08:55:26 +11:00
local wx = ( tx + x + linex - 1 ) | 0
2016-01-14 11:10:04 +11:00
local wy = ( ty + y + i - 1 ) | 0
2016-02-10 08:55:26 +11:00
if tbuffer [ wy ] then
2021-05-28 11:18:10 +10:00
setBackground ( bg )
setForeground ( foreground )
--write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m
write ( " \x1b [ " .. wy .. " ; " .. wx .. " H " .. line )
2016-02-10 08:55:26 +11:00
tbuffer [ wy ] = insertString ( tbuffer [ wy ] , line , wx )
2021-05-28 11:18:10 +10:00
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 )
2016-02-10 08:55:26 +11:00
end
2016-02-10 03:42:11 +11:00
2021-05-28 11:18:10 +10:00
bg = btbuf [ i ] : sub ( j * 3 - 2 , j * 3 ) : unpack ( " >I3 " )
fg = ftbuf [ i ] : sub ( j * 3 - 2 , j * 3 ) : unpack ( " >I3 " )
2016-01-14 11:10:04 +11:00
line = nil
linex = nil
2016-01-18 06:07:51 +11:00
lwrite = false
2016-01-14 11:10:04 +11:00
end
2016-01-16 22:42:09 +11:00
if not line then linex = j end
2016-02-10 03:42:11 +11:00
line = ( line or " " ) .. usub ( ttbuf [ i ] , j , j )
2016-01-14 11:10:04 +11:00
end
if line then
2016-02-10 08:55:26 +11:00
local wx = ( tx + x + linex - 1 ) | 0
2016-01-14 11:10:04 +11:00
local wy = ( ty + y + i - 1 ) | 0
2016-02-10 08:55:26 +11:00
if tbuffer [ wy ] then
2021-05-28 11:18:10 +10:00
setBackground ( bg )
setForeground ( fg )
--write("\x1b[4" .. bg .. "m\x1b[3" .. fg .. "m
write ( " \x1b [ " .. wy .. " ; " .. wx .. " H " .. line )
2016-02-10 08:55:26 +11:00
tbuffer [ wy ] = insertString ( tbuffer [ wy ] , line , wx )
2021-05-28 11:18:10 +10:00
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 )
2016-02-10 08:55:26 +11:00
end
2016-01-14 11:10:04 +11:00
line = nil
linex = nil
2016-01-18 06:07:51 +11:00
lwrite = false
2016-01-14 11:10:04 +11:00
end
end
2021-05-28 11:18:10 +10:00
setBackground ( background )
setForeground ( foreground )
--write("\x1b[4" .. background .. "m")
--write("\x1b[3" .. foreground .. "m")
2016-01-18 06:07:51 +11:00
flush ( )
2016-01-14 11:10:04 +11:00
return true
2016-01-07 02:58:05 +11:00
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 " )
2016-02-10 03:42:11 +11:00
ch = usub ( ch , 1 , 1 ) : rep ( math.floor ( w ) )
2016-01-07 02:58:05 +11:00
for i = 1 , h do
2016-02-10 08:55:26 +11:00
if i + y - 1 <= _height and i + y > 1 then
2016-02-10 03:42:11 +11:00
gpu.set ( x , y + i - 1 , ch )
end
2016-01-07 02:58:05 +11:00
end
return true
end
2016-01-20 04:25:09 +11:00
local screenAddr
function gpu . getScreen ( )
return screenAddr
end
2016-02-28 01:30:34 +11:00
if not termutils.init ( ) then
return nil , " Cannot initialize terminal based gpu "
end
2016-01-18 06:07:51 +11:00
write ( " \x1b [?25l " ) --Disable cursor
2016-01-14 11:10:04 +11:00
local w , h = gpu.getResolution ( )
2016-02-10 03:42:11 +11:00
_height = h
2016-01-14 11:10:04 +11:00
prepareBuffers ( w , h )
2016-01-07 02:58:05 +11:00
gpu.setForeground ( 0xFFFFFF )
gpu.setBackground ( 0x000000 )
2016-02-28 01:30:34 +11:00
local gpuaddr = modules.component . api.register ( nil , " gpu " , gpu )
2016-01-20 04:25:09 +11:00
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
2016-01-16 22:42:09 +11:00
modules.component . api.register ( " TODO:SetThisUuid " , " keyboard " , { } )
2016-01-10 05:39:48 +11:00
deadhooks [ # deadhooks + 1 ] = function ( )
2016-02-10 03:42:11 +11:00
write ( " \x1b [?25h \x1b [ " .. ( ( h - 1 ) | 0 ) .. " ;1H " ) --Enable cursor on quit
io.flush ( )
termutils.restore ( )
2016-01-10 05:39:48 +11:00
end
2016-02-28 01:30:34 +11:00
return gpuaddr
2016-01-07 02:58:05 +11:00
end
2016-01-20 05:46:40 +11:00
return textgpu