# readsram.py file.nv|file.srm  -- prints the season table stored in battery RAM (and checks the hack's checksum)
import sys
d = open(sys.argv[1], 'rb').read()
b = d
if len(d) == 16384:                              # 16 KB files: data on every other byte (MAME .nv even, RetroArch .srm odd)
    b = d[0::2] if d[0::2].find(b'SESN') >= 0 or d[1::2].find(b'SESN') < 0 else d[1::2]
AB = ['ANA','BOS','BUF','CGY','CAR','CHI','COL','CBJ','DAL','DET','EDM','FLA','LAK','MIN','MTL','NSH',
      'NJD','NYI','NYR','OTT','PHI','PIT','SJS','SEA','STL','TBL','TOR','UTA','VAN','VGK','WSH','WPG']
s = sum(b[:0x1FFE]) & 0xff
print('checksum', 'OK' if b[0x1FFF] == s and b[0x1FFE] == (~s & 0xff) else 'BAD', hex(s), b[0x1FFE:0x2000].hex())
blk = b[0x1000:0x1210]
w = lambda o: int.from_bytes(blk[o:o + 2], 'big')
print('magic', blk[:4], 'games', w(4))
rows = []
for t in range(32):
    r = [w(16 + 16 * t + 2 * k) for k in range(8)]
    if r[0]: rows.append((2 * r[1] + r[3] + r[6], AB[t], r))
print('team  GP  W OTW OTL  L  T  GF  GA  PTS   (W = regulation wins)')
for pts, ab, r in sorted(rows, reverse=True):
    print(f'{ab:4} {r[0]:3} {r[1] - r[7]:2} {r[7]:3} {r[3]:3} {r[2]:2} {r[6]:2} {r[4]:3} {r[5]:3} {pts:4}')

# player stats (SRAM $1220: 32 teams x 100 bytes: slots 1..25 x (goals, assists, shots word)), names from the ROM
fmt = int.from_bytes(blk[14:16], 'big')
if len(sys.argv) > 2 and fmt in (2, 3):
    import struct as st
    rom = open(sys.argv[2], 'rb').read()
    def names(t):
        a = st.unpack('>I', rom[0x30E + 4 * t:0x312 + 4 * t])[0]; h = st.unpack('>6H', rom[a:a + 12]); i = a + h[0]; out = []
        while i < a + h[2] - 2:
            n = st.unpack('>H', rom[i:i + 2])[0]; out.append(rom[i + 2:i + n].rstrip(b'\x00').decode('latin1')); i += n + 8
        return out
    rows = []; problems = 0
    for t in range(32):
        nm = names(t); row = b[0x1220 + 100 * t:0x1220 + 100 * t + 100]
        tg = ta = ts = 0
        for k in range(1, 26):
            g, a_, sog = row[4 * (k - 1)], row[4 * (k - 1) + 1], st.unpack('>H', row[4 * (k - 1) + 2:4 * k])[0]
            tg += g; ta += a_; ts += sog
            if sog < g: problems += 1; print('  !! shots < goals', AB[t], nm[k])
            if g or a_ or sog: rows.append((g + a_, g, a_, sog, nm[k] if k < len(nm) else '?', AB[t]))
        gf = int.from_bytes(blk[16 + 16 * t + 8:16 + 16 * t + 10], 'big')
        if tg != gf: problems += 1; print(f'  !! {AB[t]}: player goals {tg} != team GF {gf}')
        if ta > 2 * tg: problems += 1; print(f'  !! {AB[t]}: assists {ta} > 2 x goals {tg}')
    rows.sort(reverse=True)
    print('scoring leaders:  pts  g  a  sog')
    for r in rows[:15]: print(f'  {r[4]:24} {r[5]} {r[0]:3} {r[1]:3} {r[2]:3} {r[3]:4}')
    print('  total goals', sum(r[1] for r in rows), 'assists', sum(r[2] for r in rows), 'shots', sum(r[3] for r in rows), ' problems:', problems)

# goalie stats (format 3, SRAM $E20: 32 teams x 3 goalies x (GP, W, GA:12 | SA:12))
if len(sys.argv) > 2 and fmt == 3:
    print('goalies:                    GP  W   GA   SA   SV%')
    gp_ = []; gproblems = 0
    for t in range(32):
        nm = names(t); tg = tw = tga = 0
        tr = [int.from_bytes(blk[16 + 16 * t + 2 * k:18 + 16 * t + 2 * k], 'big') for k in range(7)]
        for g in range(3):
            r = b[0xE20 + 15 * t + 5 * g:0xE20 + 15 * t + 5 * g + 5]
            gp, wn = r[0], r[1]; ga = (r[2] << 4) | (r[3] >> 4); sa = ((r[3] & 15) << 8) | r[4]
            tg += gp; tw += wn; tga += ga
            if sa < ga: gproblems += 1; print('  !! SA < GA', AB[t], nm[g])
            if gp: gp_.append((gp, AB[t], nm[g], wn, ga, sa))
        if tr[0] and (tg != tr[0] or tw != tr[1] or tga != tr[5]):
            gproblems += 1; print(f'  !! {AB[t]}: goalies GP {tg} W {tw} GA {tga} vs team GP {tr[0]} W {tr[1]} GA {tr[5]}')
    for gp, ab, n, wn, ga, sa in sorted(gp_, reverse=True)[:12]:
        print(f'  {n:24} {ab} {gp:3} {wn:2} {ga:4} {sa:4}  {(sa - ga) / sa if sa else 0:.3f}')
    print('  goalies with games:', len(gp_), ' problems:', gproblems)
