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.
117 lines
3.6 KiB
117 lines
3.6 KiB
2 years ago
|
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||
|
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||
|
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||
|
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||
|
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||
|
# Magicbane Emulator Project © 2013 - 2022
|
||
|
# www.magicbane.com
|
||
2 years ago
|
|
||
|
import struct
|
||
|
import zlib
|
||
|
|
||
|
|
||
|
def read_dword(cache_file):
|
||
|
data = cache_file.read(4)
|
||
|
return struct.unpack('<I', data)[0]
|
||
|
|
||
|
|
||
|
def read_qword(cache_file):
|
||
|
dwords = struct.unpack('<II', cache_file.read(8))
|
||
|
buffer = struct.pack('<II', dwords[1], dwords[0])
|
||
|
return struct.unpack('<Q', buffer)[0]
|
||
|
|
||
|
|
||
|
def read_resource_data(cache_file, start, length):
|
||
|
current_position = cache_file.tell()
|
||
|
|
||
|
cache_file.seek(start)
|
||
|
data = cache_file.read(length)
|
||
|
|
||
|
cache_file.seek(current_position)
|
||
|
return data
|
||
|
|
||
|
|
||
|
def load_cache_file(filename):
|
||
|
cache_file = open(filename, 'rb')
|
||
|
num_resources = read_dword(cache_file)
|
||
|
read_dword(cache_file)
|
||
|
read_dword(cache_file)
|
||
|
read_dword(cache_file)
|
||
|
|
||
|
resources = []
|
||
|
for _ in range(num_resources):
|
||
|
resource_id = read_qword(cache_file)
|
||
|
resource_offset = read_dword(cache_file)
|
||
|
resource_decompressed_len = read_dword(cache_file)
|
||
|
resource_compressed_len = read_dword(cache_file)
|
||
|
|
||
|
resource_data = read_resource_data(
|
||
|
cache_file,
|
||
|
resource_offset,
|
||
|
resource_compressed_len
|
||
|
)
|
||
|
|
||
|
if resource_decompressed_len > resource_compressed_len:
|
||
|
resource_data = zlib.decompress(resource_data)
|
||
|
|
||
|
resources.append([
|
||
|
resource_id,
|
||
|
resource_data
|
||
|
])
|
||
|
|
||
|
return resources
|
||
|
|
||
|
|
||
|
def write_dword(cache_file, value):
|
||
|
data = struct.pack('<I', value)
|
||
|
cache_file.write(data)
|
||
|
|
||
|
|
||
|
def write_qword(cache_file, value):
|
||
|
qword = struct.pack('<Q', value)
|
||
|
dwords = [
|
||
|
struct.unpack('<I', qword[:4])[0],
|
||
|
struct.unpack('<I', qword[4:])[0],
|
||
|
]
|
||
|
data = struct.pack('<II', dwords[1], dwords[0])
|
||
|
cache_file.write(data)
|
||
|
|
||
|
|
||
|
def write_bytes(cache_file, value):
|
||
|
cache_file.write(value)
|
||
|
|
||
|
|
||
|
def save_cache_file(filename, resources, compress=True):
|
||
|
cache_file = open(filename, 'wb')
|
||
|
|
||
|
num_resources = len(resources)
|
||
|
|
||
|
last_offset = 0
|
||
|
last_offset += 0x10 # header
|
||
|
last_offset += num_resources * 0x14 # resource_headers
|
||
|
|
||
|
data_start = last_offset
|
||
|
for resource in resources:
|
||
|
resource.append(last_offset)
|
||
|
resource.append(len(resource[1]))
|
||
|
|
||
|
if compress:
|
||
|
resource[1] = zlib.compress(resource[1])
|
||
|
resource.append(len(resource[1]))
|
||
|
|
||
|
last_offset += resource[4]
|
||
|
|
||
|
data_end = last_offset
|
||
|
write_dword(cache_file, num_resources)
|
||
|
write_dword(cache_file, data_start)
|
||
|
write_dword(cache_file, data_end)
|
||
|
write_dword(cache_file, 0xffffffff)
|
||
|
for resource in resources:
|
||
|
write_qword(cache_file, resource[0])
|
||
|
write_dword(cache_file, resource[2])
|
||
|
write_dword(cache_file, resource[3])
|
||
|
write_dword(cache_file, resource[4])
|
||
|
|
||
|
for resource in resources:
|
||
|
write_bytes(cache_file, resource[1])
|