load "VP-map.lua" load "slz3-patch.lua" restrict = { [3613] = true, } --[[ dump_glyph = true ]]-- --dump_mode = true function dump_mkdir(dir) if dump_mode then mkdir(dir) end end globals = {} biggest_pad = 0 lookup_rooms = 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 startup(file_in, file_in2, iso_out) if not loadmodule then error("This can only be used with lua-interface...") end loadmodule "lualibs" loadmodule "luahandle" loadmodule "luacd" loadmodule "luaslz" loadmodule "luahttp" loadmodule "luaxml" globals[1] = cdabstract(file_in or "VP-SQUISH.bin") local cdutil = cdutils(globals[1]) if file_in2 then globals[2] = cdabstract(file_in2) local cdutil2 = cdutils(globals[2]) end return cdutil, cdutil2, iso_out end num_entries = 5120 fkey_size = 256 skey_size = 16 num_files = 4866 log_file = nil function log(str) print(str) log_file:write(str .. "\n") 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 load_index(cdutil) 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() 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 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 = Buffer(true) ucl_compress(single_file_out, single_file_compressed) 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() 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 function process_arcgfx(fname, h, size, ext) log("Processing " .. fname .. "." .. ext) if dump_mode then o = Output(fname .. "." .. ext) o:copyfrom(h, size) o:destroy() h:seek(-size, SEEK_CUR) end log("Extracting " .. fname .. " - format 'arcgfx'") dump_mkdir(fname) local nfiles = h:readU32() local extra = h:readU32() local ret if dump_mode then o = Output(fname .. "/--extra.bin") o:writeU32(extra) o:destroy() o = Output(fname .. string.format("/0000-%08X", extra)) o:writeU32(extra) o:destroy() else ret = Buffer(true) ret:writeU32(nfiles) ret:writeU32(extra) end index = {} for i = 1, nfiles do index[i] = {} index[i].extra = h:readU32() index[i].size = h:readU32() end local tell local outfile = {} for i = 1, nfiles do tell = h:tell() outfile[i] = process_single_file(fname .. string.format("/%04i-%08X", i, index[i].extra), h, index[i].size, ext) h:seek(tell + index[i].size) end if not dump_mode then for i = 1, nfiles do local alignment_bytes = alignment(outfile[i]:getsize(), 4) for j = 1, alignment_bytes do outfile[i]:writeU8(0) end ret:writeU32(index[i].extra) ret:writeU32(outfile[i]:getsize()) end for i = 1, nfiles do ret:copyfrom(outfile[i]) outfile[i]:destroy() end end -- return ret end function resolve_font(font) local r = {} for k, v in pairs(font) do local idx = v.Width .. "-" .. v.Data local g = glyphes[idx] if not g then error("Glyphe " .. idx .. " not found!") end r[k] = g.attr.Text end return r end function extract_font(fname, h) local n_glyphes = h:readU32() local height = h:readU32() local widths = {} for i = 1, n_glyphes do widths[i] = h:readU8() end local o local r = {} if dump_glyph then dump_mkdir(fname) end for i = 1, n_glyphes do if dump_mode and dump_glyph then o = Output(fname .. string.format("/%03i-%02i.glyph", i, widths[i])) o:copyfrom(h, height * 2) o:destroy() h:seek(-height * 2, SEEK_CUR) o = Output(fname .. string.format("/%03i-%02i.raw", i, widths[i])) local bits for j = 1, height do bits = h:readU16() for k = 1, height do -- should be widths[i] bits = shl(bits, 1) local bit = andB(bits, 65536) ~= 0 o:writeU8(bit and 0xff or 0) end end o:destroy() h:seek(-height * 2, SEEK_CUR) end local b = Buffer(true) b:copyfrom(h, height * 2) if widths[i] ~= 0 then r[i] = { Data = Base64Encode(b), Width = widths[i] } else -- Verify the strange behavior of "0-sized spaces" local Data = Base64Encode(b) if Data ~= "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" then error("Font not consistant.") end end b:destroy() end return r end function dump_special(script, code) if code == 0 then return "\n" elseif code == 1 then return "\n\n" elseif code == 3 then local speed = script:readU8() if speed == 255 then return '' else return '' end elseif code == 5 then return '' elseif code == 7 then local rep = script:readU8() if rep == 1 then return '' else return '' end elseif code == 8 then local siz = script:readU8() if siz == 1 then return '' else return '' end elseif code == 19 then local arg1, arg2 arg1 = script:readU8() arg2 = script:readU8() if arg1 == 255 and arg2 == 255 then return '' else return '' end elseif code == 14 then return '' elseif code == 4 then return '' else local a1, a2 if code == 3 or code == 4 or code == 7 or code == 8 or code == 14 then a1 = script:readU8() return '' elseif code == 6 or code == 12 or code == 17 or code == 19 then a1 = script:readU8() a2 = script:readU8() return '' else return '' end end error "Should not end up there" end function extract_char(script, lookup) local c = script:readU8() if c == 0 then return nil end if c >= 0x80 then c = (c - 0x80) + (script:readU8() * 128) end if c >= 0x4000 then return dump_special(script, c - 0x4000) else local l = lookup[c] if not l and not sloppy_extract then error("Lookup failed for character " .. c) end if not l then return '' else return l end end error "Should not end up there" end local all_txts = {} local all_sha1 = {} local all_origins = {} local current_file function get_txt_idx(txt) local sha1 = SHA1(txt) return all_sha1[sha1] end function add_txt_idx(txt) local idx idx = #all_txts + 1 local sha1 = SHA1(txt) all_sha1[sha1] = idx all_txts[idx] = { sha1 = sha1, txt = txt, } if all_origins[idx] then error("Something's inconsistant") end all_origins[idx] = "" .. (current_file - 3610) return idx end function process_ptrs(ptrs_contents, ptr_begin, ptr_end) local r = {} for i = ptr_begin, ptr_end do local idx = get_txt_idx(ptrs_contents[i]) if not idx then idx = add_txt_idx(ptrs_contents[i]) else if not all_origins[idx] then error("Something's inconsistant") end all_origins[idx] = all_origins[idx] .. "," .. (current_file - 3610) end r[i] = idx end return r end local 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 extract_script(fname, script, font, stype) log("Processing script " .. fname) dump_mkdir(fname) dump_mkdir(fname .. "/EXTRA") local font = extract_font(fname .. "/FONT", font) local lookup = resolve_font(font) local size_1 = script:readU32() local u1 = script:readU32() local u2 = script:readU32() local n_ptrs = script:readU32() local u3 = script:readU32() local u4 = script:readU32() local u5 = script:readU32() local o if dump_mode then o = Output(fname .. "/EXTRA/00-head1-" .. string.format("%08X-%08X", u1, u2) .. ".bin") o:writeU32(u1) o:writeU32(u2) o:destroy() o = Output(fname .. "/EXTRA/00-head2-" .. string.format("%08X-%08X-%08X", u3, u4, u5) .. ".bin") o:writeU32(u3) o:writeU32(u4) o:writeU32(u5) o:destroy() o = Output(fname .. "/EXTRA/01-head1.bin") o:writeU32(u1) o:writeU32(u2) o:destroy() o = Output(fname .. "/EXTRA/01-head2.bin") o:writeU32(u3) o:writeU32(u4) o:writeU32(u5) o:destroy() o = Output(fname .. "/EXTRA/02-part1.bin") o:copyfrom(script, size_1) o:destroy() end local ptrs = {} local ptr_start = 1 for i = 1, n_ptrs do ptrs[i] = script:readU16() end local ptrs_contents = {} local tell = script:tell() if stype == "room" then ptrs_contents[1] = "" ptrs_contents[2] = "" ptr_start = 3 elseif stype then error("Script type unknown: " .. stype) end if stype then local header = script_types[stype].header for i = 1, script_types[stype].size do if script:readU8() ~= header[i] then error("Script header file of type '" .. stype .. "' not according to its header") end end end for i = ptr_start, n_ptrs do ptrs_contents[i] = "" if tell + ptrs[i] ~= script:tell() then error("Script consistancy failure for pointer " .. i .. " - we're at " .. script:tell() .. " and " .. (tell + ptrs[i]) .. " was expected.") end while true do local r = extract_char(script, lookup) if not r then break end ptrs_contents[i] = ptrs_contents[i] .. r end end -- WARNING -- only for rooms local ptrs_idx = process_ptrs(ptrs_contents, ptr_start, n_ptrs) local o = Output(fname .. "-script.txt") if stype then o:write("template:" .. stype .. "\n") else o:write("notemplate\n") end for i = ptr_start, n_ptrs do o:write(ptrs_idx[i] .. "\n") end if stype == "room" then lookup_rooms:write(" [" .. current_file - 3610 .. "] = { ") for i = ptr_start, n_ptrs do lookup_rooms:write(ptrs_idx[i] .. ", ") end lookup_rooms:write "},\n" end end function add_glyph(font, char) local idx = font.idx font.ilookup[idx] = char font.clookup[char] = idx font.idx = font.idx + 1 return idx end function get_next_utf8(str) local ret = "" local n local b n = str:sub(1, 1) ret = ret .. n str = str:sub(2) b = n:byte() if b <= 0x7f then return ret, str end if b >= 0x80 and b <= 0xc1 then error("Wrong UTF-8 sequence.") end n = str:sub(1, 1) ret = ret .. n str = str:sub(2) if b <= 0xdf then return ret, str end n = str:sub(1, 1) ret = ret .. n str = str:sub(2) if b <= 0xef then return ret, str end n = str:sub(1, 1) ret = ret .. n str = str:sub(2) if b <= 0xf4 then return ret, str end error("Wrong UTF-8 sequence.") end function process_current_room_script() local script, font, scriptfile, fontfile, nptrs room_idx = current_file - 3610 if not rooms_lookup[room_idx] then return nil, nil end script = Buffer(true) scriptfile = Buffer(true) fontfile = Buffer(true) font = { idx = 1, ilookup = {}, clookup = {} } for k, v in ipairs(script_types.room.translated) do add_glyph(font, v) end for i = 1, script_types.room.size do script:writeU8(script_types.room.header[i]) end scriptfile:writeU16(0) scriptfile:writeU16(3) nptrs = 0 for pidx, pval in ipairs(rooms_lookup[room_idx]) do nptrs = nptrs + 1 local ptr = rooms_txts[pval] scriptfile:writeU16(script:getsize()) for k, v in ipairs(ptr) do if type(v) == "string" then local str = v local char local gidx while str:len() ~= 0 do char, str = get_next_utf8(str) gidx = font.clookup[char] or add_glyph(font, char) if gidx < 0x80 then script:writeU8(gidx) else local high = shl(gidx, 7) local low = andB(gidx, 127) + 0x80 script:writeU8(low) script:writeU8(high) end end elseif type(v) == "table" then local code = v[1] local high = 0x80 local low = 0x80 + code script:writeU8(low) script:writeU8(high) if v[2] then script:writeU8(v[2]) end if v[3] then script:writeU8(v[3]) end if v[4] then error "Wrong script..." end else error("Wrong script...") end end script:writeU8(0) end scriptfile:copyfrom(script) script:destroy() fontfile:writeU32(#font.ilookup) fontfile:writeU32(12) for _, glyph in ipairs(font.ilookup) do if not glyphes[glyph] then error("No glyph in database for " .. glyph) end fontfile:writeU8(glyphes[glyph].attr.Width) end for _, glyph in ipairs(font.ilookup) do Base64DecodeBin(glyphes[glyph].attr.Data, fontfile) end return scriptfile, fontfile, nptrs + 2 end function insert_script(old, new, nptrs) local size_1 = old:readU32() local u1 = old:readU32() local u2 = old:readU32() local n_ptrs = old:readU32() local u3 = old:readU32() local u4 = old:readU32() local u5 = old:readU32() local ret = Buffer(true) ret:writeU32(size_1) ret:writeU32(u1) ret:writeU32(u2) if nptrs ~= n_ptrs then error("Script inconsistancy! Got " .. nptrs .. " instead of " .. n_ptrs) end ret:writeU32(nptrs) ret:writeU32(u3) ret:writeU32(u4) ret:writeU32(u5) ret:copyfrom(old, size_1) ret:copyfrom(new) return ret end function process_arcroom(fname, h, size, ext) log("Processing " .. fname .. "." .. ext) local o if dump_mode then o = Output(fname .. "." .. ext) o:copyfrom(h, size) o:destroy() h:seek(-size, SEEK_CUR) end log("Extracting " .. fname .. " - format 'arcroom'") dump_mkdir(fname) local nfiles = h:readU32() local offset = h:readU32() if nfiles * 8 + 8 ~= offset then error("Bad archive format.") end local ret if not dump_mode then ret = Buffer(true) ret:writeU32(nfiles) ret:writeU32(offset) end index = {} for i = 1, nfiles do index[i] = {} index[i].ftype = h:readU32() index[i].size = h:readU32() end local tell local outfile = {} local script = nil local font = nil local nptrs if not dump_mode then script, font, nptrs = process_current_room_script() end for i = 1, nfiles do tell = h:tell() local handler = nil local counter = 1 if dump_mode and index[i].ftype == 4 then log("Preparing to dump script...") script = Buffer(true) font = Buffer(true) handler = function(fname, h, size, ext) if counter == 1 then log("Taking script...") script:copyfrom(h) elseif counter == 2 then log("Taking font...") font:copyfrom(h) else error("Too many files.") end counter = counter + 1 end elseif index[i].ftype == 4 and script and font then old_script = Buffer(true) handler = function(fname, h, size, ext) local ret if counter == 1 then log("Putting script...") ret = insert_script(h, script, nptrs) elseif counter == 2 then log("Putting font...") ret = Buffer(true) ret:copyfrom(font) else error("Too many files.") end counter = counter + 1 return ret end end outfile[i] = process_single_file(fname .. string.format("/%04i-%08X", i, index[i].ftype), h, index[i].size, "room", handler) if handler then if counter ~= 3 then error("Didn't get enough files; got " .. (counter - 1) .. " instead of 2.") end if dump_mode then extract_script(fname .. string.format("/%04i", i), script, font, "room") end script:destroy() font:destroy() end h:seek(tell + index[i].size) end if not dump_mode then for i = 1, nfiles do local alignment_bytes = alignment(outfile[i]:getsize(), 4) for j = 1, alignment_bytes do outfile[i]:writeU8(0) end ret:writeU32(index[i].ftype) ret:writeU32(outfile[i]:getsize()) end for i = 1, nfiles do ret:copyfrom(outfile[i]) outfile[i]:destroy() end end return ret end function do_dump(i) if not restrict then return true end return restrict[i] 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 prepare_index(iso, fkey, skey, fr, sr) 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 function process_files(index, map, iso, iso_full, cindex) 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 do_dump(i) file_out = file_in elseif not ftype then file_out = process_single_file("DUMP/" .. dir .. string.format("/%04i", i), file_in, file_in:getsize(), ext) elseif ftype == "arcgfx" then file_out = process_arcgfx("DUMP/" .. dir .. string.format("/%04i", i), file_in, file_in:getsize(), ext) elseif ftype == "arcroom" then file_out = process_arcroom("DUMP/" .. dir .. string.format("/%04i", i), file_in, file_in:getsize(), ext) else error("Unknow ftype: " .. ftype) 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 apply_hacks(hacks, file) local k, v, i, h for k, v in pairs(hacks) do for i, h in ipairs(v) do file[k + i - 1] = h end end end anti_cd_swap_hack = { [0x278C] = { 0x00, 0x00, 0x00, 0x00 }, [0x27A0] = { 0x00, 0x00, 0x00, 0x00 }, [0x27B4] = { 0x21, 0x10, 0x00, 0x00 }, [0x2820] = { 0x00, 0x00, 0x00, 0x00 }, } function build_basic(iso, cdutil, iso_full) local slusdirent = cdutil:findpath "/SLUS_011.56;1" or cdutil:findpath "/SLUS_011.79;1" or cdutil:findpath "/VALKYRIE.EXE;1" or error "Not a Valkyrie Profile US CD" iso:foreword(cdutil) local pvd = createpvd(cdutil) pvd.volid = "VP-FR" local root = iso:setbasics(pvd) local systemcnfstring = "BOOT=cdrom:\\VP-FR.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)) slus:seek(0) systemcnf:write(systemcnfstring) local dirent = cdutil:findpath("/SYSTEM.CNF;1") iso:createfile(root, "SYSTEM.CNF", systemcnf, dirent):setbasicsxa() if iso_full then apply_hacks(anti_cd_swap_hack, slus) end apply_hacks(slz3_patch, slus) slus:seek(0) iso:createfile(root, "VP-FR.EXE", slus, slusdirent):setbasicsxa() slus:seek(0) local readme = Buffer() readme:write("Readme...") 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 prepare_out(file_out) globals[3] = Output(file_out or "VP-FR.bin") local iso = isobuilder(globals[3]) return iso end function main(...) local cd, cd2, iso_out = startup(...) local false_sect = Buffer(true) false_sect:writeU8(0) local tglyphes = xml.LoadHandle(Input "VP-database.xml")[1] glyphes = {} for k, v in ipairs(tglyphes) do glyphes[v.attr.Width .. "-" .. v.attr.Data] = v glyphes[v.attr.Text] = v end dump_mkdir "DUMP" log_file = 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 for k, v in pairs(VP_maintypes) do dump_mkdir("DUMP/" .. v) end local iso_full = true for i = 1, (num_files - 1) do if not index[i] then iso_full = false end 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) 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) for i = 1, 148 do false_sect:seek(0) iso:putfile(false_sect, MODE2) end iso:close() end log("Biggest pad = " .. biggest_pad) log_file:destroy() end