Advertisement
awsumben13

BASIC Decompiler

Dec 5th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.73 KB | None | 0 0
  1.  
  2. local args = {...}
  3.  
  4. local function printUsage()
  5.     print "Usage:"
  6.     print " decompile [-l|-p] inputFile [outputFile]"
  7. end
  8.  
  9. if #args == 0 then
  10.     return printUsage()
  11. end
  12.  
  13. local lineNumbers = args[1] == "-l" or args[2] == "-l"
  14. local printOutput = args[1] == "-p" or args[2] == "-p"
  15.  
  16. for i = 1, (lineNumbers and 1 or 0) + (printOutput and 1 or 0) do
  17.     table.remove(args, 1)
  18. end
  19.  
  20. if #args == 0 then
  21.     printError "Missing argument inputFile"
  22.     return printUsage()
  23. end
  24.  
  25. local inf, opf = unpack(args)
  26. if inf:find "%." then
  27.     opf = opf or inf:gsub("%.", "_decompiled.")
  28. else
  29.     opf = opf or inf .. "_decompiled"
  30. end
  31.  
  32. local BC_HALT = 0x00
  33. local BC_GOSUB = 0x01
  34. local BC_ADD = 0x02
  35. local BC_SUB = 0x03
  36. local BC_VSET = 0x04
  37. local BC_VGET = 0x05
  38. local BC_ARGS = 0x06
  39. local BC_MUL = 0x07
  40. local BC_DIV = 0x08
  41. local BC_PUSH = 0x09
  42. local BC_POP = 0x0A
  43. local BC_CALL = 0x0B
  44. local BC_JUMP = 0x0C
  45. local BC_RET = 0x0D
  46. local BC_VFREE = 0x0E
  47. local BC_VDEF = 0x0F
  48. local BC_MOD = 0x10
  49. local BC_POW = 0x11
  50. local BC_CMP = 0x12
  51. local BC_JPC = 0x13
  52. local BC_STORE = 0x14
  53. local BC_LOAD = 0x15
  54. local BC_DUP = 0x16
  55. local BC_CARR = 0x17
  56. local BC_AND = 0x18
  57. local BC_OR = 0x19
  58.  
  59. local bc_END_STRING = 0x0
  60. local bc_START_STRING = 0x1
  61. local bc_NEXT_BC = 0x2
  62. local bc_NEXT_ARG = 0x3
  63.  
  64. local opToName = {
  65.     [ BC_HALT ] = { "HALT", 0 };
  66.     [ BC_GOSUB ] = { "GOSUB", 1 };
  67.     [ BC_ADD ] = { "ADD", 0 };
  68.     [ BC_SUB ] = { "SUB", 0 };
  69.     [ BC_VSET ] = { "VARSET", 1 };
  70.     [ BC_VGET ] = { "VARGET", 1 };
  71.     [ BC_ARGS ] = { "ARGS", 1 };
  72.     [ BC_MUL ] = { "MUL", 0 };
  73.     [ BC_DIV ] = { "DIV", 0 };
  74.     [ BC_PUSH ] = { "PUSH", 1 };
  75.     [ BC_POP ] = { "POP", 0 };
  76.     [ BC_CALL ] = { "CALL", 1 };
  77.     [ BC_JUMP ] = { "JUMP", 1 };
  78.     [ BC_RET ] = { "RETURN", 0 };
  79.     [ BC_VFREE ] = { "VARFREE", 1 };
  80.     [ BC_VDEF ] = { "VARDEF", 1 };
  81.     [ BC_MOD ] = { "MOD", 0 };
  82.     [ BC_POW ] = { "POW", 0 };
  83.     [ BC_CMP ] = { "COMPARE", 1 };
  84.     [ BC_JPC ] = { "CONDJMP", 2 };
  85.     [ BC_STORE ] = { "STORE", 1 };
  86.     [ BC_LOAD ] = { "LOAD", 1 };
  87.     [ BC_DUP ] = { "DUP", 0 };
  88.     [ BC_AND ] =  { "AND", 0 };
  89.     [ BC_OR ] = { "OR", 0 };
  90.     [ BC_CARR ] = { "CREATEARRAY", 0 };
  91. }
  92.  
  93. local function readBytecodeFile( fn )
  94.     local file = fs.open( fn, 'r' )
  95.     local content = file.readAll()
  96.     local t = {}
  97.  
  98.     file.close()
  99.  
  100.     for seg in content:gmatch "%S+" do
  101.         t[#t + 1] = tonumber(seg, 16)
  102.     end
  103.  
  104.     return t
  105. end
  106.  
  107. local function makeBytecode( bc )
  108.     local b = {}
  109.     local check = false
  110.     local i = 1
  111.     local function fetch()
  112.         local v = bc[ i ]
  113.         i = i + 1
  114.         return v
  115.     end
  116.     local function fetchString()
  117.         local str = ""
  118.         while true do
  119.             local v = fetch()
  120.             if v == bc_END_STRING then
  121.                 break
  122.             else
  123.                 str = str .. string.char( v )
  124.             end
  125.         end
  126.         return str
  127.     end
  128.     while i <= #bc do
  129.         local tp = fetch()
  130.         if tp == bc_NEXT_BC then
  131.             local byte = fetch()
  132.             local op = opToName[ byte ]
  133.             local iter = op[ 2 ]
  134.             b[ #b + 1 ] = byte
  135.             for j=1, iter do
  136.                 local nx = fetch()
  137.                 if nx == bc_NEXT_ARG then
  138.                     local x = fetch()
  139.                     b[ #b + 1 ] = x
  140.                 elseif nx == bc_START_STRING then
  141.                     local x = fetchString()
  142.                     b[ #b + 1 ] = x
  143.                 else
  144.                     error( "Expected Start of String or Start of Argument!", 0 )
  145.                 end
  146.             end
  147.         else
  148.             print( bc[ i-1 ] )
  149.             error( "Expected bytecode!", 0 )
  150.         end
  151.     end
  152.     return b
  153. end
  154.  
  155. local i = 1
  156. local of = io.open(opf, "w")
  157. local bc = makeBytecode(readBytecodeFile(inf))
  158. while i <= #bc do
  159.     local s = "UNKNOWN (" .. bc[i] .. ")"
  160.     if opToName[bc[i]] then
  161.         s = (lineNumbers and "%03d: " or ""):format(i) .. opToName[bc[i]][1]:lower()
  162.  
  163.         for j = 1, opToName[bc[i]][2] do
  164.             i = i + 1
  165.             s = s .. " " .. (type(bc[i]) == "string" and ("%q"):format(bc[i]) or bc[i])
  166.         end
  167.     end
  168.     if printOutput then
  169.         print(s)
  170.     end
  171.     of:write(s .. "\n")
  172.     i = i + 1
  173. end
  174.  
  175. of:close()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement