TITLE "DDIR05 - Syslib 4.0" ;================================================================= ; Copyright (C) 1989 by Harold F. Bower. Permission granted to ; Alpha Systems Corp. to distribute with The Libraries, Version 4 ;----------------------------------------------------------------- ; Author : Harold F. Bower ; Derived from SDIR05.Z80 Ver 1.5 by Richard Conn ; Date : 11 Oct 93 ; Version : 1.3 ; Module : DDIR05 ; Abstract: This module contains the routines DDIRLD and ; DDIRSLD which build a table of file names in memory. ; Each entry is 16 bytes long, with DDIRSLD entries ; containing enough information to permit file sizes to ; be determined. DDIRSLD is less efficient in terms of ; file size and execution speed. It relys on search code ; in DSLIB to return indices if DateStamper is running. ; Revision: ; 1.2 - 27 Feb 89 - Initial Release. HFB ; 1.3 - 11 Oct 93 - Added NZTIME capabilities. HFB ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Module Entry Points PUBLIC DDIRLD, DDIRSLD EXT SELFLG, DIRBUF, @FNCMP, HFILB, GETMTOP ; SysLib EXT FINDCK, CKTDF, OPENTD, RWTD, CLOSTD, FSTNXT ; DsLib EXT P2UTIM, M2UTIM, BIN2BCD ;1.3 " ; Definitions BDOS EQU 0005 ; DOS Entry vector address BUFF EQU 0080H ; Default CP/M Sector Buffer FNSIZE EQU 16 ; Basic File Name & Type element size ESIZE EQU FNSIZE+15 ; Element size + Create, Access & Mod time size SRCHF EQU 17 ; DOS Search first command SRCHN EQU 18 ; DOS Search next command SETDMA EQU 26 ; DOS Set transfer address command .Z80 CSEG ;=============================================================== ; NAME - DDIRSLD (WITH Sizing Info) ; Entry: HL - Points to Directory Buffer (ESIZE X N max) ; C - Stamp Method flag (0=P2Dos, FF=DateStamper) ; Exit : BC - Contains the Number of Files loaded ; A <> 0, Zero Flag Reset (NZ) if No Errors ; A = 0 and Zero Flag Set (Z) if TPA overflow ; Uses : AF,BC ; Special Requirements: None ;=============================================================== DDIRSLD: XOR A ; Select Larger EX JR DDIRL ; ..jump to set flag and continue ;=============================================================== ; NAME - DDIRLD (No Sizing Info) ; Entry: HL - Points to Directory Buffer (ESIZE X N max) ; C - Stamp Method flag (0=P2Dos, FF=DateStamper) ; Exit : BC - Contains the Number of Files loaded ; A <> 0, Zero Flag Reset (NZ) if No Errors ; A = 0 and Zero Flag Set (Z) if TPA overflow ; Uses : AF,BC ; Special Requirements: None ;=============================================================== DDIRLD: LD A,0FFH ; Select files of smaller EX DDIRL: LD (DFLAG),A ; Set Flag LD (DIRBUF),HL ; Save ptr to Directory Buffer LD (DSTART),HL ; Set start of buffer area PUSH DE LD A,C ; Get Stamp method OR A ; Are we going for DateStamper type? JR Z,DDIRV0 ; ..jump if P2Dos type PUSH HL ; Save regs while we test for DS Routines PUSH AF ; ..including flag byte in A CALL FINDCK ; Is DateStamper alive and well? JR Z,NODS ; ..jump to P2D if not CALL CKTDF ; Do we have a valid !!!TIME&.DAT file? JR Z,NODS ; ..jump to P2D if not POP AF ; Else we have everything ready for DS, Do it JR DSOK ; ..bypass defaulting to P2D and continue NODS: POP AF ; Restore flag byte XOR A ; ..and set for P2D DSOK: POP HL ; Restore rest of regs DDIRV0: LD (TSFLAG),A ; ..and save PUSH HL ; Save Registers LD HL,TFCB ; Prepare the FCB for all Users, LD A,'?' LD B,13 ; ..Names, Types and Extents CALL HFILB XOR A ; Set Zero for other entries LD (HL),A INC HL LD (HL),'?' ; Get all Data Modules INC HL LD B,21 CALL HFILB ; This section of code initializes the counters used LD HL,0 ; HL = 0 LD (FCOUNT),HL ; Total Files on Disk = 0 ; Insure default DMA address set to 80H LD DE,BUFF LD C,SETDMA CALL BDOS ; Now we begin scanning for files to place into the Memory Buffer LD C,SRCHF ; Search for File JR DIRLP1 DIRLP: CALL PENTRY ; Place entry in Dir JR Z,DIRDNX ; Memory Overflow error. Exit Z LD C,SRCHN ; Search for Next match DIRLP1: LD DE,TFCB ; Pt to Wild Name CALL FSTNXT CP 255 ; Done? JR NZ,DIRLP LD A,(TSFLAG) ; Are we loading P2D Stamps? OR A JR Z,DIRPDN ; ..jump to exit if so ; We are using DateStamper stamps, so append stamps to FN.FT string XOR A ; Open T&D for Read-only CALL OPENTD ; ..don't check errs cause CKTD was Ok LD BC,(FCOUNT) ; Load this many records LD HL,(DSTART) ; ..starting with this entry LD DE,0FFFFH ; Set dummy Random record # to force read TDLOOP: LD A,B ; Are we done? OR C JR Z,DIRDDN ; ..exit if so PUSH BC ; Save count LD BC,FNSIZE ; Offset to RR # ADD HL,BC LD A,(HL) ; Get Index # PUSH HL ; Save index to entry TD field PUSH AF ; ..and index INC HL LD A,(HL) ; Get RR # to HL INC HL LD H,(HL) LD L,A OR A ; Compare current (DE) w/desired (HL) SBC HL,DE ADD HL,DE JR Z,SAMREC ; ..jump if we already have the record EX DE,HL ; Else put desired rec in DE PUSH DE ; ..and save XOR A CALL RWTD ; Read the T&D file LD (TDBUF),HL ; Save TD buffer start addr JR NZ,TDRDOK ; ..jump if read Ok, else null fields LD B,128 ; Null the entire sector (A=0 already) TDBADL: LD (HL),A INC HL DJNZ TDBADL ; Loop til all done TDRDOK: POP DE ; ..and restore RR # SAMREC: POP AF ; Restore record Index ADD A,A ; ..and mult by 16 to get relative addr ADD A,A ADD A,A ADD A,A LD C,A LD B,0 LD HL,(TDBUF) ADD HL,BC ; HL now points at source T&D string in Buffer EX DE,HL ; Swap regs.. EX (SP),HL ; ..to put RR # on stack, dest adr in HL EX DE,HL ; ...then Dest in DE, source in HL LD BC,15 ; Move all three stamps LDIR EX DE,HL ; HL --> Next Dir entry POP DE ; DE = RR # in BUFF POP BC ; BC = Count DEC BC JR TDLOOP ; ..and loop til done ; Now we are done with the Load -- Set up Return Values DIRDDN: CALL CLOSTD ; Close the T&D File for safety DIRPDN: OR 0FFH ; Set Flags for Load OK (NZ) DIRDNX: LD BC,(FCOUNT) ; Get total number of files in BC JP DEXIT ; ..restore regs elsewhere & return ;..... ; PENTRY -- ; Place Entry in Directory Buffer if not an erased entry ; ; On Input, A = 0-3 for adr index in Buff of Entry FCB ; FCOUNT = Number of Files in Dir so far ; On Output, FCOUNT = Number of Files in Dir so far ; A = 0 and Zero Flag set if Memory Overflow Error PENTRY: PUSH HL ; Save Regs PUSH DE PUSH BC LD (INDX),A ; Save index into directory buffer RRCA ; Multiply by 32 for Offset Computation RRCA RRCA AND 60H ; A = Byte offset LD DE,BUFF ; Pt to Buffer Entry LD L,A ; Let HL = Offset LD H,0 ADD HL,DE ; HL = Ptr to FCB LD A,(HL) ; Get User Number CP 20H ; Is it CP/M Plus Volume, T&D, or ZSDOS2 Del? JP NC,PEDONE ; ..jump if so ; HL = Adr of FCB in Buff ; Scan Directory entries as loaded so far for another entry by same ; name; If found, set that entry to be the entry with the larger EX ; and return with the zero flag set, indicating no new file; If not ; found, return with Zero Flag Reset (NZ) CALL DUPENTR ; Check for Duplicate and select EX JR Z,PEDONE ; Skip if Duplicate ; Increment total number of Files LD DE,(FCOUNT) ; Total Files = Total Files + 1 INC DE LD (FCOUNT),DE ; Copy FCB pted to by HL into Directory Buffer LD DE,(DIRBUF) ; DE pts to Next Entry Locn, HL pts to FCB LD BC,FNSIZE ; Number of Bytes in basic entry LDIR ; Copy FCB into Memory Buffer LD A,(TSFLAG) ; Which method do we use? OR A JR Z,USEMS ; ..jump if using MS/P2Dos Time stamps POP BC ; Else restore DS indices POP HL PUSH HL PUSH BC ; ..while keeping on stack EX DE,HL ; Put destination in HL LD (HL),B ; stash Index into T&D Sector INC HL LD (HL),E ; ..and T&D Sector number INC HL LD (HL),D INC HL EX DE,HL ; Put Buffer pointer back in DE LD B,ESIZE-FNSIZE-3 JR FILLIT ; Null out remaining USEMS: LD HL,BUFF+16 ; Point to DosDisk Flag bytes LD A,(HL) ; Get the first byte CP 0FDH ; Is it the MS-DOS 40-track flag? JR NZ,USEP2D ; ..jump if not INC HL ; Else check second byte to be sure SUB (HL) JR NZ,USEP2D ; ..jump if no match LD B,10 ; Ok, so null Create and Access fields CALL NULLIT LD HL,BUFF+22 ; Point to source MS-DOS DateSpec CALL M2UTIM ; ..and do the conversions to DE JR P2DONE ; Continue with common code USEP2D: LD HL,BUFF+60H ; Point to P2D Time indicator LD A,(HL) AND 7FH ;1.3 .(mask diff between P2D and NZTime) CP 21H ; Is there a valid time stamp flag? JR NZ,NOTP2D ; ..jump if not LD A,(INDX) ; Else calculate offset to correct entry LD C,A ADD A,A ; *2 ADD A,A ; *4 ADD A,C ; *5 ADD A,A ; *10 INC A ; +1 LD C,A ; Entries start at offset=1, 11, 21 decimal LD B,0 LD A,(HL) ;1.3 Get Flag Byte (A1=NZTime, 21=P2Dos) ADD HL,BC ; Point to Stamp field for desired entry RLA ;1.3 Is it NZTime? JR C,USENZT ;1.3 ..jump if NZTime Stamping CALL P2UTIM ; ..and parse Create Stamp to Table LD B,5 ; Null the Last Accessed field CALL NULLIT CALL P2UTIM ; Parse Modify Stamp JR P2DONE ; ..and continue NOTP2D: LD B,ESIZE-FNSIZE ; Set count to fill entire field FILLIT: CALL NULLIT ; Fill rest of time with Nulls P2DONE: LD (DIRBUF),DE ; Set ptr to Next Entry CALL GETMTOP ; Get top available addr in HL LD A,H ; Get base page of Bdos DEC A ; ..and move one more page down CP D ; Is ptr to next entry beyond this? JR NZ,PEDONE ; Ok if not at Buffer Overflow Level ; Done with PENTRY with Memory Overflow Error XOR A ; Error DEFB 21H ; Code for "LD HL,xxx". Trash HL and fall thru ; Done with PENTRY and No Error PEDONE: OR 0FFH ; Set Flags for No Error (NZ) POP BC ; Restore regs DEXIT: POP HL POP DE RET ; Gather File Stamps from NZTime-stamped directory USENZT: LD (IPTR),HL ;1.3 Save Pointer to input NZTime stamps LD L,(HL) ;1.3 LD A,(INDX) ;1.3 Get Index number (0,1,2) LD B,A ;1.3 .save LD A,8 ;1.3 SUB B ;1.3 Compute current byte when starting LD C,A ;1.3 save INC B ;1.3 DEC B ;1.3 Is Input byte already aligned? JR Z,USENZ1 ;1.3 ..jump if so USENZ0: ADD HL,HL ;1.3 Else rotate input byte (H is don't care) DJNZ USENZ0 ;1.3 ..looping til done USENZ1: LD A,3 ;1.3 Get all three stamps USENZ2: LD (LPCTR),A ;1.3 Set Outer Loop Counter LD B,7 ;1.3 CALL GBITS ;1.3 Get Year (7 bits) LD B,4 ;1.3 CALL GBITS ;1.3 Month (4 bits) LD B,5 ;1.3 CALL GBITS ;1.3 Day (5 bits) LD B,5 ;1.3 CALL GBITS ;1.3 Hour (5 bits) LD B,6 ;1.3 CALL GBITS ;1.3 Minute (6 bits) LD A,(LPCTR) ;1.3 DEC A ;1.3 Have we done all 3 fields? JR NZ,USENZ2 ;1.3 .loop if Not (saving new count) JR P2DONE ;1.3 ..jump to exit when finished ;..... ; Scan Directory Entries as loaded so far for another entry by the same ; name; If found, set that entry to be the entry with the larger EX & DM ; and return with the Zero Flag set, indicating no new file; If not ; found, return with Zero Flag Reset (NZ) ; On Input, HL pts to entry to scan for, FCOUNT = Number of entries so far, ; and (DSTART) = Starting Address of Directory Loaded ; On Output, A = 0 and Zero Flag Set if duplicate entry found; A = 0FFH and NZ ; if no Dup Entry found ; Only HL Not affected DUPENTR: PUSH HL ; Save ptr to entry to scan for EX DE,HL ; Ptr in DE LD BC,(FCOUNT) ; Check Count LD A,B ; No Entries? OR C JR Z,NODUP ; No Duplicate Entry Return LD HL,(DSTART) ; HL pts to First Entry DUPLOP: PUSH BC ; Save count PUSH HL ; Save ptrs PUSH DE LD B,12 ; Compare User Number, FN, and FT CALL @FNCMP JR Z,HAVDUP ; If equal, jump to process Duplicate ; No duplicate found; Advance to next entry POP DE ; Restore ptrs POP HL LD BC,ESIZE ; HL pts to current entry in Buffer ADD HL,BC ; ..Add ESIZE to it POP BC ; Get COUNT DEC BC ; Count down LD A,B ; Check for done OR C JR NZ,DUPLOP ; No Duplicate found, Period NODUP: OR 0FFH ; Set flags to Indicate Dup not found (NZ) POP HL ; Restore ptr to entry to scan for RET ; Duplicate entries have been identified at this point HAVDUP: EX DE,HL ; DE not pts to Dir Entry, HL pts to target ; Before we check EX field, check Data Module PUSH HL ; Save pointers to Extent PUSH DE INC HL ; Advance to DM (aka S2) INC HL INC DE ; ..on both pointers INC DE EX DE,HL LD A,(DE) ; Get Data Module field from target CP (HL) ; ..compare with that in Dir Entry POP DE ; Restore pointers to EX POP HL CALL STCOND ; Set conditions JR NC,DUPBIG ; ..and jump if Dir is greater LD A,(DE) ; Get Extent Field from Directory Entry CP (HL) ; Compare with that in target ; Carry Set if New entry > Existing entry CALL STCOND ; Set conditions JR Z,DUPFND ; ..jump if New > Orig but Not Sizing ; ...or New < Orig and Sizing ; New target is larger than stored entry and Sizing, or New target smaller ; than stored and Not Sizing. Must move sizing data to Stored Entry DUPBIG: LD BC,FNSIZE-12 ; Number of bytes to move LDIR ; Move it ; Return indicator that Duplicate WAS found DUPFND: POP DE ; Clear stored addrs from stack POP HL POP BC ; Clear count from stack XOR A ; Indicate dup found POP HL ; Restore ptr to entry to scan for RET ;..... ; Set duplicate condition flags ; Enter: C flag has results of compare ; Exit : Z flag Set (Z) if No replacement needed STCOND: LD A,(DFLAG) ; Get Search flag (0=Sizing, FF=No Sizing) RLA ; Move Carry Flag to LSB AND 0011B ; Keep bit for Search Flag, and Carry RET Z ; ..jump if New < Orig and Sizing CP 0011B RET ; ..jump if New > Orig but Not Sizing ;..... ; NZTime Support Routine. Get # of bits spec'ed from NZTIM, Return BCD Digit ; ENTER: L = Current working byte ; DE = Ptr to Dest of Univ stamps ; C = Bit # currently in position (8..1) ; B = Number of bits to gather ; EXIT : A = BCD Conversion of # bits from entry GBITS: LD H,0 ;1.3 Clear Bit Accumulator GBITS0: ADD HL,HL ;1.3 Shift B7 of L into B0 of H, H shifts left DEC C ;1.3 Have we shifted last of input Byte? JR NZ,GBITS1 ;1.3 ..jump if Not PUSH HL ;1.3 Else need a byte, save regs LD HL,(IPTR) ;1.3 Get input ptr INC HL ;1.3 .go to next byte LD A,(HL) ;1.3 ..fetch LD (IPTR),HL ;1.3 ...save updated ptr POP HL ;1.3 .(restore regs LD L,A ;1.3 Place new Input byte for shifting LD C,8 ;1.3 and init Bits Remaining counter GBITS1: DJNZ GBITS0 ;1.3 ..Shift another if not done LD A,H ;1.3 Else get completed output byte CALL BIN2BCD ;1.3 .make BCD for Universal LD (DE),A ;1.3 ..store in Output INC DE ;1.3 ...and advance to next digit RET ;1.3 ;..... ; Fill the string addressed by DE with a Zero for B bytes NULLIT: XOR A ; Load a cheap Null NULL0: LD (DE),A ; Stuff a byte INC DE ; ..and advance DJNZ NULL0 ; Loop til done RET ;..... ; Data Buffers DSEG ; Put in Data Segment IPTR: DEFS 2 ;1.3 Pointer to current NZTime Input Byte LPCTR: DEFS 1 ;1.3 Loop Counter for NZTime Conversion INDX: DEFS 1 ; Index to desired file in Directory Buffer DFLAG: DEFS 1 ; 0 = Select Files w/Larger EX, Else w/Smaller EX TSFLAG: DEFS 1 ; 0 = Use P2Dos Stamps, FF = Use DateStamper stamps DSTART: DEFS 2 ; Pointer to First Directory Entry FCOUNT: DEFS 2 ; Total Number of Files/Number of Selected Files TFCB: DEFS 36 ; Temporary FCB (FN,FT Wild) TDBUF: DEFS 2 ; Temp Address of T&D Sector buffer END