mirror of
https://github.com/20kdc/OC-KittenOS.git
synced 2024-11-23 10:58:06 +11:00
Bigram compression for fun and size reduction
This commit is contained in:
parent
f5ba0489b2
commit
d2ee505316
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,8 +1,6 @@
|
||||
# This is released into the public domain.
|
||||
# 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/data/app-claw/*
|
||||
work.tar
|
||||
@ -32,7 +30,7 @@ laboratory/*/*/*/*
|
||||
inst.lua
|
||||
# Available as the respective release
|
||||
inst-gold.lua
|
||||
com2/code.tar.bd
|
||||
inst/code.tar.bd
|
||||
upldr.sh
|
||||
upldr-dev.sh
|
||||
upldr-gold.sh
|
||||
|
@ -1,49 +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.
|
||||
|
||||
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
|
||||
|
@ -1,72 +0,0 @@
|
||||
-- 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")
|
@ -1,20 +0,0 @@
|
||||
-- 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
27
heroes.lua
@ -1,27 +0,0 @@
|
||||
-- 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
|
36
inst/bdivide/bga.lua
Normal file
36
inst/bdivide/bga.lua
Normal file
@ -0,0 +1,36 @@
|
||||
-- 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
|
118
inst/bdivide/compress.lua
Normal file
118
inst/bdivide/compress.lua
Normal file
@ -0,0 +1,118 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- PREPROC (r9 edition): preprocess input to be 7-bit
|
||||
|
||||
local
|
||||
-- SHARED WITH DECOMPRESSION ENGINE
|
||||
function p(x, y)
|
||||
if x == 126 then
|
||||
if y >= 32 then
|
||||
return ({
|
||||
-- Before adding to this, check how installer size is changed.
|
||||
"\x7E", "\x7F"
|
||||
})[y - 31], 3
|
||||
end
|
||||
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(math.floor(x / 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 preproc(blk)
|
||||
local out = ""
|
||||
while blk ~= "" do
|
||||
local len = math.min(preprocMaxLen, #blk)
|
||||
while len > 0 do
|
||||
local seg = blk:sub(1, len)
|
||||
if preprocParts[seg] then
|
||||
out = out .. preprocParts[seg]
|
||||
blk = blk:sub(#seg + 1)
|
||||
break
|
||||
end
|
||||
len = len - 1
|
||||
end
|
||||
assert(len ~= 0)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- 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 function bdivide(blk)
|
||||
local out = ""
|
||||
|
||||
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!
|
||||
out = out .. bestData
|
||||
crop(bestRes)
|
||||
blk = blk:sub(#bestRes + 1)
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
return function (data)
|
||||
data = preproc(data)
|
||||
io.stderr:write("---\n")
|
||||
data = bdivide(data)
|
||||
return data
|
||||
end
|
85
inst/bdivide/instdeco.lua
Normal file
85
inst/bdivide/instdeco.lua
Normal file
@ -0,0 +1,85 @@
|
||||
-- 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
|
||||
|
||||
-- cb: sector accumulator
|
||||
-- ct: preproc accumulator
|
||||
-- cc: bdivide accumulator
|
||||
-- cw: bdivide window
|
||||
|
||||
-- cp: function to submit to preproc
|
||||
-- cd: function to submit to bdivide
|
||||
|
||||
cb,ct,cc,cw="","","",("\x00"):rep(2^16)
|
||||
-- High-level breakdown:
|
||||
-- CP is unescaper & TAR-sector-breakup.
|
||||
-- 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 Ct (input buffer) and Cp (output buffer).
|
||||
-- Ignore its second argument, as that's a lie, it's just there for a local.
|
||||
-- CD is the actual decompressor. It has the same quirk as CP, wanting two more bytes.
|
||||
-- It stores to Cc (compressed), and Cw (window).
|
||||
-- It outputs that which goes to the window to CP also.
|
||||
-- And it also uses a fake local.
|
||||
|
||||
-- SEE compress.lua FOR THIS FUNCTION
|
||||
function p(x, y)
|
||||
if x == 126 then
|
||||
if y >= 32 then
|
||||
return ({
|
||||
-- Before adding to this, check how installer size is changed.
|
||||
"\x7E", "\x7F"
|
||||
})[y - 31], 3
|
||||
end
|
||||
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(math.floor(x / 5) + 1)), 2
|
||||
end
|
||||
|
||||
function cp(d, b, a)
|
||||
ct = ct .. d
|
||||
while #ct > 1 do
|
||||
b, a = p(ct:byte(), ct:byte(2))
|
||||
cb = cb .. b
|
||||
ct = ct:sub(a)
|
||||
if #cb > 511 then
|
||||
M(cb:sub(1, 512))
|
||||
cb = cb:sub(513)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cd(d, b, p)
|
||||
cc = cc .. d
|
||||
while #cc > 2 do
|
||||
b = cc:byte()
|
||||
if 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
|
||||
|
||||
-- quick & dirty integration with the existing stuff
|
||||
function L(d)
|
||||
if not d then
|
||||
cd("\x00\x00")cp("\x00\x00")
|
||||
else
|
||||
cd(d)
|
||||
end
|
||||
end
|
||||
|
31
inst/build.lua
Normal file
31
inst/build.lua
Normal file
@ -0,0 +1,31 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- KittenOS NEO Installer Generator --
|
||||
local alg, tarName = ...
|
||||
|
||||
local function read(fn)
|
||||
local f = io.open(fn, "rb")
|
||||
local d = f:read("*a")
|
||||
f:close()
|
||||
return d
|
||||
end
|
||||
|
||||
local tarData = read(tarName)
|
||||
local tarSectors = math.floor(#tarData / 512)
|
||||
|
||||
local instCode = "K=" .. tarSectors .. "\n" .. read(alg .. "/instdeco.lua") .. read("instbase.lua")
|
||||
instCode = require("libs.lexcrunch")(instCode)
|
||||
io.write(instCode)
|
||||
|
||||
-- the \x00 is the indicator to start reading
|
||||
io.write("--[[\x00")
|
||||
io.stderr:write("compressing...\n")
|
||||
local compressedData = require(alg .. ".compress")(tarData)
|
||||
io.stderr:write("compression with " .. alg .. ": " .. #tarData .. " -> " .. #compressedData .. "\n")
|
||||
-- Program the read-in state machine
|
||||
compressedData = compressedData:gsub("\xFE", "\xFE\xFE")
|
||||
compressedData = compressedData:gsub("]]", "]\xFE]")
|
||||
io.write(compressedData)
|
||||
io.write("]]")
|
||||
|
145
inst/instbase.lua
Normal file
145
inst/instbase.lua
Normal file
@ -0,0 +1,145 @@
|
||||
-- KOSNEO installer base
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
-- DECOMPRESSION ENGINE PRECEDES THIS CODE --
|
||||
-- NOTE: upper-case is reserved for this file,
|
||||
-- lower-case is reserved for the decompression engine
|
||||
|
||||
-- A: temporary
|
||||
|
||||
-- B: computer
|
||||
-- C: component
|
||||
|
||||
-- D: additional temporary
|
||||
-- E: read-in state machine
|
||||
|
||||
-- F: current file: filename
|
||||
-- H: remaining bytes to copy/skip
|
||||
-- I: current file: handle (nil if not writing)
|
||||
|
||||
-- J: sectors handled
|
||||
-- K: sector count (injected during build)
|
||||
-- L: compression engine data function (set by CE)
|
||||
-- M: sector handler function (called by CE)
|
||||
|
||||
-- O: current character for read-in state machine
|
||||
-- P: file handle for selfread
|
||||
|
||||
-- Q: octal decoding function
|
||||
|
||||
-- X: screen address
|
||||
-- Y: component: gpu
|
||||
-- Z: component: filesystem
|
||||
B = computer
|
||||
C = component
|
||||
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.")
|
||||
|
||||
X = C.list("screen", true)()
|
||||
Y = C.list("gpu", true)()
|
||||
|
||||
Z = C.proxy(B.getBootAddress())
|
||||
|
||||
Z.remove("init.neoi.lua")
|
||||
Z.rename("init.lua","init.neoi.lua")
|
||||
P = Z.open("init.neoi.lua","rb")
|
||||
|
||||
F = "Starting..."
|
||||
H = 0
|
||||
|
||||
if X and Y then
|
||||
Y = C.proxy(Y)
|
||||
Y.bind(X)
|
||||
Y.setResolution(50, 5)
|
||||
Y.setBackground(2^24-1)
|
||||
Y.setForeground(0)
|
||||
Y.fill(1, 1, 50, 5, "█")
|
||||
Y.fill(1, 2, 50, 1, " ")
|
||||
Y.set(2, 2, "KittenOS NEO Installer")
|
||||
end
|
||||
|
||||
function Q(A)
|
||||
if A == "" then return 0 end
|
||||
return Q(A:sub(1, -2)) * 8 + (A:byte(#A) - 48)
|
||||
end
|
||||
|
||||
J = 0
|
||||
|
||||
function M(n)
|
||||
if H > 0 then
|
||||
A = math.min(512, H)
|
||||
H = H - A
|
||||
if I then
|
||||
Z.write(I, n:sub(1, A))
|
||||
if H <= 0 then
|
||||
Z.close(I)
|
||||
I = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
F = n:sub(1, 100):gsub("\x00", "")
|
||||
-- this sets up the reading/skipping of data
|
||||
H = Q(n:sub(125, 135))
|
||||
if F:sub(1, 2) == "./" and F ~= "./" then
|
||||
F = F:sub(3)
|
||||
if F:sub(#F) == "/" then
|
||||
Z.makeDirectory(F)
|
||||
else
|
||||
I = Z.open(F, "wb")
|
||||
if H == 0 then
|
||||
Z.close(I)
|
||||
I = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- UPDATE DISPLAY --
|
||||
J = J + 1
|
||||
if X and Y then
|
||||
Y.fill(1, 2, 50, 1, " ")
|
||||
Y.set(2, 2, "KittenOS NEO Installer : " .. F)
|
||||
Y.fill(2, 4, 48, 1, "█")
|
||||
Y.fill(2, 4, math.ceil(48 * J / K), 1, " ")
|
||||
end
|
||||
if J % 8 == 0 then
|
||||
B.pullSignal(0.01)
|
||||
end
|
||||
if J == K then
|
||||
Z.close(P)
|
||||
Z.remove("init.neoi.lua")
|
||||
B.shutdown(true)
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
A = Z.read(P, 64)
|
||||
if not A then
|
||||
L()
|
||||
-- IF WE GET HERE,
|
||||
-- YOU BROKE SOMETHING!
|
||||
A()
|
||||
end
|
||||
D = ""
|
||||
for i = 1, #A do
|
||||
-- Read-in state machine
|
||||
O = A:sub(i, i)
|
||||
if not E then
|
||||
if O == "\x00" then
|
||||
E = 0
|
||||
end
|
||||
elseif E == 0 then
|
||||
if O == "\xFE" then
|
||||
E = 1
|
||||
else
|
||||
D = D .. O
|
||||
end
|
||||
else
|
||||
D = D .. O
|
||||
E = 0
|
||||
end
|
||||
end
|
||||
L(D)
|
||||
end
|
||||
|
||||
-- COMPRESSED DATA FOLLOWS THIS CODE --
|
||||
|
@ -1,13 +1,7 @@
|
||||
-- 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
|
||||
|
||||
-- This library helps in crunching down the installer a bit further.
|
||||
local sequences = {
|
||||
{"\n", " "},
|
||||
{" ", " "},
|
||||
@ -77,12 +71,24 @@ local function pass(buffer)
|
||||
end
|
||||
return ob
|
||||
end
|
||||
local op = io.read("*a")
|
||||
|
||||
return function (op)
|
||||
-- comment removal
|
||||
while true do
|
||||
local np = pass(op)
|
||||
local np = op:gsub("%-%-[^\n]*\n", " ")
|
||||
np = np:gsub("%-%-[^\n]*$", "")
|
||||
if np == op then
|
||||
io.write(np)
|
||||
return
|
||||
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
|
7
inst/uncompressed/compress.lua
Normal file
7
inst/uncompressed/compress.lua
Normal file
@ -0,0 +1,7 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
return function (b)
|
||||
return b
|
||||
end
|
||||
|
12
inst/uncompressed/instdeco.lua
Normal file
12
inst/uncompressed/instdeco.lua
Normal file
@ -0,0 +1,12 @@
|
||||
-- This is released into the public domain.
|
||||
-- No warranty is provided, implied or otherwise.
|
||||
|
||||
t = ""
|
||||
function L(d)
|
||||
t = t .. d
|
||||
while #t >= 512 do
|
||||
M(t:sub(1, 512))
|
||||
t = t:sub(513)
|
||||
end
|
||||
end
|
||||
|
97
insthead.lua
97
insthead.lua
@ -1,97 +0,0 @@
|
||||
-- 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
|
@ -7,5 +7,5 @@ cp ocemu.cfg.default ocemu.cfg && rm -rf c1-sda c1-sdb tmpfs
|
||||
mkdir c1-sda c1-sdb
|
||||
echo -n c1-sda > c1-eeprom/data.bin
|
||||
cd ..
|
||||
./package.sh
|
||||
./package.sh $1
|
||||
cp inst.lua laboratory/c1-sda/init.lua
|
||||
|
28
mkucinst.lua
28
mkucinst.lua
@ -1,28 +0,0 @@
|
||||
-- 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()
|
17
package.sh
17
package.sh
@ -9,15 +9,20 @@ lua claw/clawconv.lua code/data/app-claw/ < claw/code-claw.lua > /dev/null
|
||||
rm code.tar
|
||||
# Hey, look behind you, there's nothing to see here.
|
||||
# ... ok, are they seriously all named "Mann"?
|
||||
tar --mtime=0 --owner=gray:0 --group=mann:0 -cf code.tar code
|
||||
cd code
|
||||
tar --mtime=0 --owner=gray:0 --group=mann:0 -cf ../code.tar .
|
||||
cd ..
|
||||
|
||||
# Solely for ensuring that a -gold.lua file can be checked before being pushed to repository.
|
||||
echo -n "-- commit: " > inst.lua
|
||||
echo -n "-- KOSNEO inst. " > inst.lua
|
||||
git status --porcelain=2 --branch | grep branch.oid >> inst.lua
|
||||
lua heroes.lua `wc -c code.tar` | lua com2/bonecrunch.lua >> inst.lua
|
||||
echo -n "--[[" >> inst.lua
|
||||
cat com2/code.tar.bd >> inst.lua
|
||||
echo -n "]]" >> inst.lua
|
||||
echo "-- This is released into the public domain." >> inst.lua
|
||||
echo "-- No warranty is provided, implied or otherwise." >> inst.lua
|
||||
|
||||
# The Installer Creator
|
||||
cd inst
|
||||
lua build.lua $1 ../code.tar >> ../inst.lua
|
||||
cd ..
|
||||
|
||||
# Common Repository Setup Code
|
||||
./package-repo.sh inst.lua
|
||||
|
@ -1,609 +0,0 @@
|
||||
-- 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
|
||||
--[[ |