Add pack softpal text dat script
This commit is contained in:
69
pack_softpal_text_dat.py
Normal file
69
pack_softpal_text_dat.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import struct
|
||||
from os.path import splitext
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
def rotate_right(val, rshift):
|
||||
return ((val >> rshift) | ((val << (8 - rshift)) & 0xFF)) & 0xFF
|
||||
|
||||
|
||||
def encrypt_bytes(data: bytes) -> bytes:
|
||||
# Matches inverse of decrypt in unpack_softpal_text_dat.py
|
||||
CONST = 0x084DF873 ^ 0xFF987DEE
|
||||
b = bytearray(data)
|
||||
pos = 0x10
|
||||
shift = 4
|
||||
while pos + 4 <= len(b):
|
||||
val = struct.unpack('<I', b[pos:pos+4])[0]
|
||||
val ^= CONST
|
||||
packed = bytearray(struct.pack('<I', val))
|
||||
packed[0] = rotate_right(packed[0], shift)
|
||||
b[pos:pos+4] = packed
|
||||
pos += 4
|
||||
shift = (shift + 1) % 8
|
||||
return bytes(b)
|
||||
|
||||
|
||||
def pack_table(table: dict, encoding: str = 'cp932', encrypt: bool = True) -> bytes:
|
||||
# header: 12 bytes (unused by unpack)
|
||||
header = b"\x00" * 12
|
||||
items = sorted(((int(k), v) for k, v in table.items()), key=lambda x: x[0])
|
||||
count = len(items)
|
||||
out = bytearray()
|
||||
out += header
|
||||
out += struct.pack('<I', count)
|
||||
# After this, the first u32 at offset 16 will be the first key
|
||||
# We'll write entries immediately after (so first key sits at offset 16)
|
||||
for key, s in items:
|
||||
out += struct.pack('<I', key)
|
||||
if isinstance(s, str):
|
||||
encoded = s.encode(encoding)
|
||||
else:
|
||||
encoded = bytes(s)
|
||||
out += encoded + b'\x00'
|
||||
if encrypt:
|
||||
out = encrypt_bytes(bytes(out))
|
||||
return bytes(out)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python pack_softpal_text_dat.py <input.json> [<output.dat>] [<encoding>] [--no-encrypt]")
|
||||
sys.exit(1)
|
||||
|
||||
infile = sys.argv[1]
|
||||
outfile = sys.argv[2] if len(sys.argv) > 2 else splitext(infile)[0] + '.dat'
|
||||
encoding = sys.argv[3] if len(sys.argv) > 3 and not sys.argv[3].startswith('--') else 'cp932'
|
||||
encrypt = True
|
||||
if '--no-encrypt' in sys.argv:
|
||||
encrypt = False
|
||||
|
||||
with open(infile, 'r', encoding='utf-8') as f:
|
||||
table = json.load(f)
|
||||
|
||||
data = pack_table(table, encoding=encoding, encrypt=encrypt)
|
||||
with open(outfile, 'wb') as f:
|
||||
f.write(data)
|
||||
|
||||
print(f'Wrote {outfile} ({len(data)} bytes)')
|
||||
Reference in New Issue
Block a user