Created
December 22, 2016 09:53
-
-
Save SonoSooS/f09eeb52d7b33304706d211375056bf9 to your computer and use it in GitHub Desktop.
FST parser Lua script
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
#!/bin/lua | |
-- =================================== | |
-- FST parser Lua script | |
-- | |
-- created by MarcusD | |
-- Copyright $(date +"%Y") | |
-- | |
-- :P | |
-- =================================== | |
local argv = {...} | |
local argc = #argv | |
local function read32(fileptr) | |
local n = {fileptr:read(4):byte(1, 4)} | |
return | |
(n[1] * 256 * 256 * 256) + | |
(n[2] * 256 * 256) + | |
(n[3] * 256) + | |
(n[4]) | |
end | |
local function read24(fileptr) | |
local n = {fileptr:read(3):byte(1, 3)} | |
return | |
(n[1] * 256 * 256) + | |
(n[2] * 256) + | |
(n[3]) | |
end | |
local function read16(fileptr) | |
local n = {fileptr:read(2):byte(1, 2)} | |
return | |
(n[1] * 256) + | |
(n[2]) | |
end | |
local function ftell(ptr) | |
return ptr:seek("cur", 0) | |
end | |
local function readstring(ptr) | |
local buf = {} | |
local n = nil | |
while true do | |
n = ptr:read(1) | |
if not n then break end | |
if n == "\0" then break end | |
buf[#buf + 1] = n | |
end | |
return table.concat(buf) | |
end | |
local fprefix = "- " | |
local dirprefix = "* " | |
local function iterdir(ptr, is, cnt, baseoffs, nameoffs, depth, topdir) | |
if not depth then depth = 1 end | |
if not topdir then topdir = -1 end | |
if not is then is = 1 end | |
local i = is | |
while i < cnt do | |
local isdir = ptr:read(1):byte() ~= 0 | |
local offs = read24(ptr) + nameoffs | |
local bakptr = ftell(ptr) | |
ptr:seek("set", offs) | |
local name = readstring(ptr) | |
ptr:seek("set", bakptr) | |
local foffs = read32(ptr) | |
local fsize = read32(ptr) | |
local flags = read16(ptr) | |
if not isdir and (flags % 8) < 4 then foffs = foffs * 0x20 end | |
local coffs = read16(ptr) | |
print(("%02i "):format(i) .. (" "):rep(depth - 1) .. (isdir and dirprefix or fprefix) .. name .. (isdir and "" or (" (Size: 0x" .. ("%X"):format(fsize)) .. ")") .. (coffs ~= 0 and (" (ContentID: " .. (coffs + 1) .. ")") or "")) | |
if isdir then | |
if foffs <= topdir then return i end | |
iterdir(ptr, i + 1, fsize, baseoffs, nameoffs, depth + 1, foffs) | |
i = fsize - 1 | |
end | |
i = i + 1 | |
end | |
end | |
if argc < 1 then | |
print("Usage: fstlist.lua <file...>") | |
return 1 | |
end | |
for _, path in pairs(argv) do | |
local ptr, err = io.open(path, "rb") | |
if ptr then | |
local num = read32(ptr) | |
if num == 0x46535400 then | |
local exhsize = read32(ptr) | |
local exhcount = read32(ptr) | |
print("exheader size: 0x" .. ("%X"):format(exhsize)) | |
print("exheader count: " .. exhcount) | |
if exhsize == 0x20 then | |
ptr:seek("cur", 0x14) | |
for i = 1, exhcount do | |
print(("#%02i:"):format(i)) | |
print("- Unknown1: 0x" .. ("%08X"):format(read32(ptr))) | |
print("- Unknown2: 0x" .. ("%08X"):format(read32(ptr))) | |
print("- TitleID: 0x" .. ("%08X%08X"):format(read32(ptr), read32(ptr))) | |
print("- GroupID: 0x" .. ("%08X"):format(read32(ptr))) | |
print("- Flags?: 0x" .. ("%04X"):format(read16(ptr))) | |
print("") | |
ptr:seek("cur", 10) | |
end | |
local fsestart = ftell(ptr) | |
ptr:seek("cur", 8) | |
local rootcnt = read32(ptr) | |
ptr:seek("cur", 4) | |
local nameoffs = fsestart + (rootcnt * 0x10) | |
iterdir(ptr, 1, rootcnt - 1, fsestart + 0x10, nameoffs) | |
else | |
print("'" .. path .. "': invalid exheader size: 0x" .. ("%X"):format(exhsize)) | |
end | |
else | |
print("'" .. path .. "': not an FST file (" .. ("%08X"):format(num) .. ")") | |
end | |
ptr:close() | |
else | |
print("Error opening '" .. path .. "': " .. err) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment