Add script to unpack softpal text.dat
This commit is contained in:
73
unpack_softpal_text_dat.py
Normal file
73
unpack_softpal_text_dat.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import struct
|
||||||
|
from io import BytesIO
|
||||||
|
import json
|
||||||
|
from os.path import splitext
|
||||||
|
|
||||||
|
|
||||||
|
def read_u32(f):
|
||||||
|
return struct.unpack('<I', f.read(4))[0]
|
||||||
|
|
||||||
|
|
||||||
|
def read_cstring(f):
|
||||||
|
chars = []
|
||||||
|
while True:
|
||||||
|
c = f.read(1)
|
||||||
|
if c == b'\x00' or c == b'':
|
||||||
|
break
|
||||||
|
chars.append(c)
|
||||||
|
return b''.join(chars)
|
||||||
|
|
||||||
|
|
||||||
|
def rotate_left(val, rshift):
|
||||||
|
return ((val << rshift) & 0xFF) | (val >> (8 - rshift))
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt(data: bytes) -> BytesIO:
|
||||||
|
pos = 0x10
|
||||||
|
shift = 4
|
||||||
|
decrypted = bytearray(data)
|
||||||
|
while pos + 4 <= len(decrypted):
|
||||||
|
data = decrypted[pos:pos+4]
|
||||||
|
data[0] = rotate_left(data[0], shift)
|
||||||
|
shift = (shift + 1) % 8
|
||||||
|
data = struct.unpack('<I', data)[0]
|
||||||
|
data ^= 0x084DF873 ^ 0xFF987DEE
|
||||||
|
decrypted[pos:pos+4] = struct.pack('<I', data)
|
||||||
|
pos += 4
|
||||||
|
return BytesIO(decrypted)
|
||||||
|
|
||||||
|
|
||||||
|
def load_text_data(f, e):
|
||||||
|
f.read(12) # Skip header
|
||||||
|
count = read_u32(f)
|
||||||
|
first_idx = read_u32(f)
|
||||||
|
if first_idx != 0:
|
||||||
|
f.seek(0)
|
||||||
|
f = decrypt(f.read())
|
||||||
|
f.read(16)
|
||||||
|
first_idx = read_u32(f)
|
||||||
|
f.seek(16)
|
||||||
|
table = {}
|
||||||
|
for j in range(count):
|
||||||
|
cur = read_u32(f)
|
||||||
|
s = read_cstring(f).decode(e)
|
||||||
|
table[cur] = s
|
||||||
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python unpack_softpal_text_dat.py <file> [<output>] [<encoding>]")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
filename = sys.argv[1]
|
||||||
|
output = sys.argv[2] if len(sys.argv) > 2 else splitext(filename)[0] + '.json'
|
||||||
|
encoding = sys.argv[3] if len(sys.argv) > 3 else 'cp932'
|
||||||
|
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
table = load_text_data(f, encoding)
|
||||||
|
with open(output, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(table, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
Reference in New Issue
Block a user