mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-25 07:05:45 +00:00
1645 lines
45 KiB
NASM
1645 lines
45 KiB
NASM
;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
|
||
|