Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local args = {...}
- local function printUsage()
- print "Usage:"
- print " decompile [-l|-p] inputFile [outputFile]"
- end
- if #args == 0 then
- return printUsage()
- end
- local lineNumbers = args[1] == "-l" or args[2] == "-l"
- local printOutput = args[1] == "-p" or args[2] == "-p"
- for i = 1, (lineNumbers and 1 or 0) + (printOutput and 1 or 0) do
- table.remove(args, 1)
- end
- if #args == 0 then
- printError "Missing argument inputFile"
- return printUsage()
- end
- local inf, opf = unpack(args)
- if inf:find "%." then
- opf = opf or inf:gsub("%.", "_decompiled.")
- else
- opf = opf or inf .. "_decompiled"
- end
- local BC_HALT = 0x00
- local BC_GOSUB = 0x01
- local BC_ADD = 0x02
- local BC_SUB = 0x03
- local BC_VSET = 0x04
- local BC_VGET = 0x05
- local BC_ARGS = 0x06
- local BC_MUL = 0x07
- local BC_DIV = 0x08
- local BC_PUSH = 0x09
- local BC_POP = 0x0A
- local BC_CALL = 0x0B
- local BC_JUMP = 0x0C
- local BC_RET = 0x0D
- local BC_VFREE = 0x0E
- local BC_VDEF = 0x0F
- local BC_MOD = 0x10
- local BC_POW = 0x11
- local BC_CMP = 0x12
- local BC_JPC = 0x13
- local BC_STORE = 0x14
- local BC_LOAD = 0x15
- local BC_DUP = 0x16
- local BC_CARR = 0x17
- local BC_AND = 0x18
- local BC_OR = 0x19
- local bc_END_STRING = 0x0
- local bc_START_STRING = 0x1
- local bc_NEXT_BC = 0x2
- local bc_NEXT_ARG = 0x3
- local opToName = {
- [ BC_HALT ] = { "HALT", 0 };
- [ BC_GOSUB ] = { "GOSUB", 1 };
- [ BC_ADD ] = { "ADD", 0 };
- [ BC_SUB ] = { "SUB", 0 };
- [ BC_VSET ] = { "VARSET", 1 };
- [ BC_VGET ] = { "VARGET", 1 };
- [ BC_ARGS ] = { "ARGS", 1 };
- [ BC_MUL ] = { "MUL", 0 };
- [ BC_DIV ] = { "DIV", 0 };
- [ BC_PUSH ] = { "PUSH", 1 };
- [ BC_POP ] = { "POP", 0 };
- [ BC_CALL ] = { "CALL", 1 };
- [ BC_JUMP ] = { "JUMP", 1 };
- [ BC_RET ] = { "RETURN", 0 };
- [ BC_VFREE ] = { "VARFREE", 1 };
- [ BC_VDEF ] = { "VARDEF", 1 };
- [ BC_MOD ] = { "MOD", 0 };
- [ BC_POW ] = { "POW", 0 };
- [ BC_CMP ] = { "COMPARE", 1 };
- [ BC_JPC ] = { "CONDJMP", 2 };
- [ BC_STORE ] = { "STORE", 1 };
- [ BC_LOAD ] = { "LOAD", 1 };
- [ BC_DUP ] = { "DUP", 0 };
- [ BC_AND ] = { "AND", 0 };
- [ BC_OR ] = { "OR", 0 };
- [ BC_CARR ] = { "CREATEARRAY", 0 };
- }
- local function readBytecodeFile( fn )
- local file = fs.open( fn, 'r' )
- local content = file.readAll()
- local t = {}
- file.close()
- for seg in content:gmatch "%S+" do
- t[#t + 1] = tonumber(seg, 16)
- end
- return t
- end
- local function makeBytecode( bc )
- local b = {}
- local check = false
- local i = 1
- local function fetch()
- local v = bc[ i ]
- i = i + 1
- return v
- end
- local function fetchString()
- local str = ""
- while true do
- local v = fetch()
- if v == bc_END_STRING then
- break
- else
- str = str .. string.char( v )
- end
- end
- return str
- end
- while i <= #bc do
- local tp = fetch()
- if tp == bc_NEXT_BC then
- local byte = fetch()
- local op = opToName[ byte ]
- local iter = op[ 2 ]
- b[ #b + 1 ] = byte
- for j=1, iter do
- local nx = fetch()
- if nx == bc_NEXT_ARG then
- local x = fetch()
- b[ #b + 1 ] = x
- elseif nx == bc_START_STRING then
- local x = fetchString()
- b[ #b + 1 ] = x
- else
- error( "Expected Start of String or Start of Argument!", 0 )
- end
- end
- else
- print( bc[ i-1 ] )
- error( "Expected bytecode!", 0 )
- end
- end
- return b
- end
- local i = 1
- local of = io.open(opf, "w")
- local bc = makeBytecode(readBytecodeFile(inf))
- while i <= #bc do
- local s = "UNKNOWN (" .. bc[i] .. ")"
- if opToName[bc[i]] then
- s = (lineNumbers and "%03d: " or ""):format(i) .. opToName[bc[i]][1]:lower()
- for j = 1, opToName[bc[i]][2] do
- i = i + 1
- s = s .. " " .. (type(bc[i]) == "string" and ("%q"):format(bc[i]) or bc[i])
- end
- end
- if printOutput then
- print(s)
- end
- of:write(s .. "\n")
- i = i + 1
- end
- of:close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement