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