Advertisement
Guest User

Untitled

a guest
Apr 30th, 2017
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.38 KB | None | 0 0
  1. -- Playground FLSH asset dumper.
  2. -- It does not allow you to make new FLSH file!!!
  3.  
  4. local arg = {...}
  5. local target_input = arg[1]
  6.  
  7. if target_input == nil then
  8. print("Usage: lua flsh_dumper.lua <flsh path>")
  9. print("It does not allow you to make new FLSH file!!!")
  10. return 1
  11. end
  12.  
  13. local input = assert(io.open(target_input, "rb"))
  14.  
  15. assert(input:read(4) == "FLSH", "Invalid FLSH file")
  16. input:read(4) -- Skip size
  17.  
  18. local function read32_be(file)
  19. local x = {file:read(4):byte(1,4)}
  20.  
  21. return x[1] * 16777216 + x[2] * 65536 + x[3] * 256 + x[4]
  22. end
  23.  
  24. local function read16_be(file)
  25. local x = {file:read(2):byte(1,2)}
  26.  
  27. return x[1] * 256 + x[2]
  28. end
  29.  
  30. local function read_float(file)
  31. return read32_be(file) / 65536.0
  32. end
  33.  
  34. local function read_byte(file)
  35. return file:read(1):byte()
  36. end
  37.  
  38. local function read_string(file)
  39. local size = read16_be(file)
  40.  
  41. return ({file:read(size):gsub("%z", "")})[1]
  42. end
  43.  
  44. local function print(...)
  45. local nt = {}
  46.  
  47. for a, b in ipairs({...}) do
  48. nt[#nt + 1] = tostring(b)
  49. end
  50.  
  51. io.write(table.concat(nt, "\t"), "\n")
  52. end
  53.  
  54. -- Start!!!
  55. print("Name", read_string(input))
  56.  
  57. do
  58. local msf = read16_be(input)
  59. print("MS/Frame", msf, math.floor(1000/msf).." FPS")
  60. end
  61.  
  62. local sounds = {}
  63. local strings_list = {}
  64. local string_count = read16_be(input)
  65. do
  66. read16_be(input) -- Skip total string size
  67.  
  68. if string_count == 65535 then
  69. -- Sound extension
  70. local sound_count = read16_be(input)
  71.  
  72. if sound_count > 0 then
  73. for i = 1, sound_count do
  74. sounds[i] = {read16_be(input)}
  75. end
  76. end
  77.  
  78. local indexTotal = read32_be(input)
  79. local shapeCount = read16_be(input)
  80.  
  81. assert(shapeCount == 0, "Shape decoding is not supported")
  82. string_count = read16_be(input)
  83. end
  84.  
  85. print()
  86. print("Contains "..string_count.." string(s) constant")
  87.  
  88. for i = 1, string_count do
  89. local x = read_string(input)
  90.  
  91. i = i - 1
  92. strings_list[i] = x
  93. print("["..i.."] = "..x)
  94. end
  95. end
  96.  
  97. if #sounds > 0 then
  98. print()
  99. print("Has sound extension")
  100.  
  101. for i = 1, #sounds do
  102. print("["..(i - 1).."] = "..strings_list[sounds[i][1]])
  103. end
  104. end
  105.  
  106. local matrix_count = read32_be(input)
  107. local float_count = read32_be(input)
  108. local matrix_data = {}
  109. local float_data = {}
  110.  
  111. print()
  112. print("Contains "..float_count.." float constants")
  113. for i = 1, float_count do
  114. local x = read_float(input)
  115. i = i - 1
  116. x = math.floor(x / 32768) * (-65536) + x
  117. float_data[i] = x
  118. print("["..i.."] = "..x)
  119. end
  120.  
  121. local matrix_type_id = {[0] = "MATRIX_ID", "MATRIX_T", "MATRIX_TS", "MATRIX_TG", "MATRIX_COL"}
  122. local matrix_idx_fmt = string.format("%%%02dd", #tostring(matrix_count - 1))
  123. print()
  124. print("Contains "..matrix_count.." matrix data")
  125. for i = 1, matrix_count do
  126. local x = read_byte(input)
  127. local y = read32_be(input)
  128.  
  129. table.insert(matrix_data, {x, y})
  130. io.write(matrix_idx_fmt:format(i - 1), "\tType\t", matrix_type_id[x] or x, "\tData Index\t", y)
  131.  
  132. if x == 0 then
  133. io.write("\t\tA = 0; D = 0; TX = 0; TY = 0; B = 0; C = 0;\n")
  134. elseif x == 1 then
  135. io.write("\t\tTX = ", float_data[y], "; TY = ", float_data[y + 1], ";\n")
  136. elseif x == 2 then
  137. 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")
  138. elseif x == 3 then
  139. 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")
  140. elseif x == 4 then
  141. 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")
  142. else
  143. io.write("\n")
  144. end
  145. end
  146.  
  147. local instr_count = read32_be(input)
  148. local instr_data = {}
  149.  
  150. print()
  151. print("Contains "..instr_count.." instructions")
  152. for i = 1, instr_count do
  153. local x = read32_be(input)
  154.  
  155. instr_data[i - 1] = x
  156. end
  157.  
  158. local movie_count = read16_be(input)
  159. local movie_data = {}
  160. print()
  161. print("Contains "..movie_count.." movie(s)")
  162. for i = 1, movie_count do
  163. local x = {
  164. name_idx = read32_be(input),
  165. framecount = read32_be(input),
  166. startindex = read32_be(input),
  167. endindex = read32_be(input)
  168. }
  169. local name = strings_list[x.name_idx]
  170.  
  171. movie_data[i - 1] = x
  172.  
  173. if x.framecount < 32768 then
  174. if name then
  175. 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))
  176. else
  177. 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))
  178. end
  179. elseif x.framecount == 65535 then
  180. print(string.format("Movie #%d image %s ; offsetx = %d ; offsety = %d", i - 1, name, x.startindex, x.endindex))
  181. elseif x.framecount == 36862 then
  182. print(string.format("Movie #%d shape %s ; offsetx = %d ; offsety = %d", i - 1, name, x.startindex, x.endindex))
  183. else
  184. --
  185. print(string.format("Movie #%d %s movie", i - 1, name or "unknown"))
  186. end
  187. end
  188.  
  189. local max_instr_len = #string.format("%x", instr_count * 4)
  190. local instr_idx_format = string.format("[%%%02dX]", max_instr_len)
  191.  
  192. for n, v in pairs(movie_data) do
  193. local movie_name = strings_list[v.name_idx]
  194. if v.framecount < 32768 then
  195. print()
  196.  
  197. if movie_name then
  198. print("Decoded instructions for movie #"..n.." ("..movie_name..")")
  199. else
  200. print("Decoded instructions for unnamed movie #"..n)
  201. end
  202.  
  203. local instr_counter = v.startindex + 4
  204. local function get_next_instruction()
  205. local x = instr_data[instr_counter]
  206.  
  207. instr_counter = instr_counter + 1
  208. return x
  209. end
  210.  
  211. while instr_counter < v.endindex do
  212. local instr_pos = instr_counter
  213. local instr = get_next_instruction()
  214. local instr_name = ""
  215. local instr_info = {}
  216. do
  217. if instr == 0 then
  218. instr_name = "SHOW_FRAME\t"
  219.  
  220. local label = get_next_instruction()
  221. local type = get_next_instruction()
  222. local frame_target = get_next_instruction() + 2
  223.  
  224. table.insert(instr_info, string.format("LABEL %08X", label))
  225. table.insert(instr_info, string.format("TYPE %08X", type))
  226.  
  227. if type == 0 then
  228. table.insert(instr_info, "STOP_INSTRUCTION")
  229. elseif type == 1 or type == 2 then
  230. if type == 1 then
  231. table.insert(instr_info, "GOTO_AND_PLAY")
  232. else
  233. table.insert(instr_info, "GOTO_AND_STOP")
  234. end
  235.  
  236. table.insert(instr_info, string.format("FRAMETARGET %08X", frame_target))
  237. end
  238. elseif instr == 1 or instr == 4 then
  239. if instr == 1 then
  240. instr_name = "PLACE_OBJECT"
  241. else
  242. instr_name = "PLACE_OBJECT_CLIP"
  243. end
  244.  
  245. local movieid = get_next_instruction()
  246. local matrixidx = get_next_instruction()
  247. local matrixcolidx = get_next_instruction()
  248. local layer = get_next_instruction()
  249.  
  250. table.insert(instr_info, string.format("MOVIEID %d MATRIXIDX %d MATRIXCOLIDX %d LAYER %d", movieid, matrixidx, matrixcolidx, layer))
  251.  
  252. if instr == 4 then
  253. local clip = get_next_instruction()
  254. table.insert(instr_info, string.format("CLIP %d", clip))
  255. end
  256. elseif instr == 2 then
  257. instr_name = "REMOVE_OBJECT"
  258.  
  259. local layer = get_next_instruction()
  260.  
  261. table.insert(instr_info, string.format("LAYER %d", layer))
  262. elseif instr == 3 then
  263. instr_name = "PLAY_SOUND\t"
  264.  
  265. local sndid = get_next_instruction()
  266.  
  267. table.insert(instr_info, string.format("SNDID %d", sndid))
  268. else
  269. instr_name = "INVALID"
  270. end
  271. end
  272.  
  273. print(string.format(instr_idx_format, instr_pos * 4), string.format("%08X\t%s\t%s", instr, instr_name, table.concat(instr_info, " ")))
  274. end
  275. end
  276. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement