zxGammon

screen.asm

The board, checkers, dice, cube, Gnubby, the scores and what he says, drawn only where they change. Download · All the source

; --------------------------------------------------------------- screen; The board: points 13-24 along the top, 12-1 along the bottom (the; player's home at the bottom right), two columns a point, each point's; number on its base while it is empty, the bar in the middle (with the; cube, in the middle or at its owner's end); beside it Gnubby's score and; checkers borne off, Gnubby, the match's length, and the player's; checkers borne off and score; what Gnubby says in the two rows along the; bottom.A_FRAME equ $0d         ; paper blue, ink cyanA_FELT  equ $20         ; paper greenA_PT0   equ $66         ; points: bright yellow, bright red, on greenA_PT1   equ $62A_HUM   equ $67         ; the player's checkers: whiteA_COMP  equ $20         ; Gnubby's: blackA_HUMB  equ $4f         ; on the barA_COMPB equ $08A_SIDE  equ $07         ; paper blackA_MSG   equ $78         ; paper whiteA_SCORE equ $46         ; yellow on blackA_MLEN  equ $45         ; the match's length: cyan on blackA_DIE   equ $78A_CUBE  equ $4f         ; the cube: white ink on the bar's blueA_DIEU  equ $39         ; a die played: blue on greyA_DIEC  equ $47         ; Gnubby's: white on black, as his checkersA_MASC  equ $70         ; Gnubby: black on yellowA_TRAYH equ $47A_TRAYC equ $42; scr: B = row, C = column -> HL = the cell's top pixel line.scr:    ld a,b        and $18        or $40        ld h,a        ld a,b        and 7        rrca        rrca        rrca        or c        ld l,a        ret; att: B = row, C = column -> HL = the cell's attribute.att:    ld a,b        rrca        rrca        rrca        ld l,a        and 3        or $58        ld h,a        ld a,l        and $e0        or c        ld l,a        ret; putg: DE -> 8 bytes, B, C = a cell, A = its attribute: drawn there.; Keeps BC; DE after the 8 bytes.putg:   push af        call scr        push bc        ld b,8.l:     ld a,(de)        ld (hl),a        inc de        inc h        djnz .l        pop bc        call att        pop af        ld (hl),a        ret; putc: A = a character, B, C = a cell, in TATTR's colours. Keeps BC.putc:   sub 32        ld l,a        ld h,0        add hl,hl        add hl,hl        add hl,hl        ld de,FONT        add hl,de        ex de,hl        ld a,(TATTR)        jr putg; print: HL -> text (| a new line, 0 the end), B, C = where. B, C left; after it.print:  ld a,c        ld (PCOL),a.l:     ld a,(hl)        inc hl        or a        ret z        cp '|'        jr nz,.c        inc b        ld a,(PCOL)        ld c,a        jr .l.c:     push hl        call putc        pop hl        inc c        jr .l; fill: B, C = a corner, D rows by E columns of attribute A (and the; pixels cleared).fill:   ld (FATTR),a.r:     push bc        push de.c:     push bc        call scr        xor a        push bc        ld b,8.p:     ld (hl),a        inc h        djnz .p        pop bc        call att        ld a,(FATTR)        ld (hl),a        pop bc        inc c        dec e        jr nz,.c        pop de        pop bc        inc b        dec d        jr nz,.r        ret; cls: the whole screen blank, black.cls:    ld hl,$4000        ld de,$4001        ld bc,6143        ld (hl),l        ldir        inc hl        inc de        ld bc,767        ld (hl),A_SIDE        ldir        ret; pcol: A = the player's point index (0-23) -> C = its column; carry for; a top point.pcol:   cp 6        jr nc,.a        add a,a        neg        add a,25        ld c,a        or a        ret.a:     cp 12        jr nc,.b        add a,a        neg        add a,23        ld c,a        or a        ret.b:     cp 18        jr nc,.c        add a,a        sub 23        ld c,a        scf        ret.c:     add a,a        sub 21        ld c,a        scf        ret; drawall: the whole board.drawall:        ld a,(UP)        or a        call z,setup        xor a.pt:    push af        call drawpt        pop af        inc a        cp 24        jr nz,.pt        call drawbar        call drawtray        call drawcube        call drawdice        call drawmasc        call drawscore        call hilite        ld a,(SAIDNEW)        or a        ret z        jp resay; setup: the board's frame and felt on a clear screen, and everything; else to be drawn: the rest of drawall only draws over what is there,; and what has not changed not at all, so nothing flickers.setup:  ld a,1        ld (UP),a        ld (SAIDNEW),a        ld a,$ff        ld hl,LSHOWN        ld b,10.m:     ld (hl),a        inc hl        djnz .m        call cls        ld bc,0        ld de,22*256+28        ld a,A_FRAME        call fill        ld bc,1        ld de,22*256+12        ld a,A_FELT        call fill        ld bc,15        ld de,22*256+12        ld a,A_FELT        jp fill; drawpt: A = a point index: its triangle and number.drawpt: ld (TMPI),a        ; its checkers: the player's, or Gnubby's        ld hl,GB        call index        ld d,A_HUM        or a        jr nz,.some        ld a,(TMPI)        ld b,a        ld a,23        sub b        ld hl,GB+32        call index        ld d,A_COMP.some:  ld (SN),a        ld a,d        ld (SATT),a        ld a,(SN)        cp 5        jr c,.n        ld a,5.n:     add a,a        ld (NCK),a        ld a,(TMPI)        call pcol        ld a,0        rla        ld (TOPPT),a        ld a,(TMPI)        and 1        ld a,A_PT0        jr z,.col        ld a,A_PT1.col:   ld (FATTR),a        ld a,(NCK)              ; the cells beyond the checkers        ld e,a        cp 10        jr z,.stk.k:     push de        ld a,e        add a,a        add a,a        add a,a        add a,a        ld l,a        ld h,0        ld de,TRI        add hl,de               ; its first line, from the base        ex de,hl        pop hl        push hl        ld a,(TOPPT)        or a        ld a,l        jr z,.bot        ld b,a        ld hl,2        jr .draw.bot:   neg        add a,21        ld b,a        ld hl,14        add hl,de        ex de,hl        ld hl,-2.draw:  ld (TSTEP),hl        push bc        call scr        ld b,8.ln:    ld a,(de)        ld (hl),a        inc de        inc l        ld a,(de)        ld (hl),a        dec de        dec l        inc h        push hl        ld hl,(TSTEP)        add hl,de        ex de,hl        pop hl        djnz .ln        pop bc        call att        ld a,(FATTR)        ld (hl),a        inc l        ld (hl),a        pop de        inc e        ld a,e        cp 10        jr nz,.k.stk:   ; the checkers, from the edge        ld a,(TMPI)        call pcol        ld b,0        ld a,2        jr c,.top        ld b,20        ld a,-2.top:   ld (SDIR),a        ld a,5        call stack        ; the number, in small digits cut out of the point's base, if        ; no checker covers it        ld a,(NCK)        or a        ret nz        ld a,(TMPI)        call pcol        ld b,0        jr c,.nb        ld b,21.nb:    ld a,(TMPI)        add a,a        add a,a        ld l,a        ld h,0        add hl,hl        add hl,hl        ld de,PTNUM        add hl,de        ex de,hl        call xorg        inc c; xorg: DE -> 8 bytes, B, C = a cell: XORed into its pixels. Keeps BC; DE; after the 8 bytes.xorg:   push bc        call scr        ld b,8.l:     ld a,(de)        xor (hl)        ld (hl),a        inc de        inc h        djnz .l        pop bc        ret; drawbar: the checkers on the bar, 2 shown each (then the count): Gnubby's; from row 6 down, the player's from row 14 up; the cells without, blank.; And the pip counts (drawpips).drawbar:        call drawpips        ld a,(GB+32+24)        ld (SN),a        cp 2        jr nc,.c        add a,a        ld d,a        add a,6        ld b,a                  ; from row 6 + 2n        ld a,4        sub d        ld d,a                  ; 4 - 2n rows        ld e,2        ld c,13        ld a,A_FRAME        call fill.c:     ld a,A_COMPB        ld (SATT),a        ld a,2        ld (SDIR),a        ld bc,6*256+13        ld a,2        call stack        ld a,(GB+24)        ld (SN),a        cp 2        jr nc,.h        add a,a        ld d,a        ld a,4        sub d        ld d,a                  ; 4 - 2n rows from row 12        ld e,2        ld bc,12*256+13        ld a,A_FRAME        call fill.h:     ld a,A_HUMB        ld (SATT),a        ld a,-2        ld (SDIR),a        ld bc,14*256+13        ld a,2        jp stack; drawpips: each side's pip count, under "PIP", in small digits on the bar:; Gnubby's at the top, the player's at the bottom; or (PIPOFF, the I key); none.drawpips:        ld a,(PIPOFF)        or a        jr z,.on        ld bc,13        ld de,2*256+2        ld a,A_FRAME        call fill        ld bc,20*256+13        ld de,2*256+2        ld a,A_FRAME        jp fill.on:    ld bc,13        call pipword        ld hl,GB+32        call pips        ld bc,1*256+13        call smallnum        ld bc,20*256+13        call pipword        ld hl,GB        call pips        ld bc,21*256+13        jp smallnum; pipword: "PIP" in small letters in the two cells at B, C.pipword:        ld a,10        ld (DIG3),a        ld (DIG3+2),a        inc a        ld (DIG3+1),a        jr smalldraw; pips: HL -> a side's 25 points -> HL = its pip count.pips:   push hl        pop ix        ld hl,0        ld de,1        ld b,25.p:     ld a,(ix+0).a:     or a        jr z,.n        add hl,de        dec a        jr .a.n:     inc ix        inc de        djnz .p        ret; smallnum: HL (0-999) in small digits, right-aligned in the two cells at; B, C, in the frame's colours. Each character 3 dots wide and 5 high, at; dots 2, 6 and 10 of the 16: the digits, then P (10) and I (11).smallnum:        push bc        ld de,NUMBUF        call utoa               ; HL left at the 0 after the digits        ex de,hl        ld de,DIG3+2        ld b,3.d:     ld a,l        or a                    ; NUMBUF starts a page        ld a,12                 ; none        jr z,.s        dec hl        ld a,(hl)        sub '0'.s:     ld (de),a        dec de        djnz .d        pop bc; smalldraw: DIG3's three small characters in the two cells at B, C.smalldraw:        push bc        call scr        xor a        ld (SLINE),a.ln:    push hl        ld de,0        ld a,(SLINE)        dec a        cp 5        jr nc,.put        ld (SROW),a        ld a,(DIG3)        call srow        ld d,a        ld a,(DIG3+1)        call srow        add a,a        add a,a        add a,a        add a,a        ld e,a        ld a,(DIG3+2)        call srow        or e        ld e,a        ex de,hl        add hl,hl        add hl,hl        add hl,hl        ex de,hl.put:   pop hl        ld (hl),d        inc l        ld (hl),e        dec l        inc h        ld a,(SLINE)        inc a        ld (SLINE),a        cp 8        jr nz,.ln        pop bc        call att        ld (hl),A_FRAME        inc l        ld (hl),A_FRAME        ret; srow: A = a small character (12 for none) -> A = its row SROW, three; dots.srow:   cp 12        jr c,.d        xor a        ret.d:     ld l,a        add a,a        add a,a        add a,l        ld l,a        ld a,(SROW)        add a,l        ld hl,SDIG        jp index; stack: SN checkers in SATT from B, C (each two cells by two, from its; top left), SDIR rows apart, at most A shown (the last with the count cut; out of it if more).stack:  ld (SMAX),a        ld a,(SN)        or a        ret z        ld e,a        ld d,0.k:     inc d        push de        ld a,d        ld hl,SMAX        cp (hl)        ld a,0        jr nz,.chk        ld a,e                  ; the last shown: the count, if more        cp d        jr nz,.chk        xor a.chk:   ld l,a                  ; CHK + 32 x (0 or the count)        ld h,0        add hl,hl        add hl,hl        add hl,hl        add hl,hl        add hl,hl        ld de,CHK        add hl,de        ex de,hl        ld a,(SATT)        call putg        inc c        call putg        inc b        dec c        call putg        inc c        call putg        dec b        dec c        ld a,(SDIR)        add a,b        ld b,a        pop de        ld a,d        cp e        ret z        ld hl,SMAX        cp (hl)        jr nz,.k        ret; num2: A (up to 99) in two cells at B, C in TATTR's colours.num2:   ld e,'0'-1.t:     inc e        sub 10        jr nc,.t        add a,10+'0'        push af        ld a,e        cp '0'        jr nz,.d        ld a,' '.d:     call putc        inc c        pop af        jp putc; drawtray: the checkers borne off, as stripes.drawtray:        ld hl,GB+32        call total        ld d,a        ld hl,GB        call total        ld e,a        ld hl,(LTRAY)        ld a,l        cp d        jr nz,.go        ld a,h        cp e        ret z.go:    ld l,d        ld h,e        ld (LTRAY),hl        ld bc,1*256+29        ld de,6*256+2        ld a,A_TRAYC        call fill        ld bc,15*256+29        ld de,6*256+2        ld a,A_TRAYH        call fill        ld hl,GB+32        call total        neg        add a,15        ld b,a        ld a,8        ld e,3        call stripes        ld hl,GB        call total        neg        add a,15        ld b,a        ld a,166        ld e,-3; stripes: B checkers, from pixel line A by E each.stripes:        inc b.s:     dec b        ret z        push af        push bc        push de        ld c,29        call pixaddr        ld a,$3f        ld (hl),a        inc l        ld (hl),$fc        pop de        pop bc        pop af        push af        inc a        push bc        push de        ld c,29        call pixaddr        ld (hl),$7f        inc l        ld (hl),$fe        pop de        pop bc        pop af        add a,e        jr .s; pixaddr: A = a pixel line, C = a column -> HL.pixaddr:        ld b,a        and 7        or $40        ld h,a        ld a,b        and $c0        rrca        rrca        rrca        or h        ld h,a        ld a,b        and $38        rlca        rlca        or c        ld l,a        ret; drawcube: the cube, by its owner: Gnubby above, the middle, the player; below.drawcube:        ld hl,LCUBE        ld a,(OWNER)        cp (hl)        jr nz,.new        inc hl        ld a,(CUBE)        cp (hl)        jr nz,.new        inc hl        ld a,(CRAW)        cp (hl)        ret z.new:   ld a,(OWNER)        ld (LCUBE),a        ld a,(CUBE)        ld (LCUBE+1),a        ld a,(CRAW)        ld (LCUBE+2),a        ld bc,3*256+13          ; its three places on the bar cleared        call .clr        ld bc,10*256+13        call .clr        ld bc,17*256+13        call .clr        ld bc,14*256+28         ; and CRAW beside the board        ld de,1*256+4        ld a,A_SIDE        call fill        ld a,(MLEN)        or a        jr z,.go        ld a,(CRAW)        dec a        jr nz,.go        ld bc,14*256+28         ; no cube in the Crawford game        ld a,A_MLEN        ld (TATTR),a        ld hl,S_CRAW        jp print.go:    ld a,(OWNER)            ; in the middle, or at its owner's end        ld b,10        or a        jr z,.r        ld b,17        dec a        jr z,.r        ld b,3.r:     ld c,13        ld a,(CUBE)             ; its face: the cube's log 2        ld e,-1.l:     inc e        srl a        jr nz,.l        ld l,e        ld h,0        add hl,hl        add hl,hl        add hl,hl        add hl,hl        add hl,hl        ld de,CUBEG        add hl,de        ex de,hl        ld a,A_CUBE        jp put4.clr:   ld de,2*256+2        ld a,A_FRAME        jp fill; drawdice: the dice rolled (SHOWN: 1 the player's, 2 Gnubby's, 3 one; each to open).drawdice:        ld a,(SHOWN)        ld hl,LSHOWN        cp (hl)        jr z,.keep        ld (hl),a        ld bc,10*256+1        ld de,2*256+12        ld a,A_FELT        call fill        ld bc,10*256+15        ld de,2*256+12        ld a,A_FELT        call fill.keep:  ld a,(SHOWN)        or a        ret z        cp 3        jr nz,.two        ld a,(DIE1)        ld bc,10*256+20        ld e,A_DIE        call die        ld a,(DIE2)        ld bc,10*256+6        ld e,A_DIEC        jr die.two:   dec a        ld c,18        jr z,.h        ld c,4        ld e,A_DIEC        ld a,(DIE1)        ld b,10        push bc        call die        pop bc        ld a,c        add a,3        ld c,a        ld e,A_DIEC        ld a,(DIE2)        jr die.h:     ; used or not        push bc        ld a,(DIE1)        ld b,a        ld a,(DIE2)        cp b        jr z,.dbl        ld a,(U1)        call used        ld a,(DIE1)        ld b,10        call die        ld a,(U2)        call used        jr .d2.dbl:   ld a,(NMAX)        ld hl,NDONE        sub (hl)        cp 3        ccf        sbc a,a        inc a        call used        ld a,(DIE1)        ld b,10        call die        ld a,(NMAX)        ld hl,NDONE        sub (hl)        cp 1        ccf        sbc a,a        inc a        call used.d2:    pop bc        ld a,c        add a,3        ld c,a        ld b,10        ld a,(DIE2); die: A = its face, B, C = where, E = its attribute.die:    dec a        add a,a        add a,a        add a,a        add a,a        add a,a        ld l,a        ld h,0        push de        ld de,DICE        add hl,de        ex de,hl        pop hl        ld a,l; put4: DE -> 32 bytes, B, C = a corner, A = the attribute: two cells by; two drawn there.put4:   call putg        inc c        call putg        dec c        inc b        call putg        inc c        jp putg; used: A nonzero if played -> E = the die's attribute. Keeps BC.used:   or a        ld e,A_DIE        ret z        ld e,A_DIEU        ret; drawmasc: Gnubby, in his mood, beside the board.drawmasc:        ld bc,8*256+28; mascot: Gnubby in MOOD at B, C.mascot: ld a,(MOOD)        ld l,0        srl a        rr l        ld h,a                  ; x 128        ld de,MASC        add hl,de        ex de,hl        ld l,4.r:     push bc        ld h,4.c:     push hl        ld a,A_MASC        call putg        pop hl        inc c        dec h        jr nz,.c        pop bc        inc b        dec l        jr nz,.r        ret; drawscore: the scores, and the match's length.drawscore:        ld hl,LSCORE        ld a,(SCH)        cp (hl)        jr nz,.new        inc hl        ld a,(SCC)        cp (hl)        jr nz,.new        inc hl        ld a,(MLEN)        cp (hl)        jr nz,.new        inc hl        ld a,(CRAW)        cp (hl)        ret z.new:   ld a,(SCH)        ld (LSCORE),a        ld a,(SCC)        ld (LSCORE+1),a        ld a,(MLEN)        ld (LSCORE+2),a        ld a,(CRAW)        ld (LSCORE+3),a        ; beside the board: Gnubby's at the top, the player's at the        ; bottom, and the match's length above the player's tray        ld bc,28        ld de,1*256+4        ld a,A_SCORE        call fill        ld bc,21*256+28        ld de,1*256+4        ld a,A_SCORE        call fill        ld bc,13*256+28        ld de,1*256+4        ld a,A_SIDE        call fill        ld a,A_SCORE        ld (TATTR),a        ld hl,(SCC)        ld b,0        call rnum        ld hl,(SCH)        ld b,21        call rnum        ld a,(MLEN)        or a        ret z        ld a,A_MLEN        ld (TATTR),a        ld bc,13*256+28        ld hl,S_TO        call print        ld a,(MLEN)        ld l,a        ld h,0; pnum: HL printed in decimal at B, C.pnum:   push bc        ld de,NUMBUF        call utoa        pop bc        ld hl,NUMBUF        jp print; rnum: HL printed in decimal in row B, ending at the screen's edge.rnum:   push bc        ld de,NUMBUF        call utoa        pop bc        ld a,32                 ; NUMBUF starts a page: E is the length        sub e        ld c,a        ld hl,NUMBUF        jp print; utoa: HL in decimal at DE, ended by 0; DE left at the 0.utoa:   xor a        ld (UZERO),a        ld bc,-10000        call .d        ld bc,-1000        call .d        ld bc,-100        call .d        ld bc,-10        call .d        ld a,l        add a,'0'        ld (de),a        inc de        xor a        ld (de),a        ret.d:     ld a,'0'-1.s:     inc a        add hl,bc        jr c,.s        sbc hl,bc        cp '0'        jr nz,.w        ld a,(UZERO)        or a        ret z        ld a,'0'.w:     ld (de),a        inc de        ld (UZERO),a        ret; hilite: the point under the cursor flashing, while the player moves.hilite: ld a,(CURS)        cp 25        ret nc        cp 24        ld bc,14*256+13        jr z,.two        call pcol               ; the base's two rows        ld b,0        jr c,.two        ld b,20.two:   call .fl        inc b.fl:    call att        set 7,(hl)        inc l        set 7,(hl)        ret; say: HL -> what Gnubby says, into the speech area (kept for redrawing).say:    ld de,SAID.cp:    ld a,(hl)        ld (de),a        inc hl        inc de        or a        jr nz,.cp; resay: what Gnubby said, written over the last, each line padded with; spaces to the edge (rather than cleared first, which would flicker).resay:  xor a        ld (SAIDNEW),a        ld a,A_MSG        ld (TATTR),a        ld hl,SAID        ld b,22.row:   ld c,0        ld a,' '        call putch        inc c.ch:    ld a,(hl)        or a        jr z,.pad        inc hl        cp '|'        jr z,.pad        call putch        inc c        ld a,c        cp 32        jr c,.ch.pad:   ld a,c        cp 32        jr nc,.next        ld a,' '        call putch        inc c        jr .pad.next:  inc b        ld a,b        cp 24        jr c,.row        ret; TICK: from the engine, before each of the opponent's rolls it tries:; the dots after the first line of what Gnubby says, one more each time; (none after three), to show he is still thinking. Keeps the registers.TICK:   push af        push bc        push de        push hl        ld a,(DOTS)        inc a        and 3        ld (DOTS),a        ld e,a        ld hl,SAID              ; the first line's end        ld c,1.end:   ld a,(hl)        or a        jr z,.dots        cp '|'        jr z,.dots        inc hl        inc c        jr .end.dots:  ld a,A_MSG        ld (TATTR),a        ld b,22        ld d,3.d:     ld a,c        cp 32        jr nc,.x        ld a,'.'        dec e        jp p,.put        ld a,' '.put:   push de        call putc        pop de        inc c        dec d        jr nz,.d.x:     pop hl        pop de        pop bc        pop af        ret; putch: putc, keeping HL.putch:  push hl        call putc        pop hl        ret; bigtext: HL -> text, B, C = where: letters twice the size, each its own; colour.bigtext:        ld a,(hl)        or a        ret z        inc hl        push hl        push bc        call bigc        pop bc        inc c        inc c        ld a,(TATTR)        inc a        and 7        jr nz,.k        ld a,2.k:     or $40        ld (TATTR),a        pop hl        jr bigtext; bigc: A = a character at B, C, doubled.bigc:   sub 32        ld l,a        ld h,0        add hl,hl        add hl,hl        add hl,hl        ld de,FONT        add hl,de        ex de,hl        call .half        inc b.half:  push bc        call scr        ld b,4.row:   ld a,(de)        inc de        push de        push hl        push bc        call dbl        pop bc        pop hl        ld (hl),d        inc l        ld (hl),e        inc h        ld (hl),e        dec l        ld (hl),d        inc h        pop de        djnz .row        pop bc        call att        ld a,(TATTR)        ld (hl),a        inc l        ld (hl),a        ret; dbl: A's bits each doubled -> D, E.dbl:    ld c,a        ld de,0        ld b,8.l:     sla e        rl d        sla e        rl d        sla c        jr nc,.n        ld a,e        or 3        ld e,a.n:     djnz .l        ret