-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathDAT decoder.py
More file actions
135 lines (118 loc) · 4.92 KB
/
DAT decoder.py
File metadata and controls
135 lines (118 loc) · 4.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from pprint import pprint
DAT_FILE_PATH = r"path goes here"
class Decoder:
Values = [
"graphic_detail", "sfx_vol", "defaultScrollProgress", "music_vol",
"swearFilter", "fullscreen", "pass_update", "tankid_password_chk2",
"legal_progress", "name", "lastworld", "tankid_checkbox",
"tankid_name", "tankid_password", "enter", "defaultInventoryHeight",
"defaultLogHeight", "Client", "meta", "rid", "touch", "rememberZoom",
"sendSkinColor", "zoomSave", "addJump", "skinColor"
]
pTypes = ["checkbox", "slider", "edit", "color", "password", "unknown"]
pType = [
5, 5, 5, 5, 5, 0, 5, 5, 5, 2, 2, 0, 2, 4, 0, 5, 5, 5, 2, 2, 0, 0, 5, 5, 0, 5
]
defValues = [1, 4, 16, 64, 256, 1024]
pChars = ""
pSize = 0
Positions = []
PositionLength = []
useFilter = True
def __init__(self, path):
self.openFile(path)
def openFile(self, path):
try:
with open(path, 'rb') as file:
content = file.read()
self.pSize = len(content)
self.pChars = content.decode('latin-1', errors='ignore')
return True
except Exception as e:
print(f"An error occurred while reading save file: {e}")
return False
def ValidateChar(self, t):
if not self.useFilter:
return True
if 0x40 <= ord(t) <= 0x5A or 0x61 <= ord(t) <= 0x7A or 0x30 <= ord(t) <= 0x39 or 0x2B <= ord(t) <= 0x2E:
return True
return False
def ValidateString(self, text):
return all(self.ValidateChar(c) for c in text)
def DecodeFile(self):
if not self.pChars or "tankid_password" not in self.pChars:
return [("Error", ["An error occurred while searching for tankid_password"])]
self.Positions.clear()
self.PositionLength.clear()
for i, value in enumerate(self.Values):
start = self.pChars.find(value)
if start != -1 and value == "tankid_password" and self.pChars[start + len(value)] == '_':
buf = self.pChars[start + 1:].find(value)
if buf != -1:
start += buf + 1
else:
start = -1
self.Positions.append(start)
for i, pos in enumerate(self.Positions):
if pos != -1:
PosEndBuffer = len(self.pChars)
for j, other_pos in enumerate(self.Positions):
if other_pos > pos and other_pos < PosEndBuffer:
PosEndBuffer = other_pos
self.PositionLength.append(PosEndBuffer)
else:
self.PositionLength.append(0)
for i, pos in enumerate(self.Positions):
if pos != -1:
self.Positions[i] += len(self.Values[i])
self.PositionLength[i] -= self.Positions[i]
content = []
for i, pos in enumerate(self.Positions):
if pos != -1 and self.pType[i] != 5:
content.append((self.Values[i], self.ListTrigger(i)))
return content
def ListTrigger(self, value):
if value >= len(self.Values):
return ["Value pointer overflow"]
pType = self.pType[value]
pos = self.Positions[value]
if pType == 0:
return ["true"] if self.pChars[pos] == '\x01' else ["false"]
elif pType == 2:
stringLength = ord(self.pChars[pos])
return [self.pChars[pos + 4: pos + 4 + stringLength]]
elif pType == 4:
stringLength = ord(self.pChars[pos])
passwordBuffer = self.pChars[pos + 4: pos + 4 + stringLength]
return self.decodePassword(passwordBuffer, True)
else:
return ["unknown type id!"]
def customIndexOf(self, result, buffer):
buffer_lower = buffer.lower()
for i, item in enumerate(result):
if item.lower() == buffer_lower:
return i
return -1
def decodePassword(self, password, file):
result = []
buffer = ""
cbuffer = 0
pbuffer = -1
password = password.replace('rid','')
for offset in range(-128, 128):
buffer = ""
for i in range(len(password)):
cbuffer = (ord(password[i]) + offset - (i if file else 0)) % 255
if not self.ValidateChar(chr(cbuffer)):
break
buffer += chr(cbuffer)
if len(buffer) >= len(password):
if not self.useFilter or (pbuffer := self.customIndexOf(result, buffer)) == -1:
result.append(buffer)
elif self.useFilter and pbuffer != -1 and self.toLowercase(result[pbuffer]) == self.toLowercase(buffer):
result[pbuffer] = buffer
return result
if __name__ == "__main__":
decoder = Decoder(DAT_FILE_PATH)
decoded_content = decoder.DecodeFile()
pprint(decoded_content)