+xor bx, dx ; bx = xss'' ^ (xss'' << 10)
+mov [xss], bx
+
+ret
+
+; init_grid() - initialize grid cells randomly --------------------------------
+
+; clobbers ax, bx, cx, dx, di
+
+init_grid:
+
+mov ah, PRINT_COLOR ; ah = color attribute
+mov di, [currvgapg] ; es:di -> grid start
+mov cx, COLS * ROWS ; for each cell
+
+.write_cell: ; do {
+ call xs ; [xss] = rand
+ mov al, DEAD ; al = DEAD (likely)
+
+ test word [xss], 0b11
+
+ jnz .nz ; if ([xss] % 4 == 0)
+ mov al, ALIVE ; al = ALIVE
+
+.nz:
+ stosw ; [es:di] = ax ; di += 2
+
+ loop .write_cell ; } while (--cx)
+
+ret
+
+; flip_vga_page() - flip active display page ----------------------------------
+
+; clobbers ax, dx
+
+flip_vga_page:
+
+call vsync_wait
+
+xor word [currvgapg], VGAPGSZ ; flip currvgapg
+setnz al ; al = !(currvgapg == 0)
+
+mov ah, 0x05 ; select active display page
+int 0x10 ; video services
+
+ret
+
+; alive_neighbours() ----------------------------------------------------------
+
+; input:
+; es:si -> current grid
+; cx -> cell index
+
+; output:
+; ax = # alive neighbours
+
+; clobbers ?
+
+alive_neighbours:
+
+; todo
+
+ret
+
+; write_next_cell_state() -----------------------------------------------------
+
+; input:
+; es:si -> current grid
+; es:di -> next grid
+; cx -> cell index
+
+; output:
+; [es:di + cx * 2] = updated cell state
+
+; clobbers ?
+
+write_next_cell_state:
+
+call alive_neighbours ; ax = # alive neighbours
+
+mov bx, cx
+shl bx, 1
+
+mov dx, [es:si + bx] ; dl = cell current state
+
+test dl, ALIVE ; if (ALIVE) {
+jne 1f
+
+test ax, 2 ; if (n < 2)
+jl .dead ; return DEAD
+
+test ax, 3 ; if (n > 3)
+jg .dead ; return DEAD
+
+jmp .alive ; return ALIVE
+
+1: ; }
+
+test ax, 3 ; if (n != 3)
+jne .dead ; return DEAD
+
+.alive: ; return ALIVE
+mov dl, ALIVE
+jmp .write
+
+.dead:
+mov dl, DEAD
+
+.write:
+mov [es:di + bx], dx