Skip to content

Instantly share code, notes, and snippets.

@bsmt
Created September 17, 2021 03:18
Show Gist options
  • Save bsmt/b5dd49760a2ae4da4584127763c8ca95 to your computer and use it in GitHub Desktop.
Save bsmt/b5dd49760a2ae4da4584127763c8ca95 to your computer and use it in GitHub Desktop.
'''Fix the checksum in ULI files.'''
import argparse
import binascii
import struct
BULLSHIT = [0, 2519730039, 744558318, 3125873049, 432303367, 2415159920, 900031465, 2744476830, 847829774, 2763578489, 518641120, 2295976599, 726447625, 3179065726, 120436967, 2434645904, 1678817053, 4062228586, 1215412723, 3728850564, 2111101466, 3957644653, 1370871028, 3347436419, 1452829715, 3232263012, 2063164157, 3972621706, 1331429652, 3647735395, 1664946170, 4111272077, 3357568571, 1578133836, 3829489877, 1920034722, 3521381180, 1205077067, 4253355474, 1807026853, 4205360437, 1821946434, 3603545051, 1090108588, 3815561266, 1969020741, 3473790684, 1497223595, 2888882470, 973135441, 2152847304, 375509183, 3052712993, 600093526, 2576726735, 262520248, 2662859304, 143131999, 3000569030, 619252657, 2273079087, 290220120, 2870829505, 1026385590, 2420235382, 108124929, 3156267672, 705746415, 2307240305, 532002310, 2783231903, 869578984, 2731083640, 888733711, 2393377174, 412618465, 3138218623, 759000328, 2540463249, 22832102, 4098976619, 1650551836, 3627050373, 1308648178, 3985966700, 2074411291, 3253995650, 1472466933, 3336155237, 1357494034, 3937975947, 2089335292, 3743276386, 1227741717, 4085044108, 1699534075, 1482797645, 3461461306, 1946205347, 3794844628, 1101389642, 3616921661, 1841615268, 4227126995, 1793681731, 4242107956, 1183344557, 3501744346, 1932330052, 3843883827, 1598818986, 3380350429, 1014039888, 2856387111, 269487038, 2250247369, 632645719, 3011866400, 164914873, 2682544590, 251256414, 2563365161, 580440240, 3030964167, 389919577, 2165158958, 995933623, 2909584064, 545503469, 3065233306, 216184323, 2597499252, 961009130, 2943865501, 354867972, 2199313523, 302736355, 2218484884, 1047162125, 2824497786, 198119140, 2650737043, 665714698, 2979923837, 1150488560, 3533899911, 1760690462, 4274128489, 1566008055, 3412551040, 1899392025, 3875957614, 1981535486, 3760968585, 1518000656, 3427458407, 1876933113, 4193238670, 1136572183, 3582898272, 3903051478, 2123616673, 3301103672, 1391648591, 4050107345, 1733803174, 3708204351, 1261875784, 3660254680, 1276840623, 4132045622, 1618609217, 3287245023, 1440704424, 4019088945, 2042521926, 2360566219, 444819132, 2698145573, 920807506, 2507607244, 54987707, 3105227298, 791020885, 3191585477, 671858098, 2455417899, 74101596, 2818561986, 835702965, 2342443308, 497999451, 2965529755, 653419500, 2627955317, 177433858, 2835745180, 1060507371, 2238121842, 324468741, 2185936789, 343587042, 2922099067, 941340172, 2609828498, 230610405, 3085950076, 568318731, 3570586502, 1122161905, 4172537192, 1854134815, 3440819841, 1529264630, 3782717551, 2001188632, 3864660104, 1885999103, 3392865894, 1544225041, 4288570767, 1773036280, 3556731745, 1171221526, 2028079776, 4006743511, 1417872462, 3266511673, 1629906855, 4145438928, 1296525641, 3682037310, 1248514478, 3696940761, 1712054080, 4030453815, 1403960489, 3315514334, 2144318023, 3925849392, 485670333, 2328017610, 814986067, 2795746340, 87478458, 2466699213, 693624404, 3211254051, 779773619, 3091882436, 35350621, 2485874474, 935201716, 2710441155, 467600730, 2381251117]
CSUM_REGION_START = 0x20
CSUM_REGION_END = 0x21c
def swap32(i):
return struct.unpack("<I", struct.pack(">I", i))[0]
def xgpro_checksum(stuff, init=0):
'''Checksum a string using XGPro's custom CRC'''
state = init
for i, char in enumerate(stuff):
idx = state & 0xff
idx = idx ^ char
state = (state >> 8) & 0xffffffff
xor = swap32(BULLSHIT[idx])
state = state ^ xor
return swap32(state)
def main():
parser = argparse.ArgumentParser(description="Fix checksum in XGPro .ULI files.")
parser.add_argument("uli", help="Path to .ULI file.")
parser.add_argument("--update", action="store_true", help="Update the checksum in the file for you.")
args = parser.parse_args()
with open(args.uli, "rb") as f:
uli_content = f.read()
csum_region = uli_content[CSUM_REGION_START:CSUM_REGION_END]
csum = xgpro_checksum(csum_region)
print(f"Checksum for {args.uli} is: {hex(csum)}")
if args.update:
print("Writing checksum to file.")
csum_bytes = csum.to_bytes(4, byteorder="big") # already swapped in checksum function
with open(args.uli, "wb") as f:
fixed_uli = uli_content[:CSUM_REGION_END] + csum_bytes
f.write(fixed_uli)
print("Done!")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment