mirror of
https://github.com/grp/Wii.py.git
synced 2025-06-19 07:15:49 -04:00
Added a CCF compressor/decompressor
This commit is contained in:
parent
02fd26a836
commit
f2a80801ca
109
compression.py
109
compression.py
@ -2,11 +2,120 @@ import os, hashlib, struct, subprocess, fnmatch, shutil, urllib, array
|
|||||||
import wx
|
import wx
|
||||||
import png
|
import png
|
||||||
|
|
||||||
|
import zlib
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Struct import Struct
|
from Struct import Struct
|
||||||
|
|
||||||
from common import *
|
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 LZ77():
|
||||||
class WiiLZ77: #class by marcan
|
class WiiLZ77: #class by marcan
|
||||||
|
Loading…
Reference in New Issue
Block a user