; SAP - SORT AND PACK DISK DIRECTORY ; ; Originally coded for CP/M by L.E. Hughes 8080SDC ; Modified 5/30/78 BY B.R. Ratoff ; 1) PICK UP VECTORS FOR ANY SIZE SYSTEM ; 2) HANDLE NULL EXTENTS OF NON-NULL FILES ; PROPERLY ; ; Modified by Trevor MARSHALL 18/10/79 ; add SAP B:,etc AND ATTRIBUTE HIDE ; ; ; Rewritten by Trevor MARSHALL, 13 Apr 80 ; Elec Eng Dept ; Uni W.A. ; to be compatible with all disks supported by CDOS 2.17 ; by including the 'READ SYSTEM DIRECTORY' feature ; of the CDOS ; ; Modified 31 Oct '80 to handle the large files of ; CDOS 2.36 by adding double precision pointer bumping ; ;********** WARNING ********* Do not use with hard disks ; (not tested other than with floppies) ; BDOS: EQU 5 FCB: EQU 5CH ; ORG 100H ; SAP: LD SP,STACK+64 LD C,19H ;WHAT DSK IS CURRENT? CALL BDOS LD (DSKSAV),A LD A,(FCB) ;DSK REQUEST PRESENT? LD (SYSDIR),A ;Set up 'SYS DIR' FCB LD (DSK),A ;Save it for write ; Now check CDOS ver 1 or higher is in use LD C,8DH CALL BDOS LD A,B CP 1 JR GE,NEXT21 LD DE,CDOSERR ;Must be incompatible sys LD C,9 ;Write error msg and exit CALL BDOS JP 0 NEXT21: LD C,0FH ;Open SYS DIR LD DE,SYSDIR CALL BDOS CP A,0FFH ;Error? JR NZ,NEXT LD DE,OPENERROR ;Yes LD C,9 ;Print the message CALL BDOS JP 0 NEXT: LD DE,MSG1 ;.....reading LD C,9 CALL BDOS ; LD A,0 ;Initialize LD (SECTORCOUNT),A ;the sector count LD DE,BUF-80H ;prepare for DMA increment LP1: LD HL,SECTORCOUNT INC (HL) ;Incr the sectorcount LD HL,80H ;Need to increment bffr pointer ADD HL,DE EX DE,HL LD C,1AH ;Set DMA address to buffer PUSH DE ;Save it CALL BDOS LD C,14H ;Read next record LD DE,SYSDIR ;Point at 'FCB' CALL BDOS POP DE ;Fetch buffer DMA addr CP A,0 ;Any errors? JR Z,LP1 ;No, get more sectors CP 1 JR Z,NEXT1 ;End of file OK LD DE,READERROR ;All else are errors LD C,9 CALL BDOS JP 0 NEXT1: LD HL,SECTORCOUNT DEC (HL) ;As we musn't pass the EOF ; We have now read in the directory. The number of ; records read is in sectorcount. ; Now calculate the directory memory image length. LD A,(HL) LD L,A LD H,0 ; How long are the sectors? ; We may have to use a system call to find out LD DE,80H ;Presently 80H LD C,89H ;Multiply DE = DE * HL CALL BDOS ; LD HL,BUF ;Add the buffer base addr ADD HL,DE LD (BUFEND),HL ;Save end addr in BUFEND ; CALL CLEAN ;CLEAN THE DIRECTORY ; LD DE,MSG2 ;.....Sorting LD C,9 CALL BDOS ; CALL SORT ;SORT THE DIRECTORY ; I have deleted PACK as it is assumed that single disk systems ; will not be used under CDOS. User may modify as required ; CALL PACK ;PACK THE DIRECTORY ; ; Now we must write the directory to the disk WRITE: LD DE,MSG3 ;.....Writing LD C,9 CALL BDOS ; LD A,(DSK) LD (SYSDIR),A ;Poke byte 1 of FCB LD C,0FH ;Open SYS DIR LD DE,SYSDIR CALL BDOS CP A,0FFH ;Error? JR NZ,NEXT2 LD DE,WRITEERROR ;Yes LD C,9 ;Print the message CALL BDOS JP 0 NEXT2: LD A,1 ;Initialize LD (SECTORSWRITTEN),A LD HL,SYSDIR RES 7,(HL) ;Reset the 'read only' atribute LD DE,BUF-80H ;prepare for DMA increment LP11: LD HL,SECTORSWRITTEN INC (HL) ;increment the count of sectors LD HL,80H ;Need to increment bffr pointer ADD HL,DE EX DE,HL LD C,1AH ;Set DMA address to buffer PUSH DE ;Save it CALL BDOS LD C,15H ;Write next record LD DE,SYSDIR ;Point at 'FCB' CALL BDOS POP DE ;Fetch buffer DMA addr CP A,0 ;Any errors? JR NZ,WERR ;Yes ; Now see if we have finished write LD A,(SECTORCOUNT) LD HL,SECTORSWRITTEN CP (HL) ;Have we written enough? JR NC,LP11 ;No, get more sectors JR NEXT12 WERR: LD DE,WRITEERROR ;All else are errors LD C,9 CALL BDOS JP 0 NEXT12: ; We have now written the directory. LD A,(DSKSAV) ;Restore logged disk LD E,A LD C,0EH CALL BDOS JP 0 ;And exit to CDOS ; ; CLEAN: LD BC,0 ;III = 0 CLEAN1: LD (III),BC CALL INDEX2 ;HL = BUF + 16 * III PUSH HL ; HL now contains the addr of the buffer entry ; we want to return if it is beyond BUFEND XOR A ;Clear carry LD DE,(BUFEND) SBC HL,DE ;HL = HL - DE - CY ; DE should be > HL, if not, return POP HL RET NC ; ; Continue LD A,(HL) ;JUMP IF THIS IS A DELETED FILE CP 0E5H JP Z,CLEAN2 LD A,L ;HL = HL + 12 ADD 12 LD L,A JP NC,$+4 INC H LD A,(HL) ;CHECK EXTENT FIELD OR A JP NZ,CLEAN4 ;SKIP IF NOT EXTENT ZERO EXTENT0: INC HL ;POINT TO RECORD COUNT FIELD INC HL INC HL LD A,(HL) ;CHECK RECORD COUNT FIELD OR A JP NZ,CLEAN4 ;JUMP IF NON-ZERO LD BC,(III) ;Clear all 32 bytes CALL INDEX2 CLEAN2: LD C,32 CLEAN3: LD (HL),0E5H INC HL DEC C JP NZ,CLEAN3 CLEAN4: LD BC,(III) ; III = III + 1 INC BC JP CLEAN1 RET ; COMP: LD BC,(III) ;;HL = BUF + 16 * III CALL INDEX2 PUSH HL LD BC,(J) ;HL = BUF + 16 * J CALL INDEX2 EX DE,HL POP HL ; Need to allocate highest priority to disk label LD A,(DE) ;Is 2nd entry a label? CP 81H ;The label's attribute JR NZ,NEXT56 ;NZ=> not a label SCF ;Must be a disk label RET ;Swap them NEXT56: LD A,(HL) ;Is 1st entry a label? CP 81H JR NZ,NEXT57 SCF CCF ;Dont swap RET NEXT57: INC HL INC DE ;POINT PAST ATRIBUTES LD C,12 ;NUMBER OF BYTES TO COMPARE COMP1: LD A,(DE) ;COMPARE NEXT BYTE CP (HL) RET NZ ;RETURN IF NOT EQUAL INC DE INC HL DEC C ;LOOP THRU FIRST 13 BYTES JP NZ,COMP1 XOR A ;CLEAR FLAGS AND EXIT RET SORT: LD BC,0 ;III = 0 LD (III),BC SORT1: LD BC,(III) ;J = III + 1 INC BC LD (J),BC SORT2: CALL COMP ;IF NAME(J) HL JR C,SORT2 ; LD BC,(III) ;III = III + 1 INC BC LD (III),BC ; ; See if I beyond BUFEND - 10H CALL INDEX2 PUSH HL ; HL now contains the addr of the buffer entry ; we want to jump if it is not beyond BUFEND-20H LD DE,(BUFEND) DEC DE ;Make end addr not inclusive LD HL,-20H ADD HL,DE EX DE,HL ;Now have end addr - 10H XOR A ;Clear carry POP HL SBC HL,DE ;HL = HL - DE - CY ; DE should be > HL JR C,SORT1 ; RET ; ; SWAP: LD BC,(III) CALL INDEX2 PUSH HL LD BC,(J) CALL INDEX2 EX DE,HL POP HL LD C,32 SWAP1: LD A,(DE) LD B,A LD A,(HL) LD (DE),A LD (HL),B INC DE INC HL DEC C JP NZ,SWAP1 RET ; Bump index in double precision INDEX2: PUSH BC ;Get BC POP HL ;into HL ADD HL,HL ; X 2 ADD HL,HL ; X 4 ADD HL,HL ADD HL,HL ADD HL,HL ; X 32 LD DE,BUF ADD HL,DE RET ;PACK: LD BC,0 ;III = 0 ; LD (III),BC ;PACK1: LD BC,(III) ; CALL INDEX2 ;HL = BUF + 16 * I ; LD A,L ;HL = HL + 9 ; ADD 9 ; LD L,A ; JP NC,$+4 ; INC H ; LD A,(HL) ;JUMP IF FILETYPE NOT 'X$$' ; SUB '0' ; WHERE 0.LE.X.LE.9 ; JP C,PACK2 ; CP 10 ; JP NC,PACK2 ; LD (J),A ; ????? ; INC HL ; LD A,(HL) ; CP '$' ; JP NZ,PACK2 ; INC HL ; LD A,(HL) ; CP '$' ; JP NZ,PACK2 ; INC HL ;SET EXTENT NUMBER TO X ; LD A,(J) ; ???? ; LD (HL),A ; DEC HL ;SET FILETYPE TO '$$$' ; LD (HL),'$' ; DEC HL ; LD (HL),'$' ; DEC HL ; LD (HL),'$' ;PACK2: LD BC,(III) ;I = I + 1 ; INC BC ; LD (III),BC ; ; See if I beyond BUFEND ; CALL INDEX2 ; HL now contains the addr of the buffer entry ; we want to jump if it is not beyond BUFEND ; XOR A ;Clear carry ; LD DE,(BUFEND) ; SBC HL,DE ;HL = HL - DE - CY ; DE should be < HL ; JR C,PACK1 ; RET ; ; ERROR MESSAGES ; CDOSERR: DB 0AH,0DH,'Incompatible with this version of CDOS.$' OPENERROR: DB 0AH,0DH,'Error in opening directory file.$' READERROR: DB 0AH,0DH,'Error whilst reading directory.$' WRITEERROR: DB 0AH,0DH,'Error whilst writing directory.' DB 0AH,0DH,'The image starts in memory at 500 H' DB 0AH,0DH,'Save it on a BLANK disk (allow 40 Blocks).$' MSG1: DB 0AH,0DH,'......Reading$' MSG2: DB 0AH,0DH,'......Sorting$' MSG3: DB 0AH,0DH,'......Writing$' ; ; DATA AREA ; SYSDIR: DB 0,'SYS DIR',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; STACK: DEFS 64 SECNO: DEFS 1 SECTORSWRITTEN: DS 1 SECTORCOUNT: DS 1 III: DEFS 2 J: DEFS 2 DSKSAV: DS 1 DSK: DS 1 BUFEND: DS 2 ORG 500H BUF: DEFS 8192 ; END 100H