2018-12-04 13:44:09 +00:00
|
|
|
'''
|
|
|
|
Handling of compressed MacOS resources.
|
|
|
|
Author: Max Poliakovski 2018
|
|
|
|
'''
|
|
|
|
import struct
|
|
|
|
|
2018-12-11 16:15:05 +00:00
|
|
|
from GreggBits import GreggDecompress, GreggCompress
|
2018-12-04 13:44:09 +00:00
|
|
|
|
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
def GetEncoding(dat):
|
|
|
|
sig, hdrlen, vers, attrs, biglen = struct.unpack_from(">IHBBI", dat)
|
|
|
|
if sig != 0xA89F6572:
|
|
|
|
print("Invalid extended resource header sig: 0x%X" % sig)
|
|
|
|
return 'UnknownCompression'
|
|
|
|
if vers not in (8, 9):
|
|
|
|
print("Unknown ext res header format: %d" % vers)
|
|
|
|
return 'UnknownCompression'
|
|
|
|
if attrs & 1 == 0:
|
2018-12-04 13:44:09 +00:00
|
|
|
print("extAttributes,bit0 isn't set. Treat this res as uncompressed.")
|
2018-12-13 04:50:40 +00:00
|
|
|
return 'UnknownCompression'
|
|
|
|
|
|
|
|
print("Uncompressed length: %d" % biglen)
|
|
|
|
|
|
|
|
if vers == 8:
|
|
|
|
print('Donn unimplemented!'); return 'UnknownCompression'
|
|
|
|
return 'DonnBits'
|
|
|
|
elif vers == 9:
|
|
|
|
if dat[12:14] == b'\x00\x02':
|
|
|
|
return 'GreggyBits'
|
|
|
|
else:
|
|
|
|
return 'UnknownCompression'
|
2018-12-04 13:44:09 +00:00
|
|
|
else:
|
2018-12-13 04:50:40 +00:00
|
|
|
return 'UnknownCompression'
|
2018-12-04 13:44:09 +00:00
|
|
|
|
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
def DecompressResource(dat):
|
|
|
|
encoding = GetEncoding(dat)
|
|
|
|
sig, hdrlen, vers, attrs, biglen = struct.unpack_from(">IHBBI", dat)
|
2018-12-04 13:44:09 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
if encoding == 'DonnBits':
|
|
|
|
raise NotImplementedError('DonnBits')
|
2018-12-04 13:44:09 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
elif encoding == 'GreggyBits':
|
|
|
|
dst = bytearray()
|
|
|
|
GreggDecompress(dat, dst, unpackSize=biglen, pos=12)
|
|
|
|
return bytes(dst)
|
2018-12-04 13:44:09 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
elif encoding == 'UnknownCompression':
|
|
|
|
return dat # passthru
|
2018-12-11 16:12:06 +00:00
|
|
|
|
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
def CompressResource(dat, encoding):
|
|
|
|
if encoding == 'UnknownCompression':
|
|
|
|
return dat
|
2018-12-11 16:12:06 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
elif encoding == 'GreggyBits':
|
|
|
|
dst = bytearray()
|
2018-12-11 16:12:06 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
# re-create extended resource header
|
|
|
|
dst.extend([0xA8, 0x9F, 0x65, 0x72, 0x00, 0x12, 0x09, 0x01])
|
|
|
|
dst.extend(len(dat).to_bytes(4, 'big'))
|
2018-12-04 13:44:09 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
# leave Gregg-specific header to the compressor
|
|
|
|
GreggCompress(dat, dst)
|
2018-12-04 13:44:09 +00:00
|
|
|
|
2018-12-13 04:50:40 +00:00
|
|
|
return bytes(dst)
|