Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local magic = 0x5f7d
- local magic_rev = 0x7d5f
- local header_fmt = "I2I2I2I2I2I6I6"
- local en = string.unpack("=I2", string.char(0x7d, 0x5f)) == magic -- true = LE, false = BE
- local function get_end(e)
- return (e and "<") or ">"
- end
- local function read_header(dat)
- local e = get_end(en)
- local m = string.unpack(e.."I2", dat)
- if m ~= magic and m ~= magic_rev then return nil, "bad magic" end
- if m ~= magic then
- e = get_end(not en)
- end
- local ent = {}
- ent.magic, ent.namesize, ent.mode, ent.uid, ent.gid, ent.filesize, ent.mtime = string.unpack(e..header_fmt, dat)
- return ent
- end
- local arc = {}
- function arc:get(path)
- if path:sub(1,1) ~= "/" then path = "/"..path end
- for i=1, #self.tbl do
- if (self.tbl[i].name == path and self.tbl[i].mode & 32768 > 0) then
- self.seek(self.tbl[i].pos-self.seek(0))
- return self.read(self.tbl[i].filesize), self.tbl[i]
- end
- end
- return nil, "file not found"
- end
- function arc:exists(path)
- if path:sub(1,1) ~= "/" then path = "/"..path end
- for i=1, #self.tbl do
- if (self.tbl[i].name == path) then
- return true
- end
- end
- return false
- end
- function arc:list(path)
- if path:sub(#path) ~= "/" then path = path .. "/" end
- if path:sub(1,1) ~= "/" then path = "/"..path end
- local ent = {}
- for i=1, #self.tbl do
- if (self.tbl[i].name:sub(1, #path) == path and not self.tbl[i].name:find("/", #path+1, false)) then
- ent[#ent+1] = self.tbl[i].name:gsub("^(.*/)", "")
- end
- end
- return ent
- end
- function arc:close()
- self.close()
- end
- local tsar_read = function(read, seek, close)
- local tbl = {}
- local lname = ""
- while lname ~= "TRAILER!!!" do
- local dat = read(22)
- local et = read_header(dat)
- et.name = read(et.namesize)
- et.pos = seek(et.namesize & 1)
- seek(et.filesize + (et.filesize & 1))
- lname = et.name
- if lname ~= "TRAILER!!!" then
- if (et.name:sub(1,1) ~= "/") then
- et.name = "/"..et.name
- end
- tbl[#tbl+1] = et
- end
- end
- return setmetatable({tbl = tbl, read = read, seek = seek, close = close}, {__index=arc})
- end
- --[[----------------------------------------------------------------------------
- LZSS - encoder / decoder
- This is free and unencumbered software released into the public domain.
- Anyone is free to copy, modify, publish, use, compile, sell, or
- distribute this software, either in source code form or as a compiled
- binary, for any purpose, commercial or non-commercial, and by any
- means.
- In jurisdictions that recognize copyright laws, the author or authors
- of this software dedicate any and all copyright interest in the
- software to the public domain. We make this dedication for the benefit
- of the public at large and to the detriment of our heirs and
- successors. We intend this dedication to be an overt act of
- relinquishment in perpetuity of all present and future rights to this
- software under copyright law.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- For more information, please refer to <http://unlicense.org/>
- --]]----------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- local M = {}
- local string, table = string, table
- --------------------------------------------------------------------------------
- local POS_BITS = 12
- local LEN_BITS = 16 - POS_BITS
- local POS_SIZE = 1 << POS_BITS
- local LEN_SIZE = 1 << LEN_BITS
- local LEN_MIN = 3
- --------------------------------------------------------------------------------
- function M.compress(input)
- local offset, output = 1, {}
- local window = ''
- local function search()
- for i = LEN_SIZE + LEN_MIN - 1, LEN_MIN, -1 do
- local str = string.sub(input, offset, offset + i - 1)
- local pos = string.find(window, str, 1, true)
- if pos then
- return pos, str
- end
- end
- end
- while offset <= #input do
- local flags, buffer = 0, {}
- for i = 0, 7 do
- if offset <= #input then
- local pos, str = search()
- if pos and #str >= LEN_MIN then
- local tmp = ((pos - 1) << LEN_BITS) | (#str - LEN_MIN)
- buffer[#buffer + 1] = string.pack('>I2', tmp)
- else
- flags = flags | (1 << i)
- str = string.sub(input, offset, offset)
- buffer[#buffer + 1] = str
- end
- window = string.sub(window .. str, -POS_SIZE)
- offset = offset + #str
- else
- break
- end
- end
- if #buffer > 0 then
- output[#output + 1] = string.char(flags)
- output[#output + 1] = table.concat(buffer)
- end
- end
- return table.concat(output)
- end
- --------------------------------------------------------------------------------
- function M.decompress(input)
- local offset, output = 1, {}
- local window = ''
- while offset <= #input do
- local flags = string.byte(input, offset)
- offset = offset + 1
- for i = 1, 8 do
- local str = nil
- if (flags & 1) ~= 0 then
- if offset <= #input then
- str = string.sub(input, offset, offset)
- offset = offset + 1
- end
- else
- if offset + 1 <= #input then
- local tmp = string.unpack('>I2', input, offset)
- offset = offset + 2
- local pos = (tmp >> LEN_BITS) + 1
- local len = (tmp & (LEN_SIZE - 1)) + LEN_MIN
- str = string.sub(window, pos, pos + len - 1)
- end
- end
- flags = flags >> 1
- if str then
- output[#output + 1] = str
- window = string.sub(window .. str, -POS_SIZE)
- end
- end
- end
- return table.concat(output)
- end
- local function struct(tbl)
- local pat = tbl.endian or "="
- local args = {}
- for i=1, #tbl do
- local a, b = pairs(tbl[i])
- local k, v = a(b)
- args[i] = k
- pat = pat .. v
- end
- return setmetatable({}, {__call=function(_, arg)
- --checkArg(1, arg, "string", "table")
- if (type(arg) == "string") then
- local sval = {string.unpack(pat, arg)}
- local rtn = {}
- for i=1, #args do
- rtn[args[i]] = sval[i]
- end
- return rtn, sval[#sval]
- elseif (type(arg) == "table") then
- local sval = {}
- for i=1, #args do
- sval[i] = arg[args[i]]
- end
- return string.pack(pat, unpack(sval))
- end
- end, __len=function()
- return string.packsize(pat)
- end})
- end
- local velx_spec = struct {
- endian = "<",
- {magic="c5"},
- {fver="B"},
- {compression="B"},
- {lver="B"},
- {os="B"},
- {arctype="c4"},
- {psize="I3"},
- {lsize="I3"},
- {ssize="I3"},
- {rsize="I4"}
- }
- local function load_velx_part(hand, env, name, lib)
- local venv = {_ENV=env}
- setmetatable(venv, {__index=env})
- venv._G = venv
- local dat = hand:read(#velx_spec)
- if (not dat or dat == "") then return nil end
- local header = velx_spec(dat)
- if (header.magic ~= "\27VelX") then
- return nil, "Bad magic."
- end
- if (header.fver ~= 0) then
- return nil, "Only version 0 is supported.", header
- end
- if (header.lver > 0x53) then
- return nil, "Wrong Lua version.", header
- end
- if (header.os & 0x7F ~= 1) then
- return nil, "Wrong OS.", header
- end
- if (header.os & 0x80 ~= ((lib and 0x80) or 0)) then
- return nil, "Wrong binary type.", header
- end
- if (header.compression > 1) then
- return nil, "Bad compression method."
- end
- if (header.arctype ~= "tsar" and header.arctype ~= "") then
- return nil, "Invalid archive type.", header
- end
- -- Load code portion
- local data = ""
- while header.psize-#data > 0 do
- data = data .. hand:read(header.psize-#data)
- end
- if (header.compression > 0) then
- data = M.decompress(data)
- end
- hand:seek("cur", header.lsize)
- hand:seek("cur", header.ssize)
- local cpos = hand:seek("cur", 0)
- if (header.arctype == "tsar") then
- venv._ARCHIVE = tsar_read(function(amt)
- local data = ""
- while amt-#data > 0 do
- data = data .. hand:read(amt-#data)
- end
- return data
- end, function(amt)
- return hand:seek("cur", amt)-cpos+1
- end, function()
- hand:close()
- end)
- end
- return load(data, "="..name, "t", venv)
- end
- local function load_velx(hand, env, name, lib)
- local func, err, head
- local lasterr
- while true do
- lasterr = err
- func, err, head = load_velx_part(hand, env, name, lib)
- if (func) then return func end
- if not head then return nil, err or lasterr end
- hand:seek("cur", head.psize+head.lsize+head.ssize+head.rsize)
- end
- end
- local velx = {}
- function velx.load(hand, env)
- return load_velx(hand, env, os.getenv("_"), false)
- end
- function velx.loadfile(path, env)
- return load_velx(package.loaded.filesystem.open(path, "rb"), env, path, true)
- end
- velx.mode = "rb"
- velx.version = "1.0"
- function velx.info()
- print(" A loader for VELX format executables.")
- print(" VELX version: 1")
- print(" Supported compression:")
- print(" - None")
- print(" - LZSS")
- print(" Supported archives:")
- print(" - None")
- print(" - tsar")
- print(" VELX OSID: 1")
- print(" Fat binaries: Supported")
- end
- return velx
Add Comment
Please, Sign In to add comment