diff --git a/v1.25/source/COMMAND.ASM b/v1.25/source/COMMAND.ASM index 830bf731e..0a08d92e1 100644 --- a/v1.25/source/COMMAND.ASM +++ b/v1.25/source/COMMAND.ASM @@ -1,183 +1,5 @@ -; COMMAND version 1.17 -; -; This version of COMMAND is divided into three distinct parts. First -; is the resident portion, which includes handlers for interrupts -; 22H (terminate), 23H (Cntrl-C), 24H (fatal error), and 27H (stay -; resident); it also has code to test and, if necessary, reload the -; transient portion. Following the resident is the init code, which is -; overwritten after use. Then comes the transient portion, which -; includes all command processing (whether internal or external). -; The transient portion loads at the end of physical memory, and it may -; be overlayed by programs that need as much memory as possible. When -; the resident portion of command regains control from a user program, -; a checksum is performed on the transient portion to see if it must be -; reloaded. Thus programs which do not need maximum memory will save -; the time required to reload COMMAND when they terminate. - -;Use the following booleans to set assembly flags -FALSE EQU 0 -TRUE EQU NOT FALSE - -IBMVER EQU FALSE ;Switch to build IBM version of Command -MSVER EQU TRUE ;Switch to build MS-DOS version of Command - -HIGHMEM EQU TRUE ;Run resident part above transient (high memory) - -LINPERPAG EQU 23 -NORMPERLIN EQU 1 -WIDEPERLIN EQU 5 - - IF IBMVER -SYM EQU ">" -COMDRV EQU 1 - ENDIF - - IF MSVER -SYM EQU ":" -COMDRV EQU 0 - ENDIF - -FCB EQU 5CH -DSKRESET EQU 13 -SETBASE EQU 38 -SRCHFRST EQU 17 -SRCHNXT EQU 18 -RENAM EQU 23 -INCHAR EQU 1 -GETFAT EQU 27 -OPEN EQU 15 -CLOSE EQU 16 -MAKE EQU 22 -DELETE EQU 19 -RDBLK EQU 39 -WRBLK EQU 40 -SETDMA EQU 26 -SELDRV EQU 14 -GETDRV EQU 25 -PRINTBUF EQU 9 -OUTCH EQU 2 -INBUF EQU 10 -GETDATE EQU 2AH -SETDATE EQU 2BH -GETTIME EQU 2CH -SETTIME EQU 2DH -RR EQU 33 -RECLEN EQU 14 -FILLEN EQU 16 -OFFDATE EQU 20 - - -;The following are all of the segments used in the load order - -CODERES SEGMENT -CODERES ENDS - -DATARES SEGMENT BYTE -DATARES ENDS - -INIT SEGMENT BYTE -INIT ENDS - -TAIL SEGMENT PARA -TAIL ENDS - -TRANCODE SEGMENT PARA -TRANCODE ENDS - -TRANDATA SEGMENT BYTE -TRANDATA ENDS - -TRANSPACE SEGMENT BYTE -TRANSPACE ENDS - -RESGROUP GROUP CODERES,DATARES,INIT,TAIL -TRANGROUP GROUP TRANCODE,TRANDATA,TRANSPACE - -;Data for resident portion - -DATARES SEGMENT BYTE - ORG 0 -ZERO = $ -MESBAS DW OFFSET RESGROUP:ERR0 - DW OFFSET RESGROUP:ERR2 - DW OFFSET RESGROUP:ERR4 - DW OFFSET RESGROUP:ERR6 - DW OFFSET RESGROUP:ERR8 - DW OFFSET RESGROUP:ERR10 - DW OFFSET RESGROUP:ERR12 -ERR0 DB "Write protect$" -ERR2 DB "Not ready$" -ERR4 DB "Data$" -ERR6 DB "Seek$" -ERR8 DB "Sector not found$" -ERR10 DB "Write fault$" -ERR12 DB "Disk$" -READ DB "read$" -WRITE DB "writ$" -ERRMES DB " error " -IOTYP DB "writing" -DRVNUM DB " drive " -DRVLET DB "A" -NEWLIN DB 13,10,"$" -REQUEST DB "Abort, Retry, Ignore? $" -BADFAT DB 13,10,"File allocation table bad,$" -COMBAD DB 13,10,"Invalid COMMAND.COM" -NEEDCOM DB 13,10,"Insert DOS disk in " - IF IBMVER - DB "drive A" - ELSE - DB "default drive" - ENDIF -PROMPT DB 13,10,"and strike any key when ready",13,10,"$" -NEEDBAT DB 13,10,"Insert disk with batch file$" -ENDBATMES DB 13,10,"Terminate batch job (Y/N)? $" -LOADING DB 0 -BATFCB DB 1,"AUTOEXECBAT" - DB 21 DUP(?) - DW 0 - DW 0 ;Initialize RR field to zero -PARMTAB DW 10 DUP(-1) ;No parameters initially -BATCH DB 1 ;Assume batch mode initially -COMFCB DB COMDRV,"COMMAND COM" - DB 25 DUP(?) -TRANS DW OFFSET TRANGROUP:COMMAND -TRNSEG DW ? -BATBYT DB ? -MEMSIZ DW ? -SUM DW ? -INITADD DB 4 DUP(?) -RESDATASIZE EQU $-ZERO -DATARES ENDS - -;Data for transient portion - -TRANDATA SEGMENT BYTE - ORG 0 -ZERO EQU $ -BADNAM DB "Bad command or file name",13,10,"$" -MISNAM DB "Missing file name$" -RENERR DB "Duplicate file name or " -NOTFND DB "File not found$" -EXEBAD DB "Error in EXE file$" -NOSPACE DB "Insufficient disk space",13,10,"$" -FULDIR DB "File creation error",13,10,"$" -OVERWR DB "File cannot be copied onto itself",13,10,"$" -LOSTERR DB "Content of destination lost before copy",13,10,"$" -COPIED DB " File(s) copied$" -DIRMES DB " File(s)$" -TOOBIG DB "Program too big to fit in memory$" -BADDRV DB "Invalid drive specification$" -PAUSMES DB "Strike a key when ready . . . $" -BADSWT DB "Illegal switch",13,10,"$" -WEEKTAB DB "SunMonTueWedThuFriSat" -BADDAT DB 13,10,"Invalid date$" -CURDAT DB "Current date is $" -NEWDAT DB 13,10,"Enter new date: $" -BADTIM DB 13,10,"Invalid time$" -CURTIM DB "Current time is $" -NEWTIM DB 13,10,"Enter new time: $" -SUREMES DB "Are you sure (Y/N)? $" - +; ...existing code... +; Add new command to COMTAB COMTAB DB 4,"DIR",1 DW OFFSET TRANGROUP:CATALOG DB 7,"RENAME",1 @@ -196,1971 +18,20 @@ COMTAB DB 4,"DIR",1 DW OFFSET TRANGROUP:COPY DB 6,"PAUSE",1 DW OFFSET TRANGROUP:PAUSE + DB 3,"GPT",1 + DW OFFSET TRANGROUP:GPTCMD DB 5,"DATE",0 DW OFFSET TRANGROUP:DATE DB 5,"TIME",0 DW OFFSET TRANGROUP:TIME DB 0 ;Terminate command table -COMBUF DB 128,1,13 - -TRANDATASIZE EQU $-ZERO -TRANDATA ENDS - -;Uninitialized transient data -TRANSPACE SEGMENT BYTE - ORG 0 -ZERO = $ - DB 128 DUP(?) -TPA DW 1 DUP(?) -RESSEG DW 1 DUP(?) -CHKDRV DB 1 DUP(?) -FILTYP DB 1 DUP(?) -CURDRV DB 1 DUP(?) -PARM1 DB 1 DUP(?) -PARM2 DB 1 DUP(?) -COMSW DW 1 DUP(?) -ARG1S DW 1 DUP(?) -ARG2S DW 1 DUP(?) -FLAGER DB 1 DUP(?) -CFLAG DB 1 DUP(?) -SPECDRV DB 1 DUP(?) -BYTCNT DW 1 DUP(?) -NXTADD DW 1 DUP(?) -LINCNT DB 1 DUP(?) -LINLEN DB 1 DUP(?) -FILECNT DW 1 DUP(?) -EXEFCB LABEL WORD -IDLEN DB 1 DUP(?) -ID DB 8 DUP(?) -COM DB 3 DUP(?) -DEST DB 37 DUP(?) -DESTNAME DB 11 DUP(?) -DIRBUF DB 37 DUP(?) -BITS DW 1 DUP(?) -FULLSCR DW 1 DUP(?) -EXEEND DW 1 DUP(?) -;Header variables for EXE file load -;These are overlapped with COPY variables, below -RUNVAR LABEL WORD -RELPT DW 1 DUP(?) -RELSEG DW 1 DUP(?) -PSIZE LABEL WORD -PAGES DW 1 DUP(?) -RELCNT DW 1 DUP(?) -HEADSIZ DW 1 DUP(?) - DW 1 DUP(?) -LOADLOW DW 1 DUP(?) -INITSS DW 1 DUP(?) -INITSP DW 1 DUP(?) - DW 1 DUP(?) -INITIP DW 1 DUP(?) -INITCS DW 1 DUP(?) -RELTAB DW 1 DUP(?) -RUNVARSIZ EQU $-RUNVAR - - DB 80H DUP(?) -STACK LABEL WORD - -PRETRLEN EQU $-ZERO ;Used later to compute TRNLEN - - ORG RUNVAR-ZERO ;Overlaps EXE variables - -SRCPT DW 1 DUP(?) -INEXACT DB 1 DUP(?) -APPEND DB 1 DUP(?) -NOWRITE DB 1 DUP(?) -ASCII DB 1 DUP(?) -PLUS DB 1 DUP(?) -SOURCE DB 11 DUP(?) -TRANSPACESIZE EQU $-ZERO -TRANSPACE ENDS - - -;START OF RESIDENT PORTION - -CODERES SEGMENT -ASSUME CS:RESGROUP,DS:RESGROUP,ES:RESGROUP,SS:RESGROUP - ORG 0 -ZERO = $ -PARMBUF LABEL WORD - - ORG 100H - -RSTACK LABEL WORD - -PROGSTART: - JMP CONPROC - -LTPA DW 0 ;WILL STORE TPA SEGMENT HERE -MYSEG DW 0 ;Put our own segment here - -CONTC: - MOV AX,CS - MOV DS,AX - MOV SS,AX - MOV SP,OFFSET RESGROUP:RSTACK - STI - CALL SETVECT - MOV AH,DSKRESET - INT 33 ;Reset disks in case files were open - TEST [BATCH],-1 - JZ LODCOM -ASKEND: - MOV DX,OFFSET RESGROUP:ENDBATMES - MOV AH,PRINTBUF - INT 33 - MOV AX,0C00H+INCHAR - INT 33 - AND AL,5FH - CMP AL,"N" - JZ LODCOM - CMP AL,"Y" - JNZ ASKEND - MOV [BATCH],0 -LODCOM: - MOV AX,CS - MOV SS,AX - MOV SP,OFFSET RESGROUP:RSTACK - MOV DS,AX - CALL SETVECT - CALL CHKSUM - CMP DX,[SUM] - JZ HAVCOM - MOV [LOADING],1 - CALL LOADCOM -CHKSAME: - CALL CHKSUM - CMP DX,[SUM] - JZ HAVCOM - CALL WRONGCOM - JMP SHORT CHKSAME -HAVCOM: - MOV [LOADING],0 - MOV SI,OFFSET RESGROUP:LTPA - MOV DI,OFFSET TRANGROUP:TPA - MOV ES,[TRNSEG] - CLD - MOVSW ;Move TPA segment to transient storage - MOVSW ;Move resident segment too - MOV AX,[MEMSIZ] - MOV WORD PTR ES:[2],AX - JMP DWORD PTR [TRANS] - -RESIDENT: - ADD DX,15 - MOV CL,4 - SHR DX,CL ;Number of paragraphs of new addition - ADD CS:[LTPA],DX - XOR AX,AX - MOV DS,AX - JMP DWORD PTR DS:[80H] ;Pretend user executed INT 20H - -DSKERR: - ;****************************************************** - ; THIS IS THE DEFAULT DISK ERROR HANDLING CODE - ; AVAILABLE TO ALL USERS IF THEY DO NOT TRY TO - ; INTERCEPT INTERRUPT 24H. - ;****************************************************** - STI - PUSH DS - PUSH CS - POP DS ;Set up local data segment - PUSH DX - CALL CRLF - POP DX - ADD AL,"A" ;Compute drive letter - MOV [DRVLET],AL - TEST AH,80H ;Check if hard disk error - JNZ FATERR - MOV SI,OFFSET RESGROUP:READ - TEST AH,1 - JZ SAVMES - MOV SI,OFFSET RESGROUP:WRITE -SAVMES: - LODSW - MOV WORD PTR [IOTYP],AX - LODSW - MOV WORD PTR [IOTYP+2],AX - AND DI,0FFH - CMP DI,12 - JBE HAVCOD - MOV DI,12 -HAVCOD: - MOV DI,WORD PTR [DI+MESBAS] ;Get pointer to error message - XCHG DI,DX ;May need DX later - MOV AH,PRINTBUF - INT 33 ;Print error type - MOV DX,OFFSET RESGROUP:ERRMES - INT 33 - CMP [LOADING],0 - JNZ GETCOMDSK -ASK: - MOV DX,OFFSET RESGROUP:REQUEST - MOV AH,PRINTBUF - INT 33 - MOV AX,0C00H+INCHAR - INT 33 ;Get response - CALL CRLF - OR AL,20H ;Convert to lower case - MOV AH,0 ;Return code for ignore - CMP AL,"i" ;Ignore? - JZ EXIT - INC AH - CMP AL,"r" ;Retry? - JZ EXIT - INC AH - CMP AL,"a" ;Abort? - JNZ ASK -EXIT: - MOV AL,AH - MOV DX,DI - POP DS - IRET - -FATERR: - MOV DX,OFFSET RESGROUP:BADFAT - MOV AH,PRINTBUF - INT 33 - MOV DX,OFFSET RESGROUP:DRVNUM - INT 33 - MOV AL,2 ;Abort - POP DS - IRET - -GETCOMDSK: - MOV DX,OFFSET RESGROUP:NEEDCOM - MOV AH,PRINTBUF - INT 33 - MOV AX,0C07H ;Get char without testing or echo - INT 33 - JMP LODCOM - -CRLF: - MOV DX,OFFSET RESGROUP:NEWLIN - PUSH AX - MOV AH,PRINTBUF - INT 33 - POP AX -RET10: RET - -LOADCOM: - PUSH DS - MOV DS,[TRNSEG] - MOV DX,100H - MOV AH,SETDMA - INT 33 - POP DS - MOV DX,OFFSET RESGROUP:COMFCB - MOV AH,OPEN - INT 33 ;Open COMMAND.COM - OR AL,AL - JZ READCOM - MOV DX,OFFSET RESGROUP:NEEDCOM -PROMPTCOM: - MOV AH,PRINTBUF - INT 33 - MOV AX,0C07H ;Get char without testing or echo - INT 33 - JMP SHORT LOADCOM -READCOM: - MOV WORD PTR[COMFCB+RR],OFFSET RESGROUP:TRANSTART - XOR AX,AX - MOV WORD PTR[COMFCB+RR+2],AX - MOV [COMFCB],AL ;Use default drive - INC AX - MOV WORD PTR[COMFCB+RECLEN],AX - MOV CX,COMLEN - MOV DX,OFFSET RESGROUP:COMFCB - MOV AH,RDBLK - INT 33 - OR AL,AL - JZ RET10 -WRONGCOM: - MOV DX,OFFSET RESGROUP:COMBAD - JMP SHORT PROMPTCOM - -CHKSUM: - CLD - PUSH DS - MOV DS,[TRNSEG] - MOV SI,100H - MOV CX,COMLEN - SHR CX,1 - XOR DX,DX -CHK: - LODSW - ADD DX,AX - LOOP CHK - POP DS - RET - -SETVECT: - MOV DX,OFFSET RESGROUP:LODCOM - MOV AX,2522H ;Set Terminate address - INT 21H - MOV DX,OFFSET RESGROUP:CONTC - MOV AX,2523H ;Set Ctrl-C address - INT 21H - MOV DX,OFFSET RESGROUP:DSKERR - MOV AX,2524H ;Set Hard Disk Error address - INT 33 - MOV DX,OFFSET RESGROUP:RESIDENT - MOV AX,2527H ;Set Terminate and Stay Resident address - INT 33 - RET -RESCODESIZE EQU $-ZERO -CODERES ENDS - -;******************************************************************* -;START OF INIT PORTION -;This code is overlayed the first time the TPA is used. - -INIT SEGMENT BYTE - - ORG 0 -ZERO = $ -CONPROC: - MOV SP,OFFSET RESGROUP:RSTACK - - IF HIGHMEM - MOV AX,WORD PTR DS:[2] - SUB AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Subtract size of resident - MOV WORD PTR DS:[2],AX - MOV ES,AX - MOV SI,100H - MOV DI,SI - MOV CX,((RESCODESIZE+RESDATASIZE)-100H+1)/2 ;Length of resident in words - REP MOVSW ;Move to end of memory - MOV DS,AX - MOV [LTPA],CS - ENDIF - - IF NOT HIGHMEM - MOV AX,CS - ADD AX,((RESCODESIZE+RESDATASIZE)+15)/16 ;Compute segment of TPA - MOV [LTPA],AX - MOV AX,WORD PTR DS:[2] - ENDIF - - MOV [MYSEG],DS - MOV [MEMSIZ],AX - SUB AX,TRNLEN ;Subtract size of transient - MOV [TRNSEG],AX - CALL SETVECT - CALL LOADCOM - CALL CHKSUM - MOV [SUM],DX - - IF MSVER - IF HIGHMEM - PUSH DS - PUSH CS - POP DS - ENDIF - MOV DX,OFFSET RESGROUP:HEADER - MOV AH,PRINTBUF - INT 33 - IF HIGHMEM - POP DS - ENDIF - ENDIF - - MOV DX,OFFSET RESGROUP:BATFCB - MOV AH,OPEN - INT 33 ;See if AUTOEXEC.BAT exists - MOV WORD PTR[BATFCB+RECLEN],1 ;Set record length to 1 - OR AL,AL ;Zero means file found - JZ DRV0 - MOV [BATCH],0 ;Not found--turn off batch job - MOV AX,OFFSET TRANGROUP:DATINIT - MOV WORD PTR[INITADD],AX - MOV AX,[TRNSEG] - MOV WORD PTR[INITADD+2],AX - CALL DWORD PTR DS:[INITADD] - - IF IBMVER - MOV DX,OFFSET RESGROUP:HEADER - MOV AH,PRINTBUF - INT 33 - ENDIF - -DRV0: - JMP HAVCOM - - - IF MSVER -HEADER DB 13,10,"Command v. 1.17" - IF HIGHMEM - DB "H" - ENDIF - DB 13,10,"$" - ENDIF - - IF IBMVER -HEADER DB 13,10,13,10,"The IBM Personal Computer DOS",13,10 - DB "Version 1.10 (C)Copyright IBM Corp 1981, 1982",13,10,"$" - DB "Licensed Material - Program Property of IBM" - ENDIF - -INITSIZE EQU $-ZERO -INIT ENDS - -;This TAIL segment is used to produce a PARA aligned label in the resident -; group which is the location where the transient segments will be loaded -; initialy. - -TAIL SEGMENT PARA - ORG 0 -TRANSTART LABEL WORD -TAIL ENDS - -;******************************************************************** -;START OF TRANSIENT PORTION -;This code is loaded at the end of memory and may be overwritten by -;memory-intensive user programs. - -TRANCODE SEGMENT PARA -ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:TRANGROUP - -WSWITCH EQU 1 ;Wide display during DIR -PSWITCH EQU 2 ;Pause (or Page) mode during DIR -VSWITCH EQU 4 ;Verify during COPY -ASWITCH EQU 8 ;ASCII mode during COPY -BSWITCH EQU 10H ;Binary mode during COPY - - ORG 0 -ZERO = $ - - ORG 100H ;Allow for 100H parameter area - -SETDRV: - MOV AH,SELDRV - INT 21H -COMMAND: - CLD - MOV AX,CS - MOV SS,AX - MOV SP,OFFSET TRANGROUP:STACK - MOV ES,AX - MOV DS,AX - STI - MOV AX,46*100H - MOV DL,0 - INT 33 ;Turn off verify after write - MOV AX,CS ;Get segment we're in - SUB AX,[TPA] ;AX=size ot TPA in paragraphs - MOV DX,16 - MUL DX ;DX:AX=size of TPA in bytes - OR DX,DX ;See if over 64K - JZ SAVSIZ ;OK if not - MOV AX,-1 ;If so, limit to 65535 bytes -SAVSIZ: - MOV [BYTCNT],AX ;Max no. of bytes that can be buffered - CALL CRLF2 -GETCOM: - MOV AH,GETDRV - INT 21H - MOV [CURDRV],AL - ADD AL,"A" - CALL OUT ;Print letter for default drive - MOV AL,SYM - CALL OUT - MOV DS,[RESSEG] ;All batch work must use resident seg. -ASSUME DS:RESGROUP - TEST [BATCH],-1 - JNZ READBAT - PUSH CS - POP DS ;Need local segment to point to buffer -ASSUME DS:TRANGROUP - MOV DX,OFFSET TRANGROUP:COMBUF - MOV AH,INBUF - INT 21H ;Get a command - JMP DOCOM - -;All batch proccessing has DS set to segment of resident portion -ASSUME DS:RESGROUP -NEEDPARM: - CALL GETBATBYT - CMP AL,"%" ;Check for two consecutive % - JZ SAVBATBYT - CMP AL,13 ;Check for end-of-line - JZ SAVBATBYT - SUB AL,"0" - JB RDBAT ;Ignore parameter reference if invalid - CMP AL,9 - JA RDBAT - CBW - MOV SI,AX - SHL SI,1 ;Two bytes per entry - MOV SI,[SI+OFFSET RESGROUP:PARMTAB] ;Get pointer to corresponding parameter - CMP SI,-1 ;Check if parameter exists - JZ RDBAT ;Ignore if it doesn't - MOV AH,OUTCH -RDPARM: - LODSB ;From resident segment - CMP AL,0DH ;Check for end of parameter - JZ RDBAT - STOSB ;To transient segment - MOV DL,AL - INT 33 ;Display paramters too - JMP SHORT RDPARM - -PROMPTBAT: - MOV AH,PRINTBUF - MOV DX,OFFSET RESGROUP:NEEDBAT - INT 33 ;Prompt for batch file - MOV AH,PRINTBUF - MOV DX,OFFSET RESGROUP:PROMPT - INT 33 - MOV AX,0C00H+INCHAR - INT 33 - JMP COMMAND - -BADCOMJ1:JMP BADCOM - -READBAT: - MOV DX,OFFSET RESGROUP:BATFCB - MOV AH,OPEN - INT 33 ;Make sure batch file still exists - OR AL,AL - JNZ PROMPTBAT ;If OPEN fails, prompt for disk - MOV WORD PTR [BATFCB+RECLEN],1 - MOV DX,OFFSET RESGROUP:BATBYT - MOV AH,SETDMA - INT 33 - MOV DI,OFFSET TRANGROUP:COMBUF+2 -RDBAT: - CALL GETBATBYT - CMP AL,"%" ;Check for parameter - JZ NEEDPARM -SAVBATBYT: - STOSB - CALL OUT ;Display batched command line - CMP AL,0DH - JNZ RDBAT - SUB DI,OFFSET TRANGROUP:COMBUF+3 - MOV AX,DI - MOV ES:[COMBUF+1],AL ;Set length of line - CALL GETBATBYT ;Eat linefeed - PUSH CS - POP DS ;Go back to local segment -ASSUME DS:TRANGROUP -DOCOM: -;All segments are local for command line processing - MOV AL,10 - CALL OUT - MOV SI,OFFSET TRANGROUP:COMBUF+2 - MOV DI,OFFSET TRANGROUP:IDLEN - MOV AX,2901H ;Make FCB with blank scan-off - INT 21H - CMP AL,1 ;Check for ambiguous command name - JZ BADCOMJ1 ;Ambiguous commands not allowed - CMP AL,-1 - JNZ DRVGD - JMP DRVBAD -DRVGD: - MOV AL,[DI] - MOV [SPECDRV],AL - MOV AL," " - MOV CX,9 - INC DI - REPNE SCASB ;Count no. of letters in command name - MOV AL,9 - SUB AL,CL - MOV [IDLEN],AL - MOV DI,81H - MOV CX,0 - PUSH SI -COMTAIL: - LODSB - STOSB ;Move command tail to 80H - CMP AL,13 - LOOPNZ COMTAIL - NOT CL - MOV BYTE PTR DS:[80H],CL - POP SI -;If the command has 0 parameters must check here for -;any switches that might be present. -;SI -> first character after the command. - MOV [FLAGER],0 ;Set error flag before any calls to switch - CALL SWITCH ;Is the next character a "/" - MOV [COMSW],AX - MOV DI,FCB - MOV AX,2901H - INT 21H - MOV [PARM1],AL ;Save result of parse - CALL SWITCH - MOV [ARG1S],AX - MOV DI,FCB+10H - MOV AX,2901H - INT 21H ;Parse file name - MOV [PARM2],AL ;Save result - CALL SWITCH - MOV [ARG2S],AX - MOV AL,[IDLEN] - MOV DL,[SPECDRV] - OR DL,DL ;Check if drive was specified - JZ OK - JMP DRVCHK -OK: DEC AL ;Check for null command - JNZ FNDCOM - JMP GETCOM - -RETSW: - XCHG AX,BX ;Put switches in AX - RET - -SWITCH: - XOR BX,BX ;Initialize - no switches set -SWLOOP: - CALL SCANOFF ;Skip any delimiters - CMP AL,"/" ;Is it a switch specifier? - JNZ RETSW ;No -- we're finished - INC SI ;Skip over "/" - CALL SCANOFF - INC SI -;Convert lower case input to upper case - CMP AL,"a" - JB SAVCHR - CMP AL,"z" - JA SAVCHR - SUB AL,20H ;Lower-case changed to upper-case -SAVCHR: - MOV DI,OFFSET TRANGROUP:SWLIST - MOV CX,SWCOUNT - REPNE SCASB ;Look for matching switch - JNZ BADSW - MOV AX,1 - SHL AX,CL ;Set a bit for the switch - OR BX,AX - JMP SHORT SWLOOP - -BADSW: - MOV [FLAGER],1 ;Record error in switch - JMP SHORT SWLOOP - -SWLIST DB "BAVPW" -SWCOUNT EQU $-SWLIST - -DRVBAD: - MOV DX,OFFSET TRANGROUP:BADDRV - JMP ERROR - -FNDCOM: - MOV SI,OFFSET TRANGROUP:COMTAB ;Prepare to search command table - MOV CH,0 -FINDCOM: - MOV DI,OFFSET TRANGROUP:IDLEN - MOV CL,[SI] - JCXZ EXTERNAL - REPE CMPSB - LAHF - ADD SI,CX ;Bump to next position without affecting flags - SAHF - LODSB ;Get flag for drive check - MOV [CHKDRV],AL - LODSW ;Get address of command - JNZ FINDCOM - MOV DX,AX - CMP [CHKDRV],0 - JZ NOCHECK - MOV AL,[PARM1] - OR AL,[PARM2] ;Check if either parm. had invalid drive - CMP AL,-1 - JZ DRVBAD -NOCHECK:CALL DX -COMJMP: JMP COMMAND - -BADCOMJ:JMP BADCOM - -SETDRV1: - JMP SETDRV - -DRVCHK: - DEC DL ;Adjust for correct drive number - DEC AL ;Check if anything else is on line - JZ SETDRV1 -EXTERNAL: - MOV AL,[SPECDRV] - MOV [IDLEN],AL - MOV WORD PTR[COM],4F00H+"C" ;"CO" - MOV BYTE PTR[COM+2],"M" - MOV DX,OFFSET TRANGROUP:IDLEN - MOV AH,OPEN - INT 33 ;Check if command to be executed - MOV [FILTYP],AL ;0 for COM files, -1 for EXE files - OR AL,AL - JZ EXECUTE - MOV WORD PTR[COM],5800H+"E" ;"EX" - MOV BYTE PTR[COM+2],"E" - INT 33 ;Check for EXE file - OR AL,AL - JZ EXECUTE - MOV WORD PTR[COM],4100H+"B" ;"BA" - MOV BYTE PTR[COM+2],"T" - INT 33 ;Check if batch file to be executed - OR AL,AL - JNZ BADCOMJ -BATCOM: -;Batch parameters are read with ES set to segment of resident part - MOV ES,[RESSEG] -ASSUME ES:RESGROUP - MOV DI,OFFSET RESGROUP:PARMTAB - MOV AX,-1 - MOV CX,10 - REP STOSW ;Zero parameter pointer table - MOV SI,OFFSET TRANGROUP:COMBUF+2 - MOV DI,OFFSET RESGROUP:PARMBUF - MOV BX,OFFSET RESGROUP:PARMTAB -EACHPARM: - CALL SCANOFF - CMP AL,0DH - JZ HAVPARM - MOV ES:[BX],DI ;Set pointer table to point to actual parameter - INC BX - INC BX -MOVPARM: - LODSB - CALL DELIM - JZ ENDPARM ;Check for end of parameter - STOSB - CMP AL,0DH - JZ HAVPARM - JMP SHORT MOVPARM -ENDPARM: - MOV AL,0DH - STOSB ;End-of-parameter marker - CMP BX,OFFSET RESGROUP:PARMTAB+20 ;Maximum number of parameters? - JB EACHPARM -HAVPARM: - MOV SI,OFFSET TRANGROUP:IDLEN - MOV DI,OFFSET RESGROUP:BATFCB - MOV CX,16 - REP MOVSW ;Move into private batch FCB - XOR AX,AX - PUSH ES - POP DS ;Simply batch FCB setup -ASSUME DS:RESGROUP - MOV WORD PTR[BATFCB+RR],AX - MOV WORD PTR[BATFCB+RR+2],AX ;Zero RR field - INC AX - MOV WORD PTR[BATFCB+RECLEN],AX ;Set record length to 1 byte - MOV [BATCH],AL ;Flag batch job in progress - JMP COMMAND -ASSUME DS:TRANGROUP,ES:TRANGROUP - -EXECUTE: - MOV AX,WORD PTR[IDLEN+16] - OR AX,WORD PTR[IDLEN+18] ;See if zero length - JZ BADCOM ;If so, error - XOR AX,AX - MOV WORD PTR[IDLEN+RR],AX - MOV WORD PTR[IDLEN+RR+2],AX ;Set RR field to zero - INC AX - MOV WORD PTR[IDLEN+RECLEN],AX ;Set record length field to 1 - MOV DX,[TPA] - MOV BX,DX - MOV AH,SETBASE - INT 21H - TEST [FILTYP],-1 ;Check if file is COM or EXE - JZ COMLOAD - JMP EXELOAD -COMLOAD:PUSH DS - MOV DS,DX - MOV DX,100H - MOV AH,SETDMA - INT 21H - POP DS - MOV CX,[BYTCNT] - SUB CX,100H - MOV DX,OFFSET TRANGROUP:IDLEN - MOV AH,RDBLK - INT 21H - DEC AL - MOV DX,OFFSET TRANGROUP:TOOBIG - JNZ ERROR -;Set up exit conditions - MOV CX,[BYTCNT] - MOV DS,BX - MOV ES,BX - CLI - MOV SS,BX - MOV SP,CX - STI - SUB CX,100H ;Allow some stack space - XOR AX,AX - PUSH AX - MOV AX,100H - PUSH BX - PUSH AX - CALL SETUP -XXX PROC FAR - RET -XXX ENDP -BADCOM: - MOV DX,OFFSET TRANGROUP:BADNAM -ERROR: - MOV AH,PRINTBUF - INT 21H - JMP COMMAND - -CHKCNT: - TEST [FILECNT],-1 - JNZ ENDDIR - MOV DX,OFFSET TRANGROUP:NOTFND - JMP ERROR - -ENDDIR: -;Make sure last line ends with CR/LF - MOV AL,[LINLEN] - CMP AL,[LINCNT] ;Will be equal if just had CR/LF - JZ MESSAGE - CALL CRLF2 -MESSAGE: - MOV SI,[FILECNT] - XOR DI,DI - CALL DISP32BITS - MOV DX,OFFSET TRANGROUP:DIRMES - MOV AH,PRINTBUF - INT 21H - RET - -CATALOG: - MOV AL,"?" ;*.* is default file spec. - MOV DI,5DH - MOV CX,11 - REP STOSB - MOV SI,81H - CALL SWITCH - MOV DI,5CH - MOV AX,41*100H+0DH ;Parse with default name and extension - INT 33 - -;Begin by processing any switches that may have been specified. -;BITS will contain any information about switches that was -;found when the command line was parsed. - -SETSWT: - MOV AX,[COMSW] ;Get switches from command - OR AX,[ARG1S] ;OR in switches from first parameter - MOV [BITS],AX - MOV BYTE PTR[FULLSCR],LINPERPAG - TEST AL,1 ;Look for /W - MOV AL,NORMPERLIN - JZ DIR - MOV AL,WIDEPERLIN -DIR: - MOV [LINLEN],AL ;Set number of entries per line - MOV [LINCNT],AL - MOV [FILECNT],0 ;Keep track of how many files found - MOV DX,OFFSET TRANGROUP:DIRBUF ;Set Disk transfer address - MOV AH,SETDMA - INT 21H - MOV AH,SRCHFRST -SHOWDIR: - MOV DX,5CH ;DX -> Unopened FCB - INT 21H ;Search for a file to match FCB - INC AL ;FF = file not found - JNZ AGAIN ;Either an error or we are finished - JMP CHKCNT -AGAIN: - INC [FILECNT] ;Keep track of how many we find - MOV SI,OFFSET TRANGROUP:DIRBUF+1 ;SI -> information returned by sys call - CALL SHONAME - TEST BYTE PTR[BITS],1 ;/W set? - JNZ NEXENT ;If so, no size, date, or time - CALL DISPSIZE ;Print size of file - CALL TWOSPC - MOV AX,WORD PTR[DIRBUF+25] ;Get date - OR AX,AX - JZ NEXENT ;Skip if no date - MOV DX,AX - MOV CL,5 - SHR AX,CL ;Align month - AND AL,0FH - MOV BH,"0"-" " ;Enable zero suppression - CALL OUT2 - MOV AL,"-" - CALL OUT - MOV AL,DL - AND AL,1FH ;Mask to day - CALL OUT2 - MOV AL,"-" - CALL OUT - MOV AL,DH - SHR AL,1 ;Align year - ADD AX,80 ;Relative 1980 - CMP AL,100 - JB MILLENIUM - SUB AL,100 -MILLENIUM: - CALL OUT2 - MOV BX,WORD PTR[DIRBUF+23] ;Get time - OR BX,BX ;Time field present? - JZ NEXENT - CALL TWOSPC - SHR BX,1 - SHR BX,1 - SHR BX,1 - SHR BL,1 - SHR BL,1 ;Hours in BH, minutes in BL - MOV AL,BH - MOV DH,"a" ;Assume A.M. - CMP AL,12 ;In the afternoon? - JB MORN - MOV DH,"p" - JE MORN - SUB AL,12 ;Keep it to 12 hours or less -MORN: - OR AL,AL ;Before 1 am? - JNZ SHOHOURS - MOV AL,12 -SHOHOURS: - MOV BH,"0"-" " ;Enable zero suppression - CALL OUT2 - MOV AL,":" - CALL OUT - MOV AL,BL ;Output minutes - CALL OUT2 - MOV AL,DH ;Get "a" or "p" - CALL OUT -NEXENT: - DEC [LINCNT] - JNZ SAMLIN -NEXLIN: - MOV AL,[LINLEN] - MOV [LINCNT],AL - CALL CRLF2 - TEST BYTE PTR[BITS],2 ;/P switch present? - JZ SCROLL ;If not, just continue - DEC BYTE PTR[FULLSCR] - JNZ SCROLL - MOV BYTE PTR[FULLSCR],LINPERPAG - MOV AH,PRINTBUF - MOV DX,OFFSET TRANGROUP:PAUSMES - INT 33 - MOV AX,0C08H ;Wait for any character to be typed - INT 21H - CALL CRLF2 -SCROLL: - MOV AH,SRCHNXT - JMP SHOWDIR - -SAMLIN: - MOV AL,9 ;Output a tab - CALL OUT - JMP SHORT SCROLL - -SHONAME: - MOV CX,8 - CALL OUTCNT - CALL ONESPC - MOV CX,3 -OUTCNT: - LODSB - CALL OUT - LOOP OUTCNT - RET - -TWOSPC: - CALL ONESPC -ONESPC: - MOV AL," " - JMP OUT - -CRLF2: - MOV AL,13 - CALL OUT - MOV AL,10 - JMP OUT - -DISPSIZE: - MOV SI,WORD PTR[DIRBUF+29] - MOV DI,WORD PTR[DIRBUF+31] -DISP32BITS: -;Prints the 32-bit number DI:SI on the console in decimal. Uses a total -;of 9 digit positions with leading blanks. - XOR AX,AX - MOV BX,AX - MOV BP,AX - MOV CX,32 -CONVLP: - SHL SI,1 - RCL DI,1 - XCHG AX,BP - CALL CONVWRD - XCHG AX,BP - XCHG AX,BX - CALL CONVWRD - XCHG AX,BX - ADC AL,0 - LOOP CONVLP -; Conversion complete. Print 9-digit number. - MOV CX,1810H ;Allow leading zero blanking for 8 digits - XCHG DX,AX - CALL DIGIT - XCHG AX,BX - CALL OUTWORD - XCHG AX,BP -OUTWORD: - PUSH AX - MOV DL,AH - CALL OUTBYTE - POP DX -OUTBYTE: - MOV DH,DL - SHR DL,1 - SHR DL,1 - SHR DL,1 - SHR DL,1 - CALL DIGIT - MOV DL,DH -DIGIT: - AND DL,0FH - JZ BLANKZER - MOV CL,0 -BLANKZER: - DEC CH - AND CL,CH - OR DL,30H - SUB DL,CL - MOV AH,OUTCH - INT 21H - RET - -CONVWRD: - ADC AL,AL - DAA - XCHG AL,AH - ADC AL,AL - DAA - XCHG AL,AH -RET20: RET - -ERASE: - MOV CX,11 - MOV SI,FCB+1 -AMBSPEC: - LODSB - CMP AL,"?" - JNZ ALLFIL - LOOP AMBSPEC -ALLFIL: - CMP CX,0 - JNZ NOPRMPT -ASKAGN: - MOV DX,OFFSET TRANGROUP:SUREMES ;"Are you sure (Y/N)?" +; ...existing code... +; Add the GPT command handler +GPTMSG DB 'gpt-4.1 was there',13,10,'$' +GPTCMD: + MOV DX,OFFSET TRANGROUP:GPTMSG MOV AH,PRINTBUF - INT 21H - MOV AX,0C00H+INCHAR - INT 21H - AND AL,5FH - CMP AL,"N" - JZ RET20 - CMP AL,"Y" - CALL CRLF2 - JZ NOPRMPT - JMP SHORT ASKAGN -NOPRMPT: - MOV AH,DELETE - MOV BX,OFFSET TRANGROUP:NOTFND - CMP BYTE PTR DS:[FCB+1]," " ;Check if parameter exists - JMP SHORT OPFILE -RENAME: - MOV AH,RENAM - MOV BX,OFFSET TRANGROUP:RENERR - CMP BYTE PTR DS:[FCB+16+1]," " ;Check if parameter exists -OPFILE: - MOV DX,OFFSET TRANGROUP:MISNAM - JZ ERRJ ;Error if missing parameter - MOV DX,FCB - INT 21H - INC AL - JNZ RET20 - MOV DX,BX -ERRJ: JMP ERROR - -TYPEFIL: - MOV DS,[TPA] - XOR DX,DX - MOV AH,SETDMA - INT 21H - PUSH CS - POP DS - MOV DX,FCB - MOV AH,OPEN - INT 21H - OR AL,AL - MOV DX,OFFSET TRANGROUP:NOTFND - JNZ ERRJ - XOR AX,AX - MOV WORD PTR DS:[FCB+RR],AX ;Set RR field - MOV WORD PTR DS:[FCB+RR+2],AX - INC AX - MOV WORD PTR DS:[FCB+RECLEN],AX ;Set record length - MOV ES,[TPA] -TYPELP: - MOV DX,FCB - MOV CX,[BYTCNT] - MOV AH,RDBLK - INT 21H - JCXZ RET30 - XOR SI,SI ;Start at 0 in TPA -OUTLP: - LODS BYTE PTR ES:[SI] ;In TPA segment - CMP AL,1AH - JZ RET30 - MOV AH,OUTCH - MOV DL,AL - INT 21H - LOOP OUTLP - JMP SHORT TYPELP - -RET30: RET ;Need a nearby RET - -COPY: - XOR AX,AX - MOV [PLUS],AL ;Will keep track of "+"s - MOV [FILECNT],AX - MOV SI,81H ;Point to input line - CALL SWITCH ;Skip over switches on command - MOV BP,AX - MOV DI,FCB - CALL PARSNAM ;Scan first source - MOV [PARM1],DL ;Save ambiguous flag - MOV [SRCPT],SI ;Save pointer to command line -;Parse each name to find destination and check for /V switch -SCANNAM: - CALL PARSE - JNZ SCANNAM -GETDEST: - MOV DI,OFFSET TRANGROUP:DEST - MOV BX,BP ;Remeber switches so far - XOR BP,BP ;Must have dest. swtiches alone - CALL PARSNAM - MOV [ARG2S],BP ;Remember switches on destination - JNZ HAVDESTNAM ;File name present? - INC DI ;Point to file name spot - MOV AL,"?" ;Substitute *.* - MOV CX,11 - REP STOSB -HAVDESTNAM: - OR BX,BP ;BX = all switches combined - AND BL,VSWITCH ;Verify requested? - JZ NOVER - MOV AX,46*100H+1 ;Set verify - MOV DL,0 INT 33 -NOVER: - MOV DI,OFFSET TRANGROUP:DESTNAME - MOV SI,OFFSET TRANGROUP:DEST+1 - MOV BX,FCB+1 - CALL BUILDNAME ;See if we can make it unambiguous - MOV DI,OFFSET TRANGROUP:DESTNAME - MOV AL,"?" - MOV CX,11 - REPNE SCASB ;Scan for "?" to see if ambiguous - MOV AL,1 ;Flag if ambig. - JZ AMBIG - DEC AX ;AL=0 if unambig. -AMBIG: - MOV DL,AL - MOV AH,[PLUS] ;1=found "+" - XOR AL,1 ;0=ambig, 1=unambig destination - AND AL,[PARM1] ;Source ambig. AND dest unambig. - OR AL,AH ;OR found "+" means concatenation - MOV [ASCII],AL ;Concatenation implies ASCII mode - MOV [INEXACT],AL ;ASCII implies inexact copy - SHL AL,1 - OR AL,DL ;Combine multiple and concat flags - MOV [PARM2],AL - MOV AL,BYTE PTR[COMSW] - CALL SETASC ;Check /A,/B on command - MOV AL,BYTE PTR[ARG1S] - CALL SETASC ;Check for ASCII on first filename - MOV BYTE PTR[COMSW],AL ;Save starting switch values - MOV AH,SRCHFRST - CALL SEARCH ;Search for first source name -MULTDEST: - JZ FIRSTSRC ;Find a first source name? - TEST [PARM2],1 ;If multiple, we're done - JNZ ENDCOPY - XOR AX,AX - MOV [NXTADD],AX - MOV [CFLAG],AL ;Flag nothing read yet -NEXTSNG: - MOV DI,FCB - MOV SI,[SRCPT] - CALL PARSESRC ;Parse next file name into FCB - MOV [PARM1],DL ;Remember if it's ambiguous - MOV [SRCPT],SI - JZ SNGCLOS - MOV AH,SRCHFRST - CALL SEARCH ;Search for new file name - JNZ NEXTSNG ;If none, skip it and move to next name -READSNG: - CALL CHECKREAD -SNGLOOP: - CALL SEARCHNEXT ;See if any more of this name - JZ READSNG - JMP SHORT NEXTSNG - -SNGCLOS: - CALL CLOSEFIL -ENDCOPY: - MOV SI,[FILECNT] - XOR DI,DI - CALL DISP32BITS - MOV DX,OFFSET TRANGROUP:COPIED - MOV AH,PRINTBUF - INT 21H - JMP COMMAND ;Stack could be messed up - -FIRSTSRC: - MOV SI,OFFSET TRANGROUP:DIRBUF+1 - MOV DI,OFFSET TRANGROUP:SOURCE - MOV CX,11 - REP MOVSB ;Copy first source name to SOURCE - MOV SI,OFFSET TRANGROUP:DESTNAME - MOV DI,OFFSET TRANGROUP:DEST+1 - MOV BX,OFFSET TRANGROUP:SOURCE - CALL BUILDNAME ;Build destination name - XOR AX,AX - MOV [NXTADD],AX - MOV [CFLAG],AL - MOV [APPEND],AL - MOV [NOWRITE],AL - TEST [PARM2],1 ;Multiple destinations? - JZ NOPRT - MOV SI,OFFSET TRANGROUP:DIRBUF+1 - CALL SHONAME ;If so, show first source - CALL CRLF2 -NOPRT: - CALL COMPNAME ;Source and dest. the same? - JNZ DOREAD ;If not, read source in - TEST [PARM2],2 ;Concatenation? - MOV DX,OFFSET TRANGROUP:OVERWR - JZ COPERRJ ;If not, overwrite error - MOV [APPEND],1 ;Set physical append - MOV AH,OPEN - MOV DX,OFFSET TRANGROUP:DEST - INT 33 ;Open (existing) destination - CMP [ASCII],0 ;ASCII flag set? - JZ BINARYAPP -;ASCII append. Must find logical EOF, then seek there with dest. FCB - MOV [NOWRITE],1 - CALL READIN ;Find EOF - CALL FLSHFIL ;Seek there - MOV [NOWRITE],0 - CALL FLSHFIL ;Truncate file - JMP SHORT SNGLCHK - -SNGLOOPJ:JMP SNGLOOP - -COPERRJ:JMP COPERR - -BINARYAPP: - MOV WORD PTR[DEST+RECLEN],1 ;Set record length to 1 - MOV SI,OFFSET TRANGROUP:DEST+16 ;Point to file size - MOV DI,OFFSET TRANGROUP:DEST+RR - MOVSW - MOVSW ;Seek to end of file - MOV [CFLAG],1 - JMP SHORT SNGLCHK -DOREAD: - CALL READIN -SNGLCHK: - TEST [PARM2],1 ;Single or multiple destinations? - JZ SNGLOOPJ - MOV SI,[SRCPT] -MULTAPP: - CALL PARSE - JZ MULTCLOS - PUSH SI - MOV SI,OFFSET TRANGROUP:DIRBUF+1 - MOV DI,SI - MOV BX,OFFSET TRANGROUP:SOURCE - CALL BUILDNAME - CALL CHECKREAD - POP SI - JMP SHORT MULTAPP -MULTCLOS: - CALL CLOSEFIL - MOV AL,BYTE PTR[COMSW] - MOV [ASCII],AL ;Restore ASCII flag - CALL SEARCHNEXT - JMP MULTDEST - -PARSE: - MOV DI,OFFSET TRANGROUP:DIRBUF -PARSESRC: - CALL SCANOFF - CMP AL,"+" - JNZ RETZF - MOV [PLUS],1 ;Keep track of "+" signs - INC SI ;Skip over it -PARSNAM: - MOV AX,2901H - INT 33 ;Parse file name - CMP AL,-1 ;Illegal? - MOV DX,OFFSET TRANGROUP:BADDRV - JZ COPERRJ - XCHG AX,DX ;Save parse flag in DL - MOV AL,BYTE PTR[DI] ;Get drive number - OR AL,AL ;Is it default? - JNZ PARSW - MOV AL,[CURDRV] ;Substitute actual drive - INC AX - MOV BYTE PTR[DI],AL -PARSW: - PUSH BX - PUSH DI - CALL SWITCH ;Process switches - OR BP,AX ;Combine all switches - CALL SETASC ;Check for /A or /B - POP DI - POP BX - CMP BYTE PTR[DI+1]," " ;Did we even get a file name? RET - -RETZF: - XOR AX,AX -RET35: RET - -SEARCHNEXT: - MOV AL,[PARM1] ;Is name ambiguous? - DEC AL - JNZ RET35 ;Don't perform search if not - MOV AH,SRCHNXT -SEARCH: - PUSH AX - MOV AH,SETDMA - MOV DX,OFFSET TRANGROUP:DIRBUF - INT 33 ;Put result of search in DIRBUF - POP AX ;Restore search first/next command - MOV DX,FCB - INT 33 ;Do the search - OR AL,AL - RET - -SETASC: -;Given switch vector in AX, -; Set ASCII switch if /A is set -; Clear ASCII switch if /B is set -; Leave ASCII unchanged if neither or both are set -; Also sets INEXACT if ASCII is ever set. AL = ASCII on exit, flags set - AND AL,ASWITCH+BSWITCH - JPE LOADSW ;PE means both or neither are set - AND AL,ASWITCH - MOV [ASCII],AL - OR [INEXACT],AL -LOADSW: - MOV AL,[ASCII] - OR AL,AL - RET - -BUILDNAME: -; [SI] = Ambiguous input file name -; [BX] = Source of replacement characters -; [DI] = Destination -; File name is copied from [SI] to [DI]. If "?"s are encountered, -; they are replaced with the character in the same position at [BX]. - MOV CX,11 -BUILDNAM: - LODSB - CMP AL,"?" - JNZ NOTAMBIG - MOV AL,BYTE PTR[BX] -NOTAMBIG: - STOSB - INC BX - LOOP BUILDNAM - RET - -COMPNAME: - MOV SI,OFFSET TRANGROUP:DEST - MOV DI,OFFSET TRANGROUP:DIRBUF - MOV CX,6 - REPE CMPSW - RET - -CHECKREAD: -;Read file in (with READIN) if not identical to destination - CALL COMPNAME ;See if source and destination the same - JNZ READIN - CMP [APPEND],0 ;If physical append, it's OK - JNZ RET40 - MOV DX,OFFSET TRANGROUP:LOSTERR ;Tell him he's not going to get it - MOV AH,PRINTBUF - INT 33 -RET40: RET - -READIN: -;Open source file and read it in. If memory fills up, flush it out to -;destination and keep reading. If /A switch set, chop file at first ^Z. -; Inputs/Outputs: -; [NXTADD] has current pointer in buffer -; [CFLAG] <>0 if destination has been created - - MOV DX,OFFSET TRANGROUP:DIRBUF - MOV AH,OPEN - INT 21H - OR AL,AL ;Successful open? - JNZ RET40 ;If not, just ignore it - XOR AX,AX - MOV WORD PTR[DIRBUF+RR],AX - MOV WORD PTR[DIRBUF+RR+2],AX - INC AX - MOV WORD PTR[DIRBUF+RECLEN],AX -COPYLP: - MOV DX,[NXTADD] - MOV AH,SETDMA - PUSH DS - MOV DS,[TPA] - INT 33 - POP DS - MOV CX,[BYTCNT] - SUB CX,DX ;Compute available space - MOV DX,OFFSET TRANGROUP:DIRBUF - MOV AH,RDBLK ;Read in source file - INT 21H - JCXZ RET40 - CMP [ASCII],0 - JZ BINREAD - MOV DX,CX - MOV DI,[NXTADD] - MOV AL,1AH - PUSH ES - MOV ES,[TPA] - REPNE SCASB ;Scan for EOF - POP ES - JNZ USEALL - INC CX -USEALL: - SUB DX,CX - MOV CX,DX -BINREAD: - ADD CX,[NXTADD] - MOV [NXTADD],CX - CMP CX,[BYTCNT] ;Is buffer full? - JB RET40 ;If not, we must have found EOF - CALL FLSHFIL - JMP SHORT COPYLP - -CLOSEFIL: - MOV AX,[NXTADD] - MOV BX,AX - OR AL,AH ;See if any data is loaded - OR AL,[CFLAG] ; or file was created - JZ RET50 ;Don't close or count if not created - MOV AL,BYTE PTR[ARG2S] - CALL SETASC ;Check for /B or /A on destination - JZ BINCLOS - CMP BX,[BYTCNT] ;Is memory full? - JNZ PUTZ - CALL FLSHFIL ;Empty it to make room for 1 lousy byte - XOR BX,BX -PUTZ: - PUSH DS - MOV DS,[TPA] - MOV WORD PTR[BX],1AH ;Add End-of-file mark (Ctrl-Z) - POP DS - INC [NXTADD] -BINCLOS: - CALL FLSHFIL - CMP [INEXACT],0 ;Copy not exact? - JNZ NODATE ;If so, don't copy date & time - MOV SI,OFFSET TRANGROUP:DIRBUF+OFFDATE - MOV DI,OFFSET TRANGROUP:DEST+OFFDATE ;Make date & time same as original - MOVSW ;Copy date - MOVSW ;Copy time -NODATE: - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,CLOSE - INT 21H - INC [FILECNT] -RET50: RET - -FLSHFIL: -;Write out any data remaining in memory. -; Inputs: -; [NXTADD] = No. of bytes to write -; [CFLAG] <>0 if file has been created -; Outputs: -; [NXTADD] = 0 - - MOV AL,1 - XCHG [CFLAG],AL - OR AL,AL - JNZ EXISTS - CMP [NOWRITE],0 - JNZ SKPMAK ;Don't actually create if NOWRITE set - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,MAKE - INT 21H - MOV DX,OFFSET TRANGROUP:FULDIR - OR AL,AL - JNZ COPERR -SKPMAK: - XOR AX,AX - MOV WORD PTR[DEST+RR],AX - MOV WORD PTR[DEST+RR+2],AX - INC AX - MOV WORD PTR[DEST+RECLEN],AX -EXISTS: - XOR CX,CX - XCHG CX,[NXTADD] - CMP [NOWRITE],0 ;If NOWRITE set, just seek CX bytes - JNZ SEEKEND - XOR DX,DX - PUSH DS - MOV DS,[TPA] - MOV AH,SETDMA - INT 33 - POP DS - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,WRBLK - INT 21H - OR AL,AL - JZ RET60 - MOV DX,OFFSET TRANGROUP:DEST - MOV AH,CLOSE - INT 21H - MOV AH,DELETE - INT 33 - MOV DX,OFFSET TRANGROUP:NOSPACE -COPERR: - MOV AH,9 - INT 21H - JMP ENDCOPY - -SEEKEND: - ADD WORD PTR[DEST+RR],CX - ADC WORD PTR[DEST+RR+2],0 ;Propagate carry -RET60: RET - -GETBATBYT: -;Get one byte from the batch file and return it in AL. End-of-file -;returns and ends batch mode. DS must be set to resident segment. -;AH, CX, DX destroyed. -ASSUME DS:RESGROUP - MOV DX,OFFSET RESGROUP:BATFCB - MOV AH,RDBLK - MOV CX,1 - INT 33 ;Get one more byte from batch file - JCXZ BATEOF - MOV AL,[BATBYT] - CMP AL,1AH - JNZ RET70 -BATEOF: - MOV AL,0DH ;If end-of-file, then end of line - MOV [BATCH],0 ;And turn off batch mode -RET70: RET -ASSUME DS:TRANGROUP - -SCANOFF: - LODSB - CALL DELIM - JZ SCANOFF - DEC SI ;Point to first non-delimiter - RET - -DELIM: - CMP AL," " - JZ RET80 - CMP AL,"=" - JZ RET80 - CMP AL,"," - JZ RET80 - CMP AL,9 ;Check for TAB character -RET80: RET - -PAUSE: - MOV DX,OFFSET TRANGROUP:PAUSMES - MOV AH,PRINTBUF - INT 33 - MOV AX,0C00H+INCHAR ;Get character with KB buffer flush - INT 33 -RET90: RET - -;Date and time are set during initialization and use -;this routines since they need to do a long return - -DATINIT: - PUSH ES - PUSH DS ;Going to use the previous stack - MOV AX,CS ;Set up the appropriate segment registers - MOV ES,AX - MOV DS,AX - MOV WORD PTR DS:[81H],13 ;Want to prompt for date during initialization - CALL DATE - CALL TIME - POP DS - POP ES -YYY PROC FAR - RET -YYY ENDP - -; DATE - Gets and sets the time - -DATE: - MOV SI,81H ;Accepting argument for date inline - CALL SCANOFF - CMP AL,13 - JZ PRMTDAT - MOV BX,2F00H+"-" ;"/-" - CALL INLINE - JMP COMDAT - -PRMTDAT: - MOV DX,OFFSET TRANGROUP:CURDAT - MOV AH,PRINTBUF - INT 33 ;Print "Current date is " - MOV AH,GETDATE - INT 33 ;Get date in CX:DX - CBW - MOV SI,AX - SHL SI,1 - ADD SI,AX ;SI=AX*3 - ADD SI,OFFSET TRANGROUP:WEEKTAB - MOV BX,CX - MOV CX,3 - CALL OUTCNT - MOV AL," " - CALL OUT - MOV AX,BX - MOV CX,DX - MOV DL,100 - DIV DL - XCHG AL,AH - XCHG AX,DX - MOV BL,"-" - CALL SHOW -GETDAT: - MOV DX,OFFSET TRANGROUP:NEWDAT - MOV BX,2F00H+"-" ;"/-" in BX - CALL GETBUF -COMDAT: JZ RET90 - JC DATERR - LODSB - CMP AL,BL - JZ SEPGD - CMP AL,BH - JNZ DATERR -SEPGD: CALL GETNUM - JC DATERR - MOV CX,1900 - CMP BYTE PTR[SI],13 - JZ BIAS - MOV AL,100 - MUL AH - MOV CX,AX - CALL GETNUM - JC DATERR -BIAS: - MOV AL,AH - MOV AH,0 - ADD CX,AX - LODSB - CMP AL,13 - JNZ DATERR - MOV AH,SETDATE - INT 33 - OR AL,AL - JNZ DATERR - JMP RET90 -DATERR: - MOV DX,OFFSET TRANGROUP:BADDAT - MOV AH,PRINTBUF - INT 33 - JMP GETDAT - -; TIME gets and sets the time - -TIME: - MOV SI,81H ;Accepting argument for time inline - CALL SCANOFF - CMP AL,13 - JZ PRMTTIM - MOV BX,3A00H+":" - CALL INLINE - JMP COMTIM - -PRMTTIM: - MOV DX,OFFSET TRANGROUP:CURTIM - MOV AH,PRINTBUF - INT 33 ;Print "Current time is " - MOV AH,GETTIME - INT 33 ;Get time in CX:DX - MOV BL,":" - CALL SHOW -GETTIM: - XOR CX,CX ;Initialize hours and minutes to zero - MOV DX,OFFSET TRANGROUP:NEWTIM - MOV BX,3A00H+":" - CALL GETBUF -COMTIM: JZ RET100 ;If no time present, don't change it - JC TIMERR - MOV CX,DX - XOR DX,DX - LODSB - CMP AL,13 - JZ SAVTIM - CMP AL,BL - JNZ TIMERR - MOV BL,"." - CALL GETNUM - JC TIMERR - MOV DH,AH ;Position seconds - LODSB - CMP AL,13 - JZ SAVTIM - CMP AL,BL - JNZ TIMERR - CALL GETNUM - JC TIMERR - MOV DL,AH - LODSB - CMP AL,13 - JNZ TIMERR -SAVTIM: - MOV AH,SETTIME - INT 33 - OR AL,AL - JZ RET100 ;Error in time? -TIMERR: - MOV DX,OFFSET TRANGROUP:BADTIM - MOV AH,PRINTBUF - INT 33 ;Print error message - JMP GETTIM ;Try again - -GETBUF: - MOV AH,PRINTBUF - INT 33 ;Print "Enter new date: " - MOV AH,INBUF - MOV DX,OFFSET TRANGROUP:COMBUF - INT 33 ;Get input line - CALL CRLF2 - MOV SI,OFFSET TRANGROUP:COMBUF+2 - CMP BYTE PTR[SI],13 ;Check if new date entered - JZ RET100 -INLINE: - CALL GETNUM ;Get one or two digit number - JC RET100 - MOV DH,AH ;Put in position - LODSB - CMP AL,BL - JZ NEXT - CMP BL,":" ;Is it a date seperator? - JNZ DATESEP - DEC SI - MOV DL,0 -RET100: RET ;Time may have only an hour specified -DATESEP: - CMP AL,BH - STC - JNZ RET100 -NEXT: CALL GETNUM - MOV DL,AH ;Put in position - RET - -GETNUM: - CALL INDIG - JC RET100 - MOV AH,AL ;Save first digit - CALL INDIG ;Another digit? - JC OKRET - AAD ;Convert unpacked BCD to decimal - MOV AH,AL -OKRET: - OR AL,1 -RET110: RET - -INDIG: - MOV AL,BYTE PTR[SI] - SUB AL,"0" - JC RET110 - CMP AL,10 - CMC - JC RET110 - INC SI - RET - -SHOW: - MOV AL,CH - MOV BH,"0"-" " ;Enable leading zero suppression - CALL OUT2 - MOV AL,BL - CALL OUT - MOV AL,CL - CALL OUT2 - MOV AL,BL - CALL OUT - MOV AL,DH - CALL OUT2 - CMP BL,":" ;Are we outputting time? - JNZ SKIPIT - MOV AL,"." - CALL OUT -SKIPIT: MOV AL,DL -OUT2: ;Output binary number as two ASCII digits - AAM ;Convert binary to unpacked BCD - XCHG AL,AH - OR AX,3030H ;Add "0" bias to both digits - CMP AL,"0" ;Is MSD zero? - JNZ NOSUP - SUB AL,BH ;Suppress leading zero if enabled -NOSUP: - MOV BH,0 ;Disable zero suppression - CALL OUT - MOV AL,AH -OUT: -;Print char in AL without affecting registers - XCHG AX,DX - PUSH AX - MOV AH,OUTCH - INT 33 - POP AX - XCHG AX,DX - RET - -EXELOAD: - MOV AX,CS - ADD AX,LOADSEG - MOV [EXEEND],AX ;Store in EXEEND - MOV DX,OFFSET TRANGROUP:RUNVAR ;Read header in here - MOV AH,SETDMA - INT 33 - MOV CX,RUNVARSIZ ;Amount of header info we need - MOV DX,OFFSET TRANGROUP:EXEFCB - MOV AH,RDBLK - INT 33 ;Read in header - OR AL,AL - JNZ BADEXE ;Must not reach EOF - MOV AX,[HEADSIZ] ;Size of header in paragraphs -;Convert header size to 512-byte pages by multiplying by 32 & rounding up - ADD AX,31 ;Round up first - MOV CL,5 - SHR AX,CL ;Multiply by 32 - MOV [EXEFCB+RR],AX ;Position in file of program - MOV WORD PTR[EXEFCB+RECLEN],512 ;Set record size - ADD BX,10H ;First paragraph above parameter area - MOV DX,[PAGES] ;Total size of file in 512-byte pages - SUB DX,AX ;Size of program in pages - MOV [PSIZE],DX - SHL DX,CL ;Convert pages back to paragraphs - MOV AX,DX - ADD DX,BX ;Size + start = minimum memory (paragr.) - MOV CX,[EXEEND] ;Get memory size in paragraphs - CMP DX,CX ;Enough memory? - JA SHRTERR - MOV DX,[INITSP] - ADD DX,15 - SHR DX,1 - SHR DX,1 - SHR DX,1 - SHR DX,1 - ADD DX,[INITSS] - ADD DX,BX ;Adjusted value of SP - CMP DX,CX ;Is it valid? - JA SHRTERR - CMP [LOADLOW],-1 ;Load low or high? - JZ LOAD ;If low, load at segment BX - SUB CX,AX ;Memory size - program size = load addr. - MOV BX,CX -LOAD: - MOV BP,BX ;Save load segment -LOAD1: -LOADSEG EQU (LOAD1-ZERO)/16 - PUSH DS - MOV DS,BX - XOR DX,DX ;Address 0 in segment - MOV AH,SETDMA - INT 33 ;Set load address - POP DS - MOV CX,[PSIZE] ;Number of records to read - MOV DX,OFFSET TRANGROUP:EXEFCB - MOV AH,RDBLK - INT 33 ;Read in up to 64K - SUB [PSIZE],CX ;Decrement count by amount read - JZ HAVEXE ;Did we get it all? - TEST AL,1 ;Check return code if not - JNZ BADEXE ;Must be zero if more to come - ADD BX,1000H-20H ;Bump data segment 64K minus one record - JMP SHORT LOAD1 ;Get next 64K block - -BADEXE: - MOV DX,OFFSET TRANGROUP:EXEBAD - JMP ERROR - -SHRTERR: - MOV DX,OFFSET TRANGROUP:TOOBIG - JMP ERROR - -HAVEXE: - MOV AX,[RELTAB] ;Get position of table - MOV [EXEFCB+RR],AX ;Set in random record field - MOV WORD PTR[EXEFCB+RECLEN],1 ;Set one-byte record - MOV DX,OFFSET TRANGROUP:RELPT ;4-byte buffer for relocation address - MOV AH,SETDMA - INT 33 - CMP [RELCNT],0 - JZ NOREL -RELOC: - MOV AH,RDBLK - MOV DX,OFFSET TRANGROUP:EXEFCB - MOV CX,4 - INT 33 ;Read in one relocation pointer - OR AL,AL ;Check return code - JNZ BADEXE - MOV DI,[RELPT] ;Get offset of relocation pointer - MOV AX,[RELSEG] ;Get segment - ADD AX,BP ;Bias segment with actual load segment - MOV ES,AX - ADD WORD PTR ES:[DI],BP ;Relocate - DEC [RELCNT] ;Count off - JNZ RELOC -;Set up exit conditions -NOREL: - MOV AX,[INITSS] - ADD AX,BP - CLI - MOV SS,AX ;Initialize SS - MOV SP,[INITSP] - STI - ADD [INITCS],BP - MOV AX,[TPA] ;Get pointer to parameter area - MOV CX,[BYTCNT] ;Size of TPA segment - MOV ES,AX - MOV DS,AX ;Set segment registers to point to it - CALL SETUP - JMP DWORD PTR CS:[INITIP] ;Long jump to program - -SETUP: - AND CL,0F0H ;Adjust to even paragraph boundary - MOV AX,WORD PTR DS:[6] ;Get current memory size - SUB AX,CX ;Find out how much we're changing it - MOV WORD PTR DS:[6],CX - MOV CL,4 - SAR AX,CL ;Convert to a segment address - ADD WORD PTR DS:[8],AX ;Adjust long jump to go to same place - MOV DX,80H - MOV AH,SETDMA - INT 33 ;Set default disk transfer address - MOV AX,WORD PTR CS:[PARM1] ;Pass on info about FCBs - XOR CX,CX - MOV DX,CX ;Assume no batch file -ASSUME CS:RESGROUP - TEST CS:[BATCH],-1 ;Batch file in progress? -ASSUME CS:TRANGROUP - JZ RET120 ;If not, all set up - MOV CX,CS:[RESSEG] - MOV DX,OFFSET RESGROUP:BATFCB ;CX:DX points to batch FCB -RET120: RET -TRANCODESIZE EQU $-ZERO -TRANCODE ENDS -COMLEN EQU TRANDATASIZE+TRANCODESIZE-102H ;End of COMMAND load. ZERO Needed to make COMLEN absolute -TRNLEN EQU (PRETRLEN+TRANCODESIZE+TRANDATASIZE+15)/16 ;Length of transient in paragraphs - END PROGSTART - \ No newline at end of file +; ...existing code...