private void readFunctions(List<LuaConstant> constants, DataSource source) throws IOException { while (source.getUByte() == '#') { int idx = source.getUShort(); LuaFunction func = readFunction(source); constants.set(idx, new LuaConstant<>(func)); } }
private ArrayList<LocalVarDefinition> readLocals(DataSource source) throws IOException { int count = source.getUShort(); ArrayList<LocalVarDefinition> lvars = new ArrayList<>(); for (int i = 0; i < count; i++) lvars.add(new LocalVarDefinition(source.getUShort(), readTString(source))); lvars.add(new LocalVarDefinition(-1, null)); return lvars; }
private String readTString(DataSource source) throws IOException { int size = source.getUShort(); if (size == 0) return null; byte[] b = new byte[size]; source.get(b, 0, size); for (int i = 0; i < b.length; i++) b[i] ^= 0xff; String s = new String(b); if (s.endsWith("\0")) s = s.substring(0, s.length() - 1); return s; }
private LuaFunction readFunction(DataSource source) throws IOException { LuaFunction lf = new LuaFunction(); lf.lineNo = source.getUShort(); lf.source = readTString(source); int codeSize = source.getInt(); lf.code = new byte[codeSize]; source.get(lf.code); lf.constants = readConstants(source); lf.localVars = readLocals(source); readFunctions(lf.constants, source); return lf; }
@Override protected LuaChunk _read(DataSource source) throws IOException { int magic = source.getInt(); if (magic != 0x1B4C7561) throw new IOException("Invalid LUA file"); int version = source.getUByte(); if (version != 0x31) throw new IOException("Invalid LUA file version: " + Integer.toHexString(version)); if (source.getUByte() != 4) throw new IOException("Invalid LUA file, float length isn't 4..."); source.skip(4); // Todo: wtf are these? LuaFunction lf = readFunction(source); // Todo: decompile? haha, if it'll be anything like the java decompiler I wrote then f**k that return new LuaChunk(source.container, source.getName(), lf); }
private ArrayList<LuaConstant> readConstants(DataSource source) throws IOException { int count = source.getUShort(); ArrayList<LuaConstant> constants = new ArrayList<>(count); for (int i = 0; i < count; i++) { int type = source.getUByte(); switch (type) { case 'N': // number, float - 4 bytes constants.add(new LuaConstant<>(source.getFloatLE())); break; case 'S': // string constants.add(new LuaConstant<>(readTString(source))); break; case 'F': // constant function, for some reason it uses null here :S // (https://github.com/residualvm/residualvm/blob/master/engines/grim/lua/lundump.cpp#L112) constants.add(new LuaConstant<LuaFunction>(null)); break; default: System.err.println("Unknown LUA constant type: " + ((char) type)); break; } } return constants; }