Cross-platform update of Jamesuminator's DMC3 Pac Tools (Including Cheburat0rr's HD updates)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

163 lines
4.6 KiB

#!/usr/bin/python
#! python2
#Pac Repacker
#Coded by James
#import
import sys
from struct import pack
#get the files from the index
def getFiles(index_file, folder):
line = index_file.readline().strip()
files = []
while line != "":
#if there's a sub PTX archive, repack it first
#then add a ptx file to the files array
if line[-6:] == "folder":
PTX(line[:-7], folder)
files.append("%s.ptx" % line[:-7])
else:
print "%s" % line
files.append(line)
line = index_file.readline().strip()
return files #this value is an array of all the filenames
#Another version of getFiles, for PTX usage
def getFilesPTX(index_file):
line = index_file.readline().strip()
files = []
while line != "":
print "\t%s" % line
files.append(line)
line = index_file.readline().strip()
return files
#repacks a PTX archive
def PTX(file, folder):
print "\nRepacking PTX Archive: %s" % file
try:
index_file = open("%s/%s/%s.index" % (folder, file, file), "r")
except:
print "Error Reading %s.index from PTX folder %s" % (file, file)
files = getFilesPTX(index_file)
num_files = len(files)
header = pack("<I", num_files)
body = ""
trailer_open = open("%s/%s.trail" % (folder, file), "rb")
#trailer_open.seek(2048)
trailer = trailer_open.read(2160)
outfile = open("%s/%s.ptx" % (folder, file), "wb")
for i in range(num_files):
bin_open = open("%s/%s/%s" % (folder, file, files[i]), "rb")
bin_str = bin_open.read()
header += pack("<I", len(bin_str)/1024/2)
body += bin_str
header += ("00000000".decode("hex"))*(513-num_files) + trailer #cushion
outfile.write(header+body)
print ""
return 0
#make the body of the pac file
def MakeBody(files, folder):
header = "PAC" + "00".decode("hex") #default
body = ""
num_files = len(files)
pointers = [0] #starting position
for i in range(num_files):
file_open = open("%s/%s" % (folder, files[i]), "rb")
body += file_open.read()
pointers.append(len(body))
del pointers[-1] #delete file size marker
header_len = (num_files * 4) + 8
while header_len%16: #if header isn't divisible by 16, make it
header_len += 4
for i in range((header_len-8)/4):
try:
pointers[i] = pointers[i] + header_len #correct the pointers
except IndexError:
pointers.append(0)
#odd rule
if pointers[-1] == 0 and pointers[-2] == 0 and pointers[-3] == 0:
pointers[-3] = pointers[0]
#another odd rule, size can't be 20
if len(pointers) == 42:
pointers.append(0)
pointers.append(0)
pointers.append(pointers[0])
pointers.append(0)
num_files += 2
for i in range(len(pointers)):
pointers[i] = pointers[i] + ((len(pointers)*4)-(header_len-8)) if pointers[i] else 0#correct the pointers
header += pack("<I", num_files)
for point in pointers:
header += pack("<I", point)
return header+body
def main():
#greetings
print "\n=================================\nDevil May Cry 3 \nPac Repacker\nvBETA\nCoded by James aka Jamesuminator\n=================================\n---------------------------------\n"
#if not enough args, usage
if len(sys.argv) < 2:
print "Usage: %s [folder] {outfile}\nif no outfile given, outfile is [folder].pac" % sys.argv[0]
return -1
else:
folder = sys.argv[1] #folder
try:
pac_file = sys.argv[2] #name of file if sufficient args
except IndexError:
pac_file = "%s.pac" % folder #else it's [folder].pac
#if can't open, exit
print "Opening: %s.index" % folder
try:
index_file = open("%s/%s.index" % (folder, folder), "r")
except:
print "Error Opening %s.index" % folder
return -1
#if can't read, exit
print "Reading: %s.index\n" % folder
try:
files = getFiles(index_file, folder)
except:
print "Error Reading %s.index" % folder
return -1
#contents
pac = MakeBody(files, folder)
#if can't open output, exit
print "\nOpening: %s" % pac_file
try:
pac_open = open(pac_file, "wb")
except:
print "Error Opening %s" % pac_file
return -1
#if can't write output, exit
print "Writing: %s" % pac_file
try:
pac_open.write(pac)
except:
print "Error Writing %s" % pac_file
return -1
#all done!
print "\nAll Done!"
return 0
main()