mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-26 12:28:05 +11:00
Compare commits
No commits in common. "8bd316338baa14b633c5d0cab1839aa8fd1b6cbf" and "fab88f137c4198aef124e41c69b5d5c2e1a4dca7" have entirely different histories.
8bd316338b
...
fab88f137c
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
# This is released into the public domain.
|
# This is released into the public domain.
|
||||||
# No warranty is provided, implied or otherwise.
|
# No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
# leaving in preSH.tar.gz for anyone who's interested
|
||||||
|
# in how NOT to do compression
|
||||||
code.tar
|
code.tar
|
||||||
code/data/app-claw/*
|
code/data/app-claw/*
|
||||||
work.tar
|
work.tar
|
||||||
@ -30,9 +32,7 @@ laboratory/*/*/*/*
|
|||||||
inst.lua
|
inst.lua
|
||||||
# Available as the respective release
|
# Available as the respective release
|
||||||
inst-gold.lua
|
inst-gold.lua
|
||||||
# Compression stuff
|
com2/code.tar.bd
|
||||||
inst/iSymTab
|
|
||||||
# internal
|
|
||||||
upldr.sh
|
upldr.sh
|
||||||
upldr-dev.sh
|
upldr-dev.sh
|
||||||
upldr-gold.sh
|
upldr-gold.sh
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
return {
|
return {
|
||||||
["neo"] = {
|
["neo"] = {
|
||||||
desc = "KittenOS NEO Kernel & Base Libs",
|
desc = "KittenOS NEO Kernel & Base Libs",
|
||||||
v = 9,
|
v = 8,
|
||||||
deps = {
|
deps = {
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
@ -18,7 +18,6 @@ return {
|
|||||||
"libs/serial.lua",
|
"libs/serial.lua",
|
||||||
"libs/fmttext.lua",
|
"libs/fmttext.lua",
|
||||||
"libs/neoux.lua",
|
"libs/neoux.lua",
|
||||||
"libs/lineedit.lua",
|
|
||||||
"libs/braille.lua",
|
"libs/braille.lua",
|
||||||
"libs/bmp.lua",
|
"libs/bmp.lua",
|
||||||
"libs/sys-filewrap.lua",
|
"libs/sys-filewrap.lua",
|
||||||
@ -55,7 +54,7 @@ return {
|
|||||||
},
|
},
|
||||||
["neo-everest"] = {
|
["neo-everest"] = {
|
||||||
desc = "KittenOS NEO / Everest (windowing)",
|
desc = "KittenOS NEO / Everest (windowing)",
|
||||||
v = 9,
|
v = 5,
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -68,7 +67,7 @@ return {
|
|||||||
},
|
},
|
||||||
["neo-icecap"] = {
|
["neo-icecap"] = {
|
||||||
desc = "KittenOS NEO / Icecap",
|
desc = "KittenOS NEO / Icecap",
|
||||||
v = 9,
|
v = 8,
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -85,7 +84,7 @@ return {
|
|||||||
},
|
},
|
||||||
["neo-secpolicy"] = {
|
["neo-secpolicy"] = {
|
||||||
desc = "KittenOS NEO / Secpolicy",
|
desc = "KittenOS NEO / Secpolicy",
|
||||||
v = 9,
|
v = 8,
|
||||||
deps = {
|
deps = {
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
@ -97,7 +96,7 @@ return {
|
|||||||
},
|
},
|
||||||
["neo-coreapps"] = {
|
["neo-coreapps"] = {
|
||||||
desc = "KittenOS NEO Core Apps",
|
desc = "KittenOS NEO Core Apps",
|
||||||
v = 9,
|
v = 5,
|
||||||
deps = {
|
deps = {
|
||||||
"neo"
|
"neo"
|
||||||
},
|
},
|
||||||
@ -126,7 +125,7 @@ return {
|
|||||||
},
|
},
|
||||||
["neo-logo"] = {
|
["neo-logo"] = {
|
||||||
desc = "KittenOS NEO Logo (data)",
|
desc = "KittenOS NEO Logo (data)",
|
||||||
v = 9,
|
v = 8,
|
||||||
deps = {
|
deps = {
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
@ -176,20 +175,6 @@ return {
|
|||||||
"apps/svc-app-claw-worker.lua"
|
"apps/svc-app-claw-worker.lua"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["svc-t"] = {
|
|
||||||
desc = "KittenOS NEO Terminal System",
|
|
||||||
v = 9,
|
|
||||||
deps = {
|
|
||||||
"neo"
|
|
||||||
},
|
|
||||||
dirs = {
|
|
||||||
"apps"
|
|
||||||
},
|
|
||||||
files = {
|
|
||||||
"apps/svc-t.lua",
|
|
||||||
"apps/app-luashell.lua"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
["neo-meta"] = {
|
["neo-meta"] = {
|
||||||
desc = "KittenOS NEO: Use 'All' to install to other disks",
|
desc = "KittenOS NEO: Use 'All' to install to other disks",
|
||||||
v = 5,
|
v = 5,
|
||||||
@ -205,7 +190,6 @@ return {
|
|||||||
"app-bmpview",
|
"app-bmpview",
|
||||||
"app-flash",
|
"app-flash",
|
||||||
"app-claw",
|
"app-claw",
|
||||||
"svc-t",
|
|
||||||
"app-wget"
|
"app-wget"
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
|
@ -24,7 +24,7 @@ return {
|
|||||||
},
|
},
|
||||||
["neo-docs"] = {
|
["neo-docs"] = {
|
||||||
desc = "KittenOS NEO system documentation",
|
desc = "KittenOS NEO system documentation",
|
||||||
v = 9,
|
v = 8,
|
||||||
deps = {
|
deps = {
|
||||||
"zzz-license-pd"
|
"zzz-license-pd"
|
||||||
},
|
},
|
||||||
@ -43,7 +43,6 @@ return {
|
|||||||
"docs/us-setti",
|
"docs/us-setti",
|
||||||
"docs/us-evrst",
|
"docs/us-evrst",
|
||||||
"docs/us-clawf",
|
"docs/us-clawf",
|
||||||
"docs/us-termi",
|
|
||||||
"docs/ul-seria",
|
"docs/ul-seria",
|
||||||
"docs/ul-fwrap",
|
"docs/ul-fwrap",
|
||||||
"docs/ul-event",
|
"docs/ul-event",
|
||||||
@ -51,7 +50,6 @@ return {
|
|||||||
"docs/ul-neoux",
|
"docs/ul-neoux",
|
||||||
"docs/ul-brail",
|
"docs/ul-brail",
|
||||||
"docs/ul-bmp__",
|
"docs/ul-bmp__",
|
||||||
"docs/ul-linee",
|
|
||||||
"docs/gp-pedan",
|
"docs/gp-pedan",
|
||||||
"docs/repoauthors/neo-docs"
|
"docs/repoauthors/neo-docs"
|
||||||
},
|
},
|
||||||
@ -91,12 +89,11 @@ return {
|
|||||||
"docs/repoauthors/app-allmem"
|
"docs/repoauthors/app-allmem"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["app-telnet"] = {
|
["app-kmt"] = {
|
||||||
desc = "TELNET client",
|
desc = "Line-terminal for MUDs & such",
|
||||||
v = 0,
|
v = 1,
|
||||||
deps = {
|
deps = {
|
||||||
"neo",
|
"neo",
|
||||||
"svc-t",
|
|
||||||
"zzz-license-pd"
|
"zzz-license-pd"
|
||||||
},
|
},
|
||||||
dirs = {
|
dirs = {
|
||||||
@ -105,8 +102,8 @@ return {
|
|||||||
"docs/repoauthors"
|
"docs/repoauthors"
|
||||||
},
|
},
|
||||||
files = {
|
files = {
|
||||||
"apps/app-telnet.lua",
|
"apps/app-kmt.lua",
|
||||||
"docs/repoauthors/app-telnet"
|
"docs/repoauthors/app-kmt"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["svc-ghostie"] = {
|
["svc-ghostie"] = {
|
||||||
@ -254,6 +251,24 @@ return {
|
|||||||
"docs/repoauthors/app-slaunch"
|
"docs/repoauthors/app-slaunch"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
["svc-virtudev"] = {
|
||||||
|
desc = "a clone of vcomponent",
|
||||||
|
v = 0,
|
||||||
|
deps = {
|
||||||
|
"neo",
|
||||||
|
"zzz-license-pd"
|
||||||
|
},
|
||||||
|
dirs = {
|
||||||
|
"apps",
|
||||||
|
"docs",
|
||||||
|
"docs/repoauthors"
|
||||||
|
},
|
||||||
|
files = {
|
||||||
|
"apps/svc-virtudev.lua",
|
||||||
|
"apps/app-vdrslamp.lua",
|
||||||
|
"docs/repoauthors/svc-virtudev"
|
||||||
|
},
|
||||||
|
},
|
||||||
-- libraries
|
-- libraries
|
||||||
["lib-knbs"] = {
|
["lib-knbs"] = {
|
||||||
desc = "NBS reader/writer library",
|
desc = "NBS reader/writer library",
|
||||||
@ -271,25 +286,6 @@ return {
|
|||||||
"docs/repoauthors/lib-knbs"
|
"docs/repoauthors/lib-knbs"
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["svc-virtudev"] = {
|
|
||||||
desc = "a clone of vcomponent",
|
|
||||||
v = 1,
|
|
||||||
deps = {
|
|
||||||
"neo",
|
|
||||||
"zzz-license-pd"
|
|
||||||
},
|
|
||||||
dirs = {
|
|
||||||
"apps",
|
|
||||||
"docs",
|
|
||||||
"docs/repoauthors"
|
|
||||||
},
|
|
||||||
files = {
|
|
||||||
"apps/svc-virtudev.lua",
|
|
||||||
"apps/app-vdrslamp.lua",
|
|
||||||
"docs/us-virtu",
|
|
||||||
"docs/repoauthors/svc-virtudev"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
-- licenses (MUST BE IMMUTABLE)
|
-- licenses (MUST BE IMMUTABLE)
|
||||||
["zzz-license-pd"] = {
|
["zzz-license-pd"] = {
|
||||||
desc = "license file 'Public Domain'",
|
desc = "license file 'Public Domain'",
|
||||||
|
@ -226,7 +226,7 @@ window = neoux.create(currentGen())
|
|||||||
while running do
|
while running do
|
||||||
local src, id, k, v = event.pull()
|
local src, id, k, v = event.pull()
|
||||||
if src == "x.neo.sys.manage" then
|
if src == "x.neo.sys.manage" then
|
||||||
if id == "set_setting" and currentGen ~= logGen then
|
if id == "set_setting" then
|
||||||
window.reset(currentGen())
|
window.reset(currentGen())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,164 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
local _, _, termId = ...
|
|
||||||
local ok = pcall(function ()
|
|
||||||
assert(string.sub(termId, 1, 12) == "x.neo.pub.t/")
|
|
||||||
end)
|
|
||||||
|
|
||||||
local termClose
|
|
||||||
|
|
||||||
if not ok then
|
|
||||||
termId = nil
|
|
||||||
assert(neo.executeAsync("svc-t", function (res)
|
|
||||||
termId = res.access
|
|
||||||
termClose = res.close
|
|
||||||
neo.scheduleTimer(0)
|
|
||||||
end, "luashell"))
|
|
||||||
while not termId do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
TERM = neo.requireAccess(termId, "terminal")
|
|
||||||
|
|
||||||
-- Using event makes it easier for stuff
|
|
||||||
-- within the shell to not spectacularly explode.
|
|
||||||
event = require("event")(neo)
|
|
||||||
|
|
||||||
local alive = true
|
|
||||||
event.listen("k.procdie", function (_, _, pid)
|
|
||||||
if pid == TERM.pid then
|
|
||||||
alive = false
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
TERM.write([[
|
|
||||||
KittenOS NEO Shell Usage Notes
|
|
||||||
|
|
||||||
Prefixing = is an alias for 'return '.
|
|
||||||
io.read(): Reads a line.
|
|
||||||
print: 'print with table dumping' impl.
|
|
||||||
TERM: Your terminal. (see us-termi doc.)
|
|
||||||
os.execute(): launch terminal apps!
|
|
||||||
tries '*', 'sys-t-*', 'svc-t-*', 'app-*'
|
|
||||||
example: os.execute("luashell")
|
|
||||||
os.exit(): quit the shell
|
|
||||||
=listCmdApps(): -t- (terminal) apps
|
|
||||||
event: useful for setting up listeners
|
|
||||||
without breaking shell functionality
|
|
||||||
]])
|
|
||||||
|
|
||||||
function listCmdApps()
|
|
||||||
local apps = {}
|
|
||||||
for _, v in ipairs(neo.listApps()) do
|
|
||||||
if v:sub(4, 6) == "-t-" then
|
|
||||||
table.insert(apps, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return apps
|
|
||||||
end
|
|
||||||
|
|
||||||
local function vPrint(slike, ...)
|
|
||||||
local s = {...}
|
|
||||||
if #s > 1 then
|
|
||||||
for i = 1, #s do
|
|
||||||
if i ~= 1 then TERM.write("\t") end
|
|
||||||
vPrint(slike, s[i])
|
|
||||||
end
|
|
||||||
elseif slike and type(s[1]) == "string" then
|
|
||||||
TERM.write("\"" .. s[1] .. "\"")
|
|
||||||
elseif type(s[1]) ~= "table" then
|
|
||||||
TERM.write(tostring(s[1]))
|
|
||||||
else
|
|
||||||
TERM.write("{")
|
|
||||||
for k, v in pairs(s[1]) do
|
|
||||||
TERM.write("[")
|
|
||||||
vPrint(true, k)
|
|
||||||
TERM.write("] = ")
|
|
||||||
vPrint(true, v)
|
|
||||||
TERM.write(", ")
|
|
||||||
end
|
|
||||||
TERM.write("}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
print = function (...)
|
|
||||||
vPrint(false, ...)
|
|
||||||
TERM.write("\r\n")
|
|
||||||
end
|
|
||||||
|
|
||||||
local ioBuffer = ""
|
|
||||||
|
|
||||||
io = {
|
|
||||||
read = function ()
|
|
||||||
while alive do
|
|
||||||
local pos = ioBuffer:find("\n")
|
|
||||||
if pos then
|
|
||||||
local line = ioBuffer:sub(1, pos):gsub("\r", "")
|
|
||||||
ioBuffer = ioBuffer:sub(pos + 1)
|
|
||||||
return line
|
|
||||||
end
|
|
||||||
local e = {event.pull()}
|
|
||||||
if e[1] == TERM.id then
|
|
||||||
if e[2] == "data" then
|
|
||||||
ioBuffer = ioBuffer .. e[3]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
write = function (s) TERM.write(s) end
|
|
||||||
}
|
|
||||||
|
|
||||||
local originalOS = os
|
|
||||||
os = setmetatable({}, {
|
|
||||||
__index = originalOS
|
|
||||||
})
|
|
||||||
|
|
||||||
function os.exit()
|
|
||||||
alive = false
|
|
||||||
end
|
|
||||||
|
|
||||||
function os.execute(x, ...)
|
|
||||||
local subPid = neo.executeAsync(x, TERM.id, ...)
|
|
||||||
if not subPid then
|
|
||||||
subPid = neo.executeAsync("sys-t-" .. x, TERM.id, ...)
|
|
||||||
end
|
|
||||||
if not subPid then
|
|
||||||
subPid = neo.executeAsync("svc-t-" .. x, TERM.id, ...)
|
|
||||||
end
|
|
||||||
if not subPid then
|
|
||||||
subPid = neo.executeAsync("app-" .. x, TERM.id, ...)
|
|
||||||
end
|
|
||||||
if not subPid then
|
|
||||||
error("cannot find " .. x)
|
|
||||||
end
|
|
||||||
while true do
|
|
||||||
local e = {event.pull()}
|
|
||||||
if e[1] == "k.procdie" then
|
|
||||||
if e[3] == subPid then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
while alive do
|
|
||||||
TERM.write("> ")
|
|
||||||
local code = io.read()
|
|
||||||
if code then
|
|
||||||
local ok, err = pcall(function ()
|
|
||||||
if code:sub(1, 1) == "=" then
|
|
||||||
code = "return " .. code:sub(2)
|
|
||||||
end
|
|
||||||
print(assert(load(code))())
|
|
||||||
end)
|
|
||||||
if not ok then
|
|
||||||
TERM.write(tostring(err) .. "\r\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if termClose then
|
|
||||||
termClose()
|
|
||||||
end
|
|
||||||
|
|
@ -30,17 +30,32 @@ local clipsrc = neo.requireAccess("x.neo.pub.globals", "clipboard")
|
|||||||
local windows = neo.requireAccess("x.neo.pub.window", "windows")
|
local windows = neo.requireAccess("x.neo.pub.window", "windows")
|
||||||
local files = neo.requireAccess("x.neo.pub.base", "files").showFileDialogAsync
|
local files = neo.requireAccess("x.neo.pub.base", "files").showFileDialogAsync
|
||||||
|
|
||||||
local lineEdit = require("lineedit")
|
|
||||||
|
|
||||||
local cursorX = 1
|
local cursorX = 1
|
||||||
local cursorY = math.ceil(#lines / 2)
|
local cursorY = math.ceil(#lines / 2)
|
||||||
local ctrlFlag, appendFlag
|
local cFlash = true
|
||||||
|
local ctrlFlag, focFlag, appendFlag
|
||||||
local dialogLock = false
|
local dialogLock = false
|
||||||
local sW, sH = 37, #lines + 2
|
local sW, sH = 37, #lines + 2
|
||||||
local window = windows(sW, sH)
|
local window = windows(sW, sH)
|
||||||
local filedialog = nil
|
local filedialog = nil
|
||||||
local flush
|
local flush
|
||||||
|
|
||||||
|
local function splitCur()
|
||||||
|
local s = lines[cursorY]
|
||||||
|
local st = unicode.sub(s, 1, cursorX - 1)
|
||||||
|
local en = unicode.sub(s, cursorX)
|
||||||
|
return st, en
|
||||||
|
end
|
||||||
|
|
||||||
|
local function clampCursorX()
|
||||||
|
local s = lines[cursorY]
|
||||||
|
if unicode.len(s) < (cursorX - 1) then
|
||||||
|
cursorX = unicode.len(s) + 1
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
local cbs = {}
|
local cbs = {}
|
||||||
|
|
||||||
local function fileDialog(writing, callback)
|
local function fileDialog(writing, callback)
|
||||||
@ -124,14 +139,31 @@ local function getline(y)
|
|||||||
-- rX is difficult!
|
-- rX is difficult!
|
||||||
local rX = 1
|
local rX = 1
|
||||||
local Xthold = math.max(1, math.floor(sW / 2) - 1)
|
local Xthold = math.max(1, math.floor(sW / 2) - 1)
|
||||||
local cLine, cursorXP = unicode.safeTextFormat(lines[cursorY], cursorX)
|
local _, cursorXP = unicode.safeTextFormat(lines[cursorY], cursorX)
|
||||||
rX = (math.max(0, math.floor(cursorXP / Xthold) - 1) * Xthold) + 1
|
rX = (math.max(0, math.floor(cursorXP / Xthold) - 1) * Xthold) + 1
|
||||||
local line = lines[rY]
|
local line = lines[rY]
|
||||||
if not line then
|
if not line then
|
||||||
return ("¬"):rep(sW)
|
return ("¬"):rep(sW)
|
||||||
end
|
end
|
||||||
line = unicode.safeTextFormat(line)
|
line = unicode.safeTextFormat(line)
|
||||||
return lineEdit.draw(sW, line, rY == cursorY and cursorXP, rX)
|
-- <alter RX here by 1 if needed>
|
||||||
|
local tl = unicode.sub(line, rX, rX + sW - 1)
|
||||||
|
cursorXP = (cursorXP - rX) + 1
|
||||||
|
if cFlash then
|
||||||
|
if rY == cursorY then
|
||||||
|
if cursorXP >= 1 then
|
||||||
|
if cursorXP <= sW then
|
||||||
|
local start = unicode.sub(tl, 1, cursorXP - 1)
|
||||||
|
local endx = unicode.sub(tl, cursorXP + 1)
|
||||||
|
tl = start .. "_" .. endx
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
while unicode.len(tl) < sW do
|
||||||
|
tl = tl .. " "
|
||||||
|
end
|
||||||
|
return tl
|
||||||
end
|
end
|
||||||
local function delLine()
|
local function delLine()
|
||||||
local contents = lines[cursorY]
|
local contents = lines[cursorY]
|
||||||
@ -147,7 +179,22 @@ local function delLine()
|
|||||||
end
|
end
|
||||||
return contents
|
return contents
|
||||||
end
|
end
|
||||||
local function key(ks, kc, down)
|
-- add a single character
|
||||||
|
local function putLetter(ch)
|
||||||
|
if ch == "\r" then
|
||||||
|
local a, b = splitCur()
|
||||||
|
lines[cursorY] = a
|
||||||
|
table.insert(lines, cursorY + 1, b)
|
||||||
|
cursorY = cursorY + 1
|
||||||
|
cursorX = 1
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local a, b = splitCur()
|
||||||
|
a = a .. ch
|
||||||
|
lines[cursorY] = a .. b
|
||||||
|
cursorX = unicode.len(a) + 1
|
||||||
|
end
|
||||||
|
local function key(ka, kc, down)
|
||||||
if dialogLock then
|
if dialogLock then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -165,22 +212,18 @@ local function key(ks, kc, down)
|
|||||||
sH = 1
|
sH = 1
|
||||||
end
|
end
|
||||||
sW, sH = window.setSize(sW, sH)
|
sW, sH = window.setSize(sW, sH)
|
||||||
return false
|
|
||||||
elseif kc == 208 then -- Down
|
elseif kc == 208 then -- Down
|
||||||
sH = sH + 1
|
sH = sH + 1
|
||||||
sW, sH = window.setSize(sW, sH)
|
sW, sH = window.setSize(sW, sH)
|
||||||
return false
|
|
||||||
elseif kc == 203 then -- Left
|
elseif kc == 203 then -- Left
|
||||||
sW = sW - 1
|
sW = sW - 1
|
||||||
if sW == 0 then
|
if sW == 0 then
|
||||||
sW = 1
|
sW = 1
|
||||||
end
|
end
|
||||||
sW, sH = window.setSize(sW, sH)
|
sW, sH = window.setSize(sW, sH)
|
||||||
return false
|
|
||||||
elseif kc == 205 then -- Right
|
elseif kc == 205 then -- Right
|
||||||
sW = sW + 1
|
sW = sW + 1
|
||||||
sW, sH = window.setSize(sW, sH)
|
sW, sH = window.setSize(sW, sH)
|
||||||
return false
|
|
||||||
elseif kc == 14 then -- ^Backspace
|
elseif kc == 14 then -- ^Backspace
|
||||||
delLine()
|
delLine()
|
||||||
return true
|
return true
|
||||||
@ -197,7 +240,7 @@ local function key(ks, kc, down)
|
|||||||
if cursorY < 1 then
|
if cursorY < 1 then
|
||||||
cursorY = 1
|
cursorY = 1
|
||||||
end
|
end
|
||||||
cursorX = lineEdit.clamp(lines[cursorY], cursorX)
|
clampCursorX()
|
||||||
return true
|
return true
|
||||||
elseif kc == 208 or kc == 209 then -- Go down one - go down page
|
elseif kc == 208 or kc == 209 then -- Go down one - go down page
|
||||||
local moveAmount = 1
|
local moveAmount = 1
|
||||||
@ -208,7 +251,36 @@ local function key(ks, kc, down)
|
|||||||
if cursorY > #lines then
|
if cursorY > #lines then
|
||||||
cursorY = #lines
|
cursorY = #lines
|
||||||
end
|
end
|
||||||
cursorX = lineEdit.clamp(lines[cursorY], cursorX)
|
clampCursorX()
|
||||||
|
return true
|
||||||
|
elseif kc == 203 then
|
||||||
|
if cursorX > 1 then
|
||||||
|
cursorX = cursorX - 1
|
||||||
|
else
|
||||||
|
if cursorY > 1 then
|
||||||
|
cursorY = cursorY - 1
|
||||||
|
cursorX = unicode.len(lines[cursorY]) + 1
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
elseif kc == 205 then
|
||||||
|
cursorX = cursorX + 1
|
||||||
|
if clampCursorX() then
|
||||||
|
if cursorY < #lines then
|
||||||
|
cursorY = cursorY + 1
|
||||||
|
cursorX = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
-- Extra Non-Control Keys
|
||||||
|
if kc == 199 then
|
||||||
|
cursorX = 1
|
||||||
|
return true
|
||||||
|
elseif kc == 207 then
|
||||||
|
cursorX = unicode.len(lines[cursorY]) + 1
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
-- Major Actions
|
-- Major Actions
|
||||||
@ -219,13 +291,10 @@ local function key(ks, kc, down)
|
|||||||
return true
|
return true
|
||||||
elseif kc == 61 then -- F3
|
elseif kc == 61 then -- F3
|
||||||
startLoad()
|
startLoad()
|
||||||
return false
|
|
||||||
elseif kc == 62 then -- F4
|
elseif kc == 62 then -- F4
|
||||||
startSave()
|
startSave()
|
||||||
return false
|
|
||||||
elseif kc == 63 then -- F5
|
elseif kc == 63 then -- F5
|
||||||
clipsrc.setSetting("clipboard", lines[cursorY])
|
clipsrc.setSetting("clipboard", lines[cursorY])
|
||||||
return false
|
|
||||||
elseif kc == 64 then -- F6
|
elseif kc == 64 then -- F6
|
||||||
local tx = clipsrc.getSetting("clipboard") or ""
|
local tx = clipsrc.getSetting("clipboard") or ""
|
||||||
local txi = tx:find("\n")
|
local txi = tx:find("\n")
|
||||||
@ -242,7 +311,6 @@ local function key(ks, kc, down)
|
|||||||
return true
|
return true
|
||||||
elseif kc == 65 then -- F7
|
elseif kc == 65 then -- F7
|
||||||
appendFlag = false
|
appendFlag = false
|
||||||
return false
|
|
||||||
elseif kc == 66 then -- F8
|
elseif kc == 66 then -- F8
|
||||||
if appendFlag then
|
if appendFlag then
|
||||||
local base = clipsrc.getSetting("clipboard")
|
local base = clipsrc.getSetting("clipboard")
|
||||||
@ -254,37 +322,29 @@ local function key(ks, kc, down)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- LEL Keys
|
-- Letters
|
||||||
local lT, lC, lX = lineEdit.key(ks, kc, lines[cursorY], cursorX)
|
if ka == 8 or kc == 211 then
|
||||||
if lT then
|
if cursorX == 1 then
|
||||||
lines[cursorY] = lT
|
if cursorY == 1 then
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
if lC then
|
|
||||||
cursorX = lC
|
|
||||||
end
|
|
||||||
if lX == "l<" and cursorY > 1 then
|
|
||||||
cursorY = cursorY - 1
|
|
||||||
cursorX = unicode.len(lines[cursorY]) + 1
|
|
||||||
elseif lX == "l>" and cursorY < #lines then
|
|
||||||
cursorY = cursorY + 1
|
|
||||||
cursorX = 1
|
|
||||||
elseif lX == "w<" and cursorY ~= 1 then
|
|
||||||
local l = table.remove(lines, cursorY)
|
local l = table.remove(lines, cursorY)
|
||||||
cursorY = cursorY - 1
|
cursorY = cursorY - 1
|
||||||
cursorX = unicode.len(lines[cursorY]) + 1
|
cursorX = unicode.len(lines[cursorY]) + 1
|
||||||
lines[cursorY] = lines[cursorY] .. l
|
lines[cursorY] = lines[cursorY] .. l
|
||||||
elseif lX == "w>" and cursorY ~= #lines then
|
else
|
||||||
local l = table.remove(lines, cursorY)
|
local a, b = splitCur()
|
||||||
cursorX = unicode.len(l) + 1
|
a = unicode.sub(a, 1, unicode.len(a) - 1)
|
||||||
lines[cursorY] = l .. lines[cursorY]
|
lines[cursorY] = a.. b
|
||||||
elseif lX == "nl" then
|
cursorX = cursorX - 1
|
||||||
local line = lines[cursorY]
|
|
||||||
lines[cursorY] = unicode.sub(line, 1, cursorX - 1)
|
|
||||||
table.insert(lines, cursorY + 1, unicode.sub(line, cursorX))
|
|
||||||
cursorX = 1
|
|
||||||
cursorY = cursorY + 1
|
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
|
end
|
||||||
|
if ka ~= 0 then
|
||||||
|
putLetter(unicode.char(ka))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
flush = function ()
|
flush = function ()
|
||||||
@ -293,9 +353,16 @@ flush = function ()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
neo.scheduleTimer(os.uptime() + 0.5)
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local e = {coroutine.yield()}
|
local e = {coroutine.yield()}
|
||||||
if e[1] == "x.neo.pub.window" then
|
if e[1] == "k.timer" and e[2] == focFlag then
|
||||||
|
cFlash = not cFlash
|
||||||
|
local csY = math.ceil(sH / 2)
|
||||||
|
window.span(1, csY, getline(csY), 0xFFFFFF, 0)
|
||||||
|
focFlag = neo.scheduleTimer(os.uptime() + 0.5)
|
||||||
|
elseif e[1] == "x.neo.pub.window" then
|
||||||
if e[2] == window.id then
|
if e[2] == window.id then
|
||||||
if e[3] == "line" then
|
if e[3] == "line" then
|
||||||
window.span(1, e[4], getline(e[4]), 0xFFFFFF, 0)
|
window.span(1, e[4], getline(e[4]), 0xFFFFFF, 0)
|
||||||
@ -306,13 +373,14 @@ while true do
|
|||||||
local csY = math.ceil(sH / 2)
|
local csY = math.ceil(sH / 2)
|
||||||
local nY = math.max(1, math.min(#lines, (math.floor(e[5]) - csY) + cursorY))
|
local nY = math.max(1, math.min(#lines, (math.floor(e[5]) - csY) + cursorY))
|
||||||
cursorY = nY
|
cursorY = nY
|
||||||
cursorX = lineEdit.clamp(lines[cursorY], cursorX)
|
clampCursorX()
|
||||||
flush()
|
flush()
|
||||||
elseif e[3] == "key" then
|
elseif e[3] == "key" then
|
||||||
if key(e[4] ~= 0 and unicode.char(e[4]), e[5], e[6]) then
|
if key(e[4], e[5], e[6]) then
|
||||||
flush()
|
flush()
|
||||||
end
|
end
|
||||||
elseif e[3] == "focus" then
|
elseif e[3] == "focus" then
|
||||||
|
focFlag = e[4] and neo.scheduleTimer(0)
|
||||||
ctrlFlag = false
|
ctrlFlag = false
|
||||||
elseif e[3] == "close" then
|
elseif e[3] == "close" then
|
||||||
return
|
return
|
||||||
@ -324,7 +392,7 @@ while true do
|
|||||||
if c == "\n" then
|
if c == "\n" then
|
||||||
c = "\r"
|
c = "\r"
|
||||||
end
|
end
|
||||||
key(c, 0, true)
|
putLetter(c)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
flush()
|
flush()
|
||||||
|
@ -1,491 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- svc-t.lua : terminal
|
|
||||||
|
|
||||||
local _, _, retTbl, title = ...
|
|
||||||
|
|
||||||
assert(retTbl, "need to alert creator")
|
|
||||||
|
|
||||||
if title ~= nil then
|
|
||||||
assert(type(title) == "string", "title must be string")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function rW()
|
|
||||||
return string.format("%04x", math.random(0, 65535))
|
|
||||||
end
|
|
||||||
|
|
||||||
local id = "neo.pub.t/" .. rW() .. rW() .. rW() .. rW()
|
|
||||||
local closeNow = false
|
|
||||||
|
|
||||||
-- Terminus Registration State --
|
|
||||||
|
|
||||||
local tReg = neo.requireAccess("r." .. id, "registration")
|
|
||||||
local sendSigs = {}
|
|
||||||
|
|
||||||
-- Display State --
|
|
||||||
-- unicode.safeTextFormat'd lines.
|
|
||||||
-- The size of this must not go below 1.
|
|
||||||
local console = {}
|
|
||||||
-- This must not go below 3.
|
|
||||||
local conW = 40
|
|
||||||
local conCX, conCY = 1, 1
|
|
||||||
local conSCX, conSCY = 1, 1
|
|
||||||
-- Performance
|
|
||||||
local consoleShown = {}
|
|
||||||
local conCYShown
|
|
||||||
for i = 1, 14 do
|
|
||||||
console[i] = (" "):rep(conW)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Line Editing State --
|
|
||||||
-- Nil if line editing is off.
|
|
||||||
-- In this case, the console height
|
|
||||||
-- must be adjusted accordingly.
|
|
||||||
local leText = ""
|
|
||||||
-- These are NOT nil'd out,
|
|
||||||
-- particularly not the history buffer.
|
|
||||||
local leCX = 1
|
|
||||||
local leHistory = {
|
|
||||||
-- Size = history buffer size
|
|
||||||
"", "", "", ""
|
|
||||||
}
|
|
||||||
local function cycleHistoryUp()
|
|
||||||
local backupFirst = leHistory[1]
|
|
||||||
for i = 1, #leHistory - 1 do
|
|
||||||
leHistory[i] = leHistory[i + 1]
|
|
||||||
end
|
|
||||||
leHistory[#leHistory] = backupFirst
|
|
||||||
end
|
|
||||||
local function cycleHistoryDown()
|
|
||||||
local backup = leHistory[1]
|
|
||||||
for i = 2, #leHistory do
|
|
||||||
backup, leHistory[i] = leHistory[i], backup
|
|
||||||
end
|
|
||||||
leHistory[1] = backup
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Window --
|
|
||||||
|
|
||||||
local window = neo.requireAccess("x.neo.pub.window", "window")(conW, #console + 1, title)
|
|
||||||
|
|
||||||
-- Core Terminal Functions --
|
|
||||||
|
|
||||||
local function setSize(w, h)
|
|
||||||
conW = w
|
|
||||||
for i = 1, #console do
|
|
||||||
consoleShown[i] = nil
|
|
||||||
end
|
|
||||||
while #console < h do
|
|
||||||
table.insert(console, "")
|
|
||||||
end
|
|
||||||
while #console > h do
|
|
||||||
table.remove(console, 1)
|
|
||||||
end
|
|
||||||
for i = 1, #console do
|
|
||||||
console[i] = unicode.sub(console[i], 1, w) .. (" "):rep(w - unicode.len(console[i]))
|
|
||||||
end
|
|
||||||
if leText then
|
|
||||||
window.setSize(w, h + 1)
|
|
||||||
else
|
|
||||||
window.setSize(w, h)
|
|
||||||
end
|
|
||||||
conCX, conCY = 1, h
|
|
||||||
end
|
|
||||||
|
|
||||||
local function setLineEditing(state)
|
|
||||||
if state and not leText then
|
|
||||||
leText = ""
|
|
||||||
leCX = 1
|
|
||||||
setSize(conW, #console)
|
|
||||||
elseif leText and not state then
|
|
||||||
leText = nil
|
|
||||||
setSize(conW, #console)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function draw(i)
|
|
||||||
if console[i] then
|
|
||||||
window.span(1, i, console[i], 0, 0xFFFFFF)
|
|
||||||
if i == conCY and not leText then
|
|
||||||
window.span(conCX, i, unicode.sub(console[i], conCX, conCX), 0xFFFFFF, 0)
|
|
||||||
end
|
|
||||||
elseif leText then
|
|
||||||
window.span(1, i, require("lineedit").draw(conW, unicode.safeTextFormat(leText, leCX)), 0xFFFFFF, 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local function drawDisplay()
|
|
||||||
for i = 1, #console do
|
|
||||||
if consoleShown[i] ~= console[i] or i == conCY or i == conCYShown then
|
|
||||||
draw(i)
|
|
||||||
consoleShown[i] = console[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
conCYShown = conCY
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Terminal Visual --
|
|
||||||
|
|
||||||
local function consoleSD()
|
|
||||||
for i = 1, #console - 1 do
|
|
||||||
console[i] = console[i + 1]
|
|
||||||
end
|
|
||||||
console[#console] = (" "):rep(conW)
|
|
||||||
end
|
|
||||||
local function consoleSU()
|
|
||||||
local backup = (" "):rep(conW)
|
|
||||||
for i = 1, #console do
|
|
||||||
backup, console[i] = console[i], backup
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function consoleCLS()
|
|
||||||
for i = 1, #console do
|
|
||||||
console[i] = (" "):rep(conW)
|
|
||||||
end
|
|
||||||
conCX, conCY = 1, 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local function writeFF()
|
|
||||||
if conCY ~= #console then
|
|
||||||
conCY = conCY + 1
|
|
||||||
else
|
|
||||||
consoleSD()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function writeData(data)
|
|
||||||
-- handle data until completion
|
|
||||||
while #data > 0 do
|
|
||||||
local char = unicode.sub(data, 1, 1)
|
|
||||||
--neo.emergency("svc-t.data: " .. char:byte())
|
|
||||||
data = unicode.sub(data, 2)
|
|
||||||
-- handle character
|
|
||||||
if char == "\t" then
|
|
||||||
-- not ideal, but allowed
|
|
||||||
char = " "
|
|
||||||
end
|
|
||||||
if char == "\r" then
|
|
||||||
conCX = 1
|
|
||||||
elseif char == "\x00" then
|
|
||||||
-- caused by TELNET \r rules
|
|
||||||
elseif char == "\n" then
|
|
||||||
conCX = 1
|
|
||||||
writeFF()
|
|
||||||
elseif char == "\a" then
|
|
||||||
-- Bell (er...)
|
|
||||||
elseif char == "\b" then
|
|
||||||
conCX = math.max(1, conCX - 1)
|
|
||||||
elseif char == "\v" or char == "\f" then
|
|
||||||
writeFF()
|
|
||||||
else
|
|
||||||
local charL = unicode.wlen(char)
|
|
||||||
if (conCX + charL - 1) > conW then
|
|
||||||
conCX = 1
|
|
||||||
writeFF()
|
|
||||||
end
|
|
||||||
local spaces = (" "):rep(charL - 1)
|
|
||||||
console[conCY] = unicode.sub(console[conCY], 1, conCX - 1) .. char .. spaces .. unicode.sub(console[conCY], conCX + charL)
|
|
||||||
conCX = conCX + charL
|
|
||||||
-- Cursor can be (intentionally!) off-screen here
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function writeANSI(s)
|
|
||||||
--neo.emergency("svc-t.ansi: " .. s)
|
|
||||||
-- This supports just about enough to get by.
|
|
||||||
if s == "c" then
|
|
||||||
consoleCLS()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local pfx = s:sub(1, 1)
|
|
||||||
local cmd = s:sub(#s)
|
|
||||||
if pfx == "[" then
|
|
||||||
local np = tonumber(s:sub(2, -2)) or 1
|
|
||||||
if cmd == "A" then
|
|
||||||
conCY = conCY - np
|
|
||||||
elseif cmd == "B" then
|
|
||||||
conCY = conCY + np
|
|
||||||
elseif cmd == "C" then
|
|
||||||
conCX = conCX + np
|
|
||||||
elseif cmd == "D" then
|
|
||||||
conCX = conCX - np
|
|
||||||
elseif cmd == "f" or cmd == "H" then
|
|
||||||
local p = s:find(";")
|
|
||||||
if not p then
|
|
||||||
conCY = np
|
|
||||||
conCX = 1
|
|
||||||
else
|
|
||||||
conCY = tonumber(s:sub(2, p - 1)) or 1
|
|
||||||
conCX = tonumber(s:sub(p + 1, -2)) or 1
|
|
||||||
end
|
|
||||||
elseif cmd == "J" then
|
|
||||||
consoleCLS()
|
|
||||||
elseif cmd == "K" then
|
|
||||||
if s == "[K" or s == "[0K" then
|
|
||||||
-- bash needs this
|
|
||||||
console[conCY] = unicode.sub(console[conCY], 1, conCX - 1) .. (" "):rep(1 + conW - conCX)
|
|
||||||
else
|
|
||||||
console[conCY] = (" "):rep(conW)
|
|
||||||
end
|
|
||||||
elseif cmd == "n" then
|
|
||||||
if s == "[6n" then
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
v("data", "\x1b[" .. conY .. ";" .. conX .. "R")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif cmd == "s" then
|
|
||||||
conSCX, conSCY = conCX, conCY
|
|
||||||
elseif cmd == "u" then
|
|
||||||
conCX, conCY = conSCX, conSCY
|
|
||||||
end
|
|
||||||
end
|
|
||||||
conCX = math.min(math.max(math.floor(conCX), 1), conW)
|
|
||||||
conCY = math.min(math.max(math.floor(conCY), 1), #console)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- The Terminus --
|
|
||||||
|
|
||||||
local tvBuildingCmd = ""
|
|
||||||
local tvBuildingUTF = ""
|
|
||||||
local tvSubnegotiation = false
|
|
||||||
local function incoming(s)
|
|
||||||
tvBuildingCmd = tvBuildingCmd .. s
|
|
||||||
-- Flush Cmd
|
|
||||||
while #tvBuildingCmd > 0 do
|
|
||||||
if tvBuildingCmd:byte() == 255 then
|
|
||||||
-- It's a command. Uhoh.
|
|
||||||
if #tvBuildingCmd < 2 then break end
|
|
||||||
local cmd = tvBuildingCmd:byte(2)
|
|
||||||
local param = tvBuildingCmd:byte(3)
|
|
||||||
local cmdLen = 2
|
|
||||||
-- Command Lengths
|
|
||||||
if cmd >= 251 and cmd <= 254 then cmdLen = 3 end
|
|
||||||
if #tvBuildingCmd < cmdLen then break end
|
|
||||||
if cmd == 240 then
|
|
||||||
-- SE
|
|
||||||
tvSubnegotiation = false
|
|
||||||
elseif cmd == 250 then
|
|
||||||
-- SB
|
|
||||||
tvSubnegotiation = true
|
|
||||||
elseif cmd == 251 and param == 1 then
|
|
||||||
-- WILL ECHO (respond with DO ECHO, disable line editing)
|
|
||||||
-- test using io.write("\xFF\xFB\x01")
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
v("telnet", "\xFF\xFD\x01")
|
|
||||||
end
|
|
||||||
setLineEditing(false)
|
|
||||||
elseif cmd == 252 and param == 1 then
|
|
||||||
-- WON'T ECHO (respond with DON'T ECHO, enable line editing)
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
v("telnet", "\xFF\xFE\x01")
|
|
||||||
end
|
|
||||||
setLineEditing(true)
|
|
||||||
elseif cmd == 251 or cmd == 252 then
|
|
||||||
-- WILL/WON'T (x) (respond with DON'T (X))
|
|
||||||
local res = "\xFF\xFE" .. string.char(param)
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
v("telnet", res)
|
|
||||||
end
|
|
||||||
elseif cmd == 253 or cmd == 254 then
|
|
||||||
-- DO/DON'T (x) (respond with WON'T (X))
|
|
||||||
local res = "\xFF\xFC" .. string.char(param)
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
v("telnet", res)
|
|
||||||
end
|
|
||||||
elseif cmd == 255 then
|
|
||||||
if not tvSubnegotiation then
|
|
||||||
tvBuildingUTF = tvBuildingUTF .. "\xFF"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tvBuildingCmd = tvBuildingCmd:sub(cmdLen + 1)
|
|
||||||
else
|
|
||||||
if not tvSubnegotiation then
|
|
||||||
tvBuildingUTF = tvBuildingUTF .. tvBuildingCmd:sub(1, 1)
|
|
||||||
end
|
|
||||||
tvBuildingCmd = tvBuildingCmd:sub(2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Flush UTF/Display
|
|
||||||
while #tvBuildingUTF > 0 do
|
|
||||||
local head = tvBuildingUTF:byte()
|
|
||||||
local len = 1
|
|
||||||
local handled = false
|
|
||||||
if head == 27 then
|
|
||||||
local h2 = tvBuildingUTF:byte(2)
|
|
||||||
if h2 == 91 then
|
|
||||||
for i = 3, #tvBuildingUTF do
|
|
||||||
local cmd = tvBuildingUTF:byte(i)
|
|
||||||
if cmd >= 0x40 and cmd <= 0x7E then
|
|
||||||
writeANSI(tvBuildingUTF:sub(2, i))
|
|
||||||
len = i
|
|
||||||
handled = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif h2 then
|
|
||||||
len = 2
|
|
||||||
writeANSI(tvBuildingUTF:sub(2, 2))
|
|
||||||
handled = true
|
|
||||||
end
|
|
||||||
if not handled then break end
|
|
||||||
end
|
|
||||||
if not handled then
|
|
||||||
if head < 192 then
|
|
||||||
len = 1
|
|
||||||
elseif head < 224 then
|
|
||||||
len = 2
|
|
||||||
elseif head < 240 then
|
|
||||||
len = 3
|
|
||||||
elseif head < 248 then
|
|
||||||
len = 4
|
|
||||||
elseif head < 252 then
|
|
||||||
len = 5
|
|
||||||
elseif head < 254 then
|
|
||||||
len = 6
|
|
||||||
end
|
|
||||||
if #tvBuildingUTF < len then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
-- verified one full character...
|
|
||||||
writeData(tvBuildingUTF:sub(1, len))
|
|
||||||
end
|
|
||||||
tvBuildingUTF = tvBuildingUTF:sub(len + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
tReg(function (_, pid, sendSig)
|
|
||||||
sendSigs[pid] = sendSig
|
|
||||||
return {
|
|
||||||
id = "x." .. id,
|
|
||||||
pid = neo.pid,
|
|
||||||
write = function (text)
|
|
||||||
incoming(tostring(text))
|
|
||||||
drawDisplay()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end, true)
|
|
||||||
|
|
||||||
if retTbl then
|
|
||||||
coroutine.resume(coroutine.create(retTbl), {
|
|
||||||
access = "x." .. id,
|
|
||||||
close = function ()
|
|
||||||
closeNow = true
|
|
||||||
neo.scheduleTimer(0)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local control = false
|
|
||||||
|
|
||||||
local function key(a, c)
|
|
||||||
if control then
|
|
||||||
if c == 203 and conW > 8 then
|
|
||||||
setSize(conW - 1, #console)
|
|
||||||
return
|
|
||||||
elseif c == 200 and #console > 1 then
|
|
||||||
setSize(conW, #console - 1)
|
|
||||||
return
|
|
||||||
elseif c == 205 then
|
|
||||||
setSize(conW + 1, #console)
|
|
||||||
return
|
|
||||||
elseif c == 208 then
|
|
||||||
setSize(conW, #console + 1)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- so with the reserved ones dealt with...
|
|
||||||
if not leText then
|
|
||||||
-- Line Editing not active.
|
|
||||||
-- For now support a bare minimum.
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
if a == "\x03" then
|
|
||||||
v("telnet", "\xFF\xF4")
|
|
||||||
elseif c == 199 then
|
|
||||||
v("data", "\x1b[H")
|
|
||||||
elseif c == 201 then
|
|
||||||
v("data", "\x1b[5~")
|
|
||||||
elseif c == 207 then
|
|
||||||
v("data", "\x1b[F")
|
|
||||||
elseif c == 209 then
|
|
||||||
v("data", "\x1b[6~")
|
|
||||||
elseif c == 203 then
|
|
||||||
v("data", "\x1b[D")
|
|
||||||
elseif c == 205 then
|
|
||||||
v("data", "\x1b[C")
|
|
||||||
elseif c == 200 then
|
|
||||||
v("data", "\x1b[A")
|
|
||||||
elseif c == 208 then
|
|
||||||
v("data", "\x1b[B")
|
|
||||||
elseif a == "\r" then
|
|
||||||
v("data", "\r\n")
|
|
||||||
elseif a then
|
|
||||||
v("data", a)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif not control then
|
|
||||||
-- Line Editing active and control isn't involved
|
|
||||||
if c == 200 or c == 208 then
|
|
||||||
-- History cursor up (history down)
|
|
||||||
leText = leHistory[#leHistory]
|
|
||||||
leCX = unicode.len(leText) + 1
|
|
||||||
if c == 208 then
|
|
||||||
cycleHistoryUp()
|
|
||||||
else
|
|
||||||
cycleHistoryDown()
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local lT, lC, lX = require("lineedit").key(a, c, leText, leCX)
|
|
||||||
leText = lT or leText
|
|
||||||
leCX = lC or leCX
|
|
||||||
if lX == "nl" then
|
|
||||||
cycleHistoryUp()
|
|
||||||
leHistory[#leHistory] = leText
|
|
||||||
-- the whole thing {
|
|
||||||
local fullText = leText .. "\r\n"
|
|
||||||
writeData(fullText)
|
|
||||||
drawDisplay()
|
|
||||||
for _, v in pairs(sendSigs) do
|
|
||||||
v("data", fullText)
|
|
||||||
end
|
|
||||||
-- }
|
|
||||||
leText = ""
|
|
||||||
leCX = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
while not closeNow do
|
|
||||||
local e = {coroutine.yield()}
|
|
||||||
if e[1] == "k.procdie" then
|
|
||||||
sendSigs[e[3]] = nil
|
|
||||||
elseif e[1] == "x.neo.pub.window" then
|
|
||||||
if e[3] == "close" then
|
|
||||||
break
|
|
||||||
elseif e[3] == "clipboard" then
|
|
||||||
for i = 1, unicode.len(e[4]) do
|
|
||||||
local c = unicode.sub(e[4], i, i)
|
|
||||||
if c ~= "\r" then
|
|
||||||
if c == "\n" then
|
|
||||||
c = "\r"
|
|
||||||
end
|
|
||||||
key(c, 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
draw(#console + 1)
|
|
||||||
elseif e[3] == "key" then
|
|
||||||
if e[5] == 29 or e[5] == 157 then
|
|
||||||
control = e[6]
|
|
||||||
elseif e[6] then
|
|
||||||
key(e[4] ~= 0 and unicode.char(e[4]), e[5])
|
|
||||||
draw(#console + 1)
|
|
||||||
end
|
|
||||||
elseif e[3] == "line" then
|
|
||||||
draw(e[4])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -600,55 +600,65 @@ end
|
|||||||
local isAltDown = false
|
local isAltDown = false
|
||||||
local isCtrDown = false
|
local isCtrDown = false
|
||||||
local function key(ku, ka, kc, down)
|
local function key(ku, ka, kc, down)
|
||||||
local ku, lin = screens.getMonitorByKeyboard(ku)
|
local ku = screens.getMonitorByKeyboard(ku)
|
||||||
|
if not ku then return end
|
||||||
for k, v in ipairs(monitors) do
|
for k, v in ipairs(monitors) do
|
||||||
if ku and v[2] == ku then
|
if v[2] == mu then
|
||||||
lin = k
|
lIM = k
|
||||||
break
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not lin then return end
|
|
||||||
lIM = lin
|
|
||||||
|
|
||||||
local focus = surfaces[1]
|
local focus = surfaces[1]
|
||||||
if kc == 29 then
|
if kc == 29 then isCtrDown = down end
|
||||||
isCtrDown = down
|
if kc == 56 then isAltDown = down end
|
||||||
elseif kc == 56 then
|
if isAltDown then
|
||||||
isAltDown = down
|
if ka == 120 then
|
||||||
|
if focus and down then ofsMSurface(focus, 1) end return
|
||||||
end
|
end
|
||||||
if isAltDown and ka == 122 then
|
if kc == 200 then
|
||||||
|
if focus and down then ofsSurface(focus, 0, -1) end return
|
||||||
|
end
|
||||||
|
if kc == 208 then
|
||||||
|
if focus and down then ofsSurface(focus, 0, 1) end return
|
||||||
|
end
|
||||||
|
if kc == 203 then
|
||||||
|
if focus and down then ofsSurface(focus, -1, 0) end return
|
||||||
|
end
|
||||||
|
if kc == 205 then
|
||||||
|
if focus and down then ofsSurface(focus, 1, 0) end return
|
||||||
|
end
|
||||||
|
if ka == 122 then
|
||||||
if focus and down then
|
if focus and down then
|
||||||
local n = table.remove(surfaces, 1)
|
local n = table.remove(surfaces, 1)
|
||||||
table.insert(surfaces, n)
|
table.insert(surfaces, n)
|
||||||
changeFocus(n)
|
changeFocus(n)
|
||||||
|
end return
|
||||||
end
|
end
|
||||||
elseif isAltDown and kc == 200 then
|
if ka == 97 then
|
||||||
if focus and down then ofsSurface(focus, 0, -1) end
|
|
||||||
elseif isAltDown and kc == 208 then
|
|
||||||
if focus and down then ofsSurface(focus, 0, 1) end
|
|
||||||
elseif isAltDown and kc == 203 then
|
|
||||||
if focus and down then ofsSurface(focus, -1, 0) end
|
|
||||||
elseif isAltDown and kc == 205 then
|
|
||||||
if focus and down then ofsSurface(focus, 1, 0) end
|
|
||||||
elseif isAltDown and ka == 120 then
|
|
||||||
if focus and down then ofsMSurface(focus, 1) end
|
|
||||||
elseif isAltDown and ka == 97 then
|
|
||||||
if not down then
|
if not down then
|
||||||
isAltDown = false
|
isAltDown = false
|
||||||
end
|
end
|
||||||
elseif isAltDown and (ka == 3 or ka == 99) then
|
return
|
||||||
|
end
|
||||||
|
if ka == 3 or ka == 99 then
|
||||||
if down then
|
if down then
|
||||||
if isCtrDown then
|
if isCtrDown then
|
||||||
error("User-authorized Everest crash.")
|
error("User-authorized Everest crash.")
|
||||||
elseif focus then
|
else
|
||||||
|
if focus then
|
||||||
focus[6](focus[8], "close")
|
focus[6](focus[8], "close")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif isAltDown and ka == 13 then
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if ka == 13 then
|
||||||
if down then
|
if down then
|
||||||
startLauncher()
|
startLauncher()
|
||||||
end
|
end
|
||||||
elseif focus then
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if focus then
|
||||||
if kc ~= 56 then
|
if kc ~= 56 then
|
||||||
lIM = focus[1]
|
lIM = focus[1]
|
||||||
end
|
end
|
||||||
|
@ -81,12 +81,20 @@ local function getPfx(xd, pkg)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function splitAC(ac)
|
local endAcPattern = "/[a-z0-9/%.]*$"
|
||||||
local sb = ac:match("/[a-z0-9/%.]*$")
|
|
||||||
if sb then
|
local function matchesSvc(xd, pkg, perm)
|
||||||
return ac:sub(1, #ac - #sb), sb
|
local pfx = getPfx(xd, pkg)
|
||||||
|
if pfx then
|
||||||
|
local permAct = perm
|
||||||
|
local paP = permAct:match(endAcPattern)
|
||||||
|
if paP then
|
||||||
|
permAct = permAct:sub(1, #permAct - #paP)
|
||||||
|
end
|
||||||
|
if permAct == pfx then
|
||||||
|
return "allow"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return ac
|
|
||||||
end
|
end
|
||||||
|
|
||||||
donkonitDFProvider(function (pkg, pid, sendSig)
|
donkonitDFProvider(function (pkg, pid, sendSig)
|
||||||
@ -122,8 +130,7 @@ donkonitDFProvider(function (pkg, pid, sendSig)
|
|||||||
myApi = getPfx("", pkg),
|
myApi = getPfx("", pkg),
|
||||||
lockPerm = function (perm)
|
lockPerm = function (perm)
|
||||||
-- Are we allowed to?
|
-- Are we allowed to?
|
||||||
local permPfx, detail = splitAC(perm)
|
if not matchesSvc("x.", pkg, perm) then
|
||||||
if getPfx("x.", pkg) ~= permPfx then
|
|
||||||
return false, "You don't own this permission."
|
return false, "You don't own this permission."
|
||||||
end
|
end
|
||||||
local set = "perm|*|" .. perm
|
local set = "perm|*|" .. perm
|
||||||
@ -216,11 +223,7 @@ local function secPolicyStage2(pid, proc, perm, req)
|
|||||||
-- Push to ICECAP thread to avoid deadlock b/c wrong event-pull context
|
-- Push to ICECAP thread to avoid deadlock b/c wrong event-pull context
|
||||||
neo.scheduleTimer(0)
|
neo.scheduleTimer(0)
|
||||||
table.insert(todo, function ()
|
table.insert(todo, function ()
|
||||||
local fPerm = perm
|
local ok, err = pcall(secpol, nexus, settings, proc.pkg, pid, perm, req, matchesSvc)
|
||||||
if fPerm:sub(1, 2) == "r." then
|
|
||||||
fPerm = splitAC(fPerm)
|
|
||||||
end
|
|
||||||
local ok, err = pcall(secpol, nexus, settings, proc.pkg, pid, fPerm, req, getPfx("", proc.pkg))
|
|
||||||
if not ok then
|
if not ok then
|
||||||
neo.emergency("Used fallback policy because of run-err: " .. err)
|
neo.emergency("Used fallback policy because of run-err: " .. err)
|
||||||
req(def)
|
req(def)
|
||||||
@ -240,7 +243,11 @@ rootAccess.securityPolicy = function (pid, proc, perm, req)
|
|||||||
end
|
end
|
||||||
-- Do we need to start it?
|
-- Do we need to start it?
|
||||||
if perm:sub(1, 6) == "x.svc." and not neo.usAccessExists(perm) then
|
if perm:sub(1, 6) == "x.svc." and not neo.usAccessExists(perm) then
|
||||||
local appAct = splitAC(perm:sub(3))
|
local appAct = perm:sub(7)
|
||||||
|
local paP = appAct:match(endAcPattern)
|
||||||
|
if paP then
|
||||||
|
appAct = appAct:sub(1, #appAct - #paP)
|
||||||
|
end
|
||||||
-- Prepare for success
|
-- Prepare for success
|
||||||
onReg[perm] = onReg[perm] or {}
|
onReg[perm] = onReg[perm] or {}
|
||||||
local orp = onReg[perm]
|
local orp = onReg[perm]
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@ -459,7 +459,7 @@ function retrieveAccess(perm, pkg, pid)
|
|||||||
accesses[uid] = function (pkg, pid)
|
accesses[uid] = function (pkg, pid)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
return function (f, secret)
|
return function (f)
|
||||||
-- Registration function
|
-- Registration function
|
||||||
ensureType(f, "function")
|
ensureType(f, "function")
|
||||||
local accessObjectCache = {}
|
local accessObjectCache = {}
|
||||||
@ -481,10 +481,8 @@ function retrieveAccess(perm, pkg, pid)
|
|||||||
end
|
end
|
||||||
-- returns nil and fails
|
-- returns nil and fails
|
||||||
end
|
end
|
||||||
if not secret then
|
|
||||||
-- Announce registration
|
-- Announce registration
|
||||||
distEvent(nil, "k.registration", uid)
|
distEvent(nil, "k.registration", uid)
|
||||||
end
|
|
||||||
end, function ()
|
end, function ()
|
||||||
-- Registration becomes null (access is held but other processes cannot retrieve object)
|
-- Registration becomes null (access is held but other processes cannot retrieve object)
|
||||||
if accesses[uid] then
|
if accesses[uid] then
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
return {
|
|
||||||
-- note: everything must already be unicode.safeTextFormat'd
|
|
||||||
draw = function (sW, line, cursorX, rX)
|
|
||||||
-- if no camera, provide a default
|
|
||||||
rX = rX or math.max(1, (cursorX or 1) - math.floor(sW * 2 / 3))
|
|
||||||
-- transform into area-relative
|
|
||||||
local tl = unicode.sub(line, rX, rX + sW - 1)
|
|
||||||
-- inject cursor
|
|
||||||
if cursorX then
|
|
||||||
cursorX = (cursorX - rX) + 1
|
|
||||||
if cursorX >= 1 then
|
|
||||||
if cursorX <= sW then
|
|
||||||
tl = unicode.sub(tl, 1, cursorX - 1) .. "_" .. unicode.sub(tl, cursorX + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return tl .. (" "):rep(sW - unicode.len(tl))
|
|
||||||
end,
|
|
||||||
clamp = function (tl, cursorX)
|
|
||||||
tl = unicode.len(tl)
|
|
||||||
if tl < cursorX - 1 then
|
|
||||||
return tl + 1
|
|
||||||
end
|
|
||||||
return cursorX
|
|
||||||
end,
|
|
||||||
-- returns line, cursorX, special
|
|
||||||
-- return values may be nil if irrelevant
|
|
||||||
key = function (ks, kc, line, cursorX)
|
|
||||||
local cS = unicode.sub(line, 1, cursorX - 1)
|
|
||||||
local cE = unicode.sub(line, cursorX)
|
|
||||||
local ll = unicode.len(line)
|
|
||||||
if kc == 203 then -- navi <
|
|
||||||
if cursorX > 1 then
|
|
||||||
return nil, cursorX - 1
|
|
||||||
else
|
|
||||||
-- cline underflow
|
|
||||||
return nil, nil, "l<"
|
|
||||||
end
|
|
||||||
elseif kc == 205 then -- navi >
|
|
||||||
if cursorX > ll then
|
|
||||||
-- cline overflow
|
|
||||||
return nil, nil, "l>"
|
|
||||||
end
|
|
||||||
return nil, cursorX + 1
|
|
||||||
elseif kc == 199 then -- home
|
|
||||||
return nil, 1
|
|
||||||
elseif kc == 207 then -- end
|
|
||||||
return nil, unicode.len(line) + 1
|
|
||||||
elseif ks == "\8" then -- del
|
|
||||||
if cursorX == 1 then
|
|
||||||
-- weld prev
|
|
||||||
return nil, nil, "w<"
|
|
||||||
else
|
|
||||||
return unicode.sub(cS, 1, unicode.len(cS) - 1) .. cE, cursorX - 1
|
|
||||||
end
|
|
||||||
elseif kc == 211 then -- del
|
|
||||||
if cursorX > ll then
|
|
||||||
return nil, nil, "w>"
|
|
||||||
end
|
|
||||||
return cS .. unicode.sub(cE, 2)
|
|
||||||
elseif ks then -- standard letters
|
|
||||||
if ks == "\r" then
|
|
||||||
-- new line
|
|
||||||
return nil, nil, "nl"
|
|
||||||
end
|
|
||||||
return cS .. ks .. cE, cursorX + unicode.len(ks)
|
|
||||||
end
|
|
||||||
-- :(
|
|
||||||
end
|
|
||||||
}
|
|
@ -339,7 +339,6 @@ newNeoux = function (event, neo)
|
|||||||
end
|
end
|
||||||
-- Note: w should be at least 2 - this is similar to buttons.
|
-- Note: w should be at least 2 - this is similar to buttons.
|
||||||
neoux.tcfield = function (x, y, w, textprop)
|
neoux.tcfield = function (x, y, w, textprop)
|
||||||
local p = 1
|
|
||||||
return {
|
return {
|
||||||
x = x,
|
x = x,
|
||||||
y = y,
|
y = y,
|
||||||
@ -348,24 +347,22 @@ newNeoux = function (event, neo)
|
|||||||
selectable = true,
|
selectable = true,
|
||||||
key = function (window, update, a, c, d, f)
|
key = function (window, update, a, c, d, f)
|
||||||
if d then
|
if d then
|
||||||
local ot = textprop()
|
|
||||||
local le = require("lineedit")
|
|
||||||
p = le.clamp(ot, p)
|
|
||||||
if c == 63 then
|
if c == 63 then
|
||||||
neo.requireAccess("x.neo.pub.globals", "clipboard").setSetting("clipboard", ot)
|
neo.requireAccess("x.neo.pub.globals", "clipboard").setSetting("clipboard", textprop())
|
||||||
elseif c == 64 then
|
elseif c == 64 then
|
||||||
local contents = neo.requireAccess("x.neo.pub.globals", "clipboard").getSetting("clipboard")
|
local contents = neo.requireAccess("x.neo.pub.globals", "clipboard").getSetting("clipboard")
|
||||||
contents = contents:match("^[^\r\n]*")
|
contents = contents:match("^[^\r\n]*")
|
||||||
textprop(contents)
|
textprop(contents)
|
||||||
update()
|
update()
|
||||||
elseif a ~= 9 then
|
elseif a == 8 then
|
||||||
local lT, lC, lX = le.key(a ~= 0 and unicode.char(a), c, ot, p)
|
local str = textprop()
|
||||||
if lT or lC then
|
textprop(unicode.sub(str, 1, unicode.len(str) - 1))
|
||||||
if lT then textprop(lT) end
|
update()
|
||||||
p = lC or p
|
return true
|
||||||
|
elseif a >= 32 then
|
||||||
|
textprop(textprop() .. unicode.char(a))
|
||||||
update()
|
update()
|
||||||
return true
|
return true
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
@ -380,10 +377,9 @@ newNeoux = function (event, neo)
|
|||||||
fg = bg
|
fg = bg
|
||||||
bg = fg1
|
bg = fg1
|
||||||
end
|
end
|
||||||
local t, e, r = textprop(), require("lineedit")
|
local text = unicode.safeTextFormat(textprop())
|
||||||
p = e.clamp(t, p)
|
text = "[" .. neoux.pad(text, w - 2, false, true, true) .. "]"
|
||||||
t, r = unicode.safeTextFormat(t, p)
|
window.span(x, y, text, bg, fg)
|
||||||
window.span(x, y, "[" .. e.draw(w - 2, t, selected and r) .. "]", bg, fg)
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -94,26 +94,12 @@ function getFsNode(fs, parent, fsc, path, mode, impliedName)
|
|||||||
for k, v in ipairs(fsc.list(path)) do
|
for k, v in ipairs(fsc.list(path)) do
|
||||||
local nm = "F: " .. v
|
local nm = "F: " .. v
|
||||||
local fp = path .. v
|
local fp = path .. v
|
||||||
local cDir = fsc.isDirectory(fp)
|
if fsc.isDirectory(fp) then
|
||||||
if cDir then
|
|
||||||
nm = "D: " .. v
|
nm = "D: " .. v
|
||||||
end
|
end
|
||||||
if (not cDir) and (fscrw or mode == false) and (mode ~= nil) then
|
|
||||||
local vn = v
|
|
||||||
n[k + 1] = {nm, function () return selectUnknown(vn) end}
|
|
||||||
else
|
|
||||||
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode, impliedName) end}
|
n[k + 1] = {nm, function () return nil, getFsNode(fs, t, fsc, fp, mode, impliedName) end}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
|
||||||
table.insert(n, {"Copy", function ()
|
|
||||||
local rt, re = require("sys-filewrap").create(fsc, path, false)
|
|
||||||
if not rt then
|
|
||||||
return false, dialog("Open Error: " .. tostring(re), parent)
|
|
||||||
end
|
|
||||||
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
|
|
||||||
end})
|
|
||||||
end
|
|
||||||
if fscrw then
|
if fscrw then
|
||||||
if dir then
|
if dir then
|
||||||
table.insert(n, {"Mk. Directory", function ()
|
table.insert(n, {"Mk. Directory", function ()
|
||||||
@ -165,6 +151,24 @@ function getFsNode(fs, parent, fsc, path, mode, impliedName)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not dir then
|
if not dir then
|
||||||
|
table.insert(n, {"Copy", function ()
|
||||||
|
local rt, re = require("sys-filewrap").create(fsc, path, false)
|
||||||
|
if not rt then
|
||||||
|
return false, dialog("Open Error: " .. tostring(re), parent)
|
||||||
|
end
|
||||||
|
return nil, setupCopyVirtualEnvironment(fs, parent, rt, path:match("[^/]*$") or "")
|
||||||
|
end})
|
||||||
|
if (fscrw or mode == false) and (mode ~= nil) then
|
||||||
|
local tx = "Open"
|
||||||
|
if mode == true then
|
||||||
|
tx = "Save (Overwrite)"
|
||||||
|
elseif mode == "append" then
|
||||||
|
tx = "Append"
|
||||||
|
end
|
||||||
|
if fscrw or mode == false then
|
||||||
|
table.insert(n, {tx, selectUnknown})
|
||||||
|
end
|
||||||
|
end
|
||||||
elseif impliedName then
|
elseif impliedName then
|
||||||
table.insert(n, {"Implied: " .. impliedName, function ()
|
table.insert(n, {"Implied: " .. impliedName, function ()
|
||||||
return selectUnknown(impliedName)
|
return selectUnknown(impliedName)
|
||||||
|
@ -11,19 +11,13 @@
|
|||||||
-- IRC is usually pretty safe, but no guarantees.
|
-- IRC is usually pretty safe, but no guarantees.
|
||||||
|
|
||||||
-- Returns "allow", "deny", or "ask".
|
-- Returns "allow", "deny", or "ask".
|
||||||
local function actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
local function actualPolicy(pkg, pid, perm, matchesSvc)
|
||||||
-- System stuff is allowed.
|
-- System stuff is allowed.
|
||||||
if pkg:sub(1, 4) == "sys-" then
|
if pkg:sub(1, 4) == "sys-" then
|
||||||
return "allow"
|
return "allow"
|
||||||
end
|
end
|
||||||
-- svc-t's job is solely to emulate terminals
|
|
||||||
-- TO INSTALL YOUR OWN TERMINAL EMULATOR:
|
|
||||||
-- perm|app-yourterm|r.neo.t
|
|
||||||
if pkg == "svc-t" and perm == "r.neo.pub.t" then
|
|
||||||
return "allow"
|
|
||||||
end
|
|
||||||
-- <The following is for apps & services>
|
-- <The following is for apps & services>
|
||||||
-- x.neo.pub.* is open to all
|
-- x.neo.pub (aka Icecap) is open to all
|
||||||
if perm:sub(1, 10) == "x.neo.pub." then
|
if perm:sub(1, 10) == "x.neo.pub." then
|
||||||
return "allow"
|
return "allow"
|
||||||
end
|
end
|
||||||
@ -31,8 +25,7 @@ local function actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
|||||||
if perm == "s.h.component_added" or perm == "s.h.component_removed" or perm == "s.h.tablet_use" or perm == "c.tablet" then
|
if perm == "s.h.component_added" or perm == "s.h.component_removed" or perm == "s.h.tablet_use" or perm == "c.tablet" then
|
||||||
return "allow"
|
return "allow"
|
||||||
end
|
end
|
||||||
-- Userlevel can register for itself
|
if matchesSvc("r.", pkg, perm) then
|
||||||
if perm == "r." .. pkgSvcPfx then
|
|
||||||
return "allow"
|
return "allow"
|
||||||
end
|
end
|
||||||
-- Userlevel has no other registration rights
|
-- Userlevel has no other registration rights
|
||||||
@ -51,8 +44,8 @@ local function actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
|||||||
return "ask"
|
return "ask"
|
||||||
end
|
end
|
||||||
|
|
||||||
return function (nexus, settings, pkg, pid, perm, rsp, pkgSvcPfx)
|
return function (nexus, settings, pkg, pid, perm, rsp, matchesSvc)
|
||||||
local res = actualPolicy(pkg, pid, perm, pkgSvcPfx)
|
local res = actualPolicy(pkg, pid, perm, matchesSvc)
|
||||||
if settings then
|
if settings then
|
||||||
res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or
|
res = settings.getSetting("perm|" .. pkg .. "|" .. perm) or
|
||||||
settings.getSetting("perm|*|" .. perm) or res
|
settings.getSetting("perm|*|" .. perm) or res
|
||||||
|
49
com2/bdivide.lua
Normal file
49
com2/bdivide.lua
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
-- BDIVIDE r5 edition
|
||||||
|
-- Algorithm simplified for smaller implementation and potentially better compression
|
||||||
|
-- format:
|
||||||
|
-- 0-127 for constants
|
||||||
|
-- <128 + (length - 4)>, <position high>, <position low>
|
||||||
|
-- Position is where in the window it was found, minus 1.
|
||||||
|
-- windowSize must be the same between the encoder and decoder,
|
||||||
|
-- and is the amount of data preserved after cropping.
|
||||||
|
|
||||||
|
io.write("\x00") -- initiation character
|
||||||
|
|
||||||
|
local blk = io.read("*a")
|
||||||
|
local windowSize = 0x10000
|
||||||
|
local windowData = ("\x00"):rep(windowSize)
|
||||||
|
|
||||||
|
local function crop(data)
|
||||||
|
windowData = (windowData .. data):sub(-windowSize)
|
||||||
|
end
|
||||||
|
|
||||||
|
while blk ~= "" do
|
||||||
|
local bestData = blk:sub(1, 1)
|
||||||
|
local bestRes = bestData
|
||||||
|
for lm = 0, 127 do
|
||||||
|
local al = lm + 4
|
||||||
|
local pfx = blk:sub(1, al)
|
||||||
|
if #pfx ~= al then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local p = windowData:find(pfx, 1, true)
|
||||||
|
if not p then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
local pm = p - 1
|
||||||
|
local thirdByte = pm % 256
|
||||||
|
-- anti ']'-corruption helper
|
||||||
|
if thirdByte ~= 93 then
|
||||||
|
bestData = string.char(128 + lm, math.floor(pm / 256), thirdByte)
|
||||||
|
bestRes = pfx
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- ok, encode!
|
||||||
|
io.write(bestData)
|
||||||
|
crop(bestRes)
|
||||||
|
blk = blk:sub(#bestRes + 1)
|
||||||
|
end
|
||||||
|
|
88
com2/bonecrunch.lua
Normal file
88
com2/bonecrunch.lua
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
-- This program tries to crunch down the installer a bit further.
|
||||||
|
-- Specific target in mind, it has no support for string escapes.
|
||||||
|
-- It also does this:
|
||||||
|
for i = 1, 3 do
|
||||||
|
print(io.read())
|
||||||
|
end
|
||||||
|
|
||||||
|
local sequences = {
|
||||||
|
{"\n", " "},
|
||||||
|
{" ", " "},
|
||||||
|
{" #", "#"},
|
||||||
|
{"# ", "#"},
|
||||||
|
{" ,", ","},
|
||||||
|
{", ", ","},
|
||||||
|
{" (", "("},
|
||||||
|
{"( ", "("},
|
||||||
|
{" )", ")"},
|
||||||
|
{") ", ")"},
|
||||||
|
{" <", "<"},
|
||||||
|
{"< ", "<"},
|
||||||
|
{" >", ">"},
|
||||||
|
{"> ", ">"},
|
||||||
|
{" *", "*"},
|
||||||
|
{"* ", "*"},
|
||||||
|
{" ~", "~"},
|
||||||
|
{"~ ", "~"},
|
||||||
|
{" /", "/"},
|
||||||
|
{"/ ", "/"},
|
||||||
|
{" %", "%"},
|
||||||
|
{"% ", "%"},
|
||||||
|
{" =", "="},
|
||||||
|
{"= ", "="},
|
||||||
|
{" -", "-"},
|
||||||
|
{"- ", "-"},
|
||||||
|
{" +", "+"},
|
||||||
|
{"+ ", "+"},
|
||||||
|
{".. ", ".."},
|
||||||
|
{" ..", ".."},
|
||||||
|
{"\"\" ", "\"\""},
|
||||||
|
{"=0 t", "=0t"},
|
||||||
|
{">0 t", ">0t"},
|
||||||
|
{">1 t", ">1t"},
|
||||||
|
{"=1 w", "=1w"},
|
||||||
|
{"=380 l", "=380l"},
|
||||||
|
{"=127 t", "=127t"},
|
||||||
|
{"<128 t", "<128t"},
|
||||||
|
{"=128 t", "=128t"},
|
||||||
|
{">255 t", ">255t"},
|
||||||
|
{"=512 t", "=512t"}
|
||||||
|
}
|
||||||
|
|
||||||
|
local function pass(buffer)
|
||||||
|
local ob = ""
|
||||||
|
local smode = false
|
||||||
|
while #buffer > 0 do
|
||||||
|
if not smode then
|
||||||
|
local ds = true
|
||||||
|
while ds do
|
||||||
|
ds = false
|
||||||
|
for _, v in ipairs(sequences) do
|
||||||
|
if buffer:sub(1, #(v[1])) == v[1] then
|
||||||
|
buffer = v[2] .. buffer:sub(#(v[1]) + 1)
|
||||||
|
ds = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local ch = buffer:sub(1, 1)
|
||||||
|
buffer = buffer:sub(2)
|
||||||
|
ob = ob .. ch
|
||||||
|
if ch == "\"" then
|
||||||
|
smode = not smode
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ob
|
||||||
|
end
|
||||||
|
local op = io.read("*a")
|
||||||
|
while true do
|
||||||
|
local np = pass(op)
|
||||||
|
if np == op then
|
||||||
|
io.write(np)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
op = np
|
||||||
|
end
|
72
com2/bundiv.lua
Normal file
72
com2/bundiv.lua
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
-- This is released into the public domain. XX
|
||||||
|
-- No warranty is provided, implied or otherwise. XX
|
||||||
|
local sector = io.write -- XX
|
||||||
|
-- XX
|
||||||
|
-- BUNDIVIDE (r5 edition) reference implementation for integration XX
|
||||||
|
-- Lines ending with XX are not included in the output. XX
|
||||||
|
-- Lines that both start and end with -- are only for use in the output, XX
|
||||||
|
-- and are thus not executed during any sanity-check procedure. XX
|
||||||
|
-- XX
|
||||||
|
Cp,Ct,Cc,Cw="","","",("\x00"):rep(65536)
|
||||||
|
-- High-level breakdown: XX
|
||||||
|
-- CP is unescaper & TAR-sector-breakup. XX
|
||||||
|
-- It'll only begin to input if at least 3 bytes are available, XX
|
||||||
|
-- so you'll want to throw in 2 extra zeroes at the end of stream as done here. XX
|
||||||
|
-- It uses Ct (input buffer) and Cp (output buffer). XX
|
||||||
|
-- Ignore its second argument, as that's a lie, it's just there for a local. XX
|
||||||
|
-- CD is the actual decompressor. It has the same quirk as CP, wanting two more bytes. XX
|
||||||
|
-- It stores to Cc (compressed), and Cw (window). XX
|
||||||
|
-- It uses Ca as the "first null" activation flag. XX
|
||||||
|
-- It outputs that which goes to the window to CP also. XX
|
||||||
|
-- And it also uses a fake local. XX
|
||||||
|
CP = function (d, b)
|
||||||
|
Ct = Ct .. d
|
||||||
|
while #Ct > 2 do
|
||||||
|
b = Ct:byte()
|
||||||
|
Ct = Ct:sub(2)
|
||||||
|
if b == 127 then
|
||||||
|
b = Ct:byte()
|
||||||
|
Ct = Ct:sub(2)
|
||||||
|
if b == 127 then
|
||||||
|
b = Ct:byte() + 254
|
||||||
|
if b > 255 then
|
||||||
|
b = b - 256
|
||||||
|
end
|
||||||
|
Ct = Ct:sub(2)
|
||||||
|
else
|
||||||
|
b = b + 127
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Cp = Cp .. string.char(b)
|
||||||
|
if #Cp == 512 then
|
||||||
|
sector(Cp)
|
||||||
|
Cp = ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- XX
|
||||||
|
CD = function (d, b, p)
|
||||||
|
Cc = Cc .. d
|
||||||
|
while #Cc > 2 do
|
||||||
|
b = Cc:byte()
|
||||||
|
if not Ca then
|
||||||
|
Ca, b, Cc = b < 1, "", Cc:sub(2)
|
||||||
|
elseif b < 128 then
|
||||||
|
b, Cc = Cc:sub(1, 1), Cc:sub(2)
|
||||||
|
else
|
||||||
|
p = Cc:byte(2) * 256 + Cc:byte(3) + 1
|
||||||
|
b, Cc = Cw:sub(p, p + b - 125), Cc:sub(4)
|
||||||
|
end
|
||||||
|
CP(b)
|
||||||
|
Cw = (Cw .. b):sub(-65536)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- XX
|
||||||
|
CD(io.read("*a")) -- XX
|
||||||
|
--D.remove("init-bdivide.lua")--
|
||||||
|
--D.rename("init.lua","init-bdivide.lua")--
|
||||||
|
--local Ch=D.open("init-bdivide.lua","rb")--
|
||||||
|
--dieCB=function()D.close(Ch)D.remove("init-bdivide.lua")end--
|
||||||
|
--while true do local t=D.read(Ch, 64)if not t then break end CD(t)end--
|
||||||
|
-- XX
|
||||||
|
CD("\x00\x00")CP("\x00\x00")
|
20
com2/preproc.lua
Normal file
20
com2/preproc.lua
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
-- PREPROC: preprocess input to be 7-bit
|
||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local c = io.read(1)
|
||||||
|
if not c then return end
|
||||||
|
local bc = c:byte()
|
||||||
|
if bc < 127 then
|
||||||
|
io.write(c)
|
||||||
|
else
|
||||||
|
if bc <= 253 then
|
||||||
|
-- 127(0) through 253(126)
|
||||||
|
io.write("\x7F" .. string.char(bc - 127))
|
||||||
|
else
|
||||||
|
-- 254(0) through 255 (1)
|
||||||
|
io.write("\x7F\x7F" .. string.char(bc - 254))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
27
heroes.lua
Normal file
27
heroes.lua
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
-- arg is the size of the code.tar file
|
||||||
|
local arg = ...
|
||||||
|
os.execute("lua com2/preproc.lua < code.tar | lua com2/bdivide.lua > com2/code.tar.bd")
|
||||||
|
os.execute("cat insthead.lua")
|
||||||
|
print("sC=" .. math.ceil(tonumber(arg) / 512))
|
||||||
|
local src = io.open("com2/bundiv.lua", "r")
|
||||||
|
while true do
|
||||||
|
local line = src:read()
|
||||||
|
if not line then
|
||||||
|
io.flush()
|
||||||
|
src:close()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local endix = line:sub(#line-1,#line)
|
||||||
|
if endix ~= "XX" then
|
||||||
|
if endix == "--" then
|
||||||
|
-- included
|
||||||
|
print(line:sub(3,#line-2))
|
||||||
|
else
|
||||||
|
print(line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- XX means ignored.
|
||||||
|
end
|
@ -1,36 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
local bga = {}
|
|
||||||
|
|
||||||
local str = io.read("*a")
|
|
||||||
|
|
||||||
for i = 1, #str - 1 do
|
|
||||||
local bg = str:sub(i, i + 1)
|
|
||||||
bga[bg] = (bga[bg] or 0) + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local first = {}
|
|
||||||
local second = {}
|
|
||||||
|
|
||||||
local mode = ...
|
|
||||||
|
|
||||||
for k, v in pairs(bga) do
|
|
||||||
if mode == "combined" then
|
|
||||||
print(string.format("%08i: %02x%02x : %s", v, k:byte(1), k:byte(2), k))
|
|
||||||
end
|
|
||||||
first[k:sub(1, 1)] = (first[k:sub(1, 1)] or 0) + v
|
|
||||||
second[k:sub(1, 1)] = (second[k:sub(1, 1)] or 0) + v
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(first) do
|
|
||||||
if mode == "first" then
|
|
||||||
print(string.format("%08i: %s", v, k))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(second) do
|
|
||||||
if mode == "second" then
|
|
||||||
print(string.format("%08i: %s", v, k))
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,85 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- PREPROC (r9 edition): preprocess input to be 7-bit
|
|
||||||
|
|
||||||
local frw = require("libs.frw")
|
|
||||||
|
|
||||||
local
|
|
||||||
-- SHARED WITH DECOMPRESSION ENGINE
|
|
||||||
function p(x, y)
|
|
||||||
if x == 126 then
|
|
||||||
return string.char(y), 3
|
|
||||||
elseif x == 127 then
|
|
||||||
return string.char(128 + y), 3
|
|
||||||
elseif x >= 32 then
|
|
||||||
return string.char(x), 2
|
|
||||||
elseif x == 31 then
|
|
||||||
return "\n", 2
|
|
||||||
elseif x == 30 then
|
|
||||||
return "\x00", 2
|
|
||||||
end
|
|
||||||
return string.char(("enart"):byte(x % 5 + 1), ("ndtelh"):byte((x - x % 5) / 5 + 1)), 2
|
|
||||||
end
|
|
||||||
|
|
||||||
local preprocParts = {}
|
|
||||||
local preprocMaxLen = 0
|
|
||||||
for i = 0, 127 do
|
|
||||||
for j = 0, 127 do
|
|
||||||
local d, l = p(i, j)
|
|
||||||
if d then
|
|
||||||
preprocMaxLen = math.max(preprocMaxLen, #d)
|
|
||||||
l = l - 1
|
|
||||||
if (not preprocParts[d]) or (#preprocParts[d] > l) then
|
|
||||||
if l == 2 then
|
|
||||||
preprocParts[d] = string.char(i, j)
|
|
||||||
else
|
|
||||||
preprocParts[d] = string.char(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function preprocWithPadding(blk, p)
|
|
||||||
local out = ""
|
|
||||||
local needsPadding = false
|
|
||||||
while blk ~= "" do
|
|
||||||
p(blk)
|
|
||||||
local len = math.min(preprocMaxLen, #blk)
|
|
||||||
while len > 0 do
|
|
||||||
local seg = blk:sub(1, len)
|
|
||||||
if preprocParts[seg] then
|
|
||||||
out = out .. preprocParts[seg]
|
|
||||||
needsPadding = #preprocParts[seg] < 2
|
|
||||||
blk = blk:sub(#seg + 1)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
len = len - 1
|
|
||||||
end
|
|
||||||
assert(len ~= 0)
|
|
||||||
end
|
|
||||||
-- This needsPadding bit is just sort of quickly added in
|
|
||||||
-- to keep this part properly maintained
|
|
||||||
-- even though it might never get used
|
|
||||||
if needsPadding then
|
|
||||||
return out .. "\x00"
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
local bdCore = require("bdivide.core")
|
|
||||||
|
|
||||||
return function (data, lexCrunch)
|
|
||||||
io.stderr:write("preproc: ")
|
|
||||||
local pi = frw.progress()
|
|
||||||
local function p(b)
|
|
||||||
pi(1 - (#b / #data))
|
|
||||||
end
|
|
||||||
data = preprocWithPadding(data, p)
|
|
||||||
io.stderr:write("\nbdivide: ")
|
|
||||||
pi = frw.progress()
|
|
||||||
data = bdCore.bdividePad(bdCore.bdivide(data, p))
|
|
||||||
io.stderr:write("\n")
|
|
||||||
return lexCrunch.process(frw.read("bdivide/instdeco.lua"), {}), data
|
|
||||||
end
|
|
@ -1,72 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- BDIVIDE r5 edition
|
|
||||||
-- Algorithm simplified for smaller implementation and potentially better compression
|
|
||||||
-- format:
|
|
||||||
-- 0-127 for constants
|
|
||||||
-- <128 + (length - 4)>, <position high>, <position low>
|
|
||||||
-- Position is where in the window it was found, minus 1.
|
|
||||||
-- windowSize must be the same between the encoder and decoder,
|
|
||||||
-- and is the amount of data preserved after cropping.
|
|
||||||
|
|
||||||
local bdivCore = {}
|
|
||||||
|
|
||||||
function bdivCore.bdivide(blk, p)
|
|
||||||
local out = ""
|
|
||||||
|
|
||||||
local windowSize = 0x10000
|
|
||||||
local windowData = ("\x00"):rep(windowSize)
|
|
||||||
|
|
||||||
while blk ~= "" do
|
|
||||||
p(blk)
|
|
||||||
local bestData = blk:sub(1, 1)
|
|
||||||
assert(blk:byte() < 128, "BDIVIDE does not handle 8-bit data")
|
|
||||||
local bestRes = bestData
|
|
||||||
for lm = 0, 127 do
|
|
||||||
local al = lm + 4
|
|
||||||
local pfx = blk:sub(1, al)
|
|
||||||
if #pfx ~= al then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local p = windowData:find(pfx, 1, true)
|
|
||||||
if not p then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local pm = p - 1
|
|
||||||
local thirdByte = pm % 256
|
|
||||||
bestData = string.char(128 + lm, math.floor(pm / 256), thirdByte)
|
|
||||||
bestRes = pfx
|
|
||||||
end
|
|
||||||
-- ok, encode!
|
|
||||||
out = out .. bestData
|
|
||||||
-- crop window
|
|
||||||
windowData = (windowData .. bestRes):sub(-windowSize)
|
|
||||||
blk = blk:sub(#bestRes + 1)
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Adds padding if required
|
|
||||||
function bdivCore.bdividePad(data)
|
|
||||||
local i = 1
|
|
||||||
-- Basically, if it ends on a literal,
|
|
||||||
-- then the literal won't get read without two padding bytes.
|
|
||||||
-- Otherwise (including if no data) it's fine.
|
|
||||||
local needsPadding = false
|
|
||||||
while i <= #data do
|
|
||||||
if data:byte(i) > 127 then
|
|
||||||
i = i + 3
|
|
||||||
needsPadding = false
|
|
||||||
else
|
|
||||||
i = i + 1
|
|
||||||
needsPadding = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if needsPadding then
|
|
||||||
return data .. "\x00\x00"
|
|
||||||
end
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
return bdivCore
|
|
@ -1,64 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- BDIVIDE (r5 edition) and PREPROC (r9 edition)
|
|
||||||
-- decompression engine for installer
|
|
||||||
|
|
||||||
$bdPPBuffer = ""
|
|
||||||
$bdBDBuffer = ""
|
|
||||||
$bdBDWindow = ("\x00"):rep(2^16)
|
|
||||||
-- High-level breakdown:
|
|
||||||
-- q is unescaper.
|
|
||||||
-- It'll only begin to input if at least 3 bytes are available,
|
|
||||||
-- so you'll want to throw in 2 extra zeroes at the end of stream as done here.
|
|
||||||
-- It uses t (input buffer) and p (output buffer).
|
|
||||||
-- Ignore its second argument, as that's a lie, it's just there for a local.
|
|
||||||
-- L is the actual decompressor. It has the same quirk as q, wanting two more bytes.
|
|
||||||
-- It stores to c (compressed), and w (window).
|
|
||||||
-- It outputs that which goes to the window to q also.
|
|
||||||
-- And it also uses a fake local.
|
|
||||||
|
|
||||||
-- SEE compress.lua FOR THIS FUNCTION
|
|
||||||
function $bdPP(x, y)
|
|
||||||
if x == 126 then
|
|
||||||
return string.char(y), 3
|
|
||||||
elseif x == 127 then
|
|
||||||
return string.char(128 + y), 3
|
|
||||||
elseif x >= 32 then
|
|
||||||
return string.char(x), 2
|
|
||||||
elseif x == 31 then
|
|
||||||
return "\n", 2
|
|
||||||
elseif x == 30 then
|
|
||||||
return "\x00", 2
|
|
||||||
end
|
|
||||||
return string.char(("enart"):byte(x % 5 + 1), ("ndtelh"):byte((x - x % 5) / 5 + 1)), 2
|
|
||||||
end
|
|
||||||
|
|
||||||
${
|
|
||||||
function $engineInput($L|lData)
|
|
||||||
$bdBDBuffer = $bdBDBuffer .. $lData
|
|
||||||
while #$bdBDBuffer > 2 do
|
|
||||||
$lData = $bdBDBuffer:byte()
|
|
||||||
if $lData < 128 then
|
|
||||||
$lData = $bdBDBuffer:sub(1, 1)
|
|
||||||
$bdBDBuffer = $bdBDBuffer:sub(2)
|
|
||||||
else
|
|
||||||
${
|
|
||||||
$L|bdBDPtr = $bdBDBuffer:byte(2) * 256 + $bdBDBuffer:byte(3) + 1
|
|
||||||
$lData = $bdBDWindow:sub($bdBDPtr, $bdBDPtr + $lData - 125)
|
|
||||||
$bdBDBuffer = $bdBDBuffer:sub(4)
|
|
||||||
$}
|
|
||||||
end
|
|
||||||
$bdPPBuffer = $bdPPBuffer .. $lData
|
|
||||||
$bdBDWindow = ($bdBDWindow .. $lData):sub(-2^16)
|
|
||||||
while #$bdPPBuffer > 1 do
|
|
||||||
${
|
|
||||||
$lData, $L|bdPPAdv = $bdPP($bdPPBuffer:byte(), $bdPPBuffer:byte(2))
|
|
||||||
$bdPPBuffer = $bdPPBuffer:sub($bdPPAdv)
|
|
||||||
$}
|
|
||||||
$engineOutput($lData)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
local frw = require("libs.frw")
|
|
||||||
|
|
||||||
local bdCore = require("bdivide.core")
|
|
||||||
|
|
||||||
return function (data, lexCrunch)
|
|
||||||
io.stderr:write("\nbdivide: ")
|
|
||||||
local pi = frw.progress()
|
|
||||||
local function p(b)
|
|
||||||
pi(1 - (#b / #data))
|
|
||||||
end
|
|
||||||
data = bdCore.bdividePad(bdCore.bdivide(data, p))
|
|
||||||
io.stderr:write("\n")
|
|
||||||
return lexCrunch.process(frw.read("bdvlite/instdeco.lua"), {}), data
|
|
||||||
end
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- BDIVIDE r5 edition
|
|
||||||
-- Algorithm simplified for smaller implementation and potentially better compression
|
|
||||||
-- format:
|
|
||||||
-- 0-127 for constants
|
|
||||||
-- <128 + (length - 4)>, <position high>, <position low>
|
|
||||||
-- Position is where in the window it was found, minus 1.
|
|
||||||
-- windowSize must be the same between the encoder and decoder,
|
|
||||||
-- and is the amount of data preserved after cropping.
|
|
||||||
|
|
||||||
local bdivCore = {}
|
|
||||||
|
|
||||||
function bdivCore.bdivide(blk, p)
|
|
||||||
local out = ""
|
|
||||||
|
|
||||||
local windowSize = 0x10000
|
|
||||||
local windowData = ("\x00"):rep(windowSize)
|
|
||||||
|
|
||||||
while blk ~= "" do
|
|
||||||
p(blk)
|
|
||||||
local bestData = blk:sub(1, 1)
|
|
||||||
assert(blk:byte() < 128, "BDIVIDE does not handle 8-bit data")
|
|
||||||
local bestRes = bestData
|
|
||||||
for lm = 0, 127 do
|
|
||||||
local al = lm + 4
|
|
||||||
local pfx = blk:sub(1, al)
|
|
||||||
if #pfx ~= al then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local p = windowData:find(pfx, 1, true)
|
|
||||||
if not p then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local pm = p - 1
|
|
||||||
local thirdByte = pm % 256
|
|
||||||
bestData = string.char(128 + lm, math.floor(pm / 256), thirdByte)
|
|
||||||
bestRes = pfx
|
|
||||||
end
|
|
||||||
-- ok, encode!
|
|
||||||
out = out .. bestData
|
|
||||||
-- crop window
|
|
||||||
windowData = (windowData .. bestRes):sub(-windowSize)
|
|
||||||
blk = blk:sub(#bestRes + 1)
|
|
||||||
end
|
|
||||||
return out
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Adds padding if required
|
|
||||||
function bdivCore.bdividePad(data)
|
|
||||||
local i = 1
|
|
||||||
-- Basically, if it ends on a literal,
|
|
||||||
-- then the literal won't get read without two padding bytes.
|
|
||||||
-- Otherwise (including if no data) it's fine.
|
|
||||||
local needsPadding = false
|
|
||||||
while i <= #data do
|
|
||||||
if data:byte(i) > 127 then
|
|
||||||
i = i + 3
|
|
||||||
needsPadding = false
|
|
||||||
else
|
|
||||||
i = i + 1
|
|
||||||
needsPadding = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if needsPadding then
|
|
||||||
return data .. "\x00\x00"
|
|
||||||
end
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
return bdivCore
|
|
@ -1,30 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- BDIVIDE (r5 edition)
|
|
||||||
-- decompression engine used to decompress DEFLATE decompression engine
|
|
||||||
|
|
||||||
$bdBDBuffer = ""
|
|
||||||
$bdBDWindow = ("\x00"):rep(2^16)
|
|
||||||
|
|
||||||
${
|
|
||||||
function $engineInput($L|lData)
|
|
||||||
$bdBDBuffer = $bdBDBuffer .. $lData
|
|
||||||
while #$bdBDBuffer > 2 do
|
|
||||||
$lData = $bdBDBuffer:byte()
|
|
||||||
if $lData < 128 then
|
|
||||||
$lData = $bdBDBuffer:sub(1, 1)
|
|
||||||
$bdBDBuffer = $bdBDBuffer:sub(2)
|
|
||||||
else
|
|
||||||
${
|
|
||||||
$L|bdBDPtr = $bdBDBuffer:byte(2) * 256 + $bdBDBuffer:byte(3) + 1
|
|
||||||
$lData = $bdBDWindow:sub($bdBDPtr, $bdBDPtr + $lData - 125)
|
|
||||||
$bdBDBuffer = $bdBDBuffer:sub(4)
|
|
||||||
$}
|
|
||||||
end
|
|
||||||
$bdBDWindow = ($bdBDWindow .. $lData):sub(-2^16)
|
|
||||||
$engineOutput($lData)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- KittenOS NEO Installer Generator --
|
|
||||||
local args = {...}
|
|
||||||
|
|
||||||
local cid = args[1]
|
|
||||||
local tarName = args[2]
|
|
||||||
local algorithmsInReverseOrder = {}
|
|
||||||
for i = 3, #args do
|
|
||||||
table.insert(algorithmsInReverseOrder, 1, args[i])
|
|
||||||
end
|
|
||||||
|
|
||||||
local u = require("libs.frw")
|
|
||||||
|
|
||||||
local instSize = 0
|
|
||||||
local function put(data)
|
|
||||||
io.write(data)
|
|
||||||
instSize = instSize + #data
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Installer Lexcrunch Context --
|
|
||||||
local lexCrunch = require("libs.lexcrunch")()
|
|
||||||
|
|
||||||
-- Installer Core --
|
|
||||||
|
|
||||||
-- installerFinalized:
|
|
||||||
-- Stuff that's already finished and put at the end of RISM. Prepend to this.
|
|
||||||
-- installerPayload / installerProgramLength:
|
|
||||||
-- The next-outer chunk that hasn't been written to the end of RISM
|
|
||||||
-- as the compression scheme (if one) has not been applied yet.
|
|
||||||
-- Really, installerProgramLength is only necessary because of the innermost chunk,
|
|
||||||
-- as that chunk has the TAR; additional data that's part of the same effective compression block,
|
|
||||||
-- but requires the program length to avoid it.
|
|
||||||
local installerPayload
|
|
||||||
local installerProgramLength
|
|
||||||
local installerFinalized = ""
|
|
||||||
|
|
||||||
do
|
|
||||||
local tarData = u.read(tarName)
|
|
||||||
local tarSectors = math.floor(#tarData / 512)
|
|
||||||
local installerCore = lexCrunch.process(u.read("instcore.lua"), {["$$SECTORS"] = tostring(tarSectors)})
|
|
||||||
installerPayload = installerCore .. tarData
|
|
||||||
installerProgramLength = #installerCore
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Installer Compression --
|
|
||||||
for _, v in ipairs(algorithmsInReverseOrder) do
|
|
||||||
io.stderr:write("compressing (" .. v .. ")\n")
|
|
||||||
local algImpl = require(v .. ".compress")
|
|
||||||
local algEngine, algData = algImpl(installerPayload, lexCrunch)
|
|
||||||
io.stderr:write("result: " .. #installerPayload .. " -> " .. #algData .. "\n")
|
|
||||||
-- prepend the program length of the last section
|
|
||||||
algEngine = lexCrunch.process("$iBlockingLen = " .. installerProgramLength .. " " .. algEngine, {})
|
|
||||||
-- commit
|
|
||||||
installerPayload = algEngine
|
|
||||||
installerProgramLength = #installerPayload
|
|
||||||
installerFinalized = algData .. installerFinalized
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Installer Final --
|
|
||||||
|
|
||||||
-- This is a special case, so the program length/payload/etc. business has to be repeated.
|
|
||||||
put("--" .. cid .. "\n")
|
|
||||||
put("--This is released into the public domain. No warranty is provided, implied or otherwise.\n")
|
|
||||||
put(lexCrunch.process(u.read("insthead.lua"), {["$$CORESIZE"] = tostring(installerProgramLength)}))
|
|
||||||
|
|
||||||
local RISM = installerPayload .. installerFinalized
|
|
||||||
RISM = RISM:gsub("\xFE", "\xFE\xFE")
|
|
||||||
RISM = RISM:gsub("]]", "]\xFE]")
|
|
||||||
RISM = "\x00" .. RISM
|
|
||||||
put("--[[" .. RISM .. "]]")
|
|
||||||
|
|
||||||
-- Dumping debug info --
|
|
||||||
local dbg = io.open("iSymTab", "wb")
|
|
||||||
lexCrunch.dump(dbg)
|
|
||||||
dbg:close()
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- This is a wrapper around (i.e. does not contain) Zopfli.
|
|
||||||
local frw = require("libs.frw")
|
|
||||||
|
|
||||||
return function (data, lexCrunch)
|
|
||||||
frw.write("tempData.bin", data)
|
|
||||||
os.execute("zopfli --i1 --deflate -c tempData.bin > tempZopf.bin")
|
|
||||||
local res = frw.read("tempZopf.bin")
|
|
||||||
os.execute("rm tempData.bin tempZopf.bin")
|
|
||||||
return lexCrunch.process(frw.read("deflate/instdeco.lua"), {}), res
|
|
||||||
end
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- THIS NEXT LINE IS CLEARLY AWFUL
|
|
||||||
$bdBDWindow = nil
|
|
||||||
|
|
||||||
-- THE DEFLATE DECOMPRESSOR OF MADNESS --
|
|
||||||
|
|
||||||
-- Core I/O --
|
|
||||||
|
|
||||||
-- $dfAlignToByteRemaining is
|
|
||||||
-- set to 8 in the outer engine
|
|
||||||
|
|
||||||
${
|
|
||||||
function $dfGetIntField($L|lLen, $L|lVal)
|
|
||||||
$lVal = 0
|
|
||||||
for $L|lI = 0, $lLen - 1 do
|
|
||||||
if coroutine.yield() then
|
|
||||||
$lVal = $lVal + 2^$lI
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return $lVal
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
-- Huffman Core --
|
|
||||||
-- The approach here is based around 1-prefixed integers.
|
|
||||||
-- These are stored in a flat table.
|
|
||||||
-- So 0b1000 is the pattern 000.
|
|
||||||
|
|
||||||
${
|
|
||||||
function $dfReadHuffmanSymbol($L|lTree, $L|lVal)
|
|
||||||
$lVal = 1
|
|
||||||
while not $lTree[$lVal] do
|
|
||||||
$lVal = ($lVal * 2) + $dfGetIntField(1)
|
|
||||||
end
|
|
||||||
return $lTree[$lVal]
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
${
|
|
||||||
function $dfGenHuffmanTree($L|lCodeLens)
|
|
||||||
-- $L|lI (used everywhere; defining inside creates a bug because it gets globalized)
|
|
||||||
$L|lNextCode = {}
|
|
||||||
${
|
|
||||||
-- To explain:
|
|
||||||
-- lNextCode is needed all the way to the end.
|
|
||||||
-- But lBLCount isn't needed after it's used to
|
|
||||||
-- generate lNextCode.
|
|
||||||
-- And lCode is very, very temporary.
|
|
||||||
-- Hence this massive block.
|
|
||||||
$L|lBLCount = {}
|
|
||||||
-- Note the 0
|
|
||||||
for $lI = 0, 15 do
|
|
||||||
$lBLCount[$lI] = 0
|
|
||||||
end
|
|
||||||
for $lI = 0, #$lCodeLens do
|
|
||||||
${
|
|
||||||
$L|lCodeLen = $lCodeLens[$lI]
|
|
||||||
if $lCodeLen ~= 0 then
|
|
||||||
$lBLCount[$lCodeLen] = $lBLCount[$lCodeLen] + 1
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
end
|
|
||||||
|
|
||||||
$L|lCode = 0
|
|
||||||
for $lI = 1, 15 do
|
|
||||||
$lCode = ($lCode + $lBLCount[$lI - 1]) * 2
|
|
||||||
$lNextCode[$lI] = $lCode
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
$L|lTree = {}
|
|
||||||
for $lI = 0, #$lCodeLens do
|
|
||||||
${
|
|
||||||
$L|lCodeLen = $lCodeLens[$lI]
|
|
||||||
if $lCodeLen ~= 0 then
|
|
||||||
$L|lPow = math.floor(2 ^ $lCodeLen)
|
|
||||||
assert($lNextCode[$lCodeLen] < $lPow, "Tl" .. $lCodeLen)
|
|
||||||
$L|lK = $lNextCode[$lCodeLen] + $lPow
|
|
||||||
assert(not $lTree[$lK], "conflict @ " .. $lK)
|
|
||||||
$lTree[$lK] = $lI
|
|
||||||
$lNextCode[$lCodeLen] = $lNextCode[$lCodeLen] + 1
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
end
|
|
||||||
return $lTree
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
-- DEFLATE fixed trees --
|
|
||||||
${
|
|
||||||
$L|dfFixedTL = {}
|
|
||||||
for $L|lI = 0, 143 do $dfFixedTL[$lI] = 8 end
|
|
||||||
for $lI = 144, 255 do $dfFixedTL[$lI] = 9 end
|
|
||||||
for $lI = 256, 279 do $dfFixedTL[$lI] = 7 end
|
|
||||||
for $lI = 280, 287 do $dfFixedTL[$lI] = 8 end
|
|
||||||
$dfFixedLit = $dfGenHuffmanTree($dfFixedTL)
|
|
||||||
-- last line possibly destroyed dfFixedTL, but that's alright
|
|
||||||
$dfFixedTL = {}
|
|
||||||
for $lI = 0, 31 do $dfFixedTL[$lI] = 5 end
|
|
||||||
$dfFixedDst = $dfGenHuffmanTree($dfFixedTL)
|
|
||||||
$}
|
|
||||||
|
|
||||||
-- DEFLATE LZ Core --
|
|
||||||
|
|
||||||
$dfWindow = ("\x00"):rep(2^15)
|
|
||||||
$dfPushBuf = ""
|
|
||||||
${
|
|
||||||
function $dfOutput($L|lData)
|
|
||||||
$dfWindow = ($dfWindow .. $lData):sub(-2^15)
|
|
||||||
$dfPushBuf = $dfPushBuf .. $lData
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
$dfBittblLength = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
1, 1, 1, 1, 2, 2, 2, 2,
|
|
||||||
3, 3, 3, 3, 4, 4, 4, 4,
|
|
||||||
5, 5, 5, 5, 0
|
|
||||||
}
|
|
||||||
$dfBasetblLength = {
|
|
||||||
3, 4, 5, 6, 7, 8, 9, 10,
|
|
||||||
11, 13, 15, 17, 19, 23, 27, 31,
|
|
||||||
35, 43, 51, 59, 67, 83, 99, 115,
|
|
||||||
131, 163, 195, 227, 258
|
|
||||||
}
|
|
||||||
$dfBittblDist = {
|
|
||||||
0, 0, 0, 0, 1, 1, 2, 2,
|
|
||||||
3, 3, 4, 4, 5, 5, 6, 6,
|
|
||||||
7, 7, 8, 8, 9, 9, 10, 10,
|
|
||||||
11, 11, 12, 12, 13, 13
|
|
||||||
}
|
|
||||||
$dfBasetblDist = {
|
|
||||||
1, 2, 3, 4, 5, 7, 9, 13,
|
|
||||||
17, 25, 33, 49, 65, 97, 129, 193,
|
|
||||||
257, 385, 513, 769, 1025, 1537, 2049, 3073,
|
|
||||||
4097, 6145, 8193, 12289, 16385, 24577
|
|
||||||
}
|
|
||||||
|
|
||||||
${
|
|
||||||
function $dfReadBlockBody($L|lLit, $L|lDst, $L|lLitSym, $L|lLen, $L|lDCode, $L|lPtr)
|
|
||||||
while true do
|
|
||||||
$lLitSym = $dfReadHuffmanSymbol($lLit)
|
|
||||||
if $lLitSym <= 255 then
|
|
||||||
$dfOutput(string.char($lLitSym))
|
|
||||||
elseif $lLitSym == 256 then
|
|
||||||
return
|
|
||||||
elseif $lLitSym <= 285 then
|
|
||||||
$lLen = $dfBasetblLength[$lLitSym - 256] + $dfGetIntField($dfBittblLength[$lLitSym - 256])
|
|
||||||
$lDCode = $dfReadHuffmanSymbol($lDst)
|
|
||||||
$lPtr = 32769 - ($dfBasetblDist[$lDCode + 1] + $dfGetIntField($dfBittblDist[$lDCode + 1]))
|
|
||||||
for $L|lI = 1, $lLen do
|
|
||||||
$dfOutput($dfWindow:sub($lPtr, $lPtr))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
error("nt" .. v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
-- Huffman Dynamics --
|
|
||||||
|
|
||||||
${
|
|
||||||
function $dfReadHuffmanDynamicSubcodes($L|lDistLens, $L|lCount, $L|lMetatree, $L|lCode)
|
|
||||||
-- used a lot: $L|lI
|
|
||||||
$lCode = 0
|
|
||||||
$lDistLens[-1] = 0
|
|
||||||
while $lCode < $lCount do
|
|
||||||
-- use a tmpglb since it's just for the chain
|
|
||||||
$L|lInstr = $dfReadHuffmanSymbol($lMetatree)
|
|
||||||
if $lInstr < 16 then
|
|
||||||
$lDistLens[$lCode] = $lInstr
|
|
||||||
$lCode = $lCode + 1
|
|
||||||
elseif $lInstr == 16 then
|
|
||||||
for $lI = 1, 3 + $dfGetIntField(2) do
|
|
||||||
$lDistLens[$lCode] = $lDistLens[$lCode - 1]
|
|
||||||
$lCode = $lCode + 1
|
|
||||||
assert($lCode <= $lCount, "sc.over")
|
|
||||||
end
|
|
||||||
elseif $lInstr == 17 then
|
|
||||||
for $lI = 1, 3 + $dfGetIntField(3) do
|
|
||||||
$lDistLens[$lCode] = 0
|
|
||||||
$lCode = $lCode + 1
|
|
||||||
assert($lCode <= $lCount, "sc.over")
|
|
||||||
end
|
|
||||||
elseif $lInstr == 18 then
|
|
||||||
for $lI = 1, 11 + $dfGetIntField(7) do
|
|
||||||
$lDistLens[$lCode] = 0
|
|
||||||
$lCode = $lCode + 1
|
|
||||||
assert($lCode <= $lCount, "sc.over")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- is this even possible?
|
|
||||||
error("sc.unki")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$lDistLens[-1] = nil
|
|
||||||
return $lDistLens
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
$dfDynamicMetalensScramble = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}
|
|
||||||
|
|
||||||
${
|
|
||||||
function $dfReadHuffmanDynamic($L|lState, $L|lLiteralSize, $L|lDistanceSize, $L|lDistanceLens)
|
|
||||||
-- $L|lI loop variable, used all over
|
|
||||||
-- to save on locals, this is reused
|
|
||||||
-- as metalens
|
|
||||||
$lState = {}
|
|
||||||
for $lI = 0, 18 do $lState[$lI] = 0 end
|
|
||||||
$lLiteralSize = $dfGetIntField(5) + 257
|
|
||||||
$lDistanceSize = $dfGetIntField(5) + 1
|
|
||||||
for $lI = 1, $dfGetIntField(4) + 4 do
|
|
||||||
$lState[$dfDynamicMetalensScramble[$lI]] = $dfGetIntField(3)
|
|
||||||
end
|
|
||||||
-- as metatree
|
|
||||||
$lState = $dfGenHuffmanTree($lState)
|
|
||||||
-- as concatenated subcodes
|
|
||||||
$lState = $dfReadHuffmanDynamicSubcodes({}, $lLiteralSize + $lDistanceSize, $lState)
|
|
||||||
-- The distance lengths are removed from lState,
|
|
||||||
-- while being added to lDistanceLens
|
|
||||||
-- The result is completion
|
|
||||||
$lDistanceLens = {}
|
|
||||||
for $lI = 0, $lDistanceSize - 1 do
|
|
||||||
$lDistanceLens[$lI] = $lState[$lLiteralSize + $lI]
|
|
||||||
$lState[$lLiteralSize + $lI] = nil
|
|
||||||
end
|
|
||||||
return $dfGenHuffmanTree($lState), $dfGenHuffmanTree($lDistanceLens)
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
-- Main Thread --
|
|
||||||
|
|
||||||
${
|
|
||||||
$dfThread = coroutine.create(function ($L|lFinal, $L|lLitLen)
|
|
||||||
while true do
|
|
||||||
$lFinal = coroutine.yield()
|
|
||||||
$L|lBlockType = $dfGetIntField(2)
|
|
||||||
if $lBlockType == 0 then
|
|
||||||
-- literal
|
|
||||||
$dfGetIntField($dfAlignToByteRemaining)
|
|
||||||
$lLitLen = $dfGetIntField(16)
|
|
||||||
-- this is weird, ignore it
|
|
||||||
$dfGetIntField(16)
|
|
||||||
for $L|lI = 1, $lLitLen do
|
|
||||||
$dfOutput(string.char($dfGetIntField(8)))
|
|
||||||
end
|
|
||||||
elseif $lBlockType == 1 then
|
|
||||||
-- fixed Huffman
|
|
||||||
$dfReadBlockBody($dfFixedLit, $dfFixedDst)
|
|
||||||
elseif $lBlockType == 2 then
|
|
||||||
-- dynamic Huffman
|
|
||||||
$dfReadBlockBody($dfReadHuffmanDynamic())
|
|
||||||
else
|
|
||||||
error("b3")
|
|
||||||
end
|
|
||||||
while $lFinal do
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
$}
|
|
||||||
|
|
||||||
-- The Outer Engine --
|
|
||||||
|
|
||||||
coroutine.resume($dfThread)
|
|
||||||
${
|
|
||||||
function $engineInput($L|lData, $L|lByte)
|
|
||||||
for $L|lI = 1, #$lData do
|
|
||||||
$lByte = $lData:byte($lI)
|
|
||||||
$dfAlignToByteRemaining = 8
|
|
||||||
while $dfAlignToByteRemaining > 0 do
|
|
||||||
-- If we're providing the first bit (v = 8), then there are 7 bits remaining.
|
|
||||||
-- So this hits 0 when the *next* 8 yields will provide an as-is byte.
|
|
||||||
$dfAlignToByteRemaining = $dfAlignToByteRemaining - 1
|
|
||||||
assert(coroutine.resume($dfThread, $lByte % 2 == 1))
|
|
||||||
$lByte = math.floor($lByte / 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- flush prepared buffer
|
|
||||||
$engineOutput($dfPushBuf)
|
|
||||||
$dfPushBuf = ""
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
|||||||
-- KOSNEO installer base
|
|
||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
$icScreen = $component.list("screen", true)()
|
|
||||||
$icGPU = $component.list("gpu", true)()
|
|
||||||
|
|
||||||
$icFilename = "Starting..."
|
|
||||||
$icBytesRemaining = 0
|
|
||||||
|
|
||||||
if $icScreen and $icGPU then
|
|
||||||
$icGPU = $component.proxy($icGPU)
|
|
||||||
$icGPU.bind($icScreen)
|
|
||||||
$icGPU.setResolution(50, 5)
|
|
||||||
$icGPU.setBackground(2^24-1)
|
|
||||||
$icGPU.setForeground(0)
|
|
||||||
$icGPU.fill(1, 1, 50, 5, "█")
|
|
||||||
$icGPU.fill(1, 2, 50, 1, " ")
|
|
||||||
$icGPU.set(2, 2, "KittenOS NEO Installer")
|
|
||||||
end
|
|
||||||
|
|
||||||
function $icOctalToNumber($a0)
|
|
||||||
if $a0 == "" then return 0 end
|
|
||||||
return $icOctalToNumber($a0:sub(1, -2)) * 8 + ($a0:byte(#$a0) - 48)
|
|
||||||
end
|
|
||||||
|
|
||||||
$icSectorsRead = 0
|
|
||||||
$iBlockingLen = 512
|
|
||||||
function $iBlockingHook($a0)
|
|
||||||
if $icBytesRemaining > 0 then
|
|
||||||
${
|
|
||||||
$L|icByteAdv = math.min(512, $icBytesRemaining)
|
|
||||||
$icBytesRemaining = $icBytesRemaining - $icByteAdv
|
|
||||||
if $icFile then
|
|
||||||
$filesystem.write($icFile, $a0:sub(1, $icByteAdv))
|
|
||||||
if $icBytesRemaining <= 0 then
|
|
||||||
$filesystem.close($icFile)
|
|
||||||
$icFile = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
else
|
|
||||||
$icFilename = $a0:sub(1, 100):gsub("\x00", "")
|
|
||||||
-- this sets up the reading/skipping of data
|
|
||||||
$icBytesRemaining = $icOctalToNumber($a0:sub(125, 135))
|
|
||||||
if $icFilename:sub(1, 2) == "./" and $icFilename ~= "./" then
|
|
||||||
$icFilename = $icFilename:sub(3)
|
|
||||||
if $icFilename:sub(#$icFilename) == "/" then
|
|
||||||
$filesystem.makeDirectory($icFilename)
|
|
||||||
else
|
|
||||||
$icFile = $filesystem.open($icFilename, "wb")
|
|
||||||
if $icBytesRemaining == 0 then
|
|
||||||
$filesystem.close($icFile)
|
|
||||||
$icFile = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- UPDATE DISPLAY --
|
|
||||||
$icSectorsRead = $icSectorsRead + 1
|
|
||||||
if $icScreen and $icGPU then
|
|
||||||
$icGPU.fill(1, 2, 50, 1, " ")
|
|
||||||
$icGPU.set(2, 2, "KittenOS NEO Installer : " .. $icFilename)
|
|
||||||
$icGPU.fill(2, 4, 48, 1, "█")
|
|
||||||
$icGPU.fill(2, 4, math.ceil(48 * $icSectorsRead / $$SECTORS), 1, " ")
|
|
||||||
end
|
|
||||||
if $icSectorsRead % 16 == 0 then
|
|
||||||
$computer.pullSignal(0.01)
|
|
||||||
end
|
|
||||||
if $icSectorsRead == $$SECTORS then
|
|
||||||
$filesystem.close($readInFile)
|
|
||||||
$filesystem.remove("init.neoi.lua")
|
|
||||||
$computer.shutdown(true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
|||||||
-- KOSNEO installer base
|
|
||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
$computer = computer
|
|
||||||
$component = component
|
|
||||||
assert($component, "KittenOS NEO installer: Copy as init.lua to the target disk, then remove other disks & reboot.")
|
|
||||||
|
|
||||||
$filesystem = $component.proxy($computer.getBootAddress())
|
|
||||||
|
|
||||||
$filesystem.remove("init.neoi.lua")
|
|
||||||
$filesystem.rename("init.lua", "init.neoi.lua")
|
|
||||||
$readInFile = $filesystem.open("init.neoi.lua", "rb")
|
|
||||||
|
|
||||||
$iBlockingBuffer = ""
|
|
||||||
$iBlockingLen = $$CORESIZE
|
|
||||||
${
|
|
||||||
function $iBlockingHook($L|lBlock)
|
|
||||||
-- Run the next script (replacement compression engine,)
|
|
||||||
assert(load($lBlock))()
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
|
|
||||||
${
|
|
||||||
function $engineOutput($L|lBlock)
|
|
||||||
$iBlockingBuffer = $iBlockingBuffer .. $lBlock
|
|
||||||
while #$iBlockingBuffer >= $iBlockingLen do
|
|
||||||
$lBlock = $iBlockingBuffer:sub(1, $iBlockingLen)
|
|
||||||
$iBlockingBuffer = $iBlockingBuffer:sub($iBlockingLen + 1)
|
|
||||||
$iBlockingHook($lBlock)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
$engineInput = $engineOutput
|
|
||||||
|
|
||||||
while true do
|
|
||||||
$readInBlock = $filesystem.read($readInFile, 1024)
|
|
||||||
${
|
|
||||||
for i = 1, #$readInBlock do
|
|
||||||
-- Read-in state machine
|
|
||||||
|
|
||||||
-- IT IS VERY IMPORTANT that read-in be performed char-by-char.
|
|
||||||
-- This is because of compression chain-loading; if the switch between engines isn't "clean",
|
|
||||||
-- bad stuff happens.
|
|
||||||
|
|
||||||
-- This character becomes invalid once
|
|
||||||
-- it gets passed to engineInput,
|
|
||||||
-- but that's the last step, so it's ok!
|
|
||||||
$L|readInChar = $readInBlock:sub(i, i)
|
|
||||||
if not $readInState then
|
|
||||||
if $readInChar == "\x00" then
|
|
||||||
$readInState = 0
|
|
||||||
end
|
|
||||||
elseif $readInState == 0 then
|
|
||||||
if $readInChar == "\xFE" then
|
|
||||||
$readInState = 1
|
|
||||||
else
|
|
||||||
$engineInput($readInChar)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
$engineInput($readInChar)
|
|
||||||
$readInState = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$}
|
|
||||||
end
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
return {
|
|
||||||
read = function (fn)
|
|
||||||
local f = io.open(fn, "rb")
|
|
||||||
local d = f:read("*a")
|
|
||||||
f:close()
|
|
||||||
return d
|
|
||||||
end,
|
|
||||||
write = function (fn, data)
|
|
||||||
local f = io.open(fn, "wb")
|
|
||||||
f:write(data)
|
|
||||||
f:close()
|
|
||||||
end,
|
|
||||||
progress = function ()
|
|
||||||
io.stderr:write("00% \\")
|
|
||||||
local lastPercent = 0
|
|
||||||
local chr = 0
|
|
||||||
return function (fraction)
|
|
||||||
local percent = math.ceil(fraction * 100)
|
|
||||||
if percent ~= lastPercent then
|
|
||||||
lastPercent = percent
|
|
||||||
chr = (chr + 1) % 4
|
|
||||||
io.stderr:write(string.format("\8\8\8\8\8%02i%% %s", percent, ("\\|/-"):sub(chr + 1, chr + 1)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
@ -1,191 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- This library helps in crunching down the installer a bit further.
|
|
||||||
local sequences = {
|
|
||||||
{"\n", " "},
|
|
||||||
{" ", " "},
|
|
||||||
{" #", "#"},
|
|
||||||
{"# ", "#"},
|
|
||||||
{" ,", ","},
|
|
||||||
{", ", ","},
|
|
||||||
{" (", "("},
|
|
||||||
{"( ", "("},
|
|
||||||
{" )", ")"},
|
|
||||||
{") ", ")"},
|
|
||||||
{" {", "{"},
|
|
||||||
{"{ ", "{"},
|
|
||||||
{" }", "}"},
|
|
||||||
{"} ", "}"},
|
|
||||||
{" <", "<"},
|
|
||||||
{"< ", "<"},
|
|
||||||
{" >", ">"},
|
|
||||||
{"> ", ">"},
|
|
||||||
{" *", "*"},
|
|
||||||
{"* ", "*"},
|
|
||||||
{" ~", "~"},
|
|
||||||
{"~ ", "~"},
|
|
||||||
{" /", "/"},
|
|
||||||
{"/ ", "/"},
|
|
||||||
{" %", "%"},
|
|
||||||
{"% ", "%"},
|
|
||||||
{" =", "="},
|
|
||||||
{"= ", "="},
|
|
||||||
{" -", "-"},
|
|
||||||
{"- ", "-"},
|
|
||||||
{" +", "+"},
|
|
||||||
{"+ ", "+"},
|
|
||||||
{".. ", ".."},
|
|
||||||
{" ..", ".."},
|
|
||||||
{"\"\" ", "\"\""},
|
|
||||||
{"=0 t", "=0t"},
|
|
||||||
{">0 t", ">0t"},
|
|
||||||
{">1 t", ">1t"},
|
|
||||||
{"=1 w", "=1w"},
|
|
||||||
{"=380 l", "=380l"},
|
|
||||||
{"=127 t", "=127t"},
|
|
||||||
{"<128 t", "<128t"},
|
|
||||||
{"=128 t", "=128t"},
|
|
||||||
{">255 t", ">255t"},
|
|
||||||
{"=512 t", "=512t"}
|
|
||||||
}
|
|
||||||
|
|
||||||
local function pass(buffer)
|
|
||||||
local ob = ""
|
|
||||||
local smode = false
|
|
||||||
while #buffer > 0 do
|
|
||||||
if not smode then
|
|
||||||
local ds = true
|
|
||||||
while ds do
|
|
||||||
ds = false
|
|
||||||
for _, v in ipairs(sequences) do
|
|
||||||
if buffer:sub(1, #(v[1])) == v[1] then
|
|
||||||
buffer = v[2] .. buffer:sub(#(v[1]) + 1)
|
|
||||||
ds = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local ch = buffer:sub(1, 1)
|
|
||||||
buffer = buffer:sub(2)
|
|
||||||
ob = ob .. ch
|
|
||||||
if ch == "\"" then
|
|
||||||
smode = not smode
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ob
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Context creation --
|
|
||||||
return function ()
|
|
||||||
local forwardSymTab = {}
|
|
||||||
local reverseSymTab = {}
|
|
||||||
|
|
||||||
local temporaryPool = {}
|
|
||||||
|
|
||||||
local stackFrames = {}
|
|
||||||
|
|
||||||
local log = {}
|
|
||||||
|
|
||||||
local possible = {}
|
|
||||||
for i = 1, 52 do
|
|
||||||
possible[i] = ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"):sub(i, i)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allocate(reason)
|
|
||||||
for _, v in pairs(possible) do
|
|
||||||
if not reverseSymTab[v] then
|
|
||||||
reverseSymTab[v] = reason
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function allocTmp(id)
|
|
||||||
assert(not forwardSymTab[id], "var already exists: " .. id)
|
|
||||||
local val = table.remove(temporaryPool, 1)
|
|
||||||
if not val then val = allocate("temporary") end
|
|
||||||
forwardSymTab[id] = val
|
|
||||||
table.insert(log, "allocTmp " .. id .. " -> " .. val)
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
|
|
||||||
local lexCrunch = {}
|
|
||||||
function lexCrunch.dump(file)
|
|
||||||
file:write("forward table:\n")
|
|
||||||
for k, v in pairs(forwardSymTab) do
|
|
||||||
file:write(k .. " -> " .. v .. "\n")
|
|
||||||
end
|
|
||||||
file:write("reverse table (where differing):\n")
|
|
||||||
for k, v in pairs(reverseSymTab) do
|
|
||||||
if forwardSymTab[v] ~= k then
|
|
||||||
file:write(v .. " -> " .. k .. "\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
file:write("log:\n")
|
|
||||||
for k, v in ipairs(log) do
|
|
||||||
file:write(v .. "\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function lexCrunch.process(op, defines)
|
|
||||||
-- symbol replacement
|
|
||||||
op = op:gsub("%$[%$a-z%{%}%|A-Z0-9]*", function (str)
|
|
||||||
if str:sub(2, 2) == "$" then
|
|
||||||
-- defines
|
|
||||||
assert(defines[str], "no define " .. str)
|
|
||||||
return defines[str]
|
|
||||||
end
|
|
||||||
local com = {}
|
|
||||||
for v in str:sub(2):gmatch("[^%|]*") do
|
|
||||||
table.insert(com, v)
|
|
||||||
end
|
|
||||||
if com[1] == "L" then
|
|
||||||
assert(#com == 2)
|
|
||||||
local id = "$" .. com[2]
|
|
||||||
assert(stackFrames[1], "allocation of " .. id .. " outside of stack frame")
|
|
||||||
table.insert(stackFrames[1], id)
|
|
||||||
return allocTmp(id)
|
|
||||||
elseif com[1] == "{" then
|
|
||||||
assert(#com == 1)
|
|
||||||
table.insert(stackFrames, 1, {})
|
|
||||||
return ""
|
|
||||||
elseif com[1] == "}" then
|
|
||||||
assert(#com == 1)
|
|
||||||
for _, id in ipairs(table.remove(stackFrames, 1)) do
|
|
||||||
table.insert(temporaryPool, forwardSymTab[id])
|
|
||||||
forwardSymTab[id] = nil
|
|
||||||
end
|
|
||||||
return ""
|
|
||||||
else
|
|
||||||
assert(#com == 1)
|
|
||||||
local id = "$" .. com[1]
|
|
||||||
-- normal handling
|
|
||||||
if forwardSymTab[id] then
|
|
||||||
return forwardSymTab[id]
|
|
||||||
end
|
|
||||||
local v = allocate(id)
|
|
||||||
forwardSymTab[id] = v
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
-- comment removal
|
|
||||||
while true do
|
|
||||||
local np = op:gsub("%-%-[^\n]*\n", " ")
|
|
||||||
np = np:gsub("%-%-[^\n]*$", "")
|
|
||||||
if np == op then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
op = np
|
|
||||||
end
|
|
||||||
-- stripping
|
|
||||||
while true do
|
|
||||||
local np = pass(op)
|
|
||||||
if np == op then
|
|
||||||
return np
|
|
||||||
end
|
|
||||||
op = np
|
|
||||||
end
|
|
||||||
return op
|
|
||||||
end
|
|
||||||
return lexCrunch
|
|
||||||
end
|
|
@ -1,36 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- Status Screen --
|
|
||||||
local target = ...
|
|
||||||
local u = require("libs.frw")
|
|
||||||
local instSize = #u.read(target)
|
|
||||||
|
|
||||||
local status = ""
|
|
||||||
local statusDetail = ""
|
|
||||||
local blinkI = ""
|
|
||||||
if instSize > 65536 then
|
|
||||||
blinkI = "5;31;"
|
|
||||||
status = " DO NOT SHIP "
|
|
||||||
statusDetail = "The installer is too big to ship safely.\nIt's possible it may crash on Tier 1 systems.\nUpgrade the compression system or remove existing code."
|
|
||||||
elseif instSize > 64000 then
|
|
||||||
blinkI = "33;"
|
|
||||||
status = " Shippable * "
|
|
||||||
statusDetail = "The installer is getting dangerously large.\nReserve further room for bugfixes."
|
|
||||||
else
|
|
||||||
blinkI = "32;"
|
|
||||||
status = " All Green "
|
|
||||||
statusDetail = "The installer is well within budget with room for features.\nDevelop as normal."
|
|
||||||
end
|
|
||||||
io.stderr:write("\n")
|
|
||||||
local ctS, ctM, ctE = " \x1b[1;" .. blinkI .. "7m", "\x1b[0;7m", "\x1b[0m\n"
|
|
||||||
io.stderr:write(ctS .. " " .. ctM .. " " .. ctE)
|
|
||||||
io.stderr:write(ctS .. status .. ctM .. string.format(" %07i ", 65536 - instSize) .. ctE)
|
|
||||||
io.stderr:write(ctS .. " " .. ctM .. " " .. ctE)
|
|
||||||
io.stderr:write("\n")
|
|
||||||
io.stderr:write(statusDetail .. "\n")
|
|
||||||
io.stderr:write("\n")
|
|
||||||
io.stderr:write("Size: " .. instSize .. "\n")
|
|
||||||
io.stderr:write(" max. 65536\n")
|
|
||||||
io.stderr:write("\n")
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
# The Symbol Guide
|
|
||||||
|
|
||||||
## lexCrunch commands
|
|
||||||
|
|
||||||
The following prefixes are really special,
|
|
||||||
and are lexcrunch's responsibility:
|
|
||||||
|
|
||||||
"$$THING" : These are defines.
|
|
||||||
"$Thing" : Writes a global into stream. If not already allocated, is allocated a global.
|
|
||||||
|
|
||||||
"${" : Opens a frame.
|
|
||||||
"$}" : Closes a frame. (Attached temps are released.)
|
|
||||||
"$L|THING" : Allocates THING from temp pool, attaches to stack frame, writes to stream.
|
|
||||||
Use inside a comment to erase the written symbol
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
The rest are convention:
|
|
||||||
"$iThing" symbols are Installer Wrapper.
|
|
||||||
"$icThing" symbols are Installer Core.
|
|
||||||
"$dfThing" symbols are DEFLATE Engine.
|
|
||||||
"$bdThing" symbols are BDIVIDE Engine.
|
|
||||||
|
|
||||||
"$a0", "$a1", etc. are Local Symbols.
|
|
||||||
DEPRECATED, THESE ARE AN OLD MECHANISM, USE FRAMED TEMPS INSTEAD.
|
|
||||||
These are reserved only for use in locals.
|
|
||||||
(For loops count.)
|
|
||||||
|
|
||||||
"$lThing" symbols are used to name Local Symbols using aliases.
|
|
||||||
|
|
||||||
NO THEY ARE NOW USED FOR ALL TEMPS, INCLUDING LOCAL SYMBOLS
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
-- This is released into the public domain.
|
|
||||||
-- No warranty is provided, implied or otherwise.
|
|
||||||
|
|
||||||
-- Example compression engine.
|
|
||||||
-- Given: data, lexCrunch
|
|
||||||
-- returns compressionEngine, compressedData
|
|
||||||
return function (data, lexCrunch)
|
|
||||||
return lexCrunch.process(" $engineInput = $engineOutput ", {}), data
|
|
||||||
end
|
|
||||||
|
|
97
insthead.lua
Normal file
97
insthead.lua
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
-- KOSNEO inst.
|
||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
C, O, G, D = component, computer
|
||||||
|
assert(C, "To install, please copy as init.lua to a blank disk or a system to update, then remove all other disks and reboot.")
|
||||||
|
|
||||||
|
sa = C.list("screen", true)()
|
||||||
|
if sa then
|
||||||
|
G = C.list("gpu", true)()
|
||||||
|
if G then
|
||||||
|
G = C.proxy(G)
|
||||||
|
G.bind(sa)
|
||||||
|
G.setForeground(0xFFFFFF)
|
||||||
|
G.setBackground(0x000000)
|
||||||
|
G.setResolution(50, 5)
|
||||||
|
G.setDepth(1)
|
||||||
|
G.fill(1, 1, 50, 5, " ")
|
||||||
|
G.setBackground(0xFFFFFF)
|
||||||
|
G.setForeground(0x000000)
|
||||||
|
G.fill(1, 2, 50, 1, " ")
|
||||||
|
G.set(2, 2, "KittenOS NEO Installer")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
D = C.proxy(O.getBootAddress())
|
||||||
|
|
||||||
|
tFN,tFSR,tW,tF="Starting...",0,0
|
||||||
|
|
||||||
|
function tO(oct)
|
||||||
|
local v = oct:byte(#oct) - 0x30
|
||||||
|
if #oct > 1 then
|
||||||
|
return (tO(oct:sub(1, #oct - 1)) * 8) + v
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
function tA(s)
|
||||||
|
if tW > 0 then
|
||||||
|
tW = tW - 1
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if tF then
|
||||||
|
local ta = math.min(512, tFSR)
|
||||||
|
D.write(tF, s:sub(1, ta))
|
||||||
|
tFSR = tFSR - ta
|
||||||
|
if tFSR == 0 then
|
||||||
|
D.close(tF)
|
||||||
|
tF = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
tFN = s:sub(1, 100):gsub("\x00", "")
|
||||||
|
local sz = tO(s:sub(125, 135))
|
||||||
|
if tFN:sub(1, 5) ~= "code/" then
|
||||||
|
tW = math.ceil(sz / 512)
|
||||||
|
else
|
||||||
|
tFN = tFN:sub(6)
|
||||||
|
if tFN == "" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if tFN:sub(#tFN) == "/" then
|
||||||
|
tW = math.ceil(sz / 512)
|
||||||
|
D.makeDirectory(tFN)
|
||||||
|
else
|
||||||
|
tF = D.open(tFN, "wb")
|
||||||
|
tFSR = sz
|
||||||
|
if tFSR == 0 then
|
||||||
|
D.close(tF)
|
||||||
|
tF = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sN, sC = 0, 0
|
||||||
|
|
||||||
|
function sector(n)
|
||||||
|
tA(n)
|
||||||
|
sN = sN + 1
|
||||||
|
if G then
|
||||||
|
local a = sN / sC
|
||||||
|
G.fill(1, 2, 50, 1, " ")
|
||||||
|
G.set(2, 2, "KittenOS NEO Installer : " .. tFN)
|
||||||
|
G.setForeground(0xFFFFFF)
|
||||||
|
G.setBackground(0x000000)
|
||||||
|
G.fill(2, 4, 48, 1, " ")
|
||||||
|
G.setBackground(0xFFFFFF)
|
||||||
|
G.setForeground(0x000000)
|
||||||
|
G.fill(2, 4, math.ceil(48 * a), 1, " ")
|
||||||
|
end
|
||||||
|
if sN % 8 == 0 then
|
||||||
|
O.pullSignal(0.05)
|
||||||
|
end
|
||||||
|
if sN == sC then
|
||||||
|
dieCB()
|
||||||
|
O.shutdown(true)
|
||||||
|
end
|
||||||
|
end
|
@ -3,8 +3,8 @@ ocemu {
|
|||||||
components {
|
components {
|
||||||
{"gpu", "c1-gpu-tier3", 0, 160, 50, 3},
|
{"gpu", "c1-gpu-tier3", 0, 160, 50, 3},
|
||||||
{"gpu", "c1-gpu-tier1", 0, 50, 16, 1},
|
{"gpu", "c1-gpu-tier1", 0, 50, 16, 1},
|
||||||
{"screen_sdl2", "c1-screen-tier3", -1, 160, 50, 3},
|
-- {"screen_sdl2", "c1-screen-tier3", -1, 160, 50, 3},
|
||||||
-- {"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1},
|
{"screen_sdl2", "c1-screen-tier1", -1, 50, 16, 1},
|
||||||
{"modem", "c1-modem", 1, false},
|
{"modem", "c1-modem", 1, false},
|
||||||
{"eeprom", "c1-eeprom", 9, "lua/bios.lua"},
|
{"eeprom", "c1-eeprom", 9, "lua/bios.lua"},
|
||||||
{"filesystem", "c1-tmpfs", -1, "tmpfs", "tmpfs", false, 5},
|
{"filesystem", "c1-tmpfs", -1, "tmpfs", "tmpfs", false, 5},
|
||||||
|
@ -7,5 +7,5 @@ cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb tmpfs
|
|||||||
mkdir c1-sda c1-sdb
|
mkdir c1-sda c1-sdb
|
||||||
echo -n c1-sda > c1-eeprom/data.bin
|
echo -n c1-sda > c1-eeprom/data.bin
|
||||||
cd ..
|
cd ..
|
||||||
./package.sh $*
|
./package.sh
|
||||||
cp inst.lua laboratory/c1-sda/init.lua
|
cp inst.lua laboratory/c1-sda/init.lua
|
||||||
|
28
mkucinst.lua
Normal file
28
mkucinst.lua
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
os.execute("tar -cf code.tar code")
|
||||||
|
os.execute("cat insthead.lua > inst.lua")
|
||||||
|
local f = io.open("inst.lua", "ab")
|
||||||
|
|
||||||
|
local df = io.open("code.tar", "rb")
|
||||||
|
local sc = 0
|
||||||
|
while true do
|
||||||
|
local d = df:read(512)
|
||||||
|
if not d then break end
|
||||||
|
sc = sc + 1
|
||||||
|
end
|
||||||
|
df:close()
|
||||||
|
local df = io.open("code.tar", "rb")
|
||||||
|
f:write("dieCB = function () end")
|
||||||
|
f:write("sC = " .. sc .. "\n")
|
||||||
|
while true do
|
||||||
|
local d = df:read(512)
|
||||||
|
if d then
|
||||||
|
f:write(string.format("sector(%q)", d))
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
df:close()
|
||||||
|
f:close()
|
16
package.sh
16
package.sh
@ -9,15 +9,15 @@ lua claw/clawconv.lua code/data/app-claw/ < claw/code-claw.lua > /dev/null
|
|||||||
rm code.tar
|
rm code.tar
|
||||||
# Hey, look behind you, there's nothing to see here.
|
# Hey, look behind you, there's nothing to see here.
|
||||||
# ... ok, are they seriously all named "Mann"?
|
# ... ok, are they seriously all named "Mann"?
|
||||||
cd code
|
tar --mtime=0 --owner=gray:0 --group=mann:0 -cf code.tar code
|
||||||
tar --mtime=0 --owner=gray:0 --group=mann:0 -cf ../code.tar .
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# The Installer Creator
|
# Solely for ensuring that a -gold.lua file can be checked before being pushed to repository.
|
||||||
cd inst
|
echo -n "-- commit: " > inst.lua
|
||||||
lua build.lua `git status --porcelain=2 --branch | grep branch.oid | grep -E -o "[0-9a-f]*$" -` ../code.tar $* > ../inst.lua
|
git status --porcelain=2 --branch | grep branch.oid >> inst.lua
|
||||||
lua status.lua ../inst.lua
|
lua heroes.lua `wc -c code.tar` | lua com2/bonecrunch.lua >> inst.lua
|
||||||
cd ..
|
echo -n "--[[" >> inst.lua
|
||||||
|
cat com2/code.tar.bd >> inst.lua
|
||||||
|
echo -n "]]" >> inst.lua
|
||||||
|
|
||||||
# Common Repository Setup Code
|
# Common Repository Setup Code
|
||||||
./package-repo.sh inst.lua
|
./package-repo.sh inst.lua
|
||||||
|
609
preSH-Ancient-Est-2-10-2017.lua
Normal file
609
preSH-Ancient-Est-2-10-2017.lua
Normal file
@ -0,0 +1,609 @@
|
|||||||
|
-- KOSNEO inst.
|
||||||
|
-- This is released into the public domain.
|
||||||
|
-- No warranty is provided, implied or otherwise.
|
||||||
|
|
||||||
|
-- PADPADPADPADPADPADPADPAD
|
||||||
|
|
||||||
|
local C, O, G, D = component, computer
|
||||||
|
local sAddr = C.list("screen", true)()
|
||||||
|
if sAddr then
|
||||||
|
G = C.list("gpu", true)()
|
||||||
|
if G then
|
||||||
|
G = C.proxy(G)
|
||||||
|
G.bind(sAddr)
|
||||||
|
G.setForeground(0xFFFFFF)
|
||||||
|
G.setBackground(0x000000)
|
||||||
|
G.setResolution(50, 5)
|
||||||
|
G.setDepth(1)
|
||||||
|
G.fill(1, 1, 50, 5, " ")
|
||||||
|
G.setBackground(0xFFFFFF)
|
||||||
|
G.setForeground(0x000000)
|
||||||
|
G.fill(1, 2, 50, 1, " ")
|
||||||
|
G.set(2, 2, "KittenOS NEO Installer")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
D = C.proxy(O.getBootAddress())
|
||||||
|
|
||||||
|
local file = nil
|
||||||
|
local fileName = "Starting..."
|
||||||
|
local fileSizeRm = 0
|
||||||
|
local ws = 0
|
||||||
|
|
||||||
|
local convoct
|
||||||
|
convoct = function (oct)
|
||||||
|
local v = oct:byte(#oct) - 0x30
|
||||||
|
if #oct > 1 then
|
||||||
|
return (convoct(oct:sub(1, #oct - 1)) * 8) + v
|
||||||
|
end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
local function sectorCore(sector)
|
||||||
|
if ws > 0 then
|
||||||
|
ws = ws - 1
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if file then
|
||||||
|
local takeaway = math.min(512, fileSizeRm)
|
||||||
|
D.write(file, sector:sub(1, takeaway))
|
||||||
|
fileSizeRm = fileSizeRm - takeaway
|
||||||
|
if fileSizeRm == 0 then
|
||||||
|
D.close(file)
|
||||||
|
file = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local name = sector:sub(1, 100):gsub("\x00", "")
|
||||||
|
local sz = convoct(sector:sub(125, 135))
|
||||||
|
if name:sub(1, 5) ~= "code/" then
|
||||||
|
ws = math.ceil(sz / 512)
|
||||||
|
else
|
||||||
|
if name:sub(#name, #name) == "/" then
|
||||||
|
ws = math.ceil(sz / 512)
|
||||||
|
D.makeDirectory(name:sub(6))
|
||||||
|
else
|
||||||
|
fileName = name:sub(6)
|
||||||
|
file = D.open(fileName, "wb")
|
||||||
|
fileSizeRm = sz
|
||||||
|
if file then
|
||||||
|
if fileSizeRm == 0 then
|
||||||
|
D.close(file)
|
||||||
|
file = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dieCB = function () end
|
||||||
|
|
||||||
|
local sectorNum = 0
|
||||||
|
local sectorCount = 0
|
||||||
|
|
||||||
|
local function sector(n)
|
||||||
|
sectorCore(n)
|
||||||
|
sectorNum = sectorNum + 1
|
||||||
|
if G then
|
||||||
|
local a = sectorNum / sectorCount
|
||||||
|
G.fill(1, 2, 50, 1, " ")
|
||||||
|
G.set(2, 2, "KittenOS NEO Installer : " .. fileName)
|
||||||
|
G.setForeground(0xFFFFFF)
|
||||||
|
G.setBackground(0x000000)
|
||||||
|
G.fill(2, 4, 48, 1, " ")
|
||||||
|
G.setBackground(0xFFFFFF)
|
||||||
|
G.setForeground(0x000000)
|
||||||
|
G.fill(2, 4, math.ceil(48 * a), 1, " ")
|
||||||
|
end
|
||||||
|
if sectorNum % 8 == 0 then
|
||||||
|
O.pullSignal(0.05)
|
||||||
|
end
|
||||||
|
if sectorNum == sectorCount then
|
||||||
|
dieCB()
|
||||||
|
O.shutdown(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sectorCount = 260
|
||||||
|
D.remove("init-symsear.lua")
|
||||||
|
D.rename("init.lua", "init-symsear.lua")
|
||||||
|
local instHandle = D.open("init-symsear.lua", "rb")
|
||||||
|
dieCB = function ()
|
||||||
|
D.close(instHandle)
|
||||||
|
D.remove("init-symsear.lua")
|
||||||
|
end
|
||||||
|
local syms = {" ","s","e","t","a","i","\24","(","r",".","\
|
||||||
|
","p","\"","o","c","m",", ","\1","l","n",")","d","u","\17","\9","x","-","\7","\6","\8","\4","\13","\2","\3","\5","g","\14","\21","\11"," then\
|
||||||
|
","1","w"," ","\12","\18","\22","f","F","y",",","\20","re","b","k"," = ","\23","return "," local ","\16","v"," if ","\
|
||||||
|
","\15","\19","\
|
||||||
|
"," ","[","en","/","0","]","path","nction (","\
|
||||||
|
","se","h"," =","or","S","T","le","\
|
||||||
|
local ",")\
|
||||||
|
","= fu","on"," == ","ne",")\
|
||||||
|
","functio","\
|
||||||
|
end\
|
||||||
|
","D","{"," t","n ","oc","lo"," end\
|
||||||
|
","\0\0\0\0\0\0\0\0\0","un"," i","W","\0\0\0\0\0\0","fu","et"," end\
|
||||||
|
","then ","nd","ni","A","ing"," tab","loca","etting",")\
|
||||||
|
","ct","C","P","}","\
|
||||||
|
end\
|
||||||
|
",")\
|
||||||
|
","onit","= ","end\
|
||||||
|
","\0","I","Y"," do\
|
||||||
|
","return\
|
||||||
|
","le.inser"," = func","= \"","al"," r"," e","in","he","nc"," e","j","donkonit","tion ()",") do\
|
||||||
|
"," the","\
|
||||||
|
",")\
|
||||||
|
","ur","#","+","N","cursor",".inse",", v ","nction (w"," neo.req"," for "," then\
|
||||||
|
","\0\0\0\0\0\0\0","nd\
|
||||||
|
","()\
|
||||||
|
","neo.","ath","table","l ","do","2","3",":","H"," = nil\
|
||||||
|
","nd\
|
||||||
|
e","hen\
|
||||||
|
","\7local ","indowCore",")\
|
||||||
|
end\
|
||||||
|
","d\") end\
|
||||||
|
"," = false","if ","pairs(","dow","string\"","ti","O","uestAcces","nd\
|
||||||
|
if ","icode."," if","v in ","pkg, pid","000","750\0000001","end\
|
||||||
|
e","750\0000000"," else\
|
||||||
|
","window","end","00",".neo.sys.","neoux.tc","= {}\
|
||||||
|
","(window, ","5","=","E","R",") end\
|
||||||
|
"," cursor","request","ode/app"," return e","\" the","equire("," "," then",".neo.pub.","hile true"," end"," en","\0\0","B","M"," ret","for ","in ipai"," true\
|
||||||
|
","close","code.sub","error(\"","return t","oroutine"," end\
|
||||||
|
if","end\
|
||||||
|
en","tion ","\", funct",":sub(","vailable"," end\
|
||||||
|
"," l"," == \"","prima"," if type(","ryWindow","window.s"," end\
|
||||||
|
","L","X","~","on ("," in ipair"," for _, v"," for k","\0\0\0\0\0cod","lose()\
|
||||||
|
"," = funct","rror(\"Exp","nsurePath","s.primary","primary","buildingS","unic"," "," re","surfaces","disallowe","ackground","neoux.","ccess","selectUnk"," end\
|
||||||
|
"," = uni","\
|
||||||
|
end\
|
||||||
|
"," f","7","Z","z","for k","rue\
|
||||||
|
end\
|
||||||
|
","ode.len("," end\
|
||||||
|
","lse\
|
||||||
|
",") end","end\
|
||||||
|
"," fu",":sub(1, ","sub(1, 4)"," ","neo","the","if not "," th","tion","unknownA","end\
|
||||||
|
","[1] == \"","= unico","Acces","\
|
||||||
|
end\
|
||||||
|
\
|
||||||
|
l","n\
|
||||||
|
","\") end\
|
||||||
|
","de.len("," end","\" then\
|
||||||
|
","0\0000001","urface","nd\
|
||||||
|
","()\
|
||||||
|
","(surfaces"," if ","\0\0\0\0\0\0\0\0","unc","urn","\
|
||||||
|
"," end\
|
||||||
|
"," neoux","ction","\
|
||||||
|
end\
|
||||||
|
","\
|
||||||
|
","neoux","\24\0\0\0\0\0\0\0\0","\
|
||||||
|
end"," end\
|
||||||
|
end\
|
||||||
|
","\
|
||||||
|
end\
|
||||||
|
"," if "," err","s[1] == \"","unicode."," window"," if ","ocal fun","= false","\0\0\0\0\0\0\0000","\0\0\0\0\0\0\00000","code","_, v in i","()\
|
||||||
|
","d\
|
||||||
|
","f ev == \""," return",", bg, fg"," end"," neoux.","\0\0\0","w.close(","\
|
||||||
|
if ev"," i"," if not ","if kc == ",")\
|
||||||
|
end\
|
||||||
|
","indow","onkonit","00175","table.",", bg, fg)"," l"," end\
|
||||||
|
",") == \"","d\
|
||||||
|
"," return ","rn","ca","q"," tabl"," error(\"","end\
|
||||||
|
re"," in ","hen err","nd\
|
||||||
|
en","nd\
|
||||||
|
","\
|
||||||
|
end","turn ","x.neo.","ion ("," table","false","string","e.len(","d\
|
||||||
|
"," re","1, unicod","cursorX ","local ","end\
|
||||||
|
end\
|
||||||
|
","cal","\" then e","nd\
|
||||||
|
if k","ion","00644\00000"," end\
|
||||||
|
","\
|
||||||
|
end"," window."," e","if not","== \"",", func"," neo.",", functi","\
|
||||||
|
end\
|
||||||
|
end"," r","end\
|
||||||
|
","ion (w)\
|
||||||
|
","\
|
||||||
|
end"," = false\
|
||||||
|
"," ret","tu"," end\
|
||||||
|
","f ","unction","= nil\
|
||||||
|
","th","n\
|
||||||
|
","6","U","_","requir","eturn\
|
||||||
|
"," funct","eturn tr","\
|
||||||
|
\
|
||||||
|
local"," table.","eques","rn ",")\
|
||||||
|
r",".insert(","ode.",")\
|
||||||
|
end","== ","\0\0\0\0\0\0\0c","n\
|
||||||
|
","\0\0\0\0\0","()\
|
||||||
|
"," = nil","able.","n\
|
||||||
|
"," = n","return","000644\0000","Access","able","etu","d\
|
||||||
|
","\
|
||||||
|
if ","end\
|
||||||
|
end","nction (p","ub(1, 4) "," return "," return","lse\
|
||||||
|
","abl","= uni","for k, ","\0\0\0\0\0\0\0\0c","cursorY","ble","bg, fg)\
|
||||||
|
","\
|
||||||
|
e","ind","ret","tring\"","000000"," neo","pairs","then\
|
||||||
|
",")\
|
||||||
|
","le.inse","loc","\
|
||||||
|
end","n error","\
|
||||||
|
end\
|
||||||
|
\
|
||||||
|
","if s[1] =","lse\
|
||||||
|
","turn","ursor","function","neou","\0\0\0\0\0\0c","function ","\0000001","end\
|
||||||
|
e","eo.","Access(\""," re"," lo","\
|
||||||
|
e",")\
|
||||||
|
end","urn ","\
|
||||||
|
re"," end\
|
||||||
|
e"," = f","\0\0\0\0","cal ","\0000000644\0","in ip","\
|
||||||
|
en"," return",")\
|
||||||
|
i","ction ","\
|
||||||
|
end\
|
||||||
|
","ode","equire(\"","r(\"Expect","ctio"," cursorY","if","%","4","<","G","\
|
||||||
|
local f","\
|
||||||
|
ret"," for ","d\
|
||||||
|
if"," erro","true\
|
||||||
|
end","ed\") end","hen ","nd\
|
||||||
|
en","al ","on ","] then\
|
||||||
|
","string\")","for _, ","unicode.l","[1] == ","true\
|
||||||
|
","uestAc","nd\
|
||||||
|
end\
|
||||||
|
"," for k, "," if ev ","then\
|
||||||
|
","\
|
||||||
|
en",")\
|
||||||
|
en","do\
|
||||||
|
","e.ins",".primary"," true","coroutine","return\
|
||||||
|
","airs(",") end\
|
||||||
|
","nd\
|
||||||
|
end\
|
||||||
|
\
|
||||||
|
","\
|
||||||
|
return","window, ","end\
|
||||||
|
e","end\
|
||||||
|
end","750\0000","eturn t",", functio"," e","d\") end","en\
|
||||||
|
","ocal","icode.len","e\
|
||||||
|
","n\
|
||||||
|
","w.close()"," uni","sub(","n ipairs("," for ","end\
|
||||||
|
","ion ()","end\
|
||||||
|
en","quest","cursorY ","eturn","unicode.s","x.neo.pub"," = neo","hen\
|
||||||
|
","then\
|
||||||
|
","string\") ","in ipa"," retur","indowCor"," re","750\00000"," do\
|
||||||
|
",")\
|
||||||
|
if "," then ret","\") end"," en","n\
|
||||||
|
","ipairs"," then err","d\
|
||||||
|
en","= f"," local",".neo.","\24\0\0\0\0\0\0\0","func","()\
|
||||||
|
",")\
|
||||||
|
en","curs","\
|
||||||
|
loca","ode/apps","nd\
|
||||||
|
if "," i"," = neo.r","kg, pid, ","\
|
||||||
|
i","win","code.sub(","require","wind"," else\
|
||||||
|
","close()"," end\
|
||||||
|
e","\
|
||||||
|
\
|
||||||
|
local "," then re","\
|
||||||
|
e",".request","wnAvailab","tion (","\
|
||||||
|
local ","error(","\0000001750\0","n\
|
||||||
|
","d\
|
||||||
|
"," ","uestA","reques","end\
|
||||||
|
end\
|
||||||
|
\
|
||||||
|
","ion ()\
|
||||||
|
"," curso","then\
|
||||||
|
","0001750","surfac",".close("," function","= neo.","if type("," loc","d\
|
||||||
|
e","oroutine."," do\
|
||||||
|
"," else\
|
||||||
|
","tion ()\
|
||||||
|
",", v in ","window.","neo.re","0000","\000000","\
|
||||||
|
end\
|
||||||
|
","ipairs("," ret","\"x.neo.pu","error","\
|
||||||
|
i","\
|
||||||
|
end","()\
|
||||||
|
","= nil\
|
||||||
|
","nsert(","n erro","rror(\"","nil\
|
||||||
|
","cursorX ="," do\
|
||||||
|
"," for","turn f","en\
|
||||||
|
"," table.","\
|
||||||
|
","\") end\
|
||||||
|
","\") end\
|
||||||
|
",".close()\
|
||||||
|
","\
|
||||||
|
re","d\
|
||||||
|
e","\
|
||||||
|
end\
|
||||||
|
","ownAvaila","000644\00000"," false\
|
||||||
|
","\
|
||||||
|
re","false\
|
||||||
|
","ion ()\
|
||||||
|
",")\
|
||||||
|
e","urn end\
|
||||||
|
",")\
|
||||||
|
if","x.neo.sys","indow, ","then\
|
||||||
|
",")\
|
||||||
|
if t","cti","ion ","ion (w","\" then"," = nil\
|
||||||
|
","then","e\" then\
|
||||||
|
"," if","on (w)\
|
||||||
|
",") do\
|
||||||
|
"," en","tAccess(\"","surePath"," end\
|
||||||
|
end","\
|
||||||
|
end\
|
||||||
|
","e.inse"," table.i"," local","oca","n (","0 then\
|
||||||
|
",") end\
|
||||||
|
"," loc","se\
|
||||||
|
","do\
|
||||||
|
","nd\
|
||||||
|
end\
|
||||||
|
"," then e","0000644\0","ion ()\
|
||||||
|
","ocal ","end\
|
||||||
|
if ","e\
|
||||||
|
"," then\
|
||||||
|
"," local","icode.le","\" then "," ==","] == \"","eoux","ndow","\0\0\0\0\0c","nownAvail"," functi","0\000000000","eoux.tc","hen error"," = neo.","table.ins"," window","(window","d\
|
||||||
|
if ","\
|
||||||
|
if ","\
|
||||||
|
local","end\
|
||||||
|
e","nd\
|
||||||
|
end","insert("," local ","k, v i","surface","eturn ","\
|
||||||
|
loc","sub(1, ","end\
|
||||||
|
if ","io","!","$","&","'","*","8","9",";",">","?","@","J","K","Q","V","\\","^","|","<22>","…","ˆ","‰","Œ","<22>","Ž","<22>","<22>","’","“","”","˜","¦","¬","¼","½","Â","ï",}
|
||||||
|
local bytBuf = ""
|
||||||
|
local bitBuf = ""
|
||||||
|
local function getByte()
|
||||||
|
if bytBuf == "" then
|
||||||
|
bytBuf = D.read(instHandle, 64)
|
||||||
|
end
|
||||||
|
local r = bytBuf:byte()
|
||||||
|
bytBuf = bytBuf:sub(2)
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
if getByte() == 0 then break end
|
||||||
|
end
|
||||||
|
local function pb(c, p) if c % (p * 2) ~= c % p then bitBuf = bitBuf .. "1" else bitBuf = bitBuf .. "0" end end
|
||||||
|
local stn = 0
|
||||||
|
local function getBit()
|
||||||
|
if bitBuf == "" then
|
||||||
|
local c = getByte()
|
||||||
|
c = (c - stn) % 256 stn = stn + 3
|
||||||
|
pb(c, 1)
|
||||||
|
pb(c, 2)
|
||||||
|
pb(c, 4)
|
||||||
|
pb(c, 8)
|
||||||
|
pb(c, 16)
|
||||||
|
pb(c, 32)
|
||||||
|
pb(c, 64)
|
||||||
|
pb(c, 128)
|
||||||
|
end
|
||||||
|
local bit = bitBuf:sub(1, 1) == "1"
|
||||||
|
bitBuf = bitBuf:sub(2)
|
||||||
|
return bit
|
||||||
|
end
|
||||||
|
local buf = ""
|
||||||
|
local mode = false
|
||||||
|
local bc2 = 10
|
||||||
|
while true do
|
||||||
|
local bc = getBit()
|
||||||
|
local v = 0
|
||||||
|
if bc then bc = bc2 v = 64 else bc = 6 end
|
||||||
|
for bit = 0, bc - 1 do
|
||||||
|
if getBit() then v = v + (2 ^ bit) end
|
||||||
|
end
|
||||||
|
buf = buf .. syms[v]
|
||||||
|
if mode then
|
||||||
|
while #buf >= 512 do
|
||||||
|
sector(buf:sub(1, 512))
|
||||||
|
buf = buf:sub(513)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if #buf == 27939 then
|
||||||
|
stn = 0
|
||||||
|
bc2 = 11
|
||||||
|
bitBuf = ""
|
||||||
|
syms = {}
|
||||||
|
while #buf > 0 do
|
||||||
|
local len = buf:byte()
|
||||||
|
if len > 127 then error("symlen") end
|
||||||
|
buf = buf:sub(2)
|
||||||
|
local ch = buf:sub(1, len)
|
||||||
|
buf = buf:sub(len + 1)
|
||||||
|
table.insert(syms, ch)
|
||||||
|
end
|
||||||
|
mode = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--[[ |