;IODVR/ASM - LS-DOS 6.2 SUBTTL ' PAGE OFF ; HOME EQU 1CH CLRFRM EQU 1FH ; ; Log out routine - display & log ; @LOGOT CALL @DSPLY ; ; Job log loger routine ; @LOGER LD A,(JLDCB$) ;If NIL, don't do XOR 8 ; anything AND 8 RET Z PUSH HL ;Save pointer to command LD HL,LOGBUF ;Get time string into buf PUSH HL CALL @TIME POP HL LD DE,JLDCB$ ;Log the time CALL @MSG POP HL ;Log the command JR @MSG LOGBUF DB 'hh:mm:ss ',3 ; ; Line print routine ; @PRINT LD DE,PRDCB$ ;Printer DCB JR @MSG ; ; Line display routine ; @DSPLY LD DE,DODCB$ ;Video DCB ; ; Device message routine ; *MOD @MSG PUSH HL ;Save pointer to message $?1 LD A,(HL) ;P/u a message character CP 3 ;Exit on ETX JR Z,$?3 CP CR ;Exit & put on ENTER JR Z,$?2 CALL NZ,@PUT ;Else put the char INC HL ; & loop on no error JR Z,$?1 ; else fall thru & exit $?2 CALL Z,@PUT $?3 POP HL RET ; ; Clear screen routine ; @CLS LD A,HOME ;Cursor home to 0,0 CALL DSPBYT RET NZ ;Return on error LD A,CLRFRM ;Clear to end of frame DSPBYT PUSH DE CALL @DSP POP DE RET ; ; Check and Clear bit SVC ; @CKBRKC PUSH HL ;Save registers LD HL,KFLAG$ ;Point to KFLAG$ BIT 0,(HL) ;Check break bit JR Z,NOBRK ; and ret if none PUSH AF ;Save flags PUSH BC PUSH DE BRKTEST RES 0,(HL) ;Reset the break bit LD BC,0B00H ;Wait more than 1/30 CALL PAUSE@ ; of a second BIT 0,(HL) ;Test the bit again JR NZ,BRKTEST ;Loop until gone LD DE,KIDCB$ ;Point at keyboard & LD A,03 ; clear buffer with CALL @CTL ; control 3 call POP DE POP BC ;Recover registers POP AF ;Recover FLAGS NOBRK POP HL RET ; ; Keyboard line input routine ; *MOD ; ; Backspace to beginning of line ; $?4 CALL $?6 ;Backspace DEC HL ;Get the char prior LD A,(HL) ; to the current INC HL CP 0AH ;Return if line feed RET Z $?5 LD A,B ;Check for empty buffer CP C JR NZ,$?4 ;Loop if not RET ; else return @KEYIN PUSH HL ;Save buffer pointer LD C,B ;Set C = buffer size $?1 LD DE,@KEY ;Init for standard input LD A,(SFLAG$) ;If JCL is active, AND 20H ; then use the JCL input JR Z,$?0 ;Must loop here in case LD E,@JCL&0FFH ; JCL exits with //STOP $?0 LD ($?1A+1),DE $?1A CALL $-$ ;Get a key JR NZ,$?3B ;Back on error CP 80H ;Break? JR Z,$?10 CP 20H ;Go if not a control JR NC,$?2 CP 0DH ;Carriage return? JR Z,$?11 CP 1FH ;Clear? JR Z,$?3 LD DE,$?1 ;Set return address PUSH DE CP 08H ;Backspace? JR Z,$?6 CP 18H ;Backspace to BOL? JR Z,$?5 CP 09H ;Tab? JR Z,$?8 CP 'R'&1FH ;CTL-R? JR Z,$?7 CP 0AH ;Line feed? RET NZ ;Ret if none above POP DE ;Pop the return $?2 LD (HL),A ;Stuff the char LD A,B ;Check on buffer full OR A JR Z,$?1 ;Loop if so LD A,(HL) ; else get char INC HL ; & bump pointer DEC B ;Count down CALL @DSP ;Display entry JR $?3A ; then loop ; ; Clear the screen invoked ; $?3 CALL @CLS LD B,C ;Reset to start of POP HL ; line & start of PUSH HL ; buffer $?3A JR Z,$?1 $?3B JR $?11 ; ; Backspace key entry ; $?6 LD A,B ;If buffer is empty, CP C ; return RET Z DEC HL ; else do the backspace LD A,(HL) CP 0AH ;Last char a linefeed? INC HL RET Z ;Return if so DEC HL INC B ;Add back one char LD A,8 ;Backspace the cursor JR @DSP ; ; Test if repeat last command ; $?7 LD A,(CFLAG$) ;Test if SYS1 KEYIN bit AND 4 ; is set (bit 2) RET Z ;Ignore CTL if not LD A,B ;If not at 1st position, CP C ; don't permit it RET NZ POP HL ;Pop return to KEY POP HL ;Point to command buffer JP @DSPLY ;Display the old command ; ; Tab entered ; $?8 PUSH HL ;Get pos on line CALL ADDR_2_ROWCOL ;Get row,col in HL LD A,L ;Xfer column to A POP HL AND 7 NEG ;Negate and add tab ADD A,8 LD E,A ;Reg E has tab length $?9 LD A,B ;Check on buffer full OR A RET Z LD A,' ' ;Put spaces until LD (HL),A ; tab expanded INC HL CALL DSPBYT RET NZ DEC B ;Dec buffer remaining DEC E ;Dec tab count RET Z JR $?9 ; ; Exit KEYIN routine ; $?10 SCF ;BREAK exit with CF $?11 PUSH AF ;Save flag LD A,0DH ;Stuff CR at end LD (HL),A CALL @DSP ; & display it LD A,C ;Calculate # of chars SUB B ; entered LD B,A POP AF ;Rcvr flag POP HL ;Restore buffer ptr RET ; ; Byte I/O device handler ; C => character if PUT or CTL ; DE => Device control block ; *MOD @CTL PUSH BC LD B,4 ;Bit 2, CTL JR IOBGN @KEY CALL @KBD ;Scan the keyboard RET Z ;Ret if key available OR A ;Return if error JR Z,@KEY RET @JCL LD DE,JCLCB$ ;JCL file FCB JR @GET @KBD LD DE,KIDCB$ ;Keyboard DCB @GET PUSH BC LD B,1 ;Bit 0, GET JR IOBGN @PRT LD DE,PRDCB$ ;Printer DCB JR @PUT @DSP LD DE,DODCB$ ;Video DCB @PUT PUSH BC LD B,2 ;Bit 1, PUT IOBGN PUSH IX ;Save the registers PUSH HL PUSH DE ;Xfer DCB to IX POP IX PUSH DE LD C,A ;Xfer the I/O char LD HL,@RSTREG ;Restore register routine LD A,(LBANK$) ;If bank 0 is not OR A ; resident, need to JR Z,$?0 ; get it resident! ; ; Some other bank is resident - invoke bank 0 ; PUSH BC ;Save reg again XOR A ;Prepare for bank-0 LD B,A LD C,A CALL @BANK ;Invoke bank-0 LD H,B ;Get old bank data LD L,C ; into reg HL POP BC ;Rcvr BC PUSH HL ;Bank data to stack LD HL,RSTBNK ;Set return address $?0 PUSH HL ; to restore registers LD A,(DE) ;P/u DCB type byte OR A RET Z ;Back if nothing CP 8 ;Ck on GET/PUT/CTL JR NC,@CHNIO ;Branch if special LD L,(IX+1) ; else p/u the vector LD H,(IX+2) $?1 LD A,B ;Xfer I/O code CP 2 ;Set flags state JP (HL) RSTBNK POP BC ;Get old bank data PUSH AF ;Can't affect AF LD A,C ;Request to A CALL @BANK ;Bring back original bank POP AF @RSTREG POP DE ;Restore regs POP HL POP IX POP BC RET ; $?2 PUSH HL POP IX @CHNIO LD L,(IX+1) ;P/u vector address LD H,(IX+2) $?3 LD A,(IX+0) ;P/u the DCB type OR A ;File Control Block? JP M,@BYTEIO BIT 3,A ;Test NIL bit 2nd JR NZ,$?5 BIT 4,A ;Routed? JR NZ,$?2 ;Go get routed DCB BIT 5,A ;If not linked, then JR Z,$?1 ; must be filtered PUSH HL ;Point to the link DCB POP IX LD (IX+3),B ;Save the direction PUSH IX CALL @CHNIO ;I/O to 1st device POP IX LD B,(IX+3) ;P/u the direction JR NZ,$?6 ;Go on NZ flag ; ; Z-flag on return - check input/output ; BIT 0,B ;If input & got char, $?4 LD L,(IX+4) ; p/u the linked DCB LD H,(IX+5) JR Z,$?2 $?5 CP A RET ; ; 1st link got NZ condition - if input, get link ; $?6 BIT 0,B ;Was it input/output? JR Z,$?7 ;Output is error OR A ;If A=0, then no input JR Z,$?4 $?7 OR A RET