;From Mastering Machine Code On Your ZX81, the book by Toni Baker.

;The keys will move you as follows: Any key on the bottom row will move
;you downwards (except for shift, which has no effect), any key on the
;top row moves you up. The middle two rows move you left and right,
;with the lefthand ten keys (QWERTASDFG) moving you to the left, and
;the ten righthand keys (YUIOPHJKLn/l) moving you to the right.

;Some Chroma fun added.

          org 16514

kscan:    equ 02bbh
stop:     equ 0cdch
slow:     equ 0f2bh
pause:    equ 0f35h
d_file:   equ 400ch
speed:	  equ 0800h
position: defw 0
lastmove: defw 0
achroma:  defb 0ffh

sprint:	  pop hl              ;This subroutine prints
          ld a,(hl)           ;out a picture of the board,
          inc hl              ;along with your initial
          push hl             ;score. It must however be
          cp 0ffh             ;provided with a list of
          ret z               ;data terminated by ff.
          rst 10h
          jr sprint

start:    call slow           ;SLOW is required.
          call sprint         ;Calls the subroutine. the
                              ;following is data for the
                              ;subroutine.

defb 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 76h
defb 80h, 15h, 80h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 80h, 76h
defb 80h, 00h, 80h, 00h, 80h, 80h, 80h, 80h, 80h, 00h, 80h, 76h
defb 80h, 00h, 80h, 00h, 80h, 00h, 00h, 00h, 80h, 00h, 80h, 76h
defb 80h, 00h, 80h, 00h, 80h, 00h, 80h, 00h, 80h, 00h, 80h, 76h
defb 80h, 00h, 80h, 00h, 80h, 80h, 80h, 00h, 80h, 00h, 80h, 76h
defb 80h, 00h, 80h, 00h, 00h, 00h, 00h, 00h, 80h, 00h, 80h, 76h
defb 80h, 00h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 00h, 80h, 76h
defb 80h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 80h, 76h
defb 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 80h, 76h
defb 76h
defb 3eh, 34h, 3ah, 37h, 00h, 38h, 28h, 34h, 37h, 2ah, 00h, 33h
defb 34h, 3ch, 00h
defb 25h, 25h, 25h, 1ch, 1ch, 0ffh

;Offsets adapted for a full display file.
;Other changes include the colons after a label,
;the commas in defb lines,
;and the notation of hexadecimal constants.

setup:    ld hl,(d_file)      ;This section initialises the
          ld de,0023h         ;two variables used in our
          add hl,de           ;program.
          ld (position),hl
          ld hl,0000h
          ld (lastmove),hl
          call ichroma
loop:     ld hl,(d_file)      ;Decrement the score.
          ld de,017dh
          add hl,de
decimal:  ld a,(hl)
          and a
          jr nz,positive      ;###########
          ld b,05h            ;#+#       #
reset:    inc hl              ;# # ##### #
          ld (hl),1ch         ;# # #   # #
          djnz reset          ;# # # # # #
          jp ending           ;# # ### # #
positive: dec a               ;# #     # #
          cp 1bh              ;# ####### #
          jr nz,ok            ;#         #
          ld (hl),25h         ;###########
          dec hl
          jr decimal
ok:       ld (hl),a
          ld bc,speed         ;A timed delay. altering the
delay:    dec bc              ;initial value of bc changes
          ld a,b              ;the speed of the game.
          or c
          jr nz,delay
          call kscan          ;Scan keyboard. l now contains
          ld a,l              ;a value corresponding to the
          cpl                 ;direction required.
          ld l,a
          and 81h
          jr z,notdown        ;Find direction.
          ld de,0021h
          jr chkmove
notdown:  ld a,l
          and 18h
          jr z,notup
          ld de,0ffdfh
          jr chkmove
notup:    ld a,l
          and 60h
          jr z,notright
          ld de,0001h
          jr chkmove
notright: ld a,l
          and 6h
          jr z,loop
          ld de,0ffffh
chkmove:  ld hl,(lastmove)    ;Is player embedded in wall?
          ld a,l
          or h
          jr z,move
          add hl,de           ;If so, is player reversing?
          ld a,l
          or h
          jr z,move
          jr loop
move:     ld hl,(position)    ;Reassign square with black
          ld a,(hl)           ;or white space as required.
          and 80h
          ld (hl),a
          add hl,de           ;Find new position.
          ld a,(hl)           ;Draw black or white cross
          or 15h              ;as appropriate.
          ld (hl),a
          ld (position),hl
          push af
          ld a,(achroma)
          and 20h
          jr nz,skip
          set 7,h
          ld (hl),1ah         ;Attributes of the current position.
skip:     pop af
          ld hl,0000h         ;Store direction moved if
          rla                 ;a wall has been hit.
          jr nc,nothit
          ld h,d
          ld l,e
nothit:   ld (lastmove),hl
          ld hl,(d_file)      ;Check to see whether the
          ld de,008ah         ;finished square has been
          add hl,de           ;reached.
          ld de,(position)
          sbc hl,de
          jp nz,loop

ending:   ld bc,64h
          call pause
          ld bc,07fefh        ;Go back to B/W.
          in a,(c)
          and 20h
          jp nz,stop
          ld a,0
          out (c),a
          jp stop

ichroma:  ld bc,07fefh        ;Chroma port.
          in a,(c)
          ld (achroma),a      ;Save port contents.
          and 20h
          ret nz              ;Check if Chroma is available.
          ld a,31h            ;Use attributes file and dark blue border.
          out (c),a
          ld hl,(d_file)      ;Initialize the attributes file.
          ld b,18h
cloop:    inc hl
          ld a,(hl)
          cp 76h
          set 7,h
          ld (hl),1eh         ;Dark background and yellow pixels.
          res 7,h
          jr nz,cloop
          djnz cloop
          ld hl,(position)
          set 7,h
          ld (hl),1ah         ;Attributes of the first position.
          ret