1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-11-10 13:29:03 -08:00
mm/n64.py

82 lines
1.6 KiB
Python
Raw Normal View History

2015-03-01 07:58:42 -08:00
# Based on uCON64's N64 checksum algorithm by Andreas Sterbenz
2015-03-01 19:52:12 -08:00
from zlib import crc32
MAX32 = 0xFFFFFFFF
2015-03-01 07:58:42 -08:00
crc_seeds = {
6101: 0xF8CA4DDC,
6102: 0xF8CA4DDC,
6103: 0xA3886759,
6105: 0xDF26F436,
6106: 0x1FEA617A,
}
2015-03-01 19:52:12 -08:00
bootcode_crcs = {
0x6170A4A1: 6101,
0x90BB6CB5: 6102,
0x0B050EE0: 6103,
0x98BC2C86: 6105,
0xACC8580A: 6106,
}
2015-03-01 07:58:42 -08:00
def ROL(i, b):
return ((i << b) | (i >> (32 - b))) & MAX32
def R4(b):
return b[0]*0x1000000 + b[1]*0x10000 + b[2]*0x100 + b[3]
def crc(f, bootcode=6105):
seed = crc_seeds[bootcode]
t1 = t2 = t3 = t4 = t5 = t6 = seed
if bootcode == 6105:
f.seek(0x0710 + 0x40)
lookup = f.read(0x100)
f.seek(0x1000)
for i in range(0x1000, 0x101000, 4):
d = R4(f.read(4))
if ((t6 + d) & MAX32) < t6:
t4 += 1
t4 &= MAX32
t6 += d
t6 &= MAX32
t3 ^= d
r = ROL(d, d & 0x1F)
2015-03-01 07:58:42 -08:00
t5 += r
t5 &= MAX32
if t2 > d:
t2 ^= r
else:
t2 ^= t6 ^ d
if bootcode == 6105:
o = i & 0xFF
temp = R4(lookup[o:o + 4])
else:
temp = t5
t1 += temp ^ d
t1 &= MAX32
if bootcode == 6103:
crc1 = (t6 ^ t4) + t3
crc2 = (t5 ^ t2) + t1
elif bootcode == 6106:
crc1 = t6*t4 + t3
crc2 = t5*t2 + t1
else:
crc1 = t6 ^ t4 ^ t3
crc2 = t5 ^ t2 ^ t1
return crc1 & MAX32, crc2 & MAX32
2015-03-01 19:52:12 -08:00
def bootcode_version(f):
f.seek(0x40)
return bootcode_crcs[crc32(f.read(0x1000 - 0x40)) & MAX32]