title Video driver routines for the KAYPRO-10 (C) 1983 By NLS. .comment % ######################################################## ## ## ## KAYPRO 10 System ## ## ## ## By M. Sherman ## ## ## ## Video driver routines for the KAYPRO-10 ## ## and the 6545 video controller chip. ## ## ## ## Copyright (C) 1983 By Non-Linear Systems, Inc ## ## No warranty is made, expressed or implied. ## ## ## ######################################################## ## Date: 04/14/83 [01] ## ######################################################## % ; external variables extrn cursor, vrbase, crow, ccol, vatt, leadflg, vgb1 extrn esccmd, row, row2, col, col2, vidram, ramlen, precur ; external routines extrn movsts, dltlin, inslin extrn pixon, pixoff, lineon, lineoff extrn kbdout ; routines for everyone else to use public vidout, vidinit, regrst, dtwait, clrdis, clreol, carret, putcur public getc, putc, getatt, putatt, print .Z80 ; conditional assembly equates TRUE equ 0ffffh FALSE equ NOT TRUE ; video controller locations vcbase equ 1ch ; video controller base address vccmd equ vcbase ; register select port vcstat equ vcbase ; status port vcrdat equ vcbase+1 ; register data port vcdata equ vcbase+3 ; video controller data port ; command format, video controller commands: ; high byte = register to select, low byte = base addr. (register select) curcmd equ 0e1ch ; place cursor command rwcmd equ 121ch ; read/write command strcmd equ 01fh ; strobe, or "tickle", command scrcmd equ 0c1ch ; set start of display address command ; ("scroll" command) hiadd equ 12h ; high byte register #, video mem. address, loadd equ 13h ; low byte register #, video mem. address. cstart equ 0ah ; cursor starting row count, cursor def. reg # cstop equ 0bh ; cursor ending row count. csron equ 60h ; cursor on, blinking at 1/32, starting row=0 csroff equ 20h ; no cursor, starting row=0 (irrelevant) ; special character equates space equ 020h nrmlatt equ 00h ; single character control codes belli equ 07h ; bell code to video driver, bello equ 04h ; bell code to keyboard. cr equ 0dh ; carriage return lf equ 0ah ; line feed ceol equ 18h ; clear to end of line ceos equ 17h ; clear to end of screen clrscr equ 1ah ; clear screen homec equ 1eh ; home cursor lcur equ 08h ; left cursor (backspace) rcur equ 0ch ; right cursor (forespace) ucur equ 0bh ; up cursor esc equ 1bh ; escape code, initiates multi- ; -character control sequences ; two-character commands dline equ 'R' ; delete line iline equ 'E' ; insert line ; three-character commands atton equ 'B' ; set attribute attoff equ 'C' ; clear attribute ; four-character commands setpix equ '*' ; set pixel clrpix equ ' ' ; clear pixel lodcur equ '=' ; load cursor address (cursor positioning) ; six-character commands lindraw equ 'L' ; draw a line lineras equ 'D' ; erase a line ; video driver equates linesiz equ 80 ; characters per line linesps equ 24 ; number of lines in the normal display statlin equ linesps+1 ; line number, status line lastlin equ (linesps-1)*linesiz ; address, first chara last ; normal display line ; (the line above the status line) ;################################################ ;# # ;# video drivers # ;# # ;################################################ ; clear to end of line clreol: call caleol ; calculate end of line count jr clrdis ; clear to end of screen clreos: ld c,linesps-1 ld a,(vatt) and 20h jr nz,ceos22 inc c ceos22: ld a,(crow) sub c jr nc,clreol ; clear to end of line if on last legal line neg ; two's complement, number of lines to erase ld b,a ld de,linesiz ld hl,0 clresl: add hl,de djnz clresl push hl call caleol pop bc add hl,bc ; total count in hl jr clrdis ; do it caleol: ld hl,linesiz ld de,(cursor) ld a,(ccol) ld c,a xor a ; clear a, clear flags (especially carry!) ld b,a ; clear b sbc hl,bc ; hl=number of bytes to move ret vidinit:; Video hardware/software initialization routine. Will set ; video driver ram storage to reset/restart values, ; reprogram the video controller chip, ; clear the screen and place the cursor in the upper right corner. ; ramini: ld hl,vidram ; first, initialize the ram. ld b,ramlen xor a rinilp: ld (hl),a inc hl djnz rinilp ctrini: ld hl,ctrtbl ; then initialize the controller, ld bc,ctblen*256+vcbase+1 xor a ; first register,=00 cinilp: dec c ; c:=base out (c),a ; select register inc a ; a:=register to program inc c ; c:=data port outi ; (hl):=program data, out to (c) jr nz,cinilp ; until b:=0 ld a,strcmd out (vccmd),a ; start video chip processing. ; fall through to clear screen clear: call home ; home cursor clear2: ld a,(vatt) and 0f0h ; clear ordinary attributes ld (vatt),a ; clear attribute byte ld de,(cursor) ; same as vrbase, now ld hl,statlin*linesiz ; screen size and 20h jr z,clrdis ld hl,linesps*linesiz ; fall through to clrdis... clrdis: ; clear display and associated attributes. ; de := start address, hl := number of locations to clear ; all registers affected... ; ld bc,hiadd*100h+loadd cdislp: in a,(vcstat) or a jp p,cdislp ; wait until ready, ld a,b ; high address byte register number, out (vccmd),a ; select it ld a,d ; get high byte, new address, and 07h ; qualify address, ld d,a ; put it back, out (vcrdat),a ; output it. ld a,c ; select out (vccmd),a ; low address byte register, ld a,e ; get low address byte, out (vcrdat),a ; output it. ld a,strcmd out (vccmd),a ; start a new cycle, cdislp3:in a,(vcstat) ; wait until it's ready, or a jp p,cdislp3 ld a,20h ; clear data byte, out (vcdata),a inc de ; set up for attr., next byte cdislp2:in a,(vcstat) ; go do attributes or a jp p,cdislp2 ld a,b ; high address byte register number, out (vccmd),a ; select it ld a,d ; get high byte, new address, or 08h ; qualify address, out (vcrdat),a ; output it. ld a,c ; select out (vccmd),a ; low address byte register, ld a,e ; get low address byte, out (vcrdat),a ; output it. ld a,strcmd out (vccmd),a ; start a new cycle, cdislp4:in a,(vcstat) ; wait until finished. or a jp p,cdislp4 xor a ; clear attribute byte out (vcdata),a dec hl ld a,h or l jr nz,cdislp ret home: xor a ld (ccol),a ; reset column count ld (crow),a ; reset row count ld hl,(vrbase) ex de,hl jp putcur ; place cursor and exit ; video controller initialization table, currently for a 25 by 80 display. ; ctrtbl: db 6ah ; reg00 total char/sweep including retrace, clocks db 50h ; reg01 total displayed, cclks db 56h db 99h db 19h db 0ah db 19h db 19h db 78h db 0fh db 60h db 0fh db 00h db 00h db 00h db 00h ctblen equ $-ctrtbl ; table length ; main entry point. vidout: ld a,(leadflg) ; set by escape sequences or a jp nz,escseq ; an escape sequence is in progress ld a,c or a ret z ; ignore nulls (requested by tech support) jp m,vgmod ; video mode set? find out if negative (>80h) cp space jp c,spechar ; special characters spcexe: ld a,c ld de,(cursor) ; special character re-entry if non-control call putc call puta ; place attribute vgmexe: ld a,(ccol) inc a cp linesiz jp nc,crlf ld (ccol),a ; save new count ld de,(cursor) inc de jp putcur ; reposition cursor and exit vgmod: ld a,(vatt) and 10h jr z,spcexe ; not video graphics mode if not zero ld a,(vgb1) and 40h jr z,vgmod2 ld a,c and 01 ld (vgb1),a ret vgmod2: ld a,(vgb1) or a ld a,c jr z,vgmod5 cpl vgmod5: or 80h ld de,(cursor) call putc ld a,(vgb1) ld c,a ld a,(vatt) or c call putatt ld a,40h ld (vgb1),a ; set first jr vgmexe ; move the cursor to the beginning of the line carret: ld hl,(cursor) ld a,(ccol) ld e,a xor a ; clear flags,a ld d,a ld (ccol),a ; reset line count to zero sbc hl,de ; hl = beginning of line ex de,hl ; de = beginning of line jr putcur ; place cursor and exit ; crlf places the cursor at the beginning of the next line and sets the ; character column count, ccol, to zero. crlf: call carret ; carriage return ; fall through to linefeed... ; move the cursor down one line, scroll if necc. linefd: ld a,(crow) ; character row count cp linesps-1 ; lines per screen jr c,linef2 ; not last line if carry, cp statlin-1 ; status line? ret z ; if so, don't scroll call scroll ; else is last line, scroll screen jr linef3 ; don't update character row count. linef2: inc a ; update character row count, ld (crow),a linef3: ld hl,(cursor) ; move the cursor down one line. ld de,linesiz add hl,de ex de,hl ; fall through to putcur... ; place cursor, new cursor address in de putcur: ld a,d and 07h ld d,a ex de,hl ld (cursor),hl ld bc,(vrbase) sbc hl,bc jr nc,putcr2 ld de,0800h add hl,de putcr2: add hl,bc ex de,hl ld bc,curcmd jp regrst upcur: ld a,(crow) cp statlin-1 ret z ; no cursor up from status line, or a ret z ; or from top line dec a ld (crow),a ; update row count ld hl,(cursor) ld de,linesiz sbc hl,de ex de,hl ; put new value in de jr putcur lfcur: ld a,(ccol) or a jr nz,lcur2 ld a,(crow) or a ret z ; no way can do cp statlin-1 ; on status line? jr z,lcur3 dec a ld (crow),a ; update row count ld a,linesiz lcur2: dec a ld (ccol),a ; update column count ld de,(cursor) dec de jr putcur ; place and exit lcur3: ld a,linesiz-1 ld (ccol),a ; going to the end of the line ld hl,(cursor) ld de,linesiz-1 add hl,de ex de,hl jr putcur rtcur: ld a,(ccol) cp linesiz-1 jp nc,crlf ; do a cr, do a lf if not status line ld de,(cursor) inc de inc a ld (ccol),a ; reset column count jr putcur scroll: jp movsts ; fast scroll setatr: ld hl,vatt ld a,c sub 30h jr z,revid ; set reverse video on dec a jr z,redint ; set reduced intensity on dec a jr z,sblink ; set blinking on dec a jr z,sunlin ; set underlining on dec a jr z,setcur ; set cursor on dec a jr z,setvid ; set video mode on dec a jr z,savcur ; save current cursor location dec a jr z,savsts ; save contents of status line during scroll ret ; illegal, exit ; set attributes revid: ld a,(hl) or 01h ld (hl),a ret redint: ld a,(hl) or 02h ld (hl),a ret sblink: ld a,(hl) or 04h ld (hl),a ret sunlin: ld a,(hl) or 08h ld (hl),a ret setcur: ld c,csron ; cursor on, 1/16 blink setcr2: ld a,cstart ; cursor select register out (vccmd),a ld a,c out (vcdata),a ; turn on cursor, 1/16 blink ret setvid: ld a,(vatt) ; turn on video mode. or 10h ; (GB1,GB2 graphics pairs) ld (vatt),a ld a,40h ld (vgb1),a ret savcur: ld hl,(crow) ; save, or 'remember', current cursor position ld (precur),hl ret savsts: ld a,(vatt) ; turn on status line preservation, or 00100000b ; protect it from scrolling. ld (vatt),a ret ; clear attributes clratr: ld hl,vatt ld a,c sub 30h jr z,nrmvid ; set normal video on dec a jr z,nrmint ; set normal intensity on dec a jr z,cblink ; set blinking off dec a jr z,cunlin ; set underlining off dec a jr z,clrcur ; set cursor off dec a jr z,clrvid ; set video mode off dec a jr z,rstcur ; restore cursor to last loc. dec a jr z,scrsts ; scroll contents of status line during scroll ret ; illegal, exit ; clear attributes: nrmvid: ld a,(hl) ; set to non-inverted display mode. and 11111110b ld (hl),a ret nrmint: ld a,(hl) ; set to normal intensity and 11111101b ld (hl),a ret cblink: ld a,(hl) ; set to no blinking. and 11111011b ld (hl),a ret cunlin: ld a,(hl) ; set to no underlining. and 11110111b ld (hl),a ret clrcur: ld c,csroff ; turn cursor off jr setcr2 clrvid: ld a,(hl) ; turn off video mode and 11101111b ld (hl),a ret rstcur: ld hl,(precur) ; return cursor to last remembered location. ld a,h ; ccol add a,space ld (col),a ld a,l add a,space ld (row),a jp curpos ; restore previously saved cursor scrsts: ld a,(vatt) ; turn off status line preservation, and 11011111b ; scroll status line on scrolls ld (vatt),a ret ; X,Y cursor positioning routine ; curpos: ld hl,0 ld c,l ; set c to zero, too. ld a,(row) sub space ret c ; error, exit ld b,a jr z,curpo3 cp statlin ; lines per screen ret nc ; error, exit ld de,linesiz curpo2: add hl,de djnz curpo2 curpo3: ld e,a ; save row count ld a,(col) sub space ret c ; error, exit cp linesiz ret nc ; error, exit ld c,a ld (ccol),a ; new column count ld a,e ld (crow),a ; new row count add hl,bc ld de,(vrbase) add hl,de ex de,hl jp putcur ; place cursor dtwait: ld bc,rwcmd rgwait: call regrst dec c ; return c to original value ld a,strcmd ; tickle the dummy out (c),a rgwt2: in a,(c) or a jp p,rgwt2 ret regrst: out (c),b inc c out (c),d dec c inc b out (c),b inc c out (c),e ret getc: ld a,d and 07h ld d,a getc2: call dtwait in a,(vcdata) ret putc: push af ; save data ld a,d and 07h ld d,a putc2: call dtwait pop af out (vcdata),a ret puta: ld a,(vatt) ; video attribute putatt: push hl ; save hl push af call addatt call dtwait pop af out (vcdata),a ex de,hl pop hl ret getatt: push hl call addatt call getc2 ex de,hl pop hl ret addatt: ld hl,801h ; video attribute offset add hl,de ld a,h and 07h ; 00000000 to 00000111 or 08h ; 00001000 to 00001111 ld h,a ex de,hl ret escseq: ld hl,leadflg ld (hl),0 ; clear flag cp 1 jr nz,esc2 ld a,c and 07fh cp dline ; delete line? jp z,dltlin cp iline ; insert line? jp z,inslin cp 'A' ; Kaypro-II display lower case? ret z ; yes, ignore cp 'G' ; Kaypro-II display greek? ret z ; yes, ignore ld (esccmd),a ; set command ld (hl),2 ret esc2: cp 2 jr nz,esc3 ld a,(esccmd) cp atton jp z,setatr ; set attribute command cp attoff jp z,clratr ; clear attribute ld a,c ld (row),a ld (hl),3 ret esc3: cp 3 jr nz,esc4 ld a,c ld (col),a ld a,(esccmd) cp lodcur jp z,curpos ; cursor positioning cp setpix jp z,pixon ; pixel on cp clrpix jp z,pixoff ; pixel off ld (hl),4 ret esc4: cp 4 jr nz,esc5 ld a,c ld (row2),a ld (hl),5 ret esc5: ld a,c ld (col2),a ld a,(esccmd) cp lindraw jp z,lineon cp lineras jp z,lineoff ret ; illegal command, exit. bell: ld c,bello ; put keyboard bell chara in c reg., jp kbdout ; ring bell spechar:cp cr jp z,carret ; carriage return cp lf jp z,linefd ; line feed cp belli jr z,bell ; bell cp ceol jp z,clreol ; clear to end of line cp ceos jp z,clreos ; clear to end of screen cp clrscr jp z,clear ; clear screen cp lcur jp z,lfcur ; left cursor cp rcur jp z,rtcur ; right cursor cp ucur jp z,upcur ; up cursor cp homec jp z,home ; home cursor cp esc jp nz,spcexe ; not a control character, write it ld a,1 ld (leadflg),a ; set escape in progress ret ; print routine print: pop hl ld a,(hl) inc hl push hl or a ret z ld c,a call vidout jr print defw 0000h END