83 lines
3.2 KiB
Lua
83 lines
3.2 KiB
Lua
-- raw-player from sanjuuni
|
|
-- Licensed under the MIT license
|
|
|
|
local b64str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
local function base64decode(str)
|
|
local retval = ""
|
|
for s in str:gmatch "...." do
|
|
if s:sub(3, 4) == '==' then
|
|
retval = retval .. string.char(bit32.bor(bit32.lshift(b64str:find(s:sub(1, 1)) - 1, 2), bit32.rshift(b64str:find(s:sub(2, 2)) - 1, 4)))
|
|
elseif s:sub(4, 4) == '=' then
|
|
local n = (b64str:find(s:sub(1, 1))-1) * 4096 + (b64str:find(s:sub(2, 2))-1) * 64 + (b64str:find(s:sub(3, 3))-1)
|
|
retval = retval .. string.char(bit32.extract(n, 10, 8)) .. string.char(bit32.extract(n, 2, 8))
|
|
else
|
|
local n = (b64str:find(s:sub(1, 1))-1) * 262144 + (b64str:find(s:sub(2, 2))-1) * 4096 + (b64str:find(s:sub(3, 3))-1) * 64 + (b64str:find(s:sub(4, 4))-1)
|
|
retval = retval .. string.char(bit32.extract(n, 16, 8)) .. string.char(bit32.extract(n, 8, 8)) .. string.char(bit32.extract(n, 0, 8))
|
|
end
|
|
end
|
|
return retval
|
|
end
|
|
|
|
local file, err = fs.open(shell.resolve(...), "r")
|
|
if not file then error(err) end
|
|
if file.readLine() ~= "32Vid 1.1" then error("Unsupported file") end
|
|
local fps = tonumber(file.readLine())
|
|
local first, second = file.readLine(), file.readLine()
|
|
if second == "" or second == nil then fps = 0 end
|
|
term.clear()
|
|
while true do
|
|
local frame
|
|
if first then frame, first = first, nil
|
|
elseif second then frame, second = second, nil
|
|
else frame = file.readLine() end
|
|
if frame == "" or frame == nil then break end
|
|
local mode = frame:match("^!CP([CD])")
|
|
if not mode then error("Invalid file") end
|
|
local b64data
|
|
if mode == "C" then
|
|
local len = tonumber(frame:sub(5, 8), 16)
|
|
b64data = frame:sub(9, len + 8)
|
|
else
|
|
local len = tonumber(frame:sub(5, 16), 16)
|
|
b64data = frame:sub(17, len + 16)
|
|
end
|
|
local data = base64decode(b64data)
|
|
-- TODO: maybe verify checksums?
|
|
assert(data:sub(1, 4) == "\0\0\0\0" and data:sub(9, 16) == "\0\0\0\0\0\0\0\0", "Invalid file")
|
|
local width, height = ("HH"):unpack(data, 5)
|
|
local c, n, pos = string.unpack("c1B", data, 17)
|
|
local text = {}
|
|
for y = 1, height do
|
|
text[y] = ""
|
|
for x = 1, width do
|
|
text[y] = text[y] .. c
|
|
n = n - 1
|
|
if n == 0 then c, n, pos = string.unpack("c1B", data, pos) end
|
|
end
|
|
end
|
|
c = c:byte()
|
|
for y = 1, height do
|
|
local fg, bg = "", ""
|
|
for x = 1, width do
|
|
fg, bg = fg .. ("%x"):format(bit32.band(c, 0x0F)), bg .. ("%x"):format(bit32.rshift(c, 4))
|
|
n = n - 1
|
|
if n == 0 then c, n, pos = string.unpack("BB", data, pos) end
|
|
end
|
|
term.setCursorPos(1, y)
|
|
term.blit(text[y], fg, bg)
|
|
end
|
|
pos = pos - 2
|
|
local r, g, b
|
|
for i = 0, 15 do
|
|
r, g, b, pos = string.unpack("BBB", data, pos)
|
|
term.setPaletteColor(2^i, r / 255, g / 255, b / 255)
|
|
end
|
|
if fps == 0 then read() break
|
|
else sleep(1 / fps) end
|
|
end
|
|
file.close()
|
|
for i = 0, 15 do term.setPaletteColor(2^i, term.nativePaletteColor(2^i)) end
|
|
term.setBackgroundColor(colors.black)
|
|
term.setTextColor(colors.white)
|
|
term.clear()
|
|
term.setCursorPos(1, 1) |