From 80ab2fddfdf30f09f0a0a637654cbb3cd5c7baa6 Mon Sep 17 00:00:00 2001 From: Rich Turner Date: Fri, 12 Aug 1983 17:53:34 -0700 Subject: MS-DOS v2.0 Release --- v2.0/source/PRINT_v211.ASM | 1645 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1645 insertions(+) create mode 100644 v2.0/source/PRINT_v211.ASM (limited to 'v2.0/source/PRINT_v211.ASM') diff --git a/v2.0/source/PRINT_v211.ASM b/v2.0/source/PRINT_v211.ASM new file mode 100644 index 0000000..4585af7 --- /dev/null +++ b/v2.0/source/PRINT_v211.ASM @@ -0,0 +1,1645 @@ +;MS-DOS PRINT program for background printing of text files to the list +; device. INT 28H is a software interrupt generated by the DOS +; in its I/O wait loops. This spooler can be assembled for +; operation using only this interrupt which is portable from +; system to system. It may also be assembled to use a hardware +; timer interrupt in addition to the software INT 28H. The +; purpose of using hardware interrupts is to allow printing to +; continue during programs which do not enter the system and +; therefore causes the INT 28H to go away. A timer interrupt is +; chosen in preference to a "printer buffer empty" interrupt +; because PRINT in the timer form is generic. It can be given +; the name of any currently installed character device as the +; "printer", this makes it portable to devices which are +; installed by the user even in the hardware case. It could be +; modified to use a buffer empty interrupt (no code is given for +; this case), if this is done the PROMPT and BADMES messages and +; their associated code should be removed as PRINT will then be +; device specific. +; +; VERSION 1.00 07/03/82 + + +FALSE EQU 0 +TRUE EQU NOT FALSE + +IBM EQU TRUE +IBMVER EQU IBM +MSVER EQU FALSE + + IF MSVER +HARDINT EQU FALSE ;No hardware ints +AINT EQU FALSE ;No need to do interrupt acknowledge + ENDIF + + IF IBM +HARDINT EQU TRUE +INTLOC EQU 1CH ;Hardware interrupt location (Timer) +AINT EQU TRUE ;Acknowledge interrupts +EOI EQU 20H ;End Of Interrupt "instruction" +AKPORT EQU 20H ;Interrupt Acknowledge port + ENDIF + +;The following values have to do with the ERRCNT variable and the +; CNTMES message. The values define levels at wich it is assumed +; an off-line error exists. ERRCNT1 defines the value of ERRCNT above +; which the CNTMES message is printed by the transient. ERRCNT2 +; defines the value of ERRCNT above which the resident will give up +; trying to print messages on the printer, it is much greater than +; ERRCNT1 because a much tighter loop is involved. The bounding event +; which determines the correct value is the time required to do a +; form feed. + + IF IBM +ERRCNT1 EQU 1000 +ERRCNT2 EQU 20000 + ELSE +ERRCNT1 EQU 1000 +ERRCNT2 EQU 20000 + ENDIF + + IF HARDINT +TIMESLICE EQU 8 ;The PRINT scheduling time slice. PRINT + ; lets this many "ticks" go by before + ; using a time slice to pump out characters. + ; Setting this to 3 for instance means PRINT + ; Will skip 3 slices, then take the fourth. + ; Thus using up 1/4 of the CPU. Setting it + ; to one gives PRINT 1/2 of the CPU. + ; The above examples assume MAXTICK is + ; 1. The actual PRINT CPU percentage is + ; (MAXTICK/(1+TIMESLICE))*100 + +MAXTICK EQU 2 ;The PRINT in timeslice. PRINT will pump + ; out characters for this many clock ticks + ; and then exit. The selection of a value + ; for this is dependent on the timer rate. + +BUSYTICK EQU 1 ;If PRINT sits in a wait loop waiting for + ; output device to come ready for this + ; many ticks, it gives up its time slice. + ; Setting it greater than or equal to + ; MAXTICK causes it to be ignored. + +;User gets TIMESLICE ticks and then PRINT takes MAXTICK ticks unless BUSYTICK +; ticks go by without getting a character out. + ENDIF + + +;WARNING DANGER WARNING: +; PRINT is a systems utility. It is clearly understood that it may have +; to be entirely re-written for future versions of MS-DOS. The following +; TWO vectors are version specific, they may not exist at all in future +; versions. If they do exist, they may function differently. +; ANY PROGRAM WHICH IMITATES PRINTS USE OF THESE VECTORS IS ALSO A SYSTEMS +; UTILITY AND IS THEREFORE NOT VERSION PORTABLE IN ANY WAY SHAPE OR FORM. +; YOU HAVE BEEN WARNED, "I DID IT THE SAME WAY PRINT DID" IS NOT AN REASON +; TO EXPECT A PROGRAM TO WORK ON FUTURE VERSIONS OF MS-DOS. +SOFTINT EQU 28H ;Software interrupt generated by DOS +COMINT EQU 2FH ;Communications interrupt used by PRINT + ; This vector number is DOS reserved. It + ; is not generally available to programs + ; other than PRINT. + +BLKSIZ EQU 512 ;Size of the PRINT I/O block in bytes +FCBSIZ EQU 40 ;Size of an FCB + + INCLUDE DOSSYM.ASM + +FCB EQU 5CH +PARMS EQU 80H + +DG GROUP CODE,DATA + +CODE SEGMENT +ASSUME CS:DG + + ORG 100H +START: + JMP TRANSIENT + +HEADER DB "Vers 1.00" + + DB 128 DUP (?) +ISTACK LABEL WORD ;Stack starts here and grows down + +;Resident data + + IF HARDINT +INDOS DD ? ;DOS buisy flag +NEXTINT DD ? ;Chain for int +BUSY DB 0 ;Internal ME flag +SOFINT DB 0 ;Internal ME flag +TICKCNT DB 0 ;Tick counter +TICKSUB DB 0 ;Tick miss counter +SLICECNT DB TIMESLICE ;Time slice counter + ENDIF + +CBUSY DB 0 ;ME on com interrupt +SPNEXT DD ? ;Chain location for INT 28 +PCANMES DB 0 ;Cancel message flag +SSsave DW ? ;Stack save area for INT 24 +SPsave DW ? +DMAADDR DD ? ;Place to save DMA address +HERRINT DD ? ;Place to save Hard error interrupt +LISTDEV DD ? ;Pointer to Device +COLPOS DB 0 ;Column position for TAB processing +NXTCHR DW OFFSET DG:BUFFER + BLKSIZ ;Buffer pointer +CURRFIL DW OFFSET DG:SPLFCB ;Current file being printed + +LASTFCB DW ? ;Back pointer +LASTFCB2 DW ? ;Another back pointer +PABORT DB 0 ;Abort flag + +;Resident messages + +ERRMES DB 13,10,13,10,"**********",13,10,"$" +ERRMEST DB " error reading file",13,10 +EMFILNAM DB " : . " +BELMES DB 13,0CH,7,"$" + +CANMES DB 13,10,13,10 +CANFILNAM DB " : . " + DB " Canceled by operator$" + +ALLCAN DB 13,10,13,10,"All files canceled by operator$" + +MESBAS DW OFFSET DG:ERR0 + DW OFFSET DG:ERR1 + DW OFFSET DG:ERR2 + DW OFFSET DG:ERR3 + DW OFFSET DG:ERR4 + DW OFFSET DG:ERR5 + DW OFFSET DG:ERR6 + DW OFFSET DG:ERR7 + DW OFFSET DG:ERR8 + DW OFFSET DG:ERR9 + DW OFFSET DG:ERR10 + DW OFFSET DG:ERR11 + DW OFFSET DG:ERR12 + +;INT 24 messages A La COMMAND + +ERR0 DB "Write protect$" +ERR1 DB "Bad unit$" +ERR2 DB "Not ready$" +ERR3 DB "Bad command$" +ERR4 DB "Data$" +ERR5 DB "Bad call format$" +ERR6 DB "Seek$" +ERR7 DB "Non-DOS disk$" +ERR8 DB "Sector not found$" +ERR9 DB "No paper$" +ERR10 DB "Write fault$" +ERR11 DB "Read fault$" +ERR12 DB "Disk$" + +FATMES DB "File allocation table bad drive " +BADDRVM DB "A.",13,10,"$" + +;The DATA buffer +BUFFER DB BLKSIZ DUP(0) + DB ? +CODE ENDS + +;Transient data + +DATA SEGMENT BYTE + ORG 0 +SWITCHAR DB ? ;User switch character +FULLFLAG DB 0 ;Flag for printing queue full message +MAKERES DB 0 ;Flag to indicate presence of resident +ARGSETUP DB 0 ;Flag to indicate a formatted FCB exists at 5C +DEFDRV DB 0 ;Default drive +CANFLG DB 0 ;Flag to indicate cancel +FILCNT DB 0 ;Number of files +SPLIST DD ? ;Pointer to FCBs in resident +CURFILE DD ? ;Pointer to current FCB +SRCHFCB DB 38 DUP (0) ;SEARCH-FIRST/NEXT FCB +ENDRES DW OFFSET DG:DEF_ENDRES ;Term-Res location + +;Messages + +NOFILS DB "PRINT queue is empty",13,10,"$" +CURMES DB 13,10," " +CURFNAM DB " : . is currently being printed",13,10,"$" +FILMES DB " " +FILFNAM DB " : . is in queue" +CRLF DB 13,10,"$" +OPMES DB "Cannot open " +OPFILNAM DB " : . ",13,10,"$" +FULLMES DB "PRINT queue is full",13,10,"$" +SRCHMES LABEL BYTE +SRCHFNAM DB " : . "," File not found",13,10,"$" +BADMES DB "List output is not assigned to a device",13,10,"$" +GOODMES DB "Resident part of PRINT installed",13,10,"$" +PROMPT DB "Name of list device [PRN]: $" +CNTMES DB "Errors on list device indicate that it",13,10 + DB "may be off-line. Please check it.",13,10,13,10,"$" +BADSWT DB "Invalid parameter",13,10,"$" + + +BADVER DB "Incorrect DOS version",13,10,"$" + + IF IBM +;Reserved names for parallel card +INT_17_HITLIST LABEL BYTE + DB 8,"PRN ",0 + DB 8,"LPT1 ",0 + DB 8,"LPT2 ",1 + DB 8,"LPT3 ",2 + DB 0 +;Reserved names for Async adaptor +INT_14_HITLIST LABEL BYTE + DB 8,"AUX ",0 + DB 8,"COM1 ",0 + DB 8,"COM2 ",1 + DB 0 + ENDIF + +COMBUF DB 14,0 ;Device name buffer + DB 14 DUP (?) +LISTFCB DB 0,"PRN " ;Device name FCB + DB 25 DUP (0) +PARSEBUF DB 80 DUP (?) ;Parsing space + +DATA ENDS + +CODE SEGMENT +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + + +;Interrupt routines +ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:NOTHING + IF HARDINT +HDSPINT: ;Hardware interrupt entry point + INC [TICKCNT] ;Tick + INC [TICKSUB] ;Tick + CMP [SLICECNT],0 + JZ TIMENOW + DEC [SLICECNT] ;Count down + JMP SHORT CHAININT ;Not time yet +TIMENOW: + CMP [BUSY],0 ;See if interrupting ourself + JNZ CHAININT + PUSH DS + PUSH SI + LDS SI,[INDOS] ;Check for making DOS calls + CMP BYTE PTR [SI],0 + POP SI + POP DS + JNZ CHAININT ;DOS is Buisy + INC [BUSY] ;Exclude furthur interrupts + MOV [TICKCNT],0 ;Reset tick counter + MOV [TICKSUB],0 ;Reset tick counter + STI ;Keep things rolling + + IF AINT + MOV AL,EOI ;Acknowledge interrupt + OUT AKPORT,AL + ENDIF + + CALL DOINT + CLI + MOV [SLICECNT],TIMESLICE ;Either soft or hard int resets time slice + MOV [BUSY],0 ;Done, let others in +CHAININT: + JMP [NEXTINT] ;Chain to next clock routine + ENDIF + + +SPINT: ;INT 28H entry point + IF HARDINT + CMP [BUSY],0 + JNZ NXTSP + INC [BUSY] ;Exclude hardware interrupt + INC [SOFINT] ;Indicate a software int in progress + ENDIF + + STI ;Hardware interrupts ok on INT 28H entry + CALL DOINT + + IF HARDINT + CLI + MOV [SOFINT],0 ;Indicate INT done + MOV [SLICECNT],TIMESLICE ;Either soft or hard int resets time slice + MOV [BUSY],0 + ENDIF + +NXTSP: JMP [SPNEXT] ;Chain to next INT 28 + +DOINT: + PUSH SI + MOV SI,[CURRFIL] + INC SI + INC SI + CMP BYTE PTR CS:[SI],-1 + POP SI + JNZ GOAHEAD + JMP SPRET ;Nothing to do +GOAHEAD: + PUSH AX ;Need a working register + MOV [SSsave],SS + MOV [SPsave],SP + MOV AX,CS + CLI +;Go to internal stack to prevent INT 24 overflowing system stack + MOV SS,AX + MOV SP,OFFSET DG:ISTACK + STI + PUSH ES + PUSH DS + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH CS + POP DS +ASSUME DS:DG + + MOV BX,[NXTCHR] + CMP BX,OFFSET DG:BUFFER + BLKSIZ + JNZ PLOOP + JMP READBUFF ;Buffer empty + +PLOOP: + IF HARDINT + MOV BX,[NXTCHR] + CMP BX,OFFSET DG:BUFFER + BLKSIZ + JZ DONEJMP ;Buffer has become empty + CMP [SOFINT],0 + JNZ STATCHK + CMP [TICKCNT],MAXTICK ;Check our time slice + JAE DONEJMP +STATCHK: + ENDIF + + CALL PSTAT + + IF HARDINT + JZ DOCHAR ;Printer ready + CMP [SOFINT],0 + ENDIF + + JNZ DONEJMP ;If soft int give up + + IF HARDINT + CMP [TICKSUB],BUSYTICK ;Check our busy timeout + JAE DONEJMP + JMP PLOOP + ENDIF + +DOCHAR: + MOV AL,BYTE PTR [BX] + CMP AL,1AH ;^Z? + JZ FILEOFJ ;CPM EOF + CMP AL,0DH ;CR? + JNZ NOTCR + MOV [COLPOS],0 +NOTCR: + CMP AL,9 ;TAB? + JNZ NOTABDO + MOV CL,[COLPOS] + OR CL,0F8H + NEG CL + XOR CH,CH + JCXZ TABDONE +TABLP: + MOV AL," " + INC [COLPOS] + PUSH CX + CALL POUT + POP CX + LOOP TABLP + JMP TABDONE + +NOTABDO: + CMP AL,8 ;Back space? + JNZ NOTBACK + DEC [COLPOS] +NOTBACK: + CMP AL,20H ;Non Printing char? + JB NOCHAR + INC [COLPOS] ;Printing char +NOCHAR: + CALL POUT ;Print it +TABDONE: + INC [NXTCHR] ;Next char + + IF HARDINT + MOV [TICKSUB],0 ;Got a character out, Reset counter + CMP [SOFINT],0 ;Soft int does one char at a time + JZ PLOOP + ENDIF + +DONEJMP: + POP DI + POP SI + POP DX + POP CX + POP BX + POP DS + POP ES +ASSUME DS:NOTHING,ES:NOTHING + CLI + MOV SS,[SSsave] ;Restore Entry Stack + MOV SP,[SPsave] + STI + POP AX +SPRET: + RET + +FILEOFJ: JMP FILEOF + +READBUFF: +ASSUME DS:DG,ES:NOTHING + + MOV AL,24H + MOV AH,GET_INTERRUPT_VECTOR + INT 21H + MOV WORD PTR [HERRINT+2],ES ;Save current vector + MOV WORD PTR [HERRINT],BX + MOV DX,OFFSET DG:DSKERR + MOV AL,24H + MOV AH,SET_INTERRUPT_VECTOR ;Install our own + INT 21H ;Spooler must catch its errors + MOV AH,GET_DMA + INT 21H + MOV WORD PTR [DMAADDR+2],ES ;Save DMA address + MOV WORD PTR [DMAADDR],BX + MOV DX,OFFSET DG:BUFFER + MOV AH,SET_DMA + INT 21H ;New DMA address + MOV [PABORT],0 ;No abort + MOV DX,[CURRFIL] ;Read + INC DX + INC DX ;Skip over pointer + MOV AH,FCB_SEQ_READ + INT 21H + PUSH AX + LDS DX,[DMAADDR] +ASSUME DS:NOTHING + MOV AH,SET_DMA + INT 21H ;Restore DMA + LDS DX,[HERRINT] + MOV AL,24H + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Restore Error INT + POP AX + PUSH CS + POP DS +ASSUME DS:DG + CMP [PABORT],0 + JNZ TONEXTFIL ;Barf on this file, got INT 24 + CMP AL,01 + JZ FILEOF ;Read EOF? + MOV BX,OFFSET DG:BUFFER ;Buffer full + MOV [NXTCHR],BX + JMP DONEJMP + +FILEOF: + MOV AL,0CH ;Form feed + CALL LOUT +TONEXTFIL: + CALL NEXTFIL + JMP DONEJMP + +;INT 24 handler + +DSKERR: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + STI + CMP [PABORT],0 + JNZ IGNRET + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH BP + PUSH ES + PUSH DS + PUSH CS + POP DS + PUSH CS + POP ES +ASSUME DS:DG,ES:DG + ADD [BADDRVM],AL ;Set correct drive letter + MOV SI,OFFSET DG:ERRMES + CALL LISTMES + TEST AH,080H + JNZ FATERR + AND DI,0FFH + CMP DI,12 + JBE HAVCOD + MOV DI,12 +HAVCOD: + SHL DI,1 + MOV DI,WORD PTR [DI+MESBAS] ; Get pointer to error message + MOV SI,DI + CALL LISTMES ; Print error type + MOV DI,OFFSET DG:EMFILNAM + MOV SI,[CURRFIL] + ADD SI,2 ;Get to file name + LODSB + ADD AL,'@' + STOSB + INC DI + MOV CX,4 + REP MOVSW + INC DI + MOVSW + MOVSB + MOV SI,OFFSET DG:ERRMEST + CALL LISTMES +SETABORT: + INC [PABORT] ;Indicate abort + POP DS + POP ES + POP BP + POP SI + POP DI + POP DX + POP CX + POP BX +IGNRET: + XOR AL,AL ;Ignore + IRET + +FATERR: + MOV SI,OFFSET DG:FATMES + CALL LISTMES + JMP SHORT SETABORT + +ADDFILJ: JMP ADDFIL + +COMBUSY: + MOV AX,-1 + IRET + +;Communications interrupt +SPCOMINT: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + CMP [CBUSY],0 + JNZ COMBUSY + INC [CBUSY] ;Exclude + STI ;Turn ints back on + PUSH SI + PUSH DI + PUSH CX + PUSH DS + PUSH CS + POP DS +ASSUME DS:DG + MOV [PCANMES],0 ;Havn't printed cancel message + OR AH,AH + JZ ADDFILJ ;Add file + CMP AH,1 + JZ CANFIL ;Cancel File(s) + XOR AL,AL +SETCOUNT: + PUSH AX ;Save AL return code + XOR AH,AH + MOV SI,OFFSET DG:SPLFCB + MOV CX,[NUMFCBS] +CNTFILS: + CMP BYTE PTR [SI+2],-1 ;Valid? + JZ LNEXT + INC AH +LNEXT: + ADD SI,FCBSIZ + LOOP CNTFILS +COMRET: + MOV BX,OFFSET DG:SPLFCB + MOV DX,[CURRFIL] + PUSH DS + POP ES +ASSUME ES:NOTHING + MOV CH,AH + POP AX ;Get AL return + MOV AH,CH + + IF HARDINT +BWAIT3: + CMP [BUSY],0 + JNZ BWAIT3 + INC [BUSY] + ENDIF + + CALL PSTAT ; Tweek error counter + + IF HARDINT + MOV [BUSY],0 + ENDIF + + POP DS +ASSUME DS:NOTHING + POP CX + POP DI + POP SI + MOV [CBUSY],0 + IRET + +DELALLJ: JMP DELALL + +CANFIL: +ASSUME DS:DG,ES:NOTHING + MOV CX,[NUMFCBS] + + IF HARDINT +BWAIT: + CMP [BUSY],0 + JNZ BWAIT + INC [BUSY] + ENDIF + + MOV SI,[CURRFIL] + CMP DX,-1 + JZ DELALLJ + MOV BX,[SI] + PUSH BX +LOOKEND: ;Set initial pointer values + CMP BX,SI + JZ GOTLAST + POP AX + PUSH BX + MOV BX,[BX] + JMP SHORT LOOKEND + +GOTLAST: + POP BX + MOV [LASTFCB],BX + MOV [LASTFCB2],BX + POP ES + PUSH ES + MOV BX,SI +LOOKMATCH: + MOV DI,DX + ADD SI,2 ;Skip pointer + CMP BYTE PTR [SI],-1 + JZ CANTERMJ ;No more + CMPSB + JNZ SKIPFIL ;DRIVE + PUSH CX + MOV CX,11 +NXTCHAR: + MOV AL,ES:[DI] + INC DI + CALL UPCONV + MOV AH,AL + LODSB + CALL UPCONV + CMP AH,"?" ;Wild card? + JZ NXTCHRLP ;Yes + CMP AH,AL + JNZ SKIPFILC +NXTCHRLP: + LOOP NXTCHAR +MATCH: + POP CX + MOV AH,-1 + XCHG AH,[BX+2] ;Zap it + CMP BX,[CURRFIL] ;Is current file? + JNZ REQUEUE ;No + MOV AL,1 + XCHG AL,[PCANMES] + OR AL,AL + JNZ DIDCMES ;Only print cancel message once + PUSH ES + PUSH CS + POP ES + MOV DI,OFFSET DG:CANFILNAM + MOV SI,BX + ADD SI,3 ;Get to file name + MOV AL,AH + ADD AL,'@' + STOSB + INC DI + MOV CX,4 + REP MOVSW + INC DI + MOVSW + MOVSB + POP ES + MOV SI,OFFSET DG:CANMES + CALL LISTMES + MOV SI,OFFSET DG:BELMES + CALL LISTMES +DIDCMES: + PUSH CX + CALL NEXTFIL +SKIPFILC: + POP CX +SKIPFIL: + MOV [LASTFCB2],BX + MOV BX,[BX] +NEXTFC: + MOV SI,BX + LOOP LOOKMATCH +CANTERMJ: JMP SHORT CANTERM + +REQUEUE: + MOV AX,[BX] + CMP AX,[CURRFIL] ;Is last FCB? + JZ SKIPFIL ;Yes, is in right place + MOV SI,[LASTFCB2] + MOV [SI],AX ;Unlink FCB + MOV SI,[CURRFIL] + MOV [BX],SI + MOV SI,[LASTFCB] + MOV [SI],BX ;Link FCB at end + MOV [LASTFCB],BX ;New end + MOV BX,AX ;Process what it pointed to + JMP SHORT NEXTFC + +DELALL: + CMP BYTE PTR CS:[SI+2],-1 ;Examine current file +DELALL2: + MOV BYTE PTR [SI+2],-1 ;Zap it + MOV SI,[SI] + LOOP DELALL2 + JZ CANTERM1 ;No message if nothing was in progress + MOV SI,OFFSET DG:ALLCAN + CALL LISTMES + MOV SI,OFFSET DG:BELMES + CALL LISTMES +CANTERM1: + MOV [NXTCHR],OFFSET DG:BUFFER + BLKSIZ ;Buffer empty +CANTERM: + + IF HARDINT + MOV [BUSY],0 + ENDIF + + XOR AX,AX + JMP SETCOUNT + +UPCONV: + CMP AL,'a' + JB NOCONV + CMP AL,'z' + JA NOCONV + SUB AL,20H +NOCONV: + RET + +ADDFIL: +ASSUME DS:DG,ES:NOTHING + MOV SI,[CURRFIL] + MOV CX,[NUMFCBS] + + IF HARDINT +BWAIT2: + CMP [BUSY],0 + JNZ BWAIT2 + INC [BUSY] + ENDIF + +LOOKSPOT: + CMP BYTE PTR [SI+2],-1 + JZ GOTSPOT + MOV SI,[SI] + LOOP LOOKSPOT + + IF HARDINT + MOV [BUSY],0 + ENDIF + + MOV AL,1 + JMP SETCOUNT + +GOTSPOT: + PUSH DS + POP ES + POP DS + PUSH DS +ASSUME DS:NOTHING + PUSH SI + MOV DI,SI + ADD DI,2 + MOV SI,DX + MOV CX,19 + REP MOVSW ;Copy in and set FCB + POP SI + PUSH ES + POP DS +ASSUME DS:DG + MOV WORD PTR [SI+2+fcb_EXTENT],0 + MOV BYTE PTR [SI+2+fcb_NR],0 + MOV WORD PTR [SI+2+fcb_RECSIZ],BLKSIZ + + IF HARDINT + MOV [BUSY],0 + ENDIF + + XOR AL,AL + JMP SETCOUNT + +NEXTFIL: +ASSUME DS:DG,ES:NOTHING + MOV SI,[CURRFIL] + MOV BYTE PTR [SI+2],-1 ;Done with current file + MOV SI,[SI] + MOV [CURRFIL],SI + MOV [NXTCHR],OFFSET DG:BUFFER + BLKSIZ ;Buffer empty + MOV [COLPOS],0 ;Start of line + RET + +LISTMES: +ASSUME DS:DG,ES:NOTHING + LODSB + CMP AL,"$" + JZ LMESDONE + CALL LOUT + JMP LISTMES + +LMESDONE: + RET + +LOUT: + PUSH BX +LWAIT: + CALL PSTAT + JZ PREADY + CMP [ERRCNT],ERRCNT2 + JA POPRET ;Don't get stuck + JMP SHORT LWAIT +PREADY: + CALL POUT +POPRET: + POP BX + RET + +;Stuff for BIOS interface +IOBUSY EQU 0200H +IOERROR EQU 8000H + +BYTEBUF DB ? + +CALLAD DD ? + +IOCALL DB 22 + DB 0 +IOREQ DB ? +IOSTAT DW 0 + DB 8 DUP(?) + DB 0 + DW OFFSET DG:BYTEBUF +INTSEG DW ? +IOCNT DW 1 + DW 0 + +PSTAT: +ASSUME DS:DG + PUSH BX + INC [ERRCNT] + MOV BL,10 + CALL DOCALL + TEST [IOSTAT],IOERROR + JZ NOSTATERR + OR [IOSTAT],IOBUSY ;If error, show buisy +NOSTATERR: + TEST [IOSTAT],IOBUSY + JNZ RET13P ;Shows buisy + MOV [ERRCNT],0 +RET13P: + POP BX + RET + +POUT: +ASSUME DS:DG + MOV [BYTEBUF],AL + MOV BL,8 +DOCALL: + PUSH ES + MOV [IOREQ],BL + MOV BX,CS + MOV ES,BX + MOV BX,OFFSET DG:IOCALL + MOV [IOSTAT],0 + MOV [IOCNT],1 + PUSH DS + PUSH SI + PUSH AX + LDS SI,[LISTDEV] +ASSUME DS:NOTHING + MOV AX,[SI+6] + MOV WORD PTR [CALLAD],AX + CALL [CALLAD] + MOV AX,[SI+8] + MOV WORD PTR [CALLAD],AX + CALL [CALLAD] + POP AX + POP SI + POP DS +ASSUME DS:DG + POP ES + RET + + IF IBM +REAL_INT_13 DD ? +INT_13_RETADDR DW OFFSET DG:INT_13_BACK + +INT_13 PROC FAR +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSHF + INC [BUSY] ;Exclude if dumb program call ROM + PUSH CS + PUSH [INT_13_RETADDR] + PUSH WORD PTR [REAL_INT_13+2] + PUSH WORD PTR [REAL_INT_13] + RET +INT_13 ENDP + +INT_13_BACK PROC FAR + PUSHF + DEC [BUSY] + POPF + RET 2 ;Chuck saved flags +INT_13_BACK ENDP + ENDIF + + + IF IBM + +REAL_INT_5 DD ? +REAL_INT_17 DD ? +INT_17_NUM DW 0 + +INT_17: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH SI + MOV SI,[CURRFIL] + INC SI + INC SI + CMP BYTE PTR CS:[SI],-1 + POP SI + JZ DO_INT_17 ;Nothing pending, so OK + CMP DX,[INT_17_NUM] + JNZ DO_INT_17 ;Not my unit + CMP [BUSY],0 + JNZ DO_INT_17 ;You are me + STI + MOV AH,0A1H ;You are bad, get out of paper + IRET + +DO_INT_17: + JMP [REAL_INT_17] ;Do a 17 + +REAL_INT_14 DD ? +INT_14_NUM DW 0 + +INT_14: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH SI + MOV SI,[CURRFIL] + INC SI + INC SI + CMP BYTE PTR CS:[SI],-1 + POP SI + JZ DO_INT_14 ;Nothing pending, so OK + CMP DX,[INT_14_NUM] + JNZ DO_INT_14 ;Not my unit + CMP [BUSY],0 + JNZ DO_INT_14 ;You are me + STI + OR AH,AH + JZ SET14_AX + CMP AH,2 + JBE SET14_AH +SET14_AX: + MOV AL,0 +SET14_AH: + MOV AH,80H ;Time out + IRET + +DO_INT_14: + JMP [REAL_INT_14] ;Do a 14 + +INT_5: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + PUSH SI + MOV SI,[CURRFIL] + INC SI + INC SI + CMP BYTE PTR CS:[SI],-1 + POP SI + JZ DO_INT_5 ;Nothing pending, so OK + CMP [INT_17_NUM],0 + JNZ DO_INT_5 ;Only care about unit 0 + IRET ;Pretend it worked + +DO_INT_5: + JMP [REAL_INT_5] ;Do a 5 + ENDIF + + +;The following data is order and position dependant +NUMFCBS DW 10 +ERRCNT DW 0 + +SPLFCB DW OFFSET DG:FC1 + DB (FCBSIZ - 2) DUP (-1) +FC1 DW OFFSET DG:FC2 + DB (FCBSIZ - 2) DUP (-1) +FC2 DW OFFSET DG:FC3 + DB (FCBSIZ - 2) DUP (-1) +FC3 DW OFFSET DG:FC4 + DB (FCBSIZ - 2) DUP (-1) +FC4 DW OFFSET DG:FC5 + DB (FCBSIZ - 2) DUP (-1) +FC5 DW OFFSET DG:FC6 + DB (FCBSIZ - 2) DUP (-1) +FC6 DW OFFSET DG:FC7 + DB (FCBSIZ - 2) DUP (-1) +FC7 DW OFFSET DG:FC8 + DB (FCBSIZ - 2) DUP (-1) +FC8 DW OFFSET DG:FC9 + DB (FCBSIZ - 2) DUP (-1) +FC9 DW OFFSET DG:SPLFCB + DB (FCBSIZ - 2) DUP (-1) + +DEF_ENDRES LABEL BYTE + +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + +BADSPOOL: + MOV DX,OFFSET DG:BADMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + INT 20H + +SETUP: +;Called once to install resident + CLD + MOV [INTSEG],CS + MOV DX,OFFSET DG:PROMPT + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + MOV DX,OFFSET DG:COMBUF + MOV AH,STD_CON_STRING_INPUT + INT 21H ;Get device name + MOV DX,OFFSET DG:CRLF + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + MOV CL,[COMBUF+1] + OR CL,CL + JZ DEFSPOOL ;User didn't specify one + XOR CH,CH + MOV DI,OFFSET DG:LISTFCB + 1 + MOV SI,OFFSET DG:COMBUF + 2 + REP MOVSB +DEFSPOOL: + MOV DX,OFFSET DG:LISTFCB + MOV AH,FCB_OPEN + INT 21H + OR AL,AL + JNZ BADSPOOL ;Bad + TEST BYTE PTR [LISTFCB.fcb_DEVID],080H + JZ BADSPOOL ;Must be a device + LDS SI,DWORD PTR [LISTFCB.fcb_FIRCLUS] +ASSUME DS:NOTHING + MOV WORD PTR [CALLAD+2],DS ;Get I/O routines + MOV WORD PTR [LISTDEV+2],DS ;Get I/O routines + MOV WORD PTR [LISTDEV],SI + PUSH CS + POP DS +ASSUME DS:DG + MOV DX,OFFSET DG:SPINT + MOV AL,SOFTINT + MOV AH,GET_INTERRUPT_VECTOR + INT 21H ;Get soft vector + MOV WORD PTR [SPNEXT+2],ES + MOV WORD PTR [SPNEXT],BX + MOV AL,SOFTINT + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Set soft vector + MOV DX,OFFSET DG:SPCOMINT + MOV AL,COMINT + MOV AH,SET_INTERRUPT_VECTOR ;Set communication vector + INT 21H + + IF IBM + MOV AL,13H + MOV AH,GET_INTERRUPT_VECTOR + INT 21H + MOV WORD PTR [REAL_INT_13+2],ES + MOV WORD PTR [REAL_INT_13],BX + MOV DX,OFFSET DG:INT_13 + MOV AL,13H + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Set diskI/O interrupt + MOV AL,17H + MOV AH,GET_INTERRUPT_VECTOR + INT 21H + MOV WORD PTR [REAL_INT_17+2],ES + MOV WORD PTR [REAL_INT_17],BX + MOV AL,14H + MOV AH,GET_INTERRUPT_VECTOR + INT 21H + MOV WORD PTR [REAL_INT_14+2],ES + MOV WORD PTR [REAL_INT_14],BX + MOV AL,5H + MOV AH,GET_INTERRUPT_VECTOR + INT 21H + MOV WORD PTR [REAL_INT_5+2],ES + MOV WORD PTR [REAL_INT_5],BX + PUSH CS + POP ES + MOV BP,OFFSET DG:LISTFCB + 1 + MOV SI,BP + MOV CX,8 +CONLP: ;Make sure device name in upper case + LODSB + CMP AL,'a' + JB DOCONLP + CMP AL,'z' + JA DOCONLP + SUB BYTE PTR [SI-1],20H +DOCONLP: + LOOP CONLP + MOV DI,OFFSET DG:INT_17_HITLIST +CHKHIT: + MOV SI,BP + MOV CL,[DI] + INC DI + JCXZ NOTONHITLIST + REPE CMPSB + LAHF + ADD DI,CX ;Bump to next position without affecting flags + MOV BL,[DI] ;Get device number + INC DI + SAHF + JNZ CHKHIT + XOR BH,BH + MOV [INT_17_NUM],BX + MOV DX,OFFSET DG:INT_17 + MOV AL,17H + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Set printer interrupt + MOV DX,OFFSET DG:INT_5 + MOV AL,5H + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Set print screen interrupt + JMP SHORT ALLSET +NOTONHITLIST: + MOV DI,OFFSET DG:INT_14_HITLIST +CHKHIT2: + MOV SI,BP + MOV CL,[DI] + INC DI + JCXZ ALLSET + REPE CMPSB + LAHF + ADD DI,CX ;Bump to next position without affecting flags + MOV BL,[DI] ;Get device number + INC DI + SAHF + JNZ CHKHIT2 + XOR BH,BH + MOV [INT_14_NUM],BX + MOV DX,OFFSET DG:INT_14 + MOV AL,14H + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Set RS232 port interrupt +ALLSET: + ENDIF + + IF HARDINT + MOV AH,GET_INDOS_FLAG + INT 21H + MOV WORD PTR [INDOS+2],ES ;Get indos flag location + MOV WORD PTR [INDOS],BX + MOV AL,INTLOC + MOV AH,GET_INTERRUPT_VECTOR + INT 21H + MOV WORD PTR [NEXTINT+2],ES + MOV WORD PTR [NEXTINT],BX + MOV DX,OFFSET DG:HDSPINT + MOV AL,INTLOC + MOV AH,SET_INTERRUPT_VECTOR + INT 21H ;Set hardware interrupt + ENDIF + + MOV [MAKERES],1 ;Indicate to do a terminate stay resident + MOV DX,OFFSET DG:GOODMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + RET + +ASSUME CS:DG,DS:DG,ES:DG,SS:DG + +TRANSIENT: +;User interface + CLD + +;Code to print header +; MOV DX,OFFSET DG:HEADER +; MOV AH,STD_CON_STRING_OUTPUT +; INT 21H + +DOSVER_LOW EQU 0136H ;1.54 in hex +DOSVER_HIGH EQU 020BH ;2.11 in hex + MOV AH,GET_VERSION + INT 21H + XCHG AH,AL ;Turn it around to AH.AL + CMP AX,DOSVER_LOW + JB GOTBADDOS + CMP AX,DOSVER_HIGH + JBE OKDOS +GOTBADDOS: + PUSH CS + POP DS + MOV DX,OFFSET DG:BADVER + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + INT 20H +OKDOS: + MOV AX,CHAR_OPER SHL 8 + INT 21H + MOV [SWITCHAR],DL ;Get user switch character + MOV AH,GET_INTERRUPT_VECTOR + MOV AL,COMINT + INT 21H +ASSUME ES:NOTHING + MOV DI,BX + MOV SI,OFFSET DG:SPCOMINT + MOV CX,13 + REPE CMPSB + JZ GOTRES ;Signature matched + PUSH CS + POP ES + CALL SETUP +GOTRES: + PUSH CS + POP ES + MOV AH,GET_DEFAULT_DRIVE + INT 21H + MOV [DEFDRV],AL + MOV SI,PARMS + LODSB + OR AL,AL + JNZ GOTPARMS +TRANEXIT: + CALL GETSPLIST + CMP [MAKERES],0 + JNZ SETRES + INT 20H + +SETRES: + MOV DX,[ENDRES] + INT 27H + +ARGSDONE: + CMP [ARGSETUP],0 + JZ TRANEXIT + CALL PROCESS + JMP SHORT TRANEXIT + +GOTPARMS: +PARSE: + MOV DI,OFFSET DG:PARSEBUF + CALL CPARSE + JC ARGSDONE + CMP AX,4 ;Switch? + JNZ GOTNORMARG + MOV AL,[DI] ;Get the switch character + CMP AL,'C' + JZ SETCAN + CMP AL,'c' + JNZ CHKSPL +SETCAN: + MOV [CANFLG],1 + JMP SHORT PARSE +CHKSPL: + CMP AL,'P' + JZ RESETCAN + CMP AL,'p' + JNZ CHKTERM +RESETCAN: + MOV [CANFLG],0 + JMP SHORT PARSE +CHKTERM: + CMP AL,'T' + JZ SETTERM + CMP AL,'t' + JZ SETTERM + MOV DX,OFFSET DG:BADSWT + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + JMP SHORT PARSE + +SETTERM: + CALL TERMPROCESS + JMP TRANEXIT ; Ignore everything after T switch + +GOTNORMARG: + XOR AL,AL + XCHG AL,[ARGSETUP] + OR AL,AL + JZ PARSEARG + CALL NORMPROC ;Don't test ARGSETUP, it just got zeroed +PARSEARG: + PUSH SI + MOV SI,DI + MOV DI,FCB + MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 1 + INT 21H ;Parse the arg + CMP BYTE PTR [DI],0 + JNZ DRVOK + MOV DL,[DEFDRV] + INC DL + MOV BYTE PTR [DI],DL ;Set the default drive +DRVOK: + POP SI + INC [ARGSETUP] + JMP SHORT PARSE + +TERMPROCESS: + MOV DX,-1 +PROCRET: + MOV AH,1 + CALL DOSET +PROCRETNFUNC: + MOV [ARGSETUP],0 + PUSH CS + POP ES +RET14: RET + +PROCESS: + CMP [ARGSETUP],0 + JZ RET14 ;Nothing to process +NORMPROC: + MOV AL,BYTE PTR DS:[FCB+1] + CMP AL," " + JZ SRCHBADJ + MOV DX,FCB + MOV AH,[CANFLG] + CMP AH,0 + JNZ PROCRET + MOV DX,OFFSET DG:SRCHFCB + MOV AH,SET_DMA + INT 21H + MOV DX,FCB + MOV AH,DIR_SEARCH_FIRST + INT 21H + OR AL,AL + JNZ SRCHBADJ +SRCHLOOP: + MOV DX,OFFSET DG:SRCHFCB + MOV AH,FCB_OPEN + INT 21H + OR AL,AL + JZ OPENOK + CALL OPENERR + JMP SHORT NEXTSEARCH +SRCHBADJ: JMP SRCHBAD +OPENOK: + MOV DX,OFFSET DG:SRCHFCB + MOV AH,0 + CALL DOSET + OR AL,AL + JZ NEXTSEARCH + XCHG AL,[FULLFLAG] ;Know AL non-zero + OR AL,AL + JNZ NEXTSEARCH ;Only print message once + MOV DX,OFFSET DG:FULLMES ;Queue full + MOV AH,STD_CON_STRING_OUTPUT + INT 21H +NEXTSEARCH: + MOV DX,OFFSET DG:SRCHFCB + MOV AH,SET_DMA + INT 21H + MOV DX,FCB + MOV AH,DIR_SEARCH_NEXT + INT 21H + OR AL,AL + JNZ PROCRETNFUNC + JMP SRCHLOOP + +DOSET: + INT COMINT + MOV [FILCNT],AH ;Suck up return info + MOV WORD PTR [SPLIST+2],ES + MOV WORD PTR [CURFILE+2],ES + MOV WORD PTR [SPLIST],BX + MOV WORD PTR [CURFILE],DX + RET + +OPENERR: + PUSH SI + PUSH DI + MOV SI,OFFSET DG:OPFILNAM + PUSH DS + POP ES + MOV DI,OFFSET DG:SRCHFCB + CALL MVFNAM + MOV DX,OFFSET DG:OPMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + POP DI + POP SI + RET + +SRCHBAD: + PUSH SI + PUSH DI + MOV SI,OFFSET DG:SRCHFNAM + PUSH DS + POP ES + MOV DI,FCB + CALL MVFNAM + MOV DX,OFFSET DG:SRCHMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + POP DI + POP SI + JMP PROCRETNFUNC + +GETSPLIST: + MOV AH,0FFH + CALL DOSET + PUSH DS + LDS DI,[SPLIST] + MOV DI,[DI-2] ;Get the error count + POP DS + CMP DI,ERRCNT1 + JB CNTOK + MOV DX,OFFSET DG:CNTMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H +CNTOK: + MOV CL,[FILCNT] + OR CL,CL + JZ NOFILES + XOR CH,CH + LES DI,[CURFILE] + PUSH DI + INC DI + INC DI + MOV SI,OFFSET DG:CURFNAM + CALL MVFNAM + POP DI + MOV DX,OFFSET DG:CURMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + DEC CX + JCXZ RET12 +FILOOP: + MOV DI,ES:[DI] + PUSH DI + INC DI + INC DI + MOV SI,OFFSET DG:FILFNAM + CALL MVFNAM + POP DI + MOV DX,OFFSET DG:FILMES + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + LOOP FILOOP +RET12: RET + +NOFILES: + MOV DX,OFFSET DG:NOFILS + MOV AH,STD_CON_STRING_OUTPUT + INT 21H + RET + +;Make a message with the file name +MVFNAM: +ASSUME DS:NOTHING,ES:NOTHING + PUSH SI + PUSH DI + PUSH CX + MOV AX,ES + PUSH DS + POP ES + MOV DS,AX + XCHG SI,DI + LODSB + ADD AL,"@" + CMP AL,"@" + JNZ STCHR + MOV AL,[DEFDRV] + ADD AL,"A" +STCHR: + STOSB + INC DI + MOV CX,4 + REP MOVSW + INC DI + MOVSW + MOVSB + MOV AX,ES + PUSH DS + POP ES + MOV DS,AX + POP CX + POP DI + POP SI + RET + +;-----------------------------------------------------------------------; +; ENTRY: ; +; DS:SI Points input buffer ; +; ES:DI Points to the token buffer ; +; ; +; EXIT: ; +; DS:SI Points to next char in the input buffer ; +; ES:DI Points to the token buffer ; +; CX Character count ; +; AX Condition Code ; +; =1 same as carry set ; +; =2 normal token ; +; =4 switch character, char in token buffer ; +; Carry Flag Set if a CR was found, Reset otherwise ; +; ; +; MODIFIES: ; +; CX, SI, AX and the Carry Flag ; +; ; +;-----------------------------------------------------------------------; + +TAB equ 09h +CR equ 0dh + +CPARSE: +ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING + pushf ;save flags + push di ;save the token buffer addrss + xor cx,cx ;no chars in token buffer + call kill_bl + + cmp al,CR ;a CR? + jne sj2 ;no, skip +sj1: + mov ax,1 ;condition code + dec si ;adjust the pointer + pop di ;retrive token buffer address + popf ;restore flags + stc ;set the carry bit + ret + +sj2: + mov dl,[SWITCHAR] + cmp al,dl ;is the char the switch char? + jne anum_char ;no, process... + call kill_bl + cmp al,CR ;a CR? + je sj1 ;yes, error exit + call move_char ;Put the switch char in the token buffer + mov ax,4 ;Flag switch + jmp short x_done2 + +anum_char: + call move_char ;just an alphanum string + lodsb + cmp al,' ' + je x_done + cmp al,tab + je x_done + cmp al,CR + je x_done + cmp al,',' + je x_done + cmp al,'=' + je x_done + cmp al,dl ;Switch character + jne anum_char +x_done: + dec si ;adjust for next round + mov ax,2 ;normal token +x_done2: + push ax ;save condition code + mov al,0 + stosb ;null at the end + pop ax + pop di ;restore token buffer pointer + popf + clc ;clear carry flag + ret + + +kill_bl proc near + lodsb + cmp al,' ' + je kill_bl + cmp al,tab + je kill_bl + cmp al,',' ;a comma? + je kill_bl + cmp al,'=' + je kill_bl + ret +kill_bl endp + + +move_char proc near + stosb ;store char in token buffer + inc cx ;increment char count + ret +move_char endp + +CODE ENDS + END START + \ No newline at end of file -- cgit v1.2.3