From e94c37a627ccd242f63bb08fdb99039c2af58289 Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 14 Oct 2009 08:03:19 -0700 Subject: Initial import. --- VP-database.xml | 464 ++++++++++++++++++++++++++++++++++++++++++++++++++ VP-disasm.lua | 245 +++++++++++++++++++++++++++ VP-fontwork.lua | 93 ++++++++++ VP-indexwork.lua | 240 ++++++++++++++++++++++++++ VP-isowork.lua | 163 ++++++++++++++++++ VP-map.lua | 171 +++++++++++++++++++ VP-miscwork.lua | 59 +++++++ VP-process.lua | 305 +++++++++++++++++++++++++++++++++ VP-roomwork.lua | 499 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ VP-slz3-patch.lua | 33 ++++ VP-textwork.lua | 143 ++++++++++++++++ 11 files changed, 2415 insertions(+) create mode 100644 VP-database.xml create mode 100644 VP-disasm.lua create mode 100644 VP-fontwork.lua create mode 100644 VP-indexwork.lua create mode 100644 VP-isowork.lua create mode 100644 VP-map.lua create mode 100644 VP-miscwork.lua create mode 100644 VP-process.lua create mode 100644 VP-roomwork.lua create mode 100644 VP-slz3-patch.lua create mode 100644 VP-textwork.lua diff --git a/VP-database.xml b/VP-database.xml new file mode 100644 index 0000000..d72f328 --- /dev/null +++ b/VP-database.xml @@ -0,0 +1,464 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VP-disasm.lua b/VP-disasm.lua new file mode 100644 index 0000000..204b280 --- /dev/null +++ b/VP-disasm.lua @@ -0,0 +1,245 @@ +local function rd(self, addr) + self.fin:seek(addr * 4) + return self.fin:readU32() +end + +local function rdn(self) + local r = self:rd(self.PC) + self.PC = self.PC + 1 + return r +end + +local opcodes_names = { +-- 0x.0 0x.1 0x.2 0x.3 0x.4 0x.5 0x.6 0x.7 0x.8 0x.9 0x.a 0x.b 0x.c 0x.d 0x.e 0x.f + "SETV", "SETV", nil, nil, nil, nil, nil, nil, "MULG0","ADDG0","PSH", nil, nil, "PSH1?",nil, -- 0x0. + nil, nil, "PSH2?","PSHI", "CALL", "JMP", "JMPZ", "RET", "SETD", "PSH3?",nil, nil, nil, nil, nil, nil, -- 0x1. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x2. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x3. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x4. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x5. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x6. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0x7. + "STTRG",nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "SSTOP",nil, nil, nil, -- 0x8. + nil, nil, "TBOX", "TBOX2",nil, nil, nil, nil, "TBOX3",nil, nil, nil, nil, nil, "SETRM","CHGRM",-- 0x9. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xa. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xb. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xc. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xd. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xe. + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -- 0xf. +} + +local opcodes_imms = { +-- 0 1 2 3 4 5 6 7 8 9 a b c d e f + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 0 + 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, -- 1 + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, -- 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -- 3 + 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6 + 0, 2, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 7 + 3, 0, 1, 2, 0, 4, 1, 1, 1, 0, 2, 0, 1, 0, 0, 2, -- 8 + 0, 0, 3, 3, 3, 0, 0, 0, 3, 0, 0, 0, 0, 1, 1, 2, -- 9 + 2, 2, 1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -- a + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- b + 2, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -- c + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -- d + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- e + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- f +} + +-- 0 = nothing +-- 1 = low8 +-- 2 = low16 +-- 3 = low23 +-- 4 = high8 +-- 5 = var_idx +-- 6 = var_idx2 +-- 7 = low8 + high8 + +local opcodes_self_vals = { +-- 0 1 2 3 4 5 6 7 8 9 a b c d e f + 5, 5, 0, 0, 0, 0, 0, 0, 3, 3, 5, 0, 0, 2, 0, -- 0 + 0, 0, 3, 0, 3, 3, 3, 0, 6, 0, 0, 0, 0, 0, 0, 0, -- 1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 7 + 2, 2, 2, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 2, 1, 0, -- 8 + 0, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 7, 2, 0, -- 9 + 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, -- a + 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, -- b + 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- c + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- d + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- f +} + +local opcodes_nparams = { +-- 0 1 2 3 4 5 6 7 8 9 a b c d e f + 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 1, 0, -- 0 + 0, 0, 1, 1, 1, 1, 2, 0, 2, 1, 1, 0, 0, 0, 0, 0, -- 1 + 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, -- 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, -- 3 + 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6 + 0, 0, 1, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, -- 7 + 4, 1, 2, 4, 0, 5, 2, 2, 2, 0, 3, 0, 1, 1, 1, 5, -- 8 + 0, 0, 7, 7, 6, 0, 0, 0, 7, 0, 0, 0, 0, 3, 2, 4, -- 9 + 6, 2, 2, 6, 0, 0, 0, 0, 2, 1, 0, 1, 0, 0, 0, 0, -- a + 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, -- b + 2, 0, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, -- c + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 0, 0, 1, 0, 0, -- d + 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, -- e + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- f +} + +local opcodes_known = { +-- 0 1 2 3 4 5 6 7 8 9 a b c d e f + true, true, false, false, false, false, false, false, true, true, true, false, false, true, false, -- 0 + false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, -- 1 + false, true, true, true, true, true, true, true, true, true, true, false, false, false, true, false, -- 2 + false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, -- 3 + false, true, true, true, true, true, false, false, false, true, false, false, false, false, false, false, -- 4 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 5 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 6 + true, true, true, true, true, true, true, false, true, false, false, true, true, false, true, false, -- 7 + true, true, true, true, false, true, true, true, true, true, true, false, true, true, true, true, -- 8 + false, true, true, true, true, false, false, false, true, false, false, false, false, true, true, true, -- 9 + true, true, true, true, false, false, false, false, true, true, false, true, false, false, false, false, -- a + true, false, true, false, false, false, false, false, true, false, false, true, false, false, true, false, -- b + true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, -- c + false, false, false, false, false, false, false, false, false, true, true, false, false, true, true, false, -- d + true, false, false, false, false, false, true, false, false, false, false, true, false, false, false, false, -- e + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- f +} + +local opcodes_fromstack = { +-- 0 1 2 3 4 5 6 7 8 9 a b c d e f + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 0 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 1 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 2 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 3 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 4 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 5 + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- 6 + false, true, true, true, false, true, false, false, false, false, false, false, false, false, false, false, -- 7 + true, true, true, true, false, true, true, true, true, false, true, false, true, false, true, true, -- 8 + false, false, true, true, true, false, false, false, true, false, false, false, false, true, true, true, -- 9 + true, true, true, true, false, false, false, false, true, true, false, true, false, false, false, false, -- a + false, false, true, false, false, false, false, false, false, false, false, true, false, false, false, false, -- b + true, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, -- c + false, false, false, false, false, false, false, false, false, true, true, false, false, true, false, false, -- d + false, false, false, false, false, false, true, false, false, false, false, true, false, false, false, false, -- e + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, -- f +} + +local function disasm_opcode(self) + self.oPC = self.PC + self.opcode = self:rdn() + self.code = shr(self.opcode, 24) + self.imm8 = andB(self.opcode, 0xff) + self.imm16 = andB(self.opcode, 0xffff) + self.imm23 = andB(self.opcode, 0x7fffff) + self.high8 = andB(shr(self.opcode, 8), 0xff) + self.idx2 = shr(shl(self.opcode, 9), 12) + self.flags = {} + self.flags.is_local = andB(self.opcode, 0x800000) ~= 0 + self.flags.from_stack = andB(self.opcode, 0x100000) ~= 0 + + self.out:write(string.format("%08X %08X ", self.oPC, self.opcode)) + + if self.code == 0 then + self.out:write("OPCODE00?!") + return + end + + local name = opcodes_names[self.code] + + if name then + self.out:write(string.format("%-8s", name)) + elseif opcodes_known[self.code] then + self.out:write(string.format("OP_%02X ", self.code)) + else + self.out:write(string.format("UNK%02X ", self.code)) + end + + if self.flags.from_stack and opcodes_fromstack[self.code] then + for i = 1, opcodes_nparams[self.code] do + self.out:write("POP()") + if i ~= opcodes_nparams[self.code] then self.out:write(", ") end + end + else + local nargs = opcodes_nparams[self.code] + local sv = opcodes_self_vals[self.code] + if false then + -- 0 = nothing + -- 1 = low8 + -- 2 = low16 + -- 3 = low23 + -- 4 = high8 + -- 5 = var_idx + -- 6 = var_idx2 + -- 7 = low8 + high8 + elseif sv == 1 then + self.out:write(string.format("%02X", self.imm8)) + nargs = nargs - 1 + elseif sv == 2 then + self.out:write(string.format("%04X", self.imm16)) + nargs = nargs - 1 + elseif sv == 3 then + self.out:write(string.format("%08X", self.imm23)) + nargs = nargs - 1 + elseif sv == 4 then + self.out:write(string.format("%02X", self.high8)) + nargs = nargs - 1 + elseif sv == 5 then + self.out:write(string.format("%s[%04X]", self.flags.is_local and "locl" or "glbl", self.imm16)) + nargs = nargs - 1 + elseif sv == 6 then + self.out:write(string.format("%s[%04X]", self.flags.is_local and "locl" or "glbl", self.idx2)) + nargs = nargs - 1 + elseif sv == 7 then + self.out:write(string.format("%02X, %02X", self.imm8, self.high8)) + nargs = nargs - 2 + end + + if sv ~= 0 and nargs ~= 0 then + self.out:write(", ") + end + + for i = 1, opcodes_imms[self.code] do + self.out:write(string.format("%08X", self:rdn())) + if i ~= opcodes_imms[self.code] then self.out:write(", ") end + nargs = nargs - 1 + end + + if not opcodes_fromstack[self.code] then + for i = 1, nargs do + self.out:write("POP()") + if i ~= nargs then self.out:write(", ") end + end + end + end + + if self.hooks[self.code] then self.hooks[self.code](self.oPC) end +end + +local function disasm(self) + while self.PC ~= self.EPC do + self:disasm_opcode() + self.out:write("\n") + for padPC = self.oPC + 1, self.PC - 1 do + self.out:write(string.format(" %08X\n", self:rd(padPC))) + end + end +end + +function logic_disasm(logic, o, hooks) + local dobj = { rd = rd, rdn = rdn, disasm_opcode = disasm_opcode, disasm = disasm, PC = 0, fin = logic, out = o, EPC = logic:getsize() / 4, hooks = hooks } + dobj:disasm() +end diff --git a/VP-fontwork.lua b/VP-fontwork.lua new file mode 100644 index 0000000..4029227 --- /dev/null +++ b/VP-fontwork.lua @@ -0,0 +1,93 @@ +function put_extra_glyph(width, data) + local idx = width .. "-" .. data + if not extra_glyphs_file then extra_glyphs_file = Output "extra-glyphs.xml" end + if extra_glyphs[idx] then return end + extra_glyphs_file:write(' \n') + extra_glyphs[idx] = true +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 + put_extra_glyph(v.Width, v.Data) + r[k] = "" + else + r[k] = g.attr.Text + end + 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 this is only padding + local Data = Base64Encode(b) + if Data ~= "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" then + error("Font not consistant.") + end + end + b:destroy() + end + + return r +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 load_glyphes() + 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 +end diff --git a/VP-indexwork.lua b/VP-indexwork.lua new file mode 100644 index 0000000..a6bc08c --- /dev/null +++ b/VP-indexwork.lua @@ -0,0 +1,240 @@ +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 diff --git a/VP-isowork.lua b/VP-isowork.lua new file mode 100644 index 0000000..4b9efb2 --- /dev/null +++ b/VP-isowork.lua @@ -0,0 +1,163 @@ +load "VP-slz3-patch.lua" + +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 + +function prepare_out(file_out) + if got_psp then + local x = Output "VP-FR.iso" + x:destroy() + globals[3] = dvdabstract(file_out or "VP-FR.iso", true) + else + globals[3] = Output(file_out or "VP-FR.bin") + end + local iso = isobuilder(globals[3]) + return iso +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") + globals[1] = dvdabstract(file_in or "VP-PSP-EUR.iso") + 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 + +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 iso_identify(cdutil) + local slusdirentuscd1 = cdutil:findpath "/SLUS_011.56;1" + local slusdirentuscd2 = cdutil:findpath "/SLUS_011.79;1" + local slusdirentjpcd1 = cdutil:findpath "/SLPM_863_79;1" + local slusdirentjpcd2 = cdutil:findpath "/SLPM_863_80;1" + local slusdirentsquished = cdutil:findpath "/VALKYRIE.EXE;1" + local pspdata = cdutil:findpath "/UMD_DATA.BIN" + if pspdata then + local pspdataf = cdutil:cdfile(pspdata) + local umddata = pspdataf:read() + if umddata == "ULUS-10107|400F6E7A41D6C586|0001|G" then + got_us = true + elseif umddata == "ULES-00724|2A9CD5DEEA986357|0001|G" then + got_eu = true + elseif umddata == "ULJM-05101|7862BF3F2632E5B5|0001|G" then + got_jp = true + else + error "Wrong PSP iso." + end + + got_psp = true + end + + if slusdirentuscd1 and got_cd1 then error "Got twice CD1." end + if slusdirentuscd2 and got_cd2 then error "Got twice CD2." end + + if slusdirentuscd1 or slusdirentuscd2 then got_us = true end + if slusdirentjpcd1 or slusdirentjpcd2 then got_jp = true end + if slusdirentuscd1 or slusdirentjpcd1 then got_cd1 = true end + if slusdirentuscd2 or slusdirentjpcd2 then got_cd2 = true end + + if slusdirentsquished then + got_cd1 = true + got_cd2 = true + -- let's fallback... + got_us = true + end + + if not slusent then + slusent = slusdirentuscd1 or slusdirentuscd2 or slusdirentjpcd1 or slusdirentjpcd2 or slusdirentsquished + end + + if got_us and got_jp then error "2 isos must from the same version of the game." end +end + +function build_basic(iso, cdutil, iso_full) + local cp = function(path, name, dirtree) copyfile(path, name, dirtree, iso, cdutil) end + iso:foreword(cdutil) + local pvd = createpvd(cdutil) + pvd.volid = "VP-FR" + local root = iso:setbasics(pvd) + dirent = cdutil:findpath "/" + root:setbasicsxa() + root:fromdir(dirent) + if got_psp then + root:setdvdmode() + psp_dirtrees.root = root + psp_dirtrees.PSP_GAME = iso:createdir(root, "PSP_GAME", 1, cdutil:findpath "/PSP_GAME") + psp_dirtrees.PSP_GAME:setbasicsxa() + psp_dirtrees.SYSDIR = iso:createdir(psp_dirtrees.PSP_GAME, "SYSDIR", 1, cdutil:findpath "/PSP_GAME/SYSDIR") + psp_dirtrees.SYSDIR:setbasicsxa() + psp_dirtrees.USRDIR = iso:createdir(psp_dirtrees.PSP_GAME, "USRDIR", 1, cdutil:findpath "/PSP_GAME/USRDIR") + psp_dirtrees.USRDIR:setbasicsxa() +--[[ + psp_dirtrees.kmodule = iso:createdir(psp_dirtrees.USRDIR, "kmodule", 1, cdutil:findpath "/PSP_GAME/USRDIR/kmodule") + psp_dirtrees.kmodule:setbasicsxa() +--]] + cp("", "UMD_DATA.BIN", root) + cp("/PSP_GAME/SYSDIR", "EBOOT.BIN", psp_dirtrees.SYSDIR) + cp("/PSP_GAME/SYSDIR", "BOOT.BIN", psp_dirtrees.SYSDIR) + for _, f in ipairs { "PARAM.SFO", "ICON0.PNG", "PIC0.PNG", "PIC1.PNG" } do + cp("/PSP_GAME", f, psp_dirtrees.PSP_GAME) + end +--[[ + for _, prx in ipairs { "audiocodec.prx", "libatrac3plus.prx", "mpeg.prx", "mpegbase.prx", "psmf.prx", "sc_sascore.prx", "videocodec.prx" } do + cp("/PSP_GAME/USRDIR/kmodule", prx, psp_dirtrees.kmodule) + end +]]-- + for _, prx in ipairs { "Title_master.prx", "Staff_master.prx", "Battle_master.prx" } do + cp("/PSP_GAME/USRDIR", prx, psp_dirtrees.USRDIR) + end + pspval1_sec = iso:getdispsect() + local dummy = Buffer() + dummy:writeU8(0) + local dirent = cdutil:findpath "/PSP_GAME/USRDIR/PSPVAL1.PFS" + psp_dirtrees.PSPVAL1 = iso:createfile(psp_dirtrees.USRDIR, "PSPVAL1.PFS", dummy, dirent) + psp_dirtrees.PSPVAL1:setbasicsxa() + dummy:destroy() + else + 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() + local cursect = iso:getdispsect() + local falsesect = {} + for i = cursect, 149 do + iso:createsector(falsesect, MODE2_FORM1) + end + end +end diff --git a/VP-map.lua b/VP-map.lua new file mode 100644 index 0000000..415ca97 --- /dev/null +++ b/VP-map.lua @@ -0,0 +1,171 @@ +VP_maintypes = { + "VIDEOS", + "SOUNDS", + "GFX", + "MAIN", + "GAME", +} + +VP_map = { } + +VP_map_spans = { + { idx_s = 3604, idx_e = 4732, data = { dir = "GAME/ROOMS", ext = "arm", ftype = "arcroom", }, }, +} + +VP_map_spans = { + { idx_s = 3721, idx_e = 4849, data = { dir = "GAME/ROOMS", ext = "arm", ftype = "arcroom", }, }, +} + +VP_map_spans = { + { idx_s = 9, idx_e = 131, data = { dir = "SOUNDS/ATK+DEATH", ext = "wag" }, }, + { idx_s = 132, idx_e = 365, data = { dir = "SOUNDS/SUMMONS+NAMES", ext = "wag" }, }, + { idx_s = 366, idx_e = 417, data = { dir = "SOUNDS/FINISH", ext = "wag" }, }, + { idx_s = 418, idx_e = 617, data = { dir = "SOUNDS/ENDS", ext = "wag" }, }, + { idx_s = 619, idx_e = 897, data = { dir = "SOUNDS/FAILED+MAGICS", ext = "wag" }, }, + { idx_s = 898, idx_e = 1020, data = { dir = "SOUNDS/BOSS", ext = "wag" }, }, + { idx_s = 1022, idx_e = 1525, data = { dir = "GFX/FRIENDS+FOES", ext = "agx", ftype = "arcgfx" }, }, + { idx_s = 1526, idx_e = 1637, data = { dir = "SOUNDS/COMBATTALKS", ext = "wag" }, }, + { idx_s = 1639, idx_e = 1661, data = { dir = "GFX/UNKNOWN01", ext = "agx", ftype = "arcgfx", }, }, + { idx_s = 1662, idx_e = 1687, data = { dir = "SOUNDS/UNKNOWN01", ext = "wag" }, }, + { idx_s = 1688, idx_e = 1698, data = { dir = "GFX/UNKNOWN02", ext = "agx", ftype = "arcgfx", }, }, + { idx_s = 1700, idx_e = 1704, data = { dir = "GFX/UNKNOWN03", ext = "agx", ftype = "arcgfx", }, }, + { idx_s = 1705, idx_e = 1805, data = { dir = "SOUNDS/UNKNOWN02", ext = "wag" }, }, + { idx_s = 1806, idx_e = 1810, data = { dir = "GFX/UNKNOWN04", ext = "agx", ftype = "arcgfx", }, }, + { idx_s = 1811, idx_e = 1823, data = { dir = "SOUNDS/MAGIC01", ext = "wag" }, }, + { idx_s = 1826, idx_e = 1837, data = { dir = "SOUNDS/MAGIC02", ext = "wag" }, }, + { idx_s = 1840, idx_e = 1852, data = { dir = "SOUNDS/MAGIC03", ext = "wag" }, }, + { idx_s = 1855, idx_e = 1866, data = { dir = "SOUNDS/MAGIC04", ext = "wag" }, }, + { idx_s = 1869, idx_e = 1880, data = { dir = "SOUNDS/MAGIC05", ext = "wag" }, }, + { idx_s = 1883, idx_e = 1894, data = { dir = "SOUNDS/MAGIC06", ext = "wag" }, }, + { idx_s = 1897, idx_e = 1908, data = { dir = "SOUNDS/MAGIC07", ext = "wag" }, }, + { idx_s = 1911, idx_e = 1923, data = { dir = "SOUNDS/MAGIC08", ext = "wag" }, }, + { idx_s = 1926, idx_e = 1938, data = { dir = "SOUNDS/MAGIC09", ext = "wag" }, }, + { idx_s = 1941, idx_e = 1953, data = { dir = "SOUNDS/MAGIC10", ext = "wag" }, }, + { idx_s = 1956, idx_e = 1967, data = { dir = "SOUNDS/MAGIC11", ext = "wag" }, }, + { idx_s = 1970, idx_e = 1982, data = { dir = "SOUNDS/MAGIC12", ext = "wag" }, }, + { idx_s = 1985, idx_e = 1985, data = { dir = "SOUNDS/MAGIC13", ext = "wag" }, }, + { idx_s = 1988, idx_e = 2017, data = { dir = "GFX/UNKNOWN05", ext = "agx", ftype = "arcgfx", }, }, + { idx_s = 2018, idx_e = 2095, data = { dir = "SOUNDS/DEATHS", ext = "wag" }, }, + { idx_s = 2096, idx_e = 2097, data = { dir = "SOUNDS/UNKNOWN03", ext = "wag", }, }, + { idx_s = 2098, idx_e = 2172, data = { dir = "SOUNDS/VICTORY", ext = "wag", }, }, + + { idx_s = 3604, idx_e = 4732, data = { dir = "GAME/ROOMS", ext = "arm", ftype = "arcroom", }, }, + + { idx_s = 4766, idx_e = 4793, data = { dir = "GFX/CDCHANGE", ext = "tim" }, }, + { idx_s = 4808, idx_e = 4846, data = { dir = "GFX/PORTRAITS", ext = "tim" }, }, + { idx_s = 4847, idx_e = 4859, data = { dir = "GFX/BGX", ext = "tim" }, }, +} + +VP_map = { + [ 1] = { dir = "MAIN/OVERLAY" }, + [ 2] = { dir = "MISC", ext = "txt" }, + [ 3] = { dir = "MISC", ext = "txt" }, + [ 4] = { dir = "MAIN/SOUNDS", ext = "wag" }, + [ 5] = { dir = "MAIN/GFX" }, + + [ 618] = { dir = "SOUNDS/MISC", ext = "wag" }, + [1021] = { dir = "SOUNDS/MISC", ext = "wag" }, + + -- unknow file in the middle of gfx bloc - is it an overlay ? + [1490] = { }, + + [1824] = { dir = "GFX/MAGIC01", ext = "agx", ftype = "arcgfx", }, + [1838] = { dir = "GFX/MAGIC02", ext = "agx", ftype = "arcgfx", }, + [1853] = { dir = "GFX/MAGIC03", ext = "agx", ftype = "arcgfx", }, + [1867] = { dir = "GFX/MAGIC04", ext = "agx", ftype = "arcgfx", }, + [1881] = { dir = "GFX/MAGIC05", ext = "agx", ftype = "arcgfx", }, + [1895] = { dir = "GFX/MAGIC06", ext = "agx", ftype = "arcgfx", }, + [1909] = { dir = "GFX/MAGIC07", ext = "agx", ftype = "arcgfx", }, + [1924] = { dir = "GFX/MAGIC08", ext = "agx", ftype = "arcgfx", }, + [1939] = { dir = "GFX/MAGIC09", ext = "agx", ftype = "arcgfx", }, + [1954] = { dir = "GFX/MAGIC10", ext = "agx", ftype = "arcgfx", }, + [1968] = { dir = "GFX/MAGIC11", ext = "agx", ftype = "arcgfx", }, + [1983] = { dir = "GFX/MAGIC12", ext = "agx", ftype = "arcgfx", }, + [1986] = { dir = "GFX/MAGIC13", ext = "agx", ftype = "arcgfx", }, + +-- +-- Videos +-- + +-- Intro + [ 8] = { dir = "VIDEOS/MISC", ext = "str" }, +-- Magics + [1825] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1839] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1854] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1868] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1882] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1896] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1910] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1940] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1955] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1969] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1984] = { dir = "VIDEOS/MAGIC", ext = "str" }, + [1987] = { dir = "VIDEOS/MAGIC", ext = "str" }, +-- Small level videos + [3507] = { dir = "VIDEOS/LEVEL01", ext = "str" }, + [3509] = { dir = "VIDEOS/LEVEL02", ext = "str" }, + [3510] = { dir = "VIDEOS/LEVEL02", ext = "str" }, + [3512] = { dir = "VIDEOS/LEVEL03", ext = "str" }, + [3515] = { dir = "VIDEOS/LEVEL04", ext = "str" }, + [3516] = { dir = "VIDEOS/LEVEL04", ext = "str" }, + [3518] = { dir = "VIDEOS/LEVEL05", ext = "str" }, + [3521] = { dir = "VIDEOS/LEVEL06", ext = "str" }, + [3523] = { dir = "VIDEOS/LEVEL07", ext = "str" }, + [3525] = { dir = "VIDEOS/LEVEL08", ext = "str" }, + [3526] = { dir = "VIDEOS/LEVEL08", ext = "str" }, + [3527] = { dir = "VIDEOS/LEVEL08", ext = "str" }, + [3528] = { dir = "VIDEOS/LEVEL08", ext = "str" }, + [3530] = { dir = "VIDEOS/LEVEL09", ext = "str" }, + [3531] = { dir = "VIDEOS/LEVEL09", ext = "str" }, + [3532] = { dir = "VIDEOS/LEVEL09", ext = "str" }, + [3534] = { dir = "VIDEOS/LEVEL10", ext = "str" }, + [3535] = { dir = "VIDEOS/LEVEL10", ext = "str" }, + [3536] = { dir = "VIDEOS/LEVEL10", ext = "str" }, + [3537] = { dir = "VIDEOS/LEVEL10", ext = "str" }, + [3538] = { dir = "VIDEOS/LEVEL10", ext = "str" }, + [3541] = { dir = "VIDEOS/LEVEL11", ext = "str" }, + [3544] = { dir = "VIDEOS/LEVEL12", ext = "str" }, + [3547] = { dir = "VIDEOS/LEVEL13", ext = "str" }, + [3550] = { dir = "VIDEOS/LEVEL14", ext = "str" }, + [3553] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3554] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3555] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3556] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3557] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3558] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3559] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3560] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3561] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3562] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3563] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3564] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3565] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3566] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3567] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3568] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3569] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3570] = { dir = "VIDEOS/LEVEL15", ext = "str" }, + [3571] = { dir = "VIDEOS/LEVEL15", ext = "str" }, +-- Misc fullscreens + [3574] = { dir = "VIDEOS/MISC", ext = "str" }, + [3575] = { dir = "VIDEOS/MISC", ext = "str" }, + [3578] = { dir = "VIDEOS/MISC", ext = "str" }, + [4864] = { dir = "VIDEOS/MISC", ext = "str" }, + [4865] = { dir = "VIDEOS/MISC", ext = "str" }, + [4866] = { dir = "VIDEOS/MISC", ext = "str" }, +} + +VP_map_gen = {} + +for _, v in pairs(VP_map_spans) do + for i = v.idx_s, v.idx_e do + VP_map_gen[i] = v.data + end +end + +for k, v in pairs(VP_map) do + VP_map_gen[k] = v +end + +VP_map = VP_map_gen diff --git a/VP-miscwork.lua b/VP-miscwork.lua new file mode 100644 index 0000000..31f7e92 --- /dev/null +++ b/VP-miscwork.lua @@ -0,0 +1,59 @@ +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 + diff --git a/VP-process.lua b/VP-process.lua new file mode 100644 index 0000000..c4f65e2 --- /dev/null +++ b/VP-process.lua @@ -0,0 +1,305 @@ +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" + +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 + +slusent = nil +got_cd1 = false +got_cd2 = false +got_us = false +got_jp = false +got_psp = false +pspval1_sec = nil +psp_dirtrees = {} + +all_txts = {} +all_sha1 = {} +all_origins = {} + +current_file = nil + +extra_glyphs_file = nil +extra_glyphs = {} + +globals = {} + +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) + 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 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) + 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) then + 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 main(...) + local cd, cd2, iso_out = startup(...) + iso_identify(cd) + if cd2 then iso_identify(cd2) end + local false_sect = Buffer(true) + false_sect:writeU8(0) + load_glyphes() + 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, 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 diff --git a/VP-roomwork.lua b/VP-roomwork.lua new file mode 100644 index 0000000..d1eabfe --- /dev/null +++ b/VP-roomwork.lua @@ -0,0 +1,499 @@ +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() + + local npadding = alignment(#font.ilookup, 4) + + fontfile:writeU32(#font.ilookup + npadding) + 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 i = 1, npadding do + fontfile:writeU8(0) + end + + for _, glyph in ipairs(font.ilookup) do + Base64DecodeBin(glyphes[glyph].attr.Data, fontfile) + end + for i = 1, npadding do + for j = 1, 6 do fontfile:writeU32(0) end + 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) + if got_us and current_file == (3610 + 125) and activate_debug_room then + ret:copyfrom(old, 0x1158 * 4) + ret:writeU32(0x9e000000) + old:readU32() + ret:copyfrom(old, size_1 - 0x1159 * 4) + else + ret:copyfrom(old, size_1) + end + 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("Processing " .. 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_room_script(fname .. string.format("/%04i", i), script, font) + 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 + +room_logic_check = { + [0x0090] = { 0x18000000, 0x00000008 }, [0x009B] = { 0x98100000, 0x17000000 }, + [0x033C] = { 0x18000000, 0x0000002C }, [0x03BC] = { 0x92100000, 0x150003E1 }, [0x03C7] = { 0x94100000, 0x150003E1 }, [0x03D3] = { 0x93100000, 0x150003E1 }, [0x03DF] = { 0x92100000, 0x150003E1 }, + [0x03E2] = { 0x18000000, 0x00000018 }, [0x03F0] = { 0x1400033C, 0x7E000000 }, + [0x03F5] = { 0x18000000, 0x00000018 }, [0x0403] = { 0x1400033C, 0x7E000000 }, + [0x0408] = { 0x18000000, 0x00000018 }, [0x0416] = { 0x1400033C, 0x7E000000 }, +-- [0x041B] = { 0x18000000, 0x00000020 }, [0x042B] = { 0x1400033C, 0x7E000000 }, +-- [0x0432] = { 0x18000000, 0x00000020 }, [0x0442] = { 0x1400033C, 0x7E000000 }, +-- [0x0449] = { 0x18000000, 0x00000020 }, [0x0459] = { 0x1400033C, 0x7E000000 }, +} + +function check_opcode(script, PC, supposed) + script:seek(PC * 4) + local r = script:readU32() + if r ~= supposed then error(string.format("Error for script: opcode %04X is %08X but was supposed to be %08X", PC, r, supposed)) end +end + +function check_room_logic(script) + for offset, v in pairs(room_logic_check) do + local PC = offset - 1 + for suboffset, supposed in ipairs(v) do + check_opcode(script, PC + suboffset, supposed) + end + end +end + +function extract_room_script(fname, script, font) + 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 logic_offset = script:readU32() + local u1 = script:readU32() + local n_ptrs = script:readU32() + local u3 = script:readU32() + local u4 = script:readU32() + local u5 = script:readU32() + + if logic_offset ~= 0 then error("Unhandled logic offset " .. logic_offset) end + + local o + o = Output(fname .. "/EXTRA/00-head1-" .. string.format("%08X", u1) .. ".bin") + o:writeU32(u1) + 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: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() + script:seek(-size_1, SEEK_CUR) + local logic = Buffer(true) + logic:copyfrom(script, size_1) + + local ptrs = {} + local ptr_start = 1 + + for i = 1, n_ptrs do + ptrs[i] = script:readU16() + end + + local ptrs_contents, ptrs_raws = {}, {} + local tell = script:tell() + ptrs_contents[1] = "" + ptrs_contents[2] = "" + ptrs_raws[1] = "" + ptrs_raws[2] = "" + ptr_start = 3 + + local header = script_types.room.header + for i = 1, script_types.room.size do + if script:readU8() ~= header[i] then error("Script header file of type 'room' not according to its header") end + end + + for i = ptr_start, n_ptrs do + ptrs_contents[i] = "" + ptrs_raws[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, rr = extract_char(script, lookup) + if not r then break end + ptrs_contents[i] = ptrs_contents[i] .. r + ptrs_raws[i] = ptrs_raws[i] .. rr + end + end + + o = Output(fname .. "/EXTRA/logic.txt") + check_room_logic(logic) + local textboxes = { } + local rd_opcode = function(PC) + logic:seek(PC * 4) + return logic:readU32() + end + local add_textbox = function(txtptr, txtbox) + if txtptr < 0 then return end + o:write("\n") + if ptrs_raws[txtptr + ptr_start] then + o:write(ptrs_raws[txtptr + ptr_start]) + if textboxes[txtptr + ptr_start] then + o:write("\n****SUSPECT****PTR ALREADY RECORDED****: " .. (txtptr + ptr_start)) + end + textboxes[txtptr + ptr_start] = txtbox + else + error("****SUSPECT****PTR TOO LARGE****: " .. (txtptr + ptr_start)) + end + end + local txt_process = function(PC) + local opcode = rd_opcode(PC) + local txtptr + local x, y, width, height + if andB(opcode, 0x00100000) ~= 0 then + local psh1 = rd_opcode(PC - 1) + local psh2 = rd_opcode(PC - 2) + local psh3 = rd_opcode(PC - 3) + local psh4 = rd_opcode(PC - 4) + local psh5 = rd_opcode(PC - 5) + local psh6 = rd_opcode(PC - 6) + + if andB(psh1, 0xff000000) ~= 0x12000000 then return end + if andB(psh2, 0xff000000) ~= 0x12000000 then return end + if andB(psh3, 0xff000000) ~= 0x12000000 then return end + if andB(psh4, 0xff000000) ~= 0x12000000 then return end + if andB(psh5, 0xff000000) ~= 0x12000000 then return end + if andB(psh6, 0xff000000) ~= 0x12000000 then return end + + local arg1 = andB(psh1, 0x7fffff) + local arg2 = andB(psh2, 0x7fffff) + local arg3 = andB(psh3, 0x7fffff) + local arg4 = andB(psh4, 0x7fffff) + local arg5 = andB(psh5, 0x7fffff) + local arg6 = andB(psh6, 0x7fffff) + + txtptr = arg6 + 1 - ptr_start + + x = arg5 + y = arg4 + width = arg3 + height = arg2 + else + txtptr = andB(opcode, 0xff) + 1 - ptr_start + local arg1 = rd_opcode(PC + 1) + local arg2 = rd_opcode(PC + 2) + x = andB(arg1, 0xffff) + y = shr(arg1, 16) + width = andB(arg2, 0xffff) + height = shr(arg2, 16) + end + add_textbox(txtptr, { + x = x, + y = y, + width = width, + height = height, + }) + end + local process_subtxt = function(PC) + local psh1 = rd_opcode(PC - 1) + local psh2 = rd_opcode(PC - 2) + local psh3 = rd_opcode(PC - 3) + local psh4 = rd_opcode(PC - 4) + local psh5 = rd_opcode(PC - 5) + local psh6 = rd_opcode(PC - 6) + + if andB(psh1, 0xff000000) ~= 0x12000000 and andB(psh1, 0xff000000) ~= 0x0B000000 then return end + if andB(psh2, 0xff000000) ~= 0x12000000 then return end + if andB(psh3, 0xff000000) ~= 0x12000000 and andB(psh3, 0xff000000) ~= 0x0B000000 then return end + if andB(psh4, 0xff000000) ~= 0x12000000 and andB(psh4, 0xff000000) ~= 0x0B000000 then return end + if andB(psh5, 0xff000000) ~= 0x12000000 and andB(psh5, 0xff000000) ~= 0x0B000000 then return end + if andB(psh6, 0xff000000) ~= 0x12000000 and andB(psh6, 0xff000000) ~= 0x0B000000 then return end + + local arg1 = andB(psh1, 0x7fffff) + local arg2 = andB(psh2, 0x7fffff) + local arg3 = andB(psh3, 0x7fffff) + local arg4 = andB(psh4, 0x7fffff) + local arg5 = andB(psh5, 0x7fffff) + local arg6 = andB(psh6, 0x7fffff) + + if andB(psh1, 0xff000000) == 0x0B000000 then arg1 = nil end + if andB(psh3, 0xff000000) == 0x0B000000 then arg3 = nil end + if andB(psh4, 0xff000000) == 0x0B000000 then arg4 = nil end + if andB(psh5, 0xff000000) == 0x0B000000 then arg5 = nil end + if andB(psh6, 0xff000000) == 0x0B000000 then arg6 = nil end + + local txtptr = arg2 + 1 - ptr_start + add_textbox(txtptr, { + x = arg6 or "var", + y = arg5 or "var", + width = arg4 or "var", + height = arg3 or "var", + }) + end + local process_subtxt2 = function(PC) + local psh1 = rd_opcode(PC - 1) + local psh2 = rd_opcode(PC - 2) + local psh3 = rd_opcode(PC - 3) + local psh4 = rd_opcode(PC - 4) + local psh5 = rd_opcode(PC - 5) + + if andB(psh1, 0xff000000) ~= 0x12000000 then return end + if andB(psh2, 0xff000000) ~= 0x0B000000 then return end + if andB(psh3, 0xff000000) ~= 0x22000000 then return end + if andB(psh4, 0xff000000) ~= 0x0B000000 then return end + if andB(psh5, 0xff000000) ~= 0xCB000000 then return end + + local txtptr = andB(psh5, 0xff) + 1 - ptr_start + add_textbox(txtptr, { + typ = "fixed", + }) + end + local call_process = function(PC) + local opcode = rd_opcode(PC) + if opcode == 0x1400033C or opcode == 0x140003E2 or opcode == 0x140003F5 or opcode == 0x14000408 then process_subtxt(PC) end + if opcode == 0x14000090 then process_subtxt2(PC) end + end + logic_disasm(logic, o, { + -- ret + [0x17] = function(PC) o:write("\n-----------------------------------------------------\n") end, + -- txtbox1 + [0x92] = txt_process, + -- txtbox2 + [0x93] = txt_process, + -- txtbox3 + [0x94] = txt_process, + -- txtbox4 + [0x98] = txt_process, + -- *sigh* + [0x14] = call_process, + } ) + + o:destroy() + logic:destroy() + + for i = ptr_start, n_ptrs do + if textboxes[i] then + local tb = textboxes[i] + if tb.typ == "fixed" then + ptrs_contents[i] = '\n' .. ptrs_contents[i] + elseif tb.typ == "auto" then + ptrs_contents[i] = '\n' .. ptrs_contents[i] + else + ptrs_contents[i] = '\n' .. ptrs_contents[i] + end + else + ptrs_contents[i] = '\n' .. ptrs_contents[i] + end + end + + -- WARNING -- only for rooms + local ptrs_idx = process_ptrs(ptrs_contents, ptr_start, n_ptrs) + + local o = Output(fname .. "-script.txt") + o:write("template:room\n") + + for i = ptr_start, n_ptrs do + o:write(ptrs_idx[i] .. "\n") + end + + lookup_rooms:write(" [" .. current_file - 3610 .. "] = { ") + for i = ptr_start, n_ptrs do + lookup_rooms:write(ptrs_idx[i] .. ", ") + end + lookup_rooms:write "},\n" + + o:destroy() +end diff --git a/VP-slz3-patch.lua b/VP-slz3-patch.lua new file mode 100644 index 0000000..cebcddc --- /dev/null +++ b/VP-slz3-patch.lua @@ -0,0 +1,33 @@ +slz3_patch = { + [0x002b5c] = { 0xe7, 0x48, 0x00, 0x08, 0x21, 0x20, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + [0x002b6b] = { 0x00 }, + [0x002b9c] = { 0x21, 0x28, 0x00, 0x02, 0x03 }, + [0x002ba3] = { 0x92, 0xd6, 0xab }, + [0x01b500] = { 0x21, 0xc8, 0xe0, 0x03, 0x21, 0x40, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x24, 0xff, 0x00, 0x0e, 0x3c, + 0x46, 0x00, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0xe0, 0x11, 0x01, 0x00, 0x0b, 0x24, + 0x00, 0x00, 0x89, 0x90, 0x01, 0x00, 0x84, 0x24, 0x00, 0x00, 0xa9, 0xa0, 0xf8, 0xff, 0x00, 0x10, + 0x01, 0x00, 0xa5, 0x24, 0x3d, 0x00, 0x11, 0x04, 0x40, 0x58, 0x0b, 0x00, 0x3b, 0x00, 0x11, 0x04, + 0x21, 0x58, 0x6f, 0x01, 0x05, 0x00, 0xe0, 0x15, 0xff, 0xff, 0x6b, 0x25, 0x37, 0x00, 0x11, 0x04, + 0x40, 0x58, 0x0b, 0x00, 0xf7, 0xff, 0x00, 0x10, 0x21, 0x58, 0x6f, 0x01, 0xff, 0xff, 0x6b, 0x25, + 0x05, 0x00, 0x60, 0x15, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x11, 0x04, 0x21, 0x58, 0x40, 0x01, + 0x0e, 0x00, 0x00, 0x10, 0x21, 0x60, 0xe0, 0x01, 0xff, 0xff, 0x6b, 0x25 }, + [0x01b57e] = { 0x89, 0x90, 0x00, 0x5a, 0x0b, 0x00, 0x01, 0x00, 0x84, 0x24, 0x21, 0x58, 0x69, 0x01, 0x01, 0x00, + 0x69, 0x25, 0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00, 0x08 }, + [0x01b59a] = { 0x20, 0x03, 0x01, 0x00, 0x2c, 0x31, 0x42, 0x58, 0x0b, 0x00, 0x01, 0x00, 0x6b, 0x25, 0x21, 0x50, + 0x60, 0x01, 0x1f }, + [0x01b5ae] = { 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x10, 0x03, 0x00, 0xec, 0x25, 0x0a, 0x00, 0xe0, 0x15, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x8c, 0x25, 0x16, 0x00, 0x11, 0x04, 0x40, 0x60, 0x0c, 0x00, 0x14, 0x00, 0x11, 0x04, 0x21, 0x60, + 0x8f, 0x01, 0xfb, 0xff, 0xe0, 0x11, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10, 0x05, 0x00, + 0x8c, 0x25, 0x0e, 0x00, 0x11, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0xec, 0x25, 0x01, 0x05, + 0x69, 0x2d, 0x23, 0x60, 0x89, 0x01, 0x23, 0x68, 0xab, 0x00, 0x00, 0x00, 0xa9, 0x91, 0x01, 0x00, + 0xad }, + [0x01b610] = { 0x00, 0x00, 0xa9, 0xa0, 0x00, 0x00 }, + [0x01b618] = { 0xff, 0xff, 0x8c, 0x25, 0xfa, 0xff, 0x80, 0x15, 0x01, 0x00, 0xa5, 0x24, 0xba, 0xff, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x48, 0x0e, 0x01, 0x03, 0x00, 0x20, 0x15, 0x00, 0x00, 0x89, 0x90, + 0x01, 0x00, 0x84, 0x24, 0x25, 0x40, 0x2e, 0x01, 0xc2, 0x79, 0x08 }, + [0x01b644] = { 0x40, 0x40, 0x08, 0x00, 0x08, 0x00, 0xe0, 0x03, 0x01, 0x00, 0xef, 0x31, 0x00, 0x00, 0x00, 0x08 }, + [0x01b758] = { 0x02, 0x00, 0x02, 0x24, 0x21, 0x18, 0xe0, 0x00, 0x08, 0x00, 0xa7, 0x8c, 0x43, 0x9e, 0x43, 0x10, + 0x10, 0x00, 0xa5, 0x24, 0x21, 0x20, 0xa0, 0x00, 0x21, 0x28, 0xc0 }, + [0x01b774] = { 0x40, 0xab, 0x00, 0x08, 0x01, 0x00, 0x02, 0x24 }, +} diff --git a/VP-textwork.lua b/VP-textwork.lua new file mode 100644 index 0000000..2d3f56c --- /dev/null +++ b/VP-textwork.lua @@ -0,0 +1,143 @@ +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 dump_special(script, code) + if code == 0 then + return "\n", "\n" + elseif code == 1 then + return "\n\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, l + end + end + error "Should not end up there" +end + +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 + -- cgit v1.2.3