home *** CD-ROM | disk | FTP | other *** search
- title 'Executive Processor For CP/M'
- ;
- ;----------------------------------------------------------------
- ; This module contains the Console I/O Drivers for CP/M as well
- ; as printer and AUX drivers, initialization code and the
- ; I/O pocessor code.
- ;
- ; These are meant to be run in conjunction with the EXEC
- ; module.
- ;
- ;
- ; Written By Richard Holmes 04-02-86
- ; Last Update By Richard Holmes 11-12-87
- ;----------------------------------------------------------------
- ;
- public sys$ini
- public con$ini,con$inp,con$out,con$ost,con$ist,con$cmd
- public aux$ini,aux$inp,aux$out,aux$ost,aux$ist,aux$cmd
- public prn$ini,prn$out,prn$ost
- public lcd$ini,lcd$out,lcd$ost,lcd$cmd
- ;
- public set$led,clr$led,tog$led,zro$led
- public set$bel,clr$bel
- public clk$rd,clk$wr
- public ms$delay
- ;
-
- public clrwdt
- public hrs, min, sec
- ;
- maclib z80
- maclib iocmd
- ;
- ; CP/M equates
- ;
- bdos equ 5 ;; Operating system entry
- dirio equ 6
- numatt equ 6 ; 6 attributes
- cr equ 0dh ; Simple video definitions
- lf equ 0ah
- ;
- clrwdt:
- set$led:
- clr$led:
- tog$led:
- zro$led:
- set$bel:
- clr$bel:
- clk$rd:
- clk$wr:
- ret
- sys$ini:
- xra a
- sta hrs
- sta min
- sta sec
- ret
- ;
- lcd$ini:
- lcd$out:
- lcd$ost:
- lcd$cmd:
- xra a
- ora a
- ret
- ;
- ms$delay:
- mov a,e
- ora d
- rz
- ;
- push d ; save it
- delay2:
- call clr$wdt
- call delay3
- dcx d ; one less millisecond less overhead
- mov a,d
- ora e
- jrnz delay2 ; keep on till DE = 0
- pop d ; restore users initial value
- ret ; back to user
- ;
- ; Delay 1 millisecond less the overhead involved in the above code.
- ;
- ; This routine must delay 3957 t-states
- ;
- delay3:
- push b ; 11
- mvi b,224 ; 7
- delay4: ; This loop does (4 + 13) * 230 - 5 = 3905 t
- nop ; 4
- nop
- djnz delay4 ; 13
- ; Fudge 14 machine cycles
- lxi b,0 ; 10
- nop ; 4
- pop b ; 10
- ret
- ;
- ;----------------------------------------------------------------
- ; This is the console command processor. The channel routines call
- ; it with a function number in C and these are then performed.
- ;----------------------------------------------------------------
- ;
- con$cmd:
- push h
- push b
- push d
- mvi b,0 ; Top offset = 0
- lxi h,con$cmd$tbl ; -> table of routine addresses
- dad b
- dad b ; Add twice for 2 byte offsets
- mov e,m ; Low address
- inx h ; -> High address
- mov d,m
- xchg ; HL -> routine
- pop d ; Restore DE, it may be a parameter
- pop b ; BC could be someones counter
- xthl ; top of stack = routine, HL restored also.
- ret
- ;
- con$cmd$tbl:
- dw 0
- dw clear
- dw cleop
- dw cleol
- dw cursor
- dw setatt
-
-
-
- aux$cmd:
- xra a
- ora a
- ret
- ;
- ;================================================================
- ;
- ; ---- Console Output ----
- ;
- ; On Entry
- ; A = character to send
- ;================================================================
- ;
- con$out:
- push h
- push b
- push d
- mov e,a ; Load the ascii character
- mvi c,dirio ; Direct console output
- call bdos
- pop d ; Restore output
- pop b
- pop h
- ora a
- ret
- ;
- ;================================================================
- ;
- ; Get a console character into A
- ;
- ;================================================================
- ;
- con$inp:
- push h
- push b
- push d
- cie$wait:
- call con$ist
- jrz cie$wait
- ;
- mvi e,0fdh ; Wait and fetch
- mvi c,dirio
- call bdos
- pop d
- pop b
- pop h
- ret
- ;
- ;================================================================
- ;
- ; Get the console status.
- ;
- ; On Exit
- ; A = 0 if not ready,
- ; 1 if got a character
- ;================================================================
- ;
- con$ist:
- push h
- push b
- push d
- mvi e,0feh ; Status only code
- mvi c,dirio ; Direct console I/O
- call bdos
- pop d
- pop b
- pop h
- ora a
- ret
- ;
- con$ini:
- con$ost:
- xra a
- ora a
- ret
- ;
- ;----------------------------------------------------------------
- ; Read a character into A and return it to the user. Wait for it
- ; for ever if needed. Not a smart routine at all.
- ;
- ; On Entry
- ;
- ; On Exit
- ; A = character read from AUX port
- ; All other registers preserved
- ;----------------------------------------------------------------
- ;
- aux$inp:
- push h
- push b
- push d
- ;
- mvi c,3 ; AUX Input code
- call bdos
- ;
- pop d
- pop b
- pop h
- ret
- ;
- ;----------------------------------------------------------------
- ; Write the character in A to the AUX port.
- ;
- ; On Entry
- ; A = character to write
- ;
- ; On Exit
- ; All other registers preserved
- ;----------------------------------------------------------------
- ;
- aux$out:
- push psw
- push h
- push b
- push d
- ;
- mvi c,4 ; Aux out code
- mov e,a ; Load data
- call bdos
- ;
- pop d
- pop b
- pop h
- pop psw
- ret
- ;
- ;----------------------------------------------------------------
- ; Return the input status.
- ;
- ; On Exit
- ; A = FF if a character ready
- ; A = 00 if no character ready
- ;----------------------------------------------------------------
- ;
- aux$ist:
- push h
- push b
- push d
- ;
- mvi c,07
- call bdos
- ;
- pop d
- pop b
- pop h
- ora a ; Set the zero flags
- ret
- ;
- ;----------------------------------------------------------------
- ; Return the output status of the console port.
- ;
- ; On Exit
- ; A = FF if port ready for character output
- ; A = 00 for device busy
- ;----------------------------------------------------------------
- ;
- aux$ost:
- push h
- push b
- push d
- ;
- mvi c,8
- call bdos
- ;
- pop d
- pop b
- pop h
- ret
- ;
- aux$ini:
- xra a
- ora a
- ret
- ;
- ;----------------------------------------------------------------
- ; Printer Drivers.
- ;----------------------------------------------------------------
- ;
- prn$out:
- push h
- push b
- push d
- ;
- mov e,a ; Load character
- mvi c,5 ; Printer output
- call bdos
- ;
- pop d
- pop b
- pop h
- ret
- ;
- prn$ost:
- prn$ini:
- xra a
- ora a
- ret
- ;
- ; Initializations.
- ;
- ini$vid:
- xra a
- sta curatt ; Select attribute 0
- sta curvid
- ret
- ;
- ;================================================================
- ; Terminal Function Codes
- ;================================================================
- ;
- ; General purpose function codes
- ;
- xyfn: db 02,01bh,'=',00,00 ; xy addressing
- ;
- rowcol: db 00 ; 00 means row first
- xoff: db 32 ; X offset
- yoff: db 32 ; Y offset
- cdly: db 01 ; Cursor positioning delay qty
- ;
- cpfn db 02,01bh,'*',00,00 ; erase whole page
- clfn db 02,01bh,'T',00,00 ; erase to end of line
- epfn db 02,01bh,'Y',00,00 ; erase to end of page
- ecfn db 03,01bh,'.','1',0 ; enable cursor function
- dcfn db 03,01bh,'.','0',0 ; disable cursor function
- ;
- attset:
- db 2,01bh,029h,00,00 ; Start half intensity
- db 2,01bh,05eh,00,00 ; Start blinking
- db 2,01bh,06ah,00,00 ; Start reverse video
- db 2,01bh,06ch,00,00 ; Start underline
- db 4,01bh,029h,01bh,05eh ; Start half-blinking
- db 4,01bh,06ah,01bh,05eh ; Start reverse-blinking
- db 0,00,00,00,00 ; Start underline
- ;
- attclr:
- db 02,01bh,028h,00,00 ; End half intensity
- db 02,01bh,071h,00,00 ; End blinking
- db 02,01bh,06bh,00,00 ; End reverse video
- db 02,01bh,06dh,00,00 ; End underline
- db 4,01bh,071h,01bh,028h ; End half-blinking
- db 4,01bh,071h,01bh,06bh ; End reverse-blinking
- db 0,00,00,00,00 ; end
- ;
- ;
- ;-----------------
- ; Clear the screen
- ;-----------------
- ;
- clear:
- push b
- push h ; save
- push psw
- lxi h,cpfn ; clear page function
- jmp do$fn ; send the function and return
- ;
- ;----------------------------------------------------------------
- ; Clear the screen till the end of the line. This is highly
- ; terminal dependant and is table driven to suit.
- ;----------------------------------------------------------------
- ;
- cleol:
- push b
- push h ; save
- push psw
- lxi h,clfn ; clear page function
- jr do$fn ; send the function and return
- ;
- ;----------------------------------------------------------------
- ; Clear to the end of the page. Same comments as the above fn.
- ;----------------------------------------------------------------
- ;
- cleop:
- push b
- push h ; save
- push psw
- lxi h,epfn ; clear page function
- jr do$fn ; end of job
- ;
- ;-----------------------------------------------
- ; Set a visual attribute onto the video terminal
- ; Attribute in register A
- ;-----------------------------------------------
- ;
- setatt:
- cpi numatt + 1 ; In range ??
- rnc ; Return tail B/N legs if too big
- push d
- push b
- push h
- push psw ; Save the users attribute
- mov c,a ; Save locally also
- lda curatt ; Get the current attribute
- cmp c
- jz set$fin ; Terminate if THE SAME
- ora a
- jrz doatt ; If 00, no need to clear old one, already 0
- ;
- ; See if the current attribute is an illegal value. This may be because of
- ; rom based software first time through and a silly ram value.
- ;
- cpi numatt + 1
- jrnc doatt ; Silly old attribute, then set new one now.
- ;
- ; Here we must clear the old attribute before proceeding.
- ;
- clr$start:
- dcr a ; Make the attribute in range
- lxi h,attclr ; Point to the table of clear atts.
- call index
- call att$send ; Send the attributes -> by HL
- doatt:
- pop psw ; Get users attribute
- sta curatt ; Save in ram.
- ora a ; Is it attribute 00 ?
- jrz set$end ; Ignore if so
- dcr a ; Make in the correct range then
- ; Now index into the table of attribute setting bytes to get the req'd code.
- lxi h,attset ; Point to start
- call index ; Get hl -> start
- call att$send ; Send attributes -> by HL
- ;
- ; Re-load registers and return.
- ;
- set$end:
- pop h
- pop b
- pop d
- ret
- ;
- ; Restore registers when terminated
- ;
- set$fin:
- pop psw
- jr set$end
- ;
- ; This routine must use HL -> a counter byte to send
- ; the proceeeding bytes to the console.
- ;
- att$send:
- mov a,m
- ora a ; See if a null length ?
- rz ; Return if a null string
- mov b,a ; Else load the length
- sloop:
- inx h ; Point to next character
- mov a,m
- call con$out ; Send
- djnz sloop
- ret
- ;
- ;----------------------------------------------------------------
- ; This routine that follows simply indexes into the table
- ; of bytes. Each table entry is assumed to be 5 bytes long.
- ;
- ; On entry hl -> start of table, on exit hl -> first element
- ; in line (a)
- ;----------------------------------------------------------------
- ;
- index:
- ora a
- rz ; Return if no loops needed
- mvi d,0 ; Clear upper register
- mov e,a ; Load counter
- ; Multiply A by 5 then add to HL
- add a ; * 2 (double original)
- add a ; * 4
- add e ; * 5 (add original)
- mov e,a ; load into indexing register
- dad d ; now HL -> start of this entry
- ret ; hl -> start of a line
- ;
- ; This routine uses HL to send the function to the screen.
- ;
- send$fn:
- mov a,m ; test if this is not supported
- ora a
- rz ; not supported if no bytes to send
- mov b,a ; load a counter
- send$fn2:
- inx h ; get next byte
- mov a,m
- call con$out
- djnz send$fn2
- ret
- ;
- ;----------------------------------------------------------------
- ; Send the function pointed to by HL to the terminal then exit
- ;----------------------------------------------------------------
- ;
- do$fn:
- call send$fn ; send it.
- ; Fall through to the exit routine
- end$fn:
- pop psw
- pop h
- pop b
- ret
- ;
- ;----------------------------------------------------------------
- ; Position the cursor to the value in DE. D = X, E = Y.
- ;----------------------------------------------------------------
- ;
- cursor:
- push b
- push h
- push psw ; save registers
- push d ; save the original
- ; Send the lead in string
- lxi h,xyfn ; XY addressing lead in string
- call send$fn
- ; Now we must add the offsets to be applied to the X and Y values
- lda xoff
- add e ; Y value
- mov e,a ; save it
- ;
- lda yoff
- add d ; X value
- mov d,a ; save it also
- ; Now decode the row or column sent first decision
- lda rowcol ; 00 = row first
- ora a
- jrz row$first
- ; Here and we are sending the column first (X value first)
- mov a,d ; X value
- call con$out
- mov a,e ; Y next
- jr row$first2
- ; Here and we send the row first for cursor addressing
- row$first:
- mov a,e ; Y value
- call con$out
- mov a,d ; X value next
- row$first2:
- call con$out
- pop d ; restore original cursor address
- ; Now do any delays required
- lda cdly
- cursor$delay:
- ora a
- jrz end$fn ; End of job
- push psw
- mvi a,0ffh ; Loop counter
- cd$loop:
- nop ; Extra waits
- dcr a
- jrnz cd$loop ; Loop till A = 0
- pop psw
- dcr a ; One done.
- jr cursor$delay
- ;
- ;----------------------------------------------------------------
- ; Write bytes at mDE till a null
- ;----------------------------------------------------------------
- ;
- wrt$vid:
- ldax d
- ora a
- rz
- call con$out
- inx d
- jr wrt$vid
- ;
- dseg
- ;
- hrs ds 1
- min ds 1
- sec ds 1
- ;
- curatt db 00
- curvid db 00
- end
- ;
- ;
- ;