e block size byte out ORA A ;is it zero JZ CLOSF4 ;if so blocks > 1024 so jump past ; ;small blocks ; MOV A,M ;pull the byte out ORA A ;test for zero LDAX D ;get the (DE) out JNZ CLOSF2 ;if not zero jump over MOV M,A ;otherwise put A into place CLOSF2: ORA A ;test the byte again JNZ CLOSF3 ;if not zero jump past MOV A,M ;otherwise pull in the byte STAX D ;stuff it back at (DE) CLOSF3: CMP M ;are they the same JNZ CLOSF7 ;if not jump JMP CLOSF5 ;otherwise skip over ; ;big blocks ; CLOSF4: CALL CHKCPY ;check and increment XCHG ;exchange again CALL CHKCPY ;check again for next byte XCHG ;exchange back - ready to continue LDAX D ;get the new byte from (DE) CMP M ;does it match (HL) JNZ CLOSF7 ;if not over we go INX D ;bump pointer INX H ; data LDAX D ;get next byte CMP M ;compare it as well JNZ CLOSF7 ;again if no match jump DCR C ;decrement the count CLOSF5: INX D ;increment the INX H ; pointers DCR C ;decrement the count JNZ CLOSF1 ;if not done spinn around again LXI B,-20 ;point back DAD B ; 20 bytes XCHG ;swap pointers DAD B ;and back this one up as well LDAX D ;pull in the byte at (DE) CMP M ;test against (HL) JC CLOSF6 ;if (HL)>(DE) jump MOV M,A ;if not put A into (HL) LXI B,3 ;get a 3 DAD B ;point down 3 XCHG ;swap pointers again DAD B ;down three also MOV A,M ;get the byte at (HL) STAX D ;stuff it in at (DE) CLOSF6: MVI A,0FFH ;get the flag data STA RWFLG1 ;set flag to say reading JMP SETD1 ;write out the directory block and return ; CLOSF7: LXI H,ODATA ;point to output data byte DCR M ;decrement it 1 RET ;and go back ; ;********************************************************************** ;make a new directory entry for a new file ; MAKE: CALL ROCHK ; is the disk read only LHLD FCB ;nope - so get the FCB address PUSH H ;and save it on the stack LXI H,TINFO ;point to the TINFO area SHLD FCB ;save this as the FCB address MVI C,01H ;set to look at only the ET byte in the FCB CALL SEARCH ;search for the new file name CALL CHKCNT ;was it there POP H ;get the old FCB back SHLD FCB ;restore it right RZ ;return if it was there XCHG ;save FCB in DE LXI H,15 ;get offset to record count DAD D ;and set the pointer there MVI C,17 ;get set to spin through 16 bytes XRA A ;get a zero ready MAK1: MOV M,A ;and move zero INX H ; into DCR C ; all JNZ MAK1 ; the group bytes LXI H,13 ;get the offset to the S1 byte DAD D ;and point to it MOV M,A ;zero this as well CALL CHKINC ;see if we have more to do CALL MOVDIR ;copy the directory in place JMP SETS28 ;set bit 7 of S2 and return ; ;********************************************************************** ;routine sets up for the next extent access for either read or write ; NEXTEX: XRA A ;get a zero STA RWFLG1 ;say we are writing CALL CLOSEF ;close the file CALL CHKCNT ;did it exist RZ ;return if not LHLD FCB ;get the FCB address LXI B,12 ;set to point to extent byte DAD B ;now it does MOV A,M ;pull the thing in INR A ;bump by one ANI 1FH ;strip off bit 7 MOV M,A ;and put it back JZ NEXTE1 ;if it was zero jump over MOV B,A ;otherwise save it in B LDA EXTMSK ;get the extent mask ANA B ;and use it LXI H,RWFLG1 ;and point to the flag ANA M ;and in this byte as well JZ NEXTE2 ;if zero jump past JMP NEXTE3 ;otherwise off to ; NEXTE1: LXI B,2 ;ready to bump 2 more DAD B ;add it in INR M ;increment this byte MOV A,M ;then pull it in ANI 0FH ;strip off the high 4 bits JZ NEXTE5 ;if zero jump NEXTE2: MVI C,0FH ;look through S2 byte in FCB CALL SEARCH ;look for the indicated file CALL CHKCNT ;see if it was there JNZ NEXTE3 ;if so open the next extent LDA RWFLG2 ;get the read/write flag INR A ;add one JZ NEXTE5 ;if it was FF then return CALL MAKE ;make a new file directory entry CALL CHKCNT ;was it ok JZ NEXTE5 ;if not set up exit routine JMP NEXTE4 ;otherwise set up extent pointers and return ; NEXTE3: CALL OPEN1 ;go open the next extent NEXTE4: CALL FIXEXT ;set the pointers up XRA A ;zero A for the return JMP GOBAK ;and go back ; NEXTE5: CALL JR1 ;set to return with problems JMP SETS28 ;set bit 7 of S2 to say so ; ;********************************************************************** ;routine to read the disk ; DSKRED: MVI A,01H ;get a ! STA DCODE ;save it for the disk code byte RRERR: MVI A,0FFH ;get a read flag STA RWFLG2 ;set it in for the control CALL FIXEXT ;go fix the extent LDA ESCNT2 ;get the extent low byte LXI H,RECCNT ;point to the record count CMP M ;are they the same? JC DSKR1 ;if record count was bigger, jump over CPI 80H ;was the count 80 hex? JNZ DERR ;if not jump out with an error CALL NEXTEX ;go get the next extent XRA A ;set a=0 STA ESCNT2 ;save this as the new extent low byte LDA ODATA ;get the output data ORA A ;set the flags JNZ DERR ;if it was not zero exit with error DSKR1: CALL SECGRP ;otherwise group from the sector count CALL TSTGRP ;see if it is ok JZ DERR ;if not go back CALL COMSEC ;if co compute the right sector CALL GETD1 ;get the directory set right CALL RDSEC ;read the sector JMP FIXREC ;fix up the record and return ; DERR: JMP JR1 ;set the error exit and return ; ;********************************************************************** ;routine to write the disk ; DSKWRT: MVI A,01H ;set the disk STA DCODE ; code up RWERR: MVI A,0 ;set the read write flag for write STA RWFLG2 ;and save it for later CALL ROCHK ;see if the drive is protected LHLD FCB ;get the FCB address CALL CHKFR1 ;see if the file is read only CALL FIXEXT ;fix up the extent LDA ESCNT2 ;and get the low extent byte CPI 80H ;is it greater that 80h JNC JR1 ;if so exit with errors CALL SECGRP ;compute the right group CALL TSTGRP ;see if it is ok MVI C,0 ;get a zero JNZ DSKW05 ;if ok jump over CALL COMBLK ;c in the data in B MOV B,A ;and save back into B LXI H,14 ;set the pointer DAD D ; to the S2 byte MOV A,M ;pull it into A ADD A ;and slide ADD A ; it ADD A ; left ADD A ; four bits PUSH PSW ;save the result on the stack ADD B ;add in B, if s2>=16 and B=17 carry is set MOV B,A ;save the result into B PUSH PSW ;save the flags and A POP H ;pull flags into L MOV A,L ;put then into A POP H ;recover the second flag set into L ORA L ;or the two together ANI 01H ;and strip off all but carry RET ;then return ; ;********************************************************************** ;routine gets the record count from the last extent of a random file ; GETSIZ: MVI C,0CH ;look at file name ant extent CALL SEARCH ;go locate the file LHLD FCB ;point to the FCB LXI D,33 ;get the offset to the DAD D ; R0 byte PUSH H ;save the address on the stack MOV M,D ;put the 0 into position INX H ;point to R1 MOV M,D ;0 goes there as well INX H ;point to R2 - overflow byte MOV M,D ;once more with zero GSLOOP: CALL CHKCNT ;check the counter JZ GSEXIT ;if zero we exit now CALL PNTDIR ;otherwise point to the directory LXI D,15 ;get the offset to extent byte CALL COMREC ;check extent overflow POP H ;recover the R0 address PUSH H ;save it again MOV E,A ;save the directory code in E MOV A,C ;and put the R0 byte into A SUB M ;subtract the byte from the FCB INX H ;point to the R1 byte MOV A,B ;put B in A SBB M ;subtract with borrow from here as well INX H ;once more with the overflow byte MOV A,E ;E into A SBB M ;subtract the overflow JC GETSZ1 ;if carry jump over - file is too big MOV M,E ;put R2 into place DCX H ;point back MOV M,B ;set R1 in as well DCX H ;back again MOV M,C ;and set R0 into place GETSZ1: CALL SERCHN ;go look for next extent JMP GSLOOP ;loop until we hit the end ; GSEXIT: POP H ;recover the address of random file size RET ;and return with it ; ;********************************************************************** ; BDOS function 36 - set random record with data set by RANFIL ; SETRND: LHLD FCB ;get the FCB address LXI D,32 ;and the offset to the record count CALL COMREC ;get the file pointers into A b and c LXI H,33 ;offset to the R0 byte DAD D ;point to it MOV M,C ;put the byte in C into R0 INX H ;point to R1 MOV M,B ;put B in there INX H ;point to overflow byte MOV M,A ;stuff A there RET ;and return ; ;********************************************************************** ;routine to log the selected disk ; LOGDSK: LHLD DLOG ;point to the login vector LDA CURDSK ;get the current disk byte MOV C,A ;and put it into C CALL SPINHL ;spin the selected disk bit into place PUSH H ;save this vector on the stack XCHG ;careful study says this is useless CALL DISKID ;go get the disk information set POP H ;recover the vector CZ PTSERR ;if trouble say so and quit MOV A,L ;otherwise put the low byte into A RAR ;slide it right bit 0 into carry RC ;return if bit was set - we already got it LHLD DLOG ;otherwise point to the login vector MOV C,L ;put the vector MOV B,H ; into BC CALL SETDBT ;set the disk bit using setro SHLD DLOG ;save the vector into place again JMP GETAL ;get the new allocation vector ; ;********************************************************************** ; BDOS function 14: select disk ; enter with selected disk in IDATA ; LOGIN: LDA IDATA ;get the disk to log LXI H,CURDSK ;point to the current disk storage CMP M ;are they the same RZ ;return if so MOV M,A ;otherwise make this current JMP LOGDSK ;and log it in then return ; ;********************************************************************** ;routine to select disk indicated in FCB drive code ; RSELCT: MVI A,0FFH ;get an FF STA OUT1 ;save it to force disk reset on exit LHLD FCB ;point to the FCB MOV A,M ;pull in the new drive code ANI 1FH ;strip off the user bits DCR A ;decrement to make it right STA IDATA ;save it for the login routines CPI 1EH ;is it too big JNC XIT ;if so go back LDA CURDSK ;get the current disk out STA OUTDSK ;save it for the return MOV A,M ;pull in the new code again STA OLDDSK ;save the value as the olddisk ANI 0E0H ;strip off the drive bits MOV M,A ;put the user bits back CALL LOGIN ;go log the new disk XIT: LDA USRCOD ;get the user code out LHLD FCB ;point back to the FCB ORA M ;set in the new user code bits MOV M,A ;and put the result back RET ;then return ; ;********************************************************************** ;BDOS function 12: routine returns CP/M version in A ; GETVER: MVI A,22H ;say this is CP/M version 2.2 JMP GOBAK ;and return ; ;********************************************************************** ; BDOS function 13: routine to reset the system disk ; RESET: LXI H,0 ;get ready to reset the vectors SHLD ROVEC ;set both read only bits SHLD DLOG ; and login bits to off XRA A ;zero A STA CURDSK ; and make it the current disk LXI H,TBUFF ;Set DMA addr to 80H SHLD DMAADR ;save this as the new DMA value CALL SETDMA ;make it so for real JMP LOGDSK ;go log in drive A and return ; ;********************************************************************** ; BDOS function 15: open file ; enter with FCB address in HL and INFO ; exit with directory code in A ; OPEN: CALL ZS2 ;set S2 to zero for the new file CALL RSELCT ;select the right disk JMP OPENF ;then open the file in the FCB ; ;********************************************************************** ; BDOS function 16: close the selected file ; enter with FCB address ; exit with directory code in A ; CLOSE: CALL RSELCT ;select the right drive JMP CLOSEF ;and finish off the close operation ; ;********************************************************************** ; BDOS function 17: search for first file entry ; enter with FCB address ; exit with directory code in A ; SEAR1: MVI C,0 ;set the search code into C XCHG ;swap FCB into DE MOV A,M ;pull in the file name byte CPI '?' ;is it a wild card JZ SRF2 ;if so jump over CALL GETEX ;otherwise get the extent MOV A,M ;pull in the byte here CPI '?' ;is it a wild card CNZ ZS2 ;if not set S2 to 0 CALL RSELCT ;select the right drive MVI C,0FH ;look at name thru S2 byte SRF2: CALL SEARCH ;search for the file JMP MOVSEC ;jump to move the sector and return ; ;********************************************************************** ;BDOS function 18: search for next directory entry ; enter with FCB set as before ; exit with directory code in A 255 says not found ; SEARN: LHLD SEARA ;get the last search FCB out SHLD FCB ;save this as the FCB CALL RSELCT ;select the right drive CALL SERCHN ;then search for the nex extent JMP MOVSEC ;move the sector and return ; ;********************************************************************** ; BDOS function 19: delete file ; enter with FCB address set ; exit with directory code in A ; DELETE: CALL RSELCT ;select the right drive CALL DELETF ;delete the indicated file JMP RETCOD ;set the return code and go back ; ;******************************************************