dethrace/tools/decode_datatxt.py

71 lines
1.9 KiB
Python
Executable File

#!/usr/bin/env python
import argparse
import sys
LONG_KEY = (
0x6c, 0x1b, 0x99, 0x5f, 0xb9, 0xcd, 0x5f, 0x13,
0xcb, 0x04, 0x20, 0x0e, 0x5e, 0x1c, 0xa1, 0x0e,
)
OTHER_LONG_KEY = (
0x67, 0xa8, 0xd6, 0x26, 0xb6, 0xdd, 0x45, 0x1b,
0x32, 0x7e, 0x22, 0x13, 0x15, 0xc2, 0x94, 0x37,
)
def decode_line(line: bytes, method: int) -> str:
line = line.rstrip(b"\r\n")
key = LONG_KEY
seed = len(line) % 16
dline = bytearray(len(line))
for i, c in enumerate(line):
if i >= 2:
if line[i - 1] == b'/' and line[i - 2] == b'/':
key = OTHER_LONG_KEY
if method == 1:
if c == ord(b'\t'):
c = 0x80
c -= 0x20
if not (c & 0x80):
c ^= key[seed]
c &= 0x7f
c += 0x20
seed += 7
seed %= 16
if c == 0x80:
c = ord(b'\t')
else:
if c == ord(b'\t'):
c = 0x9f
c -= 0x20
c ^= key[seed]
c &= 0x7f
c += 0x20
seed += 7
seed %= 16
if c == 0x9f:
c = ord(b'\t')
dline[i] = c
return dline.decode(errors="replace")
def main():
parser = argparse.ArgumentParser(allow_abbrev=False, description="Decode a Carmageddon encoded file")
parser.add_argument("file", metavar="FILE", nargs="?", help="input file (default=stdin)")
parser.add_argument("--method", choices=[1, 2], type=int, default=2, help="decryption method to use")
args = parser.parse_args()
istream = open(args.file, "rb") if args.file else sys.stdin.buffer
for line in istream.readlines():
if line[0] == ord(b'@'):
dline = decode_line(line[1:], args.method)
print(dline)
else:
print(line.decode())
if __name__ == "__main__":
raise SystemExit(main())