; Z80DOS - Z80 Disk Operating System Nov 15, 1988 ; ; Version 2.31 Fast file lookup for random records fix ; Date: 15 Nov 88 ; Update: Eugene Nolan ; ;----------------------------------------------------------------------- ; ; Version 2.3 Fast file lookup, ZRL compatibility ; Date: 4 Nov 88 ; Update: Eugene Nolan ; ;----------------------------------------------------------------------- ; ; Version 2.0a - BETA TEST VERSION - 6 Nov 87 by Carson Wilson ; ; Support file: Z80DDISK.Z80 ; Version: 2.0 ; Date: 6 Nov 87 ; Author: Carson Wilson ; Description: DOS Return CP/M Version, Disk Functions ; ; Changes: -------- ; Changed READR and WRITER to use a common error function, ; RWERR, which displays "Data error on D:". ; ; New disk will be overwritten, data from the first file ; will probably be lost. ; ; -------- ; Command 37 (reset individual disk) now resets the disk ; changed vector instead of the drive R/O vector. ; ; -------- ; Removed code which made public files read-only from ; other user areas. The user must now manually set public ; files to read-only using the R/O attribute (t1). This ; change was made because some applications must write to ; public files. ; ; -------- ; System files are now R/W unless referenced by wildcards. ; ;----------------------------------------------------------------------- ; ; Return version number ; ;----------------------------------------------------------------------- ; CMND12: LD A,22H ; Set version number LD IX,3800H ; This will put an '8' into D ; ; Register upon return, saying ; ; Z80DOS operating JR CMD25A ; And exit ; ;----------------------------------------------------------------------- ; ; Disk functions ; ;----------------------------------------------------------------------- ; ; Reset disk system ; CMND13: LD HL,0 ; Load zero LD (LOGIN),HL ; All drives logged out LD (DSKRO),HL ; All drives read/write LD (DIFF),HL ; No disks changed LD HL,RAMLOW+80H ; Set up DMA address LD (DMA),HL ; And save it CALL STDMA ; Do BIOS call XOR A ; Set default drive = 'A' LD (DEFDRV),A ; Save it LD A,RESDSK ; CALL SELDK ; Select drive 0=A, 1=B, etc. LD A,(SUBFLG) ; Get submit flag JR CMD25A ; Exit ; ; Search for file ; CMND17: CALL SELDRV ; Select drive from FCB LD A,(IX+0) ; Get drive number from FCB SUB '?' ; Test if '?' JR Z,CMD17B ; If so all entries match LD A,(IX+14) ; Get system byte CP '?' ; Test if '?' JR Z,CMD17A ; Yes, jump LD (IX+14),0 ; Load system byte with zero ; CMD17A: LD A,15 ; Test first 15 items in FCB ; CMD17B: CALL SEARCH ; Do search ; CMD17C: LD HL,(DIRBUF) ; Copy directory buffer LD DE,(DMA) ; To DMA address LD BC,128 ; Directory=128 bytes LDIR RET ; Exit ; ; Search for next occurrence of file ; CMND18: LD IX,(DCOPY) ; Get last FCB used by search CALL SELDRV ; Select drive from FCB CALL SEARCN ; Search next file match JR CMD17C ; And copy directory to DMA address ; ; Delete file ; CMND19: CALL SELDRV ; Select drive from FCB CALL DELETE ; Delete file ; CMD19A: LD A,(SEAREX) ; Get exit byte 00=file found,0ffh not JR CMD25A ; And exit ; ; Rename file ; CMND23: CALL SELDRV ; Select drive from FCB CALL RENAM ; Rename file JR CMD19A ; And exit ; ; Return login vector ; CMND24: LD HL,(LOGIN) ; Get login vector ; CMD24A: LD (PEXIT),HL ; Save it RET ; And exit ; ; Return current drive ; CMND25: LD A,(DEFDRV) ; Get current drive ; CMD25A: JP EXIT ; And exit ; ; Return allocation vector ; CMND27: LD HL,(ALV) ; Get allocation vector JR CMD24A ; And exit ; ; Return disk R/O vector ; CMND29: LD HL,(DSKRO) ; Get disk R/O vector JR CMD24A ; And exit ; ; Set file attributes ; CMND30: CALL SELDRV ; Select drive from FCB CALL CSTAT ; Change status JR CMD19A ; And exit ; ; Get Disk Parameter Block Address ; CMND31: LD HL,(IXP) ; Get drive table JR CMD24A ; And exit ; ; Set/get user code ; CMND32: LD A,E ; Get user code INC A ; Test if 0ffh LD A,(USER) ; Get old user code JR Z,CMD25A ; If 0ffh then exit LD A,E ; Get new user code AND 01FH ; Mask it LD (USER),A ; Save it RET ; And exit ; ; Compute file size ; CMND35: CALL SELDRV ; Select drive from FCB CALL FILSZ ; Compute file size JR CMD19A ; And exit ; ; Set random record count ; CMND36: LD HL,32 ; Set pointer to next record CALL CALRRC ; Calculate random record count ; LDRRC: LD (IX+33),D ; And save random record count LD (IX+34),C LD (IX+35),B RET ; And exit ; ; Reset individual disk drives from vector in DE ; CMND37: LD A,E ; Get mask LSB CPL ; Complement it LD E,A LD A,D ; Get mask MSB CPL ; Complement it LD D,A LD HL,(LOGIN) ; Get login vector LD A,E ; Mask login vector AND L ; LSB LD L,A LD A,D ; Mask login vector AND H ; MSB LD H,A LD (LOGIN),HL ; Save login vector EX DE,HL ; Use login vector as mask LD HL,(DIFF) ; Get disk changed vector LD A,E ; Mask drive R/O vector AND L ; LSB LD L,A LD A,D ; Mask drive R/O vector AND H ; LSB LD H,A LD (DIFF),HL ; Save disk changed vector RET ; And exit ; ; Select disk from FCB ; SELDRV: LD A,0FFH ; Set disk select done flag LD (FLDRV),A LD A,(DEFDRV) ; Get current drive LD (DRIVE),A ; Save it in memory LD E,A ; Save it in register e LD A,(IX+0) ; Get drive from FCB LD (FCB0),A ; Save it LD D,A CP '?' ; Test if '?' JR Z,CMND14 ; Yes, then select drive from register e AND 01FH ; Mask drive LD A,E ; Test if zero JR Z,SELDR0 ; Select drive from register e LD A,D DEC A ; Decrement drive ; SELDR0: CALL SELDK ; Select drive LD A,(IX+0) ; Get drive from FCB AND 0E0H ; Remove drive bits LD B,A ; Save register LD A,(USER) ; Get user number OR B ; Insert user number in FCB LD (IX+0),A RET ; And exit ; ; Select disk ; CMND14: LD A,E ; Copy drive number ; SELDK: AND 0FH ; Mask drive number to 0-15 LD B,A ; Save counter LD DE,(LOGIN) ; Get login vector OR A ; Test drive 'a' JR Z,SELDK1 ; Yes then jump ; SELDK0: RR D ; Shift login vector RR E ; Until bit 0 register e DJNZ SELDK0 ; Is current drive ; SELDK1: LD HL,DEFDRV ; Get pointer last drive BIT 0,E ; Test if drive logged in JR Z,SELDK2 ; No, login drive CP (HL) ; Test same drive RET Z ; Yes then exit ; SELDK2: LD (HL),A ; Save new current drive PUSH DE ; Save drive logged in flag LD C,A CALL SELDSK ; Do BIOS select LD A,H ; Test if error OR L JR Z,SELDK3 ; Yes, illegal drive number LD E,(HL) ; Get LSB translation vector INC HL ; Increment pointer LD D,(HL) ; Get MSB translation vector INC HL ; Increment pointer LD (TRANS),DE ; Save translation vector LD (TEMP0),HL ; Save address temp0 LD DE,6 ADD HL,DE ; Point to dirbuf pointer LD DE,DIRBUF ; Load dirbuf pointer LD BC,8 ; Copy pointers to dirbuf, LDIR ; Csv (wacd), alv from BIOS LD HL,(IXP) ; Get drive parameter address LD C,15 ; Copy 15 bytes LDIR POP DE ; Get drive logged in flag BIT 0,E ; Test it RET NZ ; Drive logged in so return LD HL,(LOGIN) ; Get login vector CALL SDRVB ; Set drive bit in login vector LD (LOGIN),HL ; Save login vector JR INITDR ; And setup drive tables ; SELDK3: LD HL,(STSEL) ; Load error message address JP (HL) ; And display error ; ; Init drive ; Clear allocation vector bit buffer after drive reset ; INITDR: LD DE,(MAXLEN) ; Get length alv buffer-1 (bits) LD A,3 ; Divide by 8 ; INITD0: SRL D ; To get bytes RR E DEC A JR NZ,INITD0 INC DE ; Increment, so all bits are cleared LD HL,(ALV) ; Get pointer alv buffer PUSH HL ; INITD1: LD (HL),0 ; Clear 8 bits INC HL ; Increment pointer DEC DE ; Decrement counter LD A,D ; Test if counter zero OR E JR NZ,INITD1 ; Not then jump POP HL ; Get alv pointer LD DE,(NDIR0) ; Get first two bytes alv buffer LD (HL),E ; Save LSB INC HL ; Increment pointer LD (HL),D ; Save MSB LD HL,(TEMP0) ; Clear number of files XOR A ; On this drive LD (HL),A ; Clear LSB INC HL ; Increment pointer LD (HL),A ; Clear MSB LD (SUBFLG),A ; Clear submit flag (reset disk command) CALL SETFCT ; Set file count ; INITD2: LD A,0FFH ; Update directory checksum CALL RDDIR ; Read FCB's from directory CALL TSTFCT ; Test last FCB RET Z ; Yes then exit CALL CALDIR ; Calculate entry point FCB LD A,(HL) ; Get first byte FCB CP 0E5H ; Test empty directory entry JR Z,INITD2 ; Yes then get next FCB CP 021H ; Test time stamp JR Z,INITD2 ; Yes then get next FCB LD A,(USER) ; Get user number CP (HL) ; Test if user is same JR NZ,INITD3 ; No then jump INC HL ; Point to file name LD A,(HL) ; Get first char filename SUB '$' ; Test if '$' JR NZ,INITD3 ; Not then jump DEC A ; Load a with 0ffh LD (SUBFLG),A ; Save it in subflg ; INITD3: LD C,1 ; Set bit in alv buffer CALL FILLBB ; Set bits from FCB in alv buffer CALL SETLF ; Update last file count JR INITD2 ; ; ; Set drive bit from (defdrv) in HL ; Exit: DE = HL before setting bit (if any) ; SDRVB: EX DE,HL ; Copy hl=>de LD HL,1 ; Get mask drive "a" LD A,(DEFDRV) ; Get current drive OR A ; Test if drive "a" JR Z,SDRVB1 ; Yes then done ; SDRVB0: ADD HL,HL ; Get next mask DEC A ; Decrement drive counter JR NZ,SDRVB0 ; And test if done ; SDRVB1: LD A,D ; Hl=hl or de OR H LD H,A LD A,E OR L LD L,A RET ; Exit ; ; Calculate sector/track directory ; STDIR: LD HL,(FILCNT) ; Get FCB counter directory SRL H ; Divide by 4 RR L ; (4 FCB's / sector) SRL H RR L LD (RECDIR),HL ; Save value (used by checksum) EX DE,HL ; Copy it to de LD HL,0 ; Clear hl ; ; Calculate sector/track ; Entry: hl,de = sector number (128 byte sector) ; Exit: set track = hl,de / maxsec ; set sector = hl,de mod maxsec ; CALST: LD BC,(MAXSEC) ; Get sectors/track LD A,17 ; Set up loop counter ; CALST0: OR A ; Test hl>=bc SBC HL,BC CCF JR C,CALST1 ; Yes then jump ADD HL,BC ; No then restore hl OR A ; And clear carry ; CALST1: RL E ; Shift result in de RL D DEC A ; Test last bit done JR Z,CALST2 ; Yes then exit RL L ; Shift next bit in hl RL H JR CALST0 ; Continue ; CALST2: PUSH HL ; Save sector number LD HL,(NFTRK) ; Get first track ADD HL,DE ; Add track number LD B,H ; Copy it to bc LD C,L CALL SETTRK ; BIOS call set track POP BC ; Restore sector number LD DE,(TRANS) ; Get translation table address CALL SECTRN ; BIOS call sector translation LD B,H ; Copy result to bc LD C,L JP SETSEC ; BIOS call set sector ; ; Get disk map block number from FCB ; ; Exit: HL = address FCB ; DE = disk map ; BC = offset in disk map ; GETDM: LD C,(IX+32) ; Get next record LD A,(NBLOCK) ; Get number of blocks LD B,A ; Save it ; GETDM0: SRL C ; Shift next record DJNZ GETDM0 ; Number of blocks times ; GETDM1: CPL ; Complement number of blocks ADD A,9 ; Add 9 LD B,A ; B=8-number of blocks LD A,(NEXTND) ; Get extend mask AND (IX+12) ; Mask with extend RRCA ; Rotate one right ; GETDM2: RLCA ; Rotate one left DJNZ GETDM2 ; 8-number of blocks times ; GETDM3: ADD A,C ; Add the two values to get entry FCB ; GETDM4: PUSH IX ; Get FCB address POP HL LD C,16 ; Add offset 16 to point to dm ADD HL,BC LD C,A ; Add entry FCB ADD HL,BC LD A,(MAXLEN+1) ; Test 8 bits/16 bits FCB entry OR A JR NZ,GETDM5 ; 16 bits => jump LD E,(HL) ; Get 8 bit value LD D,A ; Make MSB zero RET ; And exit ; GETDM5: ADD HL,BC ; Add twice (16 bit values) LD E,(HL) ; Get LSB INC HL ; Increment pointer LD D,(HL) ; Get MSB DEC HL ; Decrement pointer RET ; And exit ; ; Calculate sector number ; entry: de=block number from FCB ; CALSEC: LD HL,0 ; Clear MSB sector number LD A,(NBLOCK) ; Get loop counter LD B,A ; Save it in b ; CALSC0: SLA E ; Shift l,d,e RL D RL L DJNZ CALSC0 ; B times ; CALSC1: LD A,(NMASK) ; Get sector mask AND (IX+32) ; And with next record OR E ; Set up LSB sector number LD E,A RET ; And exit ; ; Calculate dirbuf entry point ; CALDIR: LD HL,(DIRBUF) ; Get start address dirbuf LD A,(SECPNT) ; Get sector pointer ADD A,L ; Add l=l+a LD L,A RET NC ; No carry exit INC H ; Increment h RET ; And exit ; ; Init file count ; SETFCT: LD HL,-1 ; Set up file count LD (FILCNT),HL ; Save it RET ; And exit ; ; Test file count ; ; Exit: Zero flag set and A = 0 if filcnt = 0ffffh ; TSTFCT: LD HL,(FILCNT) ; Test file count=0ffffh LD A,H ; Get MSB AND L ; And LSB INC A ; Test if result=0ffh RET ; And exit ; ; Set last file ; SETLF: CALL TSTLF ; Test last file RET C ; No then exit INC DE ; Increment last file LD (HL),D ; Save it in temp0 DEC HL LD (HL),E RET ; And exit ; ; Test last file ; TSTLF: LD HL,(TEMP0) ; Get pointer to last file LD DE,(FILCNT) ; Get file counter LD A,E ; Subtract filcnt-(temp0) SUB (HL) INC HL LD A,D SBC A,(HL) ; Carry means (temp0) > filcnt RET ; Exit ; ; Get next FCB from drive ; Entry: A = 0 check checksum ; A = 0ffh update checksum ; RDDIR: LD C,A ; Save checksum flag LD HL,(FILCNT) ; Get file counter INC HL ; Increment it LD (FILCNT),HL ; And save it LD DE,(NFILES) ; Get maximum number of files OR A ; Clear carry SBC HL,DE ; Test if last file ADD HL,DE JR Z,RDDIR0 ; No, jump JR NC,SETFCT ; Yes, set file count to 0ffffh ; RDDIR0: LD A,L ; Get file count LSB ADD A,A ; *32 ADD A,A ADD A,A ADD A,A ADD A,A AND 060H ; Mask it LD (SECPNT),A ; Save it for later use RET NZ ; Return if not first FCB sector PUSH BC ; Save checksum flag CALL STDIR ; Calculate sector/track directory CALL READDR ; Read sector directory POP BC ; Restore checksum flag ; ; Update/check checksum directory ; Entry C=0 check checksum, C=0ffh update checksum ; CHKDIR: LD HL,(NCHECK) ; Get number of checked records LD A,H OR L RET Z LD DE,(RECDIR) ; Get current record OR A ; Clear carry SBC HL,DE ; Test current record RET Z ; Exit if zero RET C ; Exit if greater then ncheck LD HL,(DIRBUF) ; Get dirbuf LD B,128 ; Set up counter XOR A ; Clear checksum ; CHKDR0: ADD A,(HL) ; Add checksum INC HL ; Increment pointer DJNZ CHKDR0 ; 128 times LD HL,(CSV) ; Get pointer checksum directory ADD HL,DE ; Add current record INC C ; Test checksum flag JR Z,CHKDR1 ; 0ffh=> update checksum CP (HL) ; Test checksum RET Z ; Exit if ok LD HL,(DIFF) ; Get disk changed vector CALL SDRVB ; Include drive bit LD (DIFF),HL ; Save disk changed bit JP SETFN ; Set # files to maximum ; CHKDR1: LD (HL),A ; Update checksum RET ; And exit ; ; Read sector from drive ; READR: CALL READ ; BIOS call read sector JR WRITE0 ; Test exit code ; ; Write sector on drive ; WRITER: CALL WRITE ; BIOS call write sector ; WRITE0: OR A ; Test exit code RET Z ; Exit if ok LD HL,(STRW) ; Point to data error routine LD (RETFLG),A ; Allow retry for read/write errors JP (HL) ; Display "Data error on d:" ; ; Read directory from drive ; READDR: CALL DMADIR ; Set up DMA directory CALL READR ; Read record JR STDMA ; Set up DMA user ; ; Write directory on drive ; WRITDR: LD C,0FFH ; Update checksum directory CALL CHKDIR CALL DMADIR ; Set up DMA directory LD C,1 ; Write directory flag CALL WRITER ; Write record JR STDMA ; Set up DMA user ; ; Set DMA address command ; CMND26: LD (DMA),DE ; Save DMA address ; STDMA: LD BC,(DMA) ; Get DMA address JR DMADR0 ; And do BIOS call ; ; Set DMA address directory ; DMADIR: LD BC,(DIRBUF) ; Get DMA address directory ; DMADR0: JP SETDMA ; BIOS call set DMA ; ; Get bit from allocation vector buffer ; ; Entry: DE = block number ; Exit: A = bit in LSB ; B = bitnumber in a ; HL = pointer in alv buffer ; GETBIT: LD A,E ; Get bit number AND 7 ; Mask it INC A ; Add 1 LD B,A ; Save it LD C,A ; Twice SRL D ; Get byte number RR E ; De=de/8 SRL D RR E SRL D RR E LD HL,(ALV) ; Get start address alv buffer ADD HL,DE ; Add byte number LD A,(HL) ; Get 8 bits ; GETBT0: RLCA ; Get correct bit DJNZ GETBT0 LD B,C ; Restore bit number RET ; And return to caller ; ; Set/reset bit in allocation vector buffer ; Entry DE = block number ; C = 0 reset bit, c=1 set bit ; SETBIT: PUSH BC ; Save set/reset bit CALL GETBIT ; Get bit AND 0FEH ; Mask it POP DE ; Get set/reset bit OR E ; Set/reset bit ; SETBT0: RRCA ; Rotate bit in correct position DJNZ SETBT0 LD (HL),A ; Save 8 bits RET ; And return to caller ; ; Fill bit buffer from FCB in dirbuf ; Entry: C = 0 reset bit ; C = 1 set bit ; FILLBB: CALL CALDIR ; Get directory entry LD DE,16 ; Get offset dm block ADD HL,DE ; Add offset LD B,E ; Get block counter ; FILLB0: LD E,(HL) ; Get LSB block number INC HL ; Increment pointer LD D,0 ; Reset MSB block number LD A,(MAXLEN+1) ; Test >256 blocks present OR A JR Z,FILLB1 ; No then jump DEC B ; Decrement block counter LD D,(HL) ; Get correct MSB INC HL ; Increment pointer ; FILLB1: LD A,D ; Test block number OR E JR Z,FILLB2 ; Zero then get next block PUSH HL ; Save pointer PUSH BC ; Save counter and set/reset bit LD HL,(MAXLEN) ; Get maximum lenght alv buffer OR A ; Reset carry SBC HL,DE ; Test de<=maxlen alv buffer CALL NC,SETBIT ; Yes then insert bit POP BC ; Get counter and set/reset bit POP HL ; Get pointer ; FILLB2: DJNZ FILLB0 ; Repeat for all dm entries RET ; And return to caller ; ; Set write protect disk ; CMND28: LD HL,(DSKRO) ; Get disk R/O vector CALL SDRVB ; Include drive bit LD (DSKRO),HL ; Save disk R/O bit ; SETFN: LD DE,(NFILES) ; Get maximum number of files-1 INC DE ; Increment it LD HL,(TEMP0) ; Get pointer to disk parameter block LD (HL),E ; And save number of files INC HL LD (HL),D RET ; And return to caller ; ; Check file R/O bit ; CHKFRO: CALL CALDIR ; Get directory entry LD DE,9 ; Offset to file R/O bit ADD HL,DE ; Add offset BIT 7,(HL) ; Test file R/O JR NZ,CHKFR2 ; Yes then error ; ; System files are R/O if referenced with wildcards: ; LD A,(SEARQU) ; Test if question mark used OR A ; Test question mark used RET Z ; No then don't test system file bit INC HL ; Increment to system file BIT 7,(HL) ; Test system file RET Z ; No system file then ok ; CHKFR2: LD HL,(SFILRO) ; Get pointer to file R/O message JP (HL) ; Display message ; ; Check drive read only ; CHKRO: LD HL,(DSKRO) ; Get drive R/O vector CALL SDRVB ; Set drive bit SBC HL,DE ; Test extra bit added RET NZ ; Yes then drive not R/O LD HL,(STRO) ; Get pointer to drive R/O message JP (HL) ; Display message ; ; Get free block from allocation vector buffer ; Entry: DE = old block number ; Exit: DE = new block number (0 if no free block) ; HL counts up ; DE counts down ; GETFRE: LD H,D ; Copy old block to hl LD L,E ; GETFR0: LD A,D ; Test down counter is zero OR E JR Z,GETFR1 ; Yes then jump DEC DE ; Decrememt down counter PUSH HL ; Save up/down counter PUSH DE CALL GETBIT ; Get bit from alv buffer RRA ; Test if zero JR NC,GETFR3 ; Yes then found empty block POP DE ; Get up/down counter POP HL ; GETFR1: LD BC,(MAXLEN) ; Get maximum alv lenght-1 in bc OR A ; Clear carry SBC HL,BC ; Test hl>=lenght alv-1 ADD HL,BC ; Restore hl (flags are not affected) JR NC,GETFR2 ; End buffer then jump INC HL ; Increment up counter PUSH DE ; Save down/up counter PUSH HL EX DE,HL ; Save up counter in de CALL GETBIT ; Get bit from alv buffer RRA ; Test if zero JR NC,GETFR3 ; Yes then found empty block POP HL ; Get down/up counter POP DE JR GETFR0 ; And test next block ; GETFR2: LD A,D ; Test if last block tested OR E JR NZ,GETFR0 ; No then test next block RET ; Exit (de=0) ; GETFR3: SCF ; Set block number used RLA ; Save bit CALL SETBT0 ; Put bit in alv buffer POP DE ; Get correct counter POP HL ; Restore stack pointer RET ; Exit (de=block number) ; ; Entry point to search for a file that is currently open ; SEAR0: LD A,15 ; Match first 15 bytes ; SEAR01: LD (SEARNB),A ; Save number of bytes LD A,(IX+13) ; Check if =FF, if was, use normal INC A ; Search routine JR Z,SR1 CALL HOME ; Force BIOS directory read LD L,(IX+13) ; Get sector of directory file was on LD H,0 ; *4 to satisify internal data base SLA L RL H SLA L RL H LD (FILCNT),HL ; Place in internal data base PUSH HL CALL STDIR ; Get sec-trk of directory entry CALL READDR ; Read it to memory POP HL DEC HL ; -1, will be +1 in readdr LD (FILCNT),HL JR SEAR1 ; ; Find file name only ; FINDFN: LD A,12 JR SEARCH ; ; Find file ; FINDF: LD A,15 ; Number of bytes to search for ; ; Search for file name ; Entry: A = number of bytes to search for ; SEARCH: LD (SEARNB),A ; Save number of bytes ; SR1: CALL SETFCT ; Initiate file counter CALL HOME ; Force BIOS directory read ; SEAR1: LD A,0FFH ; Set exit code to 0ffh (not found) LD (SEAREX),A LD (DCOPY),IX ; Copy FCB pointer to ram (search next) ; ; ..after disk change ; Search next file name ; SEARCN: XOR A ; Clear accu, check checksum dir. LD (SEARQU),A ; Clear question mark detected flag LD (SEARPU),A ; Clear public file flag CALL RDDIR ; Get FCB from directory CALL TSTFCT ; Test if past last entry JP Z,SEARC8 ; Yes then jump LD DE,(DCOPY) ; Get FCB pointer LD A,(DE) ; Get first byte CP 0E5H ; Test if searching empty directory JR Z,SEARC1 ; Yes then jump PUSH DE ; Save FCB pointer CALL TSTLF ; Test last file on this drive POP DE ; Restore FCB pointer JR NC,SEARC8 ; Yes then jump ; SEARC1: CALL CALDIR ; Get entry in directory LD A,(HL) ; Get first byte directory entry CP 021H ; Test time stamp JR Z,SEARCN ; Yes then get next directory entry LD A,(SEARNB) ; Get number of bytes to search for LD B,A ; Save it in counter XOR A ; Clear accu LD C,A ; Clear counter ; SEARC2: LD A,B ; Test if counter is zero OR A JR Z,SEARC9 ; Yes then jump LD A,(DE) ; Get byte from FCB XOR '?' ; Test if question mark AND 07FH ; Mask it (remove high bit) JR Z,SEARC6 ; Yes then jump LD A,C ; Get FCB counter OR A ; Test whether first byte JR NZ,SEARC3 ; No LD A,(FLAGS) ; Yes. get flag byte BIT 0,A ; Test public file enable JR Z,SEARC3 ; No INC HL ; Yes. get pointer to public bit INC HL BIT 7,(HL) ; Test public bit directory DEC HL ; Restore pointer DEC HL JR Z,SEARC3 ; No public file then jump LD A,(DE) ; Get first byte FCB CP 0E5H ; Test if searching empty directory JR Z,SEARC3 ; Yes then jump XOR (HL) ; Test FCB=directory entry AND 07FH ; Mask it JR Z,SEARC5 ; Yes then jump AND 0E0H ; Mask user number JR NZ,SEARC3 ; Not the same then jump DEC A ; A=0ffh LD (SEARPU),A ; Set public file found JR SEARC5 ; Jump found ; SEARC3: LD A,C ; Get FCB counter CP 13 ; Test if at user code JR Z,SEARC5 ; Yes then no test CP 12 ; Test if at extend number LD A,(DE) ; Get byte from FCB JR Z,SEARC7 ; Jump if extent number XOR (HL) ; Test byte FCB=byte directory entry AND 07FH ; Mask it ; SEARC4: JR NZ,SEARCN ; Not the same then get next entry ; SEARC5: INC DE ; Increment pointer FCB INC HL ; Increment pointer directory entry INC C ; Increment counter DEC B ; Decrement counter JR SEARC2 ; Test next byte ; SEARC6: DEC A ; Set question mark found flag LD (SEARQU),A JR SEARC5 ; Jump found ; SEARC7: PUSH BC ; Save counters XOR (HL) ; Test extends LD B,A ; Save it LD A,(NEXTND) ; Get extent mask CPL ; Complement it AND 01FH ; Mask it AND B ; Mask extents POP BC ; Restore counters JR SEARC4 ; And test result ; SEARC8: CALL SETFCT ; Error set file counter LD A,0FFH ; And set exit code LD (PEXIT),A RET ; Return to caller ; SEARC9: LD A,(SEARQU) ; Get question mark found flag LD B,A ; Save it LD A,(SEARPU) ; Get public file flag AND B ; Test if public file and question mark JR NZ,SEARC4 ; Yes then search for next entry CALL SETLF ; Update last file count (empty FCB) LD A,(FILCNT) ; Get file counter AND 3 ; Mask it LD (PEXIT),A ; And set exit code XOR A ; Clear exit code search LD (SEAREX),A RET ; And return to caller ; ; Delete file ; DELETE: CALL CHKRO ; Check disk R/O CALL FINDFN ; DEL0: CALL TSTFCT ; Test if file found RET Z ; Not then exit CALL CHKFRO ; Check file R/O CALL CALDIR ; Get entry point directory LD (HL),0E5H ; Remove file LD C,0 ; Remove bits alv buffer CALL FILLBB CALL WRFCB ; Write directory buffer on disk CALL SEARCN ; Search next entry JR DEL0 ; And test it ; ; Rename file ; RENAM: CALL CHKRO ; Check disk R/O CALL FINDFN ; RENAM0: CALL TSTFCT ; Test if file found RET Z ; Not then exit CALL CHKFRO ; Check file R/O PUSH IX ; Save FCB entry POP HL ; Get it in hl LD DE,16 ; Offset to new name ADD HL,DE ; Add offset EX DE,HL ; Copy hl=>de CALL CALDIR ; Get directory entry LD B,11 ; Set up loop counter ; RENAM1: INC HL ; Increment directory pointer INC DE ; Increment FCB pointer LD A,(DE) ; Get character from FCB AND 07FH ; Mask it CP '?' ; Test if question mark JR Z,RENAM2 ; Yes then do not change char. on disk LD C,A ; Save it in c LD A,(HL) ; Get character from directory AND 080H ; Mask status bit OR C ; Or with new character LD (HL),A ; Save in directory ; RENAM2: DJNZ RENAM1 ; Loop until done CALL WRFCB ; And write directory on disk CALL SEARCN ; Search next file JR RENAM0 ; And test it ; ; Change status file ; CSTAT: CALL CHKRO ; Check disk R/O CALL FINDFN ; CSTAT0: CALL TSTFCT ; Test if file found RET Z ; Not then exit PUSH IX ; Save FCB entry POP DE ; Get it in hl CALL CALDIR ; Get directory entry LD B,11 ; Set up loop counter ; CSTAT1: INC HL ; Increment directory pointer INC DE ; Increment FCB pointer LD A,(DE) ; Get status bit from FCB AND 080H ; Mask it LD C,A ; Save it in c LD A,(HL) ; Get character from directory AND 07FH ; Mask it OR C ; Or with new status bit LD (HL),A ; Save in directory DJNZ CSTAT1 ; Loop until done CALL WRFCB ; And write directory to disk CALL SEARCN ; Search next file JR CSTAT0 ; And test it ; ; Compute file size ; FILSZ: LD BC,0 ; Reset file size lenght LD D,C CALL LDRRC ; Save it in FCB+33,34,35 CALL FINDFN ; FILSZ0: CALL TSTFCT ; Test if file found RET Z ; Not then exit CALL CALDIR ; Get directory entry EX DE,HL ; Copy to de LD HL,15 ; Offset to next record CALL CALRRC ; Calculate random record count LD A,D ; Test LSB < (ix+33) SUB (IX+33) LD A,C ; Test isb < (ix+34) SBC A,(IX+34) LD A,B ; Test MSB < (ix+35) SBC A,(IX+35) CALL NC,LDRRC ; Write new maximum CALL SEARCN ; Search next file JR FILSZ0 ; And test it ; ; Write FCB on disk ; WRFCB: CALL STDIR ; Calculate sector/track directory JP WRITDR ; Write directory on disk ; ; Calculate sector of file opened in FCB ; CMD15: CALL TSTFCT ; Look for ffff JR Z,CMD151 ; Yes, save ff, can't do fast lookup SRL H ; HL=(filcnt)/4-1 RR L SRL H RR L DEC L CMD151: LD (IX+13),L ; Save in FCB+13 for use in SEAR0 RET ; ; Open file ; CMND15: CALL SELDRV ; Select drive from FCB LD (IX+14),0 ; Clear FCB+14 ; OPENF: CALL FINDF ; Find file CALL TSTFCT ; Test file found RET Z ; No then exit ; OPENF0: LD A,(IX+12) ; Get extent number from FCB PUSH AF ; Save it CALL CALDIR ; Get directory entry PUSH HL ; Save it LD E,8 ; Set access date/time CALL STIME ; Zero flag set if stamps present POP HL ; Get directory entry PUSH IX ; Save FCB entry POP DE ; Get in in de LD BC,32 ; Number of bytes to move LDIR ; Move directory to FCB CALL Z,WRFCB ; Write to disk if stamps present SET 7,(IX+14) ; Set FCB/file not modified LD B,(IX+12) ; Get extent number LD C,(IX+15) ; Get next record number POP AF ; Get old extent number LD (IX+12),A ; Save it CP B ; Compare old and new extent number JR Z,OPENF1 ; Same then jump LD C,0 ; Set next record count to 0 JR NC,OPENF1 ; Old extent >= new extent then jump LD C,80H ; Set next record count to maximum ; OPENF1: LD (IX+15),C ; Save next record count CALL CMD15 ; Fill in FCB+13,fast lookup RET ; And return to caller ; ; Close file command ; CMND16: CALL SELDRV ; Select drive from FCB ; ; Close file ; CLOSE: BIT 7,(IX+14) ; Test FCB/file modified RET NZ ; Not then no close required CALL CHKRO ; Test disk R/O CALL SEAR0 ; Use fast search CALL TSTFCT ; Test file present RET Z ; No then exit CALL CHKFRO ; Check file R/O CALL CALDIR ; Get directory entry LD BC,16 ; Offset to dm block ADD HL,BC ; Add offset EX DE,HL ; Save hl in de PUSH IX ; Save FCB pointer POP HL ; Get it in hl ADD HL,BC ; Add offset LD A,(MAXLEN+1) ; Test number of block >= 256 OR A JR Z,CLOSE0 ; No then jump DEC B ; Set flag ; CLOSE0: CALL COPYDM ; Copy and test blocks EX DE,HL ; Exchange copy direction CALL COPYDM ; Copy and test blocks EX DE,HL ; Exchange copy direction JR NZ,CLOSE4 ; Block not the same then error INC HL ; Increment pointer FCB INC DE ; Increment pointer directory BIT 0,B ; Test number of block >= 256 JR Z,CLOSE1 ; No then jump INC HL ; Increment pointer FCB INC DE ; Increment pointer directory DEC C ; Decrement counter ; CLOSE1: DEC C ; Decrement counter JR NZ,CLOSE0 ; Not ready then jump LD HL,-20 ; Add -20 to get extent number ADD HL,DE ; HL contains pointer to extent number LD A,(IX+12) ; Get extent number FCB CP (HL) ; Compare with extent number directory JR C,CLOSE3 ; FCB < directory then jump LD (HL),A ; Save extent number in directory INC HL ; Get pointer to next record INC HL INC HL LD A,(IX+15) ; Get next record FCB ; CLOSE2: LD (HL),A ; Save next record in directory ; CLOSE3: LD E,4 ; Set last update date/time CALL STIME ; Update time CALL CALDIR ; Get directory entry LD BC,11 ; Point to archive byte ADD HL,BC RES 7,(HL) ; Reset archive bit RES 7,(IX+11) ; Reset bit in FCB INC HL INC HL PUSH HL CALL CMD15 ; Fill in FCB+13 for next fast lookup LD A,L POP HL LD (HL),A JP WRFCB ; Write FCB on disk ; CLOSE4: LD A,0FFH ; Flag error LD (PEXIT),A RET ; And return to caller ; ; Copy and test disk map ; ; Entry: HL = pointer to first FCB ; DE = pointer to second FCB ; B = 000h if less then 256 blocks ; 0ffh if more or equal to 256 blocks ; Exit: Z blocks are the same ; NZ blocks are not the same ; COPYDM: LD A,(HL) ; Get byte first FCB BIT 0,B ; Test number of blocks >=256 JR Z,COPYD0 ; No then jump INC HL ; Increment pointer OR (HL) ; Test byte =0 DEC HL ; Decrement pointer ; COPYD0: OR A ; Test block number is zero JR NZ,COPYD1 ; No then compare blocks LD A,(DE) ; Copy block from other FCB in empty location LD (HL),A BIT 0,B ; Test number of blocks >=256 RET Z ; No then exit INC HL ; Increment to MSB block numbers INC DE LD A,(DE) ; Copy block from other FCB in empty location LD (HL),A JR COPYD2 ; Jump trick to save space ; COPYD1: LD A,(DE) ; Get block number first FCB SUB (HL) ; Test if the same RET NZ ; Not then return OR B ; Test if >=256 blocks RET Z ; No then return INC HL ; Increment to MSB block numbers INC DE ; COPYD2: LD A,(DE) ; Get block number first FCB SUB (HL) ; Test if the same DEC HL ; Decrement block FCB pointers DEC DE RET ; And exit to caller ; ; Entry point to use fast lookup to 'MAKE' next FCB entry for open file ; MAKER: CALL MAK0 PUSH AF LD A,1 CALL SEAR01 JR MAK1 ; ; Common code for MAKE/MAKER ; MAK0: CALL CHKRO ; Check drive R/O LD A,(IX+0) ; Get first byte FCB LD (IX+0),0E5H ; Set first byte to empty file RET ; ; Make file command ; CMND22: CALL SELDRV ; Select drive from FCB LD (IX+14),0 ; Clear FCB+14 ; ; Make file ; MAKE: CALL MAK0 PUSH AF ; Save it LD A,1 ; Search for 1 byte CALL SEARCH ; Search empty file ; MAK1: POP AF ; Get first byte FCB LD (IX+0),A ; Restore it CALL TSTFCT ; Test empty file found RET Z ; No then return error XOR A ; Clear FCB+13 PUSH IX ; Save FCB pointer POP HL ; Get it back in hl LD DE,15 ; Prepare offset ADD HL,DE ; Add it LD B,17 ; Set loop counter ; MAKE0: LD (HL),A ; Clear FCB+15 up to FCB+31 INC HL ; Increment pointer DJNZ MAKE0 ; And clear all bytes LD E,2 ; Set creation date CALL STIME ; Update time in directory LD E,4 ; Set last update date/time CALL STIME ; Update time in directory LD E,8 ; Set access date/time CALL STIME RES 7,(IX+11) ; Reset archive bit if present CALL CALDIR ; Get directory entry PUSH HL ; Save directory pointer PUSH IX ; Put FCB pointer on stack CALL CMD15 ; Fill in FCB+13 POP DE ; FCB pointer to DE POP HL ; Directory entry pointer EX DE,HL ; Exchange FCB and directory entry LD BC,32 ; Number of bytes to move LDIR ; Move bytes CALL WRFCB ; Write FCB on disk SET 7,(IX+14) ; Set FCB/file not modified RET ; And return to caller ; ; Open next extent ; OPENEX: BIT 7,(IX+14) ; Test if FCB/file modified (write) JR NZ,OPENX2 ; Not then jump CALL CLOSE ; Close current FCB LD A,(PEXIT) ; Get exit code INC A ; Test if error RET Z ; Yes then exit CALL CALNEX ; Calculate next extent JR C,OPENX3 ; Error then jump JR NZ,OPENX5 ; FCB present from close then jump ; OPENX0: CALL SEAR0 ; Use fast lookup to find next extent ; OPENX1: CALL TSTFCT ; Test if file found JR NZ,OPENX5 ; Yes then jump LD A,(RDWR) ; Test read/write flag OR A ; Test if read JR Z,OPENX3 ; Yes then error CALL MAKER ; Make new extent if write CALL TSTFCT ; Test if succesfull JR NZ,OPENX6 ; Yes then exit JR OPENX3 ; No then error ; OPENX2: CALL CALNEX ; Calculate next extent JR NC,OPENX0 ; OPENX3: SET 7,(IX+14) ; Set FCB/file not modified LD A,0FFH ; Set exit code ; OPENX4: LD (PEXIT),A RET ; And return to caller ; OPENX5: CALL OPENF0 ; Open file ; OPENX6: XOR A ; And clear exit code JR OPENX4 ; Use same routine ; ; Calculate next extent ; ; Exit: C overflow detected ; Z search next extent ; NZ next extent present (close) ; CALNEX: LD B,(IX+12) ; Get extent number LD C,(IX+14) ; Get FCB+14 BIT 6,C ; Test error bit random record SCF ; Set error flag RET NZ ; Non zero then error exit INC B ; Increment extent number LD A,B ; Get extent number AND 01FH ; Mask it LD B,A ; Save it in b JR NZ,CALNX0 ; Non zero then jump INC C ; Increment FCB+14 LD A,C ; Get it in a AND 03FH ; Mask it LD C,A ; Save it in c SCF ; Set error flag RET Z ; And return if file overflow XOR A ; Clear zero flag (not same extent) JR CALNX1 ; And save extent number and FCB+14 ; CALNX0: LD A,(NEXTND) ; Get next extent mask AND B ; Test if same extent (close) ; CALNX1: LD (IX+12),B ; Save extent number LD (IX+14),C ; Save FCB+14 RET ; And return to caller ; ; Read random record command ; CMND33: CALL SELDRV ; Select drive from FCB ; ; Read random sector ; RDRAN: XOR A ; Set read/write flag CALL LDFCB ; Load random record in FCB JR Z,READS ; No error then read sector RET ; Return error ; ; Read sequential ; CMND20: CALL SELDRV ; Select drive from FCB ; ; Read sector ; READS: XOR A ; Set read/write flag LD (RDWR),A ; Save it LD A,(IX+32) ; Get record counter CP 080H ; Test if last record this extent JR NC,READS1 ; Yes then open next extent CP (IX+15) ; Test if greater then current record JR C,READS2 ; No then get record ; READS0: LD A,1 ; Set end of file flag LD (PEXIT),A ; Save it RET ; And return to caller ; READS1: CALL OPENEX ; To open next extent LD A,(PEXIT) ; Get exit code OR A JR NZ,READS0 ; Yes then end of file LD (IX+32),0 ; Clear record counter ; READS2: CALL GETDM ; Get block number from dm in FCB LD A,D ; Test block number = 0 OR E JR Z,READS0 ; Yes then end file CALL CALSEC ; Calculate sector number (128 bytes) CALL CALST ; Calculate sector/track number CALL READR ; Read data LD A,(FUNCT) ; Get function number CP 20 ; Test if read sequential RET NZ ; No then return INC (IX+32) ; Increment next record counter RET ; And return to caller ; ; Write random record commands ; CMND34: DS 0 ; CMND40: CALL SELDRV ; Select drive from FCB ; ; Write random sector ; WRRAN: LD A,0FFH ; Set read/write flag CALL LDFCB ; Load FCB from random record JR Z,WRITES ; No error then write record RET ; Return error ; ; Write sequential ; CMND21: CALL SELDRV ; Select drive from FCB ; ; Write sector ; WRITES: LD A,0FFH ; Set read/write flag LD (RDWR),A ; And save it CALL CHKRO ; Check disk R/O BIT 7,(IX+9) ; Test if file R/O JP NZ,CHKFR2 ; Yes then file R/O message ; ; Check for changed disk. ; If disk changed: ; If file modified, abort. ; Else reset disk and disk changed bit. ; ; ; Test disk changed ; LD HL,(DIFF) ; Get drive changed vector CALL SDRVB ; Set current drive bit SBC HL,DE ; Test extra bit added JR NZ,WRITSA ; Bit added, so disk not changed ; ; Test file modified ; BIT 7,(IX+14) ; File modified? JP Z,CHGERR ; Yes, abort and warm boot ; ; Reset disk and disk changed bit. ; HL = 0 from SBC, DE = (diff) from SDRVB above ; PUSH DE ; Save (diff) CALL SDRVB ; Set current bit only in HL POP DE ; Get (diff) PUSH HL ; Save current drive bit for reset LD A,D XOR H LD D,A ; Mask current bit in DE LD A,E XOR L LD E,A LD (DIFF),DE ; Reset disk changed bit in (diff) POP DE ; Get current bit for disk reset CALL CMND37 ; No, reset drive: LD A,(DEFDRV) ; Get drive CALL SELDK ; And log it in again ; WRITSA: LD A,(IX+32) ; Get record count CP 080H ; Test if end this extent JR C,WRITS0 ; Yes then open next extent CALL OPENEX ; Open next extent LD A,(PEXIT) ; Get error code OR A JP NZ,WRITS9 ; Error then directory full error LD (IX+32),0 ; Clear record counter ; WRITS0: CALL GETDM ; Get block number from FCB LD A,D ; Test if block number = 0 OR E JR NZ,WRITS5 ; No then write sector PUSH HL ; Save pointer to block number LD A,C ; Test first block number in extent OR A JR Z,WRITS1 ; Yes then jump DEC A ; Decrement pointer to block number CALL GETDM4 ; Get previous blocknumber ; WRITS1: CALL GETFRE ; Get nearest free block POP HL ; Get pointer to block number LD A,D ; Test if blocknumber = 0 OR E JR Z,WRITS8 ; Yes then disk full error RES 7,(IX+14) ; Reset FCB/file modified LD (HL),E ; Save blocknumber LD A,(MAXLEN+1) ; Get number of blocks OR A ; Test if <256 JR Z,WRITS2 ; Yes then jump INC HL ; Increment to MSB block number LD (HL),D ; Save MSB block number ; WRITS2: LD C,2 ; Set write new block flag LD A,(NMASK) ; Get sector mask AND (IX+32) ; Mask with record counter JR Z,WRITSX ; Zero then ok (at start new record) LD C,0 ; Else clear new block flag ; WRITSX: LD A,(FUNCT) ; Get function number SUB 40 ; Test if write rr with zero fill JR NZ,WRITS6 ; No then jump PUSH DE ; Save blocknumber LD HL,(DIRBUF) ; Use directory buffer for zero fill LD B,128 ; 128 bytes to clear ; WRITS3: LD (HL),A ; Clear directory buffer INC HL ; Increment pointer DJNZ WRITS3 ; Clear all bytes CALL CALSEC ; Calculate sector number (128 bytes) LD A,(NMASK) ; Get sector mask LD B,A ; Copy it INC B ; Increment it to get number of writes CPL ; Complement sector mask AND E ; Mask sector number LD E,A ; And save it LD C,2 ; Set write new block flag ; WRITS4: PUSH HL ; Save registers PUSH DE PUSH BC CALL CALST ; Calculate sector/track CALL DMADIR ; Set DMA directory buffer POP BC ; Get write new block flag PUSH BC ; Save it again CALL WRITER ; Write record on disk POP BC ; Restore registers POP DE POP HL LD C,0 ; Clear write new block flag INC E ; Increment sector number DJNZ WRITS4 ; Write all blocks CALL STDMA ; Set user DMA address POP DE ; Get block number ; WRITS5: LD C,0 ; Clear write new block flag ; WRITS6: RES 7,(IX+14) ; Reset FCB/file modified flag PUSH BC ; Save it CALL CALSEC ; Calculate sector number (128 bytes) CALL CALST ; Calculate sector/track POP BC ; Get write new block flag CALL WRITER ; Write record on disk LD A,(IX+32) ; Get record counter CP (IX+15) ; Compare with next record JR C,WRITS7 ; If less then jump INC A ; Increment record count LD (IX+15),A ; Save it on next record position RES 7,(IX+14) ; Reset FCB/file modified flag ; WRITS7: LD A,(FUNCT) ; Get function number CP 21 ; Test write sequential RET NZ ; Not then return INC (IX+32) ; Increment record count RET ; And return to caller ; WRITS8: LD A,2 ; Set disk full error LD (PEXIT),A RET ; And return to caller ; WRITS9: LD A,1 ; Set directory full flag LD (PEXIT),A RET ; And return to caller ; ; Load FCB for random read/write ; ; Exit: Z no error ; NZ error occured ; LDFCB: LD (RDWR),A ; Save read/write flag LD A,(IX+33) ; Get first byte random record LD D,A ; Save it in d RES 7,D ; Reset MSB to get next record RLA ; Shift MSB in carry LD A,(IX+34) ; Load next byte random record RLA ; Shift carry PUSH AF ; Save it AND 01FH ; Mask next extent LD C,A ; Save it in c POP AF ; Get byte RLA ; Shift 4 times RLA RLA RLA AND 0FH ; Mask it LD B,A ; Save FCB+14 LD A,(IX+35) ; Get next byte random record LD E,6 ; Set random record to large flag CP 4 ; Test random record to large JR NC,LDFCB6 ; Yes then error RLCA ; Shift 4 times RLCA RLCA RLCA ADD A,B ; Add byte LD B,A ; Save FCB+14 in b LD (IX+32),D ; Set next record count LD D,(IX+14) ; Get FCB+14 BIT 6,D ; Test error random record JR NZ,LDFCB1 ; Yes then jump LD A,C ; Get new extent number CP (IX+12) ; Compare with FCB JR NZ,LDFCB1 ; Not equal then open next extent LD A,B ; Get new FCB+14 XOR (IX+14) ; Compare with FCB+14 AND 03FH ; Mask it JR Z,LDFCB4 ; Equal then return ; LDFCB1: BIT 7,D ; Test FCB modified (write) JR NZ,LDFCB2 ; No then jump PUSH DE ; Save registers PUSH BC CALL CLOSE ; Close extent POP BC ; Restore registers POP DE LD E,3 ; Set close error LD A,(PEXIT) ; Get exit code INC A JR Z,LDFCB5 ; Error then exit ; LDFCB2: LD (IX+12),C ; Save new extent number LD (IX+14),B ; Save new FCB+14 CALL FINDF ; Open file old way because may not ; ; Have valid FCB+13 for fast lookup LD A,(PEXIT) ; Get error code INC A JR NZ,LDFCB3 ; No error then exit LD A,(RDWR) ; Get read/write flag LD E,4 ; Set read empty record INC A JR NZ,LDFCB5 ; Read then error CALL MAKER ; Make new FCB using fast lookup LD E,5 ; Set make error LD A,(PEXIT) ; Get error code INC A JR Z,LDFCB5 ; Error then exit JR LDFCB4 ; No error exit (zero set) ; LDFCB3: CALL OPENF0 ; Open file ; LDFCB4: XOR A ; Set zero flag and clear error code LD (PEXIT),A RET ; And return to caller ; LDFCB5: LD (IX+14),0C0H ; Set random record error ; LDFCB6: LD A,E ; Get error code LD (PEXIT),A ; And save it SET 7,(IX+14) ; Set FCB/file not modified OR A ; Clear zero flag RET ; And return to caller ; ; Calculate random record ; Entry: HL = offset in FCB ; DE = FCB pointer ; Exit: D = LSB random record ; C = ISB random record ; B = MSB random record ; CALRRC: ADD HL,DE ; Pointer to FCB+15 or FCB+32 LD A,(HL) ; Get byte LD HL,12 ; Offset to extent number ADD HL,DE ; Get pointer to extent byte LD D,A ; Save first byte LD A,(HL) ; Get extent byte AND 01FH ; Mask it RL D ; Shift MSB in carry ADC A,0 ; Add carry RRA ; Shift 1 time (16 bits) RR D LD C,A ; Save isb INC HL ; Increment to FCB+14 INC HL LD A,(HL) ; Get FCB+14 RRCA ; Shift 4 times RRCA RRCA RRCA PUSH AF ; Save it AND 03H ; Mask MSB LD B,A ; Save it POP AF ; Get LSB AND 0F0H ; Mask it ADD A,C ; Add with isb LD C,A ; Save isb RET NC ; No carry then return INC B ; Increment MSB RET ; And return to caller ; ; END Z80DDISK.Z80