Skip to content

Instantly share code, notes, and snippets.

@nesrak1
Created January 17, 2022 04:01
Show Gist options
  • Select an option

  • Save nesrak1/c78ae9c744ff76a8cc63efad3c080b58 to your computer and use it in GitHub Desktop.

Select an option

Save nesrak1/c78ae9c744ff76a8cc63efad3c080b58 to your computer and use it in GitHub Desktop.
Removes CRC from StreamingAssets catalog.json file for addressables asset bundles
from enum import Enum
from struct import *
import base64
import json
import io
class BinaryStream:
def __init__(self, base_stream):
self.base_stream = base_stream
def readB(self):
return self.base_stream.read(1)[0]
def readBs(self, length):
return self.base_stream.read(length)
def readC(self):
return self.unpack('b')
def readUC(self):
return self.unpack('B')
def readBl(self):
return self.unpack('?')
def readI16(self):
return self.unpack('h', 2)
def readU16(self):
return self.unpack('H', 2)
def readI32(self):
return self.unpack('i', 4)
def readU32(self):
return self.unpack('I', 4)
def readI64(self):
return self.unpack('q', 8)
def readU64(self):
return self.unpack('Q', 8)
def readF(self):
return self.unpack('f', 4)
def readD(self):
return self.unpack('d', 8)
def readS(self):
length = self.readU16()
return self.unpack(str(length) + 's', length)
def readSL(self, length):
return self.unpack(str(length) + 's', length)
def writeB(self, value):
self.base_stream.write(bytes([value]))
def writeBs(self, value):
self.base_stream.write(value)
def writeC(self, value):
self.pack('c', value)
def writeUC(self, value):
self.pack('C', value)
def writeBl(self, value):
self.pack('?', value)
def writeI16(self, value):
self.pack('h', value)
def writeU16(self, value):
self.pack('H', value)
def writeI32(self, value):
self.pack('i', value)
def writeU32(self, value):
self.pack('I', value)
def writeI64(self, value):
self.pack('q', value)
def writeU64(self, value):
self.pack('Q', value)
def writeF(self, value):
self.pack('f', value)
def writeD(self, value):
self.pack('d', value)
def writeS(self, value):
length = len(value)
self.writeU16(length)
self.pack(str(length) + 's', value)
def writeSL(self, value):
length = len(value)
self.writeB(length)
self.pack(str(length) + 's', value)
def pack(self, fmt, data):
return self.writeBs(pack(fmt, data))
def unpack(self, fmt, length = 1):
return unpack(fmt, self.readBs(length))[0]
def getSize(self):
last_pos = self.base_stream.tell()
self.base_stream.seek(0, 2)
size = self.base_stream.tell()
self.base_stream.seek(last_pos)
return size
def getPos(self):
return self.base_stream.tell()
class ObjectType(Enum):
AsciiString = 0,
UnicodeString = 1,
UInt16 = 2,
UInt32 = 3,
Int32 = 4,
Hash128 = 5,
Type = 6,
JsonObject = 7
class SerializedObject:
def __init__(self, stream):
self.objType = stream.readB()
if ObjectType(self.objType) == ObjectType.JsonObject:
assemblyNameLength = stream.readB()
self.assemblyName = stream.readSL(assemblyNameLength)
classNameLength = stream.readB()
self.className = stream.readSL(classNameLength)
jsonLength = stream.readI32()
self.jsonText = stream.readBs(jsonLength).decode("utf-16")
self.json = json.loads(self.jsonText)
else:
print(f"{ObjectType(objType)} type not supported")
def write(self, stream):
stream.writeB(self.objType)
if ObjectType(self.objType) == ObjectType.JsonObject:
stream.writeSL(self.assemblyName)
stream.writeSL(self.className)
self.jsonText = json.dumps(self.json)
jsonBytes = bytes(self.jsonText, "utf-16")[2:] # trim \xff\xfe
jsonLength = len(jsonBytes)
stream.writeI32(jsonLength)
stream.writeBs(jsonBytes)
else:
print(f"{ObjectType(self.objType)} type not supported")
class Entry:
def __init__(self, stream):
self.internalId = stream.readI32()
self.providerIndex = stream.readI32()
self.dependencyKeyIndex = stream.readI32()
self.depHash = stream.readI32()
self.dataIndex = stream.readI32()
self.primaryKey = stream.readI32()
self.resourceType = stream.readI32()
def write(self, stream):
stream.writeI32(self.internalId)
stream.writeI32(self.providerIndex)
stream.writeI32(self.dependencyKeyIndex)
stream.writeI32(self.depHash)
stream.writeI32(self.dataIndex)
stream.writeI32(self.primaryKey)
stream.writeI32(self.resourceType)
def editCatalog():
with open("settings.json") as settings_file:
settings_json = json.load(settings_file)
ab_directory = settings_json["m_buildTarget"]
#ab_directory = "idc"
with open("catalog.json") as catalog_file:
catalog_json = json.load(catalog_file)
m_ExtraDataString = catalog_json["m_ExtraDataString"]
m_EntryDataString = catalog_json["m_EntryDataString"]
extraData = base64.b64decode(m_ExtraDataString)
extraDataStream = BinaryStream(io.BytesIO(extraData))
entryData = base64.b64decode(m_EntryDataString)
entryDataStream = BinaryStream(io.BytesIO(entryData))
entryDataCount = entryDataStream.readI32()
dataEntries = []
for i in range(entryDataCount):
e = Entry(entryDataStream)
#print(f"{e.internalId} / {e.providerIndex} / {e.dependencyKeyIndex} / {e.depHash} / {e.dataIndex} / {e.primaryKey} / {e.resourceType}")
dataEntries.append(e)
extraDataEntries = []
for entry in dataEntries:
if entry.dataIndex == -1:
continue
extraDataStream.base_stream.seek(entry.dataIndex)
serializedObject = SerializedObject(extraDataStream)
serializedObject.dataEntry = entry
extraDataEntries.append(serializedObject)
for entry in extraDataEntries:
m_Hash = entry.json["m_Hash"]
print(f"clearing crc for {ab_directory}/xxx_{m_Hash}.bundle")
entry.json["m_Crc"] = 0
newExtraDataStream = BinaryStream(io.BytesIO())
newEntryDataStream = BinaryStream(io.BytesIO())
for entry in extraDataEntries:
startPos = newExtraDataStream.getPos()
entry.dataEntry.dataIndex = startPos
entry.write(newExtraDataStream)
newEntryDataStream.writeI32(len(dataEntries))
for entry in dataEntries:
entry.write(newEntryDataStream)
newExtraData = base64.b64encode(newExtraDataStream.base_stream.getvalue()).decode("utf-8")
newEntryData = base64.b64encode(newEntryDataStream.base_stream.getvalue()).decode("utf-8")
catalog_json["m_ExtraDataString"] = newExtraData
catalog_json["m_EntryDataString"] = newEntryData
with open("catalog_new.json", "w") as catalog_new_file:
json.dump(catalog_json, catalog_new_file)
editCatalog()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment