local makepfs_sig = { 0x4d, 0x61, 0x6b, 0x65, 0x50, 0x66, 0x73, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x2e, 0x32, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } function load_psp_index(cdutil) local pspval1_ent = cdutil:findpath "/PSP_GAME/USRDIR/PSPVAL1.PFS" if not pspval1_ent then error "VP-PSP iso seems wrong..." end local pspval1 = cdutil:cdfile(pspval1_ent) for k, v in ipairs(makepfs_sig) do if pspval1:readU8() ~= v then error "Wrong MakePfs signature." end end num_entries = pspval1:readU32() num_files = num_entries local idx_pos = pspval1:readU32() local index = {} pspval1:seek(2048 * idx_pos + 4) local last_sector = 1 for i = 1, num_entries - 1 do local sector = pspval1:readU32() local abssector = pspval1_ent.Sector + sector index[i] = { sector = abssector, cd = cdutil } if i ~= 1 then index[i - 1].size = sector - last_sector end last_sector = sector end index[num_entries - 1].size = idx_pos - last_sector for i = 1, num_entries - 1 do if index[i].size == 0 then index[i] = nil else log("Entry " .. i .. ", sector " .. index[i].sector .. ", nsectors = " .. index[i].size) end end return index end function load_index(cdutil) if got_psp then return load_psp_index(cdutil) end local vp_sec, cfat, csiz, fat, siz, fkey, skey, fkey_pos, skey_pos vp_sec = 150 cfat = cdutil:cdfile(vp_sec, num_entries * 4) csiz = cdutil:cdfile(vp_sec + num_entries * 4 / 2048, num_entries) fat = Buffer(true) siz = Buffer(true) fkey = Buffer(true) skey = Buffer(true) cfat:seek(num_entries * 4 - fkey_size) csiz:seek(num_entries - skey_size) fkey:copyfrom(cfat, fkey_size) skey:copyfrom(csiz, skey_size) cfat:seek(0) csiz:seek(0) fkey_pos = 0 skey_pos = 0 print "Decrypting index..." for i = 0, (num_entries * 4 - 1) do fat:writeU8(xorB(cfat:readU8(), fkey:readU8())) fkey_pos = fkey_pos + 1 if fkey_pos == fkey_size then fkey_pos = 0 fkey:seek(0) end end for i = 0, (num_entries - 1) do siz:writeU8(xorB(csiz:readU8(), skey:readU8())) skey_pos = skey_pos + 1 if skey_pos == skey_size then skey_pos = 0 skey:seek(0) end end cfat:destroy() csiz:destroy() fkey:seek(0) skey:seek(0) print "Done." local o, m, s, f, size_high, size local fr = fat:readU32() local sr = siz:readU8() local index = {} for i = 1, (num_entries - 1) do m = fat:readU8() s = fat:readU8() f = fat:readU8() size_high = fat:readU8() sector = from_MSF(m, s, f) size = siz:readU8() + size_high * 256 if (sector ~= 4294967146) then log("Entry " .. i .. ", sector " .. sector .. ", nsectors = " .. size) index[i] = { sector = sector, size = size, cd = cdutil } end end fat:destroy() siz:destroy() return index, fkey, skey, fr, sr end function add_file(cindex, iso, file, i) local size_full = math.ceil(file:getsize() / 2048) local dest_sector = iso:putfile(file) local _, m, s, f = to_MSF(dest_sector) local size_high = math.floor(size_full / 256) local size = size_full - size_high * 256 log("Putting file " .. i .. " at " .. dest_sector .. " - size = " .. size_full) cindex.fat:wseek(i * 4) cindex.siz:wseek(i) cindex.fat:writeU8(m) cindex.fat:writeU8(s) cindex.fat:writeU8(f) cindex.fat:writeU8(size_high) cindex.siz:writeU8(size) end function close_index(cindex, iso) for i = cindex.fat:getsize(), (num_entries * 4 - 1) do cindex.fat:writeU8(0) end for i = cindex.siz:getsize(), (num_entries - 1) do cindex.siz:writeU8(0) end local fkey_pos = 0 local skey_pos = 0 local cfat = Buffer(true) local csiz = Buffer(true) cindex.fat:seek(0) cindex.siz:seek(0) cindex.fkey:seek(0) cindex.skey:seek(0) for i = 0, (num_entries * 4 - 1) do cfat:writeU8(xorB(cindex.fat:readU8(), cindex.fkey:readU8())) fkey_pos = fkey_pos + 1 if fkey_pos == fkey_size then fkey_pos = 0 cindex.fkey:seek(0) end end for i = 0, (num_entries - 1) do csiz:writeU8(xorB(cindex.siz:readU8(), cindex.skey:readU8())) skey_pos = skey_pos + 1 if skey_pos == skey_size then skey_pos = 0 cindex.skey:seek(0) end end iso:putfile(cfat, -1, 150) iso:putfile(csiz, -1, 160) cfat:destroy() csiz:destroy() end function psp_add_file(cindex, iso, file, i) local size_full = math.ceil(file:getsize() / 2048) local dest_sector = iso:putfile(file) cindex.index[i] = { size = size_fill, sector = dest_sector } log("Putting file " .. i .. " at " .. dest_sector .. " - size = " .. size_full) end function copyfile(path, name, dirtree, iso, cdutil) local dirent = cdutil:findpath(path .. "/" .. name) if not dirent then error("Failing finding path " .. path .. "/" .. name) end iso:createfile(dirtree, name, cdutil:cdfile(dirent), dirent):setbasicsxa() end function psp_close_index(cindex, iso, cdutil) local index_sec = iso:getdispsect() local indexfile = Buffer(true) local indexhead = Buffer(true) indexhead:write "MakePfs Version1.20" indexhead:writeU8(0) indexhead:writeU32(0) indexhead:writeU32(0) indexhead:writeU32(0) indexhead:writeU32(num_files) indexhead:writeU32(index_sec - pspval1_sec) indexhead:writeU32(0) for i = indexhead:getsize(), 2047 do indexhead:writeU8(0x98) end iso:putfile(indexhead, -1, pspval1_sec) indexfile:writeU32(1) local last_entry = nil for i = 1, num_files - 1 do if cindex.index[i] then last_entry = cindex.index[i].sector - pspval1_sec indexfile:writeU32(last_entry) else indexfile:writeU32(last_entry) end end local more_bytes = alignment(indexfile:getsize(), 2048) for i = 1, more_bytes do indexfile:writeU8(0x98) end iso:putfile(indexfile) psp_dirtrees.PSPVAL1.size = (iso:getdispsect() - pspval1_sec) * 2048 indexfile:destroy() indexhead:destroy() local cp = function(path, name, dirtree) copyfile(path, name, dirtree, iso, cdutil) end for _, f in ipairs { "Field_master.prx", "Camp_master.prx", "MiniMap_master.prx", "WldMap_master.prx", "GodCamp_master.prx", "moviepac.dat" } do cp("/PSP_GAME/USRDIR", f, psp_dirtrees.USRDIR) end end function prepare_index(iso, fkey, skey, fr, sr) if got_psp then return { add_file = psp_add_file, close_index = psp_close_index, index = { } } end local false_sect = {} for i = 1, 13 do iso:createsector(false_sect, MODE2_FORM1) end local ret = { fat = Buffer(true), siz = Buffer(true), fkey = fkey, skey = skey, add_file = add_file, close_index = close_index } ret.fat:writeU32(fr) ret.siz:writeU8(sr) return ret end