-- Parasite Eve's french patch -- $Id: pe-hack.lua,v 1.8 2003-12-28 13:07:52 pixel Exp $ function mainpatch() local dirent, slusdirent, pvd, root, is_cd1, is_cd2, slusname, fmvdir, systemcnfstring, inslus, slus, peimg, pesect, tim, startsect, slussect, fmvdirtree, xadirtree, falsesect, i, picts, pict slusdirent = cdutil:findpath "/SLUS_006.62;1" or cdutil:findpath "/SLUS_006.68;1" or error "Not a Parasite Eve CD" iso:foreword(cdutil) pvd = createpvd(cdutil) print "Identifying CD..." if (slusdirent.id == "SLUS_006.62;1") then print "CD is Parasite Eve CD1" pvd.volid = "PE-FR-CD1" slusname = "PE-FR.CD1" -- slusname = "SLUS_006.62" fmvdir = "FMV1" is_cd1 = true is_cd2 = false else print "CD is Parasite Eve CD2" pvd.volid = "PE-FR-CD2" slusname = "PE-FR.CD2" -- slusname = "SLUS_006.68" fmvdir = "FMV2" is_cd1 = false is_cd2 = true end root = iso:setbasics(pvd) systemcnfstring = "BOOT=cdrom:\\" .. slusname .. ";1\r\nTCB=4\r\nEVENT=16\r\nSTACK=801fff00\r\n" systemcnf = Buffer() systemcnf:write(systemcnfstring) dirent = cdutil:findpath("/SYSTEM.CNF;1") -- iso:createfile(root, "SYSTEM.CNF", cdfile(cdutil, dirent), dirent) iso:createfile(root, "SYSTEM.CNF", systemcnf, slusdirent) print "Reading CD's slus file" inslus = cdfile(cdutil, slusdirent) -- inslus = Input("PE-SLUS00662-patched-debug-room.exe") slus = Buffer(true) slus:copyfrom(inslus) apply_hacks(slus_hacks, slus) slussect = iso:getdispsect() print("Reserving space for SLUS file at sector " .. slussect) slus:seek(0) iso:createfile(root, slusname, slus, slusdirent):setbasicsxa() slus:seek(0) dirent = cdutil:findpath "/" root:setbasicsxa() root:fromdir(dirent) dirent = cdutil:findpath "/PE.IMG;1" pesect = dirent.Sector peimg = cdfile(cdutil, dirent) tim = Buffer() peimg:copyto(tim, 0x23800) startsect = iso:createfile(root, "PE.TIM", tim, dirent).sector print "Compiling IMG file" do_img_file(slus, startsect, pesect) -- iso:createfile(root, "PE.IMG", peimg, dirent) print "Writing final main file" slus:seek(0) iso:putfile(slus, -1, slussect) print "Copying FMV directory" dirent = cdutil:findpath("/" .. fmvdir) fmvdirtree = iso:createdir(root, fmvdir, 1, dirent) fmvdirtree:setbasicsxa() fmvdirtree.hardhide = true iso:copydir(fmvdirtree, cdutil, dirent) if (is_cd2) then print "Copying xastream directory" dirent = cdutil:findpath("/XASTREAM") xadirtree = iso:createdir(root, "XASTREAM", 1, dirent) xadirtree:setbasicsxa() xadirtree.hardhide = true iso:copydir(xadirtree, cdutil, dirent) end print "Finalizing CD" iso:createfile(root, "README.TXT", Input("readme.txt")):setbasicsxa() iso:createfile(root, "DIVERS.HTM", Input("divers.htm")):setbasicsxa() picts = iso:createdir(root, "PICTS") picts:setbasicsxa() for i, pict in ipairs(picts_files) do iso:createfile(picts, string.upper(pict), Input("picts/" .. pict)):setbasicsxa() end falsesect = {} for i = 1, 148, 1 do iso:createsector(falsesect, MODE2) end iso:close() end function do_img_file(slus, startsect, pesect) local i, j, sect1, tab1, sect2, tab2, sect3, tab3, sizes1, sizes2, sizes3, sect, file, file1, file2, file3, songsect, b1, b2, b3, b4, lastsect, s1, s2, s3, str = 0, 0, {}, {}, {}, {}, {}, {}, {}, {}, {} print "Putting various files" slus:seek(0x838da) for i = 1, 80, 1 do sect1[i] = slus:readU16() + pesect end for i = 1, 79, 1 do if (files[i] ~= nil) then if (type(files[i]) == "string") then print("Putting file " .. files[i] .. " instead"); file = Input(files[i]) else file = files[i](sect1[i], (sect1[i + 1] - sect1[i]) * 2048) end else file = cdfile(cdutil, sect1[i], (sect1[i + 1] - sect1[i]) * 2048) end s1 = iso:putfile(file) tab1[i] = s1 - startsect print("Putting file " .. i .. " from sector " .. sect1[i] .. " to sector " .. s1) end tab1[80] = iso:getdispsect() - startsect songsect = tab1[80] print "Putting musics" slus:seek(0x83980) for i = 1, 251, 1 do sect2[i] = slus:readU16() + sect1[80] end for i = 1, 250, 1 do file = nil if ((sect2[i + 1] - sect2[i]) ~= 0) then file = cdfile(cdutil, sect2[i], (sect2[i + 1] - sect2[i]) * 2048) end if (file) then s1 = iso:putfile(file) end tab2[i] = s1 - startsect - songsect print("Putting music " .. i .. " from sector " .. sect2[i] .. " to sector " .. s1) end tab2[251] = iso:getdispsect() - startsect - songsect print "Putting rooms" slus:seek(0x83b78) for i = 1, 438, 1 do sect3[i] = slus:readU32() + pesect b1 = slus:readU8() b2 = slus:readU8() b3 = slus:readU8() b4 = slus:readU8() sizes1[i] = b1 sizes2[i] = orB(b2, (shl(andB(b3, 0x0f), 8))) sizes3[i] = orB(shr(b3, 4), shl(b4, 4)) end for i = 1, 438, 1 do file1 = nil file2 = nil file3 = nil if (sizes1[i] ~= 0) then file1 = cdfile(cdutil, sect3[i], sizes1[i] * 2048) end if (sizes2[i] ~= 0) then file2 = cdfile(cdutil, sect3[i] + sizes1[i], sizes2[i] * 2048) end if (sizes3[i] ~= 0) then file3 = cdfile(cdutil, sect3[i] + sizes1[i] + sizes2[i], sizes3[i] * 2048) end s1 = iso:getdispsect() - startsect if (file1) then iso:putfile(file1) end s2 = iso:getdispsect() - startsect if (file2) then iso:putfile(file2) end s3 = iso:getdispsect() - startsect if (file3) then if (groups[i] ~= nil) then str = string.format("%02i", groups[i]) file3 = patch_room(file3, Input("scripts/" .. str .. ".bin"), i) end iso:putfile(file3) end print("Putting room " .. i .. " from sector " .. sect3[i] .. " to sector " .. s1 + startsect) tab3[i] = s1 sizes1[i] = s2 - s1 sizes2[i] = s3 - s2 sizes3[i] = iso:getdispsect() - s3 - startsect end slus:wseek(0x838da) for i = 1, 80, 1 do slus:writeU16(tab1[i]) end slus:writeU16(0) slus:writeU16(songsect) slus:writeU16(0) for i = 1, 251, 1 do slus:writeU16(tab2[i]) end slus:wseek(0x83b78) for i = 1, 438, 1 do s1 = sizes1[i] s2 = sizes2[i] s3 = sizes3[i] b1 = s1 b2 = andB(s2, 0xff) b3 = orB(shr(s2, 8), shl(andB(s3, 0x0f), 4)) b4 = shr(s3, 4) slus:writeU32(tab3[i]) slus:writeU8(b1) slus:writeU8(b2) slus:writeU8(b3) slus:writeU8(b4) end for i = 1, 11, 1 do slus:writeU32(iso:getdispsect()) slus:writeU32(0) end end function patch_map(sector, size) local map, font, names, buff font = Input("font.tim") names = Input("names.tim") buff = Buffer(true) buff:writeU32(8) buff:writeU32(font:getsize() + 8) buff:copyfrom(font) buff:copyfrom(names) return buff end function patch_day1(sector, size) local day1, buffs, offs, i, trad, r = nil, {}, {} day1 = cdfile(cdutil, sector, size) for i = 1, 4, 1 do buffs[i] = Buffer() offs[i] = day1:readU32() end day1:seek(offs[4]) offs[5] = offs[4] + day1:readU32() for i = 1, 4, 1 do day1:seek(offs[i]) buffs[i]:copyfrom(day1, offs[i + 1] - offs[i]) end trad = Input("map.bin") buffs[2] = Buffer(true) buffs[2]:copyfrom(trad) buffer_pad(buffs[2]) offs[1] = 0x10 offs[2] = offs[1] + buffs[1]:getsize() offs[3] = offs[2] + buffs[2]:getsize() offs[4] = offs[3] + buffs[3]:getsize() r = Buffer() for i = 1, 4, 1 do r:writeU32(offs[i]) end for i = 1, 4, 1 do r:copyfrom(buffs[i]) end return r end function patch_room(_room, _script, nb) local r, truescriptsize, scriptsize, enlargment, room, script, roomsize, ptrptrs, ptrscriptptrs, oldscriptsize, scriptptr, rest, t, i, nbptrs, add script = Buffer(true) script:copyfrom(_script) buffer_pad(script) r = Buffer() truescriptsize = _script:getsize() scriptsize = script:getsize() roomsize = _room:readU32() room = Buffer(true) ptrptrs = _room:readU32() _room:seek(0) room:copyfrom(_room, roomsize) room:seek(ptrptrs + 32) ptrscriptsptr = andB(room:readU32(), 0xfffff) add = andB(room:readU32(), 0xfffff) add = (andB(room:readU32(), 0xfffff) - add) / 4 room:seek(ptrscriptsptr + 8) oldscriptsize = room:readU32() scriptptr = andB(room:readU32(), 0xfffff) rest = 4 - andB(oldscriptsize, 3) if (rest == 4) then rest = 0 end enlargment = scriptsize - (oldscriptsize + rest) r:writeU32(roomsize + enlargment) r:writeU32(ptrptrs + enlargment) room:seek(8) r:copyfrom(room, scriptptr - 8) r:copyfrom(script) room:seek(scriptptr + oldscriptsize + rest) r:copyfrom(room, ptrptrs - (scriptptr + oldscriptsize + rest)) t = room:readU32() r:writeU32(t) for i = 1, 12, 1 do t = room:readU32() r:writeU32(orB(shl(shr(t, 20), 20), andB(t, 0xfffff) + enlargment)) end r:copyfrom(room, ptrscriptsptr - room:tell() + 8) r:writeU32(truescriptsize) room:readU32() r:writeU32(room:readU32()) for i = 1, add, 1 do r:writeU32(room:readU32()) end nbptrs = (roomsize - room:tell()) / 12 for i = 1, nbptrs, 1 do r:writeU32(room:readU32()) t = room:readU32() r:writeU32(orB(shl(shr(t, 20), 20), andB(t, 0xfffff) + enlargment)) r:writeU32(room:readU32()) end -- r:copyto(Output("output/room-" .. hex(nb, "%04i") .. ".bin")) -- r:seek(0) return r end function apply_hacks(hacks, file) local k, v, i, h for k, v in pairs(slus_hacks) do for i, h in ipairs(v) do file[k + i - 1] = h end end end function buffer_pad(buffer) local rest, i rest = 4 - andB(buffer:getsize(), 3) if (rest == 4) then return end buffer:wseek(0, SEEK_END) for i = 1, rest, 1 do buffer:writeU8(0) end end files = { [1] = "various.bin", [2] = "menus.bin", [10] = "font.tim", [70] = "mainmenu.bin", [72] = patch_map, [76] = patch_day1, } slus_hacks = { -- ASM Ptr hack [0x1603c] = { 0xbc }, -- ASM Font hack [0x284e4] = { 0x21 }, [0x28540] = { 0x21, 0x18, 0x00, 0x00 }, [0x28fb8] = { 0x21, 0x18, 0x00, 0x00 }, [0x29074] = { 0x00, 0x00, 0x00 }, -- Text "Susceptible to poison" [0x81c96] = { 0x25, 0x34, 0x3d, 0x38, 0x3c, 0x34, 0x44, 0x47, 0xff }, -- Text "Susceptible to acid" [0x81cc0] = { 0x14, 0x3c, 0x3f, 0x3e, 0x38, 0x42, 0x3e, 0x3d, 0x3d, 0x34, 0x0f, 0x3f, 0x30, 0x41, 0x0f, 0x30, 0x32, 0x38, 0x33, 0x34, 0xff }, -- Text "Easily tranquilized" [0x81ce8] = { 0x22, 0x34, 0x3d, 0x42, 0x38, 0x31, 0x3b, 0x34, 0x0f, 0x30, 0x44, 0x47, 0x0f, 0x43, 0x41, 0x30, 0x3d, 0x40, 0x44, 0x38, 0x3b, 0x38, 0x42, 0x30, 0x3d, 0x43, 0x42, 0xff }, -- Text "Sensitive to heat" [0x81d0e] = { 0x22, 0x34, 0x3d, 0x42, 0x38, 0x31, 0x3b, 0x34, 0x0f, 0x51, 0x0f, 0x3b, 0x30, 0x0f, 0x32, 0x37, 0x30, 0x3b, 0x34, 0x44, 0x41, 0xff }, -- Text "Sensitive to cold" [0x81d32] = { 0x22, 0x34, 0x3d, 0x42, 0x38, 0x31, 0x3b, 0x34, 0x0f, 0x30, 0x44, 0x0f, 0x35, 0x41, 0x3e, 0x38, 0x33, 0xff }, -- Text "Objects easily stolen" [0x81d5a] = { 0x1f, 0x3e, 0x42, 0x42, 0x4e, 0x33, 0x34, 0x0f, 0x33, 0x34, 0x42, 0x0f, 0x3e, 0x31, 0x39, 0x34, 0x43, 0x42, 0x0f, 0x51, 0x0f, 0x45, 0x3e, 0x3b, 0x34, 0x41, 0xff }, -- Text "Gets confused easily" [0x81d85] = { 0x12, 0x3e, 0x3d, 0x35, 0x44, 0x42, 0x38, 0x3e, 0x3d, 0x0f, 0x3f, 0x3e, 0x42, 0x42, 0x38, 0x31, 0x3b, 0x34, 0x0f, 0x34, 0x43, 0x0f, 0x34, 0x35, 0x35, 0x38, 0x32, 0x30, 0x32, 0x34, 0xff }, -- Text "Failed to escape" [0x81dad] = { 0x15, 0x44, 0x38, 0x43, 0x34, 0x0f, 0x4d, 0x32, 0x37, 0x3e, 0x44, 0x4d, 0x34, 0xff }, -- Text "Can't escape!" [0x81dca] = { 0x15, 0x44, 0x38, 0x43, 0x34, 0x0f, 0x38, 0x3c, 0x3f, 0x3e, 0x42, 0x42, 0x38, 0x31, 0x3b, 0x34, 0x2b, 0xff }, -- Font width table [0x81ea1] = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 8, 11, 14, 9, 8, 7, 8, 7, 7, 8, 9, 6, 7, 9, 8, 11, 9, 7, 8, 7, 9, 7, 7, 9, 9, 11, 7, 9, 7, 9, 4, 7, 6, 4, 4, 8, 8, 7, 7, 7, 7, 8, 9, 5, 4, 8, 5, 11, 9, 7, 8, 8, 7, 6, 5, 9, 9, 11, 7, 9, 6, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 7, 7, 9, 9, 9, 7, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -- PE.BIN filename extension [0x01b4c] = { 0x54, 0x49, 0x4d }, -- savefile filename [0x016e5] = { 0x38 }, -- Debug room -- [0x2f888] = { }, } groups = { [1] = 1, [2] = 1, [3] = 1, [4] = 1, [5] = 1, [6] = 1, [9] = 1, [10] = 1, [11] = 1, [12] = 1, [13] = 1, [14] = 1, [16] = 1, [17] = 1, [18] = 1, [20] = 1, [21] = 1, [22] = 1, [23] = 1, [24] = 1, [25] = 1, [26] = 2, [27] = 2, [28] = 2, [29] = 2, [30] = 2, [31] = 2, [32] = 2, [33] = 2, [34] = 2, [35] = 3, [36] = 3, [37] = 3, [38] = 3, [39] = 3, [40] = 3, [41] = 4, [42] = 4, [43] = 4, [44] = 5, [45] = 4, [46] = 4, [47] = 4, [48] = 5, [49] = 1, [50] = 1, [51] = 4, [52] = 4, [53] = 4, [54] = 4, [55] = 4, [56] = 4, [57] = 6, [58] = 6, [59] = 6, [60] = 6, [61] = 6, [62] = 6, [63] = 6, [64] = 6, [65] = 6, [66] = 6, [67] = 6, [68] = 6, [69] = 6, [70] = 6, [71] = 6, [72] = 6, [73] = 6, [74] = 6, [75] = 6, [76] = 6, [77] = 6, [78] = 6, [79] = 6, [80] = 6, [81] = 7, [82] = 6, [83] = 6, [84] = 6, [85] = 6, [86] = 6, [87] = 6, [88] = 6, [89] = 6, [90] = 8, [91] = 8, [92] = 8, [93] = 8, [94] = 8, [95] = 8, [96] = 8, [97] = 8, [98] = 5, [99] = 5, [100] = 5, [102] = 5, [103] = 5, [104] = 5, [106] = 5, [107] = 5, [108] = 5, [109] = 5, [110] = 5, [111] = 5, [112] = 5, [113] = 5, [114] = 5, [115] = 5, [116] = 5, [117] = 5, [118] = 5, [120] = 5, [121] = 5, [122] = 5, [123] = 5, [124] = 5, [125] = 9, [126] = 9, [127] = 9, [128] = 9, [129] = 9, [130] = 9, [131] = 9, [132] = 9, [133] = 9, [134] = 9, [135] = 9, [136] = 9, [137] = 9, [138] = 9, [139] = 9, [140] = 9, [141] = 9, [142] = 9, [143] = 9, [144] = 9, [145] = 9, [146] = 9, [147] = 9, [148] = 9, [149] = 9, [150] = 9, [151] = 9, [152] = 9, [153] = 9, [154] = 9, [155] = 9, [156] = 9, [157] = 9, [158] = 9, [159] = 9, [160] = 9, [161] = 10, [162] = 10, [163] = 10, [164] = 10, [165] = 10, [166] = 11, [167] = 11, [168] = 11, [169] = 11, [170] = 11, [171] = 11, [172] = 11, [173] = 11, [174] = 11, [175] = 11, [176] = 11, [178] = 11, [179] = 11, [180] = 11, [181] = 11, [182] = 11, [183] = 11, [184] = 11, [185] = 11, [186] = 11, [187] = 11, [188] = 11, [189] = 11, [190] = 11, [191] = 12, [192] = 13, [193] = 13, [194] = 13, [195] = 12, [196] = 13, [197] = 13, [198] = 13, [199] = 13, [200] = 13, [201] = 13, [202] = 13, [203] = 13, [204] = 13, [205] = 13, [206] = 13, [207] = 13, [208] = 12, [209] = 13, [210] = 13, [211] = 13, [212] = 13, [213] = 13, [214] = 13, [215] = 13, [216] = 13, [217] = 13, [218] = 13, [219] = 13, [220] = 13, [221] = 12, [222] = 13, [223] = 13, [224] = 13, [225] = 13, [226] = 13, [227] = 13, [228] = 13, [229] = 13, [230] = 12, [231] = 13, [232] = 13, [233] = 12, [234] = 13, [235] = 13, [236] = 13, [237] = 13, [238] = 13, [239] = 12, [240] = 13, [241] = 13, [242] = 13, [243] = 13, [244] = 13, [245] = 13, [246] = 13, [247] = 13, [248] = 13, [249] = 13, [250] = 13, [251] = 13, [252] = 13, [253] = 13, [254] = 13, [255] = 13, [256] = 12, [257] = 13, [258] = 13, [259] = 3, [260] = 14, [262] = 14, [263] = 14, [265] = 14, [266] = 14, [267] = 14, [268] = 14, [269] = 14, [271] = 15, [272] = 15, [273] = 16, [275] = 17, [276] = 17, [278] = 17, [279] = 17, [280] = 17, [281] = 17, [282] = 17, [283] = 17, [284] = 17, [285] = 17, [286] = 17, [287] = 17, [288] = 18, [290] = 19, [291] = 19, [292] = 19, [293] = 19, [294] = 19, [295] = 19, [296] = 19, [297] = 19, [298] = 19, [299] = 19, [300] = 19, [301] = 19, [302] = 19, [303] = 19, [304] = 19, [305] = 19, [306] = 19, [307] = 19, [308] = 19, [309] = 19, [310] = 19, [311] = 19, [312] = 19, [313] = 19, [314] = 19, [315] = 19, [316] = 19, [317] = 19, [318] = 19, [319] = 1, [320] = 9, [321] = 9, [322] = 9, [323] = 9, [324] = 9, [325] = 9, [326] = 9, [327] = 9, [328] = 9, [329] = 9, [330] = 9, [331] = 9, [332] = 9, [333] = 14, [334] = 2, [335] = 19, [337] = 5, [339] = 9, [340] = 13, [341] = 13, [342] = 13, [343] = 13, [344] = 13, [345] = 13, [346] = 13, [347] = 20, [348] = 2, [349] = 12, [350] = 17, [351] = 3, [352] = 3, [358] = 6, [359] = 1, [360] = 3, [367] = 1, [371] = 13, [372] = 1, [373] = 1, [374] = 6, [377] = 1, [378] = 1, [379] = 13, [380] = 9, [381] = 9, [382] = 20, [383] = 19, [384] = 19, [385] = 19, [386] = 19, [388] = 19, [389] = 19, [390] = 19, [391] = 19, [392] = 19, [393] = 19, [394] = 19, [395] = 19, [396] = 19, [397] = 19, [398] = 19, [399] = 19, [400] = 19, [401] = 19, [402] = 19, [403] = 19, [404] = 19, [405] = 19, [406] = 19, [407] = 19, [408] = 19, [409] = 19, [410] = 19, [411] = 19, [412] = 19, [413] = 19, [414] = 19, [416] = 19, [417] = 19, [418] = 19, [419] = 19, [420] = 19, [421] = 19, [422] = 19, [423] = 19, [424] = 19, [425] = 17, [426] = 17, [427] = 17, [428] = 17, [429] = 17, [430] = 17, [431] = 1, [432] = 16, [433] = 11, [434] = 19, [435] = 19, [436] = 19, [437] = 19, } picts_files = { "foe.jpg", "tune-up1.jpg", "tune-up2.jpg", "tuto1.jpg", "tuto10.jpg", "tuto11.jpg", "tuto12.jpg", "tuto13.jpg", "tuto14.jpg", "tuto15.jpg", "tuto16.jpg", "tuto17.jpg", "tuto18.jpg", "tuto19.jpg", "tuto2.jpg", "tuto20.jpg", "tuto21.jpg", "tuto22.jpg", "tuto23.jpg", "tuto3.jpg", "tuto4.jpg", "tuto5.jpg", "tuto6.jpg", "tuto7.jpg", "tuto8.jpg", "tuto9.jpg", } mainpatch()