SUBTTL READIO - I/O OPERATIONS PAGE + PUBLIC GETLIN GETLIN PROC MOV AX,CX ; (A0) AX HAS NUMBER OF ARGS TO READ PUSH BX MOV SCRHLD,1 ; (7n) HOLD SCRIPTING PUSH SI MOV CL,ES:[SI] MOV BX,OFFSET INBUF MOV BYTE PTR [BX],CL CMP CL,MAXLIN ; (7r) DON'T EXCEED BUFFER LENGTH JBE GTLN0 ; (7r) FIX IF ABOVE MOV BYTE PTR [BX],MAXLIN ; (7r) WITH OUR NEW MAXIMUM GTLN0: MOV DX,BX CMP AX,2 ; (A0) TIME OUT VERSION? JBE GTLNA ; (A0) TWO TABLES, GET NORMALLY MOV BX,OFFSET ARGBLK ; (A0) GET ADDR OF ARGBLK MOV AX,[BX+4] ; (A0) GET THE DELAY COUNT MOV BX,[BX+6] ; (A0) AND THE TIMEOUT FUNCTION PUSH SI ; (A0) SI IS GETTING WRECKED??? CALL LININP ; (A0) CALL TIMEOUT INPUT ROUTINE POP SI ; (A0) SO I PRESERVED IT JMP GTLNB ; (A0) SKIP NORMAL CALL ;GTLNA: MOV AH,CRDLIN ; INT 21H GTLNA: CALL RDLIN ;(A9) GTLNB: TEST SCROLL,1 ;(7) WHAT KIND OF SCROLLING JNZ GTLN1 MOV AH,SCROLLUP ;(7) USE A VIDEO BIOS SCROLL MOV AL,1 ;(7) ONLY 1 LINE MOV CX,TOPLIN ;(7) ALWAYS FREEZE TOP LINE MOV DH,SLPP ;(7) GET SCREEN LENGTH MOV DL,SCPL ;(7) GET THE WIDTH OF THE SCREEN DEC DL ; (7v) COORDINATES ARE ZERO BASED MOV BH,SCRATR ;(7) GET THE SCREEN ATTRIBUTE INT 10H ;(7) CALL THE VIDEO JMP GTLN2 ;(7) SKIP LINE FEED OUTPUT GTLN1: MOV AH,CCONIO MOV DL,10 INT 21H GTLN2: POP DX MOV BX,OFFSET INBUF MOV CL,BYTE PTR [BX+1] SUB CH,CH INC BX CMP CL,0 JE GETLEM GETLLP: INC SI INC BX MOV AL,BYTE PTR [BX] CMP AL,"A" JL GETLLC CMP AL,"Z" JG GETLLC ADD AL,32 GETLLC: MOV ES:[SI],AL LOOP GETLLP GETLEM: INC SI SUB AL,AL MOV ES:[SI],AL MOV SCRHLD,0 ; (7n) TURN OFF SCRIPT HOLD POP BX RET GETLIN ENDP PUBLIC PRTOUT PRTOUT PROC PUSH AX PUSH BX PUSH CX PUSH DX ; (7) SAVE THIS, USING STD PRT TEST WORD PTR ES:[PFLAGS],SCRPTBT ; (A17) SCRIPTING ON? JZ POUT2 ; (A17) NOPE TEST CMDLIN,16 ; (7n) DO WE WANT IBM PRINTER JZ POUT1 ; (7n) GUESS NOT POUT0: MOV AH,0 ; (7) FUNCTION TO PRINT MOV DX,0 ; (7) TO THE FIRST PRINTER INT 17H ; (7) TRY IT TEST AH,RDYBIT ; (7) TIME OUT? JZ POUT2 ; (7) WORKED, RETURN CALL PRNRDY ; (7) JC POUT2 JMP POUT0 ; (7) RETRY POUT1: MOV DL,AL ; (7n) GET CHARACTER TO PRINT MOV AH,CPROUT ; (7n) PRINT IT INT 21H POUT2: POP DX ; (7n) FORGET THIS AND BREAK... POP CX POP BX POP AX RET PRTOUT ENDP PUBLIC PRNRDY PRNRDY PROC OR WORD PTR ES:[PFLAGS],REFRESH ;(E0) REFRESH THE STATUS LINE PUSH AX MOV SCRHLD,1 ; (7n) HOLD OFF SCRIPTING PRINT PRNNRDY ; (7) ASK USER ABOUT ACTION RDY1: CALL MCHRI ; (7) GET A RESPONSE CALL MTTYO ; (7u) ECHO THE CHARACTER AND AL,5FH ; (7) UPPPER CASIFY CMP AL,'A' ; (7) SHOULD WE ABORT JNZ RDY2 ; (7) ATTEMPTING RETRY MOV SCRFLG,0 ; (7) TURN OFF SCRIPTING ; (A10) COMMENTED OUT LINE ; AND ES:[PFLAGS],SCRMSK ; (7) AND IN THE MODE WORD MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING STC ; (7) SET CARRY FOR NO RETRY PUSHF ; (7) SAVE THESE JMP RDY3 ; (7) CR LF ON EXIT RDY2: CMP AL,'R' ; (7) RETRY??? JNZ RDY1 ; (7) WRONG CHARACTER CLC ; (7) CLEAR CARRY FOR RETRY PUSHF ; (7) SAVE FLAGS RDY3: CALL MCRLF ; (7) DO A MOV SCRHLD,0 ; (7n) TURN OFF BAN ON SCRIPTING POPF ; (7) RESTORE FLAGS AND POP AX ; (7) CHARACTER TO PRINT RET PRNRDY ENDP SCRCHK PROC PUSH AX PUSH BX PUSH DX TEST SCRFLG,1 ; (A11) IS SCRIPTING ENABLED? JNZ SCR0L$ ; (7x) ....YES, CONTINUE JMP SCREX$ ; (A11)....NO ; MOV SCRFLG,1 ; (7n) TURN ON SCRIPT FLAG ; CMP SCROLL,0 ; (7) SHOULD WE BE DOING THIS? ; JNZ SCR0L$ ; (7) NOPE... ; TEST CMDLIN,16 ; (7n) DID WE REALLY REQUEST IBM ; JZ SCR0L$ ;SCR_1$: MOV DX,0 ; (7) TRY TO INIT THE PRINTER ; MOV AH,1 ; INT 17H ; (7) SO THAT WE WILL TIME OUT FAST ; TEST AH,PRTMSK ; (7) TEST FOR TIME OUT ; JZ SCR0L$ ; (7) NO PROBLEM, WE'RE FINE ; CALL PRNRDY ; (7) INFORM USER OF PROBLEM ; JNC SCR_1$ ; JMP SCRNN$ ; (7) TURN OFF SCRIPTING SCR0L$: SUB CX,CX MOV BP,DX INC BP SCR1L$: MOV AL,ES:[BP] INC BP CMP BP,SI JLE SCR2L$ CALL PRTCRL JMP SCREX$ SCR2L$: CALL PRTOUT INC CX CMP CL,SCPL JNE SCR1L$ CALL PRTCRL JC SCREX$ SUB CX,CX JMP SCR1L$ SCRNN$: MOV SCRFLG,0 SCREX$: POP DX POP BX POP AX RET SCRCHK ENDP PUBLIC PRTCRL PRTCRL PROC TEST WORD PTR ES:[PFLAGS],SCRPTBT ;(A18) DON'T SCRIPT READ JNZ PRTC1 RET PRTC1: MOV AL,13 ;FINISH UP WITH CRLF CALL PRTOUT MOV AL,10 CALL PRTOUT ; OR WORD PTR ES:[PFLAGS],REFRESH ; (A17) SET THE REFRESH BIT RET PRTCRL ENDP ;READ (A LINE OF INPUT & PARSE IT, LINE BUF IN ES:AX, ;RETURN BUF IN ES:BX) PUBLIC OPREAD,ORD1$,ORDNS$,ORD8$,ORD9$,ORD10$,ORD1A$,ORD11$,ORD12$ ; PUBLIC ORD13$,ORD14$,ORD15$,ORD16$,ORD17$,ORD18$,ORD19$,ORD20$ ; PUBLIC ORD21$,ORD22$,ORD23$ OPREAD PROC NOP ; (A0) GET ARGS IN ARGBLK MOV CX,AX ; (A0) GET # OF ARGS MOV BX,OFFSET ARGBLK MOV AX,[BX] ; (A0) GET FIRST TWO ARGS INTO AX & BX MOV BX,[BX+2] PUSH AX ;SAVE LINE BUF MOV BP,CHRPTR ;NEXT CHARACTER POSITION MOV BYTE PTR DS:[BP],80H ;(6)DON'T END OUTPUT, IF ANY, WITH CRLF ORD1$: PRINT OUTBUF ;FORCE OUT ANY QUEUED TEXT MOV CHRPTR,OFFSET OUTBUF ;RESET CHARACTER POINTER POP SI ;INPUT BUFFER POINTER MOV MORLIN,0 ;RE-INITIALIZE MORE COUNT FROM HERE MOV CHRCNT,BUFLEN ; (A15) RE-INITIALIZE THE CHAR COUNTER CALL GETLIN ;GET SOME CHARACTERS CALL SCRCHK ;PRINT THE BUFFER IF SCRIPTING IS ON ORDNS$: PUSH DI MOV RDBOS,DX ;INITIALIZE RDBOS MOV RDEOS,SI ;AND RDEOS MOV RDRET,BX ;STORE RET POINTER MOV RDNWDS,0 ;NO WORDS SO FAR INC DX ;SKIP LENGTH BYTE MOV DI,BX ;THIS WILL BE WORD ENTRY POINTER INC DI ;SKIP MAX WORDS & NWORDS BYTES INC DI ORD8$: MOV CX,OFFSET RDWSTR;HERE FOR NEXT WORD, POINT TO WORD STRING MOV BX,DX ;AND SAVE BEGINNING OF WORD POINTER ORD9$: CMP DX,RDEOS ;END OF STRING? JNE ORD10$ ;NO CMP CX,OFFSET RDWSTR;YES, WAS A WORD FOUND? JNE ORD15$ ;YES, WE STILL HAVE TO LOOKUP WORD JMP ORD23$ ;NO, WE'RE DONE ORD10$: MOV BP,DX ;GET NEXT CHARACTER FROM BUFFER MOV AL,ES:[BP] CMP AL,"A" JL ORD1A$ CMP AL,"Z" JG ORD1A$ ADD AL,32 ;LOWERCASIFY ALPHABETICS ORD1A$: INC DX MOV SI,OFFSET RBRKS ;LIST OF READ BREAK CHARACTERS ORD11$: INC SI CMP AL,[SI-1] ;SEARCH LIST FOR THIS ONE JE ORD12$ ;FOUND IT CMP BYTE PTR [SI],0 ;END OF LIST? JNE ORD11$ ;NO, CONTINUE SEARCH CMP CX,OFFSET RDWSTR[9] ;YES, NOT A BREAK, WORD STRING FULL? JE ORD9$ ;YES, LOOP UNTIL END OF WORD MOV BP,CX ;NO, TACK THIS CHARACTER ONTO STRING MOV DS:[BP],AL INC CX JMP ORD9$ ;AND LOOP ORD12$: CMP CX,OFFSET RDWSTR;WORD READ BEFORE THIS BREAK? JNE ORD14$ ;YES CMP SI,ESIBKS ;NO, BUT IS IT A SELF-INSERTING BREAK? JBE ORD13$ ;YES INC BX ;NO, UPDATE BEGINNING OF WORD TO SKIP BREAK JMP ORD9$ ;AND RETURN TO LOOP TO FIND A WORD ORD13$: MOV BP,CX ;STORE THE BREAK IN WORD STRING MOV DS:[BP],AL INC CX JMP ORD15$ ;AND GO FOR THE WORD ORD14$: DEC DX ;UNREAD TERMINATING BREAK IN CASE IT WAS SI ORD15$: INC RDNWDS ;INCREMENT FOUND WORD COUNT MOV BP,BX ;GREATER THAN MAX ALLOWED? MOV BX,RDRET MOV BL,ES:[BX] CMP BL,59 ; (7w) GAME FIX JBE ORD15A ; (7w) FIX NUMBER OF TOKENS ALLOWED MOV BL,59 ; (7w) OTHERWISE WE OVERRUN A TABLE ORD15A: CMP RDNWDS,BL MOV BX,BP JLE ORD16$ ;NO PRINT ERR2 ;YES, INFORM LOSER MOV AX,BX ;BEGINNING OF THIS WORD MOV BP,RDEOS ;SAVE BYTE AFTER EOS MOV BL,ES:[BP] MOV BYTE PTR ES:[BP],0 ; ZERO IT TO MAKE STRING ASCIZ PUSH BX ; (7w) SAVE THIS ADDRESS MOV BX,DS ; (7w) FIGURE WHERE STRING IS IN DS NEG BX ; (7w) SUBTRACT DS FROM ES ADD BX,GAMESEG ; (7w) BX HAS PARAGRAPHS OF DIFFERENCE MOV CL,4 ; (7w) CONVERT TO AN OFFSET SHL BX,CL ; (7w) TO ADD IN WITH AX ADD AX,BX ; (7w) NOW DS:AX SHOULD EQUAL PREV ES:AX POP BX ; (7w) RESTORE BX CALL MPRNT ;PRINT IT MOV ES:[BP],BL ; AND RESTORE OLD BYTE DEC RDNWDS ;REMEMBER THAT WE FLUSHED THIS WORD JMP ORD23$ ;AND WE'RE DONE ORD16$: MOV AX,BX ;CALCULATE NUMBER OF CHARACTERS IN WORD NEG AX ADD AX,DX MOV ES:[DI+2],AL ;(6)SAVE THE NUMBER IN RET TABLE SUB BX,RDBOS ;BYTE OFFSET FOR BEGINNING OF WORD MOV ES:[DI+3],BL ;(6)STORE IT, TOO MOV BP,CX ;MAKE WORD STRING ASCIZ MOV BYTE PTR DS:[BP],0 ;(6) REMOVED SEG OVERRIDE (DS) MOV AX,OFFSET RDWSTR;POINT TO IT CALL ZWORD ;AND CONVERT TO (2-WORD) ZWORD MOV ZTHIRD,CX ; (A0) SAVE THIRD WORD PUSH DX ;SAVE CHAR & WORD ENTRY POINTERS PUSH DI MOV DI,AX ;FIRST ZWORD WORD MOV SI,VWORDS ;NUMBER OF VOCABULARY WORDS MOV AX,SI DEC AX ;WE WANT TO POINT TO LAST WORD MUL VWLEN ;MULTIPLY BY WORD LENGTH IN BYTES ADD AX,VOCBEG ;ADD POINTER TO BEGINNING TO FIND LAST WORD MOV CX,AX ;POINTER TO LAST WORD MOV DX,DI ;FIRST ZWORD WORD MOV DI,BX ;SECOND ZWORD WORD MOV BX,VWLEN ;CALCULATE INITIAL OFFSET FOR BINARY SEARCH SAR SI,1 ORD17$: SAL BX,1 SAR SI,1 CMP SI,0 JNE ORD17$ MOV SI,VOCBEG ;BEGINNING OF WORD TABLE ADD SI,BX ;ADD CURRENT OFFSET(HALF OF POWER-OF-2 TABLE) PUSH AX ;SAVE MOV AX,VWLEN ;AVOID FENCEPOST BUG FOR EXACT POWER-OF-2 TBL SUB SI,AX POP AX ;RESTORE ORD18$: SAR BX,1 ;NEXT OFFSET WILL BE HALF OF PREVIOUS ONE GTAWRD A,[SI] ;GET FIRST HALF OF CURRENT ZWORD CMP DX,AX ;COMPARE DESIRED ONE TO IT JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN MOV BP,SI ;SAME, GET SECOND HALF ADD BP,2 ; (A0) LOOK AT SECOND WORD GTAWRD A,[BP] CMP DI,AX ;COMPARE DESIRED WORD WITH IT JA ORD19$ ;GREATER, WE'LL HAVE TO MOVE UP JB ORD20$ ;LESS, WE'LL HAVE TO MOVE DOWN MOV BP,SI ; (A0) SAME, GET SECOND HALF ADD BP,4 ; (A0) LOOK AT THIRD WORD GTAWRD A,[BP] ; (A0) CMP ZTHIRD,AX ; (A0) COMPARE DESIRED WORD WITH IT JA ORD19$ ; (A0) GREATER, WE'LL HAVE TO MOVE UP JB ORD20$ ; (A0) LESS, WE'LL HAVE TO MOVE DOWN JMP ORD22$ ;SAME, WE'VE FOUND IT, RETURN IT ORD19$: ADD SI,BX ;TO MOVE UP, ADD CURRENT OFFSET jc ORD24$ ; overflowed a segment, set back to end CMP SI,CX ;HAVE WE MOVED PAST END OF TABLE? JBE ORD21$ ;NO ORD24$: MOV SI,CX ;YES, POINT TO END OF TABLE INSTEAD JMP ORD21$ ORD20$: SUB SI,BX ;TO MOVE DOWN, SIMPLY SUBTRACT OFFSET ORD21$: CMP BX,VWLEN ;IS OFFSET RESOLUTION BELOW ONE WORD? JGE ORD18$ ;NO, CONTINUE LOOP SUB SI,SI ;YES, WORD NOT FOUND, RETURN ZERO ORD22$: POP DI ;RESTORE WORD ENTRY POINTER MOV DX,SI ;POINTER TO WORD FOUND XCHG DH,DL MOV ES:[DI],DX ;(6) STORE IT POP DX ;RESTORE CHAR POINTER ADD DI,4 ;UPDATE POINTER FOR NEXT WORD ENTRY JMP ORD8$ ;GO FOR IT ORD23$: INC RDRET ;DONE, STORE NUMBER OF WORDS FOUND MOV BP,RDRET MOVM ES:[BP],RDNWDS,DL ; REMOVED ES OVERRIDE POP DI ;RESTORE USER STACK POINTER RET ;AND RETURN OPREAD ENDP PUBLIC OPBFOUT OPBFOUT PROC CMP AX,0 ; (A0) WHAT DO WE WANT? JNZ BUFFED ; (A0) TURN OFF BUFFERED INPUT MOV BUFBIT,0 ; (A0) SET FLAG PUSH BX MOV BX,CHRPTR ; (A0) LOCATION FOR NEXT CHAR MOV BYTE PTR [BX],80H ; (A0) INDICATE END OF STRING PRINT OUTBUF ; (A0) FLUSH THE BUFFER MOV BX,OFFSET OUTBUF ; (A0) GET BUFFER ADDR MOV CHRPTR,BX ; (A0) RESET THE CHRPTR POP BX ; (A0) RESTORE BX RET BUFFED: MOV BUFBIT,1 ; (A0) TURN BUFFERING BACK ON RET OPBFOUT ENDP PUBLIC OPDIRIN OPDIRIN PROC RET OPDIRIN ENDP ; ; SELECT OR DESELECT A VIRTUAL OUTPUT DEVICE ; PUBLIC OPDIROU OPDIROU PROC OR AL,AL ; (A10) ENABLE OR DISABLE A DEVICE JNS ODIR0 ; (A10) IF (+) IT'S ENABLE JMP ODIR5 ; (A10) IF (-) IT'S DISABLE ; {CASE} DEVICE ENABLE HANDLER ODIR0: CMP AL,1 ; (A10) IS IT THE SCREEN? JNE ODIR1 ; (A10) NOPE ; {SUBCASE} SCREEN HANDLER MOV VIDFLG,1 ; (A10) TURN SCREEN ON RET ODIR1: CMP AL,2 ; (A10) IS IT THE SCRIPT DEVICE? JNE ODIR2 ; (A10) NOPE ; {SUBCASE} SCRIPT HANDLER PUSH AX PUSH BX PUSH DX TEST SCRFLG,1 ; (A11) IS SCRIPTING ALREADY ENABLED? JNZ ODIR1B ; (A11) ....YES ; OR WORD PTR ES:[PFLAGS],SCRPTBT ;(A18) TURN ON SCRIPT FOR HI MOV SCRFLG,1 ; (A18) TURN ON ZIP FLAG TEST CMDLIN,16 ; (A11) DID WE REALLY REQUEST IBM? JZ ODIR1B ; (A11) ....YES ; INITIALIZE PRINTER ODIR1A: MOV DX,0 ; TRY TO INIT THE PRINTER MOV AH,1 INT 17H ; SO THAT WE WILL TIME OUT FAST TEST AH,PRTMSK ; TEST FOR TIME OUT JZ ODIR1B ; NO PROBLEM, WE'RE FINE CALL PRNRDY ; INFORM USER OF PROBLEM JNC ODIR1A ; THE PRINTER WOULDN'T INITIALIZE XOR AH,AH ; (A13) DISABLE SCRIPTING MOV SCRFLG,AH ; (A13) OR AH,STSBIT ; (A13) TURN ON STATUS LINE REFRESH BIT XOR AL,AL ; (A13) XCHG AH,AL ; (A18) BYTE SWAP MOV WORD PTR ES:[PFLAGS],AX ; (A13) LET HIGH LEVEL KNOW ODIR1B: POP DX POP BX POP AX RET ODIR2: CMP AL,3 ; (A10) IS IT THE TABLE DEVICE? JNE ODIR3 ; (A10) NOPE ; {SUBCASE} TABLE HANDLER MOV AL,BUFBIT ; (A0) GET STATE OF BUFBIT MOV PREVBUF,AL ; (A0) AND SAVE IT FOR LATER ; (B0) Dirout should not flush the buffer ; MOV AX,0 ; (A0) USE TO CALL BUFOUT ; CALL OPBFOUT ; (A0) TURN OFF BUFBIT AND FLUSH MOV BUFBIT,0 ; (B0) TURN OFF BUFBIT MOV RDIR,1 ; (A0) STORE REDIRECTION FLAG MOV RTABLE,BX ; (A0) ZEROTH ELEMENT OF TABLE MOV RDIROUT,0 ; (A0) ZERO THE NUMBER OF BYTES READ ADD BX,2 ; (A0) THIS IS TABLE+2 MOV RTABLE2,BX ; (A0) AND TABLE LOCATION (IF INT IS <> 1) RET ODIR3: CMP AL,4 ; (A10) IS IT A FILE? JNE ODIR4 ; (A10) NOPE, DON'T HANDLE IT ; {SUBCASE} FILE HANDLER ; NOT IMPLIMENTED ODIR4: RET ; ; {CASE} DEVICE DISABLE HANDLER ODIR5: CMP AL,0FFH ; (A10) IS IT THE SCREEN? JNE ODIR6 ; (A10) NOPE ; {SUBCASE} SCREEN HANDLER MOV VIDFLG,0 ; (A10) TURN SCREEN OFF RET ODIR6: CMP AL,0FEH ; (A10) IS IT THE SCRIPT DEVICE? JNE ODIR7 ; (A10) NOPE ; {SUBCASE} SCRIPT HANDLER MOV SCRFLG,0 ; (A18) TURN OFF SCRIPTING AND WORD PTR ES:[PFLAGS],SCRMSK ; XOR AH,AH ; (A13) DISABLE SCRIPTING ; MOV SCRFLG,AH ; (A13) ; OR AH,STSBIT ; (A13) TURN ON STATUS LINE REFRESH T ; XOR AL,AL ; (A13) ; MOV ES:[PFLAGS],AX ; (A13) LET HIGH LEVEL KNOW RET ODIR7: CMP AL,0FDH ; (A10) IS IT THE TABLE DEVICE? JNE ODIR8 ; (A10) NOPE ; {SUBCASE} TABLE HANDLER CMP RDIR,0 ; (C0) IF ALREADY OFF JE OUT7 ; (C0) LEAVE AS IS MOV AL,PREVBUF ; (A0) GET PREVIOUS STATE OF BUFFER MOV BUFBIT,AL ; (A0) AND RESTORE THAT STATE MOV RDIR,0 ; (A0) AND RESTORE REDIRECTION TO SCREEN MOV AX,RDIROUT ; (A0) GET NUMBER OF CHARS WRITTEN MOV BX,RTABLE ; (A0) GET ADDR OF ZEROTH ELEMENT PTAWRD ES:[BX],A ; (A0) PUT THE WORD INTO THE TABLE MOV BX,RTABLE2 ; (A18) GET FIRST ELEMENT MOV BYTE PTR ES:[BX],0 ; (A18) DROP IN A NULL OUT7: RET ; (C0) ODIR8: CMP AL,0FCH ; (A10) IS IT A FILE? JNE ODIR9 ; (A10) NOPE, DON'T HANDLE IT ; {SUBCASE} FILE HANDLER ; NOT IMPLIMENTED ODIR9: RET OPDIROU ENDP SUBTTL OPINPUT PAGE ; ------- ; OPINPUT ; ------- ; ; PURPOSE: THIS ROUTINE IS USED TO PERFORM A TIMED CHARACTER REQUEST ; ; IF [ARG1] = 1, THEN THIS IS A TIMED INPUT KEYBOARD REQUEST ; AND THE TIME LIMIT IS PROVIDED IN [ARG2]. ; ; IF A KEY IS DETECTED BEFORE TIMEOUT, THEN WE RETURN THE ; CHARACTER VIA PUTBYTE. ; ;IF A FUNCTION IS PROVIDED [ARG3] IT IS INTERNALLY CALLED AFTER ; TIMEOUT. IF THE VALUE RETURNED BY THE FUNCTION = 0, THEN ; WE KEEP LOOPING. ; ; IF A TIMEOUT OCCURS AND WE HAVE NO FUNCTION TO CALL, OR THE ; VALUE RETURNED FROM THE INTERNAL FUNCTION CALL NE. 0, THEN ; WE RETURN A "0" VIA RET0. ; ; INPUTS: [NARGS],[ARG1],[ARG2]opt,[ARG3]opt ; ; OUTPUTS: EITHER A ASCII CHAR RETURNED VIA PUTBYTE ; OR "0" VIA RET0 ; ; REGISTERS DESTROYED: AX,DX ; ; EXTERNAL REFERENCES: INCALL ; PUBLIC OPINPUT,ZTIMLP,NOZFCN,ZIN OPINPUT PROC NOP ; (A0) GET ARGS IN ARGBLK PUSH BX ;(A0) SAVE REGISTERS PUSH CX MOV MORLIN,0 ; (A8) RESET THIS VAR MOV CHRCNT,BUFLEN ; (A15) RESET INPUT CHAR COUNT MOV BX,ARGBLK ; (A0) GET ARG1 CMP BX,1 ; (A0) KEYBOARD? JNE NOZFCN ;....NO INVALID REQUEST CMP AX,3 ;(A0) IS THIS A TIMED INPUT JB ZIN ;(A0) ....NO ; ; TIMED INPUT ; ZTIMLP: MOV AX,ARGBLK[2] ; (A0) GET DELAY COUNT IDIV RADIX MOV DLYCNT,AX MOV BX,ARGBLK[4] ; (A0) GET FUNCTION ADDR CALL TIMLP1 ; (A0) GET A CHAR [+ TIMEOUT] JNC ZIN ; (A0) GET THE CHAR READY TEST AL,AL ; (A0) WHAT DID INCALL RETURN JZ ZIN ; (A0) A ZERO MEANS CONTINUE ANYWAY NOZFCN: POP CX ; (A0) RESTORE REGISTERS POP BX MOV AX,0 ; (A0) RETURN A NULL JMP BYTVAL ; (A0) IS THIS RIGHT? ; GET A CHARACTER FROM THE KEYBOARD ZIN: CALL GETKEY POP CX ; (A0) RESTORE REGISTERS POP BX JMP BYTVAL ; (A0) RETURN THE BYTE OPINPUT ENDP SUBTTL LINE INPUT FOR GETLIN PAGE ; ------ ; LININP ; ------ ; ; PURPOSE: THIS ROUTINE IS USED BY GETLIN TO FETCH A LINE OF INPUT ; FROM THE KEYBOARD AND PLACE IT IN THE INPUT BUFFER (INBUFF) ; IN ADDITION, IT HAS THE RESPONSIBILITY TO TACKLE TIMED LINE ; INPUT REQUESTS. ; ; {CASE TIMED INPUT} ; IF NARGS GE. 3, THEN THIS IS A TIMED INPUT ; IF A KEY IS DETECTED BEFORE TIMEOUT, THEN WE DROP INTO ; LINE INPUT PROCESSING. ; ; IF NARGS EQ. 4, THEN UPON TIMEOUT THE FUNCTION [ARG4] IS ; INTERNALLY CALLED. IF THE VALUE RETURNED BY THE FUNCTION = 0, ; THEN WE KEEP LOOPING. ; ;IF NARGS NE. 4 OR THE VALUE RETURNED FROM THE INTERNAL FUNCTION ; CALL NE. 0, THEN WE RETURN A "FALSE" IN [AX] TO {GETLIN}. ; ; {CASE LINE INPUT PROCESSING} ; GET A LINE OF INPUT AND RETURN A "TRUE" IN [AX] TO {GETLIN}. ; ; INPUTS: [NARGS],[ARG3]opt,[AGR4]opt ; ; OUTPUTS: DX = ADDRESS OF INBUF, AX = TRUE OR FALSE (see above) ; ; REGISTERS DESTROYED: AX,DX ; ; EXTERNAL REFERENCES: INCALL,CHROUT ; PUBLIC LININP LININP PROC PUSH BX ; (A0) SAVE FCN ADDRESS MOV BX,OFFSET INBUF ; (A0) POINT AT INPUT BUFFER MOV BYTE PTR [BX],MAXLIN ; (A0) MAXIMUM NUMBER OF CHARACTERS MOV BYTE PTR [BX+1],0 ; (A0) RESET THE CHARACTER COUNT ; ; TIMED INPUT ; TIMELP: IDIV RADIX MOV DLYCNT,AX ; (A0) AX HAS DELAY COUNT POP BX ; (A0) RESTORE FCN ADDRESS CALL TIMLP1 ; (A0) SEE IF CHAR IS READY JNC ENTIN ; (A0) YES, NO TIMEOUT, GET IT TEST AL,AL ; (A0) SEE WHAT INCALL RETURNED JZ ENTIN ; (A0) CONTINUE NORMALLY MOV BX,OFFSET INBUF+2 ;POINT THE START OF THE ACTUAL BUFFER ADD BX,CX ;(A0) POINT AT THE CHARACTER SLOT MOV [BX],AL ;(A0) SAVE THE EOL CALL MTTYO ;(A0) AND OUTPUT IT TO THE CONSOLE RET ENTIN: JMP INLOOP LININP ENDP ; ; GET A LINE OF INPUT ; PUBLIC INLOOP INLOOP PROC CALL GETKEY CMP AL,14 ;(A0) CLEAR OFF ARROWS JE INBAD CMP AL,7 JE INBAD CMP AL,EOL ;(A0) CARRIAGE RETURN? JE ENDLIN ;(A0) ....YES. WE'RE DONE CMP AL,7FH ;(A0) REGULAR DELETE JE BACKUP ;(A0) ....YES CMP AL,BACKSP ;(A0) BACKSPACE (DELETE)? JE BACKUP ;(A0) ....YES CMP AL,11 ;(A0) LEFT ARROW (DELETE)? JE BACKUP ;(A0) ....YES ; PUT THE CHARACTER IN THE INPUT BUFFER, IF POSSIBLE SUB CH,CH MOV CL,INBUF+1 ;(A0) GET NUMBER OF CHARACTERS ALREADY ;(A0) IN THE BUFFER ; CMP CL,INBUF ;(A0) IS THE BUFFER FULL? MOV BL,INBUF ;(A9) GET THE MAXIMUM NO. OF CHARACTERS DEC BL ;(A9) ENDS ALL INPUT - LEAVE ROOM DEC BL ;(B0) bl/Length, not ptr CMP CL,BL ;(A9) IS THE BUFFER FULL? JE NOMO ;(A0) ....YES ; THERE'S ROOM IN THE BUFFER INC BYTE PTR INBUF+1 ;(A0) UPDATE NUMBER OF CHARACTERS ;(A0) IN THE BUFFER MOV BX,OFFSET INBUF+2 ;POINT THE START OF THE ACTUAL BUFFER ADD BX,CX ;(A0) POINT AT THE CHARACTER SLOT MOV [BX],AL ;(A0) SAVE THE CHARACTER ;DISPLAY THE CHARACTER ON THE SCREEN SHOWIT: CALL MTTYO ;(A0) DISPLAY IT JMP INLOOP ;(A0) AND GET ANOTHER ; ; LINE OVERFLOW ; NOMORE: CALL GETKEY ;(A0) GET A KEY CMP AL,EOL ;(A0) ? JE ENDLIN ;(A0) ....YES, WE'RE DONE CMP AL,7FH ;(A0) REGULAR DELETE JE BACKUP ;(A0) ....YES CMP AL,BACKSP ;(A0) BACKSPACE (DELETE)? JE BACKUP ;(A0) ....YES CMP AL,11 ;(A0) LEFT ARROW (DELETE)? JE BACKUP ;(A0) ....YES NOMO: CALL FEEP ;(A0) CAN' DO IT, SO COMPLAIN JMP NOMORE ;(A0) AND DON'T LET THEM OFF THE HOOK ; ; BACKUP (DELETE A CHARACTER) ; BACKUP: CMP BYTE PTR INBUF+1,0 ;(A0) CAN WE REALLY DELETE A CHARACTER? JE INBAD ;(A0) ....NO, WE HAVE NONE TO DELETE ; ACTUAL DELETE DEC BYTE PTR INBUF+1 ;(A0) ONE LESS IN THE BUFFER MOV AL,BACKSP ;(A0) BACKUP A CHARACTER POSITION CALL MTTYO ;(A0) ON THE SCREEN MOV AL,SPACE ;(A0) ERASE CHARACTER CALL MTTYO ;(A0) BY REPLACING IT WITH A SPACE MOV AL,BACKSP ;(A0) BACKUP A CHARACTER POSITION JMP SHOWIT ;(A0) ON THE SCREEN AND LOOP INBAD: CALL FEEP ;(A0) CAN' DO IT, SO COMPLAIN JMP INLOOP ;(A0) AND DON'T LET THEM OFF THE HOOK ; ; LINE TERMINATED BY A EOL ; ENDLIN: MOV BX,OFFSET INBUF+2 ;POINT THE START OF THE ACTUAL BUFFER SUB CX,CX MOV CL,INBUF+1 ;(B1) Point at 1st unused byte ADD BX,CX ;(A0) POINT AT THE CHARACTER SLOT ; INC BX ;(A9)(b1 2 entry pts w/different conditions;fixed cx) MOV [BX],AL ;(A0) SAVE THE EOL CALL MTTYO ;(A0) AND OUTPUT IT TO THE CONSOLE LINRET: RET INLOOP ENDP ; ---------------------- ; FETCH AN ASCII KEYCODE ; ---------------------- ; ; PURPOSE: GETKEY WAITS FOR A KEY TO BE DEPRESSED ON THE CONSOLE. ; WHEN A KEY IS DEPRESSED, IT'S ASCII VALUE IS RETURNED ; FROM THE DOS FUNCTION.THE ASCII VALUE IS THEN PREPROCESSED ; SO THAT CERTAIN KEYS ARE TRANSLATED INTO EZIP ASCII VALUES ; ; OTHER KEYS ARE CONSIDERED ILLEGAL AND IF DETECTED CAUSE A ; BEEP SOUND TO BE HEARD, THE KEYPRESS IS IGNORED, AND THE ; ROUTINE CONTINUES TO WAIT FOR A VALID KEY. ; ; INPUTS: NONE ; ; OUTPUTS: [AL] = A 7-BIT ASCII CODE ; ; REGISTERS DESTROYED: ; AX,BX,CX ; ; EXTERNAL REFERENCES: FEEP ; PUBLIC GETKEY,GK0,GK1,GK2,GK3,GK4,KEYOK,CHKKEY GETKEY PROC GK0: MOV AH,CNOECHO ;(A0) WAIT FOR KEYPRESS, NO ECHO INT 21H ;(A0) MSDOS FUNCTION CALL AND AL,7FH ;(A0) 7-BIT ASCII ONLY ; EXTENDED SPECIAL FUNCTIONS CMP AL,0 ;(A0) IF AL=0,THIS IS AN EXTENDED KEY JNE CHKKEY ;(A0) THANK GOODNESS, IT ISN'T ; PROCESS EXTENDED KEYS ; DO A SECOND READ MOV AH,CNOECHO ;(A0) WAIT FOR KEYPRESS, NO ECHO INT 21H ;(A0) MSDOS FUNCTION CALL CMP AL,72 ;(A0) UP ARROW JNE GK1 MOV AL,14 JMP KEYOK GK1: CMP AL,75 ;(A0) LEFT ARROW JNE GK2 MOV AL,11 JMP KEYOK GK2: CMP AL,77 ;(A0) RIGHT ARROW JNE GK3 MOV AL,7 JMP KEYOK GK3: CMP AL,80 ;(A0) DOWN ARROW JNE GK4 MOV AL,13 JMP KEYOK GK4: CMP AL,83 ;(A0) DEL KEY JNE GK0 ;(A0) IT'S BAD, TRY AGAIN MOV AL,7FH JMP KEYOK ;(A9) ; ; WE'RE RECEIVED A NON-EXTENDED KEY ; SO, NATURALLY ENOUGH, WE'RE GOING TO RUN IT THROUGH ; AN ASCII FILTER TO REMOVE THOSE KEYS THAT WE DON'T ; (THROUGH NO FAULT OF THEIR OWN) LIKE. ; CHKKEY: CMP AL,08H ;(A9) BACKSPACE IS OK JE KEYOK ;(A9) CMP AL,0DH ;(A9) JE KEYOK ;(A9) CMP AL,20H ;(A9) AND SO ARE KEYS .GE SPACE JAE KEYOK ;(A9) JMP GK0 ;(A9) KEYOK: MOV IOCHAR,AL ; (LD1) HOLD A SEC ADC AX,RSEED1 ; (LD1) PLAY WITH RANDOM BYTES MOV RSEED1,AX ; (LD1) EACH TIME THRU HERE XOR RSEED2,AX ; (LD1) MOV AL,IOCHAR ; (LD1) THANKS FOR WAITING RET GETKEY ENDP ; POLL THE KEYBOARD FOR 1/nTH SEC ; NOTE: THIS ROUTINE DOES IT IN 0.11 SEC WITH A FAIR DEGREE ; OF PRECISION, INDEPENDENT OF SYSTEM CLOCK (AT+, PC, ETC.) TIMLP1 PROC PUSH DI TRESET: MOV DI,DLYCNT TIMIN: MOV AH,CTIME ;(A0) GET TIME FROM REAL TIME CLOCK INT 21H ;(A0) MSDOS FUNCTION CALL MOV CLKLOW,DX ;(A0) SAVE 1/100 SEC COUNT ; IS A KEY AVAILABLE TRY: MOV AH,CINSTAT ;(A0) CHECK STANDARD INPUT STATUS INT 21H ;(A0) MSDOS FUNCTION CALL OR AL,AL ;(A0) IS A CHARACTER AVAILABLE JZ TRY1 ;(A0) NO POP DI CLC ; (A0) CLEAR TO SIGNAL A CHAR RET ; NOKEY TRY1: MOV AH,CTIME ;(A0) GET TIME FROM REAL TIME CLOCK INT 21H ;(A0) MSDOS FUNCTION CALL MOV AX,DX ; (A0) SAVE IT SUB DX,CLKLOW ;(A0) IF EQUAL TO SAVED TIME CMP DX,100H JB TRY ;(A0) .1 SECS HASN'T EXPIRED YET NEG DX CMP DX,100H JB TRY MOV CLKLOW,AX ;(A0) SAVE 1/100 SEC COUNT DEC DI ;(A0) DECREMENT DELAY TIMER JNZ TIMIN ;(A0) IF TIME IS LEFT, TRY AGAIN ; TIME OUT, CHECK FOR A FUNCTION MOV AX,BX ;(A0) GET ORIGINAL BX (FCN) INTO AX CALL INCALL ;(A0) ....YES, CALL THE FUNCTION CMP AX,0 ; IF VALUE RETURNED=0 JNZ INFAIL ;(A0) THEN TRY AGAIN JMP TRESET INFAIL: POP DI ; (A0) RESTORE THIS ONE STC ; (A0) INDICATE A TIMEOUT RET ; (A0) RETURN WITH TIMEOUT RET IN AX TIMLP1 ENDP SUBTTL RDLIN PAGE ; ------ ; RDLIN ; ------ ; ; PURPOSE: THIS ROUTINE PROVIDES BUFFERED KEYBOARD INPUT ; ; ; NOTE: NORMALLY LINE INPUT IS PROVIDED BY USING DOS ; INT 21H FUNCTION CALLS WITH [AH]=0AH. BECAUSE WE ; WANT TO INTERCEPT AND IGNORE MANY POSSIBLE KEYS, THIS ; ROUTINE IS NECESSARY. ; ; ; INPUTS: [AH]=0AH, DS:DX ^ INPUT BUFFER. THE FIRST BYTE ; SPECIFIES THE NUMBER OF BYTES THE BUFFER CAN HOLD ; (MUST BE .NE 0). THE SECOND BYTE IS SET TO THE ; NUMBER OF CHARACTERS RECEIVED. ; ; OUTPUTS: THE INPUT BUFFER WILL CONTAIN A FILTERED ASCII STRING ; TERMINATED BY . ; ; REGISTERS DESTROYED: NONE? ; ; RDLIN PROC PUSH AX ;(A9) PUSH BX ;(A9) PUSH CX ;(A9) PUSH DX ;(A9) PUSH DX ;(A9) POP BX ;(A9) MOV BYTE PTR [BX+1],0 ;(A9) RESET THE CHARACTER COUNT CALL INLOOP ;(A9) POP DX ;(A9) POP CX ;(A9) POP BX ;(A9) POP AX ;(A9) RET RDLIN ENDP