from __future__ import print_function import os import subprocess from struct import * import g import dir def removecomment(line): i = line.find('#') if i < 0: return line return line[:i] def commaline(line): return [f.strip() for f in line.split(',')] def readIDE(file): section = 'end' data = {} for line in file: line = removecomment(line) line = line.strip() if line == '': continue if section == 'end': section = line data[section] = [] continue if line == 'end': section = 'end' continue fields = commaline(line) i = 0 if section == 'objs' or section == 'tobj': obj = {} obj['type'] = section obj['id'] = int(fields[i]) obj['model'] = fields[i+1] obj['texture'] = fields[i+2] i += 3 obj['objectCount'] = 0 if section == 'objs' and len(fields) > 5 or \ section == 'tobj' and len(fields) > 7: obj['objectCount'] = int(fields[i]) i += 1 drawdist = [] for j in range(obj['objectCount'] or 1): drawdist.append(float(fields[i])) i += 1 obj['drawdist'] = drawdist obj['flags'] = int(fields[i]) if section == 'tobj': obj['timeon'] = fields[i+1] obj['timeoff'] = fields[i+2] data[section].append(obj) elif section == 'anim': anim = {} anim['type'] = section anim['id'] = int(fields[i]) anim['model'] = fields[i+1] anim['texture'] = fields[i+2] anim['animation'] = fields[i+3] anim['drawdist'] = float(fields[i+4]) anim['flags'] = int(fields[i+5]) data[section].append(anim) elif section == 'txdp': txdp = {} txdp['type'] = section txdp['child'] = fields[0] txdp['parent'] = fields[1] data[section].append(txdp) elif section == '2dfx': # no complete documentation (but placement anyway) pass else: print(section, line) return data def readwriteIDE(inf, outf, idtrans, unused): section = 'end' for orig_line in inf: line = removecomment(orig_line).strip() modifyline = True if line == '': modifyline = False elif section == 'end': section = line modifyline = False elif line == 'end': section = 'end' modifyline = False elif section == 'txdp': modifyline = False if modifyline: fields = commaline(line) id = int(fields[0]) if id in idtrans: newid = idtrans[id] else: newid = unused.pop() idtrans[id] = newid fields[0] = str(newid) print(', '.join(fields), file=outf) else: print(orig_line, end='', file=outf) # ['zone', 'inst', 'cull', 'path', 'grge', 'enex', 'pick', 'jump', 'tcyc', 'auzo', 'mult', 'cars', 'occl'] def readwriteIPL(inf, outf, idtrans): section = 'end' for orig_line in inf: line = removecomment(orig_line).strip() modifyline = False; if line == '': pass elif section == 'end': section = line elif line == 'end': section = 'end' elif section == 'inst': modifyline = True if modifyline: fields = commaline(line) id = int(fields[0]) newid = idtrans[id] fields[0] = str(newid) print(', '.join(fields), file=outf) else: print(orig_line, end='', file=outf) def readwriteBinIPL(inf, outf, idtrans): header = inf.read(19*4) (fourcc, ninst, nunk1, nunk2, nunk3, ncar, nunk4, \ instOff, instSize, unk1Off, unk1Size, unk2Off, unk2Size, \ unk3Off, unk3Size, carOff, carSize, unk4Off, unk4Size) = \ unpack('4s18I', header) outf.write(header) assert fourcc == b'bnry' assert nunk1 == 0 assert nunk2 == 0 assert nunk3 == 0 assert nunk4 == 0 if ncar: assert carOff == instOff+ninst*40 for i in range(ninst): inst = inf.read(10*4) data = list(unpack('10I', inst)) data[7] = idtrans[data[7]] outf.write(pack('10I', *data)) for i in range(ncar): car = inf.read(12*4) outf.write(car) #def checkmissingfiles(items, dirs): # def fileindirs(name): # if name == "vehicle.txd": # return True # for _, d in dirs.items(): # if dir.hasfile(d, name): # return True # return False # # for _, item in items.items(): # if not fileindirs(item['model']+".dff"): # print(item['model']+".dff") # if not fileindirs(item['texture']+".txd"): # print(item['texture']+".txd") #def movefiles(directory, items): # for _, item in items.items(): # os.system("MOVE "+directory+"\\"+item['model']+".dff "+directory+"\\mapfiles") # os.system("MOVE "+directory+"\\"+item['texture']+".txd "+directory+"\\mapfiles") def makeideline(item): s = '' if item['type'] in ['objs', 'tobj']: a = [item['id'], item['model'], item['texture']] if item['objectCount'] == 0: a += [item['objectCount']] a += item['drawdist'] a += [item['flags']] if item['type'] == 'tobj': a += [item['timeon'], item['timeoff']] s = ', '.join([str(x) for x in a]) elif item['type'] == 'anim': a = [item['id'], item['model'], item['texture'], item['animation'], item['drawdist'], anim['flags']] s = ', '.join([str(x) for x in a]) return item['type']+' '+s def checkmultiplemodels(ide, models): def insertmodel(obj): if obj['model'] in models: print(obj) else: models[obj['model']] = obj for type in ['objs', 'tobj', 'anim']: if type in ide: for obj in ide[type]: insertmodel(obj); def listdiff(lst1, lst2, idtrans=None, unused=None): for key, val in lst1.items(): if not key in lst2: # print(makeideline(val)) if unused != None: unused.append(val['id']) elif idtrans != None: idtrans[lst2[key]['id']] = val['id'] def buildlists(ide, dffs, txds): def addDFFandTXD(obj): if not obj['model'].lower() in dffs: dffs.append(obj['model'].lower()) if not obj['texture'].lower() in txds: txds.append(obj['texture'].lower()) for type in ['objs', 'tobj', 'anim']: if type in ide: for obj in ide[type]: #print(obj['id']) addDFFandTXD(obj) def convertdff(dff, archives): for img, path in archives: if dir.hasfile(img, dff): dir.extract1(img, dff, dff) #subprocess.call(['dffconv', '-v', 'GTASA', '-c', '-m', dff, g.jp(path, dff)]) print(dff) subprocess.call(['convdff', '-u', dff, g.jp(path, dff)]) os.remove(dff) return def converttxd(txd, archives): for img, path in archives: if dir.hasfile(img, txd): dir.extract1(img, txd, txd) subprocess.call(['txdconv', '-v', 'GTASA', '-9', txd, g.jp(path, txd)]) os.remove(txd) return def main(): gta3img = dir.readIMG(g.jp(g.ps2path, "models", "gta3.img")) gta_intimg = dir.readIMG(g.jp(g.ps2path, "models", "gta_int.img")) cutsceneimg = dir.readIMG(g.jp(g.ps2path, "models", "cutscene.img")) # playerimg = dir.readIMG(g.ps2path+"models\\player.img") pcgta3img = dir.readIMG(g.jp(g.pcpath, "models", "gta3.img")) pcgta_intimg = dir.readIMG(g.jp(g.pcpath, "models", "gta_int.img")) pccutsceneimg = dir.readIMG(g.jp(g.pcpath, "models", "cutscene.img")) # pcplayerimg = dir.readIMG(g.pcpath+"models\\player.img") dir.extract(pcgta3img, g.jp(g.buildpath, "gta3_archive")) dir.extract(pcgta_intimg, g.jp(g.buildpath, "gta_int_archive")) dir.extract(pccutsceneimg, g.jp(g.buildpath, "cutscene_archive")) ps2items = {} pcitems = {} ps2dffs = [] ps2txds = [] for ide in g.ides: print(ide) f = open(g.jp(g.ps2path, ide), 'r') ps2data = readIDE(f) f.close() f = open(g.jp(g.pcpath, ide), 'r') pcdata = readIDE(f) f.close() checkmultiplemodels(ps2data, ps2items) checkmultiplemodels(pcdata, pcitems) buildlists(ps2data, ps2dffs, ps2txds) #buildlists(pcdata, ps2dffs, ps2txds) archives = [(gta3img, g.jp(g.buildpath, "gta3_archive")), (gta_intimg, g.jp(g.buildpath, "gta_int_archive")), (cutsceneimg, g.jp(g.buildpath, "cutscene_archive"))] print("converting DFFs...") for dff in ps2dffs: convertdff(dff+".dff", archives) print("converting TXDs...") for txd in ps2txds: converttxd(txd+".txd", archives) ## dirs = {"gta3": gta3img, "gta_int": gta_intimg, ## "cutscene": cutsceneimg, "player": playerimg} ## print("missing files in PC imgs:") ## checkmissingfiles(ps2items, dirs) ## movefiles("C:\\Users\\aap\\Desktop\\testfiles", pcitems) idtrans = {} unused = [] # print("only PS2:") # listdiff(ps2items, pcitems) # print("only PC:") # make PS2 ID -> PC ID dict and get unused IDs (let's hope the main.scm doesn't use them) listdiff(pcitems, ps2items, idtrans, unused) # print(unused) for ide in g.ides: print(ide) inf = open(g.jp(g.ps2path, ide), 'r') outf = g.opencreate(g.jp(g.buildpath, ide), 'w') readwriteIDE(inf, outf, idtrans, unused) inf.close() outf.close() for ipl in g.ipls: print(ipl) inf = open(g.jp(g.ps2path, ipl), 'r') outf = g.opencreate(g.jp(g.buildpath, ipl), 'w') readwriteIPL(inf, outf, idtrans) inf.close() outf.close() for ipl in g.binipls: print(ipl) inf = dir.openFile(gta3img, ipl) outf = g.opencreate(g.jp(g.buildpath,'gta3_archive',ipl), 'wb') readwriteBinIPL(inf, outf, idtrans) inf.close() outf.close() for ipl in g.biniplsint: print(ipl) inf = dir.openFile(gta_intimg, ipl) outf = g.opencreate(g.jp(g.buildpath,'gta_int_archive',ipl), 'wb') readwriteBinIPL(inf, outf, idtrans) inf.close() outf.close() for col in g.cols: # print(col) dir.extract1(gta3img, col, g.jp(g.buildpath,'gta3_archive',col)) for col in g.colsint: # print(col) dir.extract1(gta_intimg, col, g.jp(g.buildpath,'gta_int_archive',col)) print("building gta3.img") dir.build(g.jp(g.buildpath,'gta3_archive'), g.jp(g.buildpath,'models','gta3.img')) print("building gta_int.img") dir.build(g.jp(g.buildpath,'gta_int_archive'), g.jp(g.buildpath,'models','gta_int.img')) print("building cutscene.img") dir.build(g.jp(g.buildpath,'cutscene_archive'), g.jp(g.buildpath,'models','cutscene.img')) return; if __name__ == '__main__': main()