mbEditorPro2.0 release
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
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])
|
||||
@@ -0,0 +1,108 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
class ResStream:
|
||||
def __init__(self, initial_bytes=b''):
|
||||
self.buffer = BytesIO(initial_bytes)
|
||||
|
||||
def read_byte(self):
|
||||
data = self.buffer.read(1)
|
||||
return struct.unpack('<B', data)[0]
|
||||
|
||||
def read_bytes(self, n):
|
||||
data = self.buffer.read(n)
|
||||
return data
|
||||
|
||||
def read_word(self):
|
||||
data = self.buffer.read(2)
|
||||
return struct.unpack('<H', data)[0]
|
||||
|
||||
def read_dword(self):
|
||||
data = self.buffer.read(4)
|
||||
return struct.unpack('<I', data)[0]
|
||||
|
||||
def read_qword(self):
|
||||
dwords = struct.unpack('<II', self.buffer.read(8))
|
||||
buffer = struct.pack('<II', dwords[1], dwords[0])
|
||||
return struct.unpack('<Q', buffer)[0]
|
||||
|
||||
def read_float(self):
|
||||
data = self.buffer.read(4)
|
||||
return struct.unpack('<f', data)[0]
|
||||
|
||||
def read_tuple(self):
|
||||
data = self.buffer.read(12)
|
||||
return struct.unpack('<fff', data)
|
||||
|
||||
def read_bool(self):
|
||||
data = self.buffer.read(1)
|
||||
return True if struct.unpack('<B', data)[0] else False
|
||||
|
||||
def read_wchar(self):
|
||||
data = self.buffer.read(2)
|
||||
return chr(struct.unpack('<H', data)[0])
|
||||
|
||||
def read_string(self):
|
||||
length = self.read_dword()
|
||||
data = [self.read_wchar() for _ in range(length)]
|
||||
return ''.join(data)
|
||||
|
||||
def write_byte(self, value):
|
||||
data = struct.pack('<B', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_bytes(self, value):
|
||||
data = value
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_word(self, value):
|
||||
data = struct.pack('<H', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_dword(self, value):
|
||||
data = struct.pack('<I', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_qword(self, 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])
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_float(self, value):
|
||||
data = struct.pack('<f', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_tuple(self, value):
|
||||
data = struct.pack('<fff', *value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_bool(self, value):
|
||||
data = struct.pack('<B', 1 if value else 0)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_wchar(self, value):
|
||||
data = struct.pack('<H', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_string(self, value):
|
||||
length = len(value)
|
||||
self.write_dword(length)
|
||||
for char in value.encode('utf-16-le'):
|
||||
self.write_byte(char)
|
||||
|
||||
def get_bytes(self):
|
||||
self.buffer.seek(0)
|
||||
return self.buffer.read()
|
||||
@@ -0,0 +1,10 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
from .ArcFileCache import load_cache_file, save_cache_file
|
||||
from .ResStream import ResStream
|
||||
@@ -0,0 +1,47 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
|
||||
def _hash_string_short(array):
|
||||
v04 = (8 * array[7]) & 0xffffffff
|
||||
v05 = v04 ^ array[4]
|
||||
v06 = (16 * v05) & 0xffffffff
|
||||
v07 = array[5] ^ v06
|
||||
v08 = (16 * v07) & 0xffffffff
|
||||
v09 = array[6] ^ v08
|
||||
v10 = (32 * v09) & 0xffffffff
|
||||
v11 = array[2] ^ v10
|
||||
v12 = (32 * v11) & 0xffffffff
|
||||
v13 = (array[1] ^ v12)
|
||||
v14 = (32 * v13) & 0xffffffff
|
||||
v15 = (array[7] ^ 0x5A0) >> 2
|
||||
return array[0] ^ (v15) ^ (v14)
|
||||
|
||||
|
||||
def _hash_string_long(array):
|
||||
i = 0
|
||||
result = 0
|
||||
for c in array:
|
||||
v = c - 32
|
||||
result ^= (v << (i)) & 0xffffffff
|
||||
if i > 0x18:
|
||||
result ^= v >> (32 - i)
|
||||
if i >= 0x1b:
|
||||
i -= 32
|
||||
i += 5
|
||||
return result & 0xffffffff
|
||||
|
||||
|
||||
def hash_string(string):
|
||||
array = bytearray(string.encode())
|
||||
length = len(string)
|
||||
|
||||
if (length == 7 or length == 8) and string[3] == '-':
|
||||
array += bytearray(b'\x00')
|
||||
return _hash_string_short(array)
|
||||
else:
|
||||
return _hash_string_long(array)
|
||||
@@ -0,0 +1,19 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄
|
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪
|
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄
|
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌
|
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪
|
||||
# Magicbane Emulator Project © 2013 - 2022
|
||||
# www.magicbane.com
|
||||
#
|
||||
|
||||
def int32(x):
|
||||
if x > 0xFFFFFFFF:
|
||||
raise OverflowError
|
||||
if x > 0x7FFFFFFF:
|
||||
x = int(0x100000000 - x)
|
||||
if x < 2147483648:
|
||||
return -x
|
||||
else:
|
||||
return -2147483648
|
||||
return x
|
||||
Reference in New Issue
Block a user