Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Playground FLSH asset dumper.
- -- It does not allow you to make new FLSH file!!!
- local arg = {...}
- local target_input = arg[1]
- if target_input == nil then
- print("Usage: lua flsh_dumper.lua <flsh path>")
- print("It does not allow you to make new FLSH file!!!")
- return 1
- end
- local input = assert(io.open(target_input, "rb"))
- assert(input:read(4) == "FLSH", "Invalid FLSH file")
- input:read(4) -- Skip size
- local function read32_be(file)
- local x = {file:read(4):byte(1,4)}
- return x[1] * 16777216 + x[2] * 65536 + x[3] * 256 + x[4]
- end
- local function read16_be(file)
- local x = {file:read(2):byte(1,2)}
- return x[1] * 256 + x[2]
- end
- local function read_float(file)
- return read32_be(file) / 65536.0
- end
- local function read_byte(file)
- return file:read(1):byte()
- end
- local function read_string(file)
- local size = read16_be(file)
- return ({file:read(size):gsub("%z", "")})[1]
- end
- local function print(...)
- local nt = {}
- for a, b in ipairs({...}) do
- nt[#nt + 1] = tostring(b)
- end
- io.write(table.concat(nt, "\t"), "\n")
- end
- -- Start!!!
- print("Name", read_string(input))
- do
- local msf = read16_be(input)
- print("MS/Frame", msf, math.floor(1000/msf).." FPS")
- end
- local sounds = {}
- local strings_list = {}
- local string_count = read16_be(input)
- do
- read16_be(input) -- Skip total string size
- if string_count == 65535 then
- -- Sound extension
- local sound_count = read16_be(input)
- if sound_count > 0 then
- for i = 1, sound_count do
- sounds[i] = {read16_be(input)}
- end
- end
- local indexTotal = read32_be(input)
- local shapeCount = read16_be(input)
- assert(shapeCount == 0, "Shape decoding is not supported")
- string_count = read16_be(input)
- end
- print()
- print("Contains "..string_count.." string(s) constant")
- for i = 1, string_count do
- local x = read_string(input)
- i = i - 1
- strings_list[i] = x
- print("["..i.."] = "..x)
- end
- end
- if #sounds > 0 then
- print()
- print("Has sound extension")
- for i = 1, #sounds do
- print("["..(i - 1).."] = "..strings_list[sounds[i][1]])
- end
- end
- local matrix_count = read32_be(input)
- local float_count = read32_be(input)
- local matrix_data = {}
- local float_data = {}
- print()
- print("Contains "..float_count.." float constants")
- for i = 1, float_count do
- local x = read_float(input)
- i = i - 1
- x = math.floor(x / 32768) * (-65536) + x
- float_data[i] = x
- print("["..i.."] = "..x)
- end
- local matrix_type_id = {[0] = "MATRIX_ID", "MATRIX_T", "MATRIX_TS", "MATRIX_TG", "MATRIX_COL"}
- local matrix_idx_fmt = string.format("%%%02dd", #tostring(matrix_count - 1))
- print()
- print("Contains "..matrix_count.." matrix data")
- for i = 1, matrix_count do
- local x = read_byte(input)
- local y = read32_be(input)
- table.insert(matrix_data, {x, y})
- io.write(matrix_idx_fmt:format(i - 1), "\tType\t", matrix_type_id[x] or x, "\tData Index\t", y)
- if x == 0 then
- io.write("\t\tA = 0; D = 0; TX = 0; TY = 0; B = 0; C = 0;\n")
- elseif x == 1 then
- io.write("\t\tTX = ", float_data[y], "; TY = ", float_data[y + 1], ";\n")
- elseif x == 2 then
- io.write("\t\tA = ", float_data[y], "; D = ", float_data[y + 1], "; TX = ", float_data[y + 2], "; TY = ", float_data[y + 3], "; B = 0; C = 0;\n")
- elseif x == 3 then
- io.write("\t\tA = ", float_data[y], "; D = ", float_data[y + 1], "; B = ", float_data[y + 2], "; C = ", float_data[y + 3], "; TX = ", float_data[y + 4], "; TY = ", float_data[y + 5], ";\n")
- elseif x == 4 then
- io.write("\t\tR = ", float_data[y] * 255, "; G = ", float_data[y + 1] * 255, "; B = ", float_data[y + 2] * 255, "; A = ", float_data[y + 3] * 255, ";\n")
- else
- io.write("\n")
- end
- end
- local instr_count = read32_be(input)
- local instr_data = {}
- print()
- print("Contains "..instr_count.." instructions")
- for i = 1, instr_count do
- local x = read32_be(input)
- instr_data[i - 1] = x
- end
- local movie_count = read16_be(input)
- local movie_data = {}
- print()
- print("Contains "..movie_count.." movie(s)")
- for i = 1, movie_count do
- local x = {
- name_idx = read32_be(input),
- framecount = read32_be(input),
- startindex = read32_be(input),
- endindex = read32_be(input)
- }
- local name = strings_list[x.name_idx]
- movie_data[i - 1] = x
- if x.framecount < 32768 then
- if name then
- print(string.format("Movie #%d name = %s ; %d frames ; start instr idx = %d ; end instr idx = %d", i - 1, name, x.framecount, x.startindex, x.endindex))
- else
- print(string.format("Movie #%d unnamed movie ; %d frames ; start instr idx = %d ; end instr idx = %d", i - 1, x.framecount, x.startindex, x.endindex))
- end
- elseif x.framecount == 65535 then
- print(string.format("Movie #%d image %s ; offsetx = %d ; offsety = %d", i - 1, name, x.startindex, x.endindex))
- elseif x.framecount == 36862 then
- print(string.format("Movie #%d shape %s ; offsetx = %d ; offsety = %d", i - 1, name, x.startindex, x.endindex))
- else
- --
- print(string.format("Movie #%d %s movie", i - 1, name or "unknown"))
- end
- end
- local max_instr_len = #string.format("%x", instr_count * 4)
- local instr_idx_format = string.format("[%%%02dX]", max_instr_len)
- for n, v in pairs(movie_data) do
- local movie_name = strings_list[v.name_idx]
- if v.framecount < 32768 then
- print()
- if movie_name then
- print("Decoded instructions for movie #"..n.." ("..movie_name..")")
- else
- print("Decoded instructions for unnamed movie #"..n)
- end
- local instr_counter = v.startindex + 4
- local function get_next_instruction()
- local x = instr_data[instr_counter]
- instr_counter = instr_counter + 1
- return x
- end
- while instr_counter < v.endindex do
- local instr_pos = instr_counter
- local instr = get_next_instruction()
- local instr_name = ""
- local instr_info = {}
- do
- if instr == 0 then
- instr_name = "SHOW_FRAME\t"
- local label = get_next_instruction()
- local type = get_next_instruction()
- local frame_target = get_next_instruction() + 2
- table.insert(instr_info, string.format("LABEL %08X", label))
- table.insert(instr_info, string.format("TYPE %08X", type))
- if type == 0 then
- table.insert(instr_info, "STOP_INSTRUCTION")
- elseif type == 1 or type == 2 then
- if type == 1 then
- table.insert(instr_info, "GOTO_AND_PLAY")
- else
- table.insert(instr_info, "GOTO_AND_STOP")
- end
- table.insert(instr_info, string.format("FRAMETARGET %08X", frame_target))
- end
- elseif instr == 1 or instr == 4 then
- if instr == 1 then
- instr_name = "PLACE_OBJECT"
- else
- instr_name = "PLACE_OBJECT_CLIP"
- end
- local movieid = get_next_instruction()
- local matrixidx = get_next_instruction()
- local matrixcolidx = get_next_instruction()
- local layer = get_next_instruction()
- table.insert(instr_info, string.format("MOVIEID %d MATRIXIDX %d MATRIXCOLIDX %d LAYER %d", movieid, matrixidx, matrixcolidx, layer))
- if instr == 4 then
- local clip = get_next_instruction()
- table.insert(instr_info, string.format("CLIP %d", clip))
- end
- elseif instr == 2 then
- instr_name = "REMOVE_OBJECT"
- local layer = get_next_instruction()
- table.insert(instr_info, string.format("LAYER %d", layer))
- elseif instr == 3 then
- instr_name = "PLAY_SOUND\t"
- local sndid = get_next_instruction()
- table.insert(instr_info, string.format("SNDID %d", sndid))
- else
- instr_name = "INVALID"
- end
- end
- print(string.format(instr_idx_format, instr_pos * 4), string.format("%08X\t%s\t%s", instr, instr_name, table.concat(instr_info, " ")))
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement