; ;BASIC DISK OPERATING SYSTEM FOR **Z-DOS** ;BDOS V. 1.53 ; ;WRITTEN BY RALPH E. BUCKNAM ;COPYRITE (C) 1979 ;ALL RIGHTS RESERVED ; ; ;EQUATES FOR FIRST PAGE ; IOBYTE: EQU 03H SM003: EQU 06H L.C.X2: EQU 4DDDH ;LD C,X' L.A.X2: EQU 7DDDH ;LD A,X' ; ;BIOS EQUATES ; BIOS: EQU 0CA00H ; **** MAY CHANGE WBOOT: EQU BIOS+03H CONST: EQU BIOS+06H CONIN: EQU BIOS+09H CONOT: EQU BIOS+0CH LIST: EQU BIOS+0FH PUNCH: EQU BIOS+12H READER: EQU BIOS+15H HOME: EQU BIOS+18H SELDSK: EQU BIOS+1BH SETTRK: EQU BIOS+1EH SETSEC: EQU BIOS+21H SETDMA: EQU BIOS+24H READ.1: EQU BIOS+27H DWRIT1: EQU BIOS+2AH F.DMA: EQU BIOS+2DH DRVBYT EQU 0DF91H ;IN SNOOPY DOS EQUATES DRIVE EQU DRVBYT ; ;The auxalary buffer of 260 bytes is used as a ;disk buffer and a keyboard input buffer. ;Normaly this buffer starts at the end of the ;BIOS ; AUXBUF EQU 0DAA0H ; FORM ; SERIAL: DB 26H,0EH,0,0,0,1BH ;SERIAL NUMBER ; JP SM019 ; SETTAB: DB 80H,40H,20H,10H DB 8H,4H,2H,1H ; UNSKEW: LD HL,TRANS ;SHOULD POINT TO TRANS. LD B,0 ADD HL,BC ;POINT TO SECTOR LD C,(HL) ;GET SECTOR JP SETSEC NOP ; ;TRANSLATE VICTORS ; TRANS: DB 01H,07H,0DH,13H,19H,05H DB 0BH,11H,17H,03H,09H,0FH DB 15H,02H,08H,0EH,14H,1AH DB 06H,0CH,12H,18H,04H,0AH DB 10H,16H ; DB 0,0,0 NOP SECSIZ: DB 1AH BLKSHF: DB 3FH ;64 FILE CONTROL BLOCKS ROTFAC: DB 03H SEC.BK: DB 07H MAXBLK: DB 0F2H X.C0: DB 0C0H ST.DIR: DB 02H ; ;END OF STORAGE ; ;BDOS INTERCHANGE ROUTINE. SAVES CALLERS STACK ; SM019: LD (HL.EXT),HL ;SAVE EXTERNAL HL EX DE,HL LD (DE.EXT),HL ;SAVE DE REG. LD A,L ;GET E.EXT IN A LD (E.EXT),A ;STORE E.EXT LD HL,0 LD (C9INFO),HL ;RESET C9INFO TO 0 LD (SP.EXT),SP LD SP,N.SP ;SET UP BDOS STACK PUSH IX ;SAVE CALLERS PROPERTY LD IX,(DE.EXT) CALL CMVICT ;EXECUTE INCOMING ;COMMAND LD HL,(C9INFO) LD A,L LD B,H POP IX ;GET CALLERS REG. LD SP,(SP.EXT) RET ;RETURN TO EXTERNAL ;CALLER ; FOX1: LD HL,SM01F CALL ER.CND JP BOOT.T ;TEST IF REBOOOT ; FOX2: LD HL,SM020 JR SM01B ; FOX3: LD HL,SM021 ; SM01B: CALL ER.CND JP WBOOT ; ;ERROR CONDITIONING ? ; ER.CND: PUSH HL CALL CRLF LD A,(DRIVE) ADD A,41H LD (DRV.NO),A LD DE,BDOSER CALL BUFOUT POP DE CALL BUFOUT JR IN.CHK ; BDOSER: DB 'BDOS ERR ON ' DRV.NO: DM ' : ' ; SM01F: DM 'BAD SECTOR' ; SM020: DM 'SELECT' ; SM021: DM 'R/O' ; ;STATUS INPUT ; IN.CHK: LD HL,STATBT LD A,(HL) LD (HL),00H OR A RET NZ JP CONIN ; ;INPUT CHARACTER AND ECHO ; INECHO: CALL IN.CHK ;OUT STATBY OR KEYBRD CALL PUNCHU RET C PUSH AF LD C,A CALL TAB.CK ;& OUTPUT CHAR. POP AF RET ; PUNCHU: CP 0DH RET Z CP 0AH RET Z CP 09H RET Z CP 20H RET ; ;STATUS OF KEYBOARD: A = 1 PRESED, A = 0 NO PRESS ;USED BY OUTPUT AND COMMAND 11 (0B) TEST CONSOLE ;READY ; TS.CON: LD A,(STATBT) OR A JR NZ,SM02A ;INPUT FROM STATBYT CALL CONST AND 01H RET Z CALL CONIN CP 13H ;^S JR NZ,SM029 ;STORE IN STATE BYTE CALL CONIN ;WAIT FOR KEY PRES BOOT.T CP 03H JP Z,WBOOT XOR A RET ; SM029: LD (STATBT),A ;SAVE INPUT SM02A: LD A,01H RET ; ;OUT # AND CRLF ; X.CRLF: LD C,23H ;# CALL OUTPUT CRLF: LD C,0DH CALL OUTPUT LD C,0AH ; ;OUTPUT A CHARACTER ; OUTPUT: PUSH BC CALL TS.CON POP BC PUSH BC CALL CONOT POP BC PUSH BC LD A,(LSTBYT) OR A CALL NZ,LIST POP BC LD A,C LD HL,LENGTH CP 7FH ;BACKSPACE JR Z,BACKER ;BACK POINTER UP INC (HL) CP 20H RET NC DEC (HL) CP 0AH RET NZ LD (HL),00H ;RESET LINE LENGTH RET ; BACKER DEC (HL) ;BACK POINTER UP RET ; ;CONTROL TRAP FOR OUTPUT: CONVERT TO ^(A-Z) ; T.CTRL: LD A,C CALL PUNCHU ;TEST FOR PUNCUATION JR NC,TAB.CK ;& OUTPUT CHAR. PUSH AF LD C,5EH ;LOAD (^) CALL OUTPUT POP AF OR 40H ;CTRLS TO LETTERS LD C,A ; TAB.CK: LD A,C CP 09H JR NZ,OUTPUT ; SM02E: LD C,20H CALL OUTPUT LD A,(LENGTH) AND 07H JR NZ,SM02E RET ; ;9 PRINT BUFFERED LINE ; PBUFFL: LD DE,(DE.EXT) ; BUFOUT: LD A,(DE) CP 24H ;TEST FOR $ RET Z OR A RET Z AND 7FH ;STRIP OFF HIGH BIT LD C,A CALL TAB.CK ;& OUTPUT CHAR. LD A,(DE) ;GET CHAR AGAIN BIT 7,A ;TEST FOR END CHAR. RET NZ ;END CHARACTER INC DE ;NEXT POSITION JR BUFOUT ; ;10 (0AH) INPUT BUFFERED LINE ; INLINE: PUSH IX ;SAVE START OF BUFFER LD E,(IX+00) ;MAX BUFFER LENGTH INC IX ;NEXT POSITION LD D,00H ; BUFLINE: BUFLOP: CALL IN.CHK ;GET INPUT CHAR. AND 7FH ;STRIP 8 BIT CP 0DH ;TEST FOR CRH JR Z,LN.END ;END OF LINE CP 7FH ;BACKSPACE JR NZ,BLINE2 ; ;BACK SPACE ROUTIN ; INC D ;TEST FOR ZERO DEC D JR Z,BUFLIN ;BUFFER WAS EMPTY DEC D DEC IX LD A,(IX+01) ;GET LAST CHAR. CP 09H ;TEST FOR TAB JR Z,RTYPE2 ;RETYPE LINE ADD 0E0H ;TEST FOR CTRLS JR C,BACK.1 ;JUST ON BACK SPACE LD C,7FH ;EXTRA BACK SPACE ;FOR CONTROL CHARS. CALL CONOT ;OUTPUT EXTRA BACK SPACE ; BACK.1: LD A,7FH ;LOAD FOR BACK SPACE JR BACK1 ;CONTINUE ; BLINE2: CP 05H ;TEST FOR ^E ;PHYISCAL CRLF ; JR NZ,TOGTST CALL CRLF JR BUFLOP ; ;TEST FOR PRINT TOGGLE ; TOGTST: CP 10H JR NZ,TNLINE LD HL,LSTBYT LD A,01H SUB (HL) LD (HL),A JR BUFLIN ; ;TEST FOR NEW LINE ; TNLINE: CP 15H ;TEST FOR ^U JR NZ,TRTYPE ; NEWLIN: CALL X.CRLF POP IX JR INLINE ; ;TEST FOR RETYPING LINE ; TRTYPE: CP 12H ;TEST FOR ^R JR NZ,OUT.IT ;PRINT CHARACTER ; RTYPE2 CALL X.CRLF ;ANOUNCE WHAT GOES POP HL ;GET START FROM STACK PUSH HL INC HL ;ASCII -1 LD B,D ;GET NO. OF CHARS. INC B ;TEST FOR ZERO DEC B JR Z,BUFLIN ;NO INPUTS ; RTYPE INC HL LD C,(HL) ;GET CHAR. PUSH BC PUSH HL CALL T.CTRL ;OUTPUT CHARACTER POP HL POP BC DJNZ RTYPE ;MORE TO GO ; JR BUFLIN ; ;PRINT CHAR. ; OUT.IT: INC IX LD (IX+00),A ;STORE CHAR INC D ; BACK1 LD C,A PUSH AF CALL T.CTRL ;OUTPUT CHAR POP AF ;GET FOR ^C TEST CP 03H LD A,D JR NZ,NOBOOT CP 01H JP Z,WBOOT ; NOBOOT CP E ;CHECK FOR END LINE JR C,BUFLIN ; LN.END: POP HL ;TRANSFER IX TO HL INC HL ;GET IN POSITION LD (HL),D ;STORE NO OF CHAR. IN ;LINE JP CRLF ;END OF LINE ; EMPTBY: DB 0E5H ;UNUSED DIRECT. BLOCK ; ;MAKE NEW DISK MAP FOR DRIVE X ; DR.SET: CALL HOME LD HL,(ST.DIR) LD C,L CALL SETTRK LD HL,(TAB.4P) XOR A LD (HL),A INC HL LD (HL),A LD HL,(TAB.3P) LD (HL),A RET ; ;CALCULATE NXT LOGICAL SECTOR TO BE PROCESSED ;AND CALCULATE NEXT TRACK AND SECTOR ; LOGSEZ: LD A,(BOXER) LD B,A LD HL,(STORM) ADD HL,HL ;MULTIPLY BY 8 ADD HL,HL ADD HL,HL LD A,07H ;SECTORS PER CLUSTER ;******** AND B OR L LD L,A LD (STORM),HL ; ;FIND TRACK AND SECTOR ;Z80 CP/M VER 1/5 TRACK AND SECTOR FINDER ;MODIFIED AND MADE TABLE COMPATABLE ; DLOCAT: PUSH IX PUSH IY LD IX,(TAB.3P) ;POINT TO LAST TRACK LD IY,(TAB.4P) ;POINT TO LAST SECTORS LD E,(IY+00) ;GET LOW SECTORS LD D,(IY+01) ;GET HIGH SECTORS LD BC,1AH ;SECTORS PER TRACK ;******** ; LOCAT1: LD HL,(STORM) ;GET TOTAL SECTORS AND A ;CLEAR CARRY FLAG SBC HL,DE ;TEST JP NC,LOCAT2 ;HIGHER DISK POSITION EX DE,HL ;LOWER DISK POSITION AND A SBC HL,BC ;REDUCE SECTORS EX DE,HL LD (IY+00),E ;SAVE LOWER SECTORS LD (IY+01),D ;SAVE UPPER SECTORS DEC (IX+00) ;ONE LESS TRACK JP LOCAT1 ; LOCAT2: EX DE,HL ADD HL,BC ;INCREASE SECTORS EX DE,HL LD HL,(STORM) ;GET TOTAL SECTORS SBC HL,DE ;TEST JP C,TRKSEL ;DONE LD (IY+00),E ;STORE NEW SECTORS LD (IY+01),D ; " " " INC (IX+00) ;INCREASE TRAK NO JP LOCAT2 ;TRY AGAIN ; TRKSEL: ADD HL,BC ;GET SECTOR [-1] LD A,02 ;START OF DIRECTORY ;******** ADD A,(IX+00) ;ADD TRACK TO ST.DIR POP IY POP IX LD C,A CALL SETTRK LD C,L JP UNSKEW ; ;READ OR WRITE SECTOR ; READ: CALL READ.1 JR ERRCHK ; CKSUMW: LD A,01H ;SET SNALE TO 01H CALL D.CKSUM ; WRITE: CALL DWRIT1 ERRCHK: LD (ER.BYT),A CP 00H ;TEST FOR ERROR JP NZ,FOX1 ;ERROR ROUTINE RET ;NO ERROR ; ;POINT TO CLUSTER IN CALLERS FILE CONTORL BLOCK ;IF CLUSTER IS NOT USED ON WRITE 00H IS RETURNED, ;IF NOT FULL THE NUMBER IS RETURNED. ON READ ;THE CLUSTER NUMBER IS RETURNED AND PROCESSED. ; PCLUST: LD A,(BOXER) SRL A SRL A SRL A ADD A,10H LD C,A LD B,00H LD HL,(DE.EXT) ADD HL,BC ;POINT TO CLUSTER LD L,(HL) ;GET CLUSTER IN L REG. LD H,00H LD (STORM),HL ;SAVE CLUSTER NO. LD A,L ;CLUSTER NO TO A CP H ;TEST FOR ZERO RET ; ;ESTABLISH NEXT DIRECTORY SECTOR TO BE READ ; NXDSEC: LD A,(ERRBYT) ;NUMBER OF DIRECTORYS AND 0FEH ;TESTED RRA ;CONVERT TO SECTORS RRA ;DIVIDE BY 4 LD (CAT),A ;STORE FOR CHECKSUM LD L,A ;TESTING LD H,00H LD (STORM),HL ;STORE SECTORS READ JP DLOCAT ;FIND TRACK AND SECTOR ; ;CHECK SUM OF 128 BYTE SECTOR BLOCK ; CHKSUM: XOR A ;GET A ZERO LD B,10H ;1 SECTOR LD HL,(DOG) ;START OF CHECKSUM ; LOOP.1: ADD A,(HL) INC HL ADD A,(HL) INC HL ADD A,(HL) INC HL ADD A,(HL) INC HL ; ADD A,(HL) INC HL ADD A,(HL) INC HL ADD A,(HL) INC HL ADD A,(HL) INC HL ; DJNZ LOOP.1 RET ; ;COMPARE ALL DIRETORY SECTORS AGAINST THE ;CHECKSUM TABLE AND SET READ ONLY BIT IF ;CHECKSUMS ARE NOT EQUAL ; FULLCK: LD HL,CKBYTE LD A,01H LD (HL),A ;SET FOR FULL R/O CK PUSH HL LD HL,(DE.EXT) PUSH HL LD HL,(REN) PUSH HL LD HL,READ LD (DE.EXT),HL CALL S.RCD0 POP HL LD (REN),HL POP HL LD (DE.EXT),HL POP HL XOR A ;GET A ZERO LD (HL),A ;SET FOR NO R/O CK RET ; ;CHECK DRIVE X FOR READ ONLY ; RITETS: LD A,(DRIVE) INC A LD B,A LD A,(SNAKE) LP.1: RRCA DJNZ LP.1 RLCA RET ; ;READ ONLY TEST. ERROR IF READ ONLY ; TWRITE: CALL RITETS RRA RET NC ;NO PROBLEMS JP FOX3 ;ERROR HAS OCCURED ; ;POINT TO NEXT FILE CONTROL BLOCK IN DIRECTORY ; NEXFCB: LD (BIRD),A LD HL,ERRBYT INC (HL) LD A,(BLKSHF) ;FILE CTRL BLOCKS CP (HL) JR NC,NXFCB2 LD (HL),0FFH RET ; ;CALCULATE START OF NEXT FILE CTRL BLOCK ; NXFCB2: LD A,(HL) ;GET ERRBYT IN A AND 03H ADD A,A ADD A,A ADD A,A ADD A,A ADD A,A LD D,0 ;ZERO D REG. LD E,A ;RUG TO E. LD HL,(DOG) ;START OF DISK BUF. ADD HL,DE ;CALCULATE N.RUG LD (N.RUG),HL ;STORE OR A ;TEST FOR UNTESTED FCB RET NZ ;END OF ROUTINEE CALL NXDSEC ;GET NEXT SECTOR CALL READ ;READ NEXT DIR SEC. LD A,(BIRD) ;00H DIRFNX - 01H MAPMAK ; ;MAKE CHECKSUM OF FIRST 10 SECTORS OF DIRECTORY ; D.CKSU: LD B,A ;STORE SNALE LD A,(CAT) CP 10H ;CHECK 10 SECTORS RET NC ;DONE ; ;DETERMINE WEATHER TO COMPARE OR STORE CHECKSUM ; LD A,B ;GET SNALE RRA JR NC,RCKSUM ;COMPARE CHECKSUMS ; ;PUT CHECKSUM IN TABLE ; CALL CHKSUM LD HL,(CAT) ;DIR SECTOR NUMBER LD H,00H EX DE,HL LD HL,(DRCSUM) ;DIR CHKSUM POINTER ADD HL,DE ;DIR CHKSUM LOCATION LD (HL),A ;STORE CKSUM HERE RET ; ;COMPARE TWO CHECKSUMS ; RCKSUM: LD A,(CKBYTE) ;CHECK BYTE RRA RET NC ;DO NOT TEST FOR ;READ ONLY DISK LD HL,(CAT) LD H,00H ;SET CAT TO 00H EX DE,HL LD HL,(DRCSUM) ADD HL,DE PUSH HL CALL CHKSUM POP HL CP (HL) RET Z ;DONT SET R/O BYTE ; ;28 (1CH) SET DISK TO READ ONLY ; RONLY: LD A,(SNAKE) CALL RONLY2 ;SET READ ONLY FLAG LD (SNAKE),A RET ; ;SET UP READ ONLY BYTE ; RONLY2: LD L,A ;SAVE OLD R/O BYTE LD A,(DRIVE) INC A LD B,A LD A,80H LP.4: RLCA DJNZ LP.4 OR L ;MAKE NEW R/0 BYTE RET ; ;REVISED UPDATE CLUSTER ROUTINE ;WHEN PLUM CONTAINS 00 CLUSTER IS SET TO UNUSED ;WHEN PLUM CONTAINS 01 CLUSTER IS SET TO USED ; ; UPCLUS: LD HL,PLUM LD B,(HL) ;GET OPERATION TYPE LD HL,SETTAB ;ADDRES OF SETTER TAB. LD A,C ;CLUSTER NO TO ACUM. AND 07H ;REMOVE UPPER BYTES LD D,0 ;ZERO D REG LD E,A ;OFFSET ADD HL,DE ;CALCULATE SETTER POS. LD A,C ;MOVE CLUSTER NO. LD C,(HL) ;GET SETTER LD HL,(BI.PNT) ;GET START OF CLUSTER ;MAP ; AND 0F8H ;STRIP LOWER 3 BYTES RRCA ;DIVIDE BY 8 RRCA RRCA LD E,A ADD HL,DE ;GET BIT MAP POSITION LD A,C ;GET SETTER DEC B ;TEST FOR TYPE JR NZ,AVAIL ;MAKE CLUSTER AVAILABLE OR (HL) ;MAKE NEW BYTE LD (HL),A ;STORE NEW BYTE RET ; AVAIL: CPL AND (HL) ;MAKE NEW BYTE LD (HL),A ;STORE NEW BYTE RET ; ; ;POINT TO FILE IN DIRECTORY AND PUT INFO IN ;CLUSTER MAP ; PTFILE: LD (PLUM),A ;STORE CLUST MODIFIER EXX PUSH HL PUSH BC PUSH DE LD HL,(N.RUG) ;GET DBUF POSITION LD DE,10H ;GET OFSET FOR CLUST. ADD HL,DE ;CALCULATE CLUST START LD B,E ;GO 16 TIMES ; PTFIL2: LD A,(HL) ;GET CLUSTER NO OR A ;TEST FOR END JR Z,XRET ;END OF CLUSTERS EXX LD C,A ;CLUSTER IN POSITION CALL UPCLUS ;UPDATE CLUSTER MAP EXX INC HL ;NEXT CLUSTER DJNZ PTFIL2 ;KEEP GOING ; XRET: POP DE POP BC POP HL EXX RET ;END OF BLOCK ; ;MAKE MAPS FOR SPECIFIED DRIVE ; MAPMAK: XOR A ;GET A ZERO LD (CURREN),A ;RESET LD (SNAKE),A ;RESET READ ONLY BYTE LD HL,(BI.PNT) LD A,(X.C0) ;GET DIRECTORY CLUSTERS LD (HL),A ;STORE DIRECTORY INFO INC HL XOR A ;GET A ZERO LD B,1FH ;NO. OF ZEROS TO BE ;PLACED IN TABLE MP.LOP: LD (HL),A ;PUT ZERO IN TABLE INC HL ;ADVANCE POINTER DJNZ MP.LOP ; CALL DR.SET ;DRIVE TO DIR. TRACK. LD HL,ERRBYT LD (HL),0FFH ;SETUP NOT FOR ERROR!! ; ;GET NEXT DIRECTOY SECTOR ; NXTDIR: LD A,01H ;SET BIRD TO 01H CALL NEXFCB ;GET NEXT FCB {READ} LD A,(ERRBYT) CP 0FFH ;TEST FOR ERROR RET Z ;ERROR HAS OCCURED LD HL,(N.RUG) LD A,(HL) CP 0E5H ;TEST FOR EMPTY FCB JR Z,NXTDIR ;JUMP TO SETUP NXT SEC INC HL LD A,(HL) SUB 24H JR Z,BRANCH ;SAVE STEPS BR.RET: LD A,01H CALL PTFILE ;POINT TO FILE IN DIR. JR NXTDIR ;NEXT DIR SECTOR ; BRANCH: SUB 01H SBC A,A LD HL,CURREN OR A LD (HL),A JR BR.RET ; ;18 (12H) FIND NEXT DIRECTORY ENTERY ; FNXDIR: LD HL,(REN) LD (DE.EXT),HL CALL LINECK ;TEST REN ; ;FIND NEXT DIRECTORY ENTRY ; DIRFNX: LD HL,(REN) LD (DE.EXT),HL ; DRFNX1: XOR A ;SET BIRD TO 00H CALL NEXFCB ;GET NEXT FCB {READ} LD A,(ERRBYT) LD (CURREN),A CP 0FFH RET Z ;ERROR HAS OCCURED LD A,(SER.LN) ;GET SEARCH LENGTH LD C,A ;TRANSFER LD B,0 ;ZERO OUT B REG. LD HL,(N.RUG) ;POSITION IN DBUF EX DE,HL LD HL,(DE.EXT) ;CALLERS F.C.B ; LOOP2: LD A,3FH ;NO COMPARE CHAR CP (HL) ;TEST FOR NO COMP. JR Z,N.TEST ;DONT COMPARE BUFFER LD A,(DE) ;MAKE TEST N.TEST: INC DE ;READY FOR NEXT TEST CPI ;COMPARE JP NZ,DRFNX1 ;NO MATCH JP PE,LOOP2 ;TRY AGAIN ; XOR A ;MATCH HAS OCCURED INC A RET ; ;17 (11H) SEARCH DIRCTORY FOR FILE NAME ; DSEARC: CALL LINECK ; ;SEARCH FOR FILE ; S.RCD0: LD A,0DH S.RCD: LD (SER.LN),A LD HL,(DE.EXT) LD (REN),HL LD HL,ERRBYT LD (HL),0FFH CALL DR.SET CALL DIRFNX RET ;RESERVED SPACE ; ;19 (13H) DELETE DISK FILE ; DLFILE: CALL LINECK CALL FULLCK ;COMPARE ALL DIREC'S CALL TWRITE ;TEST FOR READ ONLY LD A,0CH ;COMPARE 0CH TIMES CALL S.RCD ;SEARCH FOR RECORD ; ;KILL FILE END TEST ; KFILE2: RET Z ;NO FILES ECT XOR A CALL PTFILE ;POINT TO FILE LD HL,(N.RUG) LD (HL),0E5H CALL CKSUMW CALL DIRFNX JR KFILE2 ; ;PART OF WRITE ROUTINE - FIND EMPTY CLUSTER ;CP/M 1.5 EMPTY CLUSTER IMPROVMENTST ; ECLUST: LD HL,(OLD.DA) ;GET OLD POSITION INC A DEC A ;TEST FOR ZERO JR Z,RELOAD CP L ;TEST FOR SAME CLUST. JR NZ,RELOAD EX DE,HL LD HL,(OLD.PO) ;GET OLD POSITION JR CHECK ;READY FOR CHECK ; RELOAD: LD DE,2000H ;CHECKING PARAMETERS LD HL,(BI.PNT) ;START OF CLUST. TAB ; CHECK: LD A,0FFH ;LOADED EMPTY CLUSTER ;BYTE ; CHECK2: CP (HL) ;TEST FOR EMPTY CLUST. JR NZ,CHECK3 ;CLUSTER WAS EMPTY INC HL ;NEXT CLUSTER DEC D ;TEST FOR END DISK JR NZ,CHECK2 ;TRY AGAIN ; XOR A ;GET A ZERO CLUST NO. RET ;END OF DISK ; CHECK3: LD (OLD.PO),HL ;SAVE POSITION LD A,D ;REMAINING TRIES CPL INC A ADD A,20H ;GET STEPS USED ADD A ;CONVERT TO CLUSTERS ADD A ADD A LD E,A ;SAVE POSITION CLUSTER ;NUMBER ; LD A,80H ;READY FOR SEARCH ; CHECK4: LD C,A ;SAVE SETTER AND (HL) ;TEST IF VACANT JP Z,L.TEST ;TEST FOR BEING LEGAL RRCA ;SETTER ONE RIGHT INC E ;INC CLUSTER NO JP CHECK4 ;TRY AGAIN ; L.TEST: EX DE,HL LD (OLD.DA),HL ;SAVE DATA EX DE,HL LD A,(MAXBLK) ;GET MAXIUM NO OF ;BLOCKS [INSTAL LABLE ;IN SOURCE] ; CP A,0FFH ;LARGE TEST LD B,A ;SAVE MAX BLOCKS LD A,E ;MOVE CLUST. NO TO A RET Z ;NO CHECKING NECESSARY INC B ;MAX BLOCKS +1 CP B ;TEST FOR TO MANY CLUS. RET C ;LEGAL CLUSTER NO XOR A ;END DISK, OO CLUSTER ;NUMBER RET ; ;23 (17H) RENAME DISK FILE ; RENAME: CALL LINECK CALL FULLCK ;COMPARE ALL DIREC'S CALL TWRITE ;TEST FOR READ ONLY LD A,0CH CALL S.RCD ;SEARCH FOR RECORD RET Z ;FILE NO FOUND LD HL,(DE.EXT) LD BC,10H PUSH HL ADD HL,BC POP DE LD A,(DE) LD (HL),A ; RNAME2: LD C,0CH ;CHARACTERS TO MOVE LD B,10H ;SOURCE OFFSET FACTOR CALL MOVE ;MOVE TO DIRECTORY CALL DIRFNX RET Z ;NO MORE FILES JR RNAME2 ; ;15 (0FH) OPEN DISK FILE ; OPENFL: CALL LINECK ; ;OPEN FILE MOVES INFOMATION FROM DISK ;BUFFER TO CALLERS FILE CONTROL BLOCK ; FL.OPN: CALL S.RCD0 ;SEARCH FOR RECORD RET Z ;FILE NOT FOUND LD BC,0DH ;OFFSET FACTOR LD HL,(DE.EXT) ;DESTINATION ADD HL,BC ;DESTINATION ADR. EX DE,HL ;SAVE IN DE REG. LD HL,(N.RUG) ;GET START OF DISK BUF. ADD HL,BC LD C,13H ;BYTES TO BE TRANSFERED LDIR ;TRANSFER BYTES RET ; ;16 (10H) CLOSE DISK FILE ; CLOSEF: CALL LINECK ; ;CLOSE FILE ; CL.FIL: XOR A ;GET A ZERO LD (CURREN),A CALL RITETS ;TEST FOR READ ONLY RRA RET C ;READ ONLY CALL S.RCD0 ;SEARCH FOR RECORD RET Z ;ERROR ; MOVE.4: LD BC,20H ;CHARACTERS TO MOVE ; ;THIS ROUTINE MOVES COMMAND LINE INFOMATION FROM ;CONSEL COMAND PROCESSER TO THE BUFFER FOR ;PLACEMENT IN DIRECTORY ; MOVE: LD D,0 LD E,B ;GET OFSET IN DE LD B,D ;MOVE ZERO IN B LD HL,(DE.EXT) ;CALLERS FCB ADD HL,DE ;GET SOURCE POSITION LD DE,(N.RUG) LDIR ;GO MOVE BYTES ; CALL NXDSEC CALL CKSUMW RET ; ;22 (16H) CREATE DISK FILE ; CREATE: CALL LINECK ; ;MAKE NEW DISK FILE ; CRE.FL: CALL TWRITE ;TEST FOR READ ONLY LD HL,(DE.EXT) LD (TEMPDE),HL LD HL,EMPTBY ;0E5H FIRST CHAR OF LD (DE.EXT),HL ;OF COMMAND LINE LD A,01H CALL S.RCD ;SEARCH FOR RECORD RET Z ;NOT 0E5H, NO SPACE LD HL,(TEMPDE) LD (DE.EXT),HL ;RESTORE DE.EXT ; ;ZERO OUT PARTS OF CALLERS FILE CONTROL BLOCK ; XOR A ;GET A ZERO IN ACUM. LD D,A LD E,0DH ;OFSET ADD HL,DE ;GET START OF ZEROS LD B,14H POKEY: LD (HL),A ;STORE A ZERO INC HL DJNZ POKEY JR MOVE.4 ;GO. MOVE FILE ; ;CLOSE OLD EXTEND OPEN NEW EXTENT ; EXENET: CALL F.DMA ;GET ADR. OF DMA LD (T.DMA),HL ;STORE LD HL,A.BUF ;AUXILARY BUFFER ADR. CALL DMATS4 ;SET UP NEW BUFFER LD (WREN),A ;STORE EXTENT TYPE OR A ;TEST FOR WRITE JR NZ,N.CLOSE ;READ FILE CALL CL.FIL ;WRITE CLOSES FILE LD A,(ERRBYT) INC A ;TEST FOR FFH RET Z ;ERROR HAS OCCURED ; N.CLOSE INC (IX+0CH) ;SET FOR NEXT EXTENT CALL S.RCD0 ;SEARCH FOR RECORD JR NZ,EXTEN4 LD A,(WREN) RRA RET C ;ERROR HAS OCCURED CALL CRE.FL JR EXTEN5 ; EXTEN4: CALL FL.OPN EXTEN5: LD A,(ERRBYT) INC A ;TEST FOR 0FFH JR Z,DSKERR ;PROBLEMS LD HL,(T.DMA) ;GET ORIGINAL DMA CALL DMATS4 ;STORE DMA ADR. CALL REX ;GET BLOCK AND SEC INFO. XOR A ;GET A ZERO IN ACCUM. JR CX.RET ;SET CURRENS TO ZERO ; ;30 (1EH) SET DMA - [CHANGE MAIN DISK BUFFER] ; FIXDMA: LD HL,MAPLE LD (HL),01 ; ;CHANGE MAIN DISK BUFFER ; DMASET: LD HL,(DE.EXT) DMATS4 LD (DOG),HL ;SAVE DMA ADDRESS JR DMATS3 ; ;TEST TO SEE IF DMA MUST BE SET (1) ; DMATS1: LD HL,(DSKBUF) JR DMATS3 ; ;TEST TO SEE IF DMA MUST BE SET (2) ; DMATS2: LD HL,(DOG) DMATS3: LD B,H LD C,L JP SETDMA ; REX: XOR A CP (IX+00H) ;CHECK FOR DRIVE CHANGE CALL NZ,LINECK LD A,(IX+0FH) LD C,A ;SAVE VALUE LD (LUXER),A LD A,(IX+20H) LD B,A ;SAVE LD (BOXER),A RET ; ;READ NEXT RECORD (20) ***SECTOR*** ; RNXREC: CALL REX ;GET OLD INFO CP C ;CP BOXER & LUXER JR C,M.READ ;MORE SECTOS TO READ LD HL,CURREN LD (HL),01H CP 80H ;TEST FOR END OF EXTENT JR NZ,R.ERR1 ;TEST FOR ERROR LD A,01H CALL EXENET ;GET NEXT EXTENT ; R.ERR1: XOR A ;GET A ZERO LD (BOXER),A ;RESET BOXER LD A,(CURREN) OR A ;TEST FOR ERROR RET NZ ;ERROR HAS OCCURED ; M.READ: CALL PCLUST ;POINT TO CLUSTER NO. JR NZ,MREAD2 ;NO ERROR DSKERR: LD A,1 ;SET UP ERROR CX.RET: LD (CURREN),A ;STORE VALUE RET ; MREAD2: CALL LOGSEZ ;FIND TRACK AND SECTOR LD A,(MAPLE) RRA CALL C,DMATS1 CALL READ LD A,(MAPLE) RRA CALL C,DMATS2 LD A,(BOXER) INC A LD (IX+20H),A ;STORE NEXT SECTOR LD A,(LUXER) ;TOTAL NO. OF SECTORS LD (IX+0FH),A ;STORE RET ; ;WRITE NEXT RECORD (21) ; WNXREC: CALL REX ;GET OLD INFO LD A,7FH CP B JR C,DSKERR ;PROBLEMS CALL PCLUST ;POINT TO CLUSTER NO. IN ;IN CALLERS FCB ? ; ;IF CLUSTER NUMBER IS ZERO THE LAST CLUSTER IS ;FULL AND ANNOTHE CLUSTER NUMBER MUST BE FOUND ; JR NZ,WRIT.A ; CLUSTER NO. EXISTS LD HL,NUT LD (HL),00H ;SET NUT TO 00H LD A,(BOXER) AND 0FCH RRA RRA RRA ADD A,10H INC HL LD (HL),A ;H OF STORM LD C,A LD A,10H CP C JR NC,WRIT.3 LD A,(OAK) DEC A LD C,A LD B,00H LD HL,(DE.EXT) ADD HL,BC LD A,(HL) LD (NUT),A ; WRIT.3: LD A,(DRIVE) ;PRESENT DRIVE LD HL,L.DRIV ;LAST DRIVE CP (HL) ;TEST IF SAME JR Z,WRIT.4 LD (HL),A ;STORE NEW DRIVE XOR A ;GET A ZERO LD (NUT),A ;SET FOR FULL SEARCH CALL TWRITE ;CHECK IF READ ONLY ; WRIT.4: LD A,(NUT) CALL ECLUST ;GET NEW CLUSTER NO. LD (NUT),A ;STORE CLUSTER NO. LD B,A ;STORE NUT OR A ;TEST FOR END OF DISK JR NZ,WRIT.9 ;NOT END OF DISK LD HL,CURREN LD (HL),02H ;SETUP END OF DISK JR WRIT.A ;JP END DISK TEST ; WRIT.9: LD A,C ;GET SETTER OR (HL) ;MAKE NEW BYTE LD (HL),A ;STORE NEW BYTE LD C,B ;TRANSFER NUT LD B,0 ;ZERO OUT B REG LD (STORM),BC LD HL,(OAK) ;RETREIVE STORE POSITION ;IN CALLERS FCB LD H,B ;ZERO OUT H REG EX DE,HL LD HL,(DE.EXT) ;START ADDRESS OF ;CALLERS FCB ADD HL,DE LD (HL),C ;STORE CLUSTER NO. ; ;WRITE RECORD ON DISK ; WRIT.A: LD A,(CURREN) OR A ;TEST FOR END OF DISK RET NZ ;ERROR HAS ACCRUED CALL LOGSEZ ;CALC TRACK AND SECTOR LD A,(MAPLE) RRA CALL C,DMATS1 CALL WRITE LD A,(MAPLE) RRA CALL C,DMATS2 LD A,(BOXER) LD B,A ;STORE BOXER LD HL,LUXER CP (HL) JR C,WRIT.B INC A LD (HL),A ;STORE A IN LUXER DEC A ; WRIT.B: CP 7FH JR Z,WRIT.X ; DATSTR: INC B ;NEXT SECTOR TO BE ;PROCESSED LD (IX+20H),B ;STORE NEXT SECTOR LD A,(HL) ;GET LUXER LD (IX+0FH),A ;STORE RET ; WRIT.X: CALL DATSTR XOR A CALL EXENET ;GET NEXT EXTENT LD BC,CURREN LD A,(BC) OR A JR NZ,WRIT.C LD HL,BOXER LD (HL),0FFH ; WRIT.C: XOR A ;GET A ZERO LD (BC),A ;SET CURREN TO ZERO RET ; ;13 (0DH) RESET CP/M AND SELECT DRIVE A ; RESET: XOR A LD HL,LENGTH ;START OF ZEROING LD DE,LENGTH+1 LD BC,101H LD (HL),A LDIR ;ZERO OUT BUFFERS LD HL,80H ;MAIN BUFFER LD (DSKBUF),HL ;RESET DISK BUFFER LD (DE.EXT),HL CALL DMASET ; ;INITILIZE TABLE POINTERS FOR DRIVE X ; D.INIT: LD A,03H LD HL,DRIVE CP (HL) ;TEST FOR NON INIT. DRIVE JP C,FOX2 ;NONEXISTANT DRIVE LD A,(DRIVE) ADD A,A ADD A,A ADD A,A ADD A,A LD C,A LD B,00H PUSH BC ;SAVE FOR LATER ADD A,A LD C,A LD HL,BITMAP ADD HL,BC LD (BI.PNT),HL ;TABLE #1 POP BC ;RETRIVE LD HL,BLKMAP ADD HL,BC LD (DRCSUM),HL ;TABLE #2 LD HL,(DRIVE) LD H,00H PUSH HL ;SAVE DRIVE BYTE LD BC,TABLE3 ADD HL,BC LD (TAB.3P),HL ;TABLE #3 POP HL PUSH HL LD BC,TABLE4 ADD HL,HL ADD HL,BC LD (TAB.4P),HL ;TABLE #4 POP BC ;GET DRIVE INFO CALL SELDSK LD A,(LOGBYT) RLCA PUSH AF LD A,(DRIVE) INC A LD B,A POP AF LP.3: RRCA DJNZ LP.3 RRA ;INIT DRIVE BIT MAP RET C ;END OF ROUTIN LD A,(LOGBYT) CALL RONLY2 ;RESET READ ONLY BYTE LD (LOGBYT),A JP MAPMAK ; ;CHECK AN CHANGE DRIVE WHEN REQUIRED ; LINECK: LD HL,(DE.EXT) LD A,1FH AND (HL) DEC A LD (E.EXT),A CP 1EH ;TEST FOR DRIVE CHANGE RET NC ;KNOW CHANGES LD A,(DRIVE) LD (PIG),A ;SAVE OLD DRIVE LD A,(HL) ;GET NEW DRIVE LD (COW),A ;SAVE NEW DRIVE LD A,0E0H AND (HL) ;CONVERT TO 00H LD (HL),A ;A TO FCB ; ;14 (0EH) SELECT DISK DRIVE - LOG IN ; LOG.IN: LD HL,DRIVE LD A,(E.EXT) CP (HL) RET Z ;SAME DRIVE LD (DRIVE),A JP D.INIT ;MAKE TABLE FOR NEW DRV. ; ;CROMEMCO COMMAND 86 ROUTINE ; CMD.86: LD HL,(HL.EXT) LD DE,(DE.EXT) PUSH DE EX DE,HL PUSH HL LD (HL),00 INC HL LD BC,200BH ; COOL: LD (HL),B INC HL DEC C JR NZ,COOL ; POP HL EX DE,HL LD B,9 INC HL CALL LFORCE DEC HL CP 3AH ;(:) JR NZ,WARM CALL LFORCE SUB 40H LD (DE),A INC HL INC HL WARM: INC DE ; HOT: CALL LFORCE CP 21H ;TEST FOR CONTROLS JR C,ENDIT CP 2EH ;(.) JR Z,WET LD (DE),A INC HL INC DE DJNZ HOT ; SCF JR FINAL ; WET: INC HL LD BC,09H EX DE,HL POP HL PUSH HL ADD HL,BC EX DE,HL LD B,04 JR HOT ; ENDIT: OR A FINAL: POP DE RET ; LFORCE: LD A,(HL) ;GET CHARACTER CP 61H ;TEST IT RET C ;LOWER CASE AND 5FH ;CHANGE TO LOWER RET ; ;VICTOR TO COMMANDS ; CMVICT: LD A,C ;GET CMD IN A CP 86H ;TEST FOR COMMAND 86 JP NZ,NCHANG ;NO CHANGE LD C,1FH ;COMMAND N0. 86 NCHANG: XOR A ;GET A ZERO IN A. LD B,A ;ZERO B REG. LD (CURREN),A ;RESET CURREN TO 00H LD (COW),A ;RESET COW TO 00H LD HL,CMDTBL ADD HL,BC ADD HL,BC ;POINT TO TABLE LOCATION LD E,(HL) INC HL LD D,(HL) EX DE,HL LD DE,RCALLR ;GET RETURN ADDRESS PUSH DE ;COMPLETE REURN JUMP JP (HL) ;JUMP TO DESIRED ROUT. ; ;0 REBOOT WITH WARM BOOT ; RBOOT: JP WBOOT ; ;1 READ CONSOLE WITH ECHO ; RDCONS: CALL INECHO JR CR.RET ; ;2 WRITE CONSOLE ; WRCONS: DW L.C.X2 ;LD C,X' JP TAB.CK ;& OUTPUT CHAR. ; ;3 READ READER ; RREAD: CALL READER JR CR.RET ; ;4 WRITE PUNCH ; WPUNCH: DW L.C.X2 ;LD C,X' JP PUNCH ; ;5 WRITE LIST ; WRLIST: DW L.C.X2 ;LD C,X' JP LIST ; ;6 ENTRY POINT OF BDOS ; BDOSJP: LD HL,(SM003) JR C9.RET ; ;7 GET I/O BYTE ; GIOBYT: LD HL,(IOBYTE) LD H,00H C9.RET: LD (C9INFO),HL RET ; ;8 SET I/O BYTE ; SIOBYT: DW L.A.X2 ;LD A,X' LD (IOBYTE),A RET ; ;11 (0BH) TEST CONSOLE READY ; TCONS: CALL TS.CON CR.RET: LD (CURREN),A RET ; ;12 (0CH) DESELECT CURRENT DRIVE ; DESEL: RET ; ;24 (18H) GET DISK LOG-IN VICTOR ; LOGVIC: LD A,(LOGBYT) JR CR.RET ; ;25 (19H) GET CURRENT DISK ; CURDSK: LD A,(DRIVE) JR CR.RET ; ;26 (1AH) SET DISK BUFFER ; DSKSET: LD A,(MAPLE) RRA LD HL,(DE.EXT) JR C,N.DMAS ;NO STORE LD (DOG),HL LD B,H LD C,L JP SETDMA ; N.DMAS LD (DSKBUF),HL RET ; ;27 (1BH) GET DISK CLUSTER ALLOCATION MAP ; CLUST: LD HL,(BI.PNT) JR C9.RET ; ;29 (1DH) TEST FOR READ ONLY DISK ; TRDONL: LD A,(SNAKE) LD (CURREN),A RET ; ;32 (20H) GET PRESENT DMA ADDRESS ; GET.DMA LD HL,(DOG) ;GET DMA ADDRESS JR C9.RET ; ;33 (21H) GET ADDRESS OF AUXILARY BUFFER ; GET.BUF LD HL,A.BUF ;ADDRESS OF BUFFER JR C9.RET ; ;COMMAND TABLE ; CMDTBL: DW RBOOT DW RDCONS DW WRCONS DW RREAD DW WPUNCH DW WRLIST DW BDOSJP DW GIOBYT DW SIOBYT DW PBUFFL DW INLINE DW TCONS DW DESEL DW RESET DW LOG.IN DW OPENFL DW CLOSEF DW DSEARC DW FNXDIR DW DLFILE DW RNXREC DW WNXREC DW CREATE DW RENAME DW LOGVIC DW CURDSK DW DSKSET DW CLUST DW RONLY DW TRDONL DW FIXDMA DW CMD.86 DW GET.DMA DW GET.BUF ; ;RELOAD REGISTERS AND RETURN TO CALLER ; RCALLR: LD A,(COW) ;TEST COMMAND LINE FOR ;DRIVE CHANGES OR A JP Z,SM0BB ;KNOW DRIVE CHANGE LD HL,(DE.EXT) ;POINT TO FCB LD (HL),A ;REPLACE DRIVE TOKEN LD A,(PIG) ;ORIGINAL DRIVE NUMBER LD (E.EXT),A CALL LOG.IN ;LOG IN WITH AN ORIGINAL ;DRIVE NUMBER SM0BB: LD A,(CURREN) LD HL,(C9INFO) ;GET INFO OR L ;COMBINE A & L LD L,A ;STORE LD (C9INFO),HL RET ; ;START OF BUFFERS ; ;END OF 25 LEVEL STACK ; DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 N.SP: DB 0 ; ;START OF 25 LEVEL STACK ; ORG BIOS+86H ; SP.EXT DB 0,0 LENGTH: NOP LSTBYT: NOP STATBT: NOP DE.EXT: DB 0,0 HL.EXT: DB 0,0 C9INFO: DB 0,0 CURREN: NOP ;FIND BETTER NAME E.EXT: NOP N.RUG: DB 0,0 ;DRIVE: DB 0 ERRBYT: NOP ;MAIN ERROR BYTE CAT: NOP DOG: DB 80H,0 DSKBUF: DB 80H,0 MAPLE: NOP ; ;TABLE #1 BIT MAP DRIVE "0" 32 BYTES PER DRIVE ; BITMAP: DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 BI.PNT: DB 0,0 ;BIT MAP POINTER SNAKE: NOP BLKMAP: DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0 DRCSUM: DB 0,0 ;BLOCK MAP POINTER PIG: NOP COW: NOP LOGBYT: NOP TABLE3: DB 0,0,0,0 TABLE4: DB 0,0,0,0,0,0,0,0 TAB.3P: DB 0,0 TAB.4P: DB 0,0 LUXER: NOP BOXER: NOP STORM: DB 0,0 ER.BYT: NOP BIRD: NOP SER.LN: NOP REN: DB 0,0 PLUM: NOP TEMPDE: DB 0,0 WREN: NOP NUT: NOP OAK: DB 0,0 OLD.DA: DB 0,0 OLD.PO: DB 0,0 L.DRIV: DB 0 CKBYTE: DB 0 T.DMA DB 0,0 ; ORG AUXBUF ;DISK BUFFER AND KEY ;BOARD BUFFER ; A.BUF: DB 0 ;THE AUXILIARY BUFFER ;IS A 128 BYTE BUFFER. DS 127 ;END OF BUFFER END BUFFER ; A.BUF: