from struct import unpack, pack from string import join from os import makedirs, mkdir, chdir, walk, stat, getcwd, sep import sys from optparse import OptionParser usage = "usage: %prog [options] directory file.pak" parser = OptionParser(usage) parser.add_option("-k", "--nocrcinfo", action="store_true", dest="nocrc", help="for producing a SceeWhPk pak (iopm, iop0, ..)") parser.add_option("-C", "--crcinfo", action="store_false", dest="nocrc", help="for producing a SceeWhPC pak (scee_pack.pak)") parser.add_option("-v", "--verbose", action="store_true", dest="verbose") parser.add_option("-q", "--quiet", action="store_false", dest="verbose") (options,args) = parser.parse_args() if len(args) != 2: parser.error("incorrect number of arguments") wdir = getcwd() chdir(args[0]) exts = [] filelist = [] for root, dirs, files in walk('.'): for fil in files: if root != '.': filelist.append(root[2:]+sep+fil) else: filelist.append(fil) fext = fil.split('.')[-1] if len(fext) < 4 and fext not in exts: exts.append(fext) chdir(wdir) reverse_exts = {} for i in range(len(exts)): if exts[i] != '': reverse_exts[exts[i]] = i filelist.sort() r_nfiles = len(filelist) if options.verbose: print "Compressing %d files" % r_nfiles headers = {} headers['name'] = r_nfiles * [''] headers['offset'] = r_nfiles * [0] headers['hoffset'] = r_nfiles * [0] headers['saved'] = r_nfiles * [0] headers['size'] = r_nfiles * [0] headers['ext'] = r_nfiles * [0] headers['dir'] = r_nfiles * [0] headers['crc'] = r_nfiles * [0] coffset = 0 hnsize = 0 curstring = '' for i in range(r_nfiles): headers['size'][i] = stat(args[0]+sep+filelist[i]).st_size name = join(filelist[i].split('.')[:-1], '.').replace('/', '\\') count = 0 while count < len(curstring) and count < len(name): if curstring[count] != name[count]: break count += 1 headers['saved'][i] = count headers['name'][i] = name[count:] curstring = name headers['ext'][i] = reverse_exts[filelist[i].split('.')[-1]] headers['offset'][i] = coffset q = headers['size'][i]/0X800 d = headers['size'][i]%0X800 if d == 0: coffset = coffset+q else: coffset = coffset+q+1 headers['hoffset'][i] = hnsize if not options.nocrc: hnsize += len(headers['name'][i])+16 else: hnsize += len(headers['name'][i])+12 for i in range(r_nfiles): c = headers['saved'][i] best = i for j in range(i+1, r_nfiles): d = headers['saved'][j] if (d < c) or (c==0 and d==0): best = j break headers['dir'][i] = headers['hoffset'][best]-headers['hoffset'][i] if not options.nocrc: hsize = hnsize+15 else: hsize = hnsize+11 q = (hsize+0x198)/0x800 d = (hsize+0x198)%0x800 if d == 0: soffset = q else: soffset = q+1 fw = file(args[1], 'wb') if options.nocrc: compcode = 'k' else: compcode = 'C' fw.write('SceeWhP'+compcode+'[14/07/89,12:12:00]\x00') fw.write(pack('i', hsize)) fw.write(pack('i', r_nfiles)) fw.write('God bless unuseful informations') fw.seek(0x114) for e in exts: fw.write(e+(4-len(e))*'\x00') fw.seek(0x198) for i in range(r_nfiles): offset = pack('i', soffset+headers['offset'][i])[:-1] fw.write(offset) fw.write(pack('BB', headers['saved'][i], len(headers['name'][i])+1)) fw.write(pack('h', headers['dir'][i])) fw.write(pack('i', headers['size'][i])) if not options.nocrc: fw.write('\x00\x00\x00\x00') fw.write(headers['name'][i]) fw.write(pack('B', headers['ext'][i]+1)) for i in range(r_nfiles): fw.seek((soffset+headers['offset'][i])*0x800) fo = file(args[0]+sep+filelist[i], 'rb') fw.write(fo.read()) fo.close() fw.close()