/
ReplayReader.py
85 lines (72 loc) · 2.92 KB
/
ReplayReader.py
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
from struct import *
import StringIO
from ArchiveHeader import ArchiveHeader
from UserData import UserData
from BlockTable import BlockTable
class ReplayReader(object):
"""Takes responsibility for reading the entire replay.
Also implements some general use algorithms.
"""
def __init__(self, file_name):
self._file_name = file_name
self._user_data = None
self._archive_header = None
self._block_table = None
self._file_contents = None
self._crypt_table = range(0x500)
self.create_crypt_table()
def read(self):
self._file_contents = open(self._file_name, 'rb')
self._user_data = UserData(self._file_contents)
if not self._user_data.read():
return False
print self._user_data
self._archive_header = ArchiveHeader(self._file_contents, self._user_data)
if not self._archive_header.read():
return False
print self._archive_header
self._block_table = BlockTable(self._file_contents, self._archive_header, self)
self._block_table.read()
print self._block_table
def create_crypt_table(self):
seed = 0x00100001
for index1 in range(0x100):
index2 = index1
for i in range(5):
seed = (seed * 125 + 3) % 0x2AAAAB
temp1 = (seed & 0xFFFF) << 0x10
seed = (seed * 125 + 3) % 0x2AAAAB
temp2 = seed & 0xFFFF
self._crypt_table[index2] = (temp1 | temp2)
index2 += 0x100
def decrypt(self, data_block, length, key):
"""in place, length is in bytes, key is an int"""
seed = 0xEEEEEEEE
# round to int32's
# If the data isn't a multiple of int32s, then the remaining bytes will
# not get decrypted.
length >>= 2
data_block_index = 0
accumulator = StringIO.StringIO()
while(length > 0):
length -= 1
seed += self._crypt_table[0x400 + (key & 0xFF)]
ch = unpack('=I', data_block[data_block_index:data_block_index + 4])[0] ^ ((key + seed) & 0xFFFFFFFF)
key = ((((~key << 0x15) & 0xFFFFFFFF) + 0x11111111) & 0xFFFFFFFF) | (key >> 0x0B)
seed = (ch + seed + (seed << 5) + 3) & 0xFFFFFFFF
accumulator.write(pack("=I", ch))
data_block_index += 4
return accumulator.getvalue()
def hash(self, name, hash_type):
seed1 = 0x7FED7FED
seed2 = 0xEEEEEEEE
for ch in name:
ch = ord(ch.upper())
seed1 = self._crypt_table[(hash_type << 8) + ch] ^ (seed1 + seed2) & 0xFFFFFFFF
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3 & 0xFFFFFFFF
return seed1
if __name__ == "__main__":
# replay_reader = ReplayReader('samples/Victory-of-the-Year.SC2Replay')
replay_reader = ReplayReader('samples/2v2.sc2replay')
replay_reader.read()
print 'Done'