; "VBIOS"; Rev 0; Written by Ben L Gee; Dec 9, 1979 ; Modified by Dan Fischler for use with a Z80 Assembler ; August 27, 1980 ; VBIOS is a driver for the SSM VB3 video board. VBIOS contains ; only enough code to run CP/M and some CP/M programs. If a more ; intelligent driver is required then you should consider ICRT. ; DEFINE SOME SYSTEM EQUATES. ROM EQU 0E000H ;Beginning of ROMmable code FALSE EQU 0 TRUE EQU NOT FALSE ; DEFINE THE VB3 PARAMETERS VIDEO EQU 0C000H ;Address of video memory OFFSET EQU 01000H ;Relative offset to attribute field VTAC EQU 0D0H ;I/O address of the CRT controller KSTAT EQU 0E0H ;Keyboard Status/Board Enable Port KDATA EQU 0E1H ;Keyboard Data/Board Disable Port NCOLS EQU 80 ;Number of Columns NROWS EQU 24 ;Number of Rows SKEW EQU 0 SCANF EQU 525 ;Scans per frame SCANR EQU 11 ;Scans per data row HCOUNT EQU 113 ;Character times in 1 horiz scan line INTERL EQU TRUE ;Display is interlaced CODE EQU 5 ;80 columns NORMAL EQU 3 ;Set alphanumeric mode IF INTERL VFILL EQU SCANF-513 ENDIF IF NOT INTERL VFILL EQU SCANF-256 ENDIF VMARG EQU (SCANF-NROWS*SCANR)/4+8 ; DEFINE SOME ASCII VALUES BS EQU 08H LF EQU 0AH CR EQU 0DH ; VIDEO DRIVER SUBROUTINES ; ENTRIES POINTS ARE: ; ; VBINIT - To initialize the hardware and software ; VBIN - To get a keystroke from the keyboard ; VBOUT - To output a character to the display ; VBSTAT - To check the keyboard status ; ; CALLING SEQUENCES: ; ; CALL VBINIT ; ; CALL VBIN ; STA KEYSTROKE ;Result in Register A ; ; LDA DATA ;Output Character in Register C ; MOV C,A ; CALL VBOUT ; ; CALL VBSTAT ;Returns Register A=0 if ; No keystroke is available, else ; Returns Register A=0FFH ORG ROM JP VBINIT JP VBIN JP VBOUT JP VBSTAT VBINIT: OUT KSTAT,A ;Enable the VB3 board LD HL,0 CALL EEOS ;Clear the screen CALL CURON ;Put the cursor on the screen ; INITALIZE ALL OF THE CONTROL REGISTERS OUT VTAC+14,A OUT VTAC+10,A ;Reset the VTAC LD A,HCOUNT-1 OUT VTAC+0,A IF NOT INTERL LD A,03CH ENDIF IF INTERL LD A,0BCH ENDIF OUT VTAC+1,A IF NOT INTERL LD A,SCANR*8-8+CODE ENDIF IF INTERL LD A,SCANR*8-16+CODE ENDIF OUT VTAC+2,A LD A,SKEW*64+NROWS-1 OUT VTAC+3,A LD A,VFILL/2 OUT VTAC+4,A LD A,VMARG OUT VTAC+5,A ;Try to center the data on the screen LD A,NROWS-1 OUT VTAC+6,A OUT VTAC+14,A ;Start the timing chain OUT KDATA,A ;Disable the VB3 board RET VBSTAT: IN A,KSTAT ;Check keyboard status CPL AND 1 RET Z ;Return a zero if no data is available LD A,0FFH RET ;Else return a 0FFH VBIN: CALL VBSTAT ;RETURN THE NEXT KEY FROM THE KEYBOARD JP Z,VBIN ;WAIT UNTIL ONE IS AVAILABLE IN A,KDATA ;Get it RET ;And return ; VBOUT IS THE MAIN DISPLAY DRIVER FOR THE VB3 BOARD VBOUT: PUSH HL ;First, save all registers PUSH DE PUSH BC OUT KSTAT,A ;And enable the VB3 board CALL CUROFF ;Then, turn off the cursor CALL PROCES ;And process the character CALL CURON ;Now, turn the cursor back on, OUT KDATA,A ;disable the VB3 board, POP BC ;and restore the registers POP DE POP HL RET ; ON ENTRY, REG HL = LOGICAL CURSOR ADDRESS AND REG C = DATA. PROCES: LD A,C ;Move the data to Register A AND 7FH ;Strip parity and set flags RET Z ;Skip nulls CP CR ;Check for control characters JP Z,DOCR ;If match, then do control character CP LF JP Z,DOLF CP BS JP Z,DOBS ; MUST BE A DATA CHARACTER. PUSH HL ;Save the logical cursor address CALL GETBA ;Get the physical cursor address LD (HL),C ;Put the data there LD DE,OFFSET ADD HL,DE ;Compute the addr of the governing attrib POP HL ;Get the logical cursor address back CALL RIGHT ;Move the cursor right RET NZ ;Done if the cursor didn't wrap around ; PUT THE CURSOR ON COLUMN 1 OF THE CURRENT LINE. DOCR: LD L,0 ;Put the cursor on Col 1 of the next line RET ; PUT THE CURSOR ON THE NEXT LINE, BLANK THE LINE. DOLF: CALL DOWN ;Move the cursor down one line PUSH HL ;Save the cursor address LD L,0 ;Put the cursor on column 1 CALL EEOL ;Erase to the end of the line POP HL ;Restore the cursor address RET ;Return to caller ; ERASE FROM THE CURSOR TO THE END OF THE CURRENT LINE. EEOL: LD A,NCOLS SUB L LD B,A LD C,1 ; ERASE THE SCREEN BEGINNING AT THE CURSOR POSITION.THE NUMBER OF CHARACTERS ; TO ERASE IS IN REG BC. ERASE: PUSH HL ERASE1: PUSH HL CALL GETBA LD DE,OFFSET EX DE,HL ADD HL,DE EX DE,HL LD A,NORMAL ;Use the normal attribute ERASE2: LD (HL),' ' LD (DE),A INC HL INC DE DEC B JP NZ,ERASE2 POP HL LD L,0 CALL DOWN LD B,NCOLS DEC C JP NZ,ERASE1 POP HL RET ; BACK THE CURSOR BY ONE POSITION. DOBS: CALL LEFT RET NZ ; MOVE THE CURSOR UP. UP: LD A,H DEC H OR A RET NZ LD H,NROWS-1 RET ; MOVE THE CURSOR DOWN. DOWN: INC H LD A,NROWS CP H RET NZ LD H,0 RET ; MOVE THE CURSOR LEFT. LEFT: LD A,L DEC L OR A RET NZ LD L,NCOLS-1 RET ; MOVE THE CURSOR RIGHT RIGHT: INC L LD A,NCOLS CP L RET NZ LD L,0 RET ; ERASE FROM THE CURSOR POSITION TO THE END OF THE SCREEN. EEOS: LD A,NCOLS SUB L LD B,A LD A,NROWS SUB H LD C,A JP ERASE ; TURN THE CURSOR ON. ; THE LOGICAL ADDRESS OF THE CURSOR MUST BE IN REG HL. CURON: LD A,L OUT VTAC+12,A LD A,H OUT VTAC+13,A OUT VTAC+6,A ;Make sure the cursor is on the bottom RET ; TURN THE CURSOR OFF. ; THE LOGICAL ADDRESS OF THE CURSOR IS RETURNED IN REG HL. CUROFF: IN A,VTAC+9 ;Read the column register LD L,A ;To Register L IN A,VTAC+8 ;Read the row register LD H,A ;To Register H LD A,0FFH ;Move the cursor off the screen OUT VTAC+12,A RET ; CONVERT A LOGICAL ADDRESS TO A PHYSICAL ADDRESS. ; ON ENTRY, HL CONTAINS THE LOGICAL ADDRESS. ; ON EXIT, HL CONTAINS THE PHYSICAL ADDRESS. ; A LOGICAL ADDRESS IS IN THE FORM (ROW, COLUMN) WITH ROW IN REG H AND COLUMN ; IN REG L. ROW MUST BE IN THE RANGE OF 0 TO NROWS-1 AND COLUMN MUST BE IN ; THE RANGE OF 0 TO NCOLS-1. ; A PHYSICAL ADDRESS IS THE ACTUAL MEMORY ADDRESS IN THE VIDEO MEMORY. GETBA: PUSH DE PUSH BC EX DE,HL INC D LD HL,-NCOLS LD BC,NCOLS GETBA2: ADD HL,BC DEC D JP NZ,GETBA2 ADD HL,DE LD DE,VIDEO ADD HL,DE POP BC POP DE RET END