PAGE 75,128 TITLE SUBRTNS - SUBROUTINES FOR CCBBS PAGE .XLIST INCLUDE CCBBS.DEF INCLUDE CCBBS.MAC .LIST ;----------------------------------------------- ;SYSTEM DATA SEGMENT ;----------------------------------------------- SYSDATA SEGMENT PARA PUBLIC 'DATA' EXTRN CALLRN:BYTE,KBDTSK:WORD EXTRN DEBUGF:BYTE,USERH:WORD,TIMEOUT:WORD EXTRN MSGINX1:WORD EXTRN CDTASK:WORD,MSGSEG:WORD EXTRN USRINXA:WORD,USRINXL:WORD DW HELPSPT-HELPFI HELPFI DB 'HELP' HELPSPT DB 'CCHELP.SPT',0 ;HELP SCRIPT FILE HELPSPX DB 'RBBSHELP.SPT',0 ;HELP SCRIPT FILE TSTFILN DB 'CCTEST.DAT',0 ;TEST FILE INPUT TSTFILH DW 0 ;TEST FILE HANDLE ;--------------------------------------------------------------------- ;EXTENDED ASCII TRANSLATE TABLE ;--------------------------------------------------------------------- XGXTAB DB 'CueaaaaCeeeiiiAA' DB 'EEEooouuyOUcLYPf' DB 'aiounNao?--//!<>' DB ' |{{{**{|*****' DB '*--}-+}}**==}=+=' DB '-=-****++** ' DB 'abgpSsmtPOOd ' DB '=+>< /=...-n2* ' ;--------------------------------------------------------------------- ;ANSI SEQUENCE JUMP TABLE ;--------------------------------------------------------------------- ANSICMD DB 'A' ;CURSOR UP DW ANCUP DB 'B' ;CURSOR DOWN DW ANCDN DB 'C' ;CURSOR FORWARD DW ANCFWD DB 'D' ;CURSOR BACK DW ANCBWD DB 'H' ;SET CURSOR POSITION DW ANSETC DB 'J' ;CLEAR SCREEN DW ANCLR DB 'K' ;ERASE EOL DW ANEEOL DB 'R' ;CURSOR POSITION REPORT DW ANNULL DB 'f' ;SET CURSOR POSITION DW ANSETC DB 'h' ;SET SCREEN MODE DW ANNULL DB 'l' ;RESET SCREEN MODE DW ANNULL DB 'm' ;SET GRAPHICS RENDITION DW ANSGR DB 'n' ;GET CURSOR POSITION DW ANNULL DB 'p' ;KEYBOARD REASSIGNMENT DW ANNULL DB 's' ;SAVE CURSOR POSITION DW ANNULL DB 'u' ;RESTORE CURSOR POSITION DW ANNULL DB 0 ;END OF TABLE ;--------------------------------------------------------------------- ;SET GRAPHICS RENDITION ENCODING TABLE ;--------------------------------------------------------------------- SGRTBL DB 0,0,7 ;RESET ATTRIBUTES DB 1,0FFH,8 ;BOLD ON DB 4,0F8H,1 ;UNDERSCORE ON DB 5,0FFH,80H ;BLINK ON DB 7,0F8H,70H ;REVERSE VIDEO ON DB 8,88H,0 ;NON-DISPLAY ON DB 30,0F8H,0 ;BLACK FOREGROUND DB 31,0F8H,4 ;RED FOREGROUND DB 32,0F8H,2 ;GREEN FOREGROUND DB 33,0F8H,6 ;YELLOW FOREGROUND DB 34,0F8H,1 ;BLUE FOREGROUND DB 35,0F8H,5 ;MAGENTA FOREGROUND DB 36,0F8H,3 ;CYAN FOREGROUND DB 37,0F8H,7 ;WHITE FOREGROUND DB 40,8FH,0 ;BLACK BACKGROUND DB 41,8FH,40H ;RED BACKGROUND DB 42,8FH,20H ;GREEN BACKGROUND DB 43,8FH,60H ;YELLOW BACKGROUND DB 44,8FH,10H ;BLUE BACKGROUND DB 45,8FH,50H ;MAGENTA BACKGROUND DB 46,8FH,30H ;CYAN BACKGROUND DB 47,8FH,70H ;WHITE BACKGROUND DB 0FFH ;END OF TABLE ;--------------------------------------------------------------- ;WAIT PSW ID TABLE ;--------------------------------------------------------------- WTPSW DW CONW10 ;OUTPUT SUSPENDED DW COMR07 ;WAITING FOR INPUT DW COMW45 ;OUTPUT BUFFER FULL DW RPOS07 ;INTER-TASK READ DW WTBUF3 ;OUTPUT NOT COMPLETE DW RESMW1 ;MODEM RESET DW RESMW2 ;MODEM RESET DW LOCK37 ;LOCKED RESOURCE DW INIL55 ;PHONE DW HAYNW1 ;MODEM RESPONSE DELAY WTMSG DW 379 DW 380 DW 381 DW 382 DW 383 DW 384 DW 384 DW 385 DW 386 DW 380 ;SYSTEM MESSAGE STRINGS DW STR02-STR01-2 STR01 DB 'ERROR 303: Message ' DW STR99-STR02 STR02 DB ' is not available.' STR99 EQU $ SYSDATA ENDS ;----------------------------------------------- ;CODE SEGMENT ;----------------------------------------------- CSEG SEGMENT PARA PUBLIC 'CODE' EXTRN GETBUF:NEAR,FREBUF:NEAR,GDBY00:NEAR EXTRN QUICKS:NEAR,READTM:NEAR,SCANM:NEAR,ENTCMT:NEAR EXTRN ENTMSG:NEAR,DELETE:NEAR,BUILDM:NEAR EXTRN READM:NEAR,WRITM:NEAR,CRCCLC:NEAR EXTRN CKMSG:NEAR,DSPCLR:NEAR,WFBLK:NEAR EXTRN ERROR:NEAR,YIELD:NEAR,WAITRT:NEAR,FREUSR:NEAR EXTRN PRBYTE:NEAR,SENDF:NEAR,RUNFIL:NEAR,INIL55:NEAR EXTRN LABWIN:NEAR PUBLIC APPBYT,APPDSB,APPDSK,QMSGNO,LALIGN PUBLIC BINASP,CMPSTA,CPCSTA,DQCMD,DQTIOA,ILINEB PUBLIC MOVSTR,PTIME,QUERY,MONO,MOVMSG,WMSGNO PUBLIC PADB,SENDHF,TXPRT,UNCMD,WRMSG,WRLIN,XLATE PUBLIC CMPSTR,CPCSTR,BLANKF,LOGDSK,MOVSTL,STRIP PUBLIC CONR,CONW,CONWRT,BINASC,FRELBF,DOSTIM,TIMHM,DATASC PUBLIC ASCBIN,TAYSOP,TSYSOP,TSIGOP,CONT,ELPTIM PUBLIC CLRIBF,CLROBF,WRBLK,STM8B,WRLF,SAVALL,RSTALL PUBLIC DOSDAT,WRCR,ELPASC,PUMENU,STM7B PUBLIC LININ,TIMON,EXPBUF,LOCKWT,UNLOCK PUBLIC ENMDI,CLEAR,CLEARW,SCRWIN,FRETIO,PURGST,PURG1 PUBLIC TIMASC,PSMENU,PUSTAT,ST1200,ST2400,ST9600 PUBLIC ST300,TAYSOP,RESMDM,DTEASC,ANINIT PUBLIC TIMRTN,CHTIOA,TAYSOP,HAYIN,FRECMD PUBLIC HAYIND,BINASD,WTBUFE,ARANGE,WTID,GETMSG PUBLIC WPOST,RPOST,TPOST,CLRITB,CKCTLK,WSNOOP,SCAUSE PUBLIC ST4800,ST1920,ST3840,LOGCP PUBLIC MVCSTR,MVLSTR,MVZSTR,CLRCSR ASSUME CS:CSEG,DS:NOTHING,ES:SYSDATA ;----------------------------------------------- ;PHYSICAL SCREEN SUBROUTINES ;----------------------------------------------- MONO PROC ;CLEAR TASKS OWN WINDOW CLEAR: PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP MOV DI,BX ;CALLING CONVENTION MOV BH,BYTE PTR [BX+CBCOLOR] ;ATTRIBUTE CLEAR0: MOV AX,600H ;BLANK WINDOW MOV CX,WORD PTR [DI+CBWINUL] ;UL CORNER MOV DX,WORD PTR [DI+CBWINLR] ;LR CORNER CMP DH,24 ;LAST PHYSICAL LINE? JZ CLEAR1 ;YES INC DH ;INCLUDE LABEL LINE CLEAR1: INT 10H MOV WORD PTR [DI+CBLINO],0 ;CLEAR LINE COUNTER MOV AH,2 ;SET CURSOR POS MOV DX,WORD PTR [DI+CBWINUL] ;UL CORNER MOV WORD PTR [DI+CBCURSE],DX ;CURSOR MOV BH,0 ;PAGE NUMBER INT 10H POP BP POP DI POP SI POP DX POP CX POP BX POP AX RET ;CLEAR WINDOW OF TASK IN DI CLEARW: PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP MOV BH,7 ;NORMAL ATTRIBUTE JMP CLEAR0 ;CLEAR DI-> TCB FROM CURSOR TO END OF WINDOW CLRCSR: PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP MOV AX,600H ;BLANK WINDOW MOV BH,BYTE PTR [DI+CBCOLOR] ;ATTRIBUTE MOV CX,WORD PTR [DI+CBCURSE] ;CURSOR MOV CL,BYTE PTR [DI+CBWINUL] ;L EDGE MOV DX,WORD PTR [DI+CBWINLR] ;LR CORNER CMP CH,DH ;CURSOR ON LAST LINE? JZ CLRCS1 ;YES - EXIT INC CH ;LINE FOLLOWING CURSOR INT 10H CLRCS1: POP BP POP DI POP SI POP DX POP CX POP BX POP AX RET ;CALLED WITH DI -> TCB SCRWIN: PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP SUB BYTE PTR [DI+CBCURSE+1],AL ;SCROLL CURSOR MOV AH,6 ;SCROLL WINDOW UP MOV BH,BYTE PTR [DI+CBCOLOR] ;ATTRIBUTE MOV CX,WORD PTR [DI+CBWINUL] ;UL CORNER MOV DX,WORD PTR [DI+CBWINLR] ;LR CORNER INT 10H POP BP POP DI POP SI POP DX POP CX POP BX POP AX RET MONO ENDP SUBRTNS PROC SAVALL: PUSH BX MOV BX,CDTASK ;CURRENT TCB MOV WORD PTR [BX+USRAX],AX MOV WORD PTR [BX+USRCX],CX MOV WORD PTR [BX+USRDX],DX MOV WORD PTR [BX+USRSI],SI MOV WORD PTR [BX+USRDI],DI MOV WORD PTR [BX+USRBP],BP MOV WORD PTR [BX+USRES],ES POP AX MOV WORD PTR [BX+USRBX],AX MOV AX,WORD PTR [BX+USRAX] RET RSTALL: MOV BX,CDTASK ;CURRENT TCB MOV AX,WORD PTR [BX+USRAX] MOV CX,WORD PTR [BX+USRCX] MOV DX,WORD PTR [BX+USRDX] MOV SI,WORD PTR [BX+USRSI] MOV DI,WORD PTR [BX+USRDI] MOV BP,WORD PTR [BX+USRBP] MOV ES,WORD PTR [BX+USRES] MOV BX,WORD PTR [BX+USRBX] RET BINASP: PUSH CX PUSH AX PUSH BX PUSH DX XOR CX,CX ;DIGIT COUNT MOV BX,10 ;DECIMAL DIVISOR BINP10: INC CX ;COUNT DIGIT XOR DX,DX ;CLEAR MSW DIV BX ;DIVIDE BY TEN OR AX,AX ;ANYTHING LEFT? JNZ BINP10 ;YES - KEEP TRUCKING POP DX POP BX POP AX CALL BINASC POP CX RET ;-------------------------------------------------------- ;BINARY TO ASCII CONVERSION ROUTINE - DOUBLE PRECISION ; DX:AX VALUE TO CONVERT ; CX LENGTH OF TARGET FIELD (MSB = ZERO FILL) ; SI ADDRESS OF STRING TO WHICH VALUE IS TO BE APPENDED ; RETURNS NUMBER OF DIGITS IN CX ; [BP-2] VALUE ; [BP-4] STRING ADDRESS ; [BP-6] FIELD ADDRESS ; [BP-8] HIGH ORDER DIGITS ; [BP-10] DIGITS PRINTED BINASD: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,10 ;ALLOCATE LOCAL STORAGE PUSH DX PUSH BX MOV [BP-2],AX ;BINARY VALUE MOV [BP-4],SI ;STRING ADDRESS MOV [BP-8],DX ;MSB VALUE MOV BL,' ' ;DEFAULT FILL CHAR TEST CH,80H ;LEADING ZEROS? JZ BA10 ;NO AND CH,7FH ;RESET FLAG MOV BL,'0' ;ALTERNATE FILL CHAR BA10: MOV DX,WORD PTR [SI-2] ;DESTINATION STRING LENGTH MOV [BP-6],DX ;OFFSET TO FIELD ADDRESS ADD DX,CX ;NEW STRING LENGTH PUSH DX ;DATA LENGTH ADD DX,8 ;ALLOW FOR HEADER CMP WORD PTR [SI-6],DX ;MAX LENGTH POP DX ;DATA LENGTH JNB BA12 ;NO PROBLEM CMP DEBUGF,0 ;DEBUG ON? JNZ BA11 ;YES - CRASH JMP BAX ;EXIT BA11: POP BX ;TCB POINTER ERR 101H ;NO ROOM IN STRING BA12: MOV WORD PTR [SI-2],DX ;NEW LENGTH ADD SI,[BP-6] ;END OF STRING MOV [BP-6],SI ;FIELD ADDRESS BA15: MOV BYTE PTR [SI],BL ;FILL CHARACTER INC SI ;NEXT FIELD POSITION LOOP BA15 ;LOOP 'TIL DONE MOV [BP-10],CX ;INIT COUNT FIELD MOV AX,[BP-2] ;LSB VALUE MOV DX,[BP-8] ;MSB VALUE MOV BX,10000 ;DIVISOR CMP DX,BX ;VALUE TOO LARGE? JB BA16 ;NO PROBLEM MOV DX,9999 ;MAX VALUE BA16: DIV BX ;DIVIDE BY 10000 MOV [BP-8],AX ;SAVE QUOTIENT MOV AX,DX ;USE REMAINDER AS VALUE BA17: MOV CX,4 ;DIGITS TO PRINT MOV BX,10 ;INIT DIVISOR BA20: XOR DX,DX ;CLEAR MSB OF DIVISOR DIV BX ;DIVIDE BY TEN ADD DL,'0' ;CONVERT TO ASCII DIGIT DEC SI ;STEP BACKWARD THROUGH BUFFER INC WORD PTR [BP-10] ;COUNT DIGIT MOV [SI],DL ;STORE DIGIT CMP SI,[BP-6] ;OUT OF SPACE? JZ BAX ;YES - QUIT OR AX,AX ;ALL DIGITS PRINTED? JNZ BA30 ;NO - KEEP TRUCKING CMP WORD PTR [BP-8],0 ;ANY MORE WORK? JZ BAX ;NO - CAN QUIT BA30: LOOP BA20 ;KEEP TRUCKING MOV AX,[BP-8] ;NEXT 4 DIGITS MOV WORD PTR [BP-8],0 ;SHOW NO MORE JMP BA17 ;PRINT REST OF DIGITS BAX: MOV AX,[BP-2] ;RESTORE VALUE MOV SI,[BP-4] ;RESTORE STRING ADDRESS MOV CX,[BP-10] ;GET DIGIT COUNT POP BX POP DX MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET ;BINARY TO ASCII - SINGLE PRECISION BINASC: PUSH DX XOR DX,DX CALL BINASD POP DX RET ;ASCII RANGE TO BINARY ;LIKE ASCBIN BUT RETURNS ;V1:V2 IN AX:DX ARANGE: PUSH SI CALL ASCBIN ;GET FIRST VALUE JC ARAN90 ;INVALID PUSH AX ;1ST RESULT PUSH CX ARAN10: LODSB ;NEXT CHAR CMP AL,':' ;DELIMITER? JZ ARAN20 ;YES LOOP ARAN10 ;KEEP LOOKING XOR AX,AX ;NO SECOND VALUE JMP SHORT ARAN30 ;DONE ARAN20: CALL ASCBIN ;GET SECOND VALUE ARAN30: MOV DX,AX ;RETURN SECOND VALUE POP CX POP AX ;RETURN FIRST VALUE ARAN90: POP SI RET ;ASCII TO BINARY CONVERSION ; CX -> FIELD LENGTH ; SI -> FIELD ADDRESS ; BP-2 INTERMEDIATE RESULT ; BP-4 FLAGS ;RETURNS AX = VALUE ASCBIN: OR CX,CX ;ANY LENGTH? JNZ ASCB00 ;NO PROBLEM STC ;SHOW INVALID RET ASCB00: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,4 ;ALLOCATE LOCAL STORAGE PUSH CX PUSH DX PUSH SI XOR DX,DX MOV [BP-2],DX ;CLEAR TOTAL MOV [BP-4],DX ;AND FLAGS ASCB10: LODSB ;GET DIGIT CMP AL,' ' ;LEADING BLANK? JNZ ASCB15 ;NO LOOP ASCB10 ;SKIP LEADING BLANKS JMP SHORT ASCB80 ;EXIT ASCB15: CMP AL,'-' ;MINUS? JNZ ASCB30 ;NO OR WORD PTR [BP-4],1 ;MARK NEGATIVE ASCB20: LODSB ;GET NEXT DIGIT ASCB30: SUB AL,'0' ;CONVERT TO BINARY JC ASCB80 ;INVALID DIGIT CMP AL,10 ;VALID? JNC ASCB80 ;NO OR WORD PTR [BP-4],2 ;MARK VALID RESULT CBW PUSH AX MOV AX,[BP-2] ;GET TOTAL MOV DX,10 ;DECIMAL MULTIPLIER MUL DX ;SHIFT DECIMAL MOV [BP-2],AX ;SAVE POP AX ;LATEST DIGIT ADD [BP-2],AX ;NEW TOTAL LOOP ASCB20 ;HANDLE NEXT DIGIT ASCB80: TEST WORD PTR [BP-4],1 ;NEGATIVE? JZ ASCB82 ;NO PROBLEM NEG WORD PTR [BP-2] ;MAKE NEGATIVE ASCB82: TEST WORD PTR [BP-4],2 ;VALID? CLC ;ASSUME YES JNZ ASCB90 ;YES STC ;NO ASCB90: MOV AX,[BP-2] ;VALUE POP SI POP DX POP CX MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET ;WRITE MESSAGE FROM DATA BASE WMSGNO: PUSH DI CALL GETMSG ;GET MESSAGE IN BUFFER XCHG SI,DI ;SWAP FOR WRITE CALL WRMSG ;WRITE TO TERMINAL PUSHF ;REMEMBER RESULT CALL FREBUF ;FREE MESSAGE XCHG SI,DI ;RESTORE POPF POP DI RET ;WRITE ONE LINE TO TERMINAL AND ADVANCE TO NEXT LINE WRMSG: CALL STRIP ;REMOVE TRAILING BLANKS CALL WRLIN ;WRITE LINE JC WRMS10 ;LINE SUPPRESSED CALL WRCR ;WRITE C/R WRMS10: RET ;WRITE ONE LINE TO TERMINAL WRLIN: CALL XGXLAT ;CHECK EXTENDED GRAPHICS CALL ANSI ;CHECK ANSI HANDLING PUSH AX PUSH SI PUSH CX MOV CX,WORD PTR [SI-2] ;DATA LENGTH JCXZ WRLI40 ;EMPTY STRING TEST WORD PTR [BX+CBFLG],SFPIP ;PROMPT? JZ WRLI10 ;NO CALL LINCNT ;GET LINE COUNT CMP AX,1 ;ONE LINE PROMPT? JZ WRLI20 ;YES - NO PAGE CHECK NEEDED WRLI10: CALL PAGFUL ;CHECK FOR FULL PAGE JC WRLI42 ;MESSAGE SUPPRESSED WRLI20: LODSB ;GET NEXT CHAR CMP AL,12 ;PAGE EJECT? JNZ WRLI22 ;NO PROBLEM TEST WORD PTR [BX+CBFLG],SFNOPL ;SUPPRESS CHECKING? JNZ WRLI22 ;YES CALL PAGBRK ;FORCE 'MORE' PROMPT WRLI22: CALL CONW ;WRITE TO CONSOLE JC WRLI40 ;LOST CARRIER CMP AL,13 ;C/R? JNZ WRLI30 ;NO CALL WRLF ;LINE FEED IF NEEDED WRLI25: LOOP WRLI10 ;CHECK PAGE FULL JMP SHORT WRLI40 ;DONE WRLI30: CMP AL,10 ;LINE FEED? JNZ WRLI35 ;NO INC WORD PTR [BX+CBLINO] ;LINE COUNT JMP WRLI25 ;CHECK PAGE FULL WRLI35: LOOP WRLI20 ;GET NEXT CHARACTER WRLI40: CLC ;SHOW GOOD RETURN WRLI42: POP CX POP SI POP AX CALL YIELD ;LET OTHER TASKS RUN RET ;WRITE ONE LINE TO SNOOP WINDOW WSNOOP: CALL STRIP ;DELETE TRAILING BLANKS PUSH AX PUSH SI PUSH CX MOV CX,WORD PTR [SI-2] ;DATA LENGTH JCXZ WSNO40 ;EMPTY STRING WSNO20: LODSB ;GET NEXT CHAR CALL CONWRT ;WRITE TO WINDOW LOOP WSNO20 ;GET NEXT CHARACTER WSNO40: MOV AL,13 ;CR CALL CONWRT ;WRITE TO WINDOW MOV AL,10 ;LF CALL CONWRT ;WRITE TO WINDOW CLC ;SHOW GOOD RETURN POP CX POP SI POP AX CALL YIELD ;LET OTHER TASKS RUN RET ;FORCE PAGE BREAK PAGBRK: CMP WORD PTR [BX+CBLINO],0 ;ALREADY AT TOP? JNZ PAGBR0 ;NO - FORCE PROMPT RET PAGBR0: PUSH AX PUSH CX PUSH SI PUSH DI JMP SHORT PAGF32 ;ENTER COMMON CODE PAGFUL: PUSH AX PUSH CX PUSH SI PUSH DI TEST WORD PTR [BX+CBFLG],SFNOPL ;IGNORE PAGING? JNZ PAGF90 ;YES TEST WORD PTR [BX+CBMDM],MDMTEST ;SIMULATED TERMINAL? JNZ PAGF90 ;YES TEST WORD PTR [BX+CBMDM],MDMKBD ;LOCAL USER? JZ PAGF10 ;NO MOV AL,[BX+CBWINLR+1] ;LAST LINE IN WINDOW SUB AL,[BX+CBWINUL+1] ;1ST LINE IN WINDOW INC AL ;INCLUDE LAST LINE CBW ;WINDOW SIZE JMP SHORT PAGF30 PAGF10: MOV DI,[BX+USRST] ;USER RECORD OR DI,DI ;HAVE USER RECORD YET? JNZ PAGF20 ;NO PROBLEM MOV AX,24 ;ASSUME 24 LINES JMP SHORT PAGF30 PAGF20: MOV AX,[DI+UEXPL] ;PAGE LENGTH PAGF30: OR AX,AX ;CONTINUOUS? JZ PAGF90 ;YES DEC AX ;ROOM FOR 'MORE' MSG CMP [BX+CBLINO],AX ;PAGE FULL? JB PAGF90 ;NO PAGF32: MOV AX,57 ;MORE MSG CALL GETMSG ;GET MESSAGE MOV SI,DI ;START OF STRING CALL ANSI ;CHECK ANSI STRINGS MOV CX,[SI-2] ;STRING LENGTH JCXZ PAGF37 ;EMPTY STRING PUSH SI PAGF35: LODSB ;GET NEXT CHAR CALL CONW ;WRITE TO SCREEN LOOP PAGF35 ;WRITE REST OF STRING POP SI PAGF37: CALL NANSI ;FILTER ANSI STRINGS MOV CX,[SI-2] ;MESSAGE LENGTH CALL FREBUF ;FREE 'MORE' MESSAGE CALL CONR ;GET REPLY AND AL,0DFH ;MAKE UPPER CASE CALL ERALIN ;ERASE LINE MOV WORD PTR [BX+CBLINO],0 ;CLEAR LINE COUNT CMP AL,13 ;CARRIAGE RETURN? JZ PAGF90 ;YES - CONTINUE CMP AL,'N' ;NO? JZ PAGF98 ;SUPRESS PRINT CMP AL,'C' ;CONTINUOUS? JNZ PAGF90 ;DEFAULT TO YES OR WORD PTR [BX+CBFLG],SFNOPL ;SET CONTINUOUS PAGF90: CLC ;SHOW GOOD RETURN PAGF92: POP DI POP SI POP CX POP AX RET PAGF98: TEST WORD PTR [BX+CBFLG],SFPIP ;PROMPT? JNZ PAGF90 ;DON'T SUPPRESS PROMPT STC ;SUPPRESS MESSAGE JMP SHORT PAGF92 ;EXIT ;ERASE CURRENT LINE ERALIN: PUSH AX MOV AL,8 ;BACKSPACE JCXZ ERAL90 ;JUST IN CASE PUSH CX ERAL10: CALL CONW LOOP ERAL10 POP CX MOV AL,' ' ;BLANK PUSH CX ERAL20: CALL CONW LOOP ERAL20 POP CX MOV AL,8 ERAL30: CALL CONW LOOP ERAL30 ERAL90: POP AX RET WRBLK: PUSH AX PUSH CX PUSH SI MOV CX,WORD PTR [SI-2] ;LENGTH JCXZ WRBLKX ;EMPTY TEST WORD PTR [BP-20],8 ;USE DLE? JZ WRBLK1 ;NO MOV AL,16H ;SYN CALL CONW ;WRITE SYN CALL CONW ;WRITE SYN WRBLK1: LODSB ;GET NXT CHAR TEST WORD PTR [BP-20],8 ;USE DLE? JZ WRBLK5 ;NO CMP AL,11H ;X-ON? JZ WRBLK3 ;YES CMP AL,13H ;X-OFF? JZ WRBLK3 ;YES CMP AL,16H ;SYN? JZ WRBLK3 ;YES CMP AL,10H ;DLE? JNZ WRBLK5 ;NO WRBLK3: XOR AL,40H ;ENCODE CONTROL CHAR PUSH AX MOV AL,10H ;DLE CALL CONW ;WRITE DLE POP AX WRBLK5: CALL CONW ;WRITE IT JC WRBLKX ;LOST CARRIER LOOP WRBLK1 ;KEEP IT MOVING WRBLKX: POP SI POP CX POP AX RET WRCR: CALL PAGFUL ;CHECK FOR FULL PAGE JC WRCR90 ;SUPPRESS BLANK LINE PUSH AX MOV AL,13 ;CR CALL CONW CALL WRLF ;LINE FEED IF NEEDED POP AX WRCR90: RET WRLF: PUSH AX INC WORD PTR [BX+CBLINO] ;COUNT LINE TEST WORD PTR [BX+CBMDM],MDMKBD ;CONSOLE? JNZ WRLF20 ;YES - NEED LF TEST BYTE PTR [BX+CBMSR],MSRCD ;HAVE CARRIER? JZ WRLFX ;NO - DON'T SEND TEST WORD PTR [BX+CBFLG],SFVUR ;VALID USER RECORD? JZ WRLF20 ;NO - SEND LF PUSH SI MOV SI,WORD PTR [BX+USRST] ;USER RECORD TEST WORD PTR [SI+UEOPTS],1 ;LFs REQUIRED? POP SI JZ WRLFX ;NO - EXIT WRLF20: MOV AL,10 ;LINE FEED CALL CONW ;WRITE IT WRLFX: POP AX RET QMSGNO: OR WORD PTR [BX+CBFLG],SFPIP ;PROMPT PUSH DI CALL GETMSG ;GET MSG IN BUFFER XCHG SI,DI ;SWAP FOR WRITE CALL WRLIN ;WRITE LINE TO TERMINAL CALL FREBUF ;FREE MSG BUFFER XCHG SI,DI ;RESTORE SI POP DI CALL LININ ;GET USER RESPONSE RET QUERY: OR WORD PTR [BX+CBFLG],SFPIP ;PROMPT CALL WRLIN ;WRITE LINE CALL LININ ;GET RESPONSE RET ;GET RESPONSE FROM USER ; BP-2 HEAD OF TIOA CHAIN ; BP-4 END OF TIOA CHAIN ; BP-6 INPUT BUFFER ADDRESS LININ: AND WORD PTR [BX+CBFLG],NOT SFPIP ;CLEAR PROMPT FLAG CALL WTBUFE ;WAIT FOR END OF OUTPUT PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,6 ;ALLOCATE LOCAL STORAGE PUSH AX PUSH CX PUSH DX PUSH SI PUSH DI MOV SI,[BX+USRST] ;LOGON RECORD OR SI,SI ;HAVE ONE? JZ LIN00 ;NO TEST WORD PTR [SI+UEOPTS],2 ;PROMPT ON? JZ LIN00 ;NO MOV AL,7 ;BELL CHAR CALL CONW ;RING BELL LIN00: MOV AX,WORD PTR [BX+USRIN] ;HEAD OF TIOA CHAIN MOV [BP-2],AX MOV AX,WORD PTR [BX+USRIX] ;END OF TIOA CHAIN MOV [BP-4],AX MOV WORD PTR [BX+USRIX],0 ;KILL CHAIN LIN10: MOV AX,80 ;BUFFER SIZE CALL GETBUF ;GET INPUT BUFFER MOV [BP-6],SI ;INPUT BUFFER ADDRESS MOV DI,SI ;CURRENT STRING POSITION XOR CX,CX ;INITIALIZE COUNT LIN15: MOV DX,WORD PTR [SI-6] ;ALLOCATION LENGTH SUB DX,QEDTA ;MAXIMUM STRING LENGTH LIN20: CALL CONR ;GET NEXT CHAR JNC LIN25 ;GOOD READ JMP LIN41 ;LOST CARRIER LIN25: CMP AL,8 ;LEFT ARROW? JZ STORC3 ;TREAT AS BACKSPACE CMP AL,127 ;BACKSPACE? JZ STORC3 ;YES CMP AL,1DH ;PC-TALK LEFT ARROW? JZ STORC3 ;TREAT AS BACKSPACE CMP AL,13 ;? JZ STORC1 ;ONLY NON-PRINT CHAR TO STORE CMP AL,' ' ;PRINTABLE? JB LIN20 ;NO - IGNORE STORC1: MOV [DI],AL ;STORE IN BUFFER INC DI AND AL,7FH ;CLEAR PARITY FOR CR TEST INC CX ;COUNT CHARS CMP AL,13 ;? JZ STORC2 ;BYPASS SECURITY CHECK TEST WORD PTR [BX+USRSE],1 ;SECURE? JZ STORC2 ;NO MOV AL,'.' ;CONVERT TO DOT STORC2: TEST WORD PTR [BX+CBMDM],MDMKBD ;LOCAL? JNZ STOR1B ;ECHO LOCAL TEST BYTE PTR [BX+CBMSR],MSRCD JZ STOR1A ;DON'T ECHO HAYES CODES STOR1B: CALL CONW ;ECHO CHAR TO SCREEN STOR1A: CMP AL,13 ;END OF LINE? JNZ STOR2A ;NO CALL WRLF ;ECHO LF IF NEEDED JMP LIN30 STOR2A: CMP AL,';' ;DELIMITER JZ LIN30 ;YES CMP CX,DX ;BUFFER FULL? JB LIN20 ;NO - KEEP READING MOV SI,[BP-6] ;INPUT BUFFER CALL EXPBUF ;EXPAND BUFFER MOV [BP-6],SI ;NEW BUFFER ADDRESS JMP LIN15 ;KEEP MOVING STORC3: JCXZ LIN28 ;CHECK FOR PREVIOUS BUFFER DEC DI ;BACK UP IN BUFFER DEC CX ;REDUCE COUNT LIN27: MOV AL,8 CALL CONW MOV AL,' ' CALL CONW MOV AL,8 JMP STORC2 ;EXIT LIN28: CALL GETPRV ;CHECK PREVIOUS BUFFER JNC LIN27 ;BACKSPACE OVER ';' JMP LIN20 ;IGNORE BACKSPACE LIN30: DEC CX ;DON'T COUNT DELIMITER MOV WORD PTR [BX+CBLINO],0 ;CLEAR LINE COUNT AND WORD PTR [BX+CBFLG],NOT SFNOPL ;AND CONTINUOUS FLAG MOV SI,[BP-6] ;BUFFER ADDRESS MOV WORD PTR [SI-2],CX ;STORE COUNT CALL CHTIOA ;ADD TIOA TO CHAIN MOV WORD PTR [BP-6],0 ;SHOW NO BUFFER CMP AL,13 ;END OF INPUT? JZ LIN40 ;YES JMP LIN10 ;GET NEW BUFFER LIN40: CLC ;SHOW GOOD RETURN LIN41: PUSHF MOV SI,[BP-6] ;BUFFER ADDRESS CALL FREBUF ;FREE PARTIAL BUFFER MOV SI,[BP-2] ;OLD HEAD OF CHAIN MOV DI,WORD PTR [BX+USRIX] ;NEW END OF CHAIN OR DI,DI ;EXIST? JNZ LIN42 ;NO PROBLEM MOV WORD PTR [BX+USRIN],SI ;RESTORE HEAD OF CHAIN JMP LIN43 LIN42: SUB DI,QENXT ;ADDRESS HEADER MOV WORD PTR [DI+QENXT],SI ;ADD OLD CHAIN TO NEW LIN43: MOV DI,[BP-4] ;OLD END OF CHAIN OR DI,DI ;EXIST? JZ LIN44 ;NO MOV WORD PTR [BX+USRIX],DI ;RESTORE END OF CHAIN LIN44: POPF POP DI POP SI POP DX POP CX POP AX MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET ;GET PREVIOUS INPUT BUFFER, IF ANY GETPRV: CMP WORD PTR [BX+USRIX],0 ;ANY PREVIOUS BUFFER? JNZ GETP10 ;YES STC ;SHOW NONE FOUND RET GETP10: PUSH SI MOV SI,[BP-6] ;EMPTY BUFFER CALL FREBUF ;FREE IT MOV SI,[BX+USRIN] ;HEAD OF CHAIN CMP SI,[BX+USRIX] ;ONLY ELEMENT? JNZ GETP20 ;NO - CHECK CHAIN MOV WORD PTR [BX+USRIN],0 ;CLEAR HEAD POINTER MOV WORD PTR [BX+USRIX],0 ;CLEAR TAIL POINTER JMP GETP40 ;SET UP REGISTERS GETP20: MOV DI,WORD PTR [SI+QENXT] ;FORWARD POINTER CMP DI,[BX+USRIX] ;POINT TO END? JZ GETP30 ;YES MOV SI,DI ;NEXT ELEMENT OR SI,SI ;ANY MORE? JNZ GETP20 ;YES ERR 204H ;BAD TIOA CHAIN GETP30: MOV [BX+USRIX],SI ;NEW TAIL POINTER MOV WORD PTR [SI+QENXT],0 ;CLEAR FORWARD PTR MOV SI,DI ;NEW CURRENT BUFFER GETP40: MOV CX,[SI+QEDLN] ;CURRENT LENGTH MOV DX,[SI+QELEN] ;ALLOCATION LENGTH SUB DX,QEDTA ;NEW MAX LENGTH MOV DI,SI ADD DI,QEDTA ;POINT TO DATA MOV [BP-6],DI ;CURRENT BUFFER ADD DI,CX ;NEW POSITION POP SI CLC ;SHOW VALUE FOUND RET ;GET RESPONSE FROM HAYES AFTER DIAL COMMAND HAYIND: MOV AX,1092 ;ABOUT 1 MIN JMP SHORT HAYN00 ;ENTER COMMON CODE ;GET RESPONSE FROM HAYES SMARTMODEM HAYIN: MOV AX,180 ;ABOUT 10 SECS HAYN00: CALL WTBUFE ;WAIT FOR OUTPUT COMPLETE PUSH DI PUSH CX XOR CX,CX ;INITIALIZE LENGTH MOV WORD PTR [BX+CBRTV],AX ;SET TIMEOUT VALUE MOV WORD PTR [BX+CBLINO],0 ;CLEAR LINE COUNT CALL FRECMD ;FREE COMMAND BUFFER MOV AX,80 ;RESPONSE MAX LENGTH CALL GETBUF ;GET RESPONSE BUFFER MOV WORD PTR [BX+USRCMD],SI ;SAVE AS COMMAND BUFFER MOV WORD PTR [SI-2],80 ;MAXIMUM LENGTH MOV DI,SI ;CURRENT POSITION HAYN10: CALL CONR ;GET NEXT CHAR JNC HAYN20 ;GOOD RESPONSE JMP SHORT HAYN40 ;TIMED OUT HAYN20: AND AL,07FH ;CLEAR PARITY BIT CMP AL,13 ;C/R? JNZ HAYN30 ;NO JCXZ HAYN10 ;IGNORE INITIAL MOV [DI],AL ;STORE IN BUFFER INC DI JMP SHORT HAYN40 ;EXIT HAYN30: CMP AL,'9' ;VALID NUMERIC? JA HAYN10 ;NO - IGNORE CMP AL,'0' ;VALID NUMERIC? JB HAYN10 ;NO INC CX ;COUNT CHARACTER MOV [DI],AL ;STORE IN BUFFER INC DI CMP CX,WORD PTR [SI-2] ;BUFFER FULL? JLE HAYN10 ;NO - KEEP TRUCKING HAYN40: PUSHF ;SAVE TIME OUT STATUS MOV WORD PTR [SI-2],CX ;STORE CURRENT LENGTH CALL ASCBIN ;CONVERT TO BINARY MOV CX,2 ;ABOUT 0.1 SEC MOV WORD PTR [BX+CBRTC],CX ;TIME TO WAIT CALL WAITRT HAYNW1: MOV CX,TIMEOUT ;STANDARD TIMEOUT VALUE MOV WORD PTR [BX+CBRTV],CX ;SET TIMEOUT POPF ;RESTORE TIME-OUT STATUS POP CX POP DI RET ;ADD SI -> BUFFER TO TASK'S TIOA CHAIN CHTIOA: PUSH DI SUB SI,QEDTA ;POINT TO HEADER CMP WORD PTR [BX+USRIX],0 ;CHAIN EXIST? JZ CHTI02 ;NO - MUST CREATE MOV DI,WORD PTR [BX+USRIX] ;-> LAST TIOA MOV WORD PTR [DI+QENXT],SI ;ADD TO CHAIN CHTI01: MOV WORD PTR [BX+USRIX],SI ;THIS ONE NOW LAST POP DI RET CHTI02: MOV WORD PTR [BX+USRIN],SI ;1ST IN CHAIN JMP CHTI01 ;UPDATE LAST POINTER ;DEQUEUE LAST COMMAND DQCMD: CALL FRECMD ;FREE COMMAND BUFFER CALL DQTIOA ;GET NEW COMMAND STRING JC DQCMDX ;NO TIOA MOV WORD PTR [BX+USRCMD],SI ;STORE ADDRESS DQCMDX: RET ;DEQUEUE 1ST TIOA FROM CHAIN DQTIOA: MOV SI,WORD PTR [BX+USRIN] ;GET TIOA POINTER CMP SI,0 ;ANY FOUND? JNZ DQTI10 ;YES STC ;SHOW NO TIOA RET DQTI10: CMP SI,WORD PTR [BX+USRIX] ;ONLY ONE ON CHAIN? JNZ DQTI20 ;NO - GO HANDLE MOV WORD PTR [BX+USRIN],0 ;CLEAR 1ST POINTER MOV WORD PTR [BX+USRIX],0 ;CLEAR LAST POINTER ADD SI,QEDTA ;POINT TO DATA CLC ;SHOW GOOD RETURN RET DQTI20: PUSH SI MOV SI,WORD PTR [SI+QENXT] ;NEXT TIOA MOV WORD PTR [BX+USRIN],SI ;SHOW AS FIRST POP SI MOV WORD PTR [SI+QENXT],0 ;CLEAR FORWARD CHAIN ADD SI,QEDTA ;POINT TO DATA CLC ;SHOW GOOD RETURN RET ;EXPAND CURRENT INPUT BUFFER EXPBUF: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,6 ;ALLOCATE LOCAL STORAGE PUSH AX PUSH CX MOV [BP-2],SI ;OLD STRING MOV [BP-6],CX ;CURRENT COUNT MOV AX,CX ;CURRENT COUNT ADD AX,40 ;EXTEND SIZE MOV DX,AX ;NEW MAXIMUM XCHG SI,DI CALL GETBUF ;GET NEW BUFFER MOV [BP-4],SI ;NEW STRING MOV WORD PTR [SI-2],CX ;MOVE CURRENT COUNT XCHG SI,DI EXPB10: LODSB ;GET DATA MOV [DI],AL ;STORE DATA INC DI LOOP EXPB10 MOV SI,[BP-2] ;OLD STRING CALL FREBUF ;FREE OLD BUFFER MOV SI,[BP-4] ;NEW STRING POP CX POP AX MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET CONW: TEST WORD PTR [BX+CBMDM],MDMKBD ;LOCAL? JNZ CONW00 ;YES JMP COMW ;MUST BE COM LINE CONW00: TEST WORD PTR [BX+CBFLG],SFHLT ;SUSPEND OUTPUT? JZ CONWRT ;NO PROBLEM CONW05: PUSH AX MOV [BX+CBWWT],BX ;REQUEST POST CALL WAITRT ;WAIT FOR RESUME CONW10: MOV WORD PTR [BX+CBWWT],0 ;ACKNOWLEDGE POST AND WORD PTR [BX+CBFLG],NOT SFHLT ;RESUME OUTPUT POP AX CONWRT: PUSH AX PUSH BX ;TCB POINTER PUSH CX PUSH DX PUSH SI PUSH DI PUSH BP PUSH AX CONW20: CALL ANSHAN ;CALL ANSI STATE DISPATCHER CLC ;CLEAR LOST CARRIER FLAG POP AX POP BP POP DI POP SI POP DX POP CX POP BX POP AX RET ;CHECK FOR SCREEN CONTROL CHARACTERS CONW30: CMP AL,0DH ;CARRIAGE RETURN? JNZ CONW33 ;NO MOV AH,BYTE PTR [BX+CBWINUL] ;LEFT MARGIN MOV BYTE PTR [BX+CBCURSE],AH ;RESET COLUMN JMP CONW60 ;UPDATE CURSOR POSITION CONW33: CMP AL,0AH ;LINE FEED? JZ CONW56 ;YES CMP AL,7 ;BELL? JNZ CONW40 ;NO CONW36: PUSH BX PUSH DI XOR BX,BX ;PAGE MOV BL,BYTE PTR [BX+CBCOLOR] ;ATTRIBUTE MOV AH,0EH ;WRITE TELETYPE INT 10H ;VIDEO BIOS CALL POP DI POP BX CONW39: RET CONW40: CMP AL,8 ;BACKSPACE? JNZ CONW45 ;NO MOV AH,BYTE PTR [BX+CBWINUL] ;LEFT MARGIN CMP AH,BYTE PTR [BX+CBCURSE] ;ALREADY AT LEFT EDGE? JZ CONW39 ;YES - IGNORE DEC BYTE PTR [BX+CBCURSE] ;PREVIOUS COLUMN JMP SHORT CONW60 ;UPDATE CURSOR POSITION CONW45: CMP AL,9 ;TAB? JNZ CONW48 ;NO XOR CX,CX ;CLEAR COUNT REGISTER MOV CL,BYTE PTR [BX+CBCURSE] ;CURRENT COLUMN ADD CL,8 ;TAB WIDTH AND CL,0F8H ;NEW COLUMN CMP CL,BYTE PTR [BX+CBWINLR] ;MAX COLUMN JA CONW54 ;TREAT AS NEW LINE MOV BYTE PTR [BX+CBCURSE],CL ;NEW COLUMN JMP SHORT CONW60 ;UPDATE CURSOR POSITION CONW48: CMP AL,12 ;NEW PAGE? JNZ CONW50 ;NO CALL CLEAR ;CLEAR SCREEN CALL LABWIN RET ;DISPLAY CHAR ON SCREEN CONW50: PUSH BX MOV DX,WORD PTR [BX+CBCURSE] ;CURSOR POSITION XOR BX,BX ;PAGE PUSH AX MOV AH,2 ;SET CURSOR INT 10H ;VIDEO BIOS CALL POP AX POP BX PUSH BX MOV BL,BYTE PTR [BX+CBCOLOR] ;ATTRIBUTE MOV BH,0 ;PAGE MOV CX,1 ;CHARACTER COUNT MOV AH,9 ;DISPLAY CHAR & ATTRIBUTE INT 10H ;VIDEO BIOS CALL POP BX INC BYTE PTR [BX+CBCURSE] ;NEXT COLUMN MOV AH,BYTE PTR [BX+CBWINLR] ;LAST COLUMN CMP BYTE PTR [BX+CBCURSE],AH ;AT END? JBE CONW60 ;NO PROBLEM ;ADVANCE TO NEXT LINE CONW54: MOV AH,BYTE PTR [BX+CBWINUL] ;LEFT MARGIN MOV BYTE PTR [BX+CBCURSE],AH ;RESET COLUMN CONW56: INC BYTE PTR [BX+CBCURSE+1] ;NEXT ROW MOV AH,BYTE PTR [BX+CBWINLR+1] ;LAST ROW CMP BYTE PTR [BX+CBCURSE+1],AH ;OFF BOTTOM? JBE CONW60 ;NO PROBLEM MOV BYTE PTR [BX+CBCURSE+1],AH ;STAY ON LAST LINE CALL SCROLL ;SCROLL SCREEN ;RESTORE CURSOR POSITION TO LOCAL USER CONW60: PUSH BX PUSH DI MOV DI,KBDTSK ;LOCAL TCB TEST WORD PTR [DI+CBFLG],SFWINV ;VALID WINDOW? JNZ CONW65 ;YES - RESTORE CURSOR MOV DI,BX ;USE SNOOP WINDOW CURSOR CONW65: MOV DX,WORD PTR [DI+CBCURSE] ;CURSOR POSITION XOR BX,BX ;PAGE MOV AH,2 ;SET CURSOR INT 10H ;VIDEO BIOS CALL CONW68: POP DI POP BX RET ;SCROLL SCREEN SCROLL: PUSH BX MOV AX,601H ;SCROLL UP ONE LINE MOV CX,WORD PTR [BX+CBWINUL] ;UL CORNER MOV DX,WORD PTR [BX+CBWINLR] ;LR CORNER MOV BH,BYTE PTR [BX+CBCOLOR] ;ATTRIBUTE INT 10H ;VIDIO BIOS CALL POP BX RET ;DISPATCH ANSI STATE HANDLER ANSHAN: MOV SI,WORD PTR [BX+CBSTATE] ;ANSI STATE HANDLER JMP SI ;ENTER APPROPRIATE ROUTINE ;INITIAL STATE HANDLER - NO ANSI SEQUENCE IN PROCESS ANINIT: CMP AL,1BH ;ESCAPE? JNZ ANIN10 ;NO MOV WORD PTR [BX+CBSTATE],OFFSET ANIN30 ;SET NEXT STATE RET ANIN10: CALL CONW30 ;DISPLAY CHAR ANIN20: MOV WORD PTR [BX+CBSTATE],OFFSET ANINIT ;SET INITIAL STATE RET ;EXPECT '[' STATE ANIN30: CMP AL,5BH ;'[' ;VIDEO CONTROL? JNZ ANINIT ;NO - GO TO INITIAL STATE MOV WORD PTR [BX+CBSTATE],OFFSET ANIN40 ;SET NEXT STATE MOV BYTE PTR [BX+CBPARMC],0 ;CLEAR PARM CNT MOV BYTE PTR [BX+CBPARMI],0 ;CLEAR PARM INDEX MOV BYTE PTR [BX+CBSDLM],0 ;CLEAR STRING DELIMITER JMP SHORT ANIN44 ;EXPECT NUMERIC PARAMETER STATE ANIN40: CMP AL,';' ;END OF PARM? JNZ ANIN50 ;NO ANIN42: INC BYTE PTR [BX+CBPARMC] ;COUNT PARM ANIN44: CALL ANINDX ;INDEX INTO PARM WORK AREA XOR AX,AX MOV [SI],AL ;CLEAR PARM VALUE RET ;CHECK FOR VALID DECIMAL DIGIT ANIN50: CMP AL,'0' ;NUMERIC? JB ANIN60 ;NO - TEST FOR DELIMITER CMP AL,'9' ;NUMERIC? JA ANIN60 ;NO - TEST FOR DELIMITER CALL ANINDX ;INDEX INTO PARM WORK AREA SUB AL,'0' ;CONVERT TO BINARY XCHG AL,[SI] ;GET PREVIOUS VALUE MOV AH,10 ;DECIMAL RADIX MUL AH ;SHIFT DECIMAL POINT ADD [SI],AL ;ADD TO CURRENT DIGIT RET ;CHECK FOR STRING DELIMITERS ANIN60: CMP AL,'=' JZ ANIN69 ;IGNORE EQUAL SIGN CMP AL,'?' JZ ANIN69 ;IGNORE QUESTION MARK CMP AL,'"' ;STRING DELIMITER? JZ ANIN65 ;YES CMP AL,"'" ;ALTERNATIVE DELIMITER? JNZ ANIN70 ;NO - CHECK ANSI CMD CODE ANIN65: MOV WORD PTR [SI],OFFSET ANIN80 ;SET STRING STATE MOV BYTE PTR [BX+CBSDLM],AL ;SET STRING DELIMITER ANIN69: RET ;CHECK FOR VALID ANSI COMMAND CODE ANIN70: LEA SI,ANSICMD-3 ;START OF TABLE ANIN72: ADD SI,3 ;NEXT ENTRY CMP BYTE PTR ES:[SI],0 ;END OF TABLE? JZ ANIN10 ;YES - INVALID CMP ES:[SI],AL ;THIS ENTRY? JNZ ANIN72 ;NO - KEEP CHECKING MOV AX,ES:[SI+1] ;ROUTINE ADDRESS LEA SI,[BX+CBPARMS] ;PARM WORK AREA MOV DL,[SI] ;GET PARM VALUE XOR DH,DH ;CBW MOV CX,DX ;REPETITION COUNT OR CX,CX ;NULL? JNZ ANIN79 ;NO PROBLEM INC CX ;DEFAULT TO 1 ANIN79: JMP AX ;ENTER ROUTINE ;MIDDLE OF STRING STATE ANIN80: CMP AL,[BX+CBSDLM] ;TERMINATING DELIMITER? JNZ ANIN85 ;NO - STORE IN WORK AREA DEC BYTE PTR [BX+CBPARMC] ;DON'T COUNT DELIMITER MOV WORD PTR [BX+CBSTATE],OFFSET ANIN50 ;NUMERIC PARM STATE RET ;STORE STRING CHARACTER IN PARM TABLE ANIN85: CALL ANINDX ;INDEX INTO PARM WORK AREA MOV [SI],AL ;STORE STRING CHAR MOV WORD PTR [BX+CBSTATE],OFFSET ANIN80 ;SET STRING STATE JMP ANIN42 ;NEXT PARM ;SET CURSOR POSITION ANSETC: MOV AX,WORD PTR [BX+CBWINLR] ;END OF WINDOW CMP CL,AH ;OFF SCREEN? JBE ANSE10 ;NO PROBLEM MOV CL,AH ;USE LAST LINE ANSE10: MOV CH,[SI+1] ;COLUMN OR CH,CH ;NULL? JZ ANSE20 ;YES DEC CH ;CONVERT TO OFFSET ANSE20: CMP AL,CH ;MAX VALUE? JA ANSE30 ;NO PROBLEM MOV CH,AL ;USE MAXIMUM ANSE30: XCHG CL,CH ;ROW DEC CH ;CONVERT TO OFFSET MOV WORD PTR [BX+CBCURSE],CX ;CURSOR POS JMP ANIN20 ;SET INITIAL STATE ;CURSOR FORWARD ANCFWD: MOV AH,BYTE PTR [BX+CBWINLR] ;MAX COLUMN MOV AL,1 ;INCREMENT COLUMN ANCFW1: LEA SI,[BX+CBCURSE] ;COLUMN COUNTER JMP ANADJ ;ADJUST VALUE ;CURSOR BACKWARD ANCBWD: MOV AL,0FFH ;DECREMENT COLUMN MOV AH,BYTE PTR [BX+CBWINUL] ;MIN COLUMN JMP ANCFW1 ;POINT TO COLUMN COUNTER ;CURSOR UP ANCUP: MOV AL,0FFH ;DECREMENT ROW MOV AH,BYTE PTR [BX+CBWINUL+1] ;MIN ROW ANCUP1: LEA SI,[BX+CBCURSE+1] ;ROW COUNTER JMP ANADJ ;ADJUST VALUE ;CURSOR DOWN ANCDN: MOV AL,1 ;INCREMENT ROW MOV AH,BYTE PTR [BX+CBWINLR+1] ;MAX ROW JMP SHORT ANCUP1 ;POINT TO ROW COUNTER ;SET GRAPHIC RENDITION ANSGR: XOR CX,CX XCHG CL,BYTE PTR [BX+CBPARMC] ;GET & CLEAR PARM COUNT CALL ANINDX ;INDEX INTO PARM WORK AREA INC CX ;NEXT PARM ANSG10: MOV AL,[SI] ;GET NEXT PARM PUSH SI ;PARM POINTER MOV SI,OFFSET SGRTBL ;ATTRIBUTE TABLE ANSG20: MOV AH,ES:[SI] ;PARM VALUE ADD SI,3 ;NEXT ENTRY CMP AH,0FFH ;END OF TABLE? JZ ANSG30 ;YES - IGNORE PARM CMP AH,AL ;THIS ENTRY? JNZ ANSG20 ;NO - KEEP CHECKING MOV AX,ES:[SI-2] ;ATTRIBUTE BYTES AND BYTE PTR [BX+CBCOLOR],AL ;TURN OFF ATTRIBUTES OR BYTE PTR [BX+CBCOLOR],AH ;TURN ON ATTRIBUTES ANSG30: POP SI ;PARM POINTER INC SI ;NEXT PARM LOOP ANSG10 ;HANDLE REST OF PARMS JMP ANIN20 ;SET INITIAL STATE ;CLEAR SCREEN AND HOME CURSOR ANCLR: MOV CX,WORD PTR [BX+CBWINUL] ;UL CORNER MOV WORD PTR [BX+CBCURSE],CX ;HOME CURSOR MOV DX,WORD PTR [BX+CBWINLR] ;LR CORNER MOV WORD PTR [BX+CBLINO],0 ;CLEAR LINE COUNT ANCL10: PUSH BX PUSH DI MOV BH,BYTE PTR [BX+CBCOLOR] ;ATTRIBUTE MOV AX,600H ;CLEAR WINDOW INT 10H ;VIDEO BIOS CALL POP DI POP BX JMP ANIN20 ;SET INITIAL STATE ;ERASE TO END OF LINE ANEEOL: MOV CX,WORD PTR [BX+CBCURSE] ;CURRENT CURSOR POS MOV DX,WORD PTR [BX+CBWINLR] ;END OF WINDOW MOV DH,CH ;SINGLE LINE WINDOW JMP ANCL10 ;CLEAR WINDOW ;BINARY TO ASCII CONVERSION L04A4: MOV DL,10 ;RADIX INC AL ;ADJUST OFFSET TO COLUMN XOR AH,AH ;CBW DIV DL ;CONVERT TO DECIMAL ADD AX,3030H ;CONVERT TO ASCII RET ANNULL: JMP ANIN20 ;SET INITIAL STATE ;INDEX INTO PARM WORK AREA ANINDX: LEA SI,[BX+CBPARMS] ;PARM WORK AREA CMP BYTE PTR [BX+CBPARMC],6 ;MAX COUNT JB ANIND1 ;NO PROBLEM DEC BYTE PTR [BX+CBPARMC] ;PREVIOUS PARM JMP SHORT ANINDX ;CHECK AGAIN ANIND1: PUSH AX MOV AL,BYTE PTR [BX+CBPARMC] ;PARM COUNT CBW ADD SI,AX ;INDEX INTO WORK AREA POP AX RET ;ADJUST CURSOR POSITION ANADJ: CMP [SI],AH ;AT MAXIMUM VALUE? JZ ANADJX ;YES - DON'T CHANGE ADD [SI],AL ;ADJUST VALUE LOOP ANADJ ;ONE AT A TIME ANADJX: JMP ANIN20 ;SET INITIAL STATE ;READ ONE CHARACTER FROM KEYBOARD CONR: PUSH AX TEST WORD PTR [BX+CBFLG],SFLCP ;LOST CARRIER PENDING? JNZ CONR00 ;DON'T CHANGE TIME-OUT VALUE MOV AX,WORD PTR [BX+CBRTV] ;TIME-OUT VALUE MOV WORD PTR [BX+CBRTC],AX ;CURRENT COUNT CONR00: AND WORD PTR [BX+CBFLG],NOT SFTO ;TURN OFF FLAG POP AX COMR: TEST WORD PTR [BX+CBMDM],MDMTEST ;SIMULATED TERMINAL? JZ COMR03 ;NO CALL TSTINP ;GET TEST DATA JC COMR03 ;NO TEST DATA RET COMR03: TEST WORD PTR [BX+CBFLG],SFLC+SFTO+SFITP JZ COMR05 ;NO PROBLEM STC ;SHOW ERROR RET COMR05: PUSH SI PUSH DI MOV DI,WORD PTR [BX+CBIBA] ;INPUT BUFFER CTL BLOCK CLI ;NO INTERRUPTS DURING TEST MOV SI,WORD PTR [DI+BFRNI] ;NEXT INPUT CHAR CMP SI,WORD PTR [DI+BFRNO] ;SAME AS OUTPUT? JNZ COMR10 ;NO PROBLEM MOV WORD PTR [BX+CBWRD],BX ;REQUEST POST CALL WAITRT COMR07: MOV WORD PTR [BX+CBWRD],0 ;ACKNOWLEDGE POST STI ;ALLOW INTERRUPTS POP DI POP SI JMP COMR ;TEST FOR ERROR POST COMR10: LODSB ;GET CHAR TEST WORD PTR [BX+USRSE],1 ;SECURITY ON? JZ COMR15 ;NO PROBLEM MOV BYTE PTR [SI-1],'.' ;HIDE PASSWORD COMR15: CMP SI,WORD PTR [DI+BFRND] ;END OF BUFFER? JB COMR20 ;NO PROBLEM MOV SI,WORD PTR [DI+BFRST] ;START OF BUFFER COMR20: MOV WORD PTR [DI+BFRNI],SI ;NEW INPUT POINTER STI ;ALLOW INTERRUPTS AGAIN TEST DS:MSGCKPT+MSOPTS,4 ;LINE TRACE ON? JZ COMR30 ;NO PUSH DI TEST WORD PTR [BX+CBFLG],SFLTR ;FOR THIS LINE? JZ COMR25 ;NO OR BYTE PTR [BX+CBCOLOR],8 ;SET HIGH INTENSITY PUSH AX CALL PRBYTE ;HEX TO CONSOLE POP AX AND BYTE PTR [BX+CBCOLOR],NOT 8 ;NORMAL INTENSITY COMR25: POP DI COMR30: POP DI POP SI CLC ;SHOW GOOD RETURN RET COMW: PUSH AX PUSH DX PUSH SI PUSH DI TEST BYTE PTR [BX+CBFLG],SFLC ;LOST CARRIER? JZ COMW30 ;NO PROBLEM COMW10: CALL CLROBF ;CLEAR OUTPUT BUFFER STC ;SHOW ERROR JMP COMW95 ;RETURN COMW30: TEST DS:MSGCKPT+MSOPTS,2 ;SNOOP ON? JZ COMW32 ;NO TEST WORD PTR [BX+CBFLG],SFSNP ;FOR THIS LINE? JZ COMW32 ;NO CMP AL,7 ;BELL CHAR? JZ COMW32 ;DON'T SEND BELL TO SNOOP CALL CONWRT ;ECHO TO SCREEN COMW32: TEST DS:MSGCKPT+MSOPTS,4 ;LINE TRACE ON? JZ COMW34 ;NO TEST WORD PTR [BX+CBFLG],SFLTR ;FOR THIS LINE? JZ COMW34 ;NO PUSH AX CALL PRBYTE ;HEX TO SCREEN POP AX COMW34: MOV SI,WORD PTR [BX+CBOBA] ;OUTPUT BUFFER CLI ;TIME SENSITIVE ROUTINE MOV DI,WORD PTR [SI+BFRNO] ;NEXT OUTPUT POSITION MOV [DI],AL ;STORE IN BUFFER INC DI CMP DI,WORD PTR [SI+BFRND] ;END OF BUFFER? JNZ COMW40 ;NO PROBLEM MOV DI,WORD PTR [SI+BFRST] ;START OF BUFFER COMW40: CMP DI,WORD PTR [SI+BFRNI] ;BUFFER FULL? JNZ COMW50 ;NO PROBLEM MOV WORD PTR [BX+CBWWT],BX ;ASK FOR POST MOV WORD PTR [BX+CBRTC],18*60 ;TIMEOUT COUNT AND WORD PTR [BX+CBFLG],NOT SFTO ;CLEAR TIME OUT CALL WAITRT ;FOLLOWING LABEL USED FOR WAIT STATUS MSG COMW45: MOV WORD PTR [BX+CBWWT],0 ;CLEAR POST TEST WORD PTR [BX+CBFLG],SFTO+SFLC ;ERROR POST? JZ COMW40 ;NO - STORE CHARACTER TEST WORD PTR [BX+CBFLG],SFLC ;LOST CARRIER? JNZ COMW48 ;YES - FLUSH BUFFER TEST BYTE PTR [BX+CBMSR],MSRCTS ;WAITING FOR MODEM? JZ COMW40 ;YES - WAIT SOME MORE STI ;ALLOW INTERRUPTS CALL ILINEB ;INITIALIZE BUFFER MOV AX,415 ;ERROR MESSAGE CALL MOVMSG ;MOVE TO BUFFER CALL LOGDSK ;LOG ERROR COMW48: JMP COMW10 ;FLUSH BUFFER COMW50: MOV WORD PTR [SI+BFRNO],DI ;UPDATE OUTPUT POINTER MOV DX,WORD PTR [BX+CBMBA] ;MODEM BASE ADDRESS ADD DX,5 ;LINE STATUS REG IN AL,DX ;GET LINE STATUS TEST AL,20H ;TRANSMITTER AVAILABLE? JZ COMW90 ;NO - EXIT TEST BYTE PTR [BX+CBMSR],MSRCTS ;CTS? JZ COMW90 ;NO - EXIT MOV DI,WORD PTR [SI+BFRNI] ;NEXT CHAR TO SEND CMP DI,WORD PTR [SI+BFRNO] ;EMPTY? JZ COMW90 ;YES - EXIT MOV DX,WORD PTR [BX+CBMBA] ;TRANSMITTER HOLDING REGISTER MOV AL,BYTE PTR [DI] ;CHAR TO SEND OUT DX,AL ;WRITE TO LINE INC DI ;NEXT BUFFER POSITION CMP DI,WORD PTR [SI+BFRND] ;END OF BUFFER? JNZ COMW60 ;NO PROBLEM MOV DI,WORD PTR [SI+BFRST] ;START OF BUFFER COMW60: MOV WORD PTR [SI+BFRNI],DI ;UPDATE POINTER COMW90: CLC COMW95: STI ;ALLOW INTERRUPTS AGAIN POP DI POP SI POP DX POP AX RET CONT: PUSH SI PUSH DI MOV DI,WORD PTR [BX+CBIBA] ;BUFFER CTL BLOCK MOV SI,WORD PTR [DI+BFRNI] ;NEXT INPUT CHAR CMP SI,WORD PTR [DI+BFRNO] ;NEXT OUTPUT CHAR POP DI POP SI RET ;READ ONE CHARACTER FROM INTER-TASK BUFFER RPOST: PUSH AX MOV AX,WORD PTR [BX+CBRTV] ;TIME-OUT VALUE MOV WORD PTR [BX+CBRTC],AX ;CURRENT COUNT AND WORD PTR [BX+CBFLG],NOT SFTO ;CLEAR TIME-OUT FLAG POP AX RPOS00: TEST WORD PTR [BX+CBFLG],SFLC+SFTO ;LOST CARRIER OR T.O.? JZ RPOS05 ;NO PROBLEM CALL CLRITB ;CLEAR INTER-TASK BUFFER STC ;SHOW ERROR RET RPOS05: PUSH SI PUSH DI MOV DI,WORD PTR [BX+CBTBA] ;BUFFER CTL BLOCK CLI ;NO INTERRUPTS DURING TEST MOV SI,WORD PTR [DI+BFRNI] ;NEXT INPUT CHAR CMP SI,WORD PTR [DI+BFRNO] ;SAME AS OUTPUT? JNZ RPOS10 ;NO PROBLEM MOV WORD PTR [BX+CBWRD],BX ;REQUEST POST CALL WAITRT RPOS07: MOV WORD PTR [BX+CBWRD],0 ;ACKNOWLEDGE POST POP DI POP SI JMP RPOS00 ;TEST FOR ERROR POST RPOS10: LODSB ;GET CHAR CMP SI,WORD PTR [DI+BFRND] ;END OF BUFFER? JB RPOS20 ;NO PROBLEM MOV SI,WORD PTR [DI+BFRST] ;START OF BUFFER RPOS20: MOV WORD PTR [DI+BFRNI],SI ;NEW INPUT POINTER CMP SI,WORD PTR [DI+BFRNO] ;EMPTY NOW? JNZ RPOS90 ;NO AND WORD PTR [BX+CBFLG],NOT SFITP ;TURN OFF POST FLAG RPOS90: STI ;ALLOW INTERRUPTS AGAIN POP DI POP SI CLC ;SHOW GOOD RETURN RET ;WRITE ONE CHAR TO INTER-TASK BUFFER AND POST TASK WPOST: PUSH AX PUSH DX PUSH SI PUSH DI ;SET DI TO LCB WITH LINE NUMBER IN AH CMP AH,DS:MAXTSK ;INVALID LINE NUMBER? JC WPOS00 ;NO PROBLEM ERR 501H ;BOMB WPOS00: XOR DX,DX ;WORK REG MOV DL,AH ;LINE NUMBER INC DX ;ALLOW FOR TASK COUNT SHL DX,1 ;CONVERT TO OFFSET ADD DX,OFFSET TSKCNT ;POINT TO TCB LIST MOV DI,DX ;NEED INDEX REG MOV DI,WORD PTR [DI] ;GET TCB ADDRESS WPOS30: PUSH DI CLI ;TIME SENSITIVE ROUTINE MOV SI,WORD PTR [DI+CBTBA] ;INTER-TASK BUFFER MOV DI,WORD PTR [SI+BFRNO] ;NEXT OUTPUT POSITION MOV [DI],AL ;STORE IN BUFFER INC DI MOV DX,DI ;NEXT BUFFER POSITION POP DI ;LCB CMP DX,WORD PTR [SI+BFRND] ;END OF BUFFER? JNZ WPOS40 ;NO PROBLEM MOV DX,WORD PTR [SI+BFRST] ;START OF BUFFER WPOS40: CMP DX,WORD PTR [SI+BFRNI] ;BUFFER FULL? JNZ WPOS50 ;NO PROBLEM STC ;BUFFER FULL JMP SHORT WPOS92 ;EXIT WPOS50: MOV WORD PTR [SI+BFRNO],DX ;UPDATE OUTPUT POINTER OR WORD PTR [DI+CBFLG],SFITP ;INTER-TASK POST MOV SI,WORD PTR [DI+CBWRD] ;TASK WAITING FOR READ OR SI,SI ;ANYONE? JZ WPOS90 ;NO MOV WORD PTR [SI],0 ;POST TASK WPOS90: CLC ;GOOD COMPLETION WPOS92: STI ;NO LONGER TIME CRITICAL POP DI POP SI POP DX POP AX RET TPOST: PUSH DI PUSH SI MOV DI,WORD PTR [BX+CBTBA] ;BUFFER CTL BLOCK MOV SI,WORD PTR [DI+BFRNI] ;NEXT INPUT CHAR CMP SI,WORD PTR [DI+BFRNO] ;NEXT OUTPUT CHAR POP SI POP DI RET TIMRTN: CALL ILINEB ;GET LINE BUFFER CALL BLANKF ;INIT TO BLANKS MOV AX,188 ;'IT IS NOW CALL MOVMSG ;PUT IN STRING CALL TIMASC ;INSERT TIME CALL WRMSG ;WRITE TO TERMINAL CALL BLANKF ;INIT TO BLANKS MOV AX,187 ;'YOU HAVE BEEN CALL MOVMSG ;MOVE TO BUFFER CALL ELPASC ;INSERT ELAPSED TIME CALL WRMSG ;WRITE TO TERMINAL RET TIMASC: PUSH DI CALL DOSTIM ;GET DOS TIME CMP CH,0 ;MIDNIGHT? JNZ TIMA05 ;NO MOV CH,24 ;FORCE 12 HOUR SYSTEM TIMA05: PUSH CX ;NEED HOURS LATER CMP CH,12 ;PAST NOON? JLE TIMA10 ;NO SUB CH,12 ;USE 12 HOUR NOTATION TIMA10: CALL TIMHM MOV AL,':' CALL APPBYT ;ADD TO STRING MOV AL,DH ;SECONDS CBW MOV CX,8002H ;FORCE LEADING ZERO CALL BINASC ;PUT IN STRING MOV AL,' ' CALL APPBYT ;ADD SPACE MOV AX,189 ;ASSUME AM POP CX ;ORIGINAL HOURS CMP CH,11 ;BEFORE NOON? JLE TIMA20 ;AM CMP CH,24 ;MIDNIGHT? JZ TIMA20 ;ALSO AM MOV AX,190 ;PM TIMA20: CALL MOVMSG ;APPEND TO STRING POP DI RET TIMHM: MOV AL,CH ;HOURS CBW PUSH CX MOV CX,2 ;STRING LENGTH MUST BE EXACT CALL BINASC ;PUT IN STRING MOV AL,':' CALL APPBYT ;ADD DELIMITER POP CX MOV AL,CL ;MINUTES CBW MOV CX,8002H ;FORCE LEADING ZERO CALL BINASC ;PUT IN STRING RET DATASC: CALL DOSDAT ;GET DATE DTEASC: PUSH CX ;SAVE YEAR MOV AL,DH ;MONTH CBW MOV CX,8002H ;FORCE LEADING ZEROS CALL BINASC ;PUT IN STRING MOV AL,'-' ;DELIMITER CALL APPBYT ;ADD TO STRING MOV AL,DL ;DAY OF MONTH CBW MOV CX,8002H ;FORCE LEADING ZEROS CALL BINASC ;PUT IN STRING MOV AL,'-' ;DELIMITER CALL APPBYT ;ADD TO STRING POP AX ;YEAR SUB AX,1900 ;JUST KEEP 2 DIGITS MOV CX,8002H ;FORCE LEADING ZEROS CALL BINASC ;PUT IN STRING RET DOSTIM: MOV AH,2CH ;GET TIME REQUEST INT 21H ;DOS REQUEST MOV DS:MSGCKPT+MLTIME,CX ;HOUR & MINUTE MOV DS:MSGCKPT+MLTIME+2,DX ;SECONDS RET DOSDAT: MOV AH,2AH ;GET DATE REQUEST INT 21H ;DOS REQUEST MOV DS:MSGCKPT+MLDATE,CX ;YEAR MOV DS:MSGCKPT+MLDATE+2,DX ;MONTH & DAY RET ELPASC: CALL ELPTIM ;GET ELAPSED TIME OR CH,CH ;ANY HOURS? JZ ELPA10 ;NO MOV AL,CH ;HOURS CBW CALL BINASP ;PUT HOURS IN STRING MOV AX,191 ;'HOURS CALL MOVMSG ;MOVE TO STRING ELPA10: OR CL,CL ;ANY MINUTES? JZ ELPA20 ;NO MOV AL,CL ;MINUTES CBW CALL BINASP ;PUT MINUTES IN STRING MOV AX,192 ;'MINUTES CALL MOVMSG ;MOVE TO STRING ELPA20: MOV AL,DH ;SECONDS CBW CALL BINASP ;PUT SECONDS IN STRING MOV AX,193 ;'SECONDS CALL MOVMSG ;PUT IN STRING RET ELPTIM: CALL DOSTIM ;GET CURRENT TIME MOV AX,WORD PTR [BX+USRSEC] ;TIME ON - SECONDS SUB DL,AL JNC ELPT10 ;NO PROBLEM ADD DL,100 ELPT10: SBB DH,AH ;SECONDS JNC ELPT20 ;NO PROBLEM ADD DH,60 ELPT20: MOV AX,WORD PTR [BX+USRMH] ;TIME ON - HOURS/MINUTES SBB CL,AL ;MINUTES JNC ELPT30 ;NO PROBLEM ADD CL,60 ELPT30: SBB CH,AH ;HOURS JNC ELPT40 ;NO PROBLEM ADD CH,24 ELPT40: RET TIMON: CALL DOSTIM ;GET CURRENT TIME MOV WORD PTR [BX+USRSEC],DX ;SAVE SECONDS MOV WORD PTR [BX+USRMH],CX ;SAVE HOURS/MINUTES RET ;CLEAR INTER-TASK BUFFER CLRITB: PUSH AX PUSH SI MOV SI,WORD PTR [BX+CBTBA] ;BUFFER CONTROL BLOCK OR SI,SI ;BUFFER EXIST? JZ CLRITX ;NO MOV AX,WORD PTR [SI+BFRNO] ;END OF CURRENT INPUT MOV WORD PTR [SI+BFRNI],AX ;FLUSH BUFFER AND WORD PTR [BX+CBFLG],NOT SFITP ;CLEAR INTER-TASK POST CLRITX: POP SI POP AX RET ;CLEAR COMMUNICATIONS INPUT BUFFER CLRIBF: PUSH AX PUSH SI MOV SI,WORD PTR [BX+CBIBA] ;BUFFER CONTROL BLOCK OR SI,SI ;BUFFER EXIST? JZ CLRIBX ;NO -MUST BE CONSOLE CLI ;NO INTERRUPTS NOW MOV AX,WORD PTR [SI+BFRNI] ;END OF CURRENT INPUT MOV WORD PTR [SI+BFRNO],AX ;FLUSH BUFFER STI ;INTERRUPTS OK CLRIBX: POP SI POP AX RET ;CLEAR COMMUNICATIONS OUTPUT BUFFER CLROBF: PUSH AX PUSH SI MOV SI,WORD PTR [BX+CBOBA] ;BUFFER CONTROL BLOCK OR SI,SI ;BUFFER EXIST? JZ CLROBX ;NO -MUST BE CONSOLE CLI ;NO INTERRUPTS NOW MOV AX,WORD PTR [SI+BFRNO] ;END OF CURRENT INPUT MOV WORD PTR [SI+BFRNI],AX ;FLUSH BUFFER STI ;INTERRUPTS OK CLROBX: POP SI POP AX RET CKCTXX: CLC ;SHOW OK POP AX RET CKCTLK: PUSH AX CALL CONT ;ANY INPUT JZ CKCTXX ;NO CALL CONR ;GET INPUT AND AL,7FH ;CLEAR PARITY (JUST IN CASE) CMP AL,11 ;ABORT REQUEST? JNZ CKCTXX ;NO CALL CLROBF ;FLUSH OUTPUT BUFFER STC ;SHOW ABORT REQUEST POP AX RET ;WAIT FOR COMMUNICATIONS OUTPUT BUFFER TO EMPTY WTBUFE: PUSH SI PUSH DI PUSH AX PUSH DX MOV SI,WORD PTR [BX+CBOBA] ;OUTPUT BUFFER CONTROL BLOCK OR SI,SI ;EXIST? JZ WTBUFX ;NO - MUST BE CONSOLE WTBU00: TEST WORD PTR [BX+CBFLG],SFLC ;LOST CARRIER? JZ WTBU10 ;NO PROBLEM CALL CLROBF ;CLEAR OUTPUT BUFFER JMP WTBUFX ;EXIT WTBU10: CLI ;NO INTERRUPTS DURING TEST MOV DI,WORD PTR [SI+BFRNI] ;NEXT CHAR TO SEND CMP DI,WORD PTR [SI+BFRNO] ;EMPTY? JZ WTBUFX ;YES - DON'T WAIT MOV DX,WORD PTR [BX+CBMBA] ;MODEM BASE ADDRESS ADD DX,5 ;LINE STATUS REG IN AL,DX ;GET STATUS TEST AL,20H ;TRANSMITTER AVAILABLE? JZ WTBU20 ;NO - WAIT TEST BYTE PTR [BX+CBMSR],MSRCTS ;OK TO SEND? JZ WTBU20 ;NO - WAIT MOV DX,WORD PTR [BX+CBMBA] ;TRANSMITTER HOLDING REGISTER MOV AL,BYTE PTR [DI] ;CHAR TO SEND OUT DX,AL ;WRITE TO LINE INC DI ;NEXT BUFFER POSITION CMP DI,WORD PTR [SI+BFRND] ;END OF BUFFER? JNZ WTBU15 ;NO PROBLEM MOV DI,WORD PTR [SI+BFRST] ;START OF BUFFER WTBU15: MOV WORD PTR [SI+BFRNI],DI ;UPDATE POINTER JMP WTBU00 ;NOW EMPTY? WTBU20: MOV WORD PTR [BX+CBWWT],BX ;REQUEST POST MOV WORD PTR [BX+CBRTC],18 ;SHORT TIMEOUT AND WORD PTR [BX+CBFLG],NOT SFTO ;CLEAR TIME OUT CALL WAITRT ;WAIT FOR POST ;FOLLOWING LABEL USED FOR STATUS MESSAGE WTBUF3: MOV WORD PTR [BX+CBWWT],0 ;ACKNOWLEDGE POST JMP WTBU00 ;NOW EMPTY? WTBUFX: STI ;INTERRUPTS OK AGAIN POP DX POP AX POP DI POP SI RET ;PRINT FULL MENU PSMENU: CALL TSYSOP ;SYSOP? JZ PSMEN1 ;NO MOV AX,20 ;SYSOP LONG MENU CALL WMSGNO ;DISPLAY MENU PSMEN1: MOV AX,22 ;USER LONG MENU CALL WMSGNO ;PRINT MENU RET ;PRINT EXPERT MENU PUMENU: CALL TSYSOP ;SYSOP? JZ PUMEN1 ;NO MOV AX,21 ;SYSOP SHORT MENU CALL WMSGNO ;DISPLAY MENU PUMEN1: MOV AX,23 ;USER SHORT MENU CALL QMSGNO ;DISPLAY MENU RET ;TEST EXPERT MODE TXPRT: PUSH SI MOV SI,WORD PTR [BX+USRST] ;SIGN ON RECORD TEST WORD PTR [SI+UEOPTS],4 ;EXPERT MODE? POP SI RET ;TEST FOR SYSOP TSYSOP: PUSH SI MOV SI,WORD PTR [BX+USRST] ;SIGNON ENTRY TEST BYTE PTR [SI+UESTAT],20H ;SYSOP? POP SI RET ;TEST FOR SYSOP OR ASSISTANT TAYSOP: PUSH SI MOV SI,WORD PTR [BX+USRST] ;SIGNON ENTRY TEST BYTE PTR [SI+UESTAT],30H ;SYSOP OR ASST? POP SI RET ;TEST FOR SIGOP OF SECTION IN AX TSIGOP: PUSH SI MOV SI,WORD PTR [BX+USRST] ;SIGNON ENTRY TEST BYTE PTR [SI+UESTAT],30H ;SYSOP OR ASST? JZ TSIG20 ;NO TEST WORD PTR DS:MSGCKPT+MDSIGS,AX ;SIG EXIST? JZ TSIG10 ;NO - MUST SEE TEST WORD PTR [SI+UESECT],AX ;WANT TO SEE THIS SECTION? JMP SHORT TSIG90 ;RETURN RESULT TSIG10: DEC SI ;SET NON-ZERO JMP SHORT TSIG90 ;RETURN RESULT TSIG20: TEST BYTE PTR [SI+UESTAT],1 ;SIGOP? JZ TSIG90 ;NO AND AX,WORD PTR DS:MSGCKPT+MDSIGS ;VALID SIGS TEST WORD PTR [SI+UESIGS],AX ;OF THIS SIG? TSIG90: POP SI RET ;PRINT REMAINING TIME PTIME: CALL ELPTIM ;GET ELAPSED TIME MOV AH,60 ;MIN/HOUR MOV AL,CH ;HOURS MUL AH ;CONVERT TO MINUTES XOR CH,CH ;CBW ADD AX,CX ;TOTAL MINUTES ELAPSED MOV CX,WORD PTR [BX+USRLMT] ;ALLOWED TIME SUB CX,AX ;TIME REMAINING JNC PTIM13 ;OK XOR CX,CX ;DONT ALLOW NEGATIVE PTIM13: PUSH DI MOV DI,WORD PTR [BX+USRST] ;USER LOGON RECORD TEST BYTE PTR [DI+UESTAT],2 ;FIXED TIME ALLOCATION? JNZ PTIM15 ;YES MOV WORD PTR [DI+UERTIM],CX ;RESIDUAL TIME PTIM15: POP DI CALL TAYSOP ;PRIVILEDGED USER? JZ PTIM18 ;NO RET ;DON'T ENFORCE TIME LIMIT PTIM18: OR CX,CX ;ANY TIME LEFT? JNZ PTIM20 ;PRINT REMAINING TIME POP AX ;KILL RETURN ADDRESS MOV AL,10H ;SHOW OUT OF TIME CALL SCAUSE ;MARK IN USER RECORD JMP GDBY00 ;LOG USER OFF PTIM20: CALL ILINEB ;GET LINE BUFFER MOV AX,194 ;'TIME REMAINING CALL MOVMSG ;PUT IN BUFFER MOV AX,CX ;REMAINING TIME CALL BINASP ;PUT TIME IN STRING MOV AX,192 ;'MINUTES CALL MOVMSG ;PUT IN BUFFER CALL WRMSG ;WRITE TO SCREEN CALL FRELBF ;FREE TERMINAL BUFFER RET ;SHOW LOGOFF REASON IN USER RECORD SCAUSE: PUSH SI MOV SI,WORD PTR [BX+USRST] ;USER RECORD AND BYTE PTR [SI+UESTAT2],NOT 30H ;CLEAR OLD STATUS OR BYTE PTR [SI+UESTAT2],AL ;SET NEW STATUS POP SI RET ;PRINT USER STATISTICS PUSTAT: CALL ILINEB ;FORMAT BUFFER MOV AX,207 ;# OF CALLERS CALL MOVMSG MOV AX,DS:MSGCKPT+MLASTCN ;CALLER NUMBER CALL BINASP CALL WRMSG ;WRITE TO TERMINAL CALL ILINEB ;FORMAT BUFFER MOV AX,208 ;ACTIVE MSGS CALL MOVMSG MOV AX,DS:MSGCKPT+MIACTM ;ACTIVE MSGS CALL BINASP CALL WRMSG ;WRITE TO TERMINAL JC PUST90 ;NO MORE MOV SI,WORD PTR [BX+USRST] ;USER STATS MOV AX,WORD PTR [SI+UEHMSG] ;LAST MESSAGE NUMBER OR AX,AX ;ANYTHING? JZ PUST10 ;NO - DON'T REPORT CALL ILINEB ;FORMAT BUFFER PUSH AX MOV AX,209 ;LAST MSG READ CALL MOVMSG POP AX CALL BINASP CALL WRMSG JC PUST90 ;NO MORE PUST10: MOV DI,DS:MSGCKPT+MILAST PUSH BX MOV BX,MSGINX1 ;NUMBER INDEX MOV AX,[BX+DI] ;LAST MESSAGE NUMBER POP BX CALL ILINEB ;FORMAT BUFFER PUSH AX MOV AX,210 ;LAST MSG CALL MOVMSG POP AX CALL BINASP CALL WRMSG PUST90: CLC RET ;WRITE LINE TO CALLERS LOG ; BP-2 FILE DATA BUFFER ; BP-4 FILE NAME BUFFER ; BP-6 PASSED DATA STRING LOGDSK: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;CREATE LOCAL FRAME SUB SP,6 ;ALLOCATE LOCAL STORAGE PUSH CX PUSH DX PUSH DI MOV [BP-6],SI ;PASSED DATA STRING CALL STRIP ;NO TRAILING BLANKS MOV AX,WORD PTR [SI-2] ;CURRENT LENGTH ADD AX,27 ;LENGTH FOR TIME STAMP MOV DI,SI ;STRING TO LOG CALL GETBUF ;GET NEW BUFFER MOV [BP-2],SI ;FILE DATA BUFFER CALL BLANKF ;BLANK BUFFER MOV AX,WORD PTR [BX+USRLN] ;LINE NUMBER ADD AL,'0' ;CONVERT TO ASCII CALL APPBYT ;ADD TO STRING INC WORD PTR [SI-2] ;LEAVE ONE BLANK CALL DATASC ;DATE STAMP INC WORD PTR [SI-2] ;LEAVE ONE BLANK CALL TIMASC ;TIME STAMP INC WORD PTR [SI-2] ;LEAVE ONE BLANK CALL MOVSTR ;COPY STRING PUSH SI ;BUFFER ADDRESS MOV AX,80 ;BUFFER LENGTH CALL GETBUF ;GET WORK BUFFER MOV [BP-4],SI ;FILE NAME BUFFER MOV DI,OFFSET CALLRN ;CALLERS FILE CALL MVZSTR ;MOVE FILE NAME PUSH SI ;FILE NAME CALL APPDSK ;APPEND TO DISK FILE JNC LOGD10 ;GOOD WRITE ERR 10H ;APPEND FAILED LOGD10: MOV SI,[BP-2] ;FILE DATA BUFFER CALL FREBUF ;FREE TEMPORARY BUFFER MOV SI,[BP-4] ;FILE NAME BUFFER CALL FREBUF ;FREE TEMPORARY BUFFER MOV SI,[BP-6] ;PASSED DATA STRING POP DI POP DX POP CX MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET ;LOG CALL PROGRESS MESSAGE LOGCP: TEST DS:MSGCKPT+MSOPTS,10H ;LOGGING ON? JZ LOGCPX ;NO CALL ILINEB ;INITIALIZE BUFFER CALL MOVMSG ;MOVE TO BUFFER CALL LOGDSK ;LOG ERROR LOGCPX: RET ;MOVE MESSAGE FROM DATA BASE TO BUFFER MOVMSG: PUSH DI CALL GETMSG ;GET MESSAGE IN BUFFER CALL MOVSTR ;MOVE TO TARGET BUFFER XCHG SI,DI ;SWAP FOR FREBUF CALL FREBUF ;FREE STRING XCHG SI,DI ;RESTORE POP DI RET ;MOVE CONSTANT STRING IN DS:DI TO BUFFER IN DS:SI MOVSTR: PUSH CX MOV CX,WORD PTR [DI-2] ;LENGTH JCXZ MOVS99 ;EMPTY STRING MOVS10: PUSH DI PUSH AX PUSH DX MOV DX,WORD PTR [SI-2] ;CURRENT TARGET LENGTH MOV AX,DX ADD AX,CX ;NEW TARGET LENGTH PUSH AX ;SAVE NEW DATA LENGTH ADD AX,8 ;ALLOW FOR HEADER CMP AX,WORD PTR [SI-6] ;MAX LENGTH POP AX ;NEW DATA LENGTH JBE MOVS20 ;NO PROBLEM PUSH CX ;LENGTH TO MOVE MOV CX,AX ;NEW TOTAL LENGTH CALL PADB ;EXTEND BUFFER CALL STRIP ;ADJUST LENGTH POP CX ;LENGTH TO MOVE MOVS20: MOV WORD PTR [SI-2],AX ;NEW LENGTH PUSH SI ADD SI,DX ;CURRENT END OF STRING XCHG SI,DI ;STRING CONVENTION JCXZ MOVS90 MOVS21: LODSB MOV [DI],AL INC DI LOOP MOVS21 MOVS90: POP SI POP DX POP AX POP DI MOVS99: POP CX RET ;MOVE DS:VARIABLE STRING TO BUFFER MOVSTL: PUSH CX JMP MOVS10 ;ENTER COMMON LOGIC ;MOVE ES:CONSTANT STRING TO BUFFER MVCSTR: PUSH CX MOV CX,WORD PTR ES:[DI-2] ;LENGTH MVCS10: PUSH DI PUSH AX PUSH DX MOV DX,WORD PTR [SI-2] ;CURRENT TARGET LENGTH MOV AX,DX ADD AX,CX ;NEW TARGET LENGTH PUSH AX ;SAVE NEW DATA LENGTH ADD AX,8 ;ALLOW FOR HEADER CMP AX,WORD PTR [SI-6] ;MAX LENGTH POP AX ;NEW DATA LENGTH JBE MVCS20 ;NO PROBLEM PUSH CX ;LENGTH TO MOVE MOV CX,AX ;NEW TOTAL LENGTH CALL PADB ;EXTEND BUFFER CALL STRIP ;ADJUST LENGTH POP CX ;LENGTH TO MOVE MVCS20: MOV WORD PTR [SI-2],AX ;NEW LENGTH PUSH SI ADD SI,DX ;CURRENT END OF STRING JCXZ MVCS90 MVCS21: MOV AL,ES:[DI] INC DI MOV [SI],AL INC SI LOOP MVCS21 MVCS90: POP SI POP DX POP AX POP DI POP CX RET ;MOVE ES:DI VARIABLE STRING TO BUFFER MVLSTR: PUSH CX JMP MVCS10 ;ENTER COMMON LOGIC ;MOVE ES:DI ZERO TERMINATED STRING TO BUFFER MVZSTR: PUSH CX PUSH AX PUSH DI XOR AX,AX ;NULL XOR CX,CX ;CLEAR COUNT MVZS10: CMP ES:[DI],AL ;END OF STRING? JZ MVZS20 ;YES INC CX ;COUNT CHAR INC DI ;POINT TO NEXT JMP MVZS10 ;TEST NEXT CHAR MVZS20: INC CX ;COPY DELIMITER POP DI POP AX JMP MVCS10 ;ENTER COMMON LOGIC ;APPEND ONE CHAR TO STRING IN [SI] ; BP-2 STRING POINTER ; BP-4 CHARACTER TO APPEND APPBYT: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,4 ;ALLOCATE LOCAL STORAGE MOV [BP-2],SI ;SAVE STRING POINTER MOV [BP-4],AX ;APPEND CHARACTER MOV AX,WORD PTR [SI-2] ;CURRENT LENGTH PUSH AX ;DATA LENGTH ADD AX,8 ;ALLOW FOR HEADER CMP AX,WORD PTR [SI-6] ;MAXIMUM LENGTH POP AX ;DATA LENGTH JB APPB20 ;NO PROBLEM PUSH CX MOV CX,WORD PTR [SI-2] ;CURRENT LENGTH SHR CX,1 ;DIVIDE BY TWO SHR CX,1 ;HAVE NOW DIVIDED BY FOUR INC CX ;ROUND UP ADD CX,WORD PTR [SI-2] ;125% OF CURRENT LENGTH CALL PADB ;EXTEND STRING MOV [BP-2],SI ;CHANGED BY PADB CALL STRIP ;TRIM TO CURRENT LENGTH POP CX APPB20: INC WORD PTR [SI-2] ;NEW LENGTH ADD SI,AX ;END OF STRING MOV AX,[BP-4] ;CHAR TO APPEND MOV BYTE PTR [SI],AL ;APPEND CHAR MOV SI,[BP-2] ;STRING POINTER MOV SP,BP ;FREE LOCAL STORAGE POP BP RET ;COMPARE TWO STRINGS IN DS FOR EXACT MATCH CMPSTA: PUSH CX MOV CX,WORD PTR [SI-2] ;SOURCE STRING LENGTH CMP CX,WORD PTR [DI-2] ;OBJECT STRING LENGTH POP CX JZ CMPSTR ;GO CHECK CONTENTS RET ;NOT EQUAL ;COMPARE TWO STRINGS FOR LENGTH OF SECOND STRING CMPSTR: PUSH CX PUSH SI PUSH DI MOV CX,WORD PTR [DI-2] ;LENGTH PUSH ES PUSH DS POP ES REPZ CMPSB ;COMPARE STRINGS POP ES POP DI POP SI POP CX RET ;COMPARE TWO STRINGS IN DS:[SI] ES:[DI] FOR EXACT MATCH CPCSTA: PUSH CX MOV CX,WORD PTR [SI-2] ;SOURCE STRING LENGTH CMP CX,WORD PTR ES:[DI-2] ;OBJECT STRING LENGTH POP CX JZ CPCSTR ;GO CHECK CONTENTS RET ;NOT EQUAL ;COMPARE TWO STRINGS FOR LENGTH OF SECOND STRING CPCSTR: PUSH AX PUSH CX PUSH SI PUSH DI MOV CX,WORD PTR ES:[DI-2] ;LENGTH CPCS10: LODSB ;GET NEXT CHAR CMP AL,ES:[DI] ;COMPARE JNZ CPCS20 ;NOT EQUAL INC DI ;POINT TO NEXT LOOP CPCS10 ;COMPARE REST OF STRING CMP AL,AL ;INC SETS NZ CPCS20: POP DI POP SI POP CX POP AX RET ;DETERMINE NUMBER OF PHYSICAL LINES A STRING NEEDS LINCNT: PUSH CX PUSH DI MOV AX,1 ;ASSUME ONE LINE MOV CX,[SI-2] ;STRING LENGTH MOV DI,SI ;WORK REG LINC10: CMP BYTE PTR [DI],13 JZ LINC20 CMP BYTE PTR [DI],12 JZ LINC20 CMP BYTE PTR [DI],10 JZ LINC20 LINC15: INC DI ;NEXT CHAR LOOP LINC10 ;CHECK IT JMP LINC90 ;DONE LINC20: INC AX ;COUNT LINE JMP LINC15 LINC90: POP DI POP CX RET ;TRANSLATE STRING TO UPPER CASE XLATE: PUSH SI PUSH CX PUSH AX MOV CX,WORD PTR [SI-2] ;CURRENT DATA LENGTH JCXZ XLATX ;EMPTY STRING XLAT1: AND BYTE PTR [SI],7FH ;REMOVE PARITY BIT CMP BYTE PTR [SI],'a' ;LC ALPHA? JB XLAT2 ;NO CMP BYTE PTR [SI],'z' ;LC ALPHA JA XLAT2 ;NO AND BYTE PTR [SI],0DFH ;TRANSLATE XLAT2: INC SI LOOP XLAT1 XLATX: POP AX POP CX POP SI RET ;INITIALIZE LINE BUFFER ILINEB: MOV SI,WORD PTR [BX+USRLB] ;GET BUFFER ADDRESS OR SI,SI ;DOES IT EXIST? JNZ ILIN10 ;YES PUSH AX MOV AX,128 ;BUFFER LENGTH CALL GETBUF ;ALLOCATE IT MOV WORD PTR [BX+USRLB],SI ;SAVE ADDRESS POP AX ILIN10: CALL BLANKF ;INIT TO BLANKS RET ;FREE LINE BUFFER FRELBF: MOV SI,WORD PTR [BX+USRLB] ;BUFFER ADDRESS MOV WORD PTR [BX+USRLB],0 ;SHOW FREE CALL FREBUF RET ;FREE COMMAND BUFFER FRECMD: PUSH SI MOV SI,WORD PTR [BX+USRCMD] ;COMMAND BUFFER ADDRESS MOV WORD PTR [BX+USRCMD],0 ;SHOW FREE CALL FREBUF ;FREE COMMAND BUFFER POP SI RET ;INITIALIZE STRING TO ALL BLANKS BLANKF: PUSH CX PUSH SI MOV CX,WORD PTR [SI-6] ;STRING LENGTH SUB CX,QEDTA ;LESS HEADER MOV WORD PTR [SI-2],0 ;SET CURRENT LENGTH = 0 CALL PADB ;PAD WITH BLANKS MOV WORD PTR [SI-2],0 ;SET CURRENT LENGTH TO ZERO POP SI POP CX RET ;PAD STRING WITH BLANKS TO LENGTH IN CX ; BP-2 STRING ADDRESS ; BP-4 TARGET LENGTH ; BP-6 NEW STRING ADDRESS PADB: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,6 ;ALLOCATE LOCAL STORAGE PUSH DI PUSH AX PUSH CX PUSH ES PUSH DS POP ES ;DS=ES FOR STRING CMDS MOV [BP-2],SI ;STRING ADDRESS MOV [BP-4],CX ;SAVE TARGET LENGTH MOV AX,WORD PTR [SI-6] ;LENGTH OF STRING SUB AX,QEDTA ;LESS HEADER CMP AX,[BP-4] ;LARGE ENOUGH? JAE PADB10 ;YES MOV AX,CX ;DESIRED LENGTH CALL GETBUF ;GET LARGER BUFFER MOV [BP-6],SI ;NEW STRING ADDRESS MOV DI,SI ;TARGET STRING MOV SI,[BP-2] ;ORIGINAL STRING MOV CX,WORD PTR [SI-2] ;LENGTH TO MOVE MOV WORD PTR [DI-2],CX ;STRING LENGTH PUSH ES PUSH DS POP ES REP MOVSB ;COPY STRING POP ES MOV SI,[BP-2] ;OLD STRING ADDRESS CALL FREBUF ;FREE OLD STRING MOV DI,[BP-6] ;NEW STRING ADDRESS MOV [BP-2],DI ;UPDATE STRING POINTER CMP SI,WORD PTR [BX+USRLB] ;WAS IT LINE BUFFER? JNZ PADB03 ;NO MOV WORD PTR [BX+USRLB],DI ;UPDATE LINE BUFFER ADDRESS JMP SHORT PADB10 PADB03: CMP SI,WORD PTR [BX+USRCMD] ;WAS IT COMMAND BUFFER? JNZ PADB10 ;NO MOV WORD PTR [BX+USRCMD],DI ;UPDATE COMMAND BUFFER ADDRESS PADB10: MOV SI,[BP-2] ;STRING ADDRESS MOV CX,WORD PTR [SI-2] ;DATA LENGTH MOV AX,[BP-4] ;TARGET LENGTH MOV WORD PTR [SI-2],AX ;SET TARGET DATA LENGTH CMP CX,AX ;OVER LIMIT? JAE PADB20 ;YES - JUST TRUNCATE MOV DI,SI ;DESTINATION STRING ADD DI,CX ;POINT PAST DATA SUB AX,CX ;NUMBER OF BLANKS MOV CX,AX ;TO LOOP REGISTER MOV AL,' ' ;BLANK PUSH ES PUSH DS POP ES REP STOSB ;BLANK FILL POP ES PADB20: POP ES POP CX POP AX POP DI MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME RET ;TRUNCATE TRAILING BLANKS STRIP: PUSH DI PUSH CX MOV CX,WORD PTR [SI-2] ;CURRENT DATA LENGTH MOV DI,SI ;START OF DATA ADD DI,CX ;POINT PAST DATA STR10: DEC DI ;PREVIOUS CHAR CMP BYTE PTR [DI],' ' ;TRAILING BLANK? JNZ STR20 ;NO - DONE LOOP STR10 ;KEEP TRYING STR20: MOV WORD PTR [SI-2],CX ;NEW DATA LENGTH POP CX POP DI RET ;STRIP LEADING BLANKS LALIGN: FRAME PUSH AX PUSH SI PUSH DI PUSH CX MOV CX,WORD PTR [SI-2] ;CURRENT DATA LENGTH MOV DI,SI ;START OF DATA LALI10: CMP BYTE PTR [DI],' ' ;TRAILING BLANK? JNZ LALI20 ;NO - DONE INC DI ;NEXT POSITION LOOP LALI10 ;KEEP TRYING LALI20: CMP SI,DI ;ANYTHING? JZ LALI90 ;NO - EXIT MOV AX,WORD PTR [SI-2] ;ORIGINAL LENGTH MOV WORD PTR [SI-2],CX ;NEW DATA LENGTH XCHG SI,DI ;FOR MOVSB PUSH ES PUSH DS POP ES REP MOVSB POP ES LALI90: POP CX POP DI POP SI POP AX EXITF ;APPEND STRING TO END OF FILE - BINARY MODE APPDSB: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;LOCAL FRAME SUB SP,4 ;LOCAL STORAGE MOV WORD PTR [BP-4],1 ;BINARY MODE JMP SHORT APPD00 ;COMMON CODE ;APPEND STRING TO END OF FILE - CREATE FILE IF NECESSARY ; BP+6 STRING ADDRESS ; BP+4 FILE NAME STRING (DS) ; BP-2 FILE HANDLE ; BP-4 FLAGS APPDSK: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,4 ;ALLOCATE LOCAL STORAGE MOV WORD PTR [BP-4],0 ;ASCII MODE APPD00: PUSH DI PUSH AX PUSH CX PUSH DX MOV SI,[BP+6] ;STRING ADDRESS TEST WORD PTR [BP-4],1 ;BINARY MODE? JNZ APPD01 MOV AX,205 ;CR/LF/EOF CALL MOVMSG MOV [BP+6],SI ;MOVE CAN CHANGE SI APPD01: MOV AX,3D01H ;OPEN FOR OUTPUT MOV DX,[BP+4] ;FILE NAME STRING INT 21H ;DOS FUNCTION CALL JNC APPD20 ;OPEN OK CMP AX,2 ;NOT FOUND? JNZ APPD10 ;WORSE THAN THAT MOV AH,3CH ;CREATE FILE XOR CX,CX ;NORMAL FILE ATTRIBUTES INT 21H ;DOS REQUEST JC APPD10 ;CAN NOT CREATE MOV [BP-2],AX ;FILE HANDLE JMP SHORT APPD30 ;GO WRITE APPD10: STC ;SHOW ERROR JMP APPD50 ;EXIT APPD20: MOV [BP-2],AX ;FILE HANDLE XOR CX,CX ;EOF TEST WORD PTR [BP-4],1 ;BINARY MODE? JNZ APPD22 ;YES DEC CX ;EOF -1 APPD22: MOV AX,4202H ;SEEK END OF FILE PUSH BX MOV BX,[BP-2] ;FILE HANDLE MOV DX,CX ;FILE OFFSET INT 21H ;DOS CALL POP BX JNC APPD24 ;SEEK OK STC ;SHOW ERROR JMP APPD50 ;EXIT APPD24: OR DX,DX ;FILE POSITION NEGATIVE? JNS APPD30 ;NO PROBLEM XOR CX,CX ;START OF FILE JMP APPD22 ;GO SEEK APPD30: MOV AH,40H ;WRITE FILE PUSH BX MOV BX,[BP-2] ;FILE HANDLE MOV CX,WORD PTR [SI-2] ;DATA LENGTH MOV DX,SI ;DATA ADDRESS INT 21H ;DOS FUNCTION CALL POP BX JC APPD50 ;HARD ERROR CMP AX,CX ;WRITE ALL BYTES? JZ APPD40 ;YES ;OUT OF SPACE ROUTINE GOES HERE APPD40: MOV AH,3EH ;CLOSE FILE PUSH BX MOV BX,[BP-2] ;FILE HANDLE INT 21H ;DOS FUNCTION CALL POP BX JNC APPD50 ;CLOSE OK STC APPD50: POP DX POP CX POP AX POP DI MOV SI,[BP+6] ;PASSED DATA STRING MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLERS FRAME RET 4 ;FREE PASSED PARMS ;GET MESSAGE FROM MESSAGE FILE AND PUT INTO DI -> BUFFER GETMSG: PUSH AX PUSH CX PUSH SI PUSH DS PUSH ES MOV ES,MSGSEG ;POINT TO AREA OR AX,AX ;ZERO? JZ GETM10 ;YES - INVALID CMP AX,WORD PTR ES:[0] ;VALID NUMBER? JBE GETM20 ;VALID GETM10: POP ES PUSH AX MOV AX,80 ;BUFFER LENGTH CALL GETBUF ;GET A BUFFER MOV DI,OFFSET STR01 ;MESSAGE CALL MVCSTR ;MOVE TO BUFFER POP AX ;MESSAGE NUMBER CALL BINASP ;PUT IN BUFFER MOV DI,OFFSET STR02 ;IS NOT AVAILABLE CALL MVCSTR ;MOVE TO BUFFER CALL LOGDSK ;LOG ERROR MOV DI,SI ;RETURN BUFFER ADDRESS JMP SHORT GETM90 ;EXIT GETM20: SHL AX,1 ;CONVERT TO INDEX SHL AX,1 ;2 ENTRIES PER MSG MOV SI,AX ;MOVE TO INDEX REG MOV AX,WORD PTR ES:[SI+2] ;MESSAGE LENGTH MOV DI,WORD PTR ES:[SI] ;MESSAGE OFFSET CALL GETBUF ;GET BUFFER XCHG SI,DI ;FOR MOVE MOV CX,AX ;LENGTH MOV WORD PTR [DI-2],CX ;STORE NEW LENGTH PUSH DS PUSH ES POP DS POP ES ;EXCHANGE DS,ES PUSH DI REP MOVSB ;COPY MESSAGE POP DI POP ES GETM90: POP DS POP SI POP CX POP AX RET SENDHF: PUSH CX PUSH SI PUSH DI CALL ILINEB ;GET WORK BUFFER MOV DI,OFFSET HELPFI ;HELP FILE PREFIX CALL MVCSTR ;MOVE TO BUFFER MOV CX,8002H ;FIELD LENGTH - ZERO FILL CALL BINASC ;STORE IN FIELD XOR CX,CX ;NO PASSED PARMS PUSH CX MOV CX,WORD PTR [BX+USRST] ;USER RECORD PUSH CX PUSH SI ;PASS FILE NAME MOV AX,80 ;WORK BUFFER LENGTH CALL GETBUF ;GET BUFFER MOV DI,OFFSET HELPSPT ;SCRIPT FILE NAME CALL MVZSTR ;MOVE TO BUFFER PUSH SI ;PASS AS PARAMETER CALL RUNFIL ;INVOKE SCRIPT CALL FREBUF ;FREE WORK BUFFER SENDH1: POP DI POP SI POP CX RET UNCMD: CALL ILINEB ;GET LINE BUFFER MOV AX,160 ;SORRY CALL MOVMSG MOV DI,WORD PTR [BX+USR1N] ;1ST NAME CALL MOVSTR MOV AX,196 ;I DON'T UNDERSTAND CALL MOVMSG MOV DI,WORD PTR [BX+USRCMD] ;LAST COMMAND CMP WORD PTR [DI-2],10 ;TOO LONG FOR LINE? JLE UNCMD5 ;NO MOV WORD PTR [DI-2],10 ;LIMIT LENGTH UNCMD5: CALL MOVSTR CALL WRMSG ;DISPLAY CALL FRELBF ;FREE LINE BUFFER RET ;PURGE ALL STORAGE OWNED BY TCB PURGST: CALL FRETIO ;FREE TERMINAL INPUT AREA MOV WORD PTR [BX+USRSL],0 ;SHOW NO USER RECORD MOV WORD PTR [BX+USRST],0 ;CLEAR USER RECORD PTR MOV SI,WORD PTR [BX+USRMB] ;MESSAGE FILE BUFFER CALL FREBUF ;FEEE BUFFER MOV WORD PTR [BX+USRMB],0 ;MARK FREE CALL FRELBF ;FREE LINE BUFFER CALL FRECMD ;FREE COMMAND BUFFER ;FREE LOG-IN INFORMATION PURG1: MOV SI,WORD PTR [BX+USR1N] ;1ST NAME CALL FREBUF ;FREE IT MOV WORD PTR [BX+USR1N],0 ;MARK FREE MOV SI,WORD PTR [BX+USR2N] ;LAST NAME CALL FREBUF ;FREE IT MOV WORD PTR [BX+USR2N],0 ;MARK FREE MOV SI,WORD PTR [BX+USR3N] ;LOGON NAME CALL FREBUF ;FREE IT MOV WORD PTR [BX+USR3N],0 ;MARK FREE RET ;------------------------------------------------------ ;BUFFER MANAGEMENT ROUTINES ;------------------------------------------------------ FRETIO: CALL DQTIOA ;DEQUEUE 1ST TIOA JNC FRET10 ;FOUND ONE RET FRET10: CALL FREBUF ;FREE THIS TIOA JMP FRETIO ;CHECK NEXT TIOA ;COMMUNICATIONS CONTROL ROUTINES ST300: MOV AX,180H ;300 BAUD DIVISOR PUSH CX MOV CH,MSP003 ;300 BAUD FLAG JMP SHORT STSP10 ST1200: MOV AX,60H ;1200 BAUD DIVISOR PUSH CX MOV CH,MSP012 ;1200 BAUD FLAG JMP SHORT STSP10 ST2400: MOV AX,30H ;2400 BAUD DIVISOR PUSH CX MOV CH,MSP024 ;2400 BAUD FLAG JMP SHORT STSP10 ST4800: MOV AX,18H ;4800 BAUD DIVISOR PUSH CX MOV CH,MSP048 ;4800 BAUD FLAG JMP SHORT STSP10 ST1920: MOV AX,06H ;1920 BAUD DIVISOR PUSH CX MOV CH,MSP192 ;1920 BAUD FLAG JMP SHORT STSP10 ST3840: MOV AX,03H ;3840 BAUD DIVISOR PUSH CX MOV CH,MSP384 ;3840 BAUD FLAG JMP SHORT STSP10 ST9600: MOV AX,0CH ;9600 BAUD DIVISOR PUSH CX MOV CH,MSP096 ;9600 BAUD FLAG STSP10: CLI ;MUST STOP INTERRRUPTS AND WORD PTR [BX+DTESTAT],255-(MSP560+MSP384+MSP192+MSP096+MSP048+MSP024+MSP012+MSP003) OR BYTE PTR [BX+DTESTAT],CH ;SET APPROPRIATE FLAG PUSH AX MOV DX,WORD PTR [BX+CBMBA] ;MODEM BASE ADDRESS ADD DX,3 ;COM1 LINE CONTROL REG IN AL,DX ;GET CURRENT SETTINGS MOV CL,AL ;SAVE FOR RESTORE OR AL,80H ;SET DIVISOR LATCH ACCESS BIT OUT DX,AL POP AX SUB DX,3 ;CLOCK DIVISOR LATCH (LSB) OUT DX,AX ADD DX,3 ;LINE CONTROL REG MOV AL,CL ;ORIGINAL CONTENTS OUT DX,AL STI ;ALLOW INTERRUPTS AGAIN POP CX RET STM7B: MOV AL,1AH ;7BIT EVEN PARITY MOV AH,MPARE SHR 8 ;7 BIT FLAG JMP SHORT STSP20 STM8B: MOV AL,13H ;8 BIT NO PARITY XOR AH,AH ;TURN OFF PARITY FLAG STSP20: PUSH DX AND WORD PTR [BX+DTESTAT],NOT (MPARE+MPARO) OR BYTE PTR [BX+DTESTAT+1],AH ;SET APPROPRIATE FLAG MOV DX,WORD PTR [BX+CBMBA] ;MODEM BASE ADDRESS OR DX,DX ;VALID? JZ STSP30 ;NO ADD DX,3 ;LINE CONTROL REGISTER OUT DX,AL ;SET LINE PARAMETERS STSP30: POP DX RET RESMDM: PUSH DX OR WORD PTR [BX+CBFLG],SFDCD ;DISABLE CARRIER CHECK TEST WORD PTR [BX+CBMDM],MDMOS ;OUT OF SERVICE? JZ RESMD0 ;NO PROBLEM RESMDW: CALL WAITRT ;NO COM ADAPTER JMP RESMDW ;IGNORE TIME OUT RESMD0: MOV DX,WORD PTR [BX+CBMBA] ;MODEM BASE ADDRESS ADD DX,4 ;MODEM CONTROL REGISTER IN AL,DX ;GET CURRENT SETTING PUSH AX AND AL,0FEH ;TURN OFF DTR OUT DX,AL ;FORCE MODEM TO CMD STATE PUSH CX MOV CX,15 ;RETRY COUNT RESMD1: MOV WORD PTR [BX+CBRTC],18 ;ONE SECOND CALL WAITRT ;ALLOW TIME FOR ACTION RESMW1: MOV DX,WORD PTR [BX+CBMBA] ;MODEM BASE ADDRESS ADD DX,6 ;MODEM STATUS REG IN AL,DX MOV BYTE PTR [BX+CBMSR],AL ;SET MODEM STATUS AND AL,80H ;CARRIER DETECT JZ RESMD2 ;RESET OK TEST WORD PTR [BX+CBMDM],MDMNULL ;NULL MODEM? JNZ RESMD2 ;YES - CARRIER WON'T RESET LOOP RESMD1 ;WAIT FOR RESET RESMD2: POP CX SUB DX,2 ;MODEM CONTROL REG POP AX OR AL,1 ;TURN ON DTR OUT DX,AL ;RESTORE NORMAL MODE AND WORD PTR [BX+CBFLG],SFSNP+SFLTR+SFWINV ;CLEAR SESSION FLAGS MOV WORD PTR [BX+CBRTC],18 ;ONE SECOND CALL WAITRT ;ALLOW TIME FOR ACTION RESMW2: POP DX RET ENMDI: PUSH AX PUSH DX ADD DX,3 ;LINE CONTROL REGISTER IN AL,DX AND AL,7FH ;RESET DLAB OUT DX,AL SUB DX,2 ;INTERRUPT ENABLE REGISTER MOV AL,0FH ;ENABLE ALL INTERRUPTS OUT DX,AL ;UPDATE CONTROLLER ;ENABLE ASYNC INTERRUPTS ADD DX,3 ;MODEM CONTROL REGISTER MOV AL,0AH ;RTS/OUT2 OUT DX,AL ;UPDATE CONTROLLER POP DX POP AX RET ;------------------------------------------------------------ ;TASK LOCKING & UNLOCKING SUBROUTINES ;------------------------------------------------------------ LOCKWT: PUSHF CLI ;NO INTERRUPTS PUSH BX MOV BX,CDTASK ;CURRENT TASK CMP BX,ES:[SI] ;ALREADY OWN? JZ LOCK08 ;YES CMP WORD PTR [BX+USNXT],0 ;ALREADY ON A QUEUE? JZ LOCK10 ;NO PROBLEM LOCK08: ERR 502H LOCK10: CMP WORD PTR ES:[SI],0 ;RESOURCE AVAILABLE? JZ LOCK40 ;YES CMP WORD PTR ES:[SI+2],0 ;ANYONE WAITING? JNZ LOCK15 ;YES MOV WORD PTR ES:[SI+2],BX ;WE ARE FIRST IN LINE JMP SHORT LOCK35 ;GO WAIT LOCK15: PUSH DI MOV DI,WORD PTR ES:[SI+2] ;HEAD OF QUEUE LOCK20: CMP WORD PTR [DI+USNXT],0 ;END OF CHAIN? JZ LOCK30 ;YES MOV DI,WORD PTR [DI+USNXT] ;NEXT ENTRY JMP LOCK20 ;TEST IT LOCK30: MOV WORD PTR [DI+USNXT],BX ;ADD SELF TO LIST POP DI LOCK35: MOV WORD PTR [BX+CBRTC],10000 ;ABOUT 9 MINUTES AND WORD PTR [BX+CBFLG],NOT SFTO ;CLEAR TIME OUT CALL WAITRT ;WAIT FOR RESOURCE LOCK37: TEST WORD PTR [BX+CBFLG],SFTO ;TIMED OUT? JZ LOCK10 ;NO - TRY RESOURCE AGAIN ERR 503H ;SHOW ERROR JMP LOCK10 ;CHECK RESOURCE LOCK40: MOV WORD PTR ES:[SI],BX ;LOCK RESOURCE POP BX POPF RET UNLOCK: PUSHF CLI PUSH BX MOV BX,CDTASK ;CURRENT TCB CMP BX,WORD PTR ES:[SI] ;DO WE OWN IT? JZ UNLO10 ;YES ERR503: ERR 503H ;BAD TRIP UNLO10: MOV WORD PTR ES:[SI],0 ;UNLOCK RESOURCE CMP WORD PTR ES:[SI+2],0 ;ANYONE WAITING? JZ UNLO90 ;NO PUSH DI PUSH CX MOV DI,WORD PTR ES:[SI+2] ;1ST WAITING TASK MOV CX,WORD PTR [DI+USNXT] ;CHAINED TCB MOV WORD PTR ES:[SI+2],CX ;UPDATE WAIT CHAIN MOV WORD PTR [DI+USNXT],0 ;CLEAR CHAIN POINTER MOV WORD PTR [DI+USRFL],0 ;POST WAITING TCB POP CX POP DI UNLO90: POP BX POPF RET XGXLAT: PUSH DI TEST WORD PTR [BX+CBMDM],MDMKBD ;LOCAL? JZ XGXL00 ;NO - CHECK USER PROFILE TEST WORD PTR DS:MSGCKPT+MSOPTS,1000H ;USE EXTENDED GRAPHICS? JZ XGXL10 ;NO - MUST TRANSLATE XGXL00: TEST WORD PTR [BX+DTESTAT],MPARE ;7 - BIT? JNZ XGXL10 ;YES - MUST TRANSLATE MOV DI,WORD PTR [BX+USRST] ;USER RECORD OR DI,DI ;EXIST? JZ XGXL10 ;NO - MUST TRANSLATE TEST BYTE PTR [DI+UEOPTS],80H ;EXTENDED GRAPHICS? JNZ XGXL90 ;YES - RETURN XGXL10: PUSH AX PUSH BX PUSH CX MOV BX,OFFSET XGXTAB ;TRANSLATE TABLE MOV DI,SI ;START OF STRING MOV CX,[SI-2] ;STRING LENGTH JCXZ XGXL40 ;EMPTY STRING XGXL20: TEST BYTE PTR [DI],80H ;EXTENDED CHAR? JZ XGXL30 ;NO MOV AL,[DI] ;GET CHAR AND AL,7FH ;ADJUST OFFSET XLAT ES:XGXTAB ;TRANSLATE CHAR MOV [DI],AL ;REPLACE IN STRING XGXL30: INC DI ;NEXT CHAR LOOP XGXL20 ;CHECK NEXT CHAR XGXL40: POP CX POP BX POP AX XGXL90: POP DI CLC RET NANSI: PUSH DI JMP SHORT ANSI20 ;FILTER ANSI SEQUENCES ANSI: PUSH DI TEST WORD PTR [BX+CBMDM],MDMKBD ;LOCAL? JZ ANSI10 ;NO - CHECK USER PROFILE JMP ANSI90 ;ANSI OK ANSI10: MOV DI,WORD PTR [BX+USRST] ;USER RECORD OR DI,DI ;EXIST? JZ ANSI20 ;NO - MUST FILTER TEST BYTE PTR [DI+UEOPTS],40H ;ANSI OK? JNZ ANSI90 ;YES - RETURN ANSI20: PUSH AX PUSH CX MOV CX,[SI-2] ;STRING LENGTH JCXZ ANSI80 ;EMPTY STRING MOV DI,SI ;START OF STRING TEST WORD PTR [BX+USRSE],2 ;ALREAD IN PROCESS? JNZ ANSI30 ;YES MOV AL,1BH ;ESC CHAR PUSH ES PUSH DS POP ES REPNZ SCASB ;SEARCH FOR ESC POP ES JNZ ANSI80 ;NO PROBLEM DEC DI ;POINT TO ESCAPE INC CX ;CORRECT COUNT OR WORD PTR [BX+USRSE],2 ;SHOW SEQUENCE IN PROCESS ANSI30: PUSH DX PUSH SI XOR DX,DX ;DELETE COUNT MOV SI,DI ;START OF SEQUENCE ANSI40: LODSB ;GET NEXT CHAR CMP AL,27 ;ANOTHER ESC? JNZ ANSI42 ;NO OR WORD PTR [BX+USRSE],2 ;HERE WE GO AGAIN ANSI42: TEST WORD PTR [BX+USRSE],2 ;STILL IN SEQUENCE? JZ ANSI60 ;NO CMP AL,'[' ;LEFT BRACKET? JZ ANSI50 ;YES - DELETE CMP AL,'A' ;ALPHBETIC JC ANSI50 ;NO - DELETE AND WORD PTR [BX+USRSE],NOT 2 ;RESET ANSI FLAG ANSI50: INC DX ;COUNT DELETION JMP SHORT ANSI70 ;CHECK FOR END OF STRING ANSI60: MOV [DI],AL ;STORE IN STRING INC DI ANSI70: LOOP ANSI40 ;NEXT CHAR POP SI SUB [SI-2],DX ;ADJUST LENGTH POP DX ANSI80: POP CX POP AX ANSI90: POP DI CLC RET ;------------------------------------------------------------------- ;TABLE LOOK UP OF WAIT STATUS MESSAGES ; INPUT AX = RESUME ADDRESS ; RETURN AX = STATUS MESSAGE ID IF C=0 ;------------------------------------------------------------------- WTID: PUSH CX PUSH DI MOV DI,OFFSET WTPSW ;WAIT TABLE MOV CX,(WTMSG-WTPSW)/2 ;NUMBER OF ENTRIES REPNZ SCASW ;SEARCH FOR ENTRY JNZ WTID80 ;NOT FOUND SUB DI,OFFSET WTPSW+2 ;OFFSET IN TABLE MOV AX,ES:WTMSG[DI] ;MESSAGE ID CLC ;SHOW GOOD RETURN WTIDX: POP DI POP CX RET WTID80: STC ;SHOW ERROR JMP WTIDX ;EXIT ;--------------------------------------------------------------------- ;READ TEST DATA FROM CCTEST.DAT AND PASS AS INPUT TO TASK ; RETURNS AL DATA BYTE FROM FILE IF C=0 ; LOCAL BP-2 ;BYTE READ ;--------------------------------------------------------------------- TSTINP: FRAME 1 PUSH CX PUSH DX CMP TSTFILH,0 ;FILE OPEN? JNZ TSTI10 ;YES MOV AX,3D00H ;OPEN READ ONLY MOV DX,OFFSET TSTFILN ;FILE NAME PUSH DS PUSH ES POP DS INT 21H ;DOS CALL POP DS JC TSTI80 ;NO FILE MOV TSTFILH,AX ;FILE HANDLE TSTI10: MOV AH,3FH ;READ REQUEST MOV CX,1 ;ONE BYTE LEA DX,[BP-2] ;LOCAL STORAGE PUSH BX MOV BX,TSTFILH ;FILE HANDLE PUSH DS PUSH SS POP DS INT 21H ;DOS REQUEST POP DS POP BX CMP AX,CX ;END OF FILE? JNZ TSTI70 ;YES MOV AX,[BP-2] ;GET DATA BYTE CMP AL,0AH ;LINE FEED? JZ TSTI10 ;IGNORE LINE FEED CMP AL,1AH ;END OF FILE? JZ TSTI70 ;YES - CLOSE FILE CLC ;SHOW GOOD RETURN JMP TSTI90 ;EXIT TSTI70: MOV AH,3EH ;CLOSE FUNCTION PUSH BX MOV BX,TSTFILH ;FILE HANDLE INT 21H ;DOS CALL POP BX TSTI80: AND WORD PTR [BX+CBMDM],NOT MDMTEST ;CLEAR TEST FLAG STC ;SHOW NO DATA TSTI90: POP DX POP CX EXITF SUBRTNS ENDP CSEG ENDS END