From f2a80801caa4092badb1040a3e6a61ce91494f3f Mon Sep 17 00:00:00 2001 From: "Giuseppe (LemonBoy)" Date: Tue, 16 Jun 2009 15:32:57 +0200 Subject: [PATCH] Added a CCF compressor/decompressor --- compression.py | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/compression.py b/compression.py index f1fd794..669958e 100644 --- a/compression.py +++ b/compression.py @@ -2,12 +2,121 @@ import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array import wx import png +import zlib from Crypto.Cipher import AES from Struct import Struct from common import * +class CCF(): + class CCFHeader(Struct): + __endian__ = Struct.LE + def __format__(self): + self.magic = Struct.string(4) + self.zeroes12 = Struct.string(12) + self.rootOffset = Struct.uint32 + self.filesCount = Struct.uint32 + self.zeroes8 = Struct.string(8) + + class CCFFile(Struct): + __endian__ = Struct.LE + def __format__(self): + self.fileName = Struct.string(20) + self.fileOffset = Struct.uint32 + self.fileSize = Struct.uint32 + self.fileSizeDecompressed = Struct.uint32 + def __init__(self, fileName): + self.fd = open(fileName, 'r+b') + + def compress(self, folder): + fileList = [] + + fileHdr = self.CCFHeader() + + files = os.listdir(folder) + + fileHdr.magic = "\x43\x43\x46\x00" + fileHdr.zeroes12 = '\x00' * 12 + fileHdr.rootOffset = 0x20 + fileHdr.zeroes8 = '\x00' * 8 + + currentOffset = len(fileHdr) + packedFiles = 0 + previousFileEndOffset = 0 + + for file in files: + if os.path.isdir(folder + '/' + file) or file == '.DS_Store': + continue + else: + fileList.append(file) + + fileHdr.filesCount = len(fileList) + self.fd.write(fileHdr.pack()) + self.fd.write('\x00' * (fileHdr.filesCount * len(self.CCFFile()))) + + for fileNumber in range(len(fileList)): + + fileEntry = self.CCFFile() + + compressedBuffer = zlib.compress(open(folder + '/' + fileList[fileNumber]).read()) + + fileEntry.fileName = fileList[fileNumber] + fileEntry.fileSize = len(compressedBuffer) + fileEntry.fileSizeDecompressed = os.stat(folder + '/' + fileList[fileNumber]).st_size + fileEntry.fileOffset = align(self.fd.tell(), 32) / 32 + + print 'File {0} ({1}Kb) placed at offset 0x{2:X}'.format(fileEntry.fileName, fileEntry.fileSize / 1024, fileEntry.fileOffset * 32) + + self.fd.seek(len(fileHdr) + fileNumber * len(self.CCFFile())) + self.fd.write(fileEntry.pack()) + self.fd.seek(fileEntry.fileOffset * 32) + self.fd.write(compressedBuffer) + + self.fd.close() + + def decompress(self): + fileHdr = self.CCFHeader() + hdrData = self.fd.read(len(fileHdr)) + fileHdr.unpack(hdrData) + + print 'Found {0} file/s and root node at 0x{1:X}'.format(fileHdr.filesCount, fileHdr.rootOffset) + + if fileHdr.magic != "\x43\x43\x46\x00": + raise ValueError("Wrong magic, 0x{0}".format(fileHdr.magic)) + + os.mkdir('/' + self.fd.name.replace(".", "_") + "_out") + os.chdir('/' + self.fd.name.replace(".", "_") + "_out") + + currentOffset = len(fileHdr) + + for x in range(fileHdr.filesCount): + self.fd.seek(currentOffset) + + fileEntry = self.CCFFile() + fileData = self.fd.read(len(fileEntry)) + fileEntry.unpack(fileData) + + fileEntry.fileOffset = fileEntry.fileOffset * 32 + + print 'File {0} at offset 0x{1:X}'.format(fileEntry.fileName, fileEntry.fileOffset) + print 'File size {0}Kb ({1}Kb decompressed)'.format(fileEntry.fileSize / 1024, fileEntry.fileSizeDecompressed / 1024) + + output = open(fileEntry.fileName.rstrip('\0'), 'w+b') + + self.fd.seek(fileEntry.fileOffset) + if fileEntry.fileSize == fileEntry.fileSizeDecompressed: + print 'The file is stored uncompressed' + output.write(self.fd.read(fileEntry.fileSize)) + else: + print 'The file is stored compressed..decompressing' + decompressedBuffer = zlib.decompress(self.fd.read(fileEntry.fileSize)) + output.write(decompressedBuffer) + output.close() + + currentOffset += len(fileEntry) + + class LZ77(): class WiiLZ77: #class by marcan TYPE_LZ77 = 1