load "VP-map.lua" load "VP-disasm.lua" load "VP-isowork.lua" load "VP-indexwork.lua" load "VP-fontwork.lua" load "VP-roomwork.lua" load "VP-miscwork.lua" load "VP-textwork.lua" load "VP-jp-in-us.lua" --restrict = { -- [3610] = true, -- [3611] = true, -- [3612] = true, -- [3613] = true, -- [3614] = true, -- [3615] = true, -- [3610 + 125] = true, --} --dump_glyph = true dump_mode = true activate_debug_room = true slusdirent = nil got_cd1 = false got_cd2 = false got_us = false got_jp = false got_eu = false got_psp = false got_add_cd1 = false got_add_cd2 = false got_add_us = false got_add_jp = false got_add_eu = false got_add_psp = false pspval1_sec = nil psp_dirtrees = {} all_txts = {} all_sha1 = {} all_origins = {} current_file = nil extra_glyphs_file = nil extra_glyphs = {} biggest_pad = 0 lookup_rooms = nil num_entries = 5120 fkey_size = 256 skey_size = 16 num_files = 4866 log_file = nil if not dump_mode then load "rooms-txt.lua" load "rooms.lua" end function new_pad(pad) if pad > biggest_pad then biggest_pad = pad end end function dump_mkdir(dir) if dump_mode then mkdir(dir) end end function log(str) print(str) if log_file then log_file:write(str .. "\n") end end function alignment(size, align) local ret = math.floor(size / align) ret = size - ret * align ret = align - ret if ret == align then ret = 0 end return ret end function process_single_file(fname, h, size, ext, handler) local sig = h:readU32() h:seek(-4, SEEK_CUR) local is_slz = sig == 0x005a4c53 or sig == 0x015a4c53 or sig == 0x025a4c53 or sig == 0x035a4c53 local is_tim = sig == 0x00000010 local eof = false if is_slz then log("Processing " .. fname .. "." .. ext .. ".slz") if dump_mode then o = Output(fname .. "." .. ext .. ".slz") o:copyfrom(h, size) o:destroy() h:seek(-size, SEEK_CUR) end local num, esiz, stype = 1 log("Extracting " .. fname .. ".slz") local ret = Buffer(true) while not eof do local snum snum = string.format("-%02i", num) if num ~= 1 then log("... file " .. num .. " to " .. fname .. snum .. "." .. ext) end o = Buffer(true) local tell = h:tell() esiz, stype = slz_decomp(h, o) eof = esiz == 0 h:seek(tell + esiz) local single_file_out = process_single_file(fname .. snum, o, o:getsize(), ext, handler) if not dump_mode then local single_file_compressed if not got_psp then single_file_compressed = Buffer(true) ucl_compress(single_file_out, single_file_compressed) else single_file_compressed = single_file_out end if single_file_compressed:getsize() >= single_file_out:getsize() then ret:writeU32(0x005a4c53) ret:writeU32(single_file_out:getsize()) ret:writeU32(single_file_out:getsize()) local alignment_bytes = alignment(single_file_out:getsize(), 4) for i = 1, alignment_bytes do single_file_out:writeU8(0) end if eof then ret:writeU32(0) else ret:writeU32(single_file_out:getsize() + 16) end ret:copyfrom(single_file_out) single_file_out:destroy() if single_file_out ~= single_file_compressed then single_file_compressed:destroy() end else ret:writeU32(0x035a4c53) ret:writeU32(single_file_compressed:getsize()) ret:writeU32(single_file_out:getsize()) local alignment_bytes = alignment(single_file_compressed:getsize(), 4) for i = 1, alignment_bytes do single_file_compressed:writeU8(0) end if eof then ret:writeU32(0) else ret:writeU32(single_file_compressed:getsize() + 16) end ret:copyfrom(single_file_compressed) single_file_compressed:destroy() single_file_out:destroy() end end o:destroy() num = num + 1 end return ret else if is_tim and ext ~= "tim" and not handler then ext = ext .. ".magic.tim" end log("Processing " .. fname .. "." .. ext) if dump_mode then o = Output(fname .. "." .. ext) local tell = h:tell() o:copyfrom(h, size) h:seek(tell) o:destroy() end local ret if handler then ret = handler(fname, h, size, ext) end if not ret and not dump_mode then ret = Buffer(true) local tell = h:tell() ret:copyfrom(h, size) h:seek(tell) end return ret end end script_types = { room = { header = { 0x01, 0x02, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x00 }, translated = { "-", "-", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "!", "O", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "!", "◎", "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨", "ǃ", "O", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "!", " " }, size = 0x33, }, } function do_dump(i) if not restrict then return true end return restrict[i] end function process_files(index, map, iso, iso_full, cindex, index_add, jp_in_us) print("Processing files...") local file_in, sig, is_slz, o, mode, dir, ftype for i = 1, (num_entries - 1) do if index[i] and ((not dump_mode) or do_dump(i)) then if map[i] then mode = map[i].mode dir = map[i].dir ext = map[i].ext ftype = map[i].ftype else mode = MODE2_FORM1 dir = "UNKNOWN" ext = "out" ftype = nil end if not mode then mode = MODE2_FORM1 end if not ext then ext = "out" end if not dir then dir = "UNKNOWN" end file_in = index[i].cd:cdfile(index[i].sector, index[i].size * sec_sizes[mode]) dump_mkdir("DUMP/" .. dir) current_file = i local file_out if not dump_mode and not do_dump(i) and not jp_in_us then file_out = file_in elseif jp_in_us then local lookup = jp_in_us[i] if lookup then log("JP-in-US: replacing file " .. i .. " by file " .. lookup) file_out = index_add[lookup].cd:cdfile(index_add[lookup].sector, index_add[lookup].size * sec_sizes[mode]) end elseif ftype then local handler = _G["process_" .. ftype] if not handler then error("Unknown ftype: " .. ftype) end file_out = handler("DUMP/" .. dir .. string.format("/%04i", i), file_in, file_in:getsize(), ext) else file_out = process_single_file("DUMP/" .. dir .. string.format("/%04i", i), file_in, file_in:getsize(), ext) end if not file_out then file_out = file_in end file_in:seek(0) if not dump_mode then cindex:add_file(iso, file_out, i) end file_in:destroy() if file_out ~= file_in then file_out:destroy() end end end end function main(...) local cd, cd2, iso_out, cd3, cd4 = startup(...) iso_identify(cd) if cd2 then iso_identify(cd2) end if cd3 then iso_identify(cd3, true) end if cd4 then iso_identify(cd4, true) end if not jp_in_us and not slz_decomp then error "luaslz module not found." end local false_sect = Buffer(true) false_sect:writeU8(0) load_glyphes() dump_mkdir "DUMP" _, log_file = pcall(Output, "log.txt") local index, fkey, skey, fr, sr = load_index(cd) if cd2 then local index2 = load_index(cd2) for k, v in pairs(index2) do if not index[k] then index[k] = v end end end local index_add if cd3 then index_add = load_index(cd3) end if cd4 and index_add then local index2_add = load_index(cd4) for k, v in pairs(index2_add) do if not index_add[k] then index_add[k] = v end end end if dump_mode then for k, v in pairs(VP_maintypes) do dump_mkdir("DUMP/" .. v) end end local iso_full = true for i = 1, (num_files - 1) do if not index[i] then iso_full = false end end local iso_add_full = false if index_add then iso_add_full = true for i = 1, (num_files - 1) do if not index_add[i] then iso_add_full = false end end end if jp_in_us then dump_mode = false end local iso, cindex if not dump_mode then iso = prepare_out(iso_out) build_basic(iso, cd, iso_full) cindex = prepare_index(iso, fkey, skey, fr, sr) else lookup_rooms = Output "DUMP/GAME/rooms.lua" lookup_rooms:write "rooms_lookup = {\n" end process_files(index, VP_map, iso, iso_full, cindex, index_add, jp_in_us and VP_jp_in_us or nil) if dump_mode then local o = Output "DUMP/GAME/rooms.xml" o:write('\n') for k, v in ipairs(all_txts) do local origin = all_origins[k] if string.len(origin) > 50 then origin="MULTIPLE" end o:write('\n\n' .. v.txt .. "\n") end o:write('\n') o:destroy() lookup_rooms:write "}\n" lookup_rooms:destroy() else cindex:close_index(iso, cd) if not got_psp then for i = 1, 148 do false_sect:seek(0) iso:putfile(false_sect, MODE2) end end iso:close() end log("Biggest pad = " .. biggest_pad) log_file:destroy() end