;*************************************************************** ; ; 86-DOS FORMAT DISK UTILITY ; ; This routine formats a new disk,clears the FAT and DIRECTORY ; then optionally copies the SYSTEM and COMMAND.COM to this ; new disk ; ; SYNTAX: FORMAT [drive][/switch1][/switch2]...[/switch16] ; ; Regardless of the drive designator , the user will be ; prompted to insert the diskette to be formatted. ; ;*************************************************************** ;Mod to ask for volume ID ARR 5/12/82 ; 05/19/82 Fixed rounding bug in CLUSCAL: ARR ;REV 1.5 ; Added rev number message ; Added dir attribute to DELALL FCB ;REV 2.00 ; Redone for 2.0 ;REV 2.10 ; 5/1/83 ARR Re-do to transfer system on small memory systems FALSE EQU 0 TRUE EQU NOT FALSE IBMJAPVER EQU FALSE ; SET ONLY ONE SWITCH TO TRUE! IBMVER EQU FALSE MSVER EQU TRUE KANJI EQU FALSE .xlist INCLUDE DOSSYM.ASM .list ;FORMAT Pre-defined switches SYSSW EQU 1 ; System transfer VOLSW EQU 2 ; Volume ID prompt OLDSW EQU 4 ; E5 dir terminator DRNUM EQU 5CH RECLEN EQU fcb_RECSIZ+7 RR EQU fcb_RR+7 ;Per system file data structure FILESTRUC STRUC FILE_HANDLE DW ? ; Source handle FILE_SIZEP DW ? ; File size in para FILE_SIZEB DD ? ; File size in bytes FILE_OFFSET DD ? ; Offset in file (partial) FILE_START DW ? ; Para number of start in buffer FILE_DATE DW ? ; Date of file FILE_TIME DW ? ; Time of file FILE_NAME DB ? ; Start of name FILESTRUC ENDS CODE SEGMENT PUBLIC 'CODE' ASSUME CS:CODE,DS:CODE,ES:CODE ORG 100H ;For OEM module PUBLIC SWITCHMAP,DRIVE EXTRN HARDFLAG:BYTE ;0 = REMOVABLE MEDIA EXTRN SWITCHLIST:BYTE,FATID:BYTE,FATSPACE:WORD EXTRN STARTSECTOR:WORD,FREESPACE:WORD,INIT:NEAR EXTRN DISKFORMAT:NEAR,BADSECTOR:NEAR,DONE:NEAR EXTRN WRTFAT:NEAR ;For FORMES module EXTRN WAITYN:NEAR,REPORT:NEAR PUBLIC PRINT,CRLF,DISP32BITS,UNSCALE,FDSKSIZ,SECSIZ,CLUSSIZ PUBLIC SYSSIZ,BADSIZ START: JMP SHORT FSTRT HEADER DB "Vers 2.10" FSTRT: MOV SP,OFFSET STACK ;Use internal stack ;Code to print header ; PUSH AX ; MOV DX,OFFSET HEADER ; CALL PRINT ; POP AX DOSVER_HIGH EQU 020BH ;2.11 in hex PUSH AX ;Save DRIVE validity info MOV AH,GET_VERSION INT 21H XCHG AH,AL ;Turn it around to AH.AL CMP AX,DOSVER_HIGH JAE OKDOS GOTBADDOS: MOV DX,OFFSET BADVER MOV AH,STD_CON_STRING_OUTPUT INT 21H INT 20H OKDOS: IF IBMVER ; IBM WANTS TO CHECK FOR ASSIGN.COM XOR AX,AX MOV ES,AX MOV BX,ES:[4*21H] MOV ES,ES:[4*21H+2] CMP BX,122H JNZ NO_ASSIGN CMP ES:[109H],0807H JNZ NO_ASSIGN CMP ES:[103H],0201H JNZ RE_ASSIGN CMP ES:[105H],0403H JNZ RE_ASSIGN CMP ES:[107H],0605H JZ NO_ASSIGN RE_ASSIGN: MOV DX,OFFSET ASGERR CALL PRINT JMP FEXIT2 NO_ASSIGN: PUSH CS POP ES ENDIF POP AX CMP AL,0FFH ;See if invalid drive specified JNZ DRVGD ;If not proceed MOV DX,OFFSET INVDRV ;Invalid drive message CALL PRINT ;Print the message JMP FEXIT2 ;Exit DRVGD: MOV AH,GET_DEFAULT_DRIVE ;Must get the default drive INT 21H ;Default now in AL MOV DEFALT,AL ;Save for later ADD AL,"A" MOV [BIODRV],AL MOV [DOSDRV],AL MOV [SYSDRV],AL MOV [COMDRV],AL MOV SI,DRNUM ;So we can get our parameters LODSB ;Fetch drive designation OR AL,AL ;See if specified JNZ DRVSPEC ;If specfied proceed MOV AL,DEFALT INC AL DRVSPEC: DEC AL ;Drive designator now correct MOV BYTE PTR DS:[DRNUM],AL ;And updated MOV DRIVE,AL ;Save copy MOV DX,OFFSET INT_23 MOV AH,SET_INTERRUPT_VECTOR MOV AL,23H INT 21H ;Set ^C vector ;Get all the swith information from the command line XOR AX,AX MOV AH,CHAR_OPER ;GET SWITCH CHARACTER INT 21H ;CALL THE DOS MOV [SWTCH],DL XOR BX,BX ;Store switch information in BX MOV SI,81H ;Point to the command line buffer NXTSWT: CALL SCANOFF LODSB CMP AL,[SWTCH] JZ GETPARM CMP AL,13 JZ SAVSWT LODSB ;Get next character CMP AL,":" ;Is it a drive specifier? JNZ INVALID ;No -- invalid parameter CMP BYTE PTR DBLFLG,0 ;Is is the only drive specifier we've seen JNZ INVALID ;No -- invalid parameter INC BYTE PTR DBLFLG ;Yes -- set the flag JMP SHORT NXTSWT GETPARM: LODSB ;Convert any lower case input into upper case CMP AL,41H JL GETCHR ;Switch is a digit don't try to convert it AND AL,0DFH GETCHR: MOV CL,SWITCHLIST ;Number of legal switches OR CL,CL ;If it's none we shouldn't be here JZ INVALID ;Report the error MOV CH,0 MOV DI,1+OFFSET SWITCHLIST ;Point to the legal switch characters REPNE SCASB JNZ INVALID MOV AX,1 SHL AX,CL OR BX,AX ;Set the appropriate bit in SWITCHMAP JMP SHORT NXTSWT ;See if there are anymore INVALID: MOV DX,OFFSET INVPAR CALL PRINT JMP FEXIT SCANOFF: LODSB CMP AL,20H JZ SCANOFF CMP AL,9 JZ SCANOFF DEC SI RET MEMERR: MOV DX,OFFSET MEMEX CALL PRINT JMP FEXIT SAVSWT: IF IBMVER ;/B SWITCH TURNS /8 ON AND /S OFF TEST BX,00100000B JZ NOT_SW_B AND BX,NOT SYSSW ;TURN OFF /S OR BX,00010000B ;TURN ON /8 NOT_SW_B: ENDIF MOV SWITCHMAP,BX TEST SWITCHMAP,SYSSW JZ INITCALL CALL SAVUDIRS MOV BX,[FREESPACE] ADD BX,15 MOV CL,4 SHR BX,CL PUSH CS POP ES MOV AH,SETBLOCK INT 21H MOV BX,0FFFFH MOV AH,ALLOC INT 21H OR BX,BX JZ MEMERR ;No memory MOV [MSIZE],BX MOV AH,ALLOC INT 21H JC MEMERR ;No memory MOV [MSTART],AX MOV DX,OFFSET SWTCH MOV AH,CHDIR INT 21H ;Go to root on default drive (source) RDFRST: CALL READDOS ;Read BIOS and DOS JNC INITCALL ;OK -- read next file NEEDSYS: CALL SYSPRM ;Prompt for system disk JMP RDFRST ;Try again INITCALL: CALL INIT ;Let OEM read any files before disk is changed JNC SWITCHCHK MOV DX,OFFSET FRMTERR CALL PRINT JMP FEXIT SWITCHCHK: MOV DX,SWITCHMAP MOV SWITCHCOPY,DX SYSLOOP: MOV WORD PTR BADSIZ,0 ;Must intialize for each iteration MOV WORD PTR BADSIZ+2,0 MOV WORD PTR SYSSIZ,0 MOV WORD PTR SYSSIZ+2,0 MOV BYTE PTR DBLFLG,0 MOV BYTE PTR CLEARFLG,0 MOV DX,SWITCHCOPY MOV SWITCHMAP,DX ;Restore original Switches MOV AL,DRIVE ;Fetch drive ADD AL,"A" ;(AL)= ASCII designation MOV BYTE PTR SNGDRV,AL ;Fill out the message MOV BYTE PTR TARGDRV,AL MOV BYTE PTR HRDDRV,AL CALL DSKPRM ;Prompt for new disk CALL DISKFORMAT ;Format the disk JNC GETTRK FRMTPROB: MOV DX,OFFSET FRMTERR CALL PRINT JMP SHORT SYSLOOP ;Mark any bad sectors in the FATs ;And keep track of how many bytes there are in bad sectors GETTRK: CALL BADSECTOR ;Do bad track fix-up JC FRMTPROB ;Had an error in Formatting - can't recover CMP AX,0 ;Are we finished? JNZ TRKFND ;No - check error conditions JMP DRTFAT ;Yes TRKFND: CMP BX,STARTSECTOR ;Are any sectors in the system area bad? JGE CLRTEST MOV DX,OFFSET NOUSE ;Can't build FATs of Directory CALL PRINT JMP FRMTPROB ;Bad disk -- try again CLRTEST: MOV SECTORS,AX ;Save the number of sectors on the track CMP BYTE PTR CLEARFLG,0 ;Have we already cleared the FAT and DIR? JNZ SYSTEST ;Yes - all set INC CLEARFLG ;Set the flag PUSH BX CALL CLEAR ;Fix-up fat and directory POP BX SYSTEST: TEST SWITCHMAP,SYSSW ;If system requested calculate size JZ BAD100 CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space? JNZ CMPTRKS ;Yes -- all ready for the compare INC BYTE PTR DBLFLG ;No -- set the flag CALL GETSIZE ;Calculate the system size MOV DX,WORD PTR SYSSIZ+2 MOV AX,WORD PTR SYSSIZ DIV SECSIZ ADD AX,STARTSECTOR MOV SYSTRKS,AX ;Space FAT,Dir,and system files require CMPTRKS: CMP BX,SYSTRKS JG BAD100 MOV DX,OFFSET NOTSYS ;Can't transfer a system CALL PRINT AND SWITCHMAP,NOT SYSSW ;Turn off system transfer switch MOV WORD PTR SYSSIZ+2,0 ;No system to transfer MOV WORD PTR SYSSIZ,0 ;No system to transfer BAD100: ; BX is the first bad sector #, SECTORS is the number of bad sectors starting ; at BX. This needs to be converted to clusters. The start sector number may ; need to be rounded down to a cluster boundry, the end sector may need to be ; rounded up to a cluster boundry. Know BX >= STARTSECTOR SUB BX,STARTSECTOR ; BX is now DATA area relative MOV CX,BX ADD CX,SECTORS DEC CX ; CX is now the last bad sector # MOV AX,BX XOR DX,DX DIV CLUSSIZ MOV BX,AX ; BX is rounded down and converted ; to a cluster #. Where cluster 0 = ; first cluster of data. First bad ; Sector is in cluster BX. MOV AX,CX XOR DX,DX DIV CLUSSIZ MOV CX,AX ; CX is rounded up and converted to a ; to a cluster #. Where cluster 0 = ; first cluster of data. Last bad ; Sector is in cluster CX. SUB CX,BX INC CX ; CX is number of clusters to mark bad ADD BX,2 ; Bias start by correct amount since ; first cluster of data is really ; cluster 2. MOV AX,CLUSSIZ ; Sectors/Cluster MUL SECSIZ ; Times Bytes/Sector MOV BP,AX ; = Bytes/Cluster ; Mark CX clusters bad starting at cluster BX PACKIT: MOV DX,0FF7H ;0FF7H indicates a bad sector CALL PACK ;Put it in the allocation map CMP DX,DI ;Have we already marked it bad? JZ BAD150 ;if so, don't add it in ADD WORD PTR BADSIZ,BP ;Add in number of bad bytes JNB BAD150 INC WORD PTR BADSIZ+2 BAD150: INC BX ;Next cluster LOOP PACKIT ;Continue for # of clusters JMP GETTRK ; Inputs: ;BX = Cluster number ;DX = Data ; Outputs: ;The data is stored in the FAT at the given cluster. ;SI is destroyed ;DI contains the former contents ;No other registers affected PACK: PUSH BX PUSH CX PUSH DX MOV SI,BX SHR BX,1 ADD BX,FATSPACE ADD BX,SI SHR SI,1 MOV SI,WORD PTR [BX] MOV DI,SI JNB ALIGNED MOV CL,4 SHL DX,CL SHR DI,CL AND SI,15 JMP SHORT PACKIN ALIGNED: AND SI,0F000H PACKIN: AND DI,00FFFH ;DI CONTAINS FORMER CONTENTS OR SI,DX MOV WORD PTR[BX],SI POP DX POP CX POP BX RET DRTFAT: CMP BYTE PTR CLEARFLG,0 JNZ CLEARED CALL CLEAR ;Clear the FAT and Dir TEST SWITCHMAP,SYSSW ;If system requested, calculate size JZ CLEARED CMP BYTE PTR DBLFLG,0 ;Have we already calculated System space? JNZ CLEARED ;Yes INC BYTE PTR DBLFLG ;No -- set the flag CALL GETSIZE ;Calculate the system size CLEARED: CALL WRTFAT JNC FATWRT MOV DX,OFFSET NOUSE CALL PRINT JMP FRMTPROB FATWRT: TEST SWITCHMAP,SYSSW ;System desired JZ STATUS CALL WRITEDOS ;Write the BIOS & DOS JNC SYSOK MOV DX,OFFSET NOTSYS ;Can't transfer a system CALL PRINT MOV WORD PTR SYSSIZ+2,0 ;No system transfered MOV WORD PTR SYSSIZ,0 ;No system transfered JMP SHORT STATUS SYSOK: MOV DX,OFFSET SYSTRAN CALL PRINT STATUS: CALL CRLF CALL VOLID MOV AH,DISK_RESET INT 21H CALL DONE ;Final call to OEM module JNC REPORTC JMP FRMTPROB ;Report an error REPORTC: CALL REPORT CALL MORE ;See if more disks to format JMP SYSLOOP ;If we returned from MORE then continue DISP32BITS: PUSH BX 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 8-digit number with 2 leading blanks. MOV CX,1810H XCHG DX,AX CALL DIGIT XCHG AX,BX CALL OUTWORD XCHG AX,BP CALL OUTWORD POP DX CMP DX,0 JZ RET3 CALL PRINT RET3: RET 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,STD_CON_OUTPUT INT 21H RET CONVWRD: ADC AL,AL DAA XCHG AL,AH ADC AL,AL DAA XCHG AL,AH RET2: RET UNSCALE: SHR CX,1 JC RET2 SHL AX,1 RCL DX,1 JMP SHORT UNSCALE ;****************************************** ; Calculate the size in bytes of the system rounded up to sector and ; cluster boundries, Answer in SYSSIZ GETSIZE: MOV AX,WORD PTR BIOSSIZB ;And calculate the system size MOV DX,WORD PTR BIOSSIZB+2 CALL FNDSIZ MOV AX,WORD PTR DOSSIZB MOV DX,WORD PTR DOSSIZB+2 CALL FNDSIZ MOV AX,WORD PTR COMSIZB MOV DX,WORD PTR COMSIZB+2 ;Calculate the number of sectors used for the system FNDSIZ: DIV SECSIZ OR DX,DX JZ FNDSIZ0 INC AX ; Round up to next sector FNDSIZ0: PUSH AX XOR DX,DX DIV CLUSSIZ POP AX OR DX,DX JZ ONCLUS SUB DX,CLUSSIZ NEG DX ADD AX,DX ; Round up sector count to cluster ; boundry ONCLUS: MUL SECSIZ ; Turn it back into bytes ADD WORD PTR SYSSIZ,AX ADC WORD PTR SYSSIZ+2,DX RET PRINT: MOV AH,STD_CON_STRING_OUTPUT ;Print msg pointed to by DX INT 21H RET MORE: CMP BYTE PTR [HARDFLAG],0 ;Check if removable media JNZ FEXIT CALL WAITYN ;Get yes or no response JB FEXIT ;Exit if CF=1 CALL CRLF CRLF: MOV DX,OFFSET CRLFMSG CALL PRINT RET PERROR: CALL PRINT ;Print message and exit FEXIT: CALL RESTUDIR ;Restore users dirs FEXIT2: INT 20H ;Prompt the user for a system diskette in the default drive SYSPRM: MOV AH,GET_DEFAULT_DRIVE ;Will find out the default drive INT 21H ;Default now in AL IF IBMVER OR IBMJAPVER MOV BX,AX ENDIF ADD AL,41H ;Now in Ascii MOV SYSDRV,AL ;Text now ok IF IBMVER OR IBMJAPVER INT 11H ;Make sure drive has insertable media AND AL,11000000B ROL AL,1 ROL AL,1 OR AL,AL JNZ NOTONEDRV INC AL NOTONEDRV: CMP BL,AL JBE ISFLOPPY MOV AL,"A" MOV BYTE PTR [SYSDRV],AL MOV [BIODRV],AL MOV [DOSDRV],AL MOV [COMDRV],AL ISFLOPPY: ENDIF MOV DX,OFFSET SYSMSG CALL PRINT ;Print first line CALL WAITKY ;Wait for a key CALL CRLF RET TARGPRM: MOV DX,OFFSET TARGMSG CALL PRINT ;Print first line CALL WAITKY ;Wait for a key CALL CRLF RET DSKPRM: MOV DX,OFFSET SNGMSG ;Point to the message CMP BYTE PTR [HARDFLAG],0 ;Check if removable media JZ GOPRNIT MOV DX,OFFSET HRDMSG GOPRNIT: CALL PRINT ;Print the message CALL WAITKY ;Wait for space bar CALL CRLF CALL CRLF RET ;Will wait for any key to be depressed. WAITKY: MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_INPUT_NO_ECHO INT 21H MOV AX,(STD_CON_INPUT_FLUSH SHL 8) + 0 INT 21H return FDPB: MOV DL,DRIVE INC DL MOV AH,GET_DPB PUSH DS INT 21H INC AL JZ DRVERR MOV DX,WORD PTR [BX+13] DEC DX MOV AL,BYTE PTR [BX+4] INC AL MOV CX,WORD PTR [BX+2] POP DS RET DRVERR: POP DS MOV DX,OFFSET INVDRV JMP PERROR ;Clear the FAT and directory and set Dirty byte in the FAT CLEAR: MOV AL,FATID OR AL,0F8H ;Make sure it's a legal value MOV AH,0FFH MOV DI,FATSPACE MOV WORD PTR[DI],AX MOV BYTE PTR[DI+2],AH MOV AH,DISK_RESET INT 21H CALL WRTFAT IF IBMJAPVER PUSH DS MOV DL,[DRIVE] ;GET THE DRIVE PARAMETER INC DL MOV AH,32H INT 21H MOV DPB_FIRST_ACCESS[BX],-1 ;FORCE MEDIA CHANGE POP DS ENDIF CALL FDPB MOV WORD PTR FDSKSIZ,DX MOV SECSIZ,CX MOV AH,0 MOV CLUSSIZ,AX SHR DX,1 JNC ROUNDED INC DX ROUNDED: ADD DX,WORD PTR FDSKSIZ XOR AX,AX MOV CX,DX MOV DI,FATSPACE ADD DI,3 REP STOSB MOV AH,DISK_RESET INT 21H CALL WRTFAT MOV DL,[DRIVE] ADD DL,'A' MOV [ROOTSTR],DL MOV DX,OFFSET ROOTSTR MOV AH,CHDIR INT 21H ;Go to root on target drive MOV AL,DRIVE INC AL MOV ALLDRV,AL MOV AH,FCB_DELETE MOV DX,OFFSET ALLFILE INT 21H TEST SWITCHMAP,OLDSW ;See if E5 terminated DIR requested JZ RET25 MOV AL,DRIVE INC AL MOV BYTE PTR CLEANFILE,AL ;Get the drive MOV DX,OFFSET CLEANFILE MOV AH,FCB_CREATE MAKE_NEXT: INT 21H OR AL,AL JNZ DELETE_THEM INC BYTE PTR CLNNAM CMP BYTE PTR CLNNAM,"Z" + 1 JNZ MAKE_NEXT MOV BYTE PTR CLNNAM,"A" INC BYTE PTR CLNNAM + 1 CMP BYTE PTR CLNNAM + 1,"Z" + 1 JNZ MAKE_NEXT MOV BYTE PTR CLNNAM + 1,"A" INC BYTE PTR CLNNAM + 2 JMP MAKE_NEXT DELETE_THEM: MOV WORD PTR CLNNAM,"??" MOV BYTE PTR CLNNAM + 2,"?" MOV AH,FCB_DELETE INT 21H RET25: RET ;And return ;***************************************** ; Process V switch if set VOLID: TEST [SWITCHMAP],VOLSW JNZ DOVOL VRET: CLC RET DOVOL: PUSH CX PUSH SI PUSH DI PUSH ES PUSH DS POP ES VOL_LOOP: MOV AL,DRIVE INC AL MOV DS:BYTE PTR[VOLFCB+7],AL MOV DX,OFFSET LABPRMT CALL PRINT MOV DX,OFFSET INBUFF MOV AH,STD_CON_STRING_INPUT INT 21H MOV DX,OFFSET CRLFMSG CALL PRINT MOV DX,OFFSET CRLFMSG CALL PRINT MOV CL,[INBUFF+1] OR CL,CL JZ VOLRET XOR CH,CH MOV SI,OFFSET INBUFF+2 MOV DI,SI ADD DI,CX MOV CX,11 MOV AL,' ' REP STOSB MOV CX,5 MOV DI,OFFSET VOLNAM REP MOVSW MOVSB MOV DX,OFFSET VOLFCB MOV AH,FCB_CREATE INT 21H OR AL,AL JZ GOOD_CREATE MOV DX,OFFSET INVCHR ;PRINT INVALID CHARS MESSAGE CALL PRINT JMP VOL_LOOP GOOD_CREATE: MOV DX,OFFSET VOLFCB MOV AH,FCB_CLOSE INT 21H CALL CRLF VOLRET: POP ES POP DI POP SI POP CX RET ;**************************************** ;Copy IO.SYS, MSDOS.SYS and COMMAND.COM into data area. ; Carry set if problems READDOS: CALL TESTSYSDISK JNC RDFILS RET RDFILS: MOV BYTE PTR [FILSTAT],0 MOV BX,[BIOSHandle] MOV AX,[MSTART] MOV DX,AX ADD DX,[MSIZE] ; CX first bad para MOV [BIOSSTRT],AX MOV CX,[BIOSSIZP] ADD AX,CX CMP AX,DX JBE GOTBIOS MOV BYTE PTR [FILSTAT],00000001B ; Got part of BIOS MOV SI,[MSIZE] XOR DI,DI CALL DISIX4 MOV DS,[BIOSSTRT] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE JC CLSALL XOR DX,DX MOV CX,DX MOV AX,(LSEEK SHL 8) OR 1 INT 21H MOV WORD PTR [BIOSOFFS],AX MOV WORD PTR [BIOSOFFS+2],DX FILESDONE: CLC CLSALL: PUSHF CALL COMCLS POPF RET GOTBIOS: MOV BYTE PTR [FILSTAT],00000010B ; Got all of BIOS LES SI,[BIOSSIZB] MOV DI,ES MOV DS,[BIOSSTRT] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE JC CLSALL MOV BX,[DOSHandle] MOV [DOSSTRT],AX CMP AX,DX ; No room left? JZ CLSALL ; Yes MOV CX,[DOSSIZP] ADD AX,CX CMP AX,DX JBE GOTDOS OR BYTE PTR [FILSTAT],00000100B ; Got part of DOS SUB DX,[DOSSTRT] MOV SI,DX XOR DI,DI CALL DISIX4 MOV DS,[DOSSTRT] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE JC CLSALL XOR DX,DX MOV CX,DX MOV AX,(LSEEK SHL 8) OR 1 INT 21H MOV WORD PTR [DOSOFFS],AX MOV WORD PTR [DOSOFFS+2],DX JMP FILESDONE GOTDOS: OR BYTE PTR [FILSTAT],00001000B ; Got all of DOS LES SI,[DOSSIZB] MOV DI,ES MOV DS,[DOSSTRT] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE CLSALLJ: JC CLSALL MOV BX,[COMHandle] MOV [COMSTRT],AX CMP AX,DX ; No room left? JZ CLSALL ; Yes MOV CX,[COMSIZP] ADD AX,CX CMP AX,DX JBE GOTCOM OR BYTE PTR [FILSTAT],00010000B ; Got part of COMMAND SUB DX,[COMSTRT] MOV SI,DX XOR DI,DI CALL DISIX4 MOV DS,[COMSTRT] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE JC CLSALLJ XOR DX,DX MOV CX,DX MOV AX,(LSEEK SHL 8) OR 1 INT 21H MOV WORD PTR [COMOFFS],AX MOV WORD PTR [COMOFFS+2],DX JMP FILESDONE GOTCOM: OR BYTE PTR [FILSTAT],00100000B ; Got all of COMMAND LES SI,[COMSIZB] MOV DI,ES MOV DS,[COMSTRT] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE JMP CLSALL ;************************************************** ;Write BIOS DOS COMMAND to the newly formatted disk. WRITEDOS: MOV CX,BIOSATT MOV DX,OFFSET BIOSFIL LES SI,[BIOSSIZB] MOV DI,ES CALL MAKEFIL JNC GOTNBIO RET34: RET GOTNBIO: MOV [TempHandle],BX TEST BYTE PTR FILSTAT,00000010B JNZ GOTALLBIO LES SI,[BIOSOFFS] MOV DI,ES MOV WORD PTR [IOCNT],SI MOV WORD PTR [IOCNT+2],DI MOV BP,OFFSET BIOSData CALL GOTTARG JC RET34 JMP SHORT BIOSDONE GOTALLBIO: LES SI,[BIOSSIZB] MOV DI,ES MOV DS,[BIOSSTRT] ASSUME DS:NOTHING CALL WRITEFILE ASSUME DS:CODE BIOSDONE: MOV BX,[TempHandle] MOV CX,BTIME MOV DX,BDATE CALL CLOSETARG MOV CX,DOSATT MOV DX,OFFSET DOSFIL LES SI,[DOSSIZB] MOV DI,ES CALL MAKEFIL JC RET34 GOTNDOS: MOV [TempHandle],BX TEST BYTE PTR FILSTAT,00001000B JNZ GOTALLDOS MOV BP,OFFSET DOSData TEST BYTE PTR FILSTAT,00000100B JNZ PARTDOS MOV WORD PTR [DOSOFFS],0 MOV WORD PTR [DOSOFFS+2],0 CALL GETSYS3 RET34J: JC RET34 JMP SHORT DOSDONE PARTDOS: LES SI,[DOSOFFS] MOV DI,ES MOV WORD PTR [IOCNT],SI MOV WORD PTR [IOCNT+2],DI CALL GOTTARG JC RET34J JMP SHORT DOSDONE GOTALLDOS: LES SI,[DOSSIZB] MOV DI,ES MOV DS,[DOSSTRT] ASSUME DS:NOTHING CALL WRITEFILE ASSUME DS:CODE DOSDONE: MOV BX,[TempHandle] MOV CX,DTIME MOV DX,DDATE CALL CLOSETARG MOV CX,COMATT MOV DX,OFFSET COMFIL LES SI,[COMSIZB] MOV DI,ES CALL MAKEFIL JNC GOTNCOM RET35: RET GOTNCOM: MOV [TempHandle],BX TEST BYTE PTR FILSTAT,00100000B JNZ GOTALLCOM MOV BP,OFFSET COMData TEST BYTE PTR FILSTAT,00010000B JNZ PARTCOM MOV WORD PTR [COMOFFS],0 MOV WORD PTR [COMOFFS+2],0 CALL GETSYS3 JC RET35 JMP SHORT COMDONE PARTCOM: LES SI,[COMOFFS] MOV DI,ES MOV WORD PTR [IOCNT],SI MOV WORD PTR [IOCNT+2],DI CALL GOTTARG JC RET35 JMP SHORT COMDONE GOTALLCOM: LES SI,[COMSIZB] MOV DI,ES MOV DS,[COMSTRT] ASSUME DS:NOTHING CALL WRITEFILE ASSUME DS:CODE COMDONE: MOV BX,[TempHandle] MOV CX,CTIME MOV DX,CDATE CALL CLOSETARG CMP BYTE PTR [FILSTAT],00101010B JZ NOREDOS RDFRST2: CALL READDOS ; Start back with BIOS JNC NOREDOS CALL SYSPRM ;Prompt for system disk JMP RDFRST2 ;Try again NOREDOS: CLC RET ;********************************************* ; Create a file on target disk ; CX = attributes, DX points to name ; DI:SI is size file is to have ; ; There is a bug in DOS 2.00 and 2.01 having to do with writes ; from the end of memory. In order to circumvent it this routine ; must create files with the length in DI:SI ; ; On return BX is handle, carry set if problem MAKEFIL: MOV BX,DX PUSH WORD PTR [BX] MOV AL,TARGDRV MOV [BX],AL MOV AH,CREAT INT 21H POP WORD PTR [BX] MOV BX,AX JC RET50 MOV CX,DI MOV DX,SI MOV AX,LSEEK SHL 8 INT 21H ; Seek to eventual EOF XOR CX,CX MOV AH,WRITE INT 21H ; Set size of file to position XOR CX,CX MOV DX,CX MOV AX,LSEEK SHL 8 INT 21H ; Seek back to start RET50: RET ;********************************************* ; Close a file on the target disk ; CX/DX is time/date, BX is handle CLOSETARG: MOV AX,(FILE_TIMES SHL 8) OR 1 INT 21H MOV AH,CLOSE INT 21H RET SAVUDIRS: XOR DL,DL MOV SI,OFFSET USERDIRS MOV BYTE PTR [SI],'\' INC SI MOV AH,CURRENT_DIR INT 21H RET43: RET RESTUDIR: TEST SWITCHMAP,SYSSW JZ RET43 MOV DX,OFFSET USERDIRS MOV AH,CHDIR INT 21H ; Restore users DIR RET INT_23: PUSH CS POP DS JMP FEXIT ;**************************************** ; Transfer system files ; BP points to data structure for file involved ; offset is set to current amount read in ; Start set to start of file in buffer ; TempHandle is handle to write to on target IOLOOP: MOV AL,[SYSDRV] CMP AL,[TARGDRV] JNZ GOTTARG MOV AH,DISK_RESET INT 21H CALL TARGPRM ;Get target disk GOTTARG: ;Enter here if some of file is already in buffer, IOCNT must be set ; to size already in buffer. MOV BX,[TempHandle] MOV SI,WORD PTR [IOCNT] MOV DI,WORD PTR [IOCNT+2] MOV DS,[BP.FILE_START] ASSUME DS:NOTHING CALL WRITEFILE ; Write next part ASSUME DS:CODE JNC TESTDONE RET TESTDONE: LES AX,[BP.FILE_OFFSET] CMP AX,WORD PTR [BP.FILE_SIZEB] JNZ GETSYS3 MOV AX,ES CMP AX,WORD PTR [BP.FILE_SIZEB+2] JNZ GETSYS3 RET ; Carry clear from CMP GETSYS3: ;Enter here if none of file is in buffer MOV AX,[MSTART] ; Furthur IO done starting here MOV [BP.FILE_START],AX MOV AL,[SYSDRV] CMP AL,[TARGDRV] JNZ TESTSYS MOV AH,DISK_RESET INT 21H GSYS: CALL SYSPRM ;Prompt for system disk TESTSYS: CALL TESTSYSDISK JC GSYS MOV BX,[BP.FILE_HANDLE] LES DX,[BP.FILE_OFFSET] PUSH DX MOV CX,ES MOV AX,LSEEK SHL 8 INT 21H POP DX LES SI,[BP.FILE_SIZEB] MOV DI,ES SUB SI,DX SBB DI,CX ; DI:SI is #bytes to go PUSH DI PUSH SI ADD SI,15 ADC DI,0 CALL DISID4 MOV AX,SI POP SI POP DI CMP AX,[MSIZE] JBE GOTSIZ2 MOV SI,[MSIZE] XOR DI,DI CALL DISIX4 GOTSIZ2: MOV WORD PTR [IOCNT],SI MOV WORD PTR [IOCNT+2],DI MOV DS,[MSTART] ASSUME DS:NOTHING CALL READFILE ASSUME DS:CODE JNC GETOFFS CALL CLSALL JMP GSYS GETOFFS: XOR DX,DX MOV CX,DX MOV AX,(LSEEK SHL 8) OR 1 INT 21H MOV WORD PTR [BP.FILE_OFFSET],AX MOV WORD PTR [BP.FILE_OFFSET+2],DX CALL CLSALL JMP IOLOOP ;************************************************* ; Test to see if correct system disk. Open handles TESTSYSDISK: MOV AX,OPEN SHL 8 MOV DX,OFFSET BIOSFIL INT 21H JNC SETBIOS CRET12: STC RET12: RET SETBIOS: MOV [BIOSHandle],AX MOV BX,AX CALL GETFSIZ CMP [BIOSSIZP],0 JZ SETBIOSSIZ CMP [BIOSSIZP],AX JZ SETBIOSSIZ BIOSCLS: MOV AH,CLOSE MOV BX,[BIOSHandle] INT 21H JMP CRET12 SETBIOSSIZ: MOV [BIOSSIZP],AX MOV WORD PTR [BIOSSIZB],SI MOV WORD PTR [BIOSSIZB+2],DI MOV [BDATE],DX MOV [BTIME],CX MOV AX,OPEN SHL 8 MOV DX,OFFSET DOSFIL INT 21H JNC DOSOPNOK JMP BIOSCLS DOSOPNOK: MOV [DOSHandle],AX MOV BX,AX CALL GETFSIZ CMP [DOSSIZP],0 JZ SETDOSSIZ CMP [DOSSIZP],AX JZ SETDOSSIZ DOSCLS: MOV AH,CLOSE MOV BX,[DOSHandle] INT 21H JMP BIOSCLS SETDOSSIZ: MOV [DOSSIZP],AX MOV WORD PTR [DOSSIZB],SI MOV WORD PTR [DOSSIZB+2],DI MOV [DDATE],DX MOV [DTIME],CX MOV AX,OPEN SHL 8 MOV DX,OFFSET COMFIL INT 21H JC DOSCLS MOV [COMHandle],AX MOV BX,AX CALL GETFSIZ CMP [COMSIZP],0 JZ SETCOMSIZ CMP [COMSIZP],AX JZ SETCOMSIZ COMCLS: MOV AH,CLOSE MOV BX,[COMHandle] INT 21H JMP DOSCLS SETCOMSIZ: MOV [COMSIZP],AX MOV WORD PTR [COMSIZB],SI MOV WORD PTR [COMSIZB+2],DI MOV [CDATE],DX MOV [CTIME],CX CLC RET ;******************************************* ; Handle in BX, return file size in para in AX ; File size in bytes DI:SI, file date in DX, file ; time in CX. GETFSIZ: MOV AX,(LSEEK SHL 8) OR 2 XOR CX,CX MOV DX,CX INT 21H MOV SI,AX MOV DI,DX ADD AX,15 ; Para round up ADC DX,0 AND DX,0FH ; If the file is larger than this ; it is bigger than the 8086 address space! MOV CL,12 SHL DX,CL MOV CL,4 SHR AX,CL OR AX,DX PUSH AX MOV AX,LSEEK SHL 8 XOR CX,CX MOV DX,CX INT 21H MOV AX,FILE_TIMES SHL 8 INT 21H POP AX RET ;******************************************** ; Read/Write file ; DS:0 is Xaddr ; DI:SI is byte count to I/O ; BX is handle ; Carry set if screw up ; ; I/O SI bytes ; I/O 64K - 1 bytes DI times ; I/O DI bytes ; DS=CS on output READFILE: ; Must preserve AX,DX PUSH AX PUSH DX PUSH BP MOV BP,READ SHL 8 CALL FILIO POP BP POP DX POP AX PUSH CS POP DS RET WRITEFILE: PUSH BP MOV BP,WRITE SHL 8 CALL FILIO POP BP PUSH CS POP DS RET FILIO: XOR DX,DX MOV CX,SI JCXZ K64IO MOV AX,BP INT 21H JC IORET ADD DX,AX CMP AX,CX ; If not =, AX