Created
May 1, 2017 02:11
-
-
Save MikuAuahDark/ffc04ddb2a655ca0cd62784a05923029 to your computer and use it in GitHub Desktop.
Lua script to view more information about Playground Flash File
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")) | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment