; BIOSVID.INC - 3/9/86 - Video for the Xerox 820 ; Here is the CRT output routine. The 820 has a 24 by 80 CRT controller ; on the board, with the refresh RAM stashed in shadow memory at ; location 3000H. This code updates that RAM and handles some control ; sequences. crtpag equ 30h ; Where CRT RAM lives, in SHADOW! crtram equ 3000h cursor: dw crtram ; Pointer into screen RAM crschr: db 0 ; Character under the cursor spccrs: db 2 ; Character to use as cursor if on space scroll: db 0 ; Current value of scroll register seqflg: db 0 ; Flag in midst of a sequence savesp: ds 2 ds 16 intstk equ $ pu3ot: push hl ; Save user's registers push de push bc di ; Turn off interrupts, since we are ; about to map out low memory ld (savesp),sp ; And that lets us borrow the ld sp,intstk ; interrupt level stack for this code in a,(pio.sd) ; Switch locs 0000-3FFF to shadow set b7,a ; By twiddling this bit out (pio.sd),a ld hl,crschr ; Character under the cursor ld b,(hl) ld hl,(cursor) ; Point where cursor is ld a,h ; Make sure cursor is within screen RAM and 0fh or crtpag ld h,a ld (hl),b ; Put back char under cursor call crtwrk ; Main body of pu3ot ld a,(hl) ; Get char where cursor is ld (crschr),a ; Hold copy of char under cursor cp ' ' ; Is it a space? set b7,a ; Make it inverse video jr nz,pu3oua ; If not space, just invert it ld a,(spccrs) ; Special char if cursor is on space pu3oua: ld (hl),a ; Make cursor visible ld (cursor),hl ; Remember where cursor wound up ld sp,(savesp) ; Back to caller's stack in a,(pio.sd) ; Put CRT RAM back in shadow res b7,a out (pio.sd),a ei ; Allow interrupts now pop bc ; Restore registers pop de pop hl ret ; Multi character sequences crtseq: ex de,hl ; Clear sequence flag for next time ld (hl),0 ex de,hl cp 1 ; Last char was ESC? jr nz,crtsq1 ; No ld a,c ; Yes, what's the next char? cp '=' ; Should be equals ret nz ; If not, junk it. ld a,2 ; Say row is next ld (de),a ; in seqflg ret crtsq1: cp 2 ; Waiting for row? jr nz,crtsq2 ; Go if not ld a,3 ; Yes, say now want column ld (de),a ; in seqflg crtrs1: ld a,(scroll) ; Compute in the autoscroller add a,c ; plus desired row sub ' '-1 ; Remove 32 bias crtwl: sub 24 ; Wrap as needed jr nc,crtwl add a,24 or crtpag+crtpag ; Figure CRT RAM addr for this row ld h,a ld l,0 srl h rr l ret crtsq2: cp 3 ; Waiting for column? jr nz,crtsto ; No, store char, screwed up ld a,c ; Yes, get the column sub ' ' ; Remove the bias crtwc: sub 80 ; Wrap the column jr nc,crtwc add a,80 or l ; In current line ld l,a ret crtwrk: ld de,seqflg ; In the middle of a multi char sequence? ld a,(de) or a jr nz,crtseq ; Go handle the sequence ld a,c ; Character to "type" on screen cp del ; Is it DEL? jr z,crtbs ; Yes, treat as backspace cp ' ' ; Control character? jr nc,crtsto ; No, display it cp bel jr z,crtbel cp bs jr z,crtbs cp ht jr z,crtht cp lf jr z,crtlf cp cr jr z,crtcr cp ff jr z,crtff cp esc jr z,crtesc ret ; Ignore control char crtsto: ld (hl),c ; Put char in screen RAM inc hl ; Use a column ld a,l ; Check for right edge and 7fh cp 80 ; Edge of screen? ret c ; No call crtcr ; Yes, wrap the cursor jr crtlf ; By doing a CR LF ; ESCAPE char. Followed by an "=" and row and column (32 offset) crtesc: ld a,1 ; Set a one into seqflg ld (de),a ; and get the args later ret ; Backspace - cursor left unless at margin crtbs: ld a,l ; Lines are 128 aligned and 7fh ; Are we at left margin? ret z ; If so, return dec hl ; Else back up one ret ; Done backspace ; Horiz tab. Move to next 8-col tab stop. crtht: ld de,8 ld a,l ; Stop which is at or to left of cursor and 78h add a,e ; Now the next one to the right cp 80 ; Beyond right edge? ret nc ; If so, ignore the tab ld a,l ; OK to do the tab and 0f8h ; Previous tabstop ld l,a add hl,de ; Plus eight ret ; Bell - flaps a hardware bit in case you want to build a bell crtbel: in a,(pio.sd) ; Preserve rest of the bits set b5,a ; Flap bit 5 out (pio.sd),a res b5,a ; And un-flap it out (pio.sd),a ret ; Carriage return. Back cursor up to start of current row. crtcr: ld a,l ; Get current row and 80h ; Mask it off to 0 ld l,a ; Update it ret ; That was easy ; FF says clear screen and re-init scope handler crtff: ld hl,crtram ; Cursor to top of screen push hl ; Hold while we clear it ld de,crtram+1 ; The old BLT .+1 trick ld bc,0c00h ; Whole screen ld (hl),' ' ; Clear with spaces ldir ; Zap! pop hl ; Restore cursor ld a,23 ; Reset the scroll hardware ld (scroll),a ; and our copy of it out (crt.sc),a ret ; That's it, screen cleared. ; Linefeed. Cursor down and maybe scroll up. crtlf: ld a,l ; Figure present line number rla ; from hl ld a,h rla and 1fh ld c,a ; Hold it call nxtlin ; Step to next line ld a,(scroll) ; Are we at bottom of screen? cp c ret nz ; If not, no need to scroll push hl ; Have to scroll. Hold cursor call clrlin ; Put up a row of spaces add hl,hl ; Shift row into H register ld a,h and 1fh ; Here's row number ld (scroll),a ; Let hardware rotate screen for us out (crt.sc),a pop hl ; Recover cursor ret ; Compute address of next line nxtlin: ld de,80h ; Step one line add hl,de ld a,h ; Off the end? cp crtpag+12 ret c ; OK if not ld h,crtpag ; Yes, back up to base ret clrlin: ld a,l ; Go to beginning of this line and 80h ld l,a ld b,80 ; Clear 80 columns crtblk: ld (hl),' ' ; Clear with spaces inc hl ; Step thru CRT RAM djnz crtblk ; Fill whole line ret