| Season penalty minutes per player (2026-10-28, NHL94 forum: "I don't see PIMs being saved").
| The game counts each player's penalty minutes in its team blocks ($C6CE home, $CA32 away)
| at +$102 + roster slot (bytes, slot 0 = the team), next to goals $B4, assists $CE, shots $E8.
| After every played season game they are added (saturating at 255) to battery RAM, in the
| logical range the hack never used (zero in every bank of jdc's save after a whole season):
|   league   $09A0 + 25*team   (32 teams x 25 slots = 800 bytes, $09A0..$0CBF)
|   playoffs $07C0 + 25*slot   (17 SEEDS slots, $07C0..$0968; postats.s clear now runs to $096A)
| The checksum is kept with season.s's running DELTA, like its player rows.
| +0 game: both teams of the game just played (season.s save, after gkreal; POGAME = playoffs)
| +4 clearleague: zero the league block (season.s clearall, a new season)
| +8 offset: d0 = team, d1 = 0 league / 1 playoffs -> d0 = SRAM offset of its 25 bytes,
|    or -1 (a team without a playoff slot)
    .equ HOME_T,0xFFFFC331
    .equ AWAY_T,0xFFFFC333
    .equ DELTA,0xFFFFF0F0
    .equ POGAME,0xFFFFF0D2
    .equ SEEDS,0xFFFFF6C0
    .equ SRAM_RD,0x1A244
    .equ SRAM_WR,0x1A1E4
    .equ BUF,0xFFFFF180                | 32 bytes (season.s row buffer area, free after its rows)
    .equ PIMF,0x102
    .equ LEAGUE,0x09A0
    .equ POBASE,0x07C0
    .text
    .globl _start
_start:
    bra.w game
    bra.w clearleague
    bra.w offset

offset:                                | d0 team, d1 0/1 -> d0 offset or -1
    movem.l %d1-%d2/%a0,-(%sp)
    andi.l #0xFF,%d0
    tst.w %d1
    bne.s 1f
    mulu.w #25,%d0
    addi.l #LEAGUE,%d0
    bra.s 9f
1:  lea SEEDS,%a0                      | the team's place in the playoff tree (as postats.s)
    moveq #0,%d2
2:  cmp.b (%a0,%d2.w),%d0
    beq.s 3f
    addq.w #1,%d2
    cmpi.w #16,%d2
    bcs.s 2b
    moveq #-1,%d0
    bra.s 9f
3:  move.l %d2,%d0
    mulu.w #25,%d0
    addi.l #POBASE,%d0
9:  movem.l (%sp)+,%d1-%d2/%a0
    rts

game:
    movem.l %d0-%d4/%a0-%a1,-(%sp)
    moveq #0,%d0
    move.b HOME_T,%d0
    movea.l #0xFFFFC6CE,%a1
    bsr.s addteam
    moveq #0,%d0
    move.b AWAY_T,%d0
    movea.l #0xFFFFCA32,%a1
    bsr.s addteam
    movem.l (%sp)+,%d0-%d4/%a0-%a1
    rts

addteam:                               | d0 = team, a1 = its team block
    moveq #0,%d1
    tst.b POGAME
    beq.s 1f
    moveq #1,%d1
1:  bsr.s offset
    tst.l %d0
    bmi.s 9f
    move.l %d0,%d4
    lea BUF,%a0
    moveq #25,%d1
    jsr SRAM_RD
    lea BUF,%a0
    lea PIMF+1(%a1),%a1                | the game's minutes of roster slot 1..25
    moveq #0,%d3
    moveq #0,%d2                       | slot index 0..24 = roster slot 1..25
2:  move.b (%a0,%d2.w),%d3
    sub.b %d3,DELTA                    | the old byte leaves the checksum
    moveq #0,%d1
    move.b (%a1,%d2.w),%d1
    add.w %d3,%d1                      | (d3 high byte is 0 from the byte loads below)
    cmpi.w #255,%d1
    bls.s 3f
    move.w #255,%d1
3:  move.b %d1,(%a0,%d2.w)
    add.b %d1,DELTA                    | the new byte enters it
    moveq #0,%d3
    addq.w #1,%d2
    cmpi.w #25,%d2
    bcs.s 2b
    lea BUF,%a0
    move.l %d4,%d0
    moveq #25,%d1
    jsr SRAM_WR
9:  rts

clearleague:
    movem.l %d0-%d4/%a0,-(%sp)
    move.l #LEAGUE,%d4
1:  lea BUF,%a0
    move.l %d4,%d0
    moveq #25,%d1
    jsr SRAM_RD
    lea BUF,%a0
    moveq #24,%d1
2:  move.b (%a0),%d0
    sub.b %d0,DELTA
    clr.b (%a0)+
    dbra %d1,2b
    lea BUF,%a0
    move.l %d4,%d0
    moveq #25,%d1
    jsr SRAM_WR
    addi.l #25,%d4
    cmpi.l #LEAGUE+800,%d4
    bcs.s 1b
    movem.l (%sp)+,%d0-%d4/%a0
    rts
