diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100755 index 0000000..4c85f17 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,46 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build", + "type": "shell", + + "windows": { + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + "if (Test-Path '${workspaceFolder}\\Build') { Remove-Item -LiteralPath '${workspaceFolder}\\Build' -Recurse -Force -ErrorAction SilentlyContinue }; New-Item -ItemType Directory -Path '${workspaceFolder}\\Build' | Out-Null; Get-ChildItem -Path '${workspaceFolder}\\Test' -Directory | ForEach-Object { $base = $_.FullName; Get-ChildItem -Path $base -File -Recurse | ForEach-Object { $rel = $_.FullName.Substring($base.Length).TrimStart(\"\\\"); $destPath = Join-Path '${workspaceFolder}\\Build' $rel; $destDir = Split-Path $destPath; if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir | Out-Null }; Copy-Item -LiteralPath $_.FullName -Destination $destPath -Force } }" + ] + }, + + "linux": { + "command": "bash", + "args": [ + "-c", + "[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done" + ] + }, + + "osx": { + "command": "bash", + "args": [ + "-c", + "[ -d \"${workspaceFolder}/Build\" ] && rm -rf \"${workspaceFolder}/Build\"; mkdir -p \"${workspaceFolder}/Build\"; for d in \"${workspaceFolder}/Test\"/*; do if [ -d \"$d\" ]; then find \"$d\" -type f | while read f; do rel=\"${f#$d/}\"; mkdir -p \"${workspaceFolder}/Build/$(dirname \"$rel\")\"; cp \"$f\" \"${workspaceFolder}/Build/$rel\"; done; fi; done" + ] + }, + + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/src/computers/0/bios.lua b/src/computers/0/bios.lua deleted file mode 100644 index 848a0b8..0000000 --- a/src/computers/0/bios.lua +++ /dev/null @@ -1,188 +0,0 @@ -local computer = component.getFirst("computer") -local screen=component.getFirst("screen") -if not screen then - local function e(...)end - screen = { - print=e, - printInline=e, - clear=e - } -end - -local ok,err = xpcall(function() - -- Init components - _G._DEVELOPMENT=true - _G.component=component - - local printed="" - local print=function(text) - printed=printed..text.."\n" - screen.print(text) - end - - -- Get CFG - local biosCfg = {} - local i=1 - while i<=256 do - biosCfg[i]=computer.getData(i) or "" - i=i+1 - end - computer.beep(800,0.2) - - local function deepcopy(orig, copies) - copies = copies or {} - - if type(orig) ~= 'table' then - return orig - elseif copies[orig] then - return copies[orig] - end - - local copy = {} - copies[orig] = copy - - for k, v in next, orig, nil do - local copied_key = deepcopy(k, copies) - local copied_val = deepcopy(v, copies) - copy[copied_key] = copied_val - end - - return copy - end - - local function save(table) - while i<=256 do - computer.setData(i, table[i] or nil) - i=i+1 - end - end - - local function hasKey(tabl, query) - for i,v in pairs(tabl) do - if i==query then - return true - end - end - return false - end - - -- Start boot seq - local disks={} - for i,v in component.list() do - if i=="disk" then - disks[v.id]=v - end - end - - local idx = 1 - local bootOption=1 - while true do - if biosCfg[idx]=="$EOF" then break end - print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".") - bootOption=bootOption+1 - local drive={} - idx=idx+1 - if not hasKey(disks,biosCfg[idx]) then - print("└─ Drive not found.") - print(" ") - idx=idx+3 - goto invalid_boot - else - drive=disks[biosCfg[idx]] - print("├─ Drive found with id of \""..drive.id.."\"") - end - idx=idx+1 - local path - local code - if drive.type=="udd" then - print("├─ Drive is Unmanaged, looking for MBR...") - sleep(0.02) - print("├─ Reading MBR...") - local tmp = drive.readBytes(0,512) - print("├─ MBR found, compiling bootloader...") - code = table.concat(tmp) - else - if not drive:fileExists(biosCfg[idx]) then - print("└─ Path not found.") - print(" ") - idx=idx+2 - goto invalid_boot - else - print("├─ Kernel exists at path \""..biosCfg[idx].."\"") - path=biosCfg[idx] - end - code = drive:open(path).read() - end - idx=idx+1 - _VG=deepcopy(_G) - print("├─ Created virtual ENV.") - local _,func = pcall(load,code,drive.id.." | "..path,nil,_G) - if not func then - print("└─ Compilation failure.") - print(" ") - idx=idx+1 - goto invalid_boot - else - print("├─ Executing.") - end - local cmd=biosCfg[idx] or "" - idx=idx+1 - local biosData = {} - biosData.bootDrive=drive - biosData.term=screen - screen.clear() - local ok, err = xpcall(func, debug.traceback, biosData, cmd) - screen.clear() - screen.print(printed) - if not ok then - print("└─ OS exited with error: "..err) - print(" ") - else - print("└─ OS exited.") - print(" ") - end - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - break - end - end - sleep(0.02) - end - ::invalid_boot:: - end - computer.beep(400,0.4) - print("No boot options available") - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end, debug.traceback) -if not ok then - screen.clear() - screen.print("BIOS PANIC: "..err) - computer.beep(800,0.2) - sleep(0.02) - computer.beep(800,0.2) - sleep(0.02) - computer.beep(800,0.2) - sleep(0.02) - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end \ No newline at end of file diff --git a/src/computers/0/computer.json b/src/computers/0/computer.json deleted file mode 100644 index 48dae9d..0000000 --- a/src/computers/0/computer.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disks":[1,2,3,56] -} \ No newline at end of file diff --git a/src/computers/0/nvram.dat b/src/computers/0/nvram.dat deleted file mode 100644 index 56883ba..0000000 --- a/src/computers/0/nvram.dat +++ /dev/null @@ -1,254 +0,0 @@ -HyperionOS -disk_1 -/boot/ac/boot.ac - -HyperionOS Dev -disk_2 -/boot/Hyprkrnl.sys - -$EOF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/computers/1/bios.lua b/src/computers/1/bios.lua deleted file mode 100644 index 76184c8..0000000 --- a/src/computers/1/bios.lua +++ /dev/null @@ -1,58 +0,0 @@ -local computer = component.getFirst("computer") -local screen=component.getFirst("screen") -if not screen then - computer.beep(400,0.2) - sleep(0.2) - computer.beep(400,0.2) - while true do - computer.shutdown() - end -end -local idx = 1 -local ok, err = xpcall(function() - for t, a in component.list() do - if t == "disk" then - if a:fileExists("boot.lua") then - screen.print("Bootable file found on "..a.id.." - reading...") - local code = a:open("boot.lua").read() - screen.print("Compiling boot.lua...") - local f = load(code) - if not f then error("bios boot compilation failed") end - screen.print("Booting...") - ---@diagnostic disable-next-line: need-check-nil - local ok, err = xpcall(f, debug.traceback) - if not ok then screen.print(err); sleep(3) end - break - else - idx = idx+1 - end - end - end -end, debug.traceback) -if not ok then - screen.print("BIOS error: "..err) - computer.beep(800,0.2) - osleep(0.02) - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end -computer.beep(400,0.4) -screen.print("No bootable filesystem found!") -screen.print("Press enter to continue...") -while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) -end \ No newline at end of file diff --git a/src/computers/1/computer.json b/src/computers/1/computer.json deleted file mode 100644 index a4402fb..0000000 --- a/src/computers/1/computer.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disks":[3,4,8] -} \ No newline at end of file diff --git a/src/computers/1/nvram.dat b/src/computers/1/nvram.dat deleted file mode 100644 index e621ffc..0000000 --- a/src/computers/1/nvram.dat +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/computers/2/bios.lua b/src/computers/2/bios.lua deleted file mode 100644 index 8c84488..0000000 --- a/src/computers/2/bios.lua +++ /dev/null @@ -1,189 +0,0 @@ -local computer = component.getFirst("computer") -local screen=component.getFirst("screen") -if not screen then - local function e(...)end - screen = { - print=e, - printInline=e, - clear=e - } -end - -local ok,err = xpcall(function() - -- Init components - _G._DEVELOPMENT=true - _G.component=component - - local printed="" - local print=function(text) - printed=printed..text.."\n" - screen.print(text) - end - - -- Get CFG - local biosCfg = {} - local i=1 - while i<=256 do - biosCfg[i]=computer.getData(i) or "" - i=i+1 - end - computer.beep(800,0.2) - -- Difine functions - local function copy(tabl) - local out = {} - for i,v in pairs(tabl) do - local t=type(v) - if t=="table" then - if i == "_G" then - out._G=out - else - out[i]=copy(v) - end - else - out[i]=v - end - end - return out - end - - local function save(table) - while i<=256 do - computer.setData(i, table[i] or nil) - i=i+1 - end - end - - local function hasKey(tabl, query) - for i,v in pairs(tabl) do - if i==query then - return true - end - end - return false - end - - -- Start boot seq - local disks={} - for i,v in component.list() do - if i=="disk" then - disks[v.id]=v - if v.type=="udd" then - v:writeBytes(0, "HDS") -- "HDS" - local tmp = v:readBytes(0,512) -- Just to make sure it writes the data - print(tmp) - end - end - end - - local idx = 1 - local bootOption=1 - while true do - if biosCfg[idx]=="$EOF" then break end - print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".") - bootOption=bootOption+1 - local drive={} - idx=idx+1 - if not hasKey(disks,biosCfg[idx]) then - print("└─ Drive not found.") - print(" ") - idx=idx+3 - goto invalid_boot - else - drive=disks[biosCfg[idx]] - print("├─ Drive found with id of \""..drive.id.."\"") - end - idx=idx+1 - local path - local code - if drive.type=="udd" then - print("├─ Drive is Unmanaged, looking for MBR...") - sleep(0.02) - print("├─ Reading MBR...") - local tmp = drive.readBytes(0,512) - print("├─ MBR found, compiling bootloader...") - code = table.concat(tmp) - else - if not drive:fileExists(biosCfg[idx]) then - print("└─ Path not found.") - print(" ") - idx=idx+2 - goto invalid_boot - else - print("├─ Kernel exists at path \""..biosCfg[idx].."\"") - path=biosCfg[idx] - end - code = drive:open(path).read() - end - idx=idx+1 - local _VG=copy(_G) - print("├─ Created virtual ENV.") - local _,func = pcall(load,code,drive.id.." | "..path,nil,_VG) - if not func then - print("└─ Compilation failure.") - print(" ") - idx=idx+1 - goto invalid_boot - else - print("├─ Executing.") - end - local cmd=biosCfg[idx] or "" - idx=idx+1 - local biosData = {} - biosData.bootDrive=drive - biosData.term=screen - screen.clear() - local ok, err = xpcall(func, debug.traceback, biosData, cmd) - screen.clear() - screen.print(printed) - if not ok then - print("└─ OS exited with error: "..err) - print(" ") - else - print("└─ OS exited.") - print(" ") - end - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - break - end - end - sleep(0.02) - end - ::invalid_boot:: - end - computer.beep(400,0.4) - print("No boot options available") - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end, debug.traceback) -if not ok then - screen.clear() - screen.print("BIOS PANIC: "..err) - computer.beep(800,0.2) - sleep(0.02) - computer.beep(800,0.2) - sleep(0.02) - computer.beep(800,0.2) - sleep(0.02) - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end \ No newline at end of file diff --git a/src/computers/2/computer.json b/src/computers/2/computer.json deleted file mode 100644 index 4aa6388..0000000 --- a/src/computers/2/computer.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disks":[1,2,3,4,8] -} \ No newline at end of file diff --git a/src/computers/2/nvram.dat b/src/computers/2/nvram.dat deleted file mode 100644 index 26d330c..0000000 --- a/src/computers/2/nvram.dat +++ /dev/null @@ -1,249 +0,0 @@ -HyperionOS -disk_3 -/boot/ac/boot.ac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/computers/6/bios.lua b/src/computers/6/bios.lua deleted file mode 100644 index 3ed9006..0000000 --- a/src/computers/6/bios.lua +++ /dev/null @@ -1,46 +0,0 @@ -local driverutil={} -function driverutil.getFirst(type) - if drivers[type] then - if drivers[type][1] then - return drivers[type][1] - end - end -end - -function driverutil.list(type) - if not type then - local tmp={} - for i,v in ipairs(drivers.raw) do - tmp[#tmp+1] = {type=v.type, obj=v} - end - local i=0 - return function() - i=i+1 - if tmp[i]==nil then return end - return tmp[i].type, tmp[i].obj - end - else - local tmp={} - for i,v in ipairs(drivers[type]) do - tmp[#tmp+1] = {type=v.type, obj=v} - end - local i=0 - return function() - i=i+1 - if tmp[i]==nil then return end - return tmp[i].type, tmp[i].obj - end - end -end - -local function runAsKernel(path, ...) - local func, err = load("return {'e'}", path, "t", _G) - if not func then return false, "\t"..err end - local ret = {xpcall(func, debug.traceback, ...)} - if not ret[1] then - return false, ret[2] - end - return true, table.unpack(ret, 2) -end - -runAsKernel(e, driverutil) \ No newline at end of file diff --git a/src/computers/6/computer.json b/src/computers/6/computer.json deleted file mode 100644 index 4aa6388..0000000 --- a/src/computers/6/computer.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "disks":[1,2,3,4,8] -} \ No newline at end of file diff --git a/src/computers/6/nvram.dat b/src/computers/6/nvram.dat deleted file mode 100644 index 26d330c..0000000 --- a/src/computers/6/nvram.dat +++ /dev/null @@ -1,249 +0,0 @@ -HyperionOS -disk_3 -/boot/ac/boot.ac - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/disks/.ignore b/src/disks/.ignore deleted file mode 100644 index 8b13789..0000000 --- a/src/disks/.ignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/disks/1h/bin/BASIC b/src/disks/1h/bin/BASIC deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/bin/hex.lua b/src/disks/1h/bin/hex.lua deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/bin/lua.lua b/src/disks/1h/bin/lua.lua deleted file mode 100644 index c5e032a..0000000 --- a/src/disks/1h/bin/lua.lua +++ /dev/null @@ -1,10 +0,0 @@ -local args={...} -if #args>0 then - load(args[1])(table.unpack(args, 2)) -else - local sys = require("system") - local evhook = sys.addEventHook("keyTyped", function() - - end) - local term = sys.getParentTermObject() -end \ No newline at end of file diff --git a/src/disks/1h/bin/shell.hex b/src/disks/1h/bin/shell.hex deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/bin/shell.lua b/src/disks/1h/bin/shell.lua deleted file mode 100644 index 9fc6382..0000000 --- a/src/disks/1h/bin/shell.lua +++ /dev/null @@ -1,783 +0,0 @@ --- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe --- --- SPDX-License-Identifier: LicenseRef-CCPL - ---[[- The shell API provides access to CraftOS's command line interface. -It allows you to @{run|start programs}, @{setCompletionFunction|add completion -for a program}, and much more. -@{shell} is not a "true" API. Instead, it is a standard program, which injects -its API into the programs that it launches. This allows for multiple shells to -run at the same time, but means that the API is not available in the global -environment, and so is unavailable to other @{os.loadAPI|APIs}. -## Programs and the program path -When you run a command with the shell, either from the prompt or -@{shell.run|from Lua code}, the shell API performs several steps to work out -which program to run: - 1. Firstly, the shell attempts to resolve @{shell.aliases|aliases}. This allows - us to use multiple names for a single command. For example, the `list` - program has two aliases: `ls` and `dir`. When you write `ls /rom`, that's - expanded to `list /rom`. - 2. Next, the shell attempts to find where the program actually is. For this, it - uses the @{shell.path|program path}. This is a colon separated list of - directories, each of which is checked to see if it contains the program. - `list` or `list.lua` doesn't exist in `.` (the current directory), so she - shell now looks in `/rom/programs`, where `list.lua` can be found! - 3. Finally, the shell reads the file and checks if the file starts with a - `#!`. This is a [hashbang][], which says that this file shouldn't be treated - as Lua, but instead passed to _another_ program, the name of which should - follow the `#!`. -[hashbang]: https://en.wikipedia.org/wiki/Shebang_(Unix) -@module[module] shell -]] -local make_package = dofile("rom/modules/main/cc/require.lua").make - -local multishell = multishell -local parentShell = shell -local parentTerm = term.current() - -if multishell then - multishell.setTitle(multishell.getCurrent(), "shell") -end - -local bExit = false -local sDir = parentShell and parentShell.dir() or "" -local sPath = parentShell and parentShell.path() or ".:/rom/programs" -local tAliases = parentShell and parentShell.aliases() or {} -local tCompletionInfo = parentShell and parentShell.getCompletionInfo() or {} -local tProgramStack = {} - -local shell = {} --- @export -local function createShellEnv(dir) - local env = { shell = shell, multishell = multishell } - env.require, env.package = make_package(env, dir) - return env -end - --- Set up a dummy require based on the current shell, for loading some of our internal dependencies. -local require -do - local env = setmetatable(createShellEnv("/rom/programs"), { __index = _ENV }) - require = env.require -end -local expect = require("cc.expect").expect -local exception = require "cc.internal.exception" - --- Colours -local promptColour, textColour, bgColour -if term.isColour() then - promptColour = colours.yellow - textColour = colours.white - bgColour = colours.black -else - promptColour = colours.white - textColour = colours.white - bgColour = colours.black -end - -local function tokenise(...) - local sLine = table.concat({ ... }, " ") - local tWords = {} - local bQuoted = false - for match in string.gmatch(sLine .. "\"", "(.-)\"") do - if bQuoted then - table.insert(tWords, match) - else - for m in string.gmatch(match, "[^ \t]+") do - table.insert(tWords, m) - end - end - bQuoted = not bQuoted - end - return tWords -end - --- Execute a program using os.run, unless a shebang is present. --- In that case, execute the program using the interpreter specified in the hashbang. --- This may occur recursively, up to the maximum number of times specified by remainingRecursion --- Returns the same type as os.run, which is a boolean indicating whether the program exited successfully. -local function executeProgram(remainingRecursion, path, args) - local file, err = fs.open(path, "r") - if not file then - printError(err) - return false - end - - -- First check if the file begins with a #! - local contents = file.readLine() or "" - - if contents:sub(1, 2) == "#!" then - file.close() - - remainingRecursion = remainingRecursion - 1 - if remainingRecursion == 0 then - printError("Hashbang recursion depth limit reached when loading file: " .. path) - return false - end - - -- Load the specified hashbang program instead - local hashbangArgs = tokenise(contents:sub(3)) - local originalHashbangPath = table.remove(hashbangArgs, 1) - local resolvedHashbangProgram = shell.resolveProgram(originalHashbangPath) - if not resolvedHashbangProgram then - printError("Hashbang program not found: " .. originalHashbangPath) - return false - elseif resolvedHashbangProgram == "rom/programs/shell.lua" and #hashbangArgs == 0 then - -- If we try to launch the shell then our shebang expands to "shell ", which just does a - -- shell.run("") again, resulting in an infinite loop. This may still happen (if the user - -- has a custom shell), but this reduces the risk. - -- It's a little ugly special-casing this, but it's probably worth warning about. - printError("Cannot use the shell as a hashbang program") - return false - end - - -- Add the path and any arguments to the interpreter's arguments - table.insert(hashbangArgs, path) - for _, v in ipairs(args) do - table.insert(hashbangArgs, v) - end - - hashbangArgs[0] = originalHashbangPath - return executeProgram(remainingRecursion, resolvedHashbangProgram, hashbangArgs) - end - - contents = contents .. "\n" .. (file.readAll() or "") - file.close() - - local dir = fs.getDir(path) - local env = setmetatable(createShellEnv(dir), { __index = _G }) - env.arg = args - - local func, err = load(contents, "@/" .. fs.combine(path), nil, env) - if not func then - -- We had a syntax error. Attempt to run it through our own parser if - -- the file is "small enough", otherwise report the original error. - if #contents < 1024 * 128 then - local parser = require "cc.internal.syntax" - if parser.parse_program(contents) then printError(err) end - else - printError(err) - end - - return false - end - - if settings.get("bios.strict_globals", false) then - getmetatable(env).__newindex = function(_, name) - error("Attempt to create global " .. tostring(name), 2) - end - end - - local ok, err, co = exception.try(func, table.unpack(args, 1, args.n)) - - if ok then return true end - - if err and err ~= "" then - printError(err) - exception.report(err, co) - end - - return false -end - ---- Run a program with the supplied arguments. --- --- Unlike @{shell.run}, each argument is passed to the program verbatim. While --- `shell.run("echo", "b c")` runs `echo` with `b` and `c`, --- `shell.execute("echo", "b c")` runs `echo` with a single argument `b c`. --- --- @tparam string command The program to execute. --- @tparam string ... Arguments to this program. --- @treturn boolean Whether the program exited successfully. --- @since 1.88.0 --- @usage Run `paint my-image` from within your program: --- --- shell.execute("paint", "my-image") -function shell.execute(command, ...) - expect(1, command, "string") - for i = 1, select('#', ...) do - expect(i + 1, select(i, ...), "string") - end - - local sPath = shell.resolveProgram(command) - if sPath ~= nil then - tProgramStack[#tProgramStack + 1] = sPath - if multishell then - local sTitle = fs.getName(sPath) - if sTitle:sub(-4) == ".lua" then - sTitle = sTitle:sub(1, -5) - end - multishell.setTitle(multishell.getCurrent(), sTitle) - end - - local result = executeProgram(100, sPath, { [0] = command, ... }) - - tProgramStack[#tProgramStack] = nil - if multishell then - if #tProgramStack > 0 then - local sTitle = fs.getName(tProgramStack[#tProgramStack]) - if sTitle:sub(-4) == ".lua" then - sTitle = sTitle:sub(1, -5) - end - multishell.setTitle(multishell.getCurrent(), sTitle) - else - multishell.setTitle(multishell.getCurrent(), "shell") - end - end - return result - else - printError("No such program") - return false - end -end - --- Install shell API - ---- Run a program with the supplied arguments. --- --- All arguments are concatenated together and then parsed as a command line. As --- a result, `shell.run("program a b")` is the same as `shell.run("program", --- "a", "b")`. --- --- @tparam string ... The program to run and its arguments. --- @treturn boolean Whether the program exited successfully. --- @usage Run `paint my-image` from within your program: --- --- shell.run("paint", "my-image") --- @see shell.execute Run a program directly without parsing the arguments. --- @changed 1.80pr1 Programs now get their own environment instead of sharing the same one. --- @changed 1.83.0 `arg` is now added to the environment. -function shell.run(...) - local tWords = tokenise(...) - local sCommand = tWords[1] - if sCommand then - return shell.execute(sCommand, table.unpack(tWords, 2)) - end - return false -end - ---- Exit the current shell. --- --- This does _not_ terminate your program, it simply makes the shell terminate --- after your program has finished. If this is the toplevel shell, then the --- computer will be shutdown. -function shell.exit() - bExit = true -end - ---- Return the current working directory. This is what is displayed before the --- `> ` of the shell prompt, and is used by @{shell.resolve} to handle relative --- paths. --- --- @treturn string The current working directory. --- @see setDir To change the working directory. -function shell.dir() - return sDir -end - ---- Set the current working directory. --- --- @tparam string dir The new working directory. --- @throws If the path does not exist or is not a directory. --- @usage Set the working directory to "rom" --- --- shell.setDir("rom") -function shell.setDir(dir) - expect(1, dir, "string") - if not fs.isDir(dir) then - error("Not a directory", 2) - end - sDir = fs.combine(dir, "") -end - ---- Set the path where programs are located. --- --- The path is composed of a list of directory names in a string, each separated --- by a colon (`:`). On normal turtles will look in the current directory (`.`), --- `/rom/programs` and `/rom/programs/turtle` folder, making the path --- `.:/rom/programs:/rom/programs/turtle`. --- --- @treturn string The current shell's path. --- @see setPath To change the current path. -function shell.path() - return sPath -end - ---- Set the @{path|current program path}. --- --- Be careful to prefix directories with a `/`. Otherwise they will be searched --- for from the @{shell.dir|current directory}, rather than the computer's root. --- --- @tparam string path The new program path. --- @since 1.2 -function shell.setPath(path) - expect(1, path, "string") - sPath = path -end - ---- Resolve a relative path to an absolute path. --- --- The @{fs} and @{io} APIs work using absolute paths, and so we must convert --- any paths relative to the @{dir|current directory} to absolute ones. This --- does nothing when the path starts with `/`. --- --- @tparam string path The path to resolve. --- @usage Resolve `startup.lua` when in the `rom` folder. --- --- shell.setDir("rom") --- print(shell.resolve("startup.lua")) --- -- => rom/startup.lua -function shell.resolve(path) - expect(1, path, "string") - local sStartChar = string.sub(path, 1, 1) - if sStartChar == "/" or sStartChar == "\\" then - return fs.combine("", path) - else - return fs.combine(sDir, path) - end -end - -local function pathWithExtension(_sPath, _sExt) - local nLen = #sPath - local sEndChar = string.sub(_sPath, nLen, nLen) - -- Remove any trailing slashes so we can add an extension to the path safely - if sEndChar == "/" or sEndChar == "\\" then - _sPath = string.sub(_sPath, 1, nLen - 1) - end - return _sPath .. "." .. _sExt -end - ---- Resolve a program, using the @{path|program path} and list of @{aliases|aliases}. --- --- @tparam string command The name of the program --- @treturn string|nil The absolute path to the program, or @{nil} if it could --- not be found. --- @since 1.2 --- @usage Locate the `hello` program. --- --- shell.resolveProgram("hello") --- -- => rom/programs/fun/hello.lua -function shell.resolveProgram(command) - expect(1, command, "string") - -- Substitute aliases firsts - if tAliases[command] ~= nil then - command = tAliases[command] - end - - -- If the path is a global path, use it directly - if command:find("/") or command:find("\\") then - local sPath = shell.resolve(command) - if fs.exists(sPath) and not fs.isDir(sPath) then - return sPath - else - local sPathLua = pathWithExtension(sPath, "lua") - if fs.exists(sPathLua) and not fs.isDir(sPathLua) then - return sPathLua - end - end - return nil - end - - -- Otherwise, look on the path variable - for sPath in string.gmatch(sPath, "[^:]+") do - sPath = fs.combine(shell.resolve(sPath), command) - if fs.exists(sPath) and not fs.isDir(sPath) then - return sPath - else - local sPathLua = pathWithExtension(sPath, "lua") - if fs.exists(sPathLua) and not fs.isDir(sPathLua) then - return sPathLua - end - end - end - - -- Not found - return nil -end - ---- Return a list of all programs on the @{shell.path|path}. --- --- @tparam[opt] boolean include_hidden Include hidden files. Namely, any which --- start with `.`. --- @treturn { string } A list of available programs. --- @usage textutils.tabulate(shell.programs()) --- @since 1.2 -function shell.programs(include_hidden) - expect(1, include_hidden, "boolean", "nil") - - local tItems = {} - - -- Add programs from the path - for sPath in string.gmatch(sPath, "[^:]+") do - sPath = shell.resolve(sPath) - if fs.isDir(sPath) then - local tList = fs.list(sPath) - for n = 1, #tList do - local sFile = tList[n] - if not fs.isDir(fs.combine(sPath, sFile)) and - (include_hidden or string.sub(sFile, 1, 1) ~= ".") then - if #sFile > 4 and sFile:sub(-4) == ".lua" then - sFile = sFile:sub(1, -5) - end - tItems[sFile] = true - end - end - end - end - - -- Sort and return - local tItemList = {} - for sItem in pairs(tItems) do - table.insert(tItemList, sItem) - end - table.sort(tItemList) - return tItemList -end - -local function completeProgram(sLine) - local bIncludeHidden = settings.get("shell.autocomplete_hidden") - if #sLine > 0 and (sLine:find("/") or sLine:find("\\")) then - -- Add programs from the root - return fs.complete(sLine, sDir, { - include_files = true, - include_dirs = false, - include_hidden = bIncludeHidden, - }) - - else - local tResults = {} - local tSeen = {} - - -- Add aliases - for sAlias in pairs(tAliases) do - if #sAlias > #sLine and string.sub(sAlias, 1, #sLine) == sLine then - local sResult = string.sub(sAlias, #sLine + 1) - if not tSeen[sResult] then - table.insert(tResults, sResult) - tSeen[sResult] = true - end - end - end - - -- Add all subdirectories. We don't include files as they will be added in the block below - local tDirs = fs.complete(sLine, sDir, { - include_files = false, - include_dirs = false, - include_hidden = bIncludeHidden, - }) - for i = 1, #tDirs do - local sResult = tDirs[i] - if not tSeen[sResult] then - table.insert (tResults, sResult) - tSeen [sResult] = true - end - end - - -- Add programs from the path - local tPrograms = shell.programs() - for n = 1, #tPrograms do - local sProgram = tPrograms[n] - if #sProgram > #sLine and string.sub(sProgram, 1, #sLine) == sLine then - local sResult = string.sub(sProgram, #sLine + 1) - if not tSeen[sResult] then - table.insert(tResults, sResult) - tSeen[sResult] = true - end - end - end - - -- Sort and return - table.sort(tResults) - return tResults - end -end - -local function completeProgramArgument(sProgram, nArgument, sPart, tPreviousParts) - local tInfo = tCompletionInfo[sProgram] - if tInfo then - return tInfo.fnComplete(shell, nArgument, sPart, tPreviousParts) - end - return nil -end - ---- Complete a shell command line. --- --- This accepts an incomplete command, and completes the program name or --- arguments. For instance, `l` will be completed to `ls`, and `ls ro` will be --- completed to `ls rom/`. --- --- Completion handlers for your program may be registered with --- @{shell.setCompletionFunction}. --- --- @tparam string sLine The input to complete. --- @treturn { string }|nil The list of possible completions. --- @see _G.read For more information about completion. --- @see shell.completeProgram --- @see shell.setCompletionFunction --- @see shell.getCompletionInfo --- @since 1.74 -function shell.complete(sLine) - expect(1, sLine, "string") - if #sLine > 0 then - local tWords = tokenise(sLine) - local nIndex = #tWords - if string.sub(sLine, #sLine, #sLine) == " " then - nIndex = nIndex + 1 - end - if nIndex == 1 then - local sBit = tWords[1] or "" - local sPath = shell.resolveProgram(sBit) - if tCompletionInfo[sPath] then - return { " " } - else - local tResults = completeProgram(sBit) - for n = 1, #tResults do - local sResult = tResults[n] - local sPath = shell.resolveProgram(sBit .. sResult) - if tCompletionInfo[sPath] then - tResults[n] = sResult .. " " - end - end - return tResults - end - - elseif nIndex > 1 then - local sPath = shell.resolveProgram(tWords[1]) - local sPart = tWords[nIndex] or "" - local tPreviousParts = tWords - tPreviousParts[nIndex] = nil - return completeProgramArgument(sPath , nIndex - 1, sPart, tPreviousParts) - - end - end - return nil -end - ---- Complete the name of a program. --- --- @tparam string program The name of a program to complete. --- @treturn { string } A list of possible completions. --- @see cc.shell.completion.program -function shell.completeProgram(program) - expect(1, program, "string") - return completeProgram(program) -end - ---- Set the completion function for a program. When the program is entered on --- the command line, this program will be called to provide auto-complete --- information. --- --- The completion function accepts four arguments: --- --- 1. The current shell. As completion functions are inherited, this is not --- guaranteed to be the shell you registered this function in. --- 2. The index of the argument currently being completed. --- 3. The current argument. This may be the empty string. --- 4. A list of the previous arguments. --- --- For instance, when completing `pastebin put rom/st` our pastebin completion --- function will receive the shell API, an index of 2, `rom/st` as the current --- argument, and a "previous" table of `{ "put" }`. This function may then wish --- to return a table containing `artup.lua`, indicating the entire command --- should be completed to `pastebin put rom/startup.lua`. --- --- You completion entries may also be followed by a space, if you wish to --- indicate another argument is expected. --- --- @tparam string program The path to the program. This should be an absolute path --- _without_ the leading `/`. --- @tparam function(shell: table, index: number, argument: string, previous: { string }):({ string }|nil) complete --- The completion function. --- @see cc.shell.completion Various utilities to help with writing completion functions. --- @see shell.complete --- @see _G.read For more information about completion. --- @since 1.74 -function shell.setCompletionFunction(program, complete) - expect(1, program, "string") - expect(2, complete, "function") - tCompletionInfo[program] = { - fnComplete = complete, - } -end - ---- Get a table containing all completion functions. --- --- This should only be needed when building custom shells. Use --- @{setCompletionFunction} to add a completion function. --- --- @treturn { [string] = { fnComplete = function } } A table mapping the --- absolute path of programs, to their completion functions. -function shell.getCompletionInfo() - return tCompletionInfo -end - ---- Returns the path to the currently running program. --- --- @treturn string The absolute path to the running program. --- @since 1.3 -function shell.getRunningProgram() - if #tProgramStack > 0 then - return tProgramStack[#tProgramStack] - end - return nil -end - ---- Add an alias for a program. --- --- @tparam string command The name of the alias to add. --- @tparam string program The name or path to the program. --- @since 1.2 --- @usage Alias `vim` to the `edit` program --- --- shell.setAlias("vim", "edit") -function shell.setAlias(command, program) - expect(1, command, "string") - expect(2, program, "string") - tAliases[command] = program -end - ---- Remove an alias. --- --- @tparam string command The alias name to remove. -function shell.clearAlias(command) - expect(1, command, "string") - tAliases[command] = nil -end - ---- Get the current aliases for this shell. --- --- Aliases are used to allow multiple commands to refer to a single program. For --- instance, the `list` program is aliased to `dir` or `ls`. Running `ls`, `dir` --- or `list` in the shell will all run the `list` program. --- --- @treturn { [string] = string } A table, where the keys are the names of --- aliases, and the values are the path to the program. --- @see shell.setAlias --- @see shell.resolveProgram This uses aliases when resolving a program name to --- an absolute path. -function shell.aliases() - -- Copy aliases - local tCopy = {} - for sAlias, sCommand in pairs(tAliases) do - tCopy[sAlias] = sCommand - end - return tCopy -end - -if multishell then - --- Open a new @{multishell} tab running a command. - -- - -- This behaves similarly to @{shell.run}, but instead returns the process - -- index. - -- - -- This function is only available if the @{multishell} API is. - -- - -- @tparam string ... The command line to run. - -- @see shell.run - -- @see multishell.launch - -- @since 1.6 - -- @usage Launch the Lua interpreter and switch to it. - -- - -- local id = shell.openTab("lua") - -- shell.switchTab(id) - function shell.openTab(...) - local tWords = tokenise(...) - local sCommand = tWords[1] - if sCommand then - local sPath = shell.resolveProgram(sCommand) - if sPath == "rom/programs/shell.lua" then - return multishell.launch(createShellEnv("rom/programs"), sPath, table.unpack(tWords, 2)) - elseif sPath ~= nil then - return multishell.launch(createShellEnv("rom/programs"), "rom/programs/shell.lua", sCommand, table.unpack(tWords, 2)) - else - printError("No such program") - end - end - end - - --- Switch to the @{multishell} tab with the given index. - -- - -- @tparam number id The tab to switch to. - -- @see multishell.setFocus - -- @since 1.6 - function shell.switchTab(id) - expect(1, id, "number") - multishell.setFocus(id) - end -end - -local tArgs = { ... } -if #tArgs > 0 then - -- "shell x y z" - -- Run the program specified on the commandline - shell.run(...) - -else - local function show_prompt() - term.setBackgroundColor(bgColour) - term.setTextColour(promptColour) - write(shell.dir() .. "> ") - term.setTextColour(textColour) - end - - -- "shell" - -- Print the header - term.setBackgroundColor(bgColour) - term.setTextColour(promptColour) - print(os.version()) - term.setTextColour(textColour) - - -- Run the startup program - if parentShell == nil then - shell.run("/rom/startup.lua") - end - - -- Read commands and execute them - local tCommandHistory = {} - while not bExit do - term.redirect(parentTerm) - if term.setGraphicsMode then term.setGraphicsMode(0) end - show_prompt() - - - local complete - if settings.get("shell.autocomplete") then complete = shell.complete end - - local ok, result - local co = coroutine.create(read) - assert(coroutine.resume(co, nil, tCommandHistory, complete)) - - while coroutine.status(co) ~= "dead" do - local event = table.pack(os.pullEvent()) - if event[1] == "file_transfer" then - -- Abandon the current prompt - local _, h = term.getSize() - local _, y = term.getCursorPos() - if y == h then - term.scroll(1) - term.setCursorPos(1, y) - else - term.setCursorPos(1, y + 1) - end - term.setCursorBlink(false) - - -- Run the import script with the provided files - local ok, err = require("cc.internal.import")(event[2].getFiles()) - if not ok and err then printError(err) end - - -- And attempt to restore the prompt. - show_prompt() - term.setCursorBlink(true) - event = { "term_resize", n = 1 } -- Nasty hack to force read() to redraw. - end - - if result == nil or event[1] == result or event[1] == "terminate" then - ok, result = coroutine.resume(co, table.unpack(event, 1, event.n)) - if not ok then error(result, 0) end - end - end - if result:match("%S") and tCommandHistory[#tCommandHistory] ~= result then - table.insert(tCommandHistory, result) - end - shell.run(result) - end -end diff --git a/src/disks/1h/boot/HBoot.sys b/src/disks/1h/boot/HBoot.sys deleted file mode 100644 index 44be336..0000000 --- a/src/disks/1h/boot/HBoot.sys +++ /dev/null @@ -1,98 +0,0 @@ -local args = {...} -local apis = args[2] -local term = args[4] -local getfile = args[5] -local computer = args[7] -local timeout = computer.time() + 5000 - -term.print("HBoot V1.0.0 //\n") -local w, h = term.getSize() - -local kernel = load(getfile("/boot/Hyprkrnl.sys").readAllText()) -local recovery = load(getfile("/boot/util/shell").readAllText()) - --- Predeclare dbg so entries can reference it -local dbg = {} -local entries = { - {"HyperionOS", function() kernel(args, nil, "/sbin/init") end}, - {"HyperionOS (Debug options)", dbg} -} - -dbg[1] = {"Back", "BACK"} -dbg[2] = {"Boot HyperionOS in debug mode", function() kernel(args, true) end} -dbg[3] = {"Boot as shell", function() kernel(args, true, "/bin/bash") end} -dbg[4] = {"Boot in recovery", function() recovery(args) end} - -local function render(tbl, selected) - term.clear() - term.print("HBoot V1.0.0 //\n\n") - for i, v in ipairs(tbl) do - if selected == i then - term.print("> " .. v[1] .. "\n") - else - term.print(" " .. v[1] .. "\n") - end - end -end - --- Initial render -render(entries, 1) - --- Wait for keypress or timeout -local exit = false -while not exit do - local ret = {computer.getMachineEvent()} - if ret[1] == "keyPressed" then - timeout = math.huge - break - end - if timeout <= computer.time() then - exit = true - break - end -end - --- Menu handling -if not exit then - local menuStack = {} - local currentMenu = entries - local selected = 1 - render(currentMenu, selected) - - while true do - local ret = {computer.getMachineEvent()} - if ret[1] == "keyTyped" then - if ret[3] == "\n" then - local entry = currentMenu[selected] - if entry then - if type(entry[2]) == "function" then - entry[2]() - elseif type(entry[2]) == "table" then - table.insert(menuStack, {currentMenu, selected}) - currentMenu = entry[2] - selected = 1 - render(currentMenu, selected) - elseif entry[2] == "BACK" then - if #menuStack > 0 then - local prev = table.remove(menuStack) - currentMenu, selected = prev[1], prev[2] - render(currentMenu, selected) - end - end - end - elseif ret[3] == "\x1b[A" then -- Up arrow - if selected > 1 then - selected = selected - 1 - render(currentMenu, selected) - end - elseif ret[3] == "\x1b[B" then -- Down arrow - if selected < #currentMenu then - selected = selected + 1 - render(currentMenu, selected) - end - end - end - end -else - kernel(args) -end diff --git a/src/disks/1h/boot/Hyprkrnl.sys b/src/disks/1h/boot/Hyprkrnl.sys deleted file mode 100644 index 0cdcb51..0000000 --- a/src/disks/1h/boot/Hyprkrnl.sys +++ /dev/null @@ -1,230 +0,0 @@ -local args={...} -local bootLoader=args[1] -local MODE=bootLoader[1] -local apis=bootLoader[2] -local bootDisk=bootLoader[3] -local term=bootLoader[4] -local getFile=bootLoader[5] -local bootData -do - local tmp=load("return "..(getFile("/var/log/kernel/bootData").readAllText() or "{}")) - if not tmp then error("Bootdata failed to load") end - bootData=tmp() -end -local list=bootLoader[6] -local computer=bootLoader[7] -local startup=true -local osleep=sleep -_G._SYSDEBUG=args[2] -bootData.debug=args[2] -local drivers={} -local eventCache={} - -while true do - local event={computer.getMachineEvent()} - if event[1]==nil then break end - eventCache[#eventCache+1] = event -end - -term.clear() -term.print("Welcome to Hyperion OS") -term.print("Creating logger") -osleep(1) -local log=load(getFile("/sys/util/logger.lua").readAllText())(computer) -term.clear() -local logHook=log.setHook(term.print) -log.api.log("Created logger") -local function saveLog() - local logNum=bootData.logNum - getFile("/var/log/kernel/"..tostring(logNum)..".log").writeAllText(log.api.get()) - getFile("/var/log/kernel/latest.log").writeAllText(log.api.get()) - if bootData.logNum==10 then - bootData.logNum=0 - else - bootData.logNum=bootData.logNum+1 - end -end -if bootData.debug then _G.saveLog=saveLog end - -local function t2t(table) - local output = "{" - for i,v in pairs(table) do - local coma=true - if type(i) == "string" then - output=output.."[\""..i.."\"]=" - end - if type(v) == "table" then - if v == table then - output=string.sub(output,1,#output-(#i+1)) - coma=false - else - output=output..t2t(v) - end - elseif type(v) == "string" then - output=output.."[=["..v.."]=]" - elseif type(v) == "number" then - output=output..tostring(v) - elseif type(v) == "boolean" then - if v == true then - output=output.."true" - else - output=output.."false" - end - elseif type(v) == "function" then - output=output.."function()" - else - error("serialization of type \""..type(v).."\" is not supported") - end - if coma then - output=output.."," - end - end - if #table>0 or string.sub(output,#output,#output) == "," then - output=string.sub(output,1,#output-1) - end - output=output.."}" - return output -end - --- Make PANIC -local function PANIC(err) - term.clear() - term.print(log.api.get()) - saveLog() - if err==bootData.prevError then - bootData.errorCount=bootData.errorCount+1 - else - bootData.prevError=err - bootData.errorCount=0 - end - getFile("/var/log/kernel/bootData").writeAllText(t2t(bootData)) - term.print("KERNEL PANIC: "..err) - term.print("Log saved to /var/log/kernel/"..tostring(bootData.logNum)..".log\n") - term.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1]~=nil then - term.print(table.concat(event, " ")) - end - if event[1] == "keyTyped" then - if event[3] == "\n" then - break - end - end - end - computer.reboot() -end - -local function runAsKernel(path, ...) - local func, err = load(getFile(path).readAllText(), path, "t", _G) - if not func then return false, "\t"..err end - local ret = {xpcall(func, debug.traceback, ...)} - if not ret[1] then - return false, ret[2] - end - return true, table.unpack(ret, 2) -end - -log.api.log("Loading globals...") -for i,v in ipairs(list("/sys/api/")) do - if bootData.debug then log.api.debug("Loading "..v) end - local ok, err = runAsKernel("/sys/api/"..v, getFile, log) - if not ok then log.api.warn(err) end -end - -local driverutil={} -function driverutil.getFirst(type) - if drivers[type] then - if drivers[type][1] then - return drivers[type][1] - end - end -end - -function driverutil.list(type) - if not type then - local tmp={} - for i,v in ipairs(drivers.raw) do - tmp[#tmp+1] = {type=v.type, obj=v} - end - local i=0 - return function() - i=i+1 - if tmp[i]==nil then return end - return tmp[i].type, tmp[i].obj - end - else - local tmp={} - for i,v in ipairs(drivers[type]) do - tmp[#tmp+1] = {type=v.type, obj=v} - end - local i=0 - return function() - i=i+1 - if tmp[i]==nil then return end - return tmp[i].type, tmp[i].obj - end - end -end - -log.api.log("Loading drivers...") -for i,v in ipairs(list("/sys/modules/")) do - if bootData.debug then log.api.debug("Loading module "..v) end - local ok, err = runAsKernel("/sys/modules/"..v, apis, drivers, log, driverutil) - if not ok then log.api.warn("["..v.."] exited with ERR:\n"..err) end -end - -log.api.log("Unloading non \""..MODE.."\" specific drivers...") -do - local tmp={} - for i,v in ipairs(drivers) do - if type(v.arch)=="table" then - for i2,v2 in ipairs(v.arch) do - if v2==MODE or v2=="ANY" then - tmp[#tmp+1] = v - end - end - else - if v.arch==MODE or v.arch=="ANY" then - tmp[#tmp+1] = v - end - end - end - drivers={} - drivers.raw=tmp -end - -if bootData.debug then log.api.debug("Sorting drivers...") end -for i,v in ipairs(drivers.raw) do - if not drivers[v.type] then drivers[v.type]={} end - drivers[v.type][#drivers[v.type]+1] = v -end - -if bootData.debug then log.api.debug("Initializing drivers...") end -for i,v in ipairs(drivers.raw) do - if v.init then - local ok, err = xpcall(v.init, debug.traceback) - if not ok then - log.api.warn("["..v.name.."]: Init function ERR:\n"..err) - if bootData.debug then log.api.debug("Removing driver ["..v.name.."]") end - table.remove(drivers.raw, i) - end - end -end -log.api.log("Loaded "..tostring(#drivers.raw).." drivers") - -log.api.log("Loading filesystem...") -local ok, fs = runAsKernel("/sys/fs/init", drivers, log, bootDisk, driverutil) -if not ok then PANIC(fs) end -if not fs then PANIC("filesystem failed to load") end -fs.delete("/tmp") -fs.mkDir("/tmp") - -log.api.log("Loading system...") -local ok, err = runAsKernel("/sys/Hyperion.sys", drivers, log) -if not ok then PANIC(err) end -local hyperion = err -if type(hyperion)~="function" then PANIC("Hyperion failed to load:\nHyperion was: "..tostring(hyperion)) end -hyperion(fs, log, drivers, PANIC, driverutil) - -PANIC("OS EXITED MAIN()") \ No newline at end of file diff --git a/src/disks/1h/boot/ac/boot.ac b/src/disks/1h/boot/ac/boot.ac deleted file mode 100644 index 769ede0..0000000 --- a/src/disks/1h/boot/ac/boot.ac +++ /dev/null @@ -1,135 +0,0 @@ -local biosData = ({...})[1] -local apis = {} - -local lua = { - coroutine = true, - debug = true, - _HOST = true, - _VERSION = true, - assert = true, - collectgarbage = true, - error = true, - gcinfo = true, - getfenv = true, - getmetatable = true, - ipairs = true, - __inext = true, - load = true, - math = true, - next = true, - pairs = true, - pcall = true, - rawequal = true, - rawget = true, - rawlen = true, - rawset = true, - select = true, - setfenv = true, - setmetatable = true, - string = true, - table = true, - tonumber = true, - tostring = true, - type = true, - xpcall = true, - _G = true -} - -local print=component.getFirst("screen").print -local comp=component --- Sandbox globals -local _REAL_G = _G -local _PAIRS = pairs - -if type(_REAL_G) ~= "table" then - error("Global environment (_G) is not a table") -end - -for i, v in _PAIRS(_REAL_G) do - if not lua[i] then - apis[i] = v - _REAL_G[i] = nil - end -end -apis.component=comp - --- File abstraction compatible with open() -> {read,write,append} -local function getFile(path) - return { - readAllText = function() - local handle = biosData.bootDrive:open(path) - if not handle or type(handle.read) ~= "function" then - error("Cannot open file for reading: " .. tostring(path)) - end - return handle.read() or "" - end, - writeAllText = function(text) - if not biosData.bootDrive:fileExists(path) then - biosData.bootDrive:createFile(path) - end - local handle = biosData.bootDrive:open(path) - if not handle or type(handle.write) ~= "function" then - error("Cannot open file for writing: " .. tostring(path)) - end - handle.write(text) - end, - appendText = function(text) - local handle = biosData.bootDrive:open(path) - if not handle or type(handle.append) ~= "function" then - error("Cannot open file for appending: " .. tostring(path)) - end - handle.append(text) - end - } -end - -local function list(path) - return biosData.bootDrive:list(path) -end - -function coroutine.resumeWithTimeout(CORO, LINES, ...) - local ret = { coroutine.resume(CORO, ...) } - if math.random(0, 1) == 0 then - return false, table.unpack(ret) - else - return true, table.unpack(ret) - end -end - --- Safety: verify APIs exist -if not apis.component then - error("Component API missing in environment") -end -if not biosData.bootDrive then - error("bootDrive missing from biosData") -end - -local computer = apis.component.getFirst("computer") - --- Read kernel file correctly -local kernelSource = getFile("/boot/Hyprkrnl.sys").readAllText() -if not kernelSource or kernelSource == "" then - error("Kernel file empty or unreadable") -end - -local kernel, err = load(kernelSource, "@kernel", "t", _G) -if not kernel then - error("Failed to load kernel: " .. tostring(err)) -end - --- Run kernel safely -local ok, perr = xpcall(function() - kernel( - "ac", - apis, - biosData.bootDrive.id, - apis.component.getFirst("screen"), - getFile, - list, - apis.component.getFirst("computer") - ) -end, debug.traceback) - -if not ok then - error("Kernel execution failed: " .. tostring(perr)) -end diff --git a/src/disks/1h/boot/cc/boot.cc b/src/disks/1h/boot/cc/boot.cc deleted file mode 100644 index 7f3b846..0000000 --- a/src/disks/1h/boot/cc/boot.cc +++ /dev/null @@ -1,119 +0,0 @@ --- UnBIOS by JackMacWindows --- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable --- To use, just place a `bios.lua` in the root of the drive, and run this program --- Here's a list of things that are irreversibly changed: --- * both `bit` and `bit32` are kept for compatibility --- * string metatable blocking (on old versions of CC) --- In addition, if `debug` is not available these things are also irreversibly changed: --- * old Lua 5.1 `load` function (for loading from a function) --- * `loadstring` prefixing (before CC:T 1.96.0) --- * `http.request` --- * `os.shutdown` and `os.reboot` --- * `peripheral` --- * `turtle.equip[Left|Right]` --- Licensed under the MIT license -local args = {...} -if _HOST:find("UnBIOS") then return end -local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true} -local t = {} -for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end -for _,k in ipairs(t) do _G[k] = nil end -local native = _G.term.native() -for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end -_G.term = native -if _G.http then - _G.http.checkURL = _G.http.checkURLAsync - _G.http.websocket = _G.http.websocketAsync -end -if _G.commands then _G.commands = _G.commands.native end -if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end -local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}} -for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end -_G._HOST = _G._HOST .. " (UnBIOS)" --- Set up TLCO --- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally --- this would cause `parallel` to throw an error, but we replace `error` with an --- empty placeholder to let it continue and return without throwing. This results --- in the `pcall` returning successfully, preventing the error-displaying code --- from running - essentially making it so that `os.shutdown` is called immediately --- after the new BIOS exits. --- --- From there, the setup code is placed in `term.native` since it's the first --- thing called after `parallel` exits. This loads the new BIOS and prepares it --- for execution. Finally, it overwrites `os.shutdown` with the new function to --- allow it to be the last function called in the original BIOS, and returns. --- From there execution continues, calling the `term.redirect` dummy, skipping --- over the error-handling code (since `pcall` returned ok), and calling --- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail --- called, which effectively makes it run as the main chunk. -local olderror = error -_G.error = function() end -_G.term.redirect = function() end -function _G.term.native() - _G.term.native = nil - _G.term.redirect = nil - _G.error = olderror - term.setBackgroundColor(32768) - term.setTextColor(1) - term.setCursorPos(1, 1) - term.setCursorBlink(true) - term.clear() - local file = fs.open("/disk/boot/cc/preboot.cc", "r") - if file == nil then - term.setCursorBlink(false) - term.setTextColor(16384) - term.write("Could not find /boot/cc/bootloader.cc. UnBIOS cannot continue.") - term.setCursorPos(1, 2) - term.write("Press any key to continue") - coroutine.yield("key") - os.shutdown() - end - local fn, err = loadstring(file.readAll(), "@preboot.cc") - file.close() - if fn == nil then - term.setCursorBlink(false) - term.setTextColor(16384) - term.write("Could not load /boot/cc/bootloader.cc. UnBIOS cannot continue.") - term.setCursorPos(1, 2) - term.write(err) - term.setCursorPos(1, 3) - term.write("Press any key to continue") - coroutine.yield("key") - os.shutdown() - end - setfenv(fn, _G) - local oldshutdown = os.shutdown - os.shutdown = function() - os.shutdown = oldshutdown - return fn(table.unpack(args)) - end -end -if debug then - -- Restore functions that were overwritten in the BIOS - -- Apparently this has to be done *after* redefining term.native - local function restoreValue(tab, idx, name, hint) - local i, key, value = 1, debug.getupvalue(tab[idx], hint) - while key ~= name and key ~= nil do - key, value = debug.getupvalue(tab[idx], i) - i=i+1 - end - tab[idx] = value or tab[idx] - end - restoreValue(_G, "loadstring", "nativeloadstring", 1) - restoreValue(_G, "load", "nativeload", 5) - if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end - restoreValue(os, "shutdown", "nativeShutdown", 1) - restoreValue(os, "reboot", "nativeReboot", 1) - if turtle then - restoreValue(turtle, "equipLeft", "v", 1) - restoreValue(turtle, "equipRight", "v", 1) - end - do - local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2) - while key ~= "native" and key ~= nil do - key, value = debug.getupvalue(peripheral.isPresent, i) - i=i+1 - end - _G.peripheral = value or peripheral - end -end \ No newline at end of file diff --git a/src/disks/1h/boot/cc/preboot.cc b/src/disks/1h/boot/cc/preboot.cc deleted file mode 100644 index 2a3189f..0000000 --- a/src/disks/1h/boot/cc/preboot.cc +++ /dev/null @@ -1,240 +0,0 @@ -local apis={} - -local lua = { - coroutine = true, - debug = true, - _HOST = true, - _VERSION = true, - assert = true, - collectgarbage = true, - error = true, - gcinfo = true, - getfenv = true, - getmetatable = true, - ipairs = true, - __inext = true, - load = true, - math = true, - next = true, - pairs = true, - pcall = true, - rawequal = true, - rawget = true, - rawlen = true, - rawset = true, - select = true, - setfenv = true, - setmetatable = true, - string = true, - table = true, - tonumber = true, - tostring = true, - type = true, - xpcall = true, - _G=true -} - -for i,v in pairs(_G) do - if not lua[i] or lua[i]==nil then - apis[i]=v - _G[i]=nil - end -end - -function sleep(time) - coroutine.yield("CC_TIMER", time) -end - -local function catErr(text) - apis.term.setCursorPos(1,1) - apis.term.write(text) - while true do - coroutine.yield() - end -end - -local function getFile(path) - if path:sub(1,1) ~= "/" then - path="/"..path - end - path="/disk"..path - if not apis.fs.exists(path) then error("File does not exist") end - if apis.fs.isDir(path) then error("Cannot open a directory") end - return { - readAllText=function() - local file = apis.fs.open(path, "r") - local text = file.readAll() - file.close() - return text - end, - writeAllText=function(text) - local file = apis.fs.open(path, "w") - file.write(text) - file.close() - end - } -end - --- Prints text handling \n, \t, and \b with scrolling (no wrapping) -local function write(text) - local x, y = apis.term.getCursorPos() - local w, h = apis.term.getSize() - - for i = 1, #text do - local c = text:sub(i, i) - - if c == "\n" then - y = y + 1 - x = 1 - elseif c == "\t" then - local tabSize = 4 - local spaces = tabSize - ((x - 1) % tabSize) - apis.term.write(string.rep(" ", spaces)) - x = x + spaces - elseif c == "\b" then - if x > 1 then - x = x - 1 - apis.term.setCursorPos(x, y) - apis.term.write(" ") - apis.term.setCursorPos(x, y) - end - else - if x <= w and y <= h then - apis.term.setCursorPos(x, y) - apis.term.write(c) - x = x + 1 - end - end - - -- Handle scrolling if we go past bottom - if y > h then - apis.term.scroll(1) - y = h - apis.term.setCursorPos(x, y) - end - end - - apis.term.setCursorPos(x, y) -end - - -local event_queue = {} -local function addEventRaw(...) - event_queue[#event_queue+1] = {...} -end - -local function getEvent() - local event = event_queue[1] - event_queue = {table.unpack(event_queue, 2)} - return table.unpack(event or {}) -end - -local lkeys={} -lkeys[apis.keys.enter]="\n" -lkeys[apis.keys.backspace]="\b" -lkeys[apis.keys.tab]="\t" -lkeys[apis.keys.up]="\x1b[A" -lkeys[apis.keys.down]="\x1b[B" -lkeys[apis.keys.right]="\x1b[C" -lkeys[apis.keys.left]="\x1b[D" - -local computer={} -computer.beep=function() end -computer.shutdown=apis.os.shutdown -computer.reboot=apis.os.reboot -computer.time=function() - return apis.os.epoch("utc") -end -computer.getMachineEvent=getEvent -computer.date=apis.os.date - -local function list(path) - if path:sub(1,1) ~= "/" then - path="/"..path - end - path="/disk"..path - if not apis.fs.isDir(path) then return {} end - return apis.fs.list(path) -end - -function coroutine.resumeWithTimeout(CORO, LINES, ...) - local yeildKey = {} - debug.sethook(CORO, function() - coroutine.yield(yeildKey) - end, "l", LINES) - local ret = {coroutine.resume(CORO, ...)} - debug.sethook(CORO) - if ret[2]==yeildKey then return false else return true, table.unpack(ret, 2) end -end - -local kernel = load(getFile("/boot/HBoot.sys").readAllText(), "@kernel", "t", _G) -if not kernel then - catErr("BOOT COMPILE ERR") -end -local kernel_coro = coroutine.create(function() - local ok,err = pcall(function() - local ok, err=xpcall(kernel, debug.traceback, "cc", apis, "disk", { - print=function(text) - write(text.."\n") - end, - printInline=function(text) - write(text) - end, - clear=function() - apis.term.clear() - apis.term.setCursorPos(1,1) - end, - getSize=function () - return apis.term.getSize() - end - }, getFile, list, computer) - if not ok then - write(err) - while true do - coroutine.yield() - end - end - end) - if not ok then - catErr(err) - end -end) - -apis.term.setCursorBlink(false) -while true do - local ret = {coroutine.resumeWithTimeout(kernel_coro, 200)} - if coroutine.status(kernel_coro) == "dead" then - catErr("KERNEL EXITED") - end - if ret[1] then - if ret[2]=="CC_TIMER" and ret[3]~=nil and type(ret[3])=="number" then - local timer = apis.os.startTimer(ret[3]) - repeat - local _, param = coroutine.yield("timer") - until param == timer - end - end - apis.os.queueEvent("nosleep") - local exit = false - repeat - local event = {coroutine.yield()} - if event[1] == "nosleep" then - exit=true - elseif event[1]==nil then - elseif event[1]=="key" then - addEventRaw("keyPressed", 1, event[2]) - if lkeys[event[2]] then - addEventRaw("keyTyped", 1, lkeys[event[2]]) - end - elseif event[1]=="char" then - addEventRaw("keyTyped", 1, event[2]) - elseif event[1]=="key_up" then - addEventRaw("keyReleased", 1, event[2]) - elseif event[1]=="disk" then - addEventRaw("componentAdded", "disk") - elseif event[1]=="disk_eject" then - addEventRaw("componentRemoved", "disk") - end - until exit -end -apis.os.reboot() \ No newline at end of file diff --git a/src/disks/1h/boot/util/shell b/src/disks/1h/boot/util/shell deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/lib/LibDeflate b/src/disks/1h/lib/LibDeflate deleted file mode 100644 index 7e0a2ef..0000000 --- a/src/disks/1h/lib/LibDeflate +++ /dev/null @@ -1,3435 +0,0 @@ ---[[-- -LibDeflate 1.0.2-release
-Pure Lua compressor and decompressor with high compression ratio using -DEFLATE/zlib format. - -@file LibDeflate.lua -@author Haoqian He (Github: SafeteeWoW; World of Warcraft: Safetyy-Illidan(US)) -@copyright LibDeflate <2018-2021> Haoqian He -@license zlib License - -This library is implemented according to the following specifications.
-Report a bug if LibDeflate is not fully compliant with those specs.
-Both compressors and decompressors have been implemented in the library.
-1. RFC1950: DEFLATE Compressed Data Format Specification version 1.3
-https://tools.ietf.org/html/rfc1951
-2. RFC1951: ZLIB Compressed Data Format Specification version 3.3
-https://tools.ietf.org/html/rfc1950
- -This library requires Lua 5.1/5.2/5.3/5.4 interpreter or LuaJIT v2.0+.
-This library does not have any dependencies.
-
-This file "LibDeflate.lua" is the only source file of -the library.
-Submit suggestions or report bugs to -https://github.com/safeteeWow/LibDeflate/issues -]] --[[ -zlib License - -(C) 2018-2021 Haoqian He - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -License History: -1. GNU General Public License Version 3 in v1.0.0 and earlier versions. -2. GNU Lesser General Public License Version 3 in v1.0.1 -3. the zlib License since v1.0.2 - -Credits and Disclaimer: -This library rewrites the code from the algorithm -and the ideas of the following projects, -and uses their code to help to test the correctness of this library, -but their code is not included directly in the library itself. -Their original licenses shall be comply when used. - -1. zlib, by Jean-loup Gailly (compression) and Mark Adler (decompression). - http://www.zlib.net/ - Licensed under zlib License. http://www.zlib.net/zlib_license.html - For the compression algorithm. -2. puff, by Mark Adler. https://github.com/madler/zlib/tree/master/contrib/puff - Licensed under zlib License. http://www.zlib.net/zlib_license.html - For the decompression algorithm. -3. LibCompress, by jjsheets and Galmok of European Stormrage (Horde) - https://www.wowace.com/projects/libcompress - Licensed under GPLv2. - https://www.gnu.org/licenses/old-licenses/gpl-2.0.html - For the code to create customized codec. -4. WeakAuras2, - https://github.com/WeakAuras/WeakAuras2 - Licensed under GPLv2. - For the 6bit encoding and decoding. -]] --[[ - Curseforge auto-packaging replacements: - - Project Date: @project-date-iso@ - Project Hash: @project-hash@ - Project Version: @project-version@ ---]] local LibDeflate - -do - -- Semantic version. all lowercase. - -- Suffix can be alpha1, alpha2, beta1, beta2, rc1, rc2, etc. - -- NOTE: Two version numbers needs to modify. - -- 1. On the top of LibDeflate.lua - -- 2. _VERSION - -- 3. _MINOR - - -- version to store the official version of LibDeflate - local _VERSION = "1.0.2-release" - - -- When MAJOR is changed, I should name it as LibDeflate2 - local _MAJOR = "LibDeflate" - - -- Update this whenever a new version, for LibStub version registration. - -- 0 : v0.x - -- 1 : v1.0.0 - -- 2 : v1.0.1 - -- 3 : v1.0.2 - local _MINOR = 3 - - local _COPYRIGHT = "LibDeflate " .. _VERSION .. - " Copyright (C) 2018-2021 Haoqian He." .. - " Licensed under the zlib License" - - -- Register in the World of Warcraft library "LibStub" if detected. - if LibStub then - local lib, minor = LibStub:GetLibrary(_MAJOR, true) - if lib and minor and minor >= _MINOR then -- No need to update. - return lib - else -- Update or first time register - LibDeflate = LibStub:NewLibrary(_MAJOR, _MINOR) - -- NOTE: It is important that new version has implemented - -- all exported APIs and tables in the old version, - -- so the old library is fully garbage collected, - -- and we 100% ensure the backward compatibility. - end - else -- "LibStub" is not detected. - LibDeflate = {} - end - - LibDeflate._VERSION = _VERSION - LibDeflate._MAJOR = _MAJOR - LibDeflate._MINOR = _MINOR - LibDeflate._COPYRIGHT = _COPYRIGHT -end - --- localize Lua api for faster access. -local assert = assert -local error = error -local pairs = pairs -local string_byte = string.byte -local string_char = string.char -local string_find = string.find -local string_gsub = string.gsub -local string_sub = string.sub -local table_concat = table.concat -local table_sort = table.sort -local tostring = tostring -local type = type - --- Converts i to 2^i, (0<=i<=32) --- This is used to implement bit left shift and bit right shift. --- "x >> y" in C: "(x-x%_pow2[y])/_pow2[y]" in Lua --- "x << y" in C: "x*_pow2[y]" in Lua -local _pow2 = {} - --- Converts any byte to a character, (0<=byte<=255) -local _byte_to_char = {} - --- _reverseBitsTbl[len][val] stores the bit reverse of --- the number with bit length "len" and value "val" --- For example, decimal number 6 with bits length 5 is binary 00110 --- It's reverse is binary 01100, --- which is decimal 12 and 12 == _reverseBitsTbl[5][6] --- 1<=len<=9, 0<=val<=2^len-1 --- The reason for 1<=len<=9 is that the max of min bitlen of huffman code --- of a huffman alphabet is 9? -local _reverse_bits_tbl = {} - --- Convert a LZ77 length (3<=len<=258) to --- a deflate literal/LZ77_length code (257<=code<=285) -local _length_to_deflate_code = {} - --- convert a LZ77 length (3<=len<=258) to --- a deflate literal/LZ77_length code extra bits. -local _length_to_deflate_extra_bits = {} - --- Convert a LZ77 length (3<=len<=258) to --- a deflate literal/LZ77_length code extra bit length. -local _length_to_deflate_extra_bitlen = {} - --- Convert a small LZ77 distance (1<=dist<=256) to a deflate code. -local _dist256_to_deflate_code = {} - --- Convert a small LZ77 distance (1<=dist<=256) to --- a deflate distance code extra bits. -local _dist256_to_deflate_extra_bits = {} - --- Convert a small LZ77 distance (1<=dist<=256) to --- a deflate distance code extra bit length. -local _dist256_to_deflate_extra_bitlen = {} - --- Convert a literal/LZ77_length deflate code to LZ77 base length --- The key of the table is (code - 256), 257<=code<=285 -local _literal_deflate_code_to_base_len = - { - 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 - } - --- Convert a literal/LZ77_length deflate code to base LZ77 length extra bits --- The key of the table is (code - 256), 257<=code<=285 -local _literal_deflate_code_to_extra_bitlen = - { - 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 - } - --- Convert a distance deflate code to base LZ77 distance. (0<=code<=29) -local _dist_deflate_code_to_base_dist = { - [0] = 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 -} - --- Convert a distance deflate code to LZ77 bits length. (0<=code<=29) -local _dist_deflate_code_to_extra_bitlen = - { - [0] = 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 - } - --- The code order of the first huffman header in the dynamic deflate block. --- See the page 12 of RFC1951 -local _rle_codes_huffman_bitlen_order = { - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 -} - --- The following tables are used by fixed deflate block. --- The value of these tables are assigned at the bottom of the source. - --- The huffman code of the literal/LZ77_length deflate codes, --- in fixed deflate block. -local _fix_block_literal_huffman_code - --- Convert huffman code of the literal/LZ77_length to deflate codes, --- in fixed deflate block. -local _fix_block_literal_huffman_to_deflate_code - --- The bit length of the huffman code of literal/LZ77_length deflate codes, --- in fixed deflate block. -local _fix_block_literal_huffman_bitlen - --- The count of each bit length of the literal/LZ77_length deflate codes, --- in fixed deflate block. -local _fix_block_literal_huffman_bitlen_count - --- The huffman code of the distance deflate codes, --- in fixed deflate block. -local _fix_block_dist_huffman_code - --- Convert huffman code of the distance to deflate codes, --- in fixed deflate block. -local _fix_block_dist_huffman_to_deflate_code - --- The bit length of the huffman code of the distance deflate codes, --- in fixed deflate block. -local _fix_block_dist_huffman_bitlen - --- The count of each bit length of the huffman code of --- the distance deflate codes, --- in fixed deflate block. -local _fix_block_dist_huffman_bitlen_count - -for i = 0, 255 do _byte_to_char[i] = string_char(i) end - -do - local pow = 1 - for i = 0, 32 do - _pow2[i] = pow - pow = pow * 2 - end -end - -for i = 1, 9 do - _reverse_bits_tbl[i] = {} - for j = 0, _pow2[i + 1] - 1 do - local reverse = 0 - local value = j - for _ = 1, i do - -- The following line is equivalent to "res | (code %2)" in C. - reverse = reverse - reverse % 2 + - (((reverse % 2 == 1) or (value % 2) == 1) and 1 or 0) - value = (value - value % 2) / 2 - reverse = reverse * 2 - end - _reverse_bits_tbl[i][j] = (reverse - reverse % 2) / 2 - end -end - --- The source code is written according to the pattern in the numbers --- in RFC1951 Page10. -do - local a = 18 - local b = 16 - local c = 265 - local bitlen = 1 - for len = 3, 258 do - if len <= 10 then - _length_to_deflate_code[len] = len + 254 - _length_to_deflate_extra_bitlen[len] = 0 - elseif len == 258 then - _length_to_deflate_code[len] = 285 - _length_to_deflate_extra_bitlen[len] = 0 - else - if len > a then - a = a + b - b = b * 2 - c = c + 4 - bitlen = bitlen + 1 - end - local t = len - a - 1 + b / 2 - _length_to_deflate_code[len] = (t - (t % (b / 8))) / (b / 8) + c - _length_to_deflate_extra_bitlen[len] = bitlen - _length_to_deflate_extra_bits[len] = t % (b / 8) - end - end -end - --- The source code is written according to the pattern in the numbers --- in RFC1951 Page11. -do - _dist256_to_deflate_code[1] = 0 - _dist256_to_deflate_code[2] = 1 - _dist256_to_deflate_extra_bitlen[1] = 0 - _dist256_to_deflate_extra_bitlen[2] = 0 - - local a = 3 - local b = 4 - local code = 2 - local bitlen = 0 - for dist = 3, 256 do - if dist > b then - a = a * 2 - b = b * 2 - code = code + 2 - bitlen = bitlen + 1 - end - _dist256_to_deflate_code[dist] = (dist <= a) and code or (code + 1) - _dist256_to_deflate_extra_bitlen[dist] = (bitlen < 0) and 0 or bitlen - if b >= 8 then - _dist256_to_deflate_extra_bits[dist] = (dist - b / 2 - 1) % (b / 4) - end - end -end - ---- Calculate the Adler-32 checksum of the string.
--- See RFC1950 Page 9 https://tools.ietf.org/html/rfc1950 for the --- definition of Adler-32 checksum. --- @param str [string] the input string to calcuate its Adler-32 checksum. --- @return [integer] The Adler-32 checksum, which is greater or equal to 0, --- and less than 2^32 (4294967296). -function LibDeflate:Adler32(str) - -- This function is loop unrolled by better performance. - -- - -- Here is the minimum code: - -- - -- local a = 1 - -- local b = 0 - -- for i=1, #str do - -- local s = string.byte(str, i, i) - -- a = (a+s)%65521 - -- b = (b+a)%65521 - -- end - -- return b*65536+a - if type(str) ~= "string" then - error(("Usage: LibDeflate:Adler32(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - local strlen = #str - - local i = 1 - local a = 1 - local b = 0 - while i <= strlen - 15 do - local x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16 = - string_byte(str, i, i + 15) - b = - (b + 16 * a + 16 * x1 + 15 * x2 + 14 * x3 + 13 * x4 + 12 * x5 + 11 * x6 + - 10 * x7 + 9 * x8 + 8 * x9 + 7 * x10 + 6 * x11 + 5 * x12 + 4 * x13 + 3 * - x14 + 2 * x15 + x16) % 65521 - a = - (a + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + - x14 + x15 + x16) % 65521 - i = i + 16 - end - while (i <= strlen) do - local x = string_byte(str, i, i) - a = (a + x) % 65521 - b = (b + a) % 65521 - i = i + 1 - end - return (b * 65536 + a) % 4294967296 -end - --- Compare adler32 checksum. --- adler32 should be compared with a mod to avoid sign problem --- 4072834167 (unsigned) is the same adler32 as -222133129 -local function IsEqualAdler32(actual, expected) - return (actual % 4294967296) == (expected % 4294967296) -end - ---- Create a preset dictionary. --- --- This function is not fast, and the memory consumption of the produced --- dictionary is about 50 times of the input string. Therefore, it is suggestted --- to run this function only once in your program. --- --- It is very important to know that if you do use a preset dictionary, --- compressors and decompressors MUST USE THE SAME dictionary. That is, --- dictionary must be created using the same string. If you update your program --- with a new dictionary, people with the old version won't be able to transmit --- data with people with the new version. Therefore, changing the dictionary --- must be very careful. --- --- The parameters "strlen" and "adler32" add a layer of verification to ensure --- the parameter "str" is not modified unintentionally during the program --- development. --- --- @usage local dict_str = "1234567890" --- --- -- print(dict_str:len(), LibDeflate:Adler32(dict_str)) --- -- Hardcode the print result below to verify it to avoid acciently --- -- modification of 'str' during the program development. --- -- string length: 10, Adler-32: 187433486, --- -- Don't calculate string length and its Adler-32 at run-time. --- --- local dict = LibDeflate:CreateDictionary(dict_str, 10, 187433486) --- --- @param str [string] The string used as the preset dictionary.
--- You should put stuffs that frequently appears in the dictionary --- string and preferablely put more frequently appeared stuffs toward the end --- of the string.
--- Empty string and string longer than 32768 bytes are not allowed. --- @param strlen [integer] The length of 'str'. Please pass in this parameter --- as a hardcoded constant, in order to verify the content of 'str'. The value --- of this parameter should be known before your program runs. --- @param adler32 [integer] The Adler-32 checksum of 'str'. Please pass in this --- parameter as a hardcoded constant, in order to verify the content of 'str'. --- The value of this parameter should be known before your program runs. --- @return [table] The dictionary used for preset dictionary compression and --- decompression. --- @raise error if 'strlen' does not match the length of 'str', --- or if 'adler32' does not match the Adler-32 checksum of 'str'. -function LibDeflate:CreateDictionary(str, strlen, adler32) - if type(str) ~= "string" then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - if type(strlen) ~= "number" then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'strlen' - number expected got '%s'."):format(type(strlen)), 2) - end - if type(adler32) ~= "number" then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'adler32' - number expected got '%s'."):format(type(adler32)), 2) - end - if strlen ~= #str then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'strlen' does not match the actual length of 'str'." .. - " 'strlen': %u, '#str': %u ." .. - " Please check if 'str' is modified unintentionally."):format( - strlen, #str)) - end - if strlen == 0 then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'str' - Empty string is not allowed."), 2) - end - if strlen > 32768 then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'str' - string longer than 32768 bytes is not allowed." .. - " Got %d bytes."):format(strlen), 2) - end - local actual_adler32 = self:Adler32(str) - if not IsEqualAdler32(adler32, actual_adler32) then - error(("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):" .. - " 'adler32' does not match the actual adler32 of 'str'." .. - " 'adler32': %u, 'Adler32(str)': %u ." .. - " Please check if 'str' is modified unintentionally."):format( - adler32, actual_adler32)) - end - - local dictionary = {} - dictionary.adler32 = adler32 - dictionary.hash_tables = {} - dictionary.string_table = {} - dictionary.strlen = strlen - local string_table = dictionary.string_table - local hash_tables = dictionary.hash_tables - string_table[1] = string_byte(str, 1, 1) - string_table[2] = string_byte(str, 2, 2) - if strlen >= 3 then - local i = 1 - local hash = string_table[1] * 256 + string_table[2] - while i <= strlen - 2 - 3 do - local x1, x2, x3, x4 = string_byte(str, i + 2, i + 5) - string_table[i + 2] = x1 - string_table[i + 3] = x2 - string_table[i + 4] = x3 - string_table[i + 5] = x4 - hash = (hash * 256 + x1) % 16777216 - local t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = i - strlen - i = i + 1 - hash = (hash * 256 + x2) % 16777216 - t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = i - strlen - i = i + 1 - hash = (hash * 256 + x3) % 16777216 - t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = i - strlen - i = i + 1 - hash = (hash * 256 + x4) % 16777216 - t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = i - strlen - i = i + 1 - end - while i <= strlen - 2 do - local x = string_byte(str, i + 2) - string_table[i + 2] = x - hash = (hash * 256 + x) % 16777216 - local t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = i - strlen - i = i + 1 - end - end - return dictionary -end - --- Check if the dictionary is valid. --- @param dictionary The preset dictionary for compression and decompression. --- @return true if valid, false if not valid. --- @return if not valid, the error message. -local function IsValidDictionary(dictionary) - if type(dictionary) ~= "table" then - return false, - ("'dictionary' - table expected got '%s'."):format(type(dictionary)) - end - if type(dictionary.adler32) ~= "number" or type(dictionary.string_table) ~= - "table" or type(dictionary.strlen) ~= "number" or dictionary.strlen <= 0 or - dictionary.strlen > 32768 or dictionary.strlen ~= #dictionary.string_table or - type(dictionary.hash_tables) ~= "table" then - return false, - ("'dictionary' - corrupted dictionary."):format(type(dictionary)) - end - return true, "" -end - ---[[ - key of the configuration table is the compression level, - and its value stores the compression setting. - These numbers come from zlib source code. - - Higher compression level usually means better compression. - (Because LibDeflate uses a simplified version of zlib algorithm, - there is no guarantee that higher compression level does not create - bigger file than lower level, but I can say it's 99% likely) - - Be careful with the high compression level. This is a pure lua - implementation compressor/decompressor, which is significant slower than - a C/C++ equivalant compressor/decompressor. Very high compression level - costs significant more CPU time, and usually compression size won't be - significant smaller when you increase compression level by 1, when the - level is already very high. Benchmark yourself if you can afford it. - - See also https://github.com/madler/zlib/blob/master/doc/algorithm.txt, - https://github.com/madler/zlib/blob/master/deflate.c for more information. - - The meaning of each field: - @field 1 use_lazy_evaluation: - true/false. Whether the program uses lazy evaluation. - See what is "lazy evaluation" in the link above. - lazy_evaluation improves ratio, but relatively slow. - @field 2 good_prev_length: - Only effective if lazy is set, Only use 1/4 of max_chain, - if prev length of lazy match is above this. - @field 3 max_insert_length/max_lazy_match: - If not using lazy evaluation, - insert new strings in the hash table only if the match length is not - greater than this length. - If using lazy evaluation, only continue lazy evaluation, - if previous match length is strictly smaller than this value. - @field 4 nice_length: - Number. Don't continue to go down the hash chain, - if match length is above this. - @field 5 max_chain: - Number. The maximum number of hash chains we look. ---]] -local _compression_level_configs = { - [0] = {false, nil, 0, 0, 0}, -- level 0, no compression - [1] = {false, nil, 4, 8, 4}, -- level 1, similar to zlib level 1 - [2] = {false, nil, 5, 18, 8}, -- level 2, similar to zlib level 2 - [3] = {false, nil, 6, 32, 32}, -- level 3, similar to zlib level 3 - [4] = {true, 4, 4, 16, 16}, -- level 4, similar to zlib level 4 - [5] = {true, 8, 16, 32, 32}, -- level 5, similar to zlib level 5 - [6] = {true, 8, 16, 128, 128}, -- level 6, similar to zlib level 6 - [7] = {true, 8, 32, 128, 256}, -- (SLOW) level 7, similar to zlib level 7 - [8] = {true, 32, 128, 258, 1024}, -- (SLOW) level 8,similar to zlib level 8 - [9] = {true, 32, 258, 258, 4096} - -- (VERY SLOW) level 9, similar to zlib level 9 -} - --- Check if the compression/decompression arguments is valid --- @param str The input string. --- @param check_dictionary if true, check if dictionary is valid. --- @param dictionary The preset dictionary for compression and decompression. --- @param check_configs if true, check if config is valid. --- @param configs The compression configuration table --- @return true if valid, false if not valid. --- @return if not valid, the error message. -local function IsValidArguments(str, check_dictionary, dictionary, - check_configs, configs) - - if type(str) ~= "string" then - return false, ("'str' - string expected got '%s'."):format(type(str)) - end - if check_dictionary then - local dict_valid, dict_err = IsValidDictionary(dictionary) - if not dict_valid then return false, dict_err end - end - if check_configs then - local type_configs = type(configs) - if type_configs ~= "nil" and type_configs ~= "table" then - return false, ("'configs' - nil or table expected got '%s'."):format( - type(configs)) - end - if type_configs == "table" then - for k, v in pairs(configs) do - if k ~= "level" and k ~= "strategy" then - return false, - ("'configs' - unsupported table key in the configs: '%s'."):format( - k) - elseif k == "level" and not _compression_level_configs[v] then - return false, - ("'configs' - unsupported 'level': %s."):format(tostring(v)) - elseif k == "strategy" and v ~= "fixed" and v ~= "huffman_only" and v ~= - "dynamic" then - -- random_block_type is for testing purpose - return false, ("'configs' - unsupported 'strategy': '%s'."):format( - tostring(v)) - end - end - end - end - return true, "" -end - ---[[ -------------------------------------------------------------------------- - Compress code ---]] -------------------------------------------------------------------------- - --- partial flush to save memory -local _FLUSH_MODE_MEMORY_CLEANUP = 0 --- full flush with partial bytes -local _FLUSH_MODE_OUTPUT = 1 --- write bytes to get to byte boundary -local _FLUSH_MODE_BYTE_BOUNDARY = 2 --- no flush, just get num of bits written so far -local _FLUSH_MODE_NO_FLUSH = 3 - ---[[ - Create an empty writer to easily write stuffs as the unit of bits. - Return values: - 1. WriteBits(code, bitlen): - 2. WriteString(str): - 3. Flush(mode): ---]] -local function CreateWriter() - local buffer_size = 0 - local cache = 0 - local cache_bitlen = 0 - local total_bitlen = 0 - local buffer = {} - -- When buffer is big enough, flush into result_buffer to save memory. - local result_buffer = {} - - -- Write bits with value "value" and bit length of "bitlen" into writer. - -- @param value: The value being written - -- @param bitlen: The bit length of "value" - -- @return nil - local function WriteBits(value, bitlen) - cache = cache + value * _pow2[cache_bitlen] - cache_bitlen = cache_bitlen + bitlen - total_bitlen = total_bitlen + bitlen - -- Only bulk to buffer every 4 bytes. This is quicker. - if cache_bitlen >= 32 then - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_char[cache % 256] .. - _byte_to_char[((cache - cache % 256) / 256 % 256)] .. - _byte_to_char[((cache - cache % 65536) / 65536 % - 256)] .. - _byte_to_char[((cache - cache % 16777216) / - 16777216 % 256)] - local rshift_mask = _pow2[32 - cache_bitlen + bitlen] - cache = (value - value % rshift_mask) / rshift_mask - cache_bitlen = cache_bitlen - 32 - end - end - - -- Write the entire string into the writer. - -- @param str The string being written - -- @return nil - local function WriteString(str) - for _ = 1, cache_bitlen, 8 do - buffer_size = buffer_size + 1 - buffer[buffer_size] = string_char(cache % 256) - cache = (cache - cache % 256) / 256 - end - cache_bitlen = 0 - buffer_size = buffer_size + 1 - buffer[buffer_size] = str - total_bitlen = total_bitlen + #str * 8 - end - - -- Flush current stuffs in the writer and return it. - -- This operation will free most of the memory. - -- @param mode See the descrtion of the constant and the source code. - -- @return The total number of bits stored in the writer right now. - -- for byte boundary mode, it includes the padding bits. - -- for output mode, it does not include padding bits. - -- @return Return the outputs if mode is output. - local function FlushWriter(mode) - if mode == _FLUSH_MODE_NO_FLUSH then return total_bitlen end - - if mode == _FLUSH_MODE_OUTPUT or mode == _FLUSH_MODE_BYTE_BOUNDARY then - -- Full flush, also output cache. - -- Need to pad some bits if cache_bitlen is not multiple of 8. - local padding_bitlen = (8 - cache_bitlen % 8) % 8 - - if cache_bitlen > 0 then - -- padding with all 1 bits, mainly because "\000" is not - -- good to be tranmitted. I do this so "\000" is a little bit - -- less frequent. - cache = cache - _pow2[cache_bitlen] + - _pow2[cache_bitlen + padding_bitlen] - for _ = 1, cache_bitlen, 8 do - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_char[cache % 256] - cache = (cache - cache % 256) / 256 - end - - cache = 0 - cache_bitlen = 0 - end - if mode == _FLUSH_MODE_BYTE_BOUNDARY then - total_bitlen = total_bitlen + padding_bitlen - return total_bitlen - end - end - - local flushed = table_concat(buffer) - buffer = {} - buffer_size = 0 - result_buffer[#result_buffer + 1] = flushed - - if mode == _FLUSH_MODE_MEMORY_CLEANUP then - return total_bitlen - else - return total_bitlen, table_concat(result_buffer) - end - end - - return WriteBits, WriteString, FlushWriter -end - --- Push an element into a max heap --- @param heap A max heap whose max element is at index 1. --- @param e The element to be pushed. Assume element "e" is a table --- and comparison is done via its first entry e[1] --- @param heap_size current number of elements in the heap. --- NOTE: There may be some garbage stored in --- heap[heap_size+1], heap[heap_size+2], etc.. --- @return nil -local function MinHeapPush(heap, e, heap_size) - heap_size = heap_size + 1 - heap[heap_size] = e - local value = e[1] - local pos = heap_size - local parent_pos = (pos - pos % 2) / 2 - - while (parent_pos >= 1 and heap[parent_pos][1] > value) do - local t = heap[parent_pos] - heap[parent_pos] = e - heap[pos] = t - pos = parent_pos - parent_pos = (parent_pos - parent_pos % 2) / 2 - end -end - --- Pop an element from a max heap --- @param heap A max heap whose max element is at index 1. --- @param heap_size current number of elements in the heap. --- @return the poped element --- Note: This function does not change table size of "heap" to save CPU time. -local function MinHeapPop(heap, heap_size) - local top = heap[1] - local e = heap[heap_size] - local value = e[1] - heap[1] = e - heap[heap_size] = top - heap_size = heap_size - 1 - - local pos = 1 - local left_child_pos = pos * 2 - local right_child_pos = left_child_pos + 1 - - while (left_child_pos <= heap_size) do - local left_child = heap[left_child_pos] - if (right_child_pos <= heap_size and heap[right_child_pos][1] < - left_child[1]) then - local right_child = heap[right_child_pos] - if right_child[1] < value then - heap[right_child_pos] = e - heap[pos] = right_child - pos = right_child_pos - left_child_pos = pos * 2 - right_child_pos = left_child_pos + 1 - else - break - end - else - if left_child[1] < value then - heap[left_child_pos] = e - heap[pos] = left_child - pos = left_child_pos - left_child_pos = pos * 2 - right_child_pos = left_child_pos + 1 - else - break - end - end - end - - return top -end - --- Deflate defines a special huffman tree, which is unique once the bit length --- of huffman code of all symbols are known. --- @param bitlen_count Number of symbols with a specific bitlen --- @param symbol_bitlen The bit length of a symbol --- @param max_symbol The max symbol among all symbols, --- which is (number of symbols - 1) --- @param max_bitlen The max huffman bit length among all symbols. --- @return The huffman code of all symbols. -local function GetHuffmanCodeFromBitlen(bitlen_counts, symbol_bitlens, - max_symbol, max_bitlen) - local huffman_code = 0 - local next_codes = {} - local symbol_huffman_codes = {} - for bitlen = 1, max_bitlen do - huffman_code = (huffman_code + (bitlen_counts[bitlen - 1] or 0)) * 2 - next_codes[bitlen] = huffman_code - end - for symbol = 0, max_symbol do - local bitlen = symbol_bitlens[symbol] - if bitlen then - huffman_code = next_codes[bitlen] - next_codes[bitlen] = huffman_code + 1 - - -- Reverse the bits of huffman code, - -- because most signifant bits of huffman code - -- is stored first into the compressed data. - -- @see RFC1951 Page5 Section 3.1.1 - if bitlen <= 9 then -- Have cached reverse for small bitlen. - symbol_huffman_codes[symbol] = _reverse_bits_tbl[bitlen][huffman_code] - else - local reverse = 0 - for _ = 1, bitlen do - reverse = reverse - reverse % 2 + - (((reverse % 2 == 1) or (huffman_code % 2) == 1) and 1 or - 0) - huffman_code = (huffman_code - huffman_code % 2) / 2 - reverse = reverse * 2 - end - symbol_huffman_codes[symbol] = (reverse - reverse % 2) / 2 - end - end - end - return symbol_huffman_codes -end - --- A helper function to sort heap elements --- a[1], b[1] is the huffman frequency --- a[2], b[2] is the symbol value. -local function SortByFirstThenSecond(a, b) - return a[1] < b[1] or (a[1] == b[1] and a[2] < b[2]) -end - --- Calculate the huffman bit length and huffman code. --- @param symbol_count: A table whose table key is the symbol, and table value --- is the symbol frenquency (nil means 0 frequency). --- @param max_bitlen: See description of return value. --- @param max_symbol: The maximum symbol --- @return a table whose key is the symbol, and the value is the huffman bit --- bit length. We guarantee that all bit length <= max_bitlen. --- For 0<=symbol<=max_symbol, table value could be nil if the frequency --- of the symbol is 0 or nil. --- @return a table whose key is the symbol, and the value is the huffman code. --- @return a number indicating the maximum symbol whose bitlen is not 0. -local function GetHuffmanBitlenAndCode(symbol_counts, max_bitlen, max_symbol) - local heap_size - local max_non_zero_bitlen_symbol = -1 - local leafs = {} - local heap = {} - local symbol_bitlens = {} - local symbol_codes = {} - local bitlen_counts = {} - - --[[ - tree[1]: weight, temporarily used as parent and bitLengths - tree[2]: symbol - tree[3]: left child - tree[4]: right child - --]] - local number_unique_symbols = 0 - for symbol, count in pairs(symbol_counts) do - number_unique_symbols = number_unique_symbols + 1 - leafs[number_unique_symbols] = {count, symbol} - end - - if (number_unique_symbols == 0) then - -- no code. - return {}, {}, -1 - elseif (number_unique_symbols == 1) then - -- Only one code. In this case, its huffman code - -- needs to be assigned as 0, and bit length is 1. - -- This is the only case that the return result - -- represents an imcomplete huffman tree. - local symbol = leafs[1][2] - symbol_bitlens[symbol] = 1 - symbol_codes[symbol] = 0 - return symbol_bitlens, symbol_codes, symbol - else - table_sort(leafs, SortByFirstThenSecond) - heap_size = number_unique_symbols - for i = 1, heap_size do heap[i] = leafs[i] end - - while (heap_size > 1) do - -- Note: pop does not change table size of heap - local leftChild = MinHeapPop(heap, heap_size) - heap_size = heap_size - 1 - local rightChild = MinHeapPop(heap, heap_size) - heap_size = heap_size - 1 - local newNode = {leftChild[1] + rightChild[1], -1, leftChild, rightChild} - MinHeapPush(heap, newNode, heap_size) - heap_size = heap_size + 1 - end - - -- Number of leafs whose bit length is greater than max_len. - local number_bitlen_overflow = 0 - - -- Calculate bit length of all nodes - local fifo = {heap[1], 0, 0, 0} -- preallocate some spaces. - local fifo_size = 1 - local index = 1 - heap[1][1] = 0 - while (index <= fifo_size) do -- Breath first search - local e = fifo[index] - local bitlen = e[1] - local symbol = e[2] - local left_child = e[3] - local right_child = e[4] - if left_child then - fifo_size = fifo_size + 1 - fifo[fifo_size] = left_child - left_child[1] = bitlen + 1 - end - if right_child then - fifo_size = fifo_size + 1 - fifo[fifo_size] = right_child - right_child[1] = bitlen + 1 - end - index = index + 1 - - if (bitlen > max_bitlen) then - number_bitlen_overflow = number_bitlen_overflow + 1 - bitlen = max_bitlen - end - if symbol >= 0 then - symbol_bitlens[symbol] = bitlen - max_non_zero_bitlen_symbol = (symbol > max_non_zero_bitlen_symbol) and - symbol or max_non_zero_bitlen_symbol - bitlen_counts[bitlen] = (bitlen_counts[bitlen] or 0) + 1 - end - end - - -- Resolve bit length overflow - -- @see ZLib/trees.c:gen_bitlen(s, desc), for reference - if (number_bitlen_overflow > 0) then - repeat - local bitlen = max_bitlen - 1 - while ((bitlen_counts[bitlen] or 0) == 0) do bitlen = bitlen - 1 end - -- move one leaf down the tree - bitlen_counts[bitlen] = bitlen_counts[bitlen] - 1 - -- move one overflow item as its brother - bitlen_counts[bitlen + 1] = (bitlen_counts[bitlen + 1] or 0) + 2 - bitlen_counts[max_bitlen] = bitlen_counts[max_bitlen] - 1 - number_bitlen_overflow = number_bitlen_overflow - 2 - until (number_bitlen_overflow <= 0) - - index = 1 - for bitlen = max_bitlen, 1, -1 do - local n = bitlen_counts[bitlen] or 0 - while (n > 0) do - local symbol = leafs[index][2] - symbol_bitlens[symbol] = bitlen - n = n - 1 - index = index + 1 - end - end - end - - symbol_codes = GetHuffmanCodeFromBitlen(bitlen_counts, symbol_bitlens, - max_symbol, max_bitlen) - return symbol_bitlens, symbol_codes, max_non_zero_bitlen_symbol - end -end - --- Calculate the first huffman header in the dynamic huffman block --- @see RFC1951 Page 12 --- @param lcode_bitlen: The huffman bit length of literal/LZ77_length. --- @param max_non_zero_bitlen_lcode: The maximum literal/LZ77_length symbol --- whose huffman bit length is not zero. --- @param dcode_bitlen: The huffman bit length of LZ77 distance. --- @param max_non_zero_bitlen_dcode: The maximum LZ77 distance symbol --- whose huffman bit length is not zero. --- @return The run length encoded codes. --- @return The extra bits. One entry for each rle code that needs extra bits. --- (code == 16 or 17 or 18). --- @return The count of appearance of each rle codes. -local function RunLengthEncodeHuffmanBitlen(lcode_bitlens, - max_non_zero_bitlen_lcode, - dcode_bitlens, - max_non_zero_bitlen_dcode) - local rle_code_tblsize = 0 - local rle_codes = {} - local rle_code_counts = {} - local rle_extra_bits_tblsize = 0 - local rle_extra_bits = {} - local prev = nil - local count = 0 - - -- If there is no distance code, assume one distance code of bit length 0. - -- RFC1951: One distance code of zero bits means that - -- there are no distance codes used at all (the data is all literals). - max_non_zero_bitlen_dcode = (max_non_zero_bitlen_dcode < 0) and 0 or - max_non_zero_bitlen_dcode - local max_code = max_non_zero_bitlen_lcode + max_non_zero_bitlen_dcode + 1 - - for code = 0, max_code + 1 do - local len = (code <= max_non_zero_bitlen_lcode) and - (lcode_bitlens[code] or 0) or ((code <= max_code) and - (dcode_bitlens[code - max_non_zero_bitlen_lcode - 1] or 0) or - nil) - if len == prev then - count = count + 1 - if len ~= 0 and count == 6 then - rle_code_tblsize = rle_code_tblsize + 1 - rle_codes[rle_code_tblsize] = 16 - rle_extra_bits_tblsize = rle_extra_bits_tblsize + 1 - rle_extra_bits[rle_extra_bits_tblsize] = 3 - rle_code_counts[16] = (rle_code_counts[16] or 0) + 1 - count = 0 - elseif len == 0 and count == 138 then - rle_code_tblsize = rle_code_tblsize + 1 - rle_codes[rle_code_tblsize] = 18 - rle_extra_bits_tblsize = rle_extra_bits_tblsize + 1 - rle_extra_bits[rle_extra_bits_tblsize] = 127 - rle_code_counts[18] = (rle_code_counts[18] or 0) + 1 - count = 0 - end - else - if count == 1 then - rle_code_tblsize = rle_code_tblsize + 1 - rle_codes[rle_code_tblsize] = prev - rle_code_counts[prev] = (rle_code_counts[prev] or 0) + 1 - elseif count == 2 then - rle_code_tblsize = rle_code_tblsize + 1 - rle_codes[rle_code_tblsize] = prev - rle_code_tblsize = rle_code_tblsize + 1 - rle_codes[rle_code_tblsize] = prev - rle_code_counts[prev] = (rle_code_counts[prev] or 0) + 2 - elseif count >= 3 then - rle_code_tblsize = rle_code_tblsize + 1 - local rleCode = (prev ~= 0) and 16 or (count <= 10 and 17 or 18) - rle_codes[rle_code_tblsize] = rleCode - rle_code_counts[rleCode] = (rle_code_counts[rleCode] or 0) + 1 - rle_extra_bits_tblsize = rle_extra_bits_tblsize + 1 - rle_extra_bits[rle_extra_bits_tblsize] = - (count <= 10) and (count - 3) or (count - 11) - end - - prev = len - if len and len ~= 0 then - rle_code_tblsize = rle_code_tblsize + 1 - rle_codes[rle_code_tblsize] = len - rle_code_counts[len] = (rle_code_counts[len] or 0) + 1 - count = 0 - else - count = 1 - end - end - end - - return rle_codes, rle_extra_bits, rle_code_counts -end - --- Load the string into a table, in order to speed up LZ77. --- Loop unrolled 16 times to speed this function up. --- @param str The string to be loaded. --- @param t The load destination --- @param start str[index] will be the first character to be loaded. --- @param end str[index] will be the last character to be loaded --- @param offset str[index] will be loaded into t[index-offset] --- @return t -local function LoadStringToTable(str, t, start, stop, offset) - local i = start - offset - while i <= stop - 15 - offset do - t[i], t[i + 1], t[i + 2], t[i + 3], t[i + 4], t[i + 5], t[i + 6], t[i + 7], t[i + - 8], t[i + 9], t[i + 10], t[i + 11], t[i + 12], t[i + 13], t[i + 14], t[i + - 15] = string_byte(str, i + offset, i + 15 + offset) - i = i + 16 - end - while (i <= stop - offset) do - t[i] = string_byte(str, i + offset, i + offset) - i = i + 1 - end - return t -end - --- Do LZ77 process. This function uses the majority of the CPU time. --- @see zlib/deflate.c:deflate_fast(), zlib/deflate.c:deflate_slow() --- @see https://github.com/madler/zlib/blob/master/doc/algorithm.txt --- This function uses the algorithms used above. You should read the --- algorithm.txt above to understand what is the hash function and the --- lazy evaluation. --- --- The special optimization used here is hash functions used here. --- The hash function is just the multiplication of the three consective --- characters. So if the hash matches, it guarantees 3 characters are matched. --- This optimization can be implemented because Lua table is a hash table. --- --- @param level integer that describes compression level. --- @param string_table table that stores the value of string to be compressed. --- The index of this table starts from 1. --- The caller needs to make sure all values needed by this function --- are loaded. --- Assume "str" is the origin input string into the compressor --- str[block_start]..str[block_end+3] needs to be loaded into --- string_table[block_start-offset]..string_table[block_end-offset] --- If dictionary is presented, the last 258 bytes of the dictionary --- needs to be loaded into sing_table[-257..0] --- (See more in the description of offset.) --- @param hash_tables. The table key is the hash value (0<=hash<=16777216=256^3) --- The table value is an array0 that stores the indexes of the --- input data string to be compressed, such that --- hash == str[index]*str[index+1]*str[index+2] --- Indexes are ordered in this array. --- @param block_start The indexes of the input data string to be compressed. --- that starts the LZ77 block. --- @param block_end The indexes of the input data string to be compressed. --- that stores the LZ77 block. --- @param offset str[index] is stored in string_table[index-offset], --- This offset is mainly an optimization to limit the index --- of string_table, so lua can access this table quicker. --- @param dictionary See LibDeflate:CreateDictionary --- @return literal/LZ77_length deflate codes. --- @return the extra bits of literal/LZ77_length deflate codes. --- @return the count of each literal/LZ77 deflate code. --- @return LZ77 distance deflate codes. --- @return the extra bits of LZ77 distance deflate codes. --- @return the count of each LZ77 distance deflate code. -local function GetBlockLZ77Result(level, string_table, hash_tables, block_start, - block_end, offset, dictionary) - local config = _compression_level_configs[level] - local config_use_lazy, config_good_prev_length, config_max_lazy_match, - config_nice_length, config_max_hash_chain = config[1], config[2], - config[3], config[4], - config[5] - - local config_max_insert_length = (not config_use_lazy) and - config_max_lazy_match or 2147483646 - local config_good_hash_chain = - (config_max_hash_chain - config_max_hash_chain % 4 / 4) - - local hash - - local dict_hash_tables - local dict_string_table - local dict_string_len = 0 - - if dictionary then - dict_hash_tables = dictionary.hash_tables - dict_string_table = dictionary.string_table - dict_string_len = dictionary.strlen - assert(block_start == 1) - if block_end >= block_start and dict_string_len >= 2 then - hash = dict_string_table[dict_string_len - 1] * 65536 + - dict_string_table[dict_string_len] * 256 + string_table[1] - local t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = -1 - end - if block_end >= block_start + 1 and dict_string_len >= 1 then - hash = - dict_string_table[dict_string_len] * 65536 + string_table[1] * 256 + - string_table[2] - local t = hash_tables[hash] - if not t then - t = {}; - hash_tables[hash] = t - end - t[#t + 1] = 0 - end - end - - local dict_string_len_plus3 = dict_string_len + 3 - - hash = (string_table[block_start - offset] or 0) * 256 + - (string_table[block_start + 1 - offset] or 0) - - local lcodes = {} - local lcode_tblsize = 0 - local lcodes_counts = {} - local dcodes = {} - local dcodes_tblsize = 0 - local dcodes_counts = {} - - local lextra_bits = {} - local lextra_bits_tblsize = 0 - local dextra_bits = {} - local dextra_bits_tblsize = 0 - - local match_available = false - local prev_len - local prev_dist - local cur_len = 0 - local cur_dist = 0 - - local index = block_start - local index_end = block_end + (config_use_lazy and 1 or 0) - - -- the zlib source code writes separate code for lazy evaluation and - -- not lazy evaluation, which is easier to understand. - -- I put them together, so it is a bit harder to understand. - -- because I think this is easier for me to maintain it. - while (index <= index_end) do - local string_table_index = index - offset - local offset_minus_three = offset - 3 - prev_len = cur_len - prev_dist = cur_dist - cur_len = 0 - - hash = (hash * 256 + (string_table[string_table_index + 2] or 0)) % 16777216 - - local chain_index - local cur_chain - local hash_chain = hash_tables[hash] - local chain_old_size - if not hash_chain then - chain_old_size = 0 - hash_chain = {} - hash_tables[hash] = hash_chain - if dict_hash_tables then - cur_chain = dict_hash_tables[hash] - chain_index = cur_chain and #cur_chain or 0 - else - chain_index = 0 - end - else - chain_old_size = #hash_chain - cur_chain = hash_chain - chain_index = chain_old_size - end - - if index <= block_end then hash_chain[chain_old_size + 1] = index end - - if (chain_index > 0 and index + 2 <= block_end and - (not config_use_lazy or prev_len < config_max_lazy_match)) then - - local depth = - (config_use_lazy and prev_len >= config_good_prev_length) and - config_good_hash_chain or config_max_hash_chain - - local max_len_minus_one = block_end - index - max_len_minus_one = (max_len_minus_one >= 257) and 257 or - max_len_minus_one - max_len_minus_one = max_len_minus_one + string_table_index - local string_table_index_plus_three = string_table_index + 3 - - while chain_index >= 1 and depth > 0 do - local prev = cur_chain[chain_index] - - if index - prev > 32768 then break end - if prev < index then - local sj = string_table_index_plus_three - - if prev >= -257 then - local pj = prev - offset_minus_three - while (sj <= max_len_minus_one and string_table[pj] == - string_table[sj]) do - sj = sj + 1 - pj = pj + 1 - end - else - local pj = dict_string_len_plus3 + prev - while (sj <= max_len_minus_one and dict_string_table[pj] == - string_table[sj]) do - sj = sj + 1 - pj = pj + 1 - end - end - local j = sj - string_table_index - if j > cur_len then - cur_len = j - cur_dist = index - prev - end - if cur_len >= config_nice_length then break end - end - - chain_index = chain_index - 1 - depth = depth - 1 - if chain_index == 0 and prev > 0 and dict_hash_tables then - cur_chain = dict_hash_tables[hash] - chain_index = cur_chain and #cur_chain or 0 - end - end - end - - if not config_use_lazy then prev_len, prev_dist = cur_len, cur_dist end - if ((not config_use_lazy or match_available) and - (prev_len > 3 or (prev_len == 3 and prev_dist < 4096)) and cur_len <= - prev_len) then - local code = _length_to_deflate_code[prev_len] - local length_extra_bits_bitlen = _length_to_deflate_extra_bitlen[prev_len] - local dist_code, dist_extra_bits_bitlen, dist_extra_bits - if prev_dist <= 256 then -- have cached code for small distance. - dist_code = _dist256_to_deflate_code[prev_dist] - dist_extra_bits = _dist256_to_deflate_extra_bits[prev_dist] - dist_extra_bits_bitlen = _dist256_to_deflate_extra_bitlen[prev_dist] - else - dist_code = 16 - dist_extra_bits_bitlen = 7 - local a = 384 - local b = 512 - - while true do - if prev_dist <= a then - dist_extra_bits = (prev_dist - (b / 2) - 1) % (b / 4) - break - elseif prev_dist <= b then - dist_extra_bits = (prev_dist - (b / 2) - 1) % (b / 4) - dist_code = dist_code + 1 - break - else - dist_code = dist_code + 2 - dist_extra_bits_bitlen = dist_extra_bits_bitlen + 1 - a = a * 2 - b = b * 2 - end - end - end - lcode_tblsize = lcode_tblsize + 1 - lcodes[lcode_tblsize] = code - lcodes_counts[code] = (lcodes_counts[code] or 0) + 1 - - dcodes_tblsize = dcodes_tblsize + 1 - dcodes[dcodes_tblsize] = dist_code - dcodes_counts[dist_code] = (dcodes_counts[dist_code] or 0) + 1 - - if length_extra_bits_bitlen > 0 then - local lenExtraBits = _length_to_deflate_extra_bits[prev_len] - lextra_bits_tblsize = lextra_bits_tblsize + 1 - lextra_bits[lextra_bits_tblsize] = lenExtraBits - end - if dist_extra_bits_bitlen > 0 then - dextra_bits_tblsize = dextra_bits_tblsize + 1 - dextra_bits[dextra_bits_tblsize] = dist_extra_bits - end - - for i = index + 1, index + prev_len - (config_use_lazy and 2 or 1) do - hash = (hash * 256 + (string_table[i - offset + 2] or 0)) % 16777216 - if prev_len <= config_max_insert_length then - hash_chain = hash_tables[hash] - if not hash_chain then - hash_chain = {} - hash_tables[hash] = hash_chain - end - hash_chain[#hash_chain + 1] = i - end - end - index = index + prev_len - (config_use_lazy and 1 or 0) - match_available = false - elseif (not config_use_lazy) or match_available then - local code = string_table[config_use_lazy and (string_table_index - 1) or - string_table_index] - lcode_tblsize = lcode_tblsize + 1 - lcodes[lcode_tblsize] = code - lcodes_counts[code] = (lcodes_counts[code] or 0) + 1 - index = index + 1 - else - match_available = true - index = index + 1 - end - end - - -- Write "end of block" symbol - lcode_tblsize = lcode_tblsize + 1 - lcodes[lcode_tblsize] = 256 - lcodes_counts[256] = (lcodes_counts[256] or 0) + 1 - - return lcodes, lextra_bits, lcodes_counts, dcodes, dextra_bits, dcodes_counts -end - --- Get the header data of dynamic block. --- @param lcodes_count The count of each literal/LZ77_length codes. --- @param dcodes_count The count of each Lz77 distance codes. --- @return a lots of stuffs. --- @see RFC1951 Page 12 -local function GetBlockDynamicHuffmanHeader(lcodes_counts, dcodes_counts) - local lcodes_huffman_bitlens, lcodes_huffman_codes, max_non_zero_bitlen_lcode = - GetHuffmanBitlenAndCode(lcodes_counts, 15, 285) - local dcodes_huffman_bitlens, dcodes_huffman_codes, max_non_zero_bitlen_dcode = - GetHuffmanBitlenAndCode(dcodes_counts, 15, 29) - - local rle_deflate_codes, rle_extra_bits, rle_codes_counts = - RunLengthEncodeHuffmanBitlen(lcodes_huffman_bitlens, - max_non_zero_bitlen_lcode, - dcodes_huffman_bitlens, - max_non_zero_bitlen_dcode) - - local rle_codes_huffman_bitlens, rle_codes_huffman_codes = - GetHuffmanBitlenAndCode(rle_codes_counts, 7, 18) - - local HCLEN = 0 - for i = 1, 19 do - local symbol = _rle_codes_huffman_bitlen_order[i] - local length = rle_codes_huffman_bitlens[symbol] or 0 - if length ~= 0 then HCLEN = i end - end - - HCLEN = HCLEN - 4 - local HLIT = max_non_zero_bitlen_lcode + 1 - 257 - local HDIST = max_non_zero_bitlen_dcode + 1 - 1 - if HDIST < 0 then HDIST = 0 end - - return HLIT, HDIST, HCLEN, rle_codes_huffman_bitlens, rle_codes_huffman_codes, - rle_deflate_codes, rle_extra_bits, lcodes_huffman_bitlens, - lcodes_huffman_codes, dcodes_huffman_bitlens, dcodes_huffman_codes -end - --- Get the size of dynamic block without writing any bits into the writer. --- @param ... Read the source code of GetBlockDynamicHuffmanHeader() --- @return the bit length of the dynamic block -local function GetDynamicHuffmanBlockSize(lcodes, dcodes, HCLEN, - rle_codes_huffman_bitlens, - rle_deflate_codes, - lcodes_huffman_bitlens, - dcodes_huffman_bitlens) - - local block_bitlen = 17 -- 1+2+5+5+4 - block_bitlen = block_bitlen + (HCLEN + 4) * 3 - - for i = 1, #rle_deflate_codes do - local code = rle_deflate_codes[i] - block_bitlen = block_bitlen + rle_codes_huffman_bitlens[code] - if code >= 16 then - block_bitlen = block_bitlen + - ((code == 16) and 2 or (code == 17 and 3 or 7)) - end - end - - local length_code_count = 0 - for i = 1, #lcodes do - local code = lcodes[i] - local huffman_bitlen = lcodes_huffman_bitlens[code] - block_bitlen = block_bitlen + huffman_bitlen - if code > 256 then -- Length code - length_code_count = length_code_count + 1 - if code > 264 and code < 285 then -- Length code with extra bits - local extra_bits_bitlen = _literal_deflate_code_to_extra_bitlen[code - - 256] - block_bitlen = block_bitlen + extra_bits_bitlen - end - local dist_code = dcodes[length_code_count] - local dist_huffman_bitlen = dcodes_huffman_bitlens[dist_code] - block_bitlen = block_bitlen + dist_huffman_bitlen - - if dist_code > 3 then -- dist code with extra bits - local dist_extra_bits_bitlen = (dist_code - dist_code % 2) / 2 - 1 - block_bitlen = block_bitlen + dist_extra_bits_bitlen - end - end - end - return block_bitlen -end - --- Write dynamic block. --- @param ... Read the source code of GetBlockDynamicHuffmanHeader() -local function CompressDynamicHuffmanBlock(WriteBits, is_last_block, lcodes, - lextra_bits, dcodes, dextra_bits, - HLIT, HDIST, HCLEN, - rle_codes_huffman_bitlens, - rle_codes_huffman_codes, - rle_deflate_codes, rle_extra_bits, - lcodes_huffman_bitlens, - lcodes_huffman_codes, - dcodes_huffman_bitlens, - dcodes_huffman_codes) - - WriteBits(is_last_block and 1 or 0, 1) -- Last block identifier - WriteBits(2, 2) -- Dynamic Huffman block identifier - - WriteBits(HLIT, 5) - WriteBits(HDIST, 5) - WriteBits(HCLEN, 4) - - for i = 1, HCLEN + 4 do - local symbol = _rle_codes_huffman_bitlen_order[i] - local length = rle_codes_huffman_bitlens[symbol] or 0 - WriteBits(length, 3) - end - - local rleExtraBitsIndex = 1 - for i = 1, #rle_deflate_codes do - local code = rle_deflate_codes[i] - WriteBits(rle_codes_huffman_codes[code], rle_codes_huffman_bitlens[code]) - if code >= 16 then - local extraBits = rle_extra_bits[rleExtraBitsIndex] - WriteBits(extraBits, (code == 16) and 2 or (code == 17 and 3 or 7)) - rleExtraBitsIndex = rleExtraBitsIndex + 1 - end - end - - local length_code_count = 0 - local length_code_with_extra_count = 0 - local dist_code_with_extra_count = 0 - - for i = 1, #lcodes do - local deflate_codee = lcodes[i] - local huffman_code = lcodes_huffman_codes[deflate_codee] - local huffman_bitlen = lcodes_huffman_bitlens[deflate_codee] - WriteBits(huffman_code, huffman_bitlen) - if deflate_codee > 256 then -- Length code - length_code_count = length_code_count + 1 - if deflate_codee > 264 and deflate_codee < 285 then - -- Length code with extra bits - length_code_with_extra_count = length_code_with_extra_count + 1 - local extra_bits = lextra_bits[length_code_with_extra_count] - local extra_bits_bitlen = - _literal_deflate_code_to_extra_bitlen[deflate_codee - 256] - WriteBits(extra_bits, extra_bits_bitlen) - end - -- Write distance code - local dist_deflate_code = dcodes[length_code_count] - local dist_huffman_code = dcodes_huffman_codes[dist_deflate_code] - local dist_huffman_bitlen = dcodes_huffman_bitlens[dist_deflate_code] - WriteBits(dist_huffman_code, dist_huffman_bitlen) - - if dist_deflate_code > 3 then -- dist code with extra bits - dist_code_with_extra_count = dist_code_with_extra_count + 1 - local dist_extra_bits = dextra_bits[dist_code_with_extra_count] - local dist_extra_bits_bitlen = (dist_deflate_code - dist_deflate_code % - 2) / 2 - 1 - WriteBits(dist_extra_bits, dist_extra_bits_bitlen) - end - end - end -end - --- Get the size of fixed block without writing any bits into the writer. --- @param lcodes literal/LZ77_length deflate codes --- @param decodes LZ77 distance deflate codes --- @return the bit length of the fixed block -local function GetFixedHuffmanBlockSize(lcodes, dcodes) - local block_bitlen = 3 - local length_code_count = 0 - for i = 1, #lcodes do - local code = lcodes[i] - local huffman_bitlen = _fix_block_literal_huffman_bitlen[code] - block_bitlen = block_bitlen + huffman_bitlen - if code > 256 then -- Length code - length_code_count = length_code_count + 1 - if code > 264 and code < 285 then -- Length code with extra bits - local extra_bits_bitlen = _literal_deflate_code_to_extra_bitlen[code - - 256] - block_bitlen = block_bitlen + extra_bits_bitlen - end - local dist_code = dcodes[length_code_count] - block_bitlen = block_bitlen + 5 - - if dist_code > 3 then -- dist code with extra bits - local dist_extra_bits_bitlen = (dist_code - dist_code % 2) / 2 - 1 - block_bitlen = block_bitlen + dist_extra_bits_bitlen - end - end - end - return block_bitlen -end - --- Write fixed block. --- @param lcodes literal/LZ77_length deflate codes --- @param decodes LZ77 distance deflate codes -local function CompressFixedHuffmanBlock(WriteBits, is_last_block, lcodes, - lextra_bits, dcodes, dextra_bits) - WriteBits(is_last_block and 1 or 0, 1) -- Last block identifier - WriteBits(1, 2) -- Fixed Huffman block identifier - local length_code_count = 0 - local length_code_with_extra_count = 0 - local dist_code_with_extra_count = 0 - for i = 1, #lcodes do - local deflate_code = lcodes[i] - local huffman_code = _fix_block_literal_huffman_code[deflate_code] - local huffman_bitlen = _fix_block_literal_huffman_bitlen[deflate_code] - WriteBits(huffman_code, huffman_bitlen) - if deflate_code > 256 then -- Length code - length_code_count = length_code_count + 1 - if deflate_code > 264 and deflate_code < 285 then - -- Length code with extra bits - length_code_with_extra_count = length_code_with_extra_count + 1 - local extra_bits = lextra_bits[length_code_with_extra_count] - local extra_bits_bitlen = - _literal_deflate_code_to_extra_bitlen[deflate_code - 256] - WriteBits(extra_bits, extra_bits_bitlen) - end - -- Write distance code - local dist_code = dcodes[length_code_count] - local dist_huffman_code = _fix_block_dist_huffman_code[dist_code] - WriteBits(dist_huffman_code, 5) - - if dist_code > 3 then -- dist code with extra bits - dist_code_with_extra_count = dist_code_with_extra_count + 1 - local dist_extra_bits = dextra_bits[dist_code_with_extra_count] - local dist_extra_bits_bitlen = (dist_code - dist_code % 2) / 2 - 1 - WriteBits(dist_extra_bits, dist_extra_bits_bitlen) - end - end - end -end - --- Get the size of store block without writing any bits into the writer. --- @param block_start The start index of the origin input string --- @param block_end The end index of the origin input string --- @param Total bit lens had been written into the compressed result before, --- because store block needs to shift to byte boundary. --- @return the bit length of the fixed block -local function GetStoreBlockSize(block_start, block_end, total_bitlen) - assert(block_end - block_start + 1 <= 65535) - local block_bitlen = 3 - total_bitlen = total_bitlen + 3 - local padding_bitlen = (8 - total_bitlen % 8) % 8 - block_bitlen = block_bitlen + padding_bitlen - block_bitlen = block_bitlen + 32 - block_bitlen = block_bitlen + (block_end - block_start + 1) * 8 - return block_bitlen -end - --- Write the store block. --- @param ... lots of stuffs --- @return nil -local function CompressStoreBlock(WriteBits, WriteString, is_last_block, str, - block_start, block_end, total_bitlen) - assert(block_end - block_start + 1 <= 65535) - WriteBits(is_last_block and 1 or 0, 1) -- Last block identifer. - WriteBits(0, 2) -- Store block identifier. - total_bitlen = total_bitlen + 3 - local padding_bitlen = (8 - total_bitlen % 8) % 8 - if padding_bitlen > 0 then - WriteBits(_pow2[padding_bitlen] - 1, padding_bitlen) - end - local size = block_end - block_start + 1 - WriteBits(size, 16) - - -- Write size's one's complement - local comp = (255 - size % 256) + (255 - (size - size % 256) / 256) * 256 - WriteBits(comp, 16) - - WriteString(str:sub(block_start, block_end)) -end - --- Do the deflate --- Currently using a simple way to determine the block size --- (This is why the compression ratio is little bit worse than zlib when --- the input size is very large --- The first block is 64KB, the following block is 32KB. --- After each block, there is a memory cleanup operation. --- This is not a fast operation, but it is needed to save memory usage, so --- the memory usage does not grow unboundly. If the data size is less than --- 64KB, then memory cleanup won't happen. --- This function determines whether to use store/fixed/dynamic blocks by --- calculating the block size of each block type and chooses the smallest one. -local function Deflate(configs, WriteBits, WriteString, FlushWriter, str, - dictionary) - local string_table = {} - local hash_tables = {} - local is_last_block = nil - local block_start - local block_end - local bitlen_written - local total_bitlen = FlushWriter(_FLUSH_MODE_NO_FLUSH) - local strlen = #str - local offset - - local level - local strategy - if configs then - if configs.level then level = configs.level end - if configs.strategy then strategy = configs.strategy end - end - - if not level then - if strlen < 2048 then - level = 7 - elseif strlen > 65536 then - level = 3 - else - level = 5 - end - end - - while not is_last_block do - if not block_start then - block_start = 1 - block_end = 64 * 1024 - 1 - offset = 0 - else - block_start = block_end + 1 - block_end = block_end + 32 * 1024 - offset = block_start - 32 * 1024 - 1 - end - - if block_end >= strlen then - block_end = strlen - is_last_block = true - else - is_last_block = false - end - - local lcodes, lextra_bits, lcodes_counts, dcodes, dextra_bits, dcodes_counts - - local HLIT, HDIST, HCLEN, rle_codes_huffman_bitlens, - rle_codes_huffman_codes, rle_deflate_codes, rle_extra_bits, - lcodes_huffman_bitlens, lcodes_huffman_codes, dcodes_huffman_bitlens, - dcodes_huffman_codes - - local dynamic_block_bitlen - local fixed_block_bitlen - local store_block_bitlen - - if level ~= 0 then - - -- GetBlockLZ77 needs block_start to block_end+3 to be loaded. - LoadStringToTable(str, string_table, block_start, block_end + 3, offset) - if block_start == 1 and dictionary then - local dict_string_table = dictionary.string_table - local dict_strlen = dictionary.strlen - for i = 0, (-dict_strlen + 1) < -257 and -257 or (-dict_strlen + 1), -1 do - string_table[i] = dict_string_table[dict_strlen + i] - end - end - - if strategy == "huffman_only" then - lcodes = {} - LoadStringToTable(str, lcodes, block_start, block_end, block_start - 1) - lextra_bits = {} - lcodes_counts = {} - lcodes[block_end - block_start + 2] = 256 -- end of block - for i = 1, block_end - block_start + 2 do - local code = lcodes[i] - lcodes_counts[code] = (lcodes_counts[code] or 0) + 1 - end - dcodes = {} - dextra_bits = {} - dcodes_counts = {} - else - lcodes, lextra_bits, lcodes_counts, dcodes, dextra_bits, dcodes_counts = - GetBlockLZ77Result(level, string_table, hash_tables, block_start, - block_end, offset, dictionary) - end - - -- LuaFormatter off - HLIT, HDIST, HCLEN, rle_codes_huffman_bitlens, rle_codes_huffman_codes, rle_deflate_codes, - rle_extra_bits, lcodes_huffman_bitlens, lcodes_huffman_codes, dcodes_huffman_bitlens, dcodes_huffman_codes = - -- LuaFormatter on - GetBlockDynamicHuffmanHeader(lcodes_counts, dcodes_counts) - dynamic_block_bitlen = GetDynamicHuffmanBlockSize(lcodes, dcodes, HCLEN, - rle_codes_huffman_bitlens, - rle_deflate_codes, - lcodes_huffman_bitlens, - dcodes_huffman_bitlens) - fixed_block_bitlen = GetFixedHuffmanBlockSize(lcodes, dcodes) - end - - store_block_bitlen = GetStoreBlockSize(block_start, block_end, total_bitlen) - - local min_bitlen = store_block_bitlen - min_bitlen = (fixed_block_bitlen and fixed_block_bitlen < min_bitlen) and - fixed_block_bitlen or min_bitlen - min_bitlen = - (dynamic_block_bitlen and dynamic_block_bitlen < min_bitlen) and - dynamic_block_bitlen or min_bitlen - - if level == 0 or - (strategy ~= "fixed" and strategy ~= "dynamic" and store_block_bitlen == - min_bitlen) then - CompressStoreBlock(WriteBits, WriteString, is_last_block, str, - block_start, block_end, total_bitlen) - total_bitlen = total_bitlen + store_block_bitlen - elseif strategy ~= "dynamic" and - (strategy == "fixed" or fixed_block_bitlen == min_bitlen) then - CompressFixedHuffmanBlock(WriteBits, is_last_block, lcodes, lextra_bits, - dcodes, dextra_bits) - total_bitlen = total_bitlen + fixed_block_bitlen - elseif strategy == "dynamic" or dynamic_block_bitlen == min_bitlen then - CompressDynamicHuffmanBlock(WriteBits, is_last_block, lcodes, lextra_bits, - dcodes, dextra_bits, HLIT, HDIST, HCLEN, - rle_codes_huffman_bitlens, - rle_codes_huffman_codes, rle_deflate_codes, - rle_extra_bits, lcodes_huffman_bitlens, - lcodes_huffman_codes, dcodes_huffman_bitlens, - dcodes_huffman_codes) - total_bitlen = total_bitlen + dynamic_block_bitlen - end - - if is_last_block then - bitlen_written = FlushWriter(_FLUSH_MODE_NO_FLUSH) - else - bitlen_written = FlushWriter(_FLUSH_MODE_MEMORY_CLEANUP) - end - - assert(bitlen_written == total_bitlen) - - -- Memory clean up, so memory consumption does not always grow linearly - -- , even if input string is > 64K. - -- Not a very efficient operation, but this operation won't happen - -- when the input data size is less than 64K. - if not is_last_block then - local j - if dictionary and block_start == 1 then - j = 0 - while (string_table[j]) do - string_table[j] = nil - j = j - 1 - end - end - dictionary = nil - j = 1 - for i = block_end - 32767, block_end do - string_table[j] = string_table[i - offset] - j = j + 1 - end - - for k, t in pairs(hash_tables) do - local tSize = #t - if tSize > 0 and block_end + 1 - t[1] > 32768 then - if tSize == 1 then - hash_tables[k] = nil - else - local new = {} - local newSize = 0 - for i = 2, tSize do - j = t[i] - if block_end + 1 - j <= 32768 then - newSize = newSize + 1 - new[newSize] = j - end - end - hash_tables[k] = new - end - end - end - end - end -end - ---- The description to compression configuration table.
--- Any field can be nil to use its default.
--- Table with keys other than those below is an invalid table. --- @class table --- @name compression_configs --- @field level The compression level ranged from 0 to 9. 0 is no compression. --- 9 is the slowest but best compression. Use nil for default level. --- @field strategy The compression strategy. "fixed" to only use fixed deflate --- compression block. "dynamic" to only use dynamic block. "huffman_only" to --- do no LZ77 compression. Only do huffman compression. - --- @see LibDeflate:CompressDeflate(str, configs) --- @see LibDeflate:CompressDeflateWithDict(str, dictionary, configs) -local function CompressDeflateInternal(str, dictionary, configs) - local WriteBits, WriteString, FlushWriter = CreateWriter() - Deflate(configs, WriteBits, WriteString, FlushWriter, str, dictionary) - local total_bitlen, result = FlushWriter(_FLUSH_MODE_OUTPUT) - local padding_bitlen = (8 - total_bitlen % 8) % 8 - return result, padding_bitlen -end - --- @see LibDeflate:CompressZlib --- @see LibDeflate:CompressZlibWithDict -local function CompressZlibInternal(str, dictionary, configs) - local WriteBits, WriteString, FlushWriter = CreateWriter() - - local CM = 8 -- Compression method - local CINFO = 7 -- Window Size = 32K - local CMF = CINFO * 16 + CM - WriteBits(CMF, 8) - - local FDIST = dictionary and 1 or 0 - local FLEVEL = 2 -- Default compression - local FLG = FLEVEL * 64 + FDIST * 32 - local FCHECK = (31 - (CMF * 256 + FLG) % 31) - -- The FCHECK value must be such that CMF and FLG, - -- when viewed as a 16-bit unsigned integer stored - -- in MSB order (CMF*256 + FLG), is a multiple of 31. - FLG = FLG + FCHECK - WriteBits(FLG, 8) - - if FDIST == 1 then - local adler32 = dictionary.adler32 - local byte0 = adler32 % 256 - adler32 = (adler32 - byte0) / 256 - local byte1 = adler32 % 256 - adler32 = (adler32 - byte1) / 256 - local byte2 = adler32 % 256 - adler32 = (adler32 - byte2) / 256 - local byte3 = adler32 % 256 - WriteBits(byte3, 8) - WriteBits(byte2, 8) - WriteBits(byte1, 8) - WriteBits(byte0, 8) - end - - Deflate(configs, WriteBits, WriteString, FlushWriter, str, dictionary) - FlushWriter(_FLUSH_MODE_BYTE_BOUNDARY) - - local adler32 = LibDeflate:Adler32(str) - - -- Most significant byte first - local byte3 = adler32 % 256 - adler32 = (adler32 - byte3) / 256 - local byte2 = adler32 % 256 - adler32 = (adler32 - byte2) / 256 - local byte1 = adler32 % 256 - adler32 = (adler32 - byte1) / 256 - local byte0 = adler32 % 256 - - WriteBits(byte0, 8) - WriteBits(byte1, 8) - WriteBits(byte2, 8) - WriteBits(byte3, 8) - local total_bitlen, result = FlushWriter(_FLUSH_MODE_OUTPUT) - local padding_bitlen = (8 - total_bitlen % 8) % 8 - return result, padding_bitlen -end - ---- Compress using the raw deflate format. --- @param str [string] The data to be compressed. --- @param configs [table/nil] The configuration table to control the compression --- . If nil, use the default configuration. --- @return [string] The compressed data. --- @return [integer] The number of bits padded at the end of output. --- 0 <= bits < 8
--- This means the most significant "bits" of the last byte of the returned --- compressed data are padding bits and they don't affect decompression. --- You don't need to use this value unless you want to do some postprocessing --- to the compressed data. --- @see compression_configs --- @see LibDeflate:DecompressDeflate -function LibDeflate:CompressDeflate(str, configs) - local arg_valid, arg_err = IsValidArguments(str, false, nil, true, configs) - if not arg_valid then - error(("Usage: LibDeflate:CompressDeflate(str, configs): " .. arg_err), 2) - end - return CompressDeflateInternal(str, nil, configs) -end - ---- Compress using the raw deflate format with a preset dictionary. --- @param str [string] The data to be compressed. --- @param dictionary [table] The preset dictionary produced by --- LibDeflate:CreateDictionary --- @param configs [table/nil] The configuration table to control the compression --- . If nil, use the default configuration. --- @return [string] The compressed data. --- @return [integer] The number of bits padded at the end of output. --- 0 <= bits < 8
--- This means the most significant "bits" of the last byte of the returned --- compressed data are padding bits and they don't affect decompression. --- You don't need to use this value unless you want to do some postprocessing --- to the compressed data. --- @see compression_configs --- @see LibDeflate:CreateDictionary --- @see LibDeflate:DecompressDeflateWithDict -function LibDeflate:CompressDeflateWithDict(str, dictionary, configs) - local arg_valid, arg_err = IsValidArguments(str, true, dictionary, true, - configs) - if not arg_valid then - error(("Usage: LibDeflate:CompressDeflateWithDict" .. - "(str, dictionary, configs): " .. arg_err), 2) - end - return CompressDeflateInternal(str, dictionary, configs) -end - ---- Compress using the zlib format. --- @param str [string] the data to be compressed. --- @param configs [table/nil] The configuration table to control the compression --- . If nil, use the default configuration. --- @return [string] The compressed data. --- @return [integer] The number of bits padded at the end of output. --- Should always be 0. --- Zlib formatted compressed data never has padding bits at the end. --- @see compression_configs --- @see LibDeflate:DecompressZlib -function LibDeflate:CompressZlib(str, configs) - local arg_valid, arg_err = IsValidArguments(str, false, nil, true, configs) - if not arg_valid then - error(("Usage: LibDeflate:CompressZlib(str, configs): " .. arg_err), 2) - end - return CompressZlibInternal(str, nil, configs) -end - ---- Compress using the zlib format with a preset dictionary. --- @param str [string] the data to be compressed. --- @param dictionary [table] A preset dictionary produced --- by LibDeflate:CreateDictionary() --- @param configs [table/nil] The configuration table to control the compression --- . If nil, use the default configuration. --- @return [string] The compressed data. --- @return [integer] The number of bits padded at the end of output. --- Should always be 0. --- Zlib formatted compressed data never has padding bits at the end. --- @see compression_configs --- @see LibDeflate:CreateDictionary --- @see LibDeflate:DecompressZlibWithDict -function LibDeflate:CompressZlibWithDict(str, dictionary, configs) - local arg_valid, arg_err = IsValidArguments(str, true, dictionary, true, - configs) - if not arg_valid then - error(("Usage: LibDeflate:CompressZlibWithDict" .. - "(str, dictionary, configs): " .. arg_err), 2) - end - return CompressZlibInternal(str, dictionary, configs) -end - ---[[ -------------------------------------------------------------------------- - Decompress code ---]] -------------------------------------------------------------------------- - ---[[ - Create a reader to easily reader stuffs as the unit of bits. - Return values: - 1. ReadBits(bitlen) - 2. ReadBytes(bytelen, buffer, buffer_size) - 3. Decode(huffman_bitlen_count, huffman_symbol, min_bitlen) - 4. ReaderBitlenLeft() - 5. SkipToByteBoundary() ---]] -local function CreateReader(input_string) - local input = input_string - local input_strlen = #input_string - local input_next_byte_pos = 1 - local cache_bitlen = 0 - local cache = 0 - - -- Read some bits. - -- To improve speed, this function does not - -- check if the input has been exhausted. - -- Use ReaderBitlenLeft() < 0 to check it. - -- @param bitlen the number of bits to read - -- @return the data is read. - local function ReadBits(bitlen) - local rshift_mask = _pow2[bitlen] - local code - if bitlen <= cache_bitlen then - code = cache % rshift_mask - cache = (cache - code) / rshift_mask - cache_bitlen = cache_bitlen - bitlen - else -- Whether input has been exhausted is not checked. - local lshift_mask = _pow2[cache_bitlen] - local byte1, byte2, byte3, byte4 = - string_byte(input, input_next_byte_pos, input_next_byte_pos + 3) - -- This requires lua number to be at least double () - cache = cache + - ((byte1 or 0) + (byte2 or 0) * 256 + (byte3 or 0) * 65536 + - (byte4 or 0) * 16777216) * lshift_mask - input_next_byte_pos = input_next_byte_pos + 4 - cache_bitlen = cache_bitlen + 32 - bitlen - code = cache % rshift_mask - cache = (cache - code) / rshift_mask - end - return code - end - - -- Read some bytes from the reader. - -- Assume reader is on the byte boundary. - -- @param bytelen The number of bytes to be read. - -- @param buffer The byte read will be stored into this buffer. - -- @param buffer_size The buffer will be modified starting from - -- buffer[buffer_size+1], ending at buffer[buffer_size+bytelen-1] - -- @return the new buffer_size - local function ReadBytes(bytelen, buffer, buffer_size) - assert(cache_bitlen % 8 == 0) - - local byte_from_cache = - (cache_bitlen / 8 < bytelen) and (cache_bitlen / 8) or bytelen - for _ = 1, byte_from_cache do - local byte = cache % 256 - buffer_size = buffer_size + 1 - buffer[buffer_size] = string_char(byte) - cache = (cache - byte) / 256 - end - cache_bitlen = cache_bitlen - byte_from_cache * 8 - bytelen = bytelen - byte_from_cache - if (input_strlen - input_next_byte_pos - bytelen + 1) * 8 + cache_bitlen < 0 then - return -1 -- out of input - end - for i = input_next_byte_pos, input_next_byte_pos + bytelen - 1 do - buffer_size = buffer_size + 1 - buffer[buffer_size] = string_sub(input, i, i) - end - - input_next_byte_pos = input_next_byte_pos + bytelen - return buffer_size - end - - -- Decode huffman code - -- To improve speed, this function does not check - -- if the input has been exhausted. - -- Use ReaderBitlenLeft() < 0 to check it. - -- Credits for Mark Adler. This code is from puff:Decode() - -- @see puff:Decode(...) - -- @param huffman_bitlen_count - -- @param huffman_symbol - -- @param min_bitlen The minimum huffman bit length of all symbols - -- @return The decoded deflate code. - -- Negative value is returned if decoding fails. - local function Decode(huffman_bitlen_counts, huffman_symbols, min_bitlen) - local code = 0 - local first = 0 - local index = 0 - local count - if min_bitlen > 0 then - if cache_bitlen < 15 and input then - local lshift_mask = _pow2[cache_bitlen] - local byte1, byte2, byte3, byte4 = - string_byte(input, input_next_byte_pos, input_next_byte_pos + 3) - -- This requires lua number to be at least double () - cache = cache + - ((byte1 or 0) + (byte2 or 0) * 256 + (byte3 or 0) * 65536 + - (byte4 or 0) * 16777216) * lshift_mask - input_next_byte_pos = input_next_byte_pos + 4 - cache_bitlen = cache_bitlen + 32 - end - - local rshift_mask = _pow2[min_bitlen] - cache_bitlen = cache_bitlen - min_bitlen - code = cache % rshift_mask - cache = (cache - code) / rshift_mask - -- Reverse the bits - code = _reverse_bits_tbl[min_bitlen][code] - - count = huffman_bitlen_counts[min_bitlen] - if code < count then return huffman_symbols[code] end - index = count - first = count * 2 - code = code * 2 - end - - for bitlen = min_bitlen + 1, 15 do - local bit - bit = cache % 2 - cache = (cache - bit) / 2 - cache_bitlen = cache_bitlen - 1 - - code = (bit == 1) and (code + 1 - code % 2) or code - count = huffman_bitlen_counts[bitlen] or 0 - local diff = code - first - if diff < count then return huffman_symbols[index + diff] end - index = index + count - first = first + count - first = first * 2 - code = code * 2 - end - -- invalid literal/length or distance code - -- in fixed or dynamic block (run out of code) - return -10 - end - - local function ReaderBitlenLeft() - return (input_strlen - input_next_byte_pos + 1) * 8 + cache_bitlen - end - - local function SkipToByteBoundary() - local skipped_bitlen = cache_bitlen % 8 - local rshift_mask = _pow2[skipped_bitlen] - cache_bitlen = cache_bitlen - skipped_bitlen - cache = (cache - cache % rshift_mask) / rshift_mask - end - - return ReadBits, ReadBytes, Decode, ReaderBitlenLeft, SkipToByteBoundary -end - --- Create a deflate state, so I can pass in less arguments to functions. --- @param str the whole string to be decompressed. --- @param dictionary The preset dictionary. nil if not provided. --- This dictionary should be produced by LibDeflate:CreateDictionary(str) --- @return The decomrpess state. -local function CreateDecompressState(str, dictionary) - local ReadBits, ReadBytes, Decode, ReaderBitlenLeft, SkipToByteBoundary = - CreateReader(str) - local state = { - ReadBits = ReadBits, - ReadBytes = ReadBytes, - Decode = Decode, - ReaderBitlenLeft = ReaderBitlenLeft, - SkipToByteBoundary = SkipToByteBoundary, - buffer_size = 0, - buffer = {}, - result_buffer = {}, - dictionary = dictionary - } - return state -end - --- Get the stuffs needed to decode huffman codes --- @see puff.c:construct(...) --- @param huffman_bitlen The huffman bit length of the huffman codes. --- @param max_symbol The maximum symbol --- @param max_bitlen The min huffman bit length of all codes --- @return zero or positive for success, negative for failure. --- @return The count of each huffman bit length. --- @return A table to convert huffman codes to deflate codes. --- @return The minimum huffman bit length. -local function GetHuffmanForDecode(huffman_bitlens, max_symbol, max_bitlen) - local huffman_bitlen_counts = {} - local min_bitlen = max_bitlen - for symbol = 0, max_symbol do - local bitlen = huffman_bitlens[symbol] or 0 - min_bitlen = (bitlen > 0 and bitlen < min_bitlen) and bitlen or min_bitlen - huffman_bitlen_counts[bitlen] = (huffman_bitlen_counts[bitlen] or 0) + 1 - end - - if huffman_bitlen_counts[0] == max_symbol + 1 then -- No Codes - return 0, huffman_bitlen_counts, {}, 0 -- Complete, but decode will fail - end - - local left = 1 - for len = 1, max_bitlen do - left = left * 2 - left = left - (huffman_bitlen_counts[len] or 0) - if left < 0 then - return left -- Over-subscribed, return negative - end - end - - -- Generate offsets info symbol table for each length for sorting - local offsets = {} - offsets[1] = 0 - for len = 1, max_bitlen - 1 do - offsets[len + 1] = offsets[len] + (huffman_bitlen_counts[len] or 0) - end - - local huffman_symbols = {} - for symbol = 0, max_symbol do - local bitlen = huffman_bitlens[symbol] or 0 - if bitlen ~= 0 then - local offset = offsets[bitlen] - huffman_symbols[offset] = symbol - offsets[bitlen] = offsets[bitlen] + 1 - end - end - - -- Return zero for complete set, positive for incomplete set. - return left, huffman_bitlen_counts, huffman_symbols, min_bitlen -end - --- Decode a fixed or dynamic huffman blocks, excluding last block identifier --- and block type identifer. --- @see puff.c:codes() --- @param state decompression state that will be modified by this function. --- @see CreateDecompressState --- @param ... Read the source code --- @return 0 on success, other value on failure. -local function DecodeUntilEndOfBlock(state, lcodes_huffman_bitlens, - lcodes_huffman_symbols, - lcodes_huffman_min_bitlen, - dcodes_huffman_bitlens, - dcodes_huffman_symbols, - dcodes_huffman_min_bitlen) - local buffer, buffer_size, ReadBits, Decode, ReaderBitlenLeft, result_buffer = - state.buffer, state.buffer_size, state.ReadBits, state.Decode, - state.ReaderBitlenLeft, state.result_buffer - local dictionary = state.dictionary - local dict_string_table - local dict_strlen - - local buffer_end = 1 - if dictionary and not buffer[0] then - -- If there is a dictionary, copy the last 258 bytes into - -- the string_table to make the copy in the main loop quicker. - -- This is done only once per decompression. - dict_string_table = dictionary.string_table - dict_strlen = dictionary.strlen - buffer_end = -dict_strlen + 1 - for i = 0, (-dict_strlen + 1) < -257 and -257 or (-dict_strlen + 1), -1 do - buffer[i] = _byte_to_char[dict_string_table[dict_strlen + i]] - end - end - - repeat - local symbol = Decode(lcodes_huffman_bitlens, lcodes_huffman_symbols, - lcodes_huffman_min_bitlen) - if symbol < 0 or symbol > 285 then - -- invalid literal/length or distance code in fixed or dynamic block - return -10 - elseif symbol < 256 then -- Literal - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_char[symbol] - elseif symbol > 256 then -- Length code - symbol = symbol - 256 - local bitlen = _literal_deflate_code_to_base_len[symbol] - bitlen = (symbol >= 8) and - (bitlen + - ReadBits(_literal_deflate_code_to_extra_bitlen[symbol])) or - bitlen - symbol = Decode(dcodes_huffman_bitlens, dcodes_huffman_symbols, - dcodes_huffman_min_bitlen) - if symbol < 0 or symbol > 29 then - -- invalid literal/length or distance code in fixed or dynamic block - return -10 - end - local dist = _dist_deflate_code_to_base_dist[symbol] - dist = (dist > 4) and - (dist + ReadBits(_dist_deflate_code_to_extra_bitlen[symbol])) or - dist - - local char_buffer_index = buffer_size - dist + 1 - if char_buffer_index < buffer_end then - -- distance is too far back in fixed or dynamic block - return -11 - end - if char_buffer_index >= -257 then - for _ = 1, bitlen do - buffer_size = buffer_size + 1 - buffer[buffer_size] = buffer[char_buffer_index] - char_buffer_index = char_buffer_index + 1 - end - else - char_buffer_index = dict_strlen + char_buffer_index - for _ = 1, bitlen do - buffer_size = buffer_size + 1 - buffer[buffer_size] = - _byte_to_char[dict_string_table[char_buffer_index]] - char_buffer_index = char_buffer_index + 1 - end - end - end - - if ReaderBitlenLeft() < 0 then - return 2 -- available inflate data did not terminate - end - - if buffer_size >= 65536 then - result_buffer[#result_buffer + 1] = table_concat(buffer, "", 1, 32768) - for i = 32769, buffer_size do buffer[i - 32768] = buffer[i] end - buffer_size = buffer_size - 32768 - buffer[buffer_size + 1] = nil - -- NOTE: buffer[32769..end] and buffer[-257..0] are not cleared. - -- This is why "buffer_size" variable is needed. - end - until symbol == 256 - - state.buffer_size = buffer_size - - return 0 -end - --- Decompress a store block --- @param state decompression state that will be modified by this function. --- @return 0 if succeeds, other value if fails. -local function DecompressStoreBlock(state) - local buffer, buffer_size, ReadBits, ReadBytes, ReaderBitlenLeft, - SkipToByteBoundary, result_buffer = state.buffer, state.buffer_size, - state.ReadBits, state.ReadBytes, - state.ReaderBitlenLeft, - state.SkipToByteBoundary, - state.result_buffer - - SkipToByteBoundary() - local bytelen = ReadBits(16) - if ReaderBitlenLeft() < 0 then - return 2 -- available inflate data did not terminate - end - local bytelenComp = ReadBits(16) - if ReaderBitlenLeft() < 0 then - return 2 -- available inflate data did not terminate - end - - if bytelen % 256 + bytelenComp % 256 ~= 255 then - return -2 -- Not one's complement - end - if (bytelen - bytelen % 256) / 256 + (bytelenComp - bytelenComp % 256) / 256 ~= - 255 then - return -2 -- Not one's complement - end - - -- Note that ReadBytes will skip to the next byte boundary first. - buffer_size = ReadBytes(bytelen, buffer, buffer_size) - if buffer_size < 0 then - return 2 -- available inflate data did not terminate - end - - -- memory clean up when there are enough bytes in the buffer. - if buffer_size >= 65536 then - result_buffer[#result_buffer + 1] = table_concat(buffer, "", 1, 32768) - for i = 32769, buffer_size do buffer[i - 32768] = buffer[i] end - buffer_size = buffer_size - 32768 - buffer[buffer_size + 1] = nil - end - state.buffer_size = buffer_size - return 0 -end - --- Decompress a fixed block --- @param state decompression state that will be modified by this function. --- @return 0 if succeeds other value if fails. -local function DecompressFixBlock(state) - return DecodeUntilEndOfBlock(state, _fix_block_literal_huffman_bitlen_count, - _fix_block_literal_huffman_to_deflate_code, 7, - _fix_block_dist_huffman_bitlen_count, - _fix_block_dist_huffman_to_deflate_code, 5) -end - --- Decompress a dynamic block --- @param state decompression state that will be modified by this function. --- @return 0 if success, other value if fails. -local function DecompressDynamicBlock(state) - local ReadBits, Decode = state.ReadBits, state.Decode - local nlen = ReadBits(5) + 257 - local ndist = ReadBits(5) + 1 - local ncode = ReadBits(4) + 4 - if nlen > 286 or ndist > 30 then - -- dynamic block code description: too many length or distance codes - return -3 - end - - local rle_codes_huffman_bitlens = {} - - for i = 1, ncode do - rle_codes_huffman_bitlens[_rle_codes_huffman_bitlen_order[i]] = ReadBits(3) - end - - local rle_codes_err, rle_codes_huffman_bitlen_counts, - rle_codes_huffman_symbols, rle_codes_huffman_min_bitlen = - GetHuffmanForDecode(rle_codes_huffman_bitlens, 18, 7) - if rle_codes_err ~= 0 then -- Require complete code set here - -- dynamic block code description: code lengths codes incomplete - return -4 - end - - local lcodes_huffman_bitlens = {} - local dcodes_huffman_bitlens = {} - -- Read length/literal and distance code length tables - local index = 0 - while index < nlen + ndist do - local symbol -- Decoded value - local bitlen -- Last length to repeat - - symbol = Decode(rle_codes_huffman_bitlen_counts, rle_codes_huffman_symbols, - rle_codes_huffman_min_bitlen) - - if symbol < 0 then - return symbol -- Invalid symbol - elseif symbol < 16 then - if index < nlen then - lcodes_huffman_bitlens[index] = symbol - else - dcodes_huffman_bitlens[index - nlen] = symbol - end - index = index + 1 - else - bitlen = 0 - if symbol == 16 then - if index == 0 then - -- dynamic block code description: repeat lengths - -- with no first length - return -5 - end - if index - 1 < nlen then - bitlen = lcodes_huffman_bitlens[index - 1] - else - bitlen = dcodes_huffman_bitlens[index - nlen - 1] - end - symbol = 3 + ReadBits(2) - elseif symbol == 17 then -- Repeat zero 3..10 times - symbol = 3 + ReadBits(3) - else -- == 18, repeat zero 11.138 times - symbol = 11 + ReadBits(7) - end - if index + symbol > nlen + ndist then - -- dynamic block code description: - -- repeat more than specified lengths - return -6 - end - while symbol > 0 do -- Repeat last or zero symbol times - symbol = symbol - 1 - if index < nlen then - lcodes_huffman_bitlens[index] = bitlen - else - dcodes_huffman_bitlens[index - nlen] = bitlen - end - index = index + 1 - end - end - end - - if (lcodes_huffman_bitlens[256] or 0) == 0 then - -- dynamic block code description: missing end-of-block code - return -9 - end - - local lcodes_err, lcodes_huffman_bitlen_counts, lcodes_huffman_symbols, - lcodes_huffman_min_bitlen = GetHuffmanForDecode(lcodes_huffman_bitlens, - nlen - 1, 15) - -- dynamic block code description: invalid literal/length code lengths, - -- Incomplete code ok only for single length 1 code - if (lcodes_err ~= 0 and - (lcodes_err < 0 or nlen ~= (lcodes_huffman_bitlen_counts[0] or 0) + - (lcodes_huffman_bitlen_counts[1] or 0))) then return -7 end - - local dcodes_err, dcodes_huffman_bitlen_counts, dcodes_huffman_symbols, - dcodes_huffman_min_bitlen = GetHuffmanForDecode(dcodes_huffman_bitlens, - ndist - 1, 15) - -- dynamic block code description: invalid distance code lengths, - -- Incomplete code ok only for single length 1 code - if (dcodes_err ~= 0 and - (dcodes_err < 0 or ndist ~= (dcodes_huffman_bitlen_counts[0] or 0) + - (dcodes_huffman_bitlen_counts[1] or 0))) then return -8 end - - -- Build buffman table for literal/length codes - return DecodeUntilEndOfBlock(state, lcodes_huffman_bitlen_counts, - lcodes_huffman_symbols, - lcodes_huffman_min_bitlen, - dcodes_huffman_bitlen_counts, - dcodes_huffman_symbols, dcodes_huffman_min_bitlen) -end - --- Decompress a deflate stream --- @param state: a decompression state --- @return the decompressed string if succeeds. nil if fails. -local function Inflate(state) - local ReadBits = state.ReadBits - - local is_last_block - while not is_last_block do - is_last_block = (ReadBits(1) == 1) - local block_type = ReadBits(2) - local status - if block_type == 0 then - status = DecompressStoreBlock(state) - elseif block_type == 1 then - status = DecompressFixBlock(state) - elseif block_type == 2 then - status = DecompressDynamicBlock(state) - else - return nil, -1 -- invalid block type (type == 3) - end - if status ~= 0 then return nil, status end - end - - state.result_buffer[#state.result_buffer + 1] = - table_concat(state.buffer, "", 1, state.buffer_size) - local result = table_concat(state.result_buffer) - return result -end - --- @see LibDeflate:DecompressDeflate(str) --- @see LibDeflate:DecompressDeflateWithDict(str, dictionary) -local function DecompressDeflateInternal(str, dictionary) - local state = CreateDecompressState(str, dictionary) - local result, status = Inflate(state) - if not result then return nil, status end - - local bitlen_left = state.ReaderBitlenLeft() - local bytelen_left = (bitlen_left - bitlen_left % 8) / 8 - return result, bytelen_left -end - --- @see LibDeflate:DecompressZlib(str) --- @see LibDeflate:DecompressZlibWithDict(str) -local function DecompressZlibInternal(str, dictionary) - local state = CreateDecompressState(str, dictionary) - local ReadBits = state.ReadBits - - local CMF = ReadBits(8) - if state.ReaderBitlenLeft() < 0 then - return nil, 2 -- available inflate data did not terminate - end - local CM = CMF % 16 - local CINFO = (CMF - CM) / 16 - if CM ~= 8 then - return nil, -12 -- invalid compression method - end - if CINFO > 7 then - return nil, -13 -- invalid window size - end - - local FLG = ReadBits(8) - if state.ReaderBitlenLeft() < 0 then - return nil, 2 -- available inflate data did not terminate - end - if (CMF * 256 + FLG) % 31 ~= 0 then - return nil, -14 -- invalid header checksum - end - - local FDIST = ((FLG - FLG % 32) / 32 % 2) - local FLEVEL = ((FLG - FLG % 64) / 64 % 4) -- luacheck: ignore FLEVEL - - if FDIST == 1 then - if not dictionary then - return nil, -16 -- need dictonary, but dictionary is not provided. - end - local byte3 = ReadBits(8) - local byte2 = ReadBits(8) - local byte1 = ReadBits(8) - local byte0 = ReadBits(8) - local actual_adler32 = byte3 * 16777216 + byte2 * 65536 + byte1 * 256 + - byte0 - if state.ReaderBitlenLeft() < 0 then - return nil, 2 -- available inflate data did not terminate - end - if not IsEqualAdler32(actual_adler32, dictionary.adler32) then - return nil, -17 -- dictionary adler32 does not match - end - end - local result, status = Inflate(state) - if not result then return nil, status end - state.SkipToByteBoundary() - - local adler_byte0 = ReadBits(8) - local adler_byte1 = ReadBits(8) - local adler_byte2 = ReadBits(8) - local adler_byte3 = ReadBits(8) - if state.ReaderBitlenLeft() < 0 then - return nil, 2 -- available inflate data did not terminate - end - - local adler32_expected = adler_byte0 * 16777216 + adler_byte1 * 65536 + - adler_byte2 * 256 + adler_byte3 - local adler32_actual = LibDeflate:Adler32(result) - if not IsEqualAdler32(adler32_expected, adler32_actual) then - return nil, -15 -- Adler32 checksum does not match - end - - local bitlen_left = state.ReaderBitlenLeft() - local bytelen_left = (bitlen_left - bitlen_left % 8) / 8 - return result, bytelen_left -end - ---- Decompress a raw deflate compressed data. --- @param str [string] The data to be decompressed. --- @return [string/nil] If the decompression succeeds, return the decompressed --- data. If the decompression fails, return nil. You should check if this return --- value is non-nil to know if the decompression succeeds. --- @return [integer] If the decompression succeeds, return the number of --- unprocessed bytes in the input compressed data. This return value is a --- positive integer if the input data is a valid compressed data appended by an --- arbitary non-empty string. This return value is 0 if the input data does not --- contain any extra bytes.
--- If the decompression fails (The first return value of this function is nil), --- this return value is undefined. --- @see LibDeflate:CompressDeflate -function LibDeflate:DecompressDeflate(str) - local arg_valid, arg_err = IsValidArguments(str) - if not arg_valid then - error(("Usage: LibDeflate:DecompressDeflate(str): " .. arg_err), 2) - end - return DecompressDeflateInternal(str) -end - ---- Decompress a raw deflate compressed data with a preset dictionary. --- @param str [string] The data to be decompressed. --- @param dictionary [table] The preset dictionary used by --- LibDeflate:CompressDeflateWithDict when the compressed data is produced. --- Decompression and compression must use the same dictionary. --- Otherwise wrong decompressed data could be produced without generating any --- error. --- @return [string/nil] If the decompression succeeds, return the decompressed --- data. If the decompression fails, return nil. You should check if this return --- value is non-nil to know if the decompression succeeds. --- @return [integer] If the decompression succeeds, return the number of --- unprocessed bytes in the input compressed data. This return value is a --- positive integer if the input data is a valid compressed data appended by an --- arbitary non-empty string. This return value is 0 if the input data does not --- contain any extra bytes.
--- If the decompression fails (The first return value of this function is nil), --- this return value is undefined. --- @see LibDeflate:CompressDeflateWithDict -function LibDeflate:DecompressDeflateWithDict(str, dictionary) - local arg_valid, arg_err = IsValidArguments(str, true, dictionary) - if not arg_valid then - error(("Usage: LibDeflate:DecompressDeflateWithDict(str, dictionary): " .. - arg_err), 2) - end - return DecompressDeflateInternal(str, dictionary) -end - ---- Decompress a zlib compressed data. --- @param str [string] The data to be decompressed --- @return [string/nil] If the decompression succeeds, return the decompressed --- data. If the decompression fails, return nil. You should check if this return --- value is non-nil to know if the decompression succeeds. --- @return [integer] If the decompression succeeds, return the number of --- unprocessed bytes in the input compressed data. This return value is a --- positive integer if the input data is a valid compressed data appended by an --- arbitary non-empty string. This return value is 0 if the input data does not --- contain any extra bytes.
--- If the decompression fails (The first return value of this function is nil), --- this return value is undefined. --- @see LibDeflate:CompressZlib -function LibDeflate:DecompressZlib(str) - local arg_valid, arg_err = IsValidArguments(str) - if not arg_valid then - error(("Usage: LibDeflate:DecompressZlib(str): " .. arg_err), 2) - end - return DecompressZlibInternal(str) -end - ---- Decompress a zlib compressed data with a preset dictionary. --- @param str [string] The data to be decompressed --- @param dictionary [table] The preset dictionary used by --- LibDeflate:CompressDeflateWithDict when the compressed data is produced. --- Decompression and compression must use the same dictionary. --- Otherwise wrong decompressed data could be produced without generating any --- error. --- @return [string/nil] If the decompression succeeds, return the decompressed --- data. If the decompression fails, return nil. You should check if this return --- value is non-nil to know if the decompression succeeds. --- @return [integer] If the decompression succeeds, return the number of --- unprocessed bytes in the input compressed data. This return value is a --- positive integer if the input data is a valid compressed data appended by an --- arbitary non-empty string. This return value is 0 if the input data does not --- contain any extra bytes.
--- If the decompression fails (The first return value of this function is nil), --- this return value is undefined. --- @see LibDeflate:CompressZlibWithDict -function LibDeflate:DecompressZlibWithDict(str, dictionary) - local arg_valid, arg_err = IsValidArguments(str, true, dictionary) - if not arg_valid then - error(("Usage: LibDeflate:DecompressZlibWithDict(str, dictionary): " .. - arg_err), 2) - end - return DecompressZlibInternal(str, dictionary) -end - --- Calculate the huffman code of fixed block -do - _fix_block_literal_huffman_bitlen = {} - for sym = 0, 143 do _fix_block_literal_huffman_bitlen[sym] = 8 end - for sym = 144, 255 do _fix_block_literal_huffman_bitlen[sym] = 9 end - for sym = 256, 279 do _fix_block_literal_huffman_bitlen[sym] = 7 end - for sym = 280, 287 do _fix_block_literal_huffman_bitlen[sym] = 8 end - - _fix_block_dist_huffman_bitlen = {} - for dist = 0, 31 do _fix_block_dist_huffman_bitlen[dist] = 5 end - local status - status, _fix_block_literal_huffman_bitlen_count, _fix_block_literal_huffman_to_deflate_code = - GetHuffmanForDecode(_fix_block_literal_huffman_bitlen, 287, 9) - assert(status == 0) - status, _fix_block_dist_huffman_bitlen_count, _fix_block_dist_huffman_to_deflate_code = - GetHuffmanForDecode(_fix_block_dist_huffman_bitlen, 31, 5) - assert(status == 0) - - _fix_block_literal_huffman_code = GetHuffmanCodeFromBitlen( - _fix_block_literal_huffman_bitlen_count, - _fix_block_literal_huffman_bitlen, 287, 9) - _fix_block_dist_huffman_code = GetHuffmanCodeFromBitlen( - _fix_block_dist_huffman_bitlen_count, - _fix_block_dist_huffman_bitlen, 31, 5) -end - --- Prefix encoding algorithm --- Credits to LibCompress. --- The code has been rewritten by the author of LibDeflate. ------------------------------------------------------------------------------- - --- to be able to match any requested byte value, the search --- string must be preprocessed characters to escape with %: --- ( ) . % + - * ? [ ] ^ $ --- "illegal" byte values: --- 0 is replaces %z -local _gsub_escape_table = { - ["\000"] = "%z", - ["("] = "%(", - [")"] = "%)", - ["."] = "%.", - ["%"] = "%%", - ["+"] = "%+", - ["-"] = "%-", - ["*"] = "%*", - ["?"] = "%?", - ["["] = "%[", - ["]"] = "%]", - ["^"] = "%^", - ["$"] = "%$" -} - -local function escape_for_gsub(str) - return str:gsub("([%z%(%)%.%%%+%-%*%?%[%]%^%$])", _gsub_escape_table) -end - ---- Create a custom codec with encoder and decoder.
--- This codec is used to convert an input string to make it not contain --- some specific bytes. --- This created codec and the parameters of this function do NOT take --- localization into account. One byte (0-255) in the string is exactly one --- character (0-255). --- Credits to LibCompress. --- The code has been rewritten by the author of LibDeflate.
--- @param reserved_chars [string] The created encoder will ensure encoded --- data does not contain any single character in reserved_chars. This parameter --- should be non-empty. --- @param escape_chars [string] The escape character(s) used in the created --- codec. The codec converts any character included in reserved\_chars / --- escape\_chars / map\_chars to (one escape char + one character not in --- reserved\_chars / escape\_chars / map\_chars). --- You usually only need to provide a length-1 string for this parameter. --- Length-2 string is only needed when --- reserved\_chars + escape\_chars + map\_chars is longer than 127. --- This parameter should be non-empty. --- @param map_chars [string] The created encoder will map every --- reserved\_chars:sub(i, i) (1 <= i <= #map\_chars) to map\_chars:sub(i, i). --- This parameter CAN be empty string. --- @return [table/nil] If the codec cannot be created, return nil.
--- If the codec can be created according to the given --- parameters, return the codec, which is a encode/decode table. --- The table contains two functions:
--- t:Encode(str) returns the encoded string.
--- t:Decode(str) returns the decoded string if succeeds. nil if fails. --- @return [nil/string] If the codec is successfully created, return nil. --- If not, return a string that describes the reason why the codec cannot be --- created. --- @usage --- -- Create an encoder/decoder that maps all "\000" to "\003", --- -- and escape "\001" (and "\002" and "\003") properly --- local codec = LibDeflate:CreateCodec("\000\001", "\002", "\003") --- --- local encoded = codec:Encode(SOME_STRING) --- -- "encoded" does not contain "\000" or "\001" --- local decoded = codec:Decode(encoded) --- -- assert(decoded == SOME_STRING) -function LibDeflate:CreateCodec(reserved_chars, escape_chars, map_chars) - if type(reserved_chars) ~= "string" or type(escape_chars) ~= "string" or - type(map_chars) ~= "string" then - error("Usage: LibDeflate:CreateCodec(reserved_chars," .. - " escape_chars, map_chars):" .. " All arguments must be string.", 2) - end - - if escape_chars == "" then return nil, "No escape characters supplied." end - if #reserved_chars < #map_chars then - return nil, "The number of reserved characters must be" .. - " at least as many as the number of mapped chars." - end - if reserved_chars == "" then return nil, "No characters to encode." end - - local encode_bytes = reserved_chars .. escape_chars .. map_chars - -- build list of bytes not available as a suffix to a prefix byte - local taken = {} - for i = 1, #encode_bytes do - local byte = string_byte(encode_bytes, i, i) - if taken[byte] then - return nil, "There must be no duplicate characters in the" .. - " concatenation of reserved_chars, escape_chars and" .. - " map_chars." - end - taken[byte] = true - end - - local decode_patterns = {} - local decode_repls = {} - - -- the encoding can be a single gsub - -- , but the decoding can require multiple gsubs - local encode_search = {} - local encode_translate = {} - - -- map single byte to single byte - if #map_chars > 0 then - local decode_search = {} - local decode_translate = {} - for i = 1, #map_chars do - local from = string_sub(reserved_chars, i, i) - local to = string_sub(map_chars, i, i) - encode_translate[from] = to - encode_search[#encode_search + 1] = from - decode_translate[to] = from - decode_search[#decode_search + 1] = to - end - decode_patterns[#decode_patterns + 1] = - "([" .. escape_for_gsub(table_concat(decode_search)) .. "])" - decode_repls[#decode_repls + 1] = decode_translate - end - - local escape_char_index = 1 - local escape_char = string_sub(escape_chars, escape_char_index, - escape_char_index) - -- map single byte to double-byte - local r = 0 -- suffix char value to the escapeChar - - local decode_search = {} - local decode_translate = {} - for i = 1, #encode_bytes do - local c = string_sub(encode_bytes, i, i) - if not encode_translate[c] then - while r >= 256 or taken[r] do - r = r + 1 - if r > 255 then -- switch to next escapeChar - decode_patterns[#decode_patterns + 1] = - escape_for_gsub(escape_char) .. "([" .. - escape_for_gsub(table_concat(decode_search)) .. "])" - decode_repls[#decode_repls + 1] = decode_translate - - escape_char_index = escape_char_index + 1 - escape_char = string_sub(escape_chars, escape_char_index, - escape_char_index) - r = 0 - decode_search = {} - decode_translate = {} - - if not escape_char or escape_char == "" then - -- actually I don't need to check - -- "not ecape_char", but what if Lua changes - -- the behavior of string.sub() in the future? - -- we are out of escape chars and we need more! - return nil, "Out of escape characters." - end - end - end - - local char_r = _byte_to_char[r] - encode_translate[c] = escape_char .. char_r - encode_search[#encode_search + 1] = c - decode_translate[char_r] = c - decode_search[#decode_search + 1] = char_r - r = r + 1 - end - if i == #encode_bytes then - decode_patterns[#decode_patterns + 1] = - escape_for_gsub(escape_char) .. "([" .. - escape_for_gsub(table_concat(decode_search)) .. "])" - decode_repls[#decode_repls + 1] = decode_translate - end - end - - local codec = {} - - local encode_pattern = "([" .. escape_for_gsub(table_concat(encode_search)) .. - "])" - local encode_repl = encode_translate - - function codec:Encode(str) - if type(str) ~= "string" then - error( - ("Usage: codec:Encode(str):" .. " 'str' - string expected got '%s'."):format( - type(str)), 2) - end - return string_gsub(str, encode_pattern, encode_repl) - end - - local decode_tblsize = #decode_patterns - local decode_fail_pattern = "([" .. escape_for_gsub(reserved_chars) .. "])" - - function codec:Decode(str) - if type(str) ~= "string" then - error( - ("Usage: codec:Decode(str):" .. " 'str' - string expected got '%s'."):format( - type(str)), 2) - end - if string_find(str, decode_fail_pattern) then return nil end - for i = 1, decode_tblsize do - str = string_gsub(str, decode_patterns[i], decode_repls[i]) - end - return str - end - - return codec -end - -local _addon_channel_codec - -local function GenerateWoWAddonChannelCodec() - return LibDeflate:CreateCodec("\000", "\001", "") -end - ---- Encode the string to make it ready to be transmitted in World of --- Warcraft addon channel.
--- The encoded string is guaranteed to contain no NULL ("\000") character. --- @param str [string] The string to be encoded. --- @return The encoded string. --- @see LibDeflate:DecodeForWoWAddonChannel -function LibDeflate:EncodeForWoWAddonChannel(str) - if type(str) ~= "string" then - error(("Usage: LibDeflate:EncodeForWoWAddonChannel(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - if not _addon_channel_codec then - _addon_channel_codec = GenerateWoWAddonChannelCodec() - end - return _addon_channel_codec:Encode(str) -end - ---- Decode the string produced by LibDeflate:EncodeForWoWAddonChannel --- @param str [string] The string to be decoded. --- @return [string/nil] The decoded string if succeeds. nil if fails. --- @see LibDeflate:EncodeForWoWAddonChannel -function LibDeflate:DecodeForWoWAddonChannel(str) - if type(str) ~= "string" then - error(("Usage: LibDeflate:DecodeForWoWAddonChannel(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - if not _addon_channel_codec then - _addon_channel_codec = GenerateWoWAddonChannelCodec() - end - return _addon_channel_codec:Decode(str) -end - --- For World of Warcraft Chat Channel Encoding --- Credits to LibCompress. --- The code has been rewritten by the author of LibDeflate.
--- Following byte values are not allowed: --- \000, s, S, \010, \013, \124, % --- Because SendChatMessage will error --- if an UTF8 multibyte character is incomplete, --- all character values above 127 have to be encoded to avoid this. --- This costs quite a bit of bandwidth (about 13-14%) --- Also, because drunken status is unknown for the received --- , strings used with SendChatMessage should be terminated with --- an identifying byte value, after which the server MAY add "...hic!" --- or as much as it can fit(!). --- Pass the identifying byte as a reserved character to this function --- to ensure the encoding doesn't contain that value. --- or use this: local message, match = arg1:gsub("^(.*)\029.-$", "%1") --- arg1 is message from channel, \029 is the string terminator --- , but may be used in the encoded datastream as well. :-) --- This encoding will expand data anywhere from: --- 0% (average with pure ascii text) --- 53.5% (average with random data valued zero to 255) --- 100% (only encoding data that encodes to two bytes) -local function GenerateWoWChatChannelCodec() - local r = {} - for i = 128, 255 do r[#r + 1] = _byte_to_char[i] end - - local reserved_chars = "sS\000\010\013\124%" .. table_concat(r) - return LibDeflate:CreateCodec(reserved_chars, "\029\031", "\015\020") -end - -local _chat_channel_codec - ---- Encode the string to make it ready to be transmitted in World of --- Warcraft chat channel.
--- See also https://wow.gamepedia.com/ValidChatMessageCharacters --- @param str [string] The string to be encoded. --- @return [string] The encoded string. --- @see LibDeflate:DecodeForWoWChatChannel -function LibDeflate:EncodeForWoWChatChannel(str) - if type(str) ~= "string" then - error(("Usage: LibDeflate:EncodeForWoWChatChannel(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - if not _chat_channel_codec then - _chat_channel_codec = GenerateWoWChatChannelCodec() - end - return _chat_channel_codec:Encode(str) -end - ---- Decode the string produced by LibDeflate:EncodeForWoWChatChannel. --- @param str [string] The string to be decoded. --- @return [string/nil] The decoded string if succeeds. nil if fails. --- @see LibDeflate:EncodeForWoWChatChannel -function LibDeflate:DecodeForWoWChatChannel(str) - if type(str) ~= "string" then - error(("Usage: LibDeflate:DecodeForWoWChatChannel(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - if not _chat_channel_codec then - _chat_channel_codec = GenerateWoWChatChannelCodec() - end - return _chat_channel_codec:Decode(str) -end - --- Credits to WeakAuras2 and Galmok for the 6 bit encoding algorithm. --- The code has been rewritten by the author of LibDeflate. --- The result of encoding will be 25% larger than the --- origin string, but every single byte of the encoding result will be --- printable characters as the following. -local _byte_to_6bit_char = { - [0] = "a", - "b", - "c", - "d", - "e", - "f", - "g", - "h", - "i", - "j", - "k", - "l", - "m", - "n", - "o", - "p", - "q", - "r", - "s", - "t", - "u", - "v", - "w", - "x", - "y", - "z", - "A", - "B", - "C", - "D", - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - "U", - "V", - "W", - "X", - "Y", - "Z", - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "(", - ")" -} - -local _6bit_to_byte = { - [97] = 0, - [98] = 1, - [99] = 2, - [100] = 3, - [101] = 4, - [102] = 5, - [103] = 6, - [104] = 7, - [105] = 8, - [106] = 9, - [107] = 10, - [108] = 11, - [109] = 12, - [110] = 13, - [111] = 14, - [112] = 15, - [113] = 16, - [114] = 17, - [115] = 18, - [116] = 19, - [117] = 20, - [118] = 21, - [119] = 22, - [120] = 23, - [121] = 24, - [122] = 25, - [65] = 26, - [66] = 27, - [67] = 28, - [68] = 29, - [69] = 30, - [70] = 31, - [71] = 32, - [72] = 33, - [73] = 34, - [74] = 35, - [75] = 36, - [76] = 37, - [77] = 38, - [78] = 39, - [79] = 40, - [80] = 41, - [81] = 42, - [82] = 43, - [83] = 44, - [84] = 45, - [85] = 46, - [86] = 47, - [87] = 48, - [88] = 49, - [89] = 50, - [90] = 51, - [48] = 52, - [49] = 53, - [50] = 54, - [51] = 55, - [52] = 56, - [53] = 57, - [54] = 58, - [55] = 59, - [56] = 60, - [57] = 61, - [40] = 62, - [41] = 63 -} - ---- Encode the string to make it printable.
--- --- Credit to WeakAuras2, this function is equivalant to the implementation --- it is using right now.
--- The code has been rewritten by the author of LibDeflate.
--- The encoded string will be 25% larger than the origin string. However, every --- single byte of the encoded string will be one of 64 printable ASCII --- characters, which are can be easier copied, pasted and displayed. --- (26 lowercase letters, 26 uppercase letters, 10 numbers digits, --- left parenthese, or right parenthese) --- @param str [string] The string to be encoded. --- @return [string] The encoded string. -function LibDeflate:EncodeForPrint(str) - if type(str) ~= "string" then - error(("Usage: LibDeflate:EncodeForPrint(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - local strlen = #str - local strlenMinus2 = strlen - 2 - local i = 1 - local buffer = {} - local buffer_size = 0 - while i <= strlenMinus2 do - local x1, x2, x3 = string_byte(str, i, i + 2) - i = i + 3 - local cache = x1 + x2 * 256 + x3 * 65536 - local b1 = cache % 64 - cache = (cache - b1) / 64 - local b2 = cache % 64 - cache = (cache - b2) / 64 - local b3 = cache % 64 - local b4 = (cache - b3) / 64 - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_6bit_char[b1] .. _byte_to_6bit_char[b2] .. - _byte_to_6bit_char[b3] .. _byte_to_6bit_char[b4] - end - - local cache = 0 - local cache_bitlen = 0 - while i <= strlen do - local x = string_byte(str, i, i) - cache = cache + x * _pow2[cache_bitlen] - cache_bitlen = cache_bitlen + 8 - i = i + 1 - end - while cache_bitlen > 0 do - local bit6 = cache % 64 - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_6bit_char[bit6] - cache = (cache - bit6) / 64 - cache_bitlen = cache_bitlen - 6 - end - - return table_concat(buffer) -end - ---- Decode the printable string produced by LibDeflate:EncodeForPrint. --- "str" will have its prefixed and trailing control characters or space --- removed before it is decoded, so it is easier to use if "str" comes form --- user copy and paste with some prefixed or trailing spaces. --- Then decode fails if the string contains any characters cant be produced by --- LibDeflate:EncodeForPrint. That means, decode fails if the string contains a --- characters NOT one of 26 lowercase letters, 26 uppercase letters, --- 10 numbers digits, left parenthese, or right parenthese. --- @param str [string] The string to be decoded --- @return [string/nil] The decoded string if succeeds. nil if fails. -function LibDeflate:DecodeForPrint(str) - if type(str) ~= "string" then - error(("Usage: LibDeflate:DecodeForPrint(str):" .. - " 'str' - string expected got '%s'."):format(type(str)), 2) - end - str = str:gsub("^[%c ]+", "") - str = str:gsub("[%c ]+$", "") - - local strlen = #str - if strlen == 1 then return nil end - local strlenMinus3 = strlen - 3 - local i = 1 - local buffer = {} - local buffer_size = 0 - while i <= strlenMinus3 do - local x1, x2, x3, x4 = string_byte(str, i, i + 3) - x1 = _6bit_to_byte[x1] - x2 = _6bit_to_byte[x2] - x3 = _6bit_to_byte[x3] - x4 = _6bit_to_byte[x4] - if not (x1 and x2 and x3 and x4) then return nil end - i = i + 4 - local cache = x1 + x2 * 64 + x3 * 4096 + x4 * 262144 - local b1 = cache % 256 - cache = (cache - b1) / 256 - local b2 = cache % 256 - local b3 = (cache - b2) / 256 - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_char[b1] .. _byte_to_char[b2] .. - _byte_to_char[b3] - end - - local cache = 0 - local cache_bitlen = 0 - while i <= strlen do - local x = string_byte(str, i, i) - x = _6bit_to_byte[x] - if not x then return nil end - cache = cache + x * _pow2[cache_bitlen] - cache_bitlen = cache_bitlen + 6 - i = i + 1 - end - - while cache_bitlen >= 8 do - local byte = cache % 256 - buffer_size = buffer_size + 1 - buffer[buffer_size] = _byte_to_char[byte] - cache = (cache - byte) / 256 - cache_bitlen = cache_bitlen - 8 - end - - return table_concat(buffer) -end - -local function InternalClearCache() - _chat_channel_codec = nil - _addon_channel_codec = nil -end - --- For test. Don't use the functions in this table for real application. --- Stuffs in this table is subject to change. -LibDeflate.internals = { - LoadStringToTable = LoadStringToTable, - IsValidDictionary = IsValidDictionary, - IsEqualAdler32 = IsEqualAdler32, - _byte_to_6bit_char = _byte_to_6bit_char, - _6bit_to_byte = _6bit_to_byte, - InternalClearCache = InternalClearCache -} - -return LibDeflate \ No newline at end of file diff --git a/src/disks/1h/lib/array/2d b/src/disks/1h/lib/array/2d deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/lib/array/math b/src/disks/1h/lib/array/math deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/lib/array/x b/src/disks/1h/lib/array/x deleted file mode 100644 index 86c476a..0000000 --- a/src/disks/1h/lib/array/x +++ /dev/null @@ -1,10 +0,0 @@ -local lib = {} - -function lib.create() - local array = {} - return setmetatable(array,{ - __add=function(t1, t2) - - end - }) -end \ No newline at end of file diff --git a/src/disks/1h/opt/astronand/ZDelta/init b/src/disks/1h/opt/astronand/ZDelta/init deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/opt/astronand/dbg/init b/src/disks/1h/opt/astronand/dbg/init deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/sbin/init b/src/disks/1h/sbin/init deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/sys/Hyperion.sys b/src/disks/1h/sys/Hyperion.sys deleted file mode 100644 index 87deca5..0000000 --- a/src/disks/1h/sys/Hyperion.sys +++ /dev/null @@ -1,27 +0,0 @@ -local args={...} -local fs=args[1] -local log=args[2] -local drivers=args[3] -local PANIC=args[4] -local driverutil=args[5] -local sys={} -local task={} - -sys._VERSION = "HyperionOS V1.0.4" - -local function run(file, args) - local func, err=fs.loadAsFunc(file) - if not file then return 8, err end - local ret={xpcall(func, debug.traceback, table.unpack(args))} - if not ret[1] then return 1, ret[2] end - return 0, table.unpack(ret, 2) -end - -local exitcode, req=run("/sys/system/require", {sys}) -if exitcode~=0 then PANIC(req) end -_G.require=req - -local exitcode, hypervisor=run("/sys/system/hypervisor/init", {sys}) -if exitcode~=0 then PANIC(hypervisor) end -_G.require=hypervisor - diff --git a/src/disks/1h/sys/api/string.lua b/src/disks/1h/sys/api/string.lua deleted file mode 100644 index 2bfdcd3..0000000 --- a/src/disks/1h/sys/api/string.lua +++ /dev/null @@ -1,57 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -function string.hasSuffix(str, suffix) - return string.sub(str, #suffix+1) == suffix -end - -function string.hasPrefix(str, prefix) - return string.sub(str, 1, #prefix) == prefix -end - -function string.getSuffix(str, prefix) - return string.sub(str, #prefix+1) -end - -function string.getPrefix(str, suffix) - return string.sub(str, 1, #suffix) -end - -function string.join(str, ...) - return table.concat(table.pack(str, ...)) -end - -function string.delim(str, ...) - return table.concat(table.pack(...), str) -end - -function string.split(str, delim, maxResultCountOrNil) - assert(#delim == 1, "only delim len 1 supported for now") - maxResultCountOrNil = (maxResultCountOrNil or 0)-1 - local rv = {} - local buf = "" - for i = 1, #str do - local c = string.sub(str,i,i) - if #rv ~= maxResultCountOrNil and c == delim then - table.insert(rv, buf) - buf = "" - else - buf = buf..c - end - end - table.insert(rv, buf) - return rv -end - -function string.replace(str, search, replacement) - local rv = "" - local consumedLen = 1 - local i = 1 - while i<#str do - if string.sub(str, i, i+#search-1) == search then - rv = rv .. string.sub(str, consumedLen, i-1) .. replacement - i=i+#search - consumedLen = i - end - i=i+1 - end - return rv .. string.sub(str, consumedLen) -end \ No newline at end of file diff --git a/src/disks/1h/sys/api/table.lua b/src/disks/1h/sys/api/table.lua deleted file mode 100644 index 0e802a3..0000000 --- a/src/disks/1h/sys/api/table.lua +++ /dev/null @@ -1,81 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -function table.deepcopy(orig, copies) - copies = copies or {} - - if type(orig) ~= 'table' then - return orig - elseif copies[orig] then - return copies[orig] - end - - local copy = {} - copies[orig] = copy - - for k, v in next, orig, nil do - local copied_key = table.deepcopy(k, copies) - local copied_val = table.deepcopy(v, copies) - copy[copied_key] = copied_val - end - - return copy -end - -function table.hasKey(tabl, query) - for i,v in pairs(tabl) do - if i==query then - return true - end - end - return false -end - -function table.hasVal(tabl, query) - for i,v in pairs(tabl) do - if v==query then - return true - end - end - return false -end - -local function serialize(table) - local output = "{" - for i,v in pairs(table) do - local coma=true - if type(i) == "string" then - output=output.."[\""..i.."\"]=" - end - if type(v) == "table" then - if v == table then - output=string.sub(output,1,#output-(#i+1)) - coma=false - else - output=output..serialize(v) - end - elseif type(v) == "string" then - output=output.."[=["..v.."]=]" - elseif type(v) == "number" then - output=output..tostring(v) - elseif type(v) == "boolean" then - if v == true then - output=output.."true" - else - output=output.."false" - end - elseif type(v) == "function" then - output=output.."function() end" - else - error("serialization of type \""..type(v).."\" is not supported") - end - if coma then - output=output.."," - end - end - if #table>0 or string.sub(output,#output,#output) == "," then - output=string.sub(output,1,#output-1) - end - output=output.."}" - return output -end - -table.serialize=serialize \ No newline at end of file diff --git a/src/disks/1h/sys/fs/init b/src/disks/1h/sys/fs/init deleted file mode 100644 index f275813..0000000 --- a/src/disks/1h/sys/fs/init +++ /dev/null @@ -1,124 +0,0 @@ -local args={...} -local drivers=args[1] -local log=args[2] -local bootDisk=args[3] -local driverutil=args[4] -local wd="/" -log.api.log("Bootdrive is "..bootDisk) -if not drivers.disk then - error("WTF") -- ??? -end - -local disks={} -local mounts={ - ["/"]=bootDisk -} -local meta={} - -local function refreshDisks() - local diskstmp={} - local tmp={} - for i,v in driverutil.list("disk") do - tmp[#tmp+1] = v - end - for _,d in ipairs(tmp) do - for i,v in d.api.list() do - if diskstmp[i]==nil then - diskstmp[i]=v - end - end - end - disks=diskstmp -end -refreshDisks() ---[[ -meta=load("return "..(disks[bootDisk].readAllText("/sys/fs/meta.ltn") or "{}"), "meta")() -if not meta then error("Meta failed to load") end -]] -local function resolve(path) - if path:sub(1,1)~="/" then path=wd..path end - local currmatch="/" - for i,_ in pairs(mounts) do - if string.hasPrefix(path, i) then - if #i>#currmatch then - currmatch=i - end - end - end - local drive=disks[mounts[currmatch]] - local newPath=string.getSuffix(path, currmatch) - return drive, newPath -end - -local fs={} - -function fs.list(path) - local drive, newPath = resolve(path) - return drive.list(newPath) -end - -function fs.readAllText(path) - local drive, newPath = resolve(path) - return drive.readAllText(newPath) -end - -function fs.writeAllText(path, content) - local drive, newPath = resolve(path) - return drive.writeAllText(newPath, content) -end - -function fs.delete(path) - local drive, newPath = resolve(path) - return drive.delete(newPath) -end - -function fs.exists(path) - local drive, newPath = resolve(path) - return (drive.fileExists(newPath) or drive.directoryExists(newPath)) -end - -function fs.fileExists(path) - local drive, newPath = resolve(path) - return drive.fileExists(newPath) -end - -function fs.directoryExists(path) - local drive, newPath = resolve(path) - return drive.directoryExists(newPath) -end - -function fs.createFile(path) - local drive, newPath = resolve(path) - return drive.makeFile(newPath) -end - -function fs.createDirectory(path) - local drive, newPath = resolve(path) - return drive.makeDirectory(newPath) -end - -fs.mkDir=fs.createDirectory -fs.mkFile=fs.createFile -fs.isDir=fs.directoryExists -fs.isFile=fs.fileExists - -function fs.getWorkingDir() - return wd -end - -function fs.setWorkingDir(dir) - if type(dir)~="string" then error("Invailid path") end - if dir:sub(1,1)~="/" then dir=wd..dir end - if dir:sub(#dir,#dir)~="/" then dir=dir.."/" end - if not fs.isDir(dir) then error("Invailid path") end -end - -function fs.loadAsFunc(path) - local file = fs.readAllText(path) - return load(file, path, "t", setmetatable({},{ - __index=_G, - __metatable=false - })) -end - -return fs \ No newline at end of file diff --git a/src/disks/1h/sys/fs/meta.ltn b/src/disks/1h/sys/fs/meta.ltn deleted file mode 100644 index d1128ee..0000000 --- a/src/disks/1h/sys/fs/meta.ltn +++ /dev/null @@ -1,69 +0,0 @@ -{["/sys/util/logger.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/bin/hex.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/opt"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/modules/cc.component.kd"]={["p"]=21,["o"]=0,["g"]=0} -,["/opt/astronand/ZDelta/init"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/api"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/10.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/7.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/1.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/bin/BASIC"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/cc/preboot.cc"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/ac"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/fs/init"]={["p"]=21,["o"]=0,["g"]=0} -,["/lib"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/api/table.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/5.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/usr/share/doc"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/3.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/opt/astronand/ZDelta"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/hypervisor/init.sys"]={["p"]=21,["o"]=0,["g"]=0} -,["/usr/share"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/modules"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/6.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/hypervisor"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/4.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/lib/array/math"]={["p"]=21,["o"]=0,["g"]=0} -,["/var"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/util/conhost.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/Hyprkrnl.sys"]={["p"]=21,["o"]=0,["g"]=0} -,["/bin"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/modules/ac.disks.kd"]={["p"]=21,["o"]=0,["g"]=0} -,["/lib/array/x"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/modules/cc.disks.kd"]={["p"]=21,["o"]=0,["g"]=0} -,["/opt/astronand/dbg"]={["p"]=21,["o"]=0,["g"]=0} -,["/usr"]={["p"]=21,["o"]=0,["g"]=0} -,["/usr/share/doc/kernel/drivers"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/util"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/8.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/9.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/latest.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/lib/array"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/cc/boot.cc"]={["p"]=21,["o"]=0,["g"]=0} -,["/home"]={["p"]=21,["o"]=0,["g"]=0} -,["/usr/share/doc/kernel/drivers/disk.md"]={["p"]=21,["o"]=0,["g"]=0} -,["/lib/LibDeflate"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/fs/meta.ltn"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/0.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/bootData"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/api/string.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log"]={["p"]=21,["o"]=0,["g"]=0} -,["/bin/shell.hex"]={["p"]=21,["o"]=0,["g"]=0} -,["/opt/astronand/dbg/init"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/bootloader.sys"]={["p"]=21,["o"]=0,["g"]=0} -,["/lib/array/2d"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/cc"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot/ac/boot.ac"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/log/kernel/2.log"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/modules/ccpc.disk.kd"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/api/require.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/bin/lua.lua"]={["p"]=21,["o"]=0,["g"]=0} -,["/usr/share/doc/kernel"]={["p"]=21,["o"]=0,["g"]=0} -,["/boot"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/fs"]={["p"]=21,["o"]=0,["g"]=0} -,["/var/system"]={["p"]=21,["o"]=0,["g"]=0} -,["/sys/modules/cc.terminal.kd"]={["p"]=21,["o"]=0,["g"]=0} -,["/opt/astronand"]={["p"]=21,["o"]=0,["g"]=0} -} \ No newline at end of file diff --git a/src/disks/1h/sys/modules/ac.disks.kd b/src/disks/1h/sys/modules/ac.disks.kd deleted file mode 100644 index 117cb36..0000000 --- a/src/disks/1h/sys/modules/ac.disks.kd +++ /dev/null @@ -1,75 +0,0 @@ -local kernelArgs={...} -local apis=kernelArgs[1] -local drivers=kernelArgs[2] -local log=kernelArgs[3] -local driver={} -local disks = {} - -driver.type = "disk" -driver.name = "AC:Disk" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for AC disks" -driver.arch = "ac" -driver.api = {} - -local function refreshDisks() - local tmp={} - for i,v in apis.component.list() do - if i=="disk" then - tmp[v.id]={ - readAllText=function(path) - return v:open(path).read() - end, - writeAllText=function(path, content) - return v:open(path).write(content) - end, - list=function(path) - return v:list(path) - end, - delete=function(path) - return v:delete(path) - end, - makeDirectory=function(path) - return v:makeDirectory(path) - end, - makeFile=function(path) - return v:makeFile(path) - end, - directoryExists=function(path) - return v:directoryExists(path) - end, - fileExists=function(path) - return v:fileExists(path) - end - } - end - end - disks=tmp -end - -function driver.init() - refreshDisks() -end - -function driver.api.list() - local tmp={} - for i,v in pairs(disks) do - tmp[#tmp+1]={id=i, obj=v} - end - local i=0 - return function() - i=i+1 - if tmp[i]==nil then return end - return tmp.id, tmp.obj - end -end - -function driver.main() - while true do - refreshDisks() - sleep(5) - end -end - -drivers[#drivers+1]=driver \ No newline at end of file diff --git a/src/disks/1h/sys/modules/cc.disks.kd b/src/disks/1h/sys/modules/cc.disks.kd deleted file mode 100644 index 4ef64d0..0000000 --- a/src/disks/1h/sys/modules/cc.disks.kd +++ /dev/null @@ -1,100 +0,0 @@ -local kernelArgs={...} -local apis=kernelArgs[1] -local drivers=kernelArgs[2] -local log=kernelArgs[3] -local driver={} -local disks={} -local driverutil=kernelArgs[4] - -driver.type = "disk" -driver.name = "CC:Disks" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for CC:Tweaked disks" -driver.arch = "cc" -driver.api = {} - -local function abs(path) - if path:sub(1,1)~="/" then path="/"..path end - return path -end - -local function newDisk(root) - root="/"..root - return { - readAllText=function(path) - local file=apis.fs.open(root..abs(path),"r") - local text=file.readAll() - file.close() - return text - end, - writeAllText=function(path, content) - local file=apis.fs.open(root..abs(path),"w") - file.write(content) - file.close() - end, - list=function(path) - return apis.fs.list(root..abs(path)) - end, - delete=function(path) - return apis.fs.delete(root..abs(path)) - end, - makeDirectory=function(path) - return apis.fs.makeDir(root..abs(path)) - end, - makeFile=function(path) - local file=apis.fs.open(root..abs(path),"w") - file.close() - end, - directoryExists=function(path) - return apis.fs.exists(root..abs(path)) and apis.fs.isDir(root..abs(path)) - end, - fileExists=function(path) - return apis.fs.exists(root..abs(path)) and not apis.fs.isDir(root..abs(path)) - end - } -end - -local function refreshDisks(peripheral) - local tmp2={} - tmp2["disk"]=newDisk("disk") - for i,v in ipairs(peripheral.api.getNames()) do - if peripheral.api.isType(v, "drive") then - local p=peripheral.api.wrap(v) - if p.isDiskPresent() then - if p.getMountPath()~="disk" then - tmp2["disk_"..p.getID()] = newDisk(p.getMountPath()) - end - end - end - end - disks=tmp2 - return true -end - -function driver.init() - local peripheral=driverutil.getFirst("component") - refreshDisks(peripheral) -end - -function driver.api.list() - local tmp={} - for i,v in pairs(disks) do - tmp[#tmp+1]={id=i, obj=v} - end - local i=0 - return function() - i=i+1 - if tmp[i]==nil then return end - return tmp[i].id, tmp[i].obj - end -end - -function driver.main() - while true do - refreshDisks() - sleep(5) - end -end - -drivers[#drivers+1] = driver \ No newline at end of file diff --git a/src/disks/1h/sys/modules/cc.periph.kd b/src/disks/1h/sys/modules/cc.periph.kd deleted file mode 100644 index 3533c64..0000000 --- a/src/disks/1h/sys/modules/cc.periph.kd +++ /dev/null @@ -1,129 +0,0 @@ -local kernelArgs={...} -local apis=kernelArgs[1] -local drivers=kernelArgs[2] -local log=kernelArgs[3] -local driver={} - -driver.type = "component" -driver.name = "CC:Periph" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for CC:Tweaked peripherals" -driver.arch = "cc" -driver.api = {} - -local native,sides -if apis.peripheral then - native = apis.peripheral - sides = apis.rs.getSides() -end - -function driver.api.getNames() - local results = {} - for n = 1, #sides do - local side = sides[n] - if native.isPresent(side) then - table.insert(results, side) - if native.hasType(side, "peripheral_hub") then - local remote = native.call(side, "getNamesRemote") - for _, name in ipairs(remote) do - table.insert(results, name) - end - end - end - end - return results -end - -function driver.api.getType(peripheral) - if type(peripheral) == "string" then -- Peripheral name passed - if native.isPresent(peripheral) then - return native.getType(peripheral) - end - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then - return native.call(side, "getTypeRemote", peripheral) - end - end - return nil - else - local mt = getmetatable(peripheral) - if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then - error("bad argument #1 (table is not a peripheral)", 2) - end - return table.unpack(mt.types) - end -end - -function driver.api.isType(peripheral, peripheral_type) - if type(peripheral) == "string" then -- Peripheral name passed - if native.isPresent(peripheral) then - return native.hasType(peripheral, peripheral_type) - end - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", peripheral) then - return native.call(side, "hasTypeRemote", peripheral, peripheral_type) - end - end - return nil - else - local mt = getmetatable(peripheral) - if not mt or mt.__name ~= "peripheral" or type(mt.types) ~= "table" then - error("bad argument #1 (table is not a peripheral)", 2) - end - return mt.types[peripheral_type] ~= nil - end -end - -function driver.api.getMethods(name) - if native.isPresent(name) then - return native.getMethods(name) - end - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then - return native.call(side, "getMethodsRemote", name) - end - end - return nil -end - -function driver.api.call(name, method, ...) - if native.isPresent(name) then - return native.call(name, method, ...) - end - - for n = 1, #sides do - local side = sides[n] - if native.hasType(side, "peripheral_hub") and native.call(side, "isPresentRemote", name) then - return native.call(side, "callRemote", name, method, ...) - end - end - return nil -end - -function driver.api.wrap(name) - local methods = driver.api.getMethods(name) - if not methods then - return nil - end - - local types = { driver.api.getType(name) } - for i = 1, #types do types[types[i]] = true end - local result = setmetatable({}, { - __name = "peripheral", - name = name, - type = types[1], - types = types, - }) - for _, method in ipairs(methods) do - result[method] = function(...) - return driver.api.call(name, method, ...) - end - end - return result -end - -drivers[#drivers+1] = driver \ No newline at end of file diff --git a/src/disks/1h/sys/modules/cc.terminal.kd b/src/disks/1h/sys/modules/cc.terminal.kd deleted file mode 100644 index 26e1fc7..0000000 --- a/src/disks/1h/sys/modules/cc.terminal.kd +++ /dev/null @@ -1,74 +0,0 @@ -local kernelArgs={...} -local apis=kernelArgs[1] -local drivers=kernelArgs[2] -local log=kernelArgs[3] -local driver={} - -driver.type = "terminal" -driver.name = "CC:Term" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for CC:Tweaked screens" -driver.arch = "cc" -driver.api = {} - --- Prints text handling \n, \t, and \b with scrolling (no wrapping) -local function write(text) - local x, y = apis.term.getCursorPos() - local w, h = apis.term.getSize() - - for i = 1, #text do - local c = text:sub(i, i) - - if c == "\n" then - y = y + 1 - x = 1 - elseif c == "\t" then - local tabSize = 4 - local spaces = tabSize - ((x - 1) % tabSize) - apis.term.write(string.rep(" ", spaces)) - x = x + spaces - elseif c == "\b" then - if x > 1 then - x = x - 1 - apis.term.setCursorPos(x, y) - apis.term.write(" ") - apis.term.setCursorPos(x, y) - end - else - if x <= w and y <= h then - apis.term.setCursorPos(x, y) - apis.term.write(c) - x = x + 1 - end - end - - -- Handle scrolling if we go past bottom - if y > h then - apis.term.scroll(1) - y = h - apis.term.setCursorPos(x, y) - end - end - - apis.term.setCursorPos(x, y) -end - -function driver.api.print(text) - write(text.."\n") -end - -function driver.api.printInline(text) - write(text) -end - -function driver.api.clear() - apis.term.clear() - apis.term.setCursorPos(1,1) -end - -function driver.api.getSize() - return apis.term.getSize() -end - -drivers[#drivers+1] = driver \ No newline at end of file diff --git a/src/disks/1h/sys/modules/ccpc.disk.kd b/src/disks/1h/sys/modules/ccpc.disk.kd deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/sys/system/hypervisor/init b/src/disks/1h/sys/system/hypervisor/init deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/sys/system/require b/src/disks/1h/sys/system/require deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/1h/sys/util/conhost.lua b/src/disks/1h/sys/util/conhost.lua deleted file mode 100644 index 81129d9..0000000 --- a/src/disks/1h/sys/util/conhost.lua +++ /dev/null @@ -1,3 +0,0 @@ - --- --- @ICON$101003000000000000092492492490080000000010082000000010080400000010080080000010080400000010082002492010080000000010092492492490000000000000092492492490080000000010080000000010092492492490000000000000 diff --git a/src/disks/1h/sys/util/logger.lua b/src/disks/1h/sys/util/logger.lua deleted file mode 100644 index 58589ec..0000000 --- a/src/disks/1h/sys/util/logger.lua +++ /dev/null @@ -1,70 +0,0 @@ -local args={...} -local computer=args[1] -local logs={["nil"]=""} -local hooks={["nil"]=function()end} -local log={api={}} - -local function convert_epoch(epoch) - return computer.date("[%b %d %H:%M:%S]", epoch/1000) -end - -function log.getProcess(func) - if type(func)=="function" then - log.getProcess=func - else - return "Hyprkrnl" - end -end - -function log.api.log(text, logID) - local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[IN] "..text - logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n" - hooks[tostring(logID)](appendedText) -end - -function log.api.warn(text, logID) - local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[WN] "..text - logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n" - hooks[tostring(logID)](appendedText) -end - -function log.api.fail(text, logID) - local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[FA] "..text - logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n" - hooks[tostring(logID)](appendedText) -end - -function log.api.debug(text, logID) - local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[DE] "..text - logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n" - hooks[tostring(logID)](appendedText) -end - -function log.api.error(text, logID) - local appendedText=convert_epoch(computer.time()).." "..log.getProcess()..":[ER] "..text - logs[tostring(logID)]=logs[tostring(logID)]..appendedText.."\n" - hooks[tostring(logID)](appendedText) -end - -function log.api.get(logID) - return logs[tostring(logID)] -end - -function log.setHook(func, logID) - hooks[tostring(logID)]=func - return { - removeHook=function() - hooks[tostring(logID)]=function()end - end - } -end - -local UUID = 0 -function log.api.createLog(logID) - if logs[tostring(logID)]~=nil then error("cannot create duplicate log") end - if logID==nil then UUID=UUID+1; logID=UUID end - hooks[tostring(logID)]=function()end - logs[tostring(logID)]="" -end - -return log \ No newline at end of file diff --git a/src/disks/1h/usr/share/doc/kernel/drivers/disk.md b/src/disks/1h/usr/share/doc/kernel/drivers/disk.md deleted file mode 100644 index d40e8c5..0000000 --- a/src/disks/1h/usr/share/doc/kernel/drivers/disk.md +++ /dev/null @@ -1,6 +0,0 @@ -### API: ---- -``` -getDisks():id, obj - -``` \ No newline at end of file diff --git a/src/disks/1h/var/log/kernel/0.log b/src/disks/1h/var/log/kernel/0.log deleted file mode 100644 index 8a5d977..0000000 --- a/src/disks/1h/var/log/kernel/0.log +++ /dev/null @@ -1,17 +0,0 @@ -[Oct 31 18:33:08] Hyprkrnl:[IN] Created logger -[Oct 31 18:33:08] Hyprkrnl:[IN] Loading globals... -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading string.lua -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading table.lua -[Oct 31 18:33:08] Hyprkrnl:[IN] Loading drivers... -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 31 18:33:08] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 31 18:33:08] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 31 18:33:08] Hyprkrnl:[DE] Sorting drivers... -[Oct 31 18:33:08] Hyprkrnl:[DE] Initializing drivers... -[Oct 31 18:33:08] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 31 18:33:08] Hyprkrnl:[IN] Loading filesystem... -[Oct 31 18:33:08] Hyprkrnl:[IN] Bootdrive is disk -[Oct 31 18:33:08] Hyprkrnl:[IN] Loading system... diff --git a/src/disks/1h/var/log/kernel/1.log b/src/disks/1h/var/log/kernel/1.log deleted file mode 100644 index ce8804c..0000000 --- a/src/disks/1h/var/log/kernel/1.log +++ /dev/null @@ -1,8 +0,0 @@ -[Nov 12 22:17:07] Hyprkrnl:[IN] Created logger -[Nov 12 22:17:07] Hyprkrnl:[IN] Loading globals... -[Nov 12 22:17:07] Hyprkrnl:[IN] Loading drivers... -[Nov 12 22:17:07] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Nov 12 22:17:07] Hyprkrnl:[IN] Loaded 3 drivers -[Nov 12 22:17:07] Hyprkrnl:[IN] Loading filesystem... -[Nov 12 22:17:07] Hyprkrnl:[IN] Bootdrive is disk -[Nov 12 22:17:07] Hyprkrnl:[IN] Loading system... diff --git a/src/disks/1h/var/log/kernel/10.log b/src/disks/1h/var/log/kernel/10.log deleted file mode 100644 index 674da0e..0000000 --- a/src/disks/1h/var/log/kernel/10.log +++ /dev/null @@ -1,17 +0,0 @@ -[Oct 30 18:13:15] Hyprkrnl:[IN] Created logger -[Oct 30 18:13:15] Hyprkrnl:[IN] Loading globals... -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading string.lua -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading table.lua -[Oct 30 18:13:15] Hyprkrnl:[IN] Loading drivers... -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 18:13:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 18:13:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 18:13:15] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 18:13:15] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 18:13:15] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 18:13:15] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 18:13:15] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 18:13:15] Hyprkrnl:[IN] Loading system... diff --git a/src/disks/1h/var/log/kernel/2.log b/src/disks/1h/var/log/kernel/2.log deleted file mode 100644 index cbe2123..0000000 --- a/src/disks/1h/var/log/kernel/2.log +++ /dev/null @@ -1,8 +0,0 @@ -[Nov 13 20:06:54] Hyprkrnl:[IN] Created logger -[Nov 13 20:06:54] Hyprkrnl:[IN] Loading globals... -[Nov 13 20:06:54] Hyprkrnl:[IN] Loading drivers... -[Nov 13 20:06:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Nov 13 20:06:54] Hyprkrnl:[IN] Loaded 3 drivers -[Nov 13 20:06:54] Hyprkrnl:[IN] Loading filesystem... -[Nov 13 20:06:54] Hyprkrnl:[IN] Bootdrive is disk -[Nov 13 20:06:54] Hyprkrnl:[IN] Loading system... diff --git a/src/disks/1h/var/log/kernel/3.log b/src/disks/1h/var/log/kernel/3.log deleted file mode 100644 index 6da724e..0000000 --- a/src/disks/1h/var/log/kernel/3.log +++ /dev/null @@ -1,17 +0,0 @@ -[Nov 13 20:07:50] Hyprkrnl:[IN] Created logger -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading globals... -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading string.lua -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading table.lua -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading drivers... -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ac.disks.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.disks.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.periph.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Nov 13 20:07:50] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Nov 13 20:07:50] Hyprkrnl:[DE] Sorting drivers... -[Nov 13 20:07:50] Hyprkrnl:[DE] Initializing drivers... -[Nov 13 20:07:50] Hyprkrnl:[IN] Loaded 3 drivers -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading filesystem... -[Nov 13 20:07:50] Hyprkrnl:[IN] Bootdrive is disk -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading system... diff --git a/src/disks/1h/var/log/kernel/4.log b/src/disks/1h/var/log/kernel/4.log deleted file mode 100644 index 20781ef..0000000 --- a/src/disks/1h/var/log/kernel/4.log +++ /dev/null @@ -1,19 +0,0 @@ -[Oct 30 17:41:54] Hyprkrnl:[IN] Created logger -[Oct 30 17:41:54] Hyprkrnl:[IN] Loading globals... -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading require.lua -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading string.lua -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading table.lua -[Oct 30 17:41:54] Hyprkrnl:[IN] Loading drivers... -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 17:41:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 17:41:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 17:41:54] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 17:41:54] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 17:41:54] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 17:41:54] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 17:41:54] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 17:41:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS -[Oct 30 17:41:54] Hyprkrnl:[IN] Loading hypervisor... diff --git a/src/disks/1h/var/log/kernel/5.log b/src/disks/1h/var/log/kernel/5.log deleted file mode 100644 index 5c03d6f..0000000 --- a/src/disks/1h/var/log/kernel/5.log +++ /dev/null @@ -1,19 +0,0 @@ -[Oct 30 17:43:09] Hyprkrnl:[IN] Created logger -[Oct 30 17:43:09] Hyprkrnl:[IN] Loading globals... -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading require.lua -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading string.lua -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading table.lua -[Oct 30 17:43:09] Hyprkrnl:[IN] Loading drivers... -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 17:43:09] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 17:43:09] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 17:43:09] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 17:43:09] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 17:43:09] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 17:43:09] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 17:43:09] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 17:43:09] Hyprkrnl:[IN] [REQUIRE]: Initialized FS -[Oct 30 17:43:09] Hyprkrnl:[IN] Loading hypervisor... diff --git a/src/disks/1h/var/log/kernel/6.log b/src/disks/1h/var/log/kernel/6.log deleted file mode 100644 index 66bbb5c..0000000 --- a/src/disks/1h/var/log/kernel/6.log +++ /dev/null @@ -1,19 +0,0 @@ -[Oct 30 17:44:55] Hyprkrnl:[IN] Created logger -[Oct 30 17:44:55] Hyprkrnl:[IN] Loading globals... -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading require.lua -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading string.lua -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading table.lua -[Oct 30 17:44:55] Hyprkrnl:[IN] Loading drivers... -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 17:44:55] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 17:44:55] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 17:44:55] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 17:44:55] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 17:44:55] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 17:44:55] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 17:44:55] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 17:44:55] Hyprkrnl:[IN] [REQUIRE]: Initialized FS -[Oct 30 17:44:55] Hyprkrnl:[IN] Loading hypervisor... diff --git a/src/disks/1h/var/log/kernel/7.log b/src/disks/1h/var/log/kernel/7.log deleted file mode 100644 index ff9969a..0000000 --- a/src/disks/1h/var/log/kernel/7.log +++ /dev/null @@ -1,19 +0,0 @@ -[Oct 30 17:45:15] Hyprkrnl:[IN] Created logger -[Oct 30 17:45:15] Hyprkrnl:[IN] Loading globals... -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading require.lua -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading string.lua -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading table.lua -[Oct 30 17:45:15] Hyprkrnl:[IN] Loading drivers... -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 17:45:15] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 17:45:15] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 17:45:15] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 17:45:15] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 17:45:15] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 17:45:15] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 17:45:15] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 17:45:15] Hyprkrnl:[IN] [REQUIRE]: Initialized FS -[Oct 30 17:45:15] Hyprkrnl:[IN] Loading hypervisor... diff --git a/src/disks/1h/var/log/kernel/8.log b/src/disks/1h/var/log/kernel/8.log deleted file mode 100644 index 67d5017..0000000 --- a/src/disks/1h/var/log/kernel/8.log +++ /dev/null @@ -1,19 +0,0 @@ -[Oct 30 18:02:54] Hyprkrnl:[IN] Created logger -[Oct 30 18:02:54] Hyprkrnl:[IN] Loading globals... -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading require.lua -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading string.lua -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading table.lua -[Oct 30 18:02:54] Hyprkrnl:[IN] Loading drivers... -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 18:02:54] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 18:02:54] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 18:02:54] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 18:02:54] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 18:02:54] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 18:02:54] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 18:02:54] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 18:02:54] Hyprkrnl:[IN] [REQUIRE]: Initialized FS -[Oct 30 18:02:54] Hyprkrnl:[IN] Loading hypervisor... diff --git a/src/disks/1h/var/log/kernel/9.log b/src/disks/1h/var/log/kernel/9.log deleted file mode 100644 index e725cfb..0000000 --- a/src/disks/1h/var/log/kernel/9.log +++ /dev/null @@ -1,19 +0,0 @@ -[Oct 30 18:03:46] Hyprkrnl:[IN] Created logger -[Oct 30 18:03:46] Hyprkrnl:[IN] Loading globals... -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading require.lua -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading string.lua -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading table.lua -[Oct 30 18:03:46] Hyprkrnl:[IN] Loading drivers... -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module ac.disks.kd -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.disks.kd -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.periph.kd -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Oct 30 18:03:46] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Oct 30 18:03:46] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Oct 30 18:03:46] Hyprkrnl:[DE] Sorting drivers... -[Oct 30 18:03:46] Hyprkrnl:[DE] Initializing drivers... -[Oct 30 18:03:46] Hyprkrnl:[IN] Loaded 3 drivers -[Oct 30 18:03:46] Hyprkrnl:[IN] Loading filesystem... -[Oct 30 18:03:46] Hyprkrnl:[IN] Bootdrive is disk -[Oct 30 18:03:46] Hyprkrnl:[IN] [REQUIRE]: Initialized FS -[Oct 30 18:03:46] Hyprkrnl:[IN] Loading hypervisor... diff --git a/src/disks/1h/var/log/kernel/bootData b/src/disks/1h/var/log/kernel/bootData deleted file mode 100644 index 6c19da0..0000000 --- a/src/disks/1h/var/log/kernel/bootData +++ /dev/null @@ -1,13 +0,0 @@ -{["debug"]=true,["prevError"]=[=[[string "/sys/Hyperion.s..."]:13: attempt to call field 'loadAsFunc' (a nil value) -stack traceback: - [string "/sys/Hyperion.s..."]:13: in function 'run' - [string "/sys/Hyperion.s..."]:20: in main chunk - [C]: in function 'xpcall' - [string "local args={......"]:121: in function 'runAsKernel' - [string "local args={......"]:224: in function 'kernel' - kernel:22: in function '?' - kernel:69: in main chunk - [C]: in function 'xpcall' - preboot.cc:176: in function - [C]: in function 'pcall' - preboot.cc:175: in function ]=],["logNum"]=4,["errorCount"]=0} \ No newline at end of file diff --git a/src/disks/1h/var/log/kernel/latest.log b/src/disks/1h/var/log/kernel/latest.log deleted file mode 100644 index 6da724e..0000000 --- a/src/disks/1h/var/log/kernel/latest.log +++ /dev/null @@ -1,17 +0,0 @@ -[Nov 13 20:07:50] Hyprkrnl:[IN] Created logger -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading globals... -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading string.lua -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading table.lua -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading drivers... -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ac.disks.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.disks.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.periph.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module cc.terminal.kd -[Nov 13 20:07:50] Hyprkrnl:[DE] Loading module ccpc.disk.kd -[Nov 13 20:07:50] Hyprkrnl:[IN] Unloading non "cc" specific drivers... -[Nov 13 20:07:50] Hyprkrnl:[DE] Sorting drivers... -[Nov 13 20:07:50] Hyprkrnl:[DE] Initializing drivers... -[Nov 13 20:07:50] Hyprkrnl:[IN] Loaded 3 drivers -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading filesystem... -[Nov 13 20:07:50] Hyprkrnl:[IN] Bootdrive is disk -[Nov 13 20:07:50] Hyprkrnl:[IN] Loading system... diff --git a/src/disks/2f/burn.lua b/src/disks/2f/burn.lua deleted file mode 100644 index 4d7fa95..0000000 --- a/src/disks/2f/burn.lua +++ /dev/null @@ -1,14 +0,0 @@ -local biosData = ({...})[1] -local disks = {} - -for i,v in component.list() do - if i == "disk" then - disks[v.id]=v - end -end - -local bootDisk = disks[biosData.bootDrive.open("/config").read()] - -if not bootDisk.type=="udd" then - error("invalid") -end \ No newline at end of file diff --git a/src/disks/2f/config b/src/disks/2f/config deleted file mode 100644 index 0f47e47..0000000 --- a/src/disks/2f/config +++ /dev/null @@ -1 +0,0 @@ -disk_56 \ No newline at end of file diff --git a/src/disks/3h/boot/Hyprkrnl.sys b/src/disks/3h/boot/Hyprkrnl.sys deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/3h/boot/ac/boot.ac b/src/disks/3h/boot/ac/boot.ac deleted file mode 100644 index 8ea9cc8..0000000 --- a/src/disks/3h/boot/ac/boot.ac +++ /dev/null @@ -1,50 +0,0 @@ -local biosData = ({...})[1] -local apis={} - -local lua = { - coroutine = true, - debug = true, - _HOST = true, - _VERSION = true, - assert = true, - collectgarbage = true, - error = true, - gcinfo = true, - getfenv = true, - getmetatable = true, - ipairs = true, - __inext = true, - load = true, - math = true, - next = true, - pairs = true, - pcall = true, - rawequal = true, - rawget = true, - rawlen = true, - rawset = true, - select = true, - setfenv = true, - setmetatable = true, - string = true, - table = true, - tonumber = true, - tostring = true, - type = true, - xpcall = true -} - -for i,v in ipairs(_G) do - if not lua[i] then - apis[i]=v - _G[i]=nil - end -end - -local function getFile(path) - return biosData.bootDrive:open(path).read() -end - -local computer = apis.component.getFirst("computer") -local kernel = load(getFile("/boot/Hyprkrnl.sys"), "@kernel", "t", _G) -kernel("ac", apis, biosData.bootDrive.id, apis.component.getFirst("screen"), computer.getMachineEvent) diff --git a/src/disks/3h/boot/cc/boot.cc b/src/disks/3h/boot/cc/boot.cc deleted file mode 100644 index 514021d..0000000 --- a/src/disks/3h/boot/cc/boot.cc +++ /dev/null @@ -1,119 +0,0 @@ --- UnBIOS by JackMacWindows --- This will undo most of the changes/additions made in the BIOS, but some things may remain wrapped if `debug` is unavailable --- To use, just place a `bios.lua` in the root of the drive, and run this program --- Here's a list of things that are irreversibly changed: --- * both `bit` and `bit32` are kept for compatibility --- * string metatable blocking (on old versions of CC) --- In addition, if `debug` is not available these things are also irreversibly changed: --- * old Lua 5.1 `load` function (for loading from a function) --- * `loadstring` prefixing (before CC:T 1.96.0) --- * `http.request` --- * `os.shutdown` and `os.reboot` --- * `peripheral` --- * `turtle.equip[Left|Right]` --- Licensed under the MIT license -if _HOST:find("UnBIOS") then return end -local keptAPIs = {keys=true, bit32 = true, bit = true, ccemux = true, config = true, coroutine = true, debug = true, fs = true, http = true, mounter = true, os = true, periphemu = true, peripheral = true, redstone = true, rs = true, term = true, utf8 = true, _HOST = true, _CC_DEFAULT_SETTINGS = true, _CC_DISABLE_LUA51_FEATURES = true, _VERSION = true, assert = true, collectgarbage = true, error = true, gcinfo = true, getfenv = true, getmetatable = true, ipairs = true, __inext = true,load = true, loadstring = true, math = true, newproxy = true, next = true, pairs = true, pcall = true, rawequal = true, rawget = true, rawlen = true, rawset = true, select = true, setfenv = true, setmetatable = true, string = true, table = true, tonumber = true, tostring = true, type = true, unpack = true, xpcall = true, turtle = true, pocket = true, commands = true, _G = true} -local t = {} -for k in pairs(_G) do if not keptAPIs[k] then table.insert(t, k) end end -for _,k in ipairs(t) do _G[k] = nil end -local native = _G.term.native() -for _, method in ipairs {"nativePaletteColor", "nativePaletteColour", "screenshot"} do native[method] = _G.term[method] end -_G.term = native -if _G.http then - _G.http.checkURL = _G.http.checkURLAsync - _G.http.websocket = _G.http.websocketAsync -end -if _G.commands then _G.commands = _G.commands.native end -if _G.turtle then _G.turtle.native, _G.turtle.craft = nil end -local delete = {os = {"version", "pullEventRaw", "pullEvent", "run", "loadAPI", "unloadAPI", "sleep"}, http = _G.http and {"get", "post", "put", "delete", "patch", "options", "head", "trace", "listen", "checkURLAsync", "websocketAsync"}, fs = {"complete", "isDriveRoot"}} -for k,v in pairs(delete) do for _,a in ipairs(v) do _G[k][a] = nil end end -_G._HOST = _G._HOST .. " (UnBIOS)" --- Set up TLCO --- This functions by crashing `rednet.run` by removing `os.pullEventRaw`. Normally --- this would cause `parallel` to throw an error, but we replace `error` with an --- empty placeholder to let it continue and return without throwing. This results --- in the `pcall` returning successfully, preventing the error-displaying code --- from running - essentially making it so that `os.shutdown` is called immediately --- after the new BIOS exits. --- --- From there, the setup code is placed in `term.native` since it's the first --- thing called after `parallel` exits. This loads the new BIOS and prepares it --- for execution. Finally, it overwrites `os.shutdown` with the new function to --- allow it to be the last function called in the original BIOS, and returns. --- From there execution continues, calling the `term.redirect` dummy, skipping --- over the error-handling code (since `pcall` returned ok), and calling --- `os.shutdown()`. The real `os.shutdown` is re-added, and the new BIOS is tail --- called, which effectively makes it run as the main chunk. -local olderror = error -_G.error = function() end -_G.term.redirect = function() end -function _G.term.native() - _G.term.native = nil - _G.term.redirect = nil - _G.error = olderror - term.setBackgroundColor(32768) - term.setTextColor(1) - term.setCursorPos(1, 1) - term.setCursorBlink(true) - term.clear() - local file = fs.open("/boot/cc/bootloader.cc", "r") - if file == nil then - term.setCursorBlink(false) - term.setTextColor(16384) - term.write("Could not find /boot/cc/bootloader.cc. UnBIOS cannot continue.") - term.setCursorPos(1, 2) - term.write("Press any key to continue") - coroutine.yield("key") - os.shutdown() - end - local fn, err = loadstring(file.readAll(), "@bootloader.cc") - file.close() - if fn == nil then - term.setCursorBlink(false) - term.setTextColor(16384) - term.write("Could not load /boot/cc/bootloader.cc. UnBIOS cannot continue.") - term.setCursorPos(1, 2) - term.write(err) - term.setCursorPos(1, 3) - term.write("Press any key to continue") - coroutine.yield("key") - os.shutdown() - end - setfenv(fn, _G) - local oldshutdown = os.shutdown - os.shutdown = function() - os.shutdown = oldshutdown - return fn() - end -end -if debug then - -- Restore functions that were overwritten in the BIOS - -- Apparently this has to be done *after* redefining term.native - local function restoreValue(tab, idx, name, hint) - local i, key, value = 1, debug.getupvalue(tab[idx], hint) - while key ~= name and key ~= nil do - key, value = debug.getupvalue(tab[idx], i) - i=i+1 - end - tab[idx] = value or tab[idx] - end - restoreValue(_G, "loadstring", "nativeloadstring", 1) - restoreValue(_G, "load", "nativeload", 5) - if http then restoreValue(http, "request", "nativeHTTPRequest", 3) end - restoreValue(os, "shutdown", "nativeShutdown", 1) - restoreValue(os, "reboot", "nativeReboot", 1) - if turtle then - restoreValue(turtle, "equipLeft", "v", 1) - restoreValue(turtle, "equipRight", "v", 1) - end - do - local i, key, value = 1, debug.getupvalue(peripheral.isPresent, 2) - while key ~= "native" and key ~= nil do - key, value = debug.getupvalue(peripheral.isPresent, i) - i=i+1 - end - _G.peripheral = value or peripheral - end -end -os.shutdown() \ No newline at end of file diff --git a/src/disks/3h/boot/cc/bootloader.cc b/src/disks/3h/boot/cc/bootloader.cc deleted file mode 100644 index ff4fea1..0000000 --- a/src/disks/3h/boot/cc/bootloader.cc +++ /dev/null @@ -1,115 +0,0 @@ -local apis={} - -local lua = { - coroutine = true, - debug = true, - _HOST = true, - _VERSION = true, - assert = true, - collectgarbage = true, - error = true, - gcinfo = true, - getfenv = true, - getmetatable = true, - ipairs = true, - __inext = true, - load = true, - math = true, - next = true, - pairs = true, - pcall = true, - rawequal = true, - rawget = true, - rawlen = true, - rawset = true, - select = true, - setfenv = true, - setmetatable = true, - string = true, - table = true, - tonumber = true, - tostring = true, - type = true, - xpcall = true -} - -for i,v in ipairs(_G) do - if not lua[i] then - apis[i]=v - _G[i]=nil - end -end - -local function getFile(path) - if path:sub(1,1) ~= "/" then - path="/"..path - end - local file = apis.fs.open("/root"..path) -end - -local function write(text) - -end - -local event_queue = {} -local function addEventRaw(...) - event_queue[#event_queue+1] = {...} -end - -local function getEvent() - local event = event_queue[1] - event_queue = {table.unpack(event_queue, 2)} - return table.unpack(event) -end - -local lkeys={} -lkeys[keys.enter]="\n" -lkeys[keys.backspace]="\b" -lkeys[keys.tab]="\t" - -local kernel = load(getFile("/boot/Hyprkrnl.sys"), "@kernel", "t", _G) -local kernel_coro = coroutine.create(function() - kernel("cc", apis, "internal", { - print=function(text) - write(text) - write("\n") - end, - printInline=function(text) - write(text) - end, - clear=function() - apis.term.clear() - apis.term.setCursorPos(1,1) - end - }, getEvent) -end) - -debug.sethook(kernel_coro, function() coroutine.yield("CC:TWEAKED", "CORO_TIMEOUT") end, "l", 3000) -while true do - local ret = {coroutine.resume(kernel_coro)} - if coroutine.status(kernel_coro) == "dead" then - break - end - local timer = os.startTimer(0) - local exit = false - repeat - local event = {coroutine.yield()} - if event[1] == "timer" and event[2]==timer then - exit=true - elseif event[1]==nil then - elseif event[1]=="key" then - addEventRaw("keyPressed", 1, event[2]) - if lkeys[event[2]] then - addEventRaw("keyTyped", 1, lkeys[event[2]]) - end - elseif event[1]=="char" then - addEventRaw("keyTyped", 1, event[2]) - elseif event[1]=="key_up" then - addEventRaw("keyReleased", 1, event[2]) - elseif event[1]=="disk" then - addEventRaw("componentAdded", "disk", sandboxedFS.new(api.disk.getMountPath(event[2]), apis.disk.getID(event[2]))) - elseif event[1]=="disk_eject" then - addEventRaw("componentRemoved", "disk") - end - until exit -end \ No newline at end of file diff --git a/src/disks/3h/boot/cc/sandboxedFS.cc b/src/disks/3h/boot/cc/sandboxedFS.cc deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/bin_/beep b/src/disks/45h/bin_/beep deleted file mode 100644 index d8e8eb0..0000000 --- a/src/disks/45h/bin_/beep +++ /dev/null @@ -1,2 +0,0 @@ -local computer=component.getFirst("computer") -computer.beep(800, 0.2, 1) \ No newline at end of file diff --git a/src/disks/45h/bin_/clear b/src/disks/45h/bin_/clear deleted file mode 100644 index 2d2c343..0000000 --- a/src/disks/45h/bin_/clear +++ /dev/null @@ -1,2 +0,0 @@ -local term=component.getFirst("screen") -term.clear() \ No newline at end of file diff --git a/src/disks/45h/bin_/debug b/src/disks/45h/bin_/debug deleted file mode 100644 index a6935aa..0000000 --- a/src/disks/45h/bin_/debug +++ /dev/null @@ -1,17 +0,0 @@ -local args={...} -local term=component.getFirst("screen") -local hpv=require("hypervisor") -local fs=require("filesystem") -if not (fs.exists("/bin/"..args[1]) and (not fs.isDir("/bin/"..args[1]))) then error("not a file") end -local handle = hpv.createProcessFromFile("/bin/"..args[1], args[1], table.unpack(args, 2)) -local pid=handle.getID() -local debugger=hpv.attachDebugger(handle) -debugger.addEvent("threadReturn", function(...) - term.print("threadReturn", ...) -end) -debugger.addEvent("threadError", function(...) - term.print("threadError", ...) -end) -while hpv.isrunning(pid) do - sleep(0.5) -end \ No newline at end of file diff --git a/src/disks/45h/bin_/ls b/src/disks/45h/bin_/ls deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/bin_/neofetch b/src/disks/45h/bin_/neofetch deleted file mode 100644 index ebba46e..0000000 --- a/src/disks/45h/bin_/neofetch +++ /dev/null @@ -1,24 +0,0 @@ -local term=component.getFirst("screen") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | root@hyperion ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ------------- ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | OS: Hyperion AC ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | Host: $Computer_id ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | Kernel: Hyprkrnl 1.0.0 ") -term.print("⠀⢷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡞⠀ | Uptime: 2:00 ") -term.print("⠀⠈⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⠁⠀ | Packages: 204 ") -term.print("⠀⠀⠘⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⠃⠀⠀ | Shell: DoomieShell ") -term.print("⠀⠀⠀⢹⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⡏⠀⠀⠀ | Resolution: $monitor_size ") -term.print("⠀⠀⠀⠀⢻⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⡟⠀⠀⠀⠀ | DE: ComputeX ") -term.print("⠀⠀⠀⠀⠈⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀ | WM: HWMS ") -term.print("⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀ | WM Theme: Standard dark ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣦⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⣠⣿⣿⣿⣿⡿⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀ | Theme: Standard dark ") -term.print("⠀⠀⠀⠀⠀⠀⠀⢠⣀⠀⠀⠈⠛⢿⣿⣿⣷⣄⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⣠⣾⣿⣿⡿⠛⠁⠀⠀⣀⡄⠀⠀⠀⠀⠀⠀⠀ | Icons: Standard ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣶⣤⣀⠀⠈⠛⢿⣿⠀⠀⣿⣿⣿⣿⣿⣿⠀⠀⣿⡿⠛⠁⠀⣀⣤⣶⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀ | Terminal: Goterm ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣶⡄⢸⣿⠀⠀⠸⣿⣿⣿⣿⡏⠀⠀⣿⡇⢠⣶⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⠿⠿⠿⠟⠛⠃⢸⣿⠀⠀⠀⠹⣿⣿⡟⠀⠀⠀⣿⡇⠘⠛⠻⠿⠿⠿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⡄⢸⣿⡀⠀⠀⠀⢻⡿⠁⠀⠀⢀⣿⡇⢠⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⠇⠘⢿⣿⣦⡀⠀⠀⠁⠀⢀⣴⣿⡿⠃⠸⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡿⠋⠀⠀⠀⠀⠙⣿⣿⣦⡀⢀⣴⣿⡿⠋⠀⠀⠀⠈⠙⠿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") -term.print("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ | ") \ No newline at end of file diff --git a/src/disks/45h/bin_/pge b/src/disks/45h/bin_/pge deleted file mode 100644 index d791837..0000000 --- a/src/disks/45h/bin_/pge +++ /dev/null @@ -1,13 +0,0 @@ -local function func(tble,space) - space=space or "" - for i,v in pairs(tble) do - print(space..tostring(i).." | "..tostring(v)) - if type(v) == "table" then - if i=="_G" then else - func(v,space.." ") - end - end - end -end - -func(_G) \ No newline at end of file diff --git a/src/disks/45h/bin_/reboot b/src/disks/45h/bin_/reboot deleted file mode 100644 index f53ddf4..0000000 --- a/src/disks/45h/bin_/reboot +++ /dev/null @@ -1,2 +0,0 @@ -local computer=component.getFirst("computer") -computer.reboot() \ No newline at end of file diff --git a/src/disks/45h/bin_/shell b/src/disks/45h/bin_/shell deleted file mode 100644 index 8d3ec40..0000000 --- a/src/disks/45h/bin_/shell +++ /dev/null @@ -1,52 +0,0 @@ -local stringBuffer="" -local hpv = require("hypervisor") -local fs = require("filesystem") -local term=component.getFirst("screen") -local captureInput=true -local exit=false -local function printPrefix() - term.printInline("root@testharness:/& ") -end - -local function tokenize(str) - return string.split(str, " ") -end - -hpv.addEvent("keyTyped",function(...) - if not captureInput then return end - local char=({...})[1] - if char == "\n" then - captureInput=false - term.print("") - elseif char == "\b" then - if #stringBuffer > 0 then - stringBuffer=stringBuffer:sub(1,#stringBuffer-1) - term.printInline(char) - end - else - stringBuffer=stringBuffer..char - term.printInline(char) - end -end) - -printPrefix() -while not exit do - while captureInput do - sleep(1) - end - local token = tokenize(stringBuffer) - if token[1] == "exit" then - exit=true - elseif fs.exists("/bin/"..token[1]) and (not fs.isDir("/bin/"..token[1])) then - local handle = hpv.createProcessFromFile("/bin/"..token[1], token[1], table.unpack(token, 2)) - local pid=handle.getID() - while hpv.isrunning(pid) do - sleep(0.5) - end - else - term.print("Command not recognized") - end - stringBuffer="" - printPrefix() - captureInput=true -end \ No newline at end of file diff --git a/src/disks/45h/bin_/t b/src/disks/45h/bin_/t deleted file mode 100644 index ed38162..0000000 --- a/src/disks/45h/bin_/t +++ /dev/null @@ -1,2 +0,0 @@ -local print=component.getFirst("screen").print -print("test") \ No newline at end of file diff --git a/src/disks/45h/bin_/top b/src/disks/45h/bin_/top deleted file mode 100644 index 84d4a6c..0000000 --- a/src/disks/45h/bin_/top +++ /dev/null @@ -1,23 +0,0 @@ -local hpv=require("hypervisor") -local term=component.getFirst("screen") - -term.clear() -local function m(str, m) - if #str>m then - return str:sub(1,m-1).."- " - else - while #str~=m do - str=str.." " - end - return str.." " - end -end - -for i in hpv.listProc() do - term.print(m(i.name, 15)..m(i.status, 7)..m(i.pid, 4)) - for _,v in ipairs(i.threads) do - if v.name~="main" then - term.print(" "..m(v.name, 12)..m(v.status, 7)) - end - end -end \ No newline at end of file diff --git a/src/disks/45h/bin_/unitest b/src/disks/45h/bin_/unitest deleted file mode 100644 index ec29501..0000000 --- a/src/disks/45h/bin_/unitest +++ /dev/null @@ -1,19 +0,0 @@ -local errors={} -local function tables_equal(t1, t2) - if #t1 ~= #t2 then return false end - for i = 1, #t1 do - if t1[i] ~= t2[i] then return false end - end - return true -end - -local function run_test(name, test_func) - local status, err = pcall(test_func) - if status then - print("[PASS] " .. name) - else - print("[FAIL] " .. name .. ": " .. err) - errors[name]=err - end -end - diff --git a/src/disks/45h/boot/Hyprkrnl.sys b/src/disks/45h/boot/Hyprkrnl.sys deleted file mode 100644 index 64afe63..0000000 --- a/src/disks/45h/boot/Hyprkrnl.sys +++ /dev/null @@ -1,215 +0,0 @@ -local function rand() - if math.random(0,1)==0 then return true else return false end -end -function coroutine.resumeWithTimeout(CORO, TIME, ...) - return rand(), coroutine.resume(CORO, ...) -end - --- Copyright (C) 2025 ASTRONAND --- Get boot arguments -local bootArgs=({...})[1] -local bootDrive=bootArgs.bootDrive -local LOG_TEXT="" -local log={} -local term -local bootData=load("return "..(bootDrive:open("var/log/kernel/bootData").read() or "{}"))() -local computer=component.getFirst("computer") -local startup=true -local osleep=sleep -local oldYield=coroutine.yield - -function coroutine.yield(...) - if not startup then - if coroutine.isyieldable(coroutine.running()) then - oldYield(...) - end - end -end - --- Find terminal(s) -local terminals={} -for i,v in component.list() do - if i == "screen" then - terminals[#terminals+1] = v - end -end -term={ - print=function(...) - for _,v in ipairs(terminals) do - v.print(...) - end - end, - printInline=function(...) - for _,v in ipairs(terminals) do - v.printInline(...) - end - end, - clear=function(...) - for _,v in ipairs(terminals) do - v.clear(...) - end - end -} - -term.print("Welcome to Hyperion OS") --- Difine logging lib -local function getPName(func) - if type(func) == "function" then - getPName=func - end - return "Hyprkrnl" -end - -function log.log(text) - if startup then term.print("[ OK ] "..getPName()..": "..text) end - LOG_TEXT=LOG_TEXT.."[ OK ] "..getPName()..": "..text.."\n" -end - -function log.error(text) - if startup then term.print("[FAILED] "..getPName()..": "..text) end - LOG_TEXT=LOG_TEXT.."[FAILED] "..getPName()..": "..text.."\n" -end - -function log.warn(text) - if startup then term.print("[ WARN ] "..getPName()..": "..text) end - LOG_TEXT=LOG_TEXT.."[ WARN ] "..getPName()..": "..text.."\n" -end - -function log.raw(text) - if startup then term.print(" "..getPName()..": "..text) end - LOG_TEXT=LOG_TEXT.." "..getPName()..": "..text.."\n" -end - -function log.get() - return LOG_TEXT -end - -local function t2t(table) - local output = "{" - for i,v in pairs(table) do - local coma=true - if type(i) == "string" then - output=output.."[\""..i.."\"]=" - end - if type(v) == "table" then - if v == table then - output=string.sub(output,1,#output-(#i+1)) - coma=false - else - output=output..t2t(v) - end - elseif type(v) == "string" then - output=output.."[=["..v.."]=]" - elseif type(v) == "number" then - output=output..tostring(v) - elseif type(v) == "function" then - output=string.sub(output,1,#output-(#i+1)) - coma=false - end - if coma then - output=output.."," - end - end - if #table>0 or string.sub(output,#output,#output) == "," then - output=string.sub(output,1,#output-1) - end - output=output.."}" - return output -end - --- My favorite function -local function PANIC(err,lvl) - term.clear() - term.print(LOG_TEXT) - term.printInline("KERNEL PANIC: "..err) - computer.beep(800,0.2) - osleep(0.02) - if err==bootData.prevError then - bootData.errorCount=bootData.errorCount+1 - else - bootData.prevError=err - bootData.errorCount=0 - end - bootDrive:open("var/log/kernel/bootData").write(t2t(bootData)) - if bootData.errorCount < 4 then - term.print("") - term.print("Atempting reboot...") - osleep(0.5) - computer.reboot() - elseif bootData.errorCount > 3 then - term.print("") - term.print("boot determined to be unrecoverable...") - osleep(0.5) - computer.shutdown() - end - while true do - - end -end - -local function runAsKernel(path, args) - local ok,err,extra = pcall(load(bootDrive:open(path):read()), args) - if not ok then - PANIC(path.." failed to load/execute err:\n"..(err or "")) - end - return err,extra -end - --- Add libray modifications+ -for _,v in ipairs(bootDrive:list("/sys/kernel/glib")) do - log.raw("running "..v) - runAsKernel("/sys/kernel/glib/"..v) - log.log("Loaded "..v) -end -log.log("Finished loading global librarys") -local sudoMaster={} -local auth=runAsKernel("sys/kernel/userManager.sys",{masterKey=sudoMaster,bootDrive=bootDrive}) -log.log("Created UE Manager") -local fs=runAsKernel("sys/kernel/filesystem.sys",{bootDrive=bootDrive,auth=auth}) -log.log("Initailized filesystem") -local io=runAsKernel("sys/kernel/ioManager.sys",{masterKey=sudoMaster}) -log.log("Started ioManager") -local packages={filesystem=fs, auth=auth, logging=log, term=term} -local req=runAsKernel("sys/modules/require",{filesystem=fs,logging=log, preload=packages}) -log.log("Loaded require") -local setRequire -local requ=req.makeRequire("lib/?;lib/?/init;sys/modules/?;sys/modules/?/init",packages) -_G.require, setRequire = requ.require, requ.load -setRequire("require",req) -log.log("Initailized require") - -local code=fs.open("sys/kernel/hypervisor.sys","xe", _G) - -if not code then - PANIC("System failed to load") -end -local ok, system=pcall(code, {masterKey=sudoMaster, setRequire=setRequire, pname=getPName}) -if not ok then - PANIC("Hypervisor failed to execute ERR:\n"..hypervisor) -end -log.log("Loaded hypervisor") -log.raw("Making kernel process") - -hypervisor(function() - local hpv=require("hypervisor") - local thread=require("thread") - log.log("Created kernel process") - hpv.createProcessFromFile("sys/os/init.lua", "systemd") - thread.create(function() - while true do - local event = {computer.getMachineEvent()} - if event[1] == nil then - coroutine.yield() - else - hpv.triggerEvent("all", event[1], table.unpack(event,2)) - coroutine.yield() - end - end - end, "eventHandler") - - while true do - coroutine.yield() - end -end) - -term.print("Goodbye :)") \ No newline at end of file diff --git a/src/disks/45h/boot/hyprboot.lua b/src/disks/45h/boot/hyprboot.lua deleted file mode 100644 index bb20764..0000000 --- a/src/disks/45h/boot/hyprboot.lua +++ /dev/null @@ -1 +0,0 @@ -if \ No newline at end of file diff --git a/src/disks/45h/etc/ast-ip/config.ini b/src/disks/45h/etc/ast-ip/config.ini deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/etc/fstab b/src/disks/45h/etc/fstab deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/etc/group b/src/disks/45h/etc/group deleted file mode 100644 index 3d470b6..0000000 --- a/src/disks/45h/etc/group +++ /dev/null @@ -1,2 +0,0 @@ -root:0:root -sudo:1:root \ No newline at end of file diff --git a/src/disks/45h/etc/passwd b/src/disks/45h/etc/passwd deleted file mode 100644 index d8f67a8..0000000 --- a/src/disks/45h/etc/passwd +++ /dev/null @@ -1 +0,0 @@ -root:x:0:0::/root:/bin/pshell \ No newline at end of file diff --git a/src/disks/45h/etc/shadow b/src/disks/45h/etc/shadow deleted file mode 100644 index eecc9f9..0000000 --- a/src/disks/45h/etc/shadow +++ /dev/null @@ -1 +0,0 @@ -root:$5$9a7f8e2b4cd01ac18d7cbb4da74f5c1e$53326d6a24ef6a050b5ef88dbbe5906d4afbcf191725f9750e44a818ab22bd62:0 \ No newline at end of file diff --git a/src/disks/45h/etc/spm/repos b/src/disks/45h/etc/spm/repos deleted file mode 100644 index 3a98ae0..0000000 --- a/src/disks/45h/etc/spm/repos +++ /dev/null @@ -1,2 +0,0 @@ -https://git.astronand.dev/Hyperion-OS/packages/raw/branch/main/spm/ -https://git.astronand.dev/Hyperion-OS/packages/raw/branch/main/ac/ diff --git a/src/disks/45h/etc/sudoers b/src/disks/45h/etc/sudoers deleted file mode 100644 index d8649da..0000000 --- a/src/disks/45h/etc/sudoers +++ /dev/null @@ -1 +0,0 @@ -root diff --git a/src/disks/45h/etc/sysinit/system/graphical.target b/src/disks/45h/etc/sysinit/system/graphical.target deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/etc/sysinit/system/halt.target b/src/disks/45h/etc/sysinit/system/halt.target deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/etc/sysinit/system/multi-user.target b/src/disks/45h/etc/sysinit/system/multi-user.target deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/etc/sysinit/system/poweroff.target b/src/disks/45h/etc/sysinit/system/poweroff.target deleted file mode 100644 index f4a4cb1..0000000 --- a/src/disks/45h/etc/sysinit/system/poweroff.target +++ /dev/null @@ -1,5 +0,0 @@ -[Unit] -Description=Shutdown of system -Conflicts=reboot.target halt.target - -[Service] \ No newline at end of file diff --git a/src/disks/45h/etc/sysinit/system/reboot.target b/src/disks/45h/etc/sysinit/system/reboot.target deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/lib/color/init b/src/disks/45h/lib/color/init deleted file mode 100644 index 8fc9447..0000000 --- a/src/disks/45h/lib/color/init +++ /dev/null @@ -1,16 +0,0 @@ -function color.screen8(r, g, b) - -- Ensure input is within valid 0-255 range - r = math.max(0, math.min(255, r)) - g = math.max(0, math.min(255, g)) - b = math.max(0, math.min(255, b)) - - -- Convert 8-bit to reduced bit depth - local r3 = math.floor(r / 32) -- 8-bit to 3-bit - local g3 = math.floor(g / 32) -- 8-bit to 3-bit - local b2 = math.floor(b / 64) -- 8-bit to 2-bit - - -- Pack into a single 8-bit value: RRR GGG BB - local rgb332 = (r3 << 5) | (g3 << 2) | b2 - - return rgb332 -end \ No newline at end of file diff --git a/src/disks/45h/lib/config/ini b/src/disks/45h/lib/config/ini deleted file mode 100644 index f4e45a6..0000000 --- a/src/disks/45h/lib/config/ini +++ /dev/null @@ -1,111 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local ini = {} -local fs=require("filesystem") - -local function trim(s) - local i, j = 1, #s - while i <= j and (s:sub(i,i) == " " or s:sub(i,i) == "\t") do - i = i + 1 - end - while j >= i and (s:sub(j,j) == " " or s:sub(j,j) == "\t") do - j = j - 1 - end - return s:sub(i, j) -end - -local function parse(list) - local lines=function () - local i=0 - return function() - i=i+1 - return list[i] - end - end - local data = {} - local section = data - for line in lines() do - line = trim(line) - - if line ~= "" and line:sub(1,1) ~= ";" and line:sub(1,1) ~= "#" then - if line:sub(1,1) == "[" and line:sub(-1) == "]" then - local secName = trim(line:sub(2, -2)) - if secName ~= "" then - data[secName] = data[secName] or {} - section = data[secName] - end - else - local eq - for i = 1, #line do - if line:sub(i,i) == "=" then - eq = i - break - end - end - if eq then - local key = trim(line:sub(1, eq-1)) - local value = trim(line:sub(eq+1)) - - local lower = value:lower() - if tonumber(value) then - value = tonumber(value) - elseif lower == "true" then - value = true - elseif lower == "false" then - value = false - end - section[key] = value - end - end - end - end - - return data -end - -function ini.read(path) - local file, err = fs.open(path, "r") - if not file then return nil, err end - local list={} - for i in file.lines() do - list[#list+1] = i - end - file.close() - return parse(list) -end - -function ini.get(text) - return parse(string.split(text, "\n")) -end - -local function write(data) - local text="" - for k,v in pairs(data) do - if type(v) ~= "table" then - text=text..k .. " = " .. tostring(v) .. "\n" - end - end - - for sec, tbl in pairs(data) do - if type(tbl) == "table" then - text=text.."\n[" .. sec .. "]\n" - for k,v in pairs(tbl) do - text=text..k .. " = " .. tostring(v) .. "\n" - end - end - end - - return text -end - -function ini.write(path, data) - local file=fs.open(path, "w") - file.write(write(data)) - file.close() - return true -end - -function ini.make(data) - return write(data) -end - -return ini \ No newline at end of file diff --git a/src/disks/45h/lib/consumer b/src/disks/45h/lib/consumer deleted file mode 100644 index 747980b..0000000 --- a/src/disks/45h/lib/consumer +++ /dev/null @@ -1,14 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local lib={} - -function lib.create(def) - local function func(fun) - if type(fun)=="function" then - func=fun - end - return def - end - return func -end - -return lib \ No newline at end of file diff --git a/src/disks/45h/lib/crypto/sha256 b/src/disks/45h/lib/crypto/sha256 deleted file mode 100644 index 3345c35..0000000 --- a/src/disks/45h/lib/crypto/sha256 +++ /dev/null @@ -1,193 +0,0 @@ --- From http://pastebin.com/gsFrNjbt linked from http://www.computercraft.info/forums2/index.php?/topic/8169-sha-256-in-pure-lua/ - --- --- Adaptation of the Secure Hashing Algorithm (SHA-244/256) --- Found Here: http://lua-users.org/wiki/SecureHashAlgorithm --- --- Using an adapted version of the bit library --- Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua --- - -local MOD = 2^32 -local MODM = MOD-1 - -local function memoize(f) - local mt = {} - local t = setmetatable({}, mt) - function mt:__index(k) - local v = f(k) - t[k] = v - return v - end - return t -end - -local function make_bitop_uncached(t, m) - local function bitop(a, b) - local res,p = 0,1 - while a ~= 0 and b ~= 0 do - local am, bm = a % m, b % m - res = res + t[am][bm] * p - a = (a - am) / m - b = (b - bm) / m - p = p*m - end - res = res + (a + b) * p - return res - end - return bitop -end - -local function make_bitop(t) - local op1 = make_bitop_uncached(t,2^1) - local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end) - return make_bitop_uncached(op2, 2 ^ (t.n or 1)) -end - -local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4}) - -local function bxor(a, b, c, ...) - local z = nil - if b then - a = a % MOD - b = b % MOD - z = bxor1(a, b) - if c then z = bxor(z, c, ...) end - return z - elseif a then return a % MOD - else return 0 end -end - -local function band(a, b, c, ...) - local z - if b then - a = a % MOD - b = b % MOD - z = ((a + b) - bxor1(a,b)) / 2 - if c then z = bit32_band(z, c, ...) end - return z - elseif a then return a % MOD - else return MODM end -end - -local function bnot(x) return (-1 - x) % MOD end - -local function rshift1(a, disp) - if disp < 0 then return lshift(a,-disp) end - return math.floor(a % 2 ^ 32 / 2 ^ disp) -end - -local function rshift(x, disp) - if disp > 31 or disp < -31 then return 0 end - return rshift1(x % MOD, disp) -end - -local function lshift(a, disp) - if disp < 0 then return rshift(a,-disp) end - return (a * 2 ^ disp) % 2 ^ 32 -end - -local function rrotate(x, disp) - x = x % MOD - disp = disp % 32 - local low = band(x, 2 ^ disp - 1) - return rshift(x, disp) + lshift(low, 32 - disp) -end - -local k = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, -} - -local function str2hexa(s) - return (string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end)) -end - -local function num2s(l, n) - local s = "" - for i = 1, n do - local rem = l % 256 - s = string.char(rem) .. s - l = (l - rem) / 256 - end - return s -end - -local function s232num(s, i) - local n = 0 - for i = i, i + 3 do n = n*256 + string.byte(s, i) end - return n -end - -local function preproc(msg, len) - local extra = 64 - ((len + 9) % 64) - len = num2s(8 * len, 8) - msg = msg .. "\128" .. string.rep("\0", extra) .. len - assert(#msg % 64 == 0) - return msg -end - -local function initH256(H) - H[1] = 0x6a09e667 - H[2] = 0xbb67ae85 - H[3] = 0x3c6ef372 - H[4] = 0xa54ff53a - H[5] = 0x510e527f - H[6] = 0x9b05688c - H[7] = 0x1f83d9ab - H[8] = 0x5be0cd19 - return H -end - -local function digestblock(msg, i, H) - local w = {} - for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end - for j = 17, 64 do - local v = w[j - 15] - local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3)) - v = w[j - 2] - w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10)) - end - - local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] - for i = 1, 64 do - local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22)) - local maj = bxor(band(a, b), band(a, c), band(b, c)) - local t2 = s0 + maj - local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25)) - local ch = bxor (band(e, f), band(bnot(e), g)) - local t1 = h + s1 + ch + k[i] + w[i] - h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2 - end - - H[1] = band(H[1] + a) - H[2] = band(H[2] + b) - H[3] = band(H[3] + c) - H[4] = band(H[4] + d) - H[5] = band(H[5] + e) - H[6] = band(H[6] + f) - H[7] = band(H[7] + g) - H[8] = band(H[8] + h) -end - -return function(msg) - msg = preproc(msg, #msg) - local H = initH256({}) - for i = 1, #msg, 64 do digestblock(msg, i, H) end - return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) .. - num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4)) -end \ No newline at end of file diff --git a/src/disks/45h/lib/ipc b/src/disks/45h/lib/ipc deleted file mode 100644 index 8f56708..0000000 --- a/src/disks/45h/lib/ipc +++ /dev/null @@ -1,6 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local pipes={} -local ports={} -local sharedObjects={} -local net=require("net") - diff --git a/src/disks/45h/lib/lua/lexer b/src/disks/45h/lib/lua/lexer deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/lib/lua/minify b/src/disks/45h/lib/lua/minify deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/sbin/spm.lua b/src/disks/45h/sbin/spm.lua deleted file mode 100644 index 1be1515..0000000 --- a/src/disks/45h/sbin/spm.lua +++ /dev/null @@ -1,47 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local args = {...} -local os = require("system") -local fs=require("filesystem") -local term = os.getEnvar("term") - -if args[1] == "help" or args[1] == "-h" then - term.print("SPM V1.0.0") - term.print("Usage:") - term.print(" install : searches for package and installs it") - term.print(" add-repo : adds repo to search list appends package to end of URL") - term.print(" download : downloads package from URL") - term.print(" local : downloads package from file") - term.print(" get : executes commands from list") -end - -local function install(package) - -end - -local function addRepo(url) - -end - -local function download(url) - -end - -local function localPackage(dir) - -end - -local function run(command) - local list = string.split(command, " ") - if list[1] == "install" then - install(list[2]) - elseif list[1] == "add-repo" then - - end -end - -if args[1] == "get" then - local list=string.split(fs.readAllText(args[2]), "\n") - for i, v in ipairs(list) do - - end -else run(args) end \ No newline at end of file diff --git a/src/disks/45h/sys/db/os.reg b/src/disks/45h/sys/db/os.reg deleted file mode 100644 index 9e26dfe..0000000 --- a/src/disks/45h/sys/db/os.reg +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/src/disks/45h/sys/drivers/ac.disk.ko b/src/disks/45h/sys/drivers/ac.disk.ko deleted file mode 100644 index 39a2bee..0000000 --- a/src/disks/45h/sys/drivers/ac.disk.ko +++ /dev/null @@ -1,40 +0,0 @@ -local driver = {} - -driver.type = "fs" -driver.name = "Advanced Computers disk driver" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for Advanced Computers disks" -driver.manifest = "ac.disk.ko" - -driver.api = function(component) - return { - readAllText = function(dir) - local drive = component:open(dir) - local file = drive.read() - drive = nil - return file - end, - writeAllText = function(dir, content) - local drive = component:open(dir) - drive.write(content) - drive = nil - end, - appendAllText = function(dir, content) - local drive = component:open(dir) - drive.append(content) - drive = nil - end, - list = function(dir) - return component:list(dir) - end, - mkFile = function(dir) - component:makeFile(dir) - end, - mkDir = function(dir) - component:makeDirectory(dir) - end - } -end - -return driver \ No newline at end of file diff --git a/src/disks/45h/sys/drivers/ac.screen.ko b/src/disks/45h/sys/drivers/ac.screen.ko deleted file mode 100644 index fb28390..0000000 --- a/src/disks/45h/sys/drivers/ac.screen.ko +++ /dev/null @@ -1,26 +0,0 @@ -local driver = {} - -driver.type = "terminal" -driver.name = "Advanced Computers screen driver" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for Advanced Computers screens" -driver.manifest = "ac.screen.ko" - -driver.api=function(component) - return { - write=function(...) - component.printInline(...) - end, - print=function(...) - component.print(...) - end, - printInline=function(...) - component.printInline(...) - end, - clear=function(...) - component.clear() - end - } -end -return driver \ No newline at end of file diff --git a/src/disks/45h/sys/drivers/ac.udisk.ko b/src/disks/45h/sys/drivers/ac.udisk.ko deleted file mode 100644 index 726d7c7..0000000 --- a/src/disks/45h/sys/drivers/ac.udisk.ko +++ /dev/null @@ -1,16 +0,0 @@ -local driver = {} - -driver.type = "ufs" -driver.name = "Advanced Computers unmanaged disk driver" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for Advanced Computers unmanaged disks" -driver.manifest = "ac.udisk.ko" - -driver.api = function(component) - return { - - } -end - -return driver \ No newline at end of file diff --git a/src/disks/45h/sys/drivers/ac.wlan.ko b/src/disks/45h/sys/drivers/ac.wlan.ko deleted file mode 100644 index f101bf3..0000000 --- a/src/disks/45h/sys/drivers/ac.wlan.ko +++ /dev/null @@ -1,8 +0,0 @@ -local driver = {} - -driver.type = "wlan" -driver.name = "Advanced Computers http driver" -driver.version = "1.0.0" -driver.apiVersion = 1 -driver.description = "Driver for Advanced Computers http" -driver.manifest = "ac.wlan.ko" \ No newline at end of file diff --git a/src/disks/45h/sys/kernel/filesystem.sys b/src/disks/45h/sys/kernel/filesystem.sys deleted file mode 100644 index 549b882..0000000 --- a/src/disks/45h/sys/kernel/filesystem.sys +++ /dev/null @@ -1,245 +0,0 @@ --- Copyright (C) 2025 ASTRONAND --- File open modes --- M | H | D --- rc | r | Read and close --- r | r | Read --- w | w | Write --- o | w | Overite file --- om | m | Overite and modify --- rw | m | Read and write --- x | f | get function - -local args=({...})[1] -local fs={} -local disks={} -local mounts={} -local bootDrive=args.bootDrive -local auth=args.auth -local log=args.logging - -for t, o in component.list() do - if t=="disk" then - if o.id==bootDrive.id then - else disks[o.id]=o end - end -end - -local function resolve(path) - if string.sub(path,1,1)~="/" then - path="/"..path - end - local drive=bootDrive - for i,v in pairs(mounts) do - if string.hasPrefix(path,v) then - drive=disks[i] - path=string.getSuffix(path,v) - break - end - end - return drive, path -end - -local function checkPerms(path, mode) - -end - -local function getHandle(backing,typ,clear) - local ret={} - local close=false - ret.close=function() - close=true - end - if typ=="r" then - ret.read=function() - if close then return "Handle closed" end - return backing.read() - end - ret.lines=function() - if close then error() end - local lines=string.split(backing.read(), "\n") - local i=0 - return function() - i=i+1 - return lines[i] - end - end - elseif typ=="w" then - ret.write=function(data) - if close then return "Handle closed" end - backing.append(data) - end - elseif typ=="m" then - ret.read=function() - if close then return "Handle closed" end - return backing.read() - end - ret.lines=function() - if close then error() end - local lines=string.split(backing.read(), "\n") - local i=0 - return function() - i=i+1 - return lines[i] - end - end - ret.write=function(data) - if close then return "Handle closed" end - backing.append(data) - end - end - if clear then - ret.clear=function() - if close then return "Handle closed" end - backing.write() - end - end - return ret -end - -local function open(path, mode, arg, pc) - if pc then - checkPerms(path, mode) - end - local drive, newPath = resolve(path) - if drive:directoryExists(newPath) then error("Cannot open directory") end - if not drive:fileExists(newPath) then error("File does not exist") end - local backing=drive:open(newPath) - if mode=="rc" then - local file=getHandle(backing,"r") - local text=file.read() - file.close() - return text - elseif mode=="r" then - return getHandle(backing,"r") - elseif mode=="w" then - return getHandle(backing,"w") - elseif mode=="o" then - local file=getHandle(backing,"w",true) - file.clear() - file.clear=nil - return file - elseif mode=="om" then - local file=getHandle(backing,"m",true) - file.clear() - file.clear=nil - return file - elseif mode=="rw" then - return getHandle(backing,"m") - elseif mode=="x" then - local file=getHandle(backing,"r") - local text=file.read() - file.close() - return load(text, path, nil, table.deepcopy(_G)) - elseif mode=="xe" then - local file=getHandle(backing,"r") - local text=file.read() - file.close() - return load(text, path, nil, arg) - else - error("Invailid mode") - end -end - -function fs.open(path, mode, arg) - return open(path, mode, arg, true) -end - -function fs.copy(orig, dest) - local destFile = fs.open(dest,"o") - local origFile = fs.open(orig, "rc") - destFile.write(origFile) - destFile.close() -end - -function fs.move(orig, dest) - local destFile = fs.open(dest,"o") - local origFile = fs.open(orig, "rc") - destFile.write(origFile) - destFile.close() - fs.delete(orig) -end - --- This fixes the weirdest bug ever -local isDir = function(path, pc) - if pc then checkPerms(path, "r") end - local drive, newPath = resolve(path) - return drive:directoryExists(newPath) -end - -local exists = function(path, pc) - if pc then checkPerms(path, "r") end - local drive, newPath = resolve(path) - return ((drive:directoryExists(newPath)) or (drive:fileExists(newPath))) -end - -local delete = function(path, pc) - if pc then checkPerms(path, "w") end - local drive, newPath = resolve(path) - return drive:delete(newPath) -end - -local list = function(path, pc) - if pc then checkPerms(path, "w") end - local drive, newPath = resolve(path) - return drive:list(newPath) -end - -function fs.list(path) - return list(path, true) -end - -function fs.isDir(path) - return isDir(path, true) -end - -function fs.exists(path) - return exists(path, true) -end - -function fs.delete(path) - return delete(path, true) -end - -function fs.getSudo(key) - if auth.sudo.isAproved(key) then - return { - createVirtDisk=function(virtualDiskName,virtualDiskObj) - disks[virtualDiskName]=virtualDiskObj - log.log("Created VirtIO disk named "..virtualDiskName) - end, - mount=function(hardwareDir,path) - mounts[hardwareDir]=path - log.log("Mounted disk ") - end, - unmount=function(hardwareDir) - mounts[hardwareDir]=nil - end, - eject=function(hardwareDir) - disks[hardwareDir]=nil - end, - sfs={ - open=function(path, mode, arg) - return open(path, mode, arg) - end, - delete=function(path) - return delete(path) - end, - copy=fs.copy, - move=fs.move, - exists=function(path) - return exists(path) - end, - isDir=function(path) - return isDir(path) - end, - list=function(path) - return list(path) - end - } - } - else - error("sudo request denied") - end -end - -return fs \ No newline at end of file diff --git a/src/disks/45h/sys/kernel/glib/component.lua b/src/disks/45h/sys/kernel/glib/component.lua deleted file mode 100644 index 75a7a58..0000000 --- a/src/disks/45h/sys/kernel/glib/component.lua +++ /dev/null @@ -1,50 +0,0 @@ --- Copyright (C) 2025 ASTRONAND ---local oldComponent = component ---_G.component={} ---local components={} ---local all={} ---local blacklisted={} --- ---function table.contains(tabl, query) --- for i,v in ipairs(tabl) do --- if v==query then --- return true --- end --- end --- return false ---end --- ---for i,v in oldComponent.list() do --- if not components[i] then --- components[i]={} --- end --- components[i][#components[i]+1]={typ=i,obj=v} --- all[#all+1]={typ=i,obj=v} ---end --- ---function component.list(filter) --- filter=filter or "all" --- local filtered --- if filter=="all" then --- filtered=all --- else --- filtered=components[filter] --- end --- local i=0 --- return function() --- while i<#filtered do --- i=i+1 --- if not table.contains(blacklisted, v.typ) then --- return v.typ, v.obj --- end --- end --- end ---end --- ---function component.getSudo(key) --- if key==masterKey then --- return oldComponent --- end ---end --- --- \ No newline at end of file diff --git a/src/disks/45h/sys/kernel/glib/string.lua b/src/disks/45h/sys/kernel/glib/string.lua deleted file mode 100644 index 3c34a99..0000000 --- a/src/disks/45h/sys/kernel/glib/string.lua +++ /dev/null @@ -1,53 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -function string.hasSuffix(str, suffix) - return string.sub(str, #suffix+1) == suffix -end - -function string.hasPrefix(str, prefix) - return string.sub(str, 1, #prefix) == prefix -end - -function string.getSuffix(str, prefix) - return string.sub(str, #prefix+1) -end - -function string.getPrefix(str, suffix) - return string.sub(str, 1, #suffix) -end - -function string.join(delim, ...) - return table.concat(table.pack(...), delim) -end - -function string.split(str, delim, maxResultCountOrNil) - assert(#delim == 1, "only delim len 1 supported for now") - maxResultCountOrNil = (maxResultCountOrNil or 0)-1 - local rv = {} - local buf = "" - for i = 1, #str do - local c = string.sub(str,i,i) - if #rv ~= maxResultCountOrNil and c == delim then - table.insert(rv, buf) - buf = "" - else - buf = buf..c - end - end - table.insert(rv, buf) - return rv -end - -function string.replace(str, search, replacement) - local rv = "" - local consumedLen = 1 - local i = 1 - while i<#str do - if string.sub(str, i, i+#search-1) == search then - rv = rv .. string.sub(str, consumedLen, i-1) .. replacement - i=i+#search - consumedLen = i - end - i=i+1 - end - return rv .. string.sub(str, consumedLen) -end \ No newline at end of file diff --git a/src/disks/45h/sys/kernel/glib/table.lua b/src/disks/45h/sys/kernel/glib/table.lua deleted file mode 100644 index 4f1a4ad..0000000 --- a/src/disks/45h/sys/kernel/glib/table.lua +++ /dev/null @@ -1,39 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -function table.deepcopy(orig, copies) - copies = copies or {} - - if type(orig) ~= 'table' then - return orig - elseif copies[orig] then - return copies[orig] - end - - local copy = {} - copies[orig] = copy - - for k, v in next, orig, nil do - local copied_key = table.deepcopy(k, copies) - local copied_val = table.deepcopy(v, copies) - copy[copied_key] = copied_val - end - - return copy -end - -function table.hasKey(tabl, query) - for i,v in pairs(tabl) do - if i==query then - return true - end - end - return false -end - -function table.hasVal(tabl, query) - for i,v in pairs(tabl) do - if v==query then - return true - end - end - return false -end \ No newline at end of file diff --git a/src/disks/45h/sys/kernel/ioManager.sys b/src/disks/45h/sys/kernel/ioManager.sys deleted file mode 100644 index 54fd9b3..0000000 --- a/src/disks/45h/sys/kernel/ioManager.sys +++ /dev/null @@ -1 +0,0 @@ --- Copyright (C) 2025 ASTRONAND diff --git a/src/disks/45h/sys/kernel/userManager.sys b/src/disks/45h/sys/kernel/userManager.sys deleted file mode 100644 index 6fcdc03..0000000 --- a/src/disks/45h/sys/kernel/userManager.sys +++ /dev/null @@ -1,29 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local args=({...})[1] -local masterKey=args.masterKey -local disk=args.bootDrive -local auth={} -auth.sudo={} -local keys={} -local ok,sha256=pcall(load(disk:open("/lib/crypto/sha256").read())) -if not ok then - error("sha256 failed to load") -end - -local users={} -local file=disk:open("/etc/passwd").read() --- for p,i in ipairs(string.split(file,"\n")) do --- for t,v in ipairs(string.split(v,":")) do --- users[p][t]=v --- end --- end - -function auth.sudo.isAproved(key) - return true -end - -function auth.sudo.elevatePerms(password) - -end - -return auth \ No newline at end of file diff --git a/src/disks/45h/sys/modules/require b/src/disks/45h/sys/modules/require deleted file mode 100644 index 87932f9..0000000 --- a/src/disks/45h/sys/modules/require +++ /dev/null @@ -1,86 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local args=({...})[1] -local log=args.logging -local fs=args.filesystem -local loaded=args.preload or {} -local function dot_to_slash(name) - local parts = {} - local start = 1 - for i = 1, #name do - if name:sub(i, i) == "." then - table.insert(parts, name:sub(start, i - 1)) - start = i + 1 - end - end - table.insert(parts, name:sub(start)) - return table.concat(parts, "/") -end - -local function replace_question_mark(path, name_path) - local result = {} - local replaced = false - for i = 1, #path do - local ch = path:sub(i, i) - if ch == "?" and not replaced then - table.insert(result, name_path) - replaced = true - else - table.insert(result, ch) - end - end - return table.concat(result) -end - -local function search_module(name,search_paths) - local name_path = dot_to_slash(name) - - for _, path in ipairs(search_paths) do - local filename = replace_question_mark(path, name_path) - if fs.exists(filename) and not fs.isDir(filename) then - local code=fs.open(filename,"x") - if code then - return code, filename - end - end - end - - return nil, "module not found: " .. name -end - -return { - makeRequire=function(search_paths) - local config=string.split(search_paths,";") - return { - require=function(query) - if loaded[query] then return table.deepcopy(loaded[query]) end - local code,file=search_module(query,config) - if code==nil then - error(file) - end - local ok,_,lib=pcall(pcall,code) - if ok then - log.log("Added: \""..query.."\" to require registry.") - loaded[query]=lib - return table.deepcopy(lib), file - else - log.warn("ERR in module "..file) - return nil, "ERR in module "..file.."." - end - end, - load=function(query, lib) - loaded[query]=lib - end - } - end, - list=function() - local list={} - for i,v in pairs(loaded) do - list[#list+1]={i=i,v=v} - end - local i=0 - while i<#list do - i=i+1 - return list[i].i, list[i].v - end - end -} \ No newline at end of file diff --git a/src/disks/45h/sys/system/sysinit.sys b/src/disks/45h/sys/system/sysinit.sys deleted file mode 100644 index e69de29..0000000 diff --git a/src/disks/45h/sys/system/system.sys b/src/disks/45h/sys/system/system.sys deleted file mode 100644 index 18f5e34..0000000 --- a/src/disks/45h/sys/system/system.sys +++ /dev/null @@ -1,152 +0,0 @@ --- Copyright (C) 2025 ASTRONAND -local args=({...})[1] -local fs=require("filesystem") ---local sfs=fs.getSudo(args.masterKey) -local auth=require("auth") -local system={} -local uuid=-1 -local computer=component.getFirst("computer") -local time=computer.time() -local tasks={} -local currentTask={} - -system.version="1.0.0" -system.name="HyperionOS" --- Task status --- "R" | Runnable/Running --- "S" | Sleeping/Waiting --- "P" | Stopped/Paused --- "Z" | Exited/Zombie --- "E" | Errored --- "T" | Terminate --- "X" | Marked for GC - -local function UUID() - uuid=uuid+1 - return tostring(uuid) -end - -function system.createTaskFromFunc(func, name, ...) - local id=UUID() - local fargs={...} - local task={} - local handle={} - task={ - sleep=0, - state="N", - thread=coroutine.create(function() - local ret={pcall(func, table.unpack(fargs))} - local ok, tret = ret[1], {table.unpack(ret,2)} - if not ok then - task.state="E" - task.exit_state=tret[1] - task.exit_code=1 - else - if #tret>0 then - task.state="Z" - task.exit_state=tret - task.exit_code=0 - else - task.state="X" - end - end - end), - PID=id, - name=name, - comm=string.sub(name, 1, 32), - parent=currentTask, - chlidren={}, - sibling=currentTask.chlidren, - files={}, - nvcsw=0, - nivcsw=0, - handle=handle, - start_time=computer.time() - } - tasks[id]=task - local close=false - function handle.exists() - return not close - end - function handle.kill() - close=true - task.state="T" - end - function handle.pause() - if close then return "Handle closed" end - if task.state=="R" then - task.state="P" - return true - else - return false - end - end - function handle.resume() - if close then return "Handle closed" end - if task.state=="P" then - task.state="R" - return true - else - return false - end - end - function handle.getPID() - if close then return "Handle closed" end - return task.PID - end - function handle.getParent() - if close then return "Handle closed" end - return task.parent.PID - end - function handle.getChildren() - if close then return "Handle closed" end - local ret = {} - for i,v in pairs(task.chlidren) do - ret[#ret+1] = v.PID - end - return ret - end - function handle.getState() - if close then return "Handle closed" end - return task.state - end - return handle -end - -function system.createTaskFromFile(path, name, ...) - local file = fs.open(path, "x") - return system.createTaskFromFunc(file, name, ...) -end - -function system.getTaskInfo(pid) - local task = tasks[pid] - if task == nil then return "No task with id "..pid end - return { - PID=task.PID, - parent=task.parent.PID, - sibling=(function() - local ret = {} - for i,v in pairs(task.sibling) do - ret[#ret+1] = i - end - return ret - end)(), - chlidren=(function() - local ret = {} - for i,v in pairs(task.chlidren) do - ret[#ret+1] = i - end - return ret - end)(), - name=task.name, - state=task.state, - nvcsw=task.nvcsw, - nivcsw=task.nivcsw, - start_time=task.start_time - } -end - -function system.getCurrentTask() - return system.getTaskInfo(currentTask.PID) -end - diff --git a/src/disks/45h/var/log/kernel/bootData b/src/disks/45h/var/log/kernel/bootData deleted file mode 100644 index 4858067..0000000 --- a/src/disks/45h/var/log/kernel/bootData +++ /dev/null @@ -1 +0,0 @@ -{["errorCount"]=4,["prevError"]=[=[random panic for testing purposes]=],["mode"]=[=["CLI"]=]} \ No newline at end of file diff --git a/src/disks/4f/bios.lua b/src/disks/4f/bios.lua deleted file mode 100644 index 1c17955..0000000 --- a/src/disks/4f/bios.lua +++ /dev/null @@ -1,190 +0,0 @@ -local computer = component.getFirst("computer") -local screen=component.getFirst("screen") -if not screen then - local function e(...)end - screen = { - print=e, - printInline=e, - clear=e - } -end - -local ok,err = xpcall(function() - -- Init components - _G._DEVELOPMENT=true - _G.component=component - - local printed="" - local print=function(text) - printed=printed..text.."\n" - screen.print(text) - end - - -- Get CFG - local biosCfg = {} - local i=1 - while i<=256 do - biosCfg[i]=computer.getData(i) or "" - i=i+1 - end - computer.beep(800,0.2) - -- Difine functions - local function copy(tabl) - local out = {} - for i,v in pairs(tabl) do - local t=type(v) - if t=="table" then - if i == "_G" then - out._G=out - else - out[i]=copy(v) - end - else - out[i]=v - end - end - return out - end - - local function save(table) - while i<=256 do - computer.setData(i, table[i] or nil) - i=i+1 - end - end - - local function hasKey(tabl, query) - for i,v in pairs(tabl) do - if i==query then - return true - end - end - return false - end - - -- Start boot seq - local disks={} - for i,v in component.list() do - if i=="disk" then - disks[v.id]=v - if v.type=="udd" then - v:writeBytes(0, "HDS") -- "HDS" - local tmp = v:readBytes(0,512) -- Just to make sure it writes the data - print(tmp) - end - end - end - - local idx = 1 - local bootOption=1 - while true do - if biosCfg[idx]=="$EOF" then break end - print("Atempting boot option "..tostring(bootOption).." labled \""..biosCfg[idx].."\".") - bootOption=bootOption+1 - local drive={} - idx=idx+1 - if not hasKey(disks,biosCfg[idx]) then - print("└─ Drive not found.") - print(" ") - idx=idx+3 - goto invalid_boot - else - drive=disks[biosCfg[idx]] - print("├─ Drive found with id of \""..drive.id.."\"") - end - idx=idx+1 - local path - local code - if drive.type=="udd" then - print("├─ Drive is Unmanaged, looking for MBR...") - sleep(0.02) - print("├─ Reading MBR...") - sleep(0.4) - print("├─ MBR found, compiling bootloader...") - local tmp = drive.readBytes(0,512) - code = table.concat(tmp) - else - if not drive:fileExists(biosCfg[idx]) then - print("└─ Path not found.") - print(" ") - idx=idx+2 - goto invalid_boot - else - print("├─ Kernel exists at path \""..biosCfg[idx].."\"") - path=biosCfg[idx] - end - code = drive:open(path).read() - end - idx=idx+1 - local _VG=copy(_G) - print("├─ Created virtual ENV.") - local _,func = pcall(load,code,drive.id.." | "..path,nil,_VG) - if not func then - print("└─ Compilation failure.") - print(" ") - idx=idx+1 - goto invalid_boot - else - print("├─ Executing.") - end - local cmd=biosCfg[idx] or "" - idx=idx+1 - local biosData = {} - biosData.bootDrive=drive - biosData.term=screen - screen.clear() - local ok, err = xpcall(func, debug.traceback, biosData, cmd) - screen.clear() - screen.print(printed) - if not ok then - print("└─ OS exited with error: "..err) - print(" ") - else - print("└─ OS exited.") - print(" ") - end - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - break - end - end - sleep(0.02) - end - ::invalid_boot:: - end - computer.beep(400,0.4) - print("No boot options available") - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end, debug.traceback) -if not ok then - screen.clear() - screen.print("BIOS PANIC: "..err) - computer.beep(800,0.2) - sleep(0.02) - computer.beep(800,0.2) - sleep(0.02) - computer.beep(800,0.2) - sleep(0.02) - screen.print("Press enter to continue...") - while true do - local event = {computer.getMachineEvent()} - if event[1] == "keyTyped" then - if event[3] == "\n" then - computer.shutdown() - end - end - sleep(0.02) - end -end \ No newline at end of file diff --git a/src/disks/4f/boot.lua b/src/disks/4f/boot.lua deleted file mode 100644 index 3801e70..0000000 --- a/src/disks/4f/boot.lua +++ /dev/null @@ -1,2 +0,0 @@ -local disk = (...)[1] -- hopefully us -component.getFirst("bios").setData(disk:open("bios.lua").read()) \ No newline at end of file diff --git a/src/disks/4f/note.txt b/src/disks/4f/note.txt deleted file mode 100644 index e83b6ae..0000000 --- a/src/disks/4f/note.txt +++ /dev/null @@ -1 +0,0 @@ -this is AC disk \ No newline at end of file diff --git a/src/disks/4f/nvram.dat b/src/disks/4f/nvram.dat deleted file mode 100644 index 358185e..0000000 --- a/src/disks/4f/nvram.dat +++ /dev/null @@ -1,254 +0,0 @@ -HyperionOS -disk_1 -/boot/Hyprkrnl.sys - -HyperionOS Dev -disk_2 -/boot/Hyprkrnl.sys - -$EOF - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/disks/56u b/src/disks/56u deleted file mode 100644 index 0c0b001..0000000 Binary files a/src/disks/56u and /dev/null differ