-- Parasite Eve's french patch -- $Id: pe-hack.lua,v 1.9 2004-01-03 15:04:47 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" fmvdir = "FMV1" is_cd1 = true is_cd2 = false else print "CD is Parasite Eve CD2" pvd.volid = "PE-FR-CD2" slusname = "PE-FR.CD2" 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", 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) 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_menu(sector, size) local menu, bmenu, i, v, o menu = Input("menus.bin") bmenu = Buffer(true) bmenu:copyfrom(menu) bmenu:seek(0x28) o = bmenu:readU32() bmenu:seek(0) bmenu:wseek(0) for i = 78, 144 do v = slus_hacks[0x81ea1][i] if (v == 0) then break end bmenu[o + i - 1] = (v - 1) * 16 end return bmenu 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] = patch_menu, [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, -- new chars here 7, 7, 7, 7, 7, 7, 7, 5, 5, 7, 7, 9, 9, 9, 7, 11, 11, 5, 5, 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 }, -- 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()