function startup(file_in1, file_in2, file_out) local cdutil1, cdutil2, iso if loadmodule then loadmodule "lualibs" loadmodule "luahandle" loadmodule "luacd" iso_in1 = cdabstract(file_in1 or "VP-CD2.bin") cdutil1 = cdutils(iso_in1) iso_in2 = cdabstract(file_in2 or "VP-CD1.bin") cdutil2 = cdutils(iso_in2) iso_out = Output(file_out or "VP-SQUISH.bin") iso = isobuilder(iso_out) else error("VP-squish will only work with lua-interface.") end return cdutil1, cdutil2, iso end num_entries = 5120 fkey_size = 128 skey_size = 16 num_files = 4866 function load_index(cdutil) local vp_sec, cfat, csiz, fat, siz, fkey, skey, fkey_pos, skey_pos vp_sec = cdutil:findpath("/VALKYRIE.BIN;1").Sector 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() 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 index[i] = { sector = sector, size = size } end end fat:destroy() siz:destroy() return index, fkey, skey, fr, sr end function build_basic(iso, cdutil) local slusdirent = cdutil:findpath "/SLUS_011.56;1" or cdutil:findpath "/SLUS_011.79;1" or error "Ce n'est pas un CD de Valkyrie Profile US" iso:foreword(cdutil) local pvd = createpvd(cdutil) pvd.volid = "VP-FR" local root = iso:setbasics(pvd) local systemcnfstring = "BOOT=cdrom:\\VALKYRIE.EXE;1\r\nTCB=4\r\nEVENT=16\r\nSTACK=801fff00\r\n" local systemcnf = Buffer() local slus = Buffer(true) slus:copyfrom(cdutil:cdfile(slusdirent)) systemcnf:write(systemcnfstring) local dirent = cdutil:findpath("/SYSTEM.CNF;1") iso:createfile(root, "SYSTEM.CNF", systemcnf, dirent):setbasicsxa() slus:seek(0) iso:createfile(root, "VALKYRIE.EXE", slus, slusdirent):setbasicsxa() slus:seek(0) local readme = Buffer() readme:write("Valkyrie Profile squished iso.\r\nUse with caution.\r\n") iso:createfile(root, "README.TXT", readme, dirent):setbasicsxa() dirent = cdutil:findpath "/" root:setbasicsxa() root:fromdir(dirent) local cursect = iso:getdispsect() local falsesect = {} for i = cursect, 149 do iso:createsector(falsesect, MODE2_FORM1) end end function get_file(idx, cd1, cd2, index1, index2) local index, cd, scd = index1[idx], cd1, 'CD1' if not index then index, cd, scd = index2[idx], cd2, 'CD2' end if not index then error("Index " .. idx .. " doesn't exist in any CD.") end return cd:cdfile(index.sector, index.size * 2048), index.size, scd, index.sector end function merge_isos(iso, cd1, cd2, index1, index2, fkey, skey, fr1, fs1) local falsesect = {} for i = 1, 13 do iso:createsector(falsesect, MODE2_FORM1) end local fat = Buffer(true) local siz = Buffer(true) fat:writeU32(fr1) siz:writeU8(fs1) for i = 1, num_files do local file, size_full, scd, sector = get_file(i, cd1, cd2, index1, index2) 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 local str = "Putting file " .. i .. " at " .. dest_sector .. " from " .. scd .. ":" .. sector .. " - size = " .. size_full print(str) fat:writeU8(m) fat:writeU8(s) fat:writeU8(f) fat:writeU8(size_high) siz:writeU8(size) file:destroy() end for i = fat:getsize(), (num_entries * 4 - 1) do fat:writeU8(0) end for i = siz:getsize(), (num_entries - 1) do siz:writeU8(0) end local fkey_pos = 0 local skey_pos = 0 local cfat = Buffer(true) local csiz = Buffer(true) fat:seek(0) siz:seek(0) fkey:seek(0) skey:seek(0) for i = 0, (num_entries * 4 - 1) do cfat:writeU8(xorB(fat: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 csiz:writeU8(xorB(siz:readU8(), skey:readU8())) skey_pos = skey_pos + 1 if skey_pos == skey_size then skey_pos = 0 skey:seek(0) end end iso:putfile(cfat, -1, 150) iso:putfile(csiz, -1, 160) end function close_iso(iso) local falsesect = Buffer(true) falsesect:writeU8(0) for i = 1, 148 do falsesect:seek(0) iso:putfile(falsesect, MODE2) end iso:close() end function main(...) local cdutil1, cdutil2, iso = startup(...) local index1, fkey1, skey1, fr1, fs1 = load_index(cdutil1) local index2, fkey2, skey2, fr2, fs2 = load_index(cdutil2) build_basic(iso, cdutil1) merge_isos(iso, cdutil1, cdutil2, index1, index2, fkey1, skey1, fr1, fs1) close_iso(iso) end