diff --git a/src/DETHRACE/common/utility.c b/src/DETHRACE/common/utility.c index 9e28473a..9446fff7 100644 --- a/src/DETHRACE/common/utility.c +++ b/src/DETHRACE/common/utility.c @@ -26,16 +26,16 @@ #define MIN_SERVICE_INTERVAL 200 // << -int gIn_check_quit; -tU32 gLost_time; +int gIn_check_quit = 0; +tU32 gLost_time = 0; #if BR_ENDIAN_BIG -tU32 gLong_key[4] = { 0x6C1B995F, 0xB9CD5F13, 0xCB04200E, 0x5E1CA10E }; -tU32 gOther_long_key[4] = { 0x67A8D626, 0xB6DD451B, 0x327E2213, 0x15C29437}; +tU32 gLong_key[4] = { 0x6c1b995f, 0xb9cd5f13, 0xcb04200e, 0x5e1ca10e }; +tU32 gOther_long_key[4] = { 0x67a8d626, 0xb6dd451b, 0x327e2213, 0x15c29437}; #else -tU32 gLong_key[4] = { 0x5F991B6C, 0x135FCDB9, 0x0E2004CB, 0x0EA11C5E }; -tU32 gOther_long_key[4] = { 0x26D6A867, 0x1B45DDB6, 0x13227E32, 0x3794C215 }; +tU32 gLong_key[4] = { 0x5f991b6c, 0x135fcdb9, 0x0e2004cb, 0x0ea11c5e }; +tU32 gOther_long_key[4] = { 0x26d6a867, 0x1b45ddb6, 0x13227e32, 0x3794c215 }; #endif -int gEncryption_method; +int gEncryption_method = 0; char* gMisc_strings[250]; br_pixelmap* g16bit_palette; br_pixelmap* gSource_for_16bit_palette; @@ -1168,31 +1168,34 @@ void DecodeLine2(char* pS) { } if (gEncryption_method == 1) { if (c == '\t') { - c = 0x80; + c = 0x9f; } - c -= 0x20; - if (!(c & 0x80)) { - c = (c ^ key[seed]) & 0x7f; - c += 0x20; - } - seed += 7; - seed = seed % 16; - if (c == 0x80) { + c -= 0x20; + c ^= key[seed]; + c &= 0x7f; + c += 0x20; + + seed += 7; + seed %= 16; + + if (c == 0x9f) { c = '\t'; } } else { if (c == '\t') { - c = 0x9f; + c = 0x80; } c -= 0x20; - c = (c ^ key[seed]) & 0x7f; + if ((c & 0x80) == 0) { + c ^= key[seed] & 0x7f; + } c += 0x20; seed += 7; - seed = seed % 16; + seed %= 16; - if (c == 0x9f) { + if (c == 0x80) { c = '\t'; } } diff --git a/test/DETHRACE/test_utility.c b/test/DETHRACE/test_utility.c index 36c9642a..83451224 100644 --- a/test/DETHRACE/test_utility.c +++ b/test/DETHRACE/test_utility.c @@ -18,7 +18,7 @@ void test_utility_EncodeLinex() { void test_utility_DecodeLine2() { char buf[50]; - gEncryption_method = 1; + gEncryption_method = 2; // first line of GENERAL.TXT, "@" prefix and line ending stripped char input[] = "\x29\x2a\x9c\x22\x61\x4d\x5e\x5f\x60\x34\x64\x57\x8d\x2b\x82\x7b\x33\x4c"; strcpy(buf, input); diff --git a/tools/decode_datatxt.py b/tools/decode_datatxt.py index 6e597f6a..f81c83a7 100755 --- a/tools/decode_datatxt.py +++ b/tools/decode_datatxt.py @@ -13,43 +13,94 @@ OTHER_LONG_KEY = ( ) +class Byte: + def __init__(self, v: int): + self.v = v & 0xff + + def __add__(self, v: int): + return Byte(self.v + v) + + def __iadd__(self, v: "Byte"): + self.v = (self.v + v) & 0xff + return self + + def __sub__(self, v: int): + return Byte(self.v - v) + + def __isub__(self, v: "Byte"): + self.v = (self.v - v) & 0xff + return self + + def __mod__(self, v: int): + return Byte(self.v % v) + + def __imod__(self, v: int): + self.v %= v + return self + + def __xor__(self, v: int): + return Byte(self.v ^ v) + + def __ixor__(self, v: int): + self.v = (self.v ^ v) & 0xff + return self + + def __and__(self, v: int): + return Byte(self.v & v) + + def __iand__(self, v: int): + self.v = (self.v & v) & 0xff + return self + + def __eq__(self, other): + if isinstance(other, Byte): + return self.v == other.v + elif isinstance(other, int): + return self.v == (other & 0xff) + raise ValueError(f"Object {other:r} of invalid type {type(other)}") + + def decode_line(line: bytes, method: int) -> str: line = line.rstrip(b"\r\n") key = LONG_KEY - seed = len(line) % 16 + seed = len(line) % len(LONG_KEY) 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 + b = Byte(c) + if dline[i - 2:i] == 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 + if b == ord(b'\t'): + b = Byte(0x9f) + + b -= 0x20 + b ^= key[seed] + b &= 0x7f + b += 0x20 seed += 7 - seed %= 16 - if c == 0x80: - c = ord(b'\t') + seed %= len(key) + + if b == 0x9f: + b = Byte(ord(b'\t')) else: - if c == ord(b'\t'): - c = 0x9f - c -= 0x20 - c ^= key[seed] - c &= 0x7f - c += 0x20 + if b == ord(b'\t'): + b = Byte(0x80) + + b -= 0x20 + if (b & 0x80) == 0: + b ^= key[seed] & 0x7f + b += 0x20 seed += 7 - seed %= 16 - if c == 0x9f: - c = ord(b'\t') - dline[i] = c + seed %= len(key) + + if b == 0x80: + b = Byte(ord(b'\t')) + dline[i] = b.v 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)")