Skip to content

Commit

Permalink
support 539099965
Browse files Browse the repository at this point in the history
  • Loading branch information
dtlnor committed Apr 2, 2023
1 parent 3c98da9 commit cfd6c80
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 17 deletions.
32 changes: 22 additions & 10 deletions REMSG.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,28 @@

VERSION_2_LANG_COUNT : Final[dict[int,int]] = {
12 : 23,
0x2022033D : 27,
14 : 28,
15 : 30,
17 : 32,
20 : 33,
0x20220626 : 33, # before 13.0.0, 0x20220626 has 32 lang count
22 : 33,
}
"""lang count in each msg version.
0x20220626 has 32 lang count in early version"""


def isVersionEncrypt(version: int) -> bool:
"""check if dataOffset exist"""
return (version > 12 and version != 0x2022033D)


def isVersionEntryByHash(version: int) -> bool:
"""check if Entry haed index by hash"""
return (version > 15 and version != 0x2022033D)


class Entry:
"""meat of MSG"""
def __init__(self, version):
Expand All @@ -124,7 +136,7 @@ def readHead(self, filestream: io.BufferedReader, langCount: int):
self.guid = uuid.UUID(bytes_le=struct.unpack("<16s", filestream.read(16))[0],)
self.crc, = struct.unpack("<I", filestream.read(4))
# actually I don't have a version 16 msg file so idk if 16 use hash or index
if (self.version > 15):
if isVersionEntryByHash(self.version):
self.hash, = struct.unpack("<I", filestream.read(4))
else:
self.index, = struct.unpack("<I", filestream.read(4))
Expand All @@ -140,7 +152,7 @@ def writeHead(self, bytestream: bytearray):
"""extend the bytearray by filling entry head"""
bytestream.extend(struct.pack("<16s", self.guid.bytes_le))
bytestream.extend(struct.pack("<I", self.crc))
if (self.version > 15):
if isVersionEntryByHash(self.version):
bytestream.extend(struct.pack("<I", self.hash))
else:
bytestream.extend(struct.pack("<I", self.index))
Expand Down Expand Up @@ -200,7 +212,7 @@ def buildEntry(self, guid: str, crc: int, name: str, attributeValues: list, lang
"""use for file modification"""
self.guid = uuid.UUID(hex=guid)
self.crc = crc
if (self.version > 15):
if isVersionEntryByHash(self.version):
self.hash = hash
else:
self.index = index
Expand Down Expand Up @@ -229,7 +241,7 @@ def readMSG(self, filestream: io.BufferedReader):
attributeCount, = struct.unpack("<I", filestream.read(4))
langCount, = struct.unpack("<I", filestream.read(4))
seek_align_up(filestream, 8) # pad to 8
if version > 12:
if isVersionEncrypt(version):
dataOffset, = struct.unpack("<Q", filestream.read(8))
unknDataOffset, = struct.unpack("<Q", filestream.read(8))
langOffset, = struct.unpack("<Q", filestream.read(8))
Expand Down Expand Up @@ -286,7 +298,7 @@ def readMSG(self, filestream: io.BufferedReader):
entry.readAttributes(filestream, attributeHeaders)

# read / decrypt string pool
if (version > 12):
if isVersionEncrypt(version):
assert dataOffset == filestream.tell(), f"expected dataOffset at {dataOffset} but at {filestream.tell()}"
else:
dataOffset = filestream.tell()
Expand All @@ -295,7 +307,7 @@ def readMSG(self, filestream: io.BufferedReader):
assert dataSize % 2 == 0, f"wstring pool size should be even: {dataSize}"
filestream.seek(dataOffset) # start of string pool
data = filestream.read(dataSize)
if (version > 12):
if isVersionEncrypt(version):
wcharPool = helper.decrypt(data)
else:
wcharPool = data
Expand All @@ -309,7 +321,7 @@ def readMSG(self, filestream: io.BufferedReader):
for entryIndex, entry in enumerate(entrys):
# set entry name
entry.setName(helper.seekString((entry.entryNameOffset - dataOffset), stringDict))
if (version > 15):
if isVersionEntryByHash(version):
nameHash = mmh3.hash(key = entry.name.encode('utf-16-le'), seed = -1, signed = False)
assert nameHash == entry.hash, f"expected {entry.hash} for {entry.name} but get {nameHash}"
else:
Expand Down Expand Up @@ -354,7 +366,7 @@ def writeMSG(self) -> bytes:
langCount = len(self.languages)
newFile.extend(struct.pack("<I", langCount))
newFile.extend(b'\x00'*(len(newFile) % 8)) # pad to 8
if self.version > 12:
if isVersionEncrypt(self.version):
dataOffsetPH = len(newFile)
newFile.extend(struct.pack("<q", -1))
unknDataOffsetPH = len(newFile)
Expand Down Expand Up @@ -399,7 +411,7 @@ def writeMSG(self) -> bytes:

# read / decrypt string pool
dataOffset = len(newFile)
if (self.version > 12):
if isVersionEncrypt(self.version):
newFile[dataOffsetPH:dataOffsetPH+8] = struct.pack("<Q", len(newFile))

# construct string pool
Expand All @@ -424,7 +436,7 @@ def writeMSG(self) -> bytes:
# strOffsetDict = dict((v,k) for k,v in self.stringDict.items())
wcharPool = b''.join(helper.toWcharBytes(x) for x in strOffsetDict.keys())

if self.version > 12:
if isVersionEncrypt(self.version):
newFile.extend(helper.encrypt(wcharPool))
else:
newFile.extend(wcharPool)
Expand Down
14 changes: 7 additions & 7 deletions REMSGUtil.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,19 @@ def importCSV(msgObj: MSG, filename: str, version: int = None, langCount: int =
name = fEntry[nameidx],
attributeValues = attributes,
langs = [helper.forceWindowsLineBreak(fEntry[i]) for i in langidxs],
hash = mmh3.hash(key = fEntry[nameidx].encode('utf-16-le'), seed = -1, signed = False) if version > 15 else None,
index = i if version <= 15 else None)
hash = mmh3.hash(key = fEntry[nameidx].encode('utf-16-le'), seed = -1, signed = False) if isVersionEntryByHash(version) else None,
index = i if not(isVersionEntryByHash(version)) else None)

# not gonna check, left it to user
# if entry.guid in oldEntrys.keys():
# assert entry.crc == oldEntrys[entry.guid].crc
# assert entry.name == oldEntrys[entry.guid].name
# if (version > 15):
# if isVersionEntryByHash(version):
# assert entry.hash == oldEntrys[entry.guid].hash
# else:
# assert entry.index == entry.index
# else:
# if (version > 15):
# if isVersionEntryByHash(version):
# if entry.hash != mmh3.hash(key = entry.name.encode('utf-16-le'), seed = -1, signed = False):
# print(f"Incorrect hash value for {entry.name}, filling a correct one")
# entry.hash = mmh3.hash(key = entry.name.encode('utf-16-le'), seed = -1, signed = False)
Expand Down Expand Up @@ -283,7 +283,7 @@ def buildmhriceJson(msg: MSG) -> dict:
"name": entry.name,
"guid": str(entry.guid),
"crc?": entry.crc,
"hash": entry.hash if msg.version > 15 else 0xFFFFFFFF,
"hash": entry.hash if isVersionEntryByHash(msg.version) else 0xFFFFFFFF,
"attributes" : list([{valueTypeEnum(attrh["valueType"]): entry.attributes[i]}
for i, attrh in enumerate(msg.attributeHeaders)]),
"content" : list([entry.langs[lang]
Expand Down Expand Up @@ -329,8 +329,8 @@ def importJson(msgObj: MSG, filename: str):
attributeValues=list([ readAttributeFromStr(next(iter(attr.values())), msg.attributeHeaders[i]["valueType"])
for i, attr in enumerate(jEntry["attributes"])]),
langs=list([ helper.forceWindowsLineBreak(content) for content in jEntry["content"] ]),
hash=mmh3.hash(key = jEntry["name"].encode('utf-16-le'), seed = -1, signed = False) if msg.version > 15 else None,
index = jIndex if msg.version <= 15 else None
hash=mmh3.hash(key = jEntry["name"].encode('utf-16-le'), seed = -1, signed = False) if isVersionEntryByHash(msg.version) else None,
index = jIndex if not(isVersionEntryByHash(msg.version)) else None
)

newEntrys.append(entry)
Expand Down

0 comments on commit cfd6c80

Please sign in to comment.