Support all .wpak files with a wpak target
Replaces the config target with wpak, which handles every known pak or a single one named on the command line. Map icon .tga entries are stored unencrypted (sb.exe 0xAACA60). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8a8ebc5632
commit
b2e38bdc06
2 files changed
+85
-47
No files matched your search
@@ -13,7 +13,8 @@ import zipfile
|
||||
from .ArcFileCache import next_available_path
|
||||
|
||||
# A .wpak is a zip (client uses minizip, ArcWPakFile 0x54D3C0) whose entries are
|
||||
# each Blowfish CFB-64 encrypted with a zero IV (BF_cfb64_encrypt 0xCD9000).
|
||||
# each Blowfish CFB-64 encrypted with a zero IV (BF_cfb64_encrypt 0xCD9000),
|
||||
# except image entries.
|
||||
WPAK_KEY = bytes([
|
||||
0x85, 0x71, 0x40, 0x3C, 0x14, 0x50, 0x0B, 0x52,
|
||||
0x73, 0x2D, 0x10, 0x08, 0x63, 0x59, 0x5B, 0xAA,
|
||||
@@ -21,6 +22,9 @@ WPAK_KEY = bytes([
|
||||
|
||||
WPAK_COMPRESS_LEVEL = 9 # zipOpenNewFileInZip level in ArcWPakFile writer
|
||||
|
||||
# Map icon paks keep their .tga entries unencrypted (LoadMapZoneData 0xAACA60).
|
||||
WPAK_PLAIN_EXTENSIONS = ('.tga',)
|
||||
|
||||
MASK32 = 0xFFFFFFFF
|
||||
|
||||
|
||||
@@ -129,6 +133,10 @@ class ArcBlowfish:
|
||||
WPAK_CIPHER = ArcBlowfish(WPAK_KEY)
|
||||
|
||||
|
||||
def is_encrypted_entry(filename):
|
||||
return not filename.lower().endswith(WPAK_PLAIN_EXTENSIONS)
|
||||
|
||||
|
||||
def load_wpak_file(filename):
|
||||
entries = []
|
||||
|
||||
@@ -136,10 +144,10 @@ def load_wpak_file(filename):
|
||||
for info in wpak_file.infolist():
|
||||
if info.is_dir():
|
||||
continue
|
||||
entries.append([
|
||||
info.filename,
|
||||
WPAK_CIPHER.cfb64_decrypt(wpak_file.read(info))
|
||||
])
|
||||
data = wpak_file.read(info)
|
||||
if is_encrypted_entry(info.filename):
|
||||
data = WPAK_CIPHER.cfb64_decrypt(data)
|
||||
entries.append([info.filename, data])
|
||||
|
||||
return entries
|
||||
|
||||
@@ -147,7 +155,7 @@ def load_wpak_file(filename):
|
||||
def load_wpak_directory(directory):
|
||||
entries = []
|
||||
|
||||
# Original archives list entries in NTFS directory order (uppercase-folded sort).
|
||||
# Client finds entries by name (unzLocateFile 0xCD7920), so order only needs to be stable.
|
||||
for filename in sorted(os.listdir(directory), key=str.upper):
|
||||
filepath = os.path.join(directory, filename)
|
||||
if not os.path.isfile(filepath):
|
||||
@@ -163,11 +171,9 @@ def build_wpak_bytes(entries, wpak_file):
|
||||
for filename, data in entries:
|
||||
info = zipfile.ZipInfo(filename, date_time=time.localtime()[:6])
|
||||
info.compress_type = zipfile.ZIP_DEFLATED
|
||||
archive.writestr(
|
||||
info,
|
||||
WPAK_CIPHER.cfb64_encrypt(data),
|
||||
compresslevel=WPAK_COMPRESS_LEVEL
|
||||
)
|
||||
if is_encrypted_entry(filename):
|
||||
data = WPAK_CIPHER.cfb64_encrypt(data)
|
||||
archive.writestr(info, data, compresslevel=WPAK_COMPRESS_LEVEL)
|
||||
|
||||
|
||||
def save_wpak_file(filename, entries):
|
||||
|
||||
Reference in new issue
Block a user