Created
October 3, 2016 11:38
-
-
Save MikuAuahDark/ca9bd2b98d6e50c4a76c1ada4be1fcee to your computer and use it in GitHub Desktop.
Playground Flash file dumper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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")) | |
if input:read(4) ~= "FLSH" then | |
error("Invalid FLSH file") | |
end | |
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 | |
-- Start!!! | |
print("Name", read_string(input)) | |
do | |
local msf = read16_be(input) | |
print("MS/Frame", msf, math.floor(1000/msf).." FPS") | |
end | |
local strings_list = {} | |
local string_count = read16_be(input) | |
do | |
read16_be(input) -- Skip total string size | |
if string_count == 65535 then | |
error("Sound extension is not supported yet") | |
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 | |
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 | |
float_data[i] = x | |
print("["..i.."] = "..x) | |
end | |
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}) | |
print("Type", x, "Data Index", y) | |
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) | |
local instr_name = "" | |
table.insert(instr_data, 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) | |
} | |
table.insert(movie_data, x) | |
if x.name_idx == 65535 then | |
print("Movie #"..i.." null/unknown movie") | |
else | |
local name = strings_list[x.name_idx] | |
if x.framecount == 65535 then | |
print(string.format("Movie #"..i.." image %s ; offsetx = %d ; offsety = %d", name, x.startindex, x.endindex)) | |
elseif x.framecount == 36862 then | |
print(string.format("Movie #"..i.." shape %s ; offsetx = %d ; offsety = %d", name, x.startindex, x.endindex)) | |
else | |
print(string.format("Movie #3 name = %s ; %d frames ; start instr idx = %d ; end instr idx = %d", name, x.framecount, x.startindex, x.endindex)) | |
end | |
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.name_idx ~= 65535 and movie_name:byte() == 70 then | |
print() | |
print("Decoded instructions for movie #"..n.." ("..movie_name..")") | |
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" | |
local label = get_next_instruction() | |
local type = get_next_instruction() | |
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 | |
local frame_target = get_next_instruction() + 2 | |
table.insert(instr_info, string.format("FRAMETARGET %08X", frame_target)) | |
else | |
get_next_instruction() | |
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" | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment