; ; START PROGRAM ; P2DOS: ; SERIAL: DB SERNO1 ; serial number DB SERNO2 DB SERNO3 DB SERNO4 DB SERNO5 DB SERNO6 ; ; START P2DOS ; START: JP ENTRY ; JUMP TO ENTRY POINT P2DOS ; ; ERROR MESSAGES P2DOS ; ;Bad sector message changed to read/write messages-B.H. STBDSC: DEFW BADSEC ; split into read and write STSEL: DEFW SELERR ; SELECT ERROR STRO: DEFW RDONLY ; DRIVE READ ONLY SFILRO: DEFW FILRO ; FILE READ ONLY ; ; BDOS Search Path Address ; PATH: ; keep same loc as in P2DOS IF PATHON DEFW RAMLOW+0040H ELSE DEFW 0000H ENDIF ; ; TIME ADDRESS P2BIOS ; TIMEAD: IF DOTIME DEFW TIME ; TIME ROUTINE ADDRESS FOR TIME ; AND DATE STAMPS ELSE DEFW CONST ENDIF ; ; ; FLAGS FOR SPECIALS ; BIT 0: PUBLIC FILE ENABLE(1)/DISABLE(0) ; BIT 1: DELAY 256 CHARACTERS ACTIVE(1)/DISABLE(0) ; BIT 2: WRITE PROTECT IGNORE ENABLED(1)/DISABLED(0) ; FLAGS: DB DEFFLG ; FLAG BYTE ; ; ENTRY POINT P2DOS COMMANDS ; ENTRY: LD A,C ; GET FUNCTION NUMBER LD (FUNCT),A ; SAVE IT FOR LATER USE LD HL,0 ; SET HL TO ZERO LD (PEXIT),HL ; CLEAR EXIT CODE XOR A ; CLEAR A LD (FLDRV),A ; RESET DRIVE SELECT DONE FLAG LD (RDWR),A ; RESET READ/WRITE FLAG LD (SPSAVE),SP ; SAVE STACK POINTER LD SP,P2DOSS ; GET INTERNAL STACK POINTER PUSH IX ; SAVE INDEX REGISTER PUSH DE ; SAVE PARAMETER REGISTER POP IX ; GET IT BACK IN IX LD HL,P2EXIT ; GET EXIT ADDRESS P2DOS PUSH HL ; SAVE IT ON STACK TO RETURN FROM P2DOS LD A,C ; GET FUNCTION CODE ; IF DOTIME CP 200 ; TEST GET TIME JP Z,GETTIM ; YES THEN GET TIME CP 201 ; TEST SET TIME JP Z,SETTIM ; YES THEN SET TIME ENDIF ; CP MAXCMD+1 ; TEST GREATER THEN MAXCMD RET NC ; IF SO RETURN TO CALLER AND DO NOTHING LD HL,CTABLE ; LOAD TABLE LD B,0 ; PREPARE 16 BIT ADD ADD HL,BC ; ADD ADD HL,BC ; ADD TWICE TO GET WORD VALUE LD A,(HL) ; GET LSB INC HL ; POINTER TO MSB LD H,(HL) ; GET MSB LD L,A ; SAVE LSB IN L JP (HL) ; JUMP TO ROUTINE ; ; COMMAND TABLE ; ; ; FUNC NAME INPUT PARAMETERS RETURNED VALUES ; 0 BOOT NONE NONE ; 1 CONSOLE INPUT NONE A=CHARACTER ; 2 CONSOLE OUTPUT E=CHARACTER A=00H ; 3 READER INPUT NONE A=CHARACTER ; 4 PUNCH OUTPUT E=CHARACTER A=00H ; 5 LIST OUTPUT E=CHARACTER A=00H ; 6 DIRECT CONSOLE I/O E=0FFH A=INPUT CHARACTER ; A=00H IF NO CHARACTER ; PRESENT ; E=0FEH A=CONSOLE STATUS ; E=000H..0FDH A=00H ; 7 GET I/O BYTE NONE A=I/O BYTE (RAMLOW+03H) ; 8 SET I/O BYTE E=I/O BYTE A=00H ; 9 PRINT STRING DE=ADDRESS STRING A=00H ; 10 READ CONSOLE BUFFER DE=ADDRESS BUFFER A=00H ; 11 GET CONSOLE STATUS NONE A=00H IF NO CHARACTER ; PRESENT ; 01H IF CHARACTER PRESENT ; 12 RETURN VERSION NUMBER NONE A=VERSION NUMBER (022H) ; 13 RESET DISK SYSTEM NONE A=00H NO $*.* FILE ; A=FFH $*.* FILE PRESENT ; 14 SELECT DISK E=DISK NUMBER A=00H ; 15 OPEN FILE DE=ADDRESS FCB A=DIRECTORY CODE ; 16 CLOSE FILE DE=ADDRESS FCB A=DIRECTORY CODE ; 17 SEARCH FOR FIRST DE=ADDRESS FCB A=DIRECTORY CODE ; 18 SEARCH FOR NEXT DE=ADDRESS FCB A=DIRECTORY CODE ; 19 DELETE FILE DE=ADDRESS FCB A=ERROR CODE ; 20 READ SEQUENTIAL DE=ADDRESS FCB A=READ/WRITE CODE ; 21 WRITE SEQUENTIAL DE=ADDRESS FCB A=READ/WRITE CODE ; 22 MAKE FILE DE=ADDRESS FCB A=DIRECTORY CODE ; 23 RENAME FILE DE=ADDRESS FCB A=ERROR CODE ; 24 RETURN LOGIN VECTOR NONE HL=LOGIN VECTOR ; 25 RETURN CURRENT DISK NONE A=CURRENT DISK ; 26 SET DMA ADDRESS DE=DMA ADDRESS A=00H ; 27 GET ALLOCATION ADDRESS NONE HL=ADDRESS ALLOCATION ; VECTOR ; 28 WRITE PROTECT DISK NONE A=00H ; 29 GET R/O VECTOR NONE HL=R/O VECTOR ; 30 SET FILE ATTRIBUTES DE=ADDRESS FCB A=ERROR CODE ; 31 GET ADDRESS DPB NONE HL=ADDRESS DPB ; 32 SET/GET USER CODE E=0FFH A=USER NUMBER ; E=USER NUMBER A=00H ; 33 READ RANDOM DE=ADDRESS FCB A=READ/WRITE CODE ; 34 WRITE RANDOM DE=ADDRESS FCB A=READ/WRITE CODE ; 35 COMPUTE FILE SIZE DE=ADDRESS FCB A=ERROR CODE ; 36 SET RANDOM RECORD DE=ADDRESS FCB A=00H ; 37 RESET MULTIPLE DRIVE DE=MASK A=00H NO $*.* FILE ; A=FFH $*.* FILE PRESENT ; 38 NOT IMPLEMENTED NONE A=00H ; 39 NOT IMPLEMENTED NONE A=00H ; 40 WRITE RANDOM WITH DE=ADDRESS FCB A=READ/WRITE CODE ; ZERO FILL ; 200 GET TIME DE=ADDRESS TO PUT TIME A=00H ; 201 SET TIME DE=ADDRESS TIME A=00H ; ; DIRECTORY CODE : A=00H,01H,02H,03H IF NO ERROR ; A=0FFH IF ERROR ; ERROR CODE : A=00H IF NO ERROR ; A=0FFH IF ERROR ; READ/WRITE CODE: A=00H IF NO ERROR ; A=01H READ => END OF FILE ; WRITE => DIRECTORY FULL ; A=02H DISK FULL ; A=03H CLOSE ERROR DURING RANDOM RECORD READ/WRITE ; A=04H READ EMPTY RECORD DURING RANDOM RECORD READ ; A=05H DIRECTORY FULL DURING RANDOM RECORD WRITE ; A=06H RANDOM RECORD TOO LARGE DURING RANDOM RECORD READ/WRITE ; ; CTABLE: DEFW WBOOT ; WARM BOOT DEFW RDCON ; CONSOLE INPUT DEFW BWRCON ; CONSOLE OUTPUT DEFW RDRDR ; READER INPUT DEFW WPUNCH ; PUNCH OUTPUT DEFW WLIST ; LIST OUTPUT DEFW DCIO ; DIRECT CONSOLE I/O DEFW GIOST ; GET I/O BYTE DEFW SIOST ; SET I/O BYTE DEFW MESS ; PRINT STRING DEFW RDBUF ; READ CONSOLE BUFFER DEFW TSTCS ; GET CONSOLE STATUS DEFW CMND12 ; RETURN VERSION NUMBER DEFW CMND13 ; RESET DISK SYSTEM DEFW CMND14 ; SELECT DISK DEFW CMND15 ; OPEN FILE DEFW CMND16 ; CLOSE FILE DEFW CMND17 ; SEARCH FOR FIRST DEFW CMND18 ; SEARCH FOR NEXT DEFW CMND19 ; DELETE FILE DEFW CMND20 ; READ SEQUENTIAL DEFW CMND21 ; WRITE SEQUENTIAL DEFW CMND22 ; MAKE FILE DEFW CMND23 ; RENAME FILE DEFW CMND24 ; RETURN LOGIN VECTOR DEFW CMND25 ; RETURN CURRENT DISK DEFW CMND26 ; SET DMA ADDRESS DEFW CMND27 ; GET ADDRESS ALLOCATION VECTOR DEFW CMND28 ; WRITE PROTECT DISK DEFW CMND29 ; GET R/O VECTOR DEFW CMND30 ; SET FILE ATTRIBUTES DEFW CMND31 ; GET ADDRESS DISK PARAMETER HEADER(DPH) DEFW CMND32 ; GET/SET USER CODE DEFW CMND33 ; READ RANDOM DEFW CMND34 ; WRITE RANDOM DEFW CMND35 ; COMPUTE FILE SIZE DEFW CMND36 ; SET RANDOM RECORD DEFW CMND37 ; RESET MULTIPLE DRIVE DEFW DUMMY ; NOT IMPLEMENTED DEFW DUMMY ; NOT IMPLEMENTED DEFW CMND40 ; WRITE RANDOM WITH ZERO FILL ; ; I/O ROUTINES ; ; P2DOS CONSOLE INPUT ; ; READ CHARACTER FROM CONSOLE AND ECHO ; IF CHAR=CR,LF,TAB,CONTH OR >=SPACE ; RDCON: CALL GETCH ; GET CHARACTER CALL TSTCH ; TEST IF CR,LF,TAB,CONTH OR >=SPACE CALL NC,WRCON ; ECHO CHARACTER EXIT: LD (PEXIT),A ; RETURN CHARACTER DUMMY: RET ; AND EXIT P2DOS ; ; P2DOS WRITE CONSOLE ; BWRCON: LD A,E ; COPY CHARACTER JR WRCON ; AND OUTPUT IT ; ; READ READER ; RDRDR: CALL READER ; GET CHARACTER FROM READER JR EXIT ; AND RETURN IT TO CALLER ; ; WRITE PUNCH ; WPUNCH: LD C,E ; COPY CHARACTER JP PUNCH ; AND OUTPUT IT TO PUNCH DEVICE ; ; WRITE LIST ; WLIST: LD C,E ; COPY CHARACTER JP LIST ; AND OUTPUT IT TO LIST DEVICE ; ; DIRECT CONSOLE INPUT/OUTPUT ; DCIO: LD C,E ; COPY CHARACTER INC E ; TEST IF 0FFH JR Z,DCIO0 ; YES DO INPUT INC E ; TEST IF 0FEH JP NZ,CONOUT ; NO THEN OUTPUT CHARACTER CALL CONST ; GET CONSOLE STATUS JR EXIT ; AND RETURN IT TO CALLER DCIO0: CALL CONST ; GET CONSOLE STATUS OR A ; TEST IT RET Z ; EXIT IF NO CHARACTER PRESENT CALL CONIN ; GET CHARACTER JR EXIT ; AND RETURN IT TO CALLER ; ; GET I/O STATUS BYTE ; GIOST: LD A,(RAMLOW+00003H) ; GET I/O BYTE FROM RAM JR EXIT ; AND RETURN IT TO CALLER ; ; SET I/O STATUS BYTE ; SIOST: LD A,E ; COPY I/O BYTE LD (RAMLOW+00003H),A ; AND SAVE IT IN RAM RET ; EXIT TO CALLER ; ; TEST CONSOLE STATUS ; TSTCS: CALL GCONST ; GET CONSOLE STATUS JR EXIT ; AND RETURN IT TO CALLER ; ; OUTPUT CHAR (CONTROL CHAR = ^CHAR) ; OUTCH: CALL TSTCH ; TEST IT CR,LF,TAB,CONTH OR >=SPACE JR NC,WRCON ; YES THEN JUMP PUSH AF ; SAVE CHARACTER LD A,'^' ; LOAD A WITH '^' CALL WRCON ; OUTPUT IT POP AF ; GET CHARACTER BACK PUSH AF ; SAVE IT AGAIN ADD A,'A'-1 ; ADD OFFSET CALL WRCON ; OUTPUT IT POP AF ; GET CHARACTER RET ; RETURN TO CALLER ; ; ECHO CR,LF ; CROUT: LD A,CR ; A=CARRIAGE RETURN CALL WRCON ; OUTPUT IT LD A,LF ; A=LINE FEED ; FALL THROUGH TO OUTPUT ROUTINE ; ; WRITE CHARACTER ON CONSOLE ; WRCON: CP TAB ; TEST IF TAB JR NZ,WRCON1 ; NO THEN JUMP WRCON0: LD A,' ' ; EXPAND TAB WITH SPACES CALL WRCON ; WRITE SPACE LD A,(TABCNT) ; GET TAB COUNT AND 7 ; TEST IF DONE JR NZ,WRCON0 ; NO THEN REPEAT LD A,TAB ; RETURN TAB RET ; RETURN TO CALLER WRCON1: PUSH AF ; SAVE CHARACTER CALL GCONST ; TEST STATUS AND CONTS/CONTC POP AF ; GET CHARACTER BACK PUSH AF ; SAVE IT AGAIN LD C,A ; COPY IT CALL CONOUT ; OUTPUT IT POP AF ; GET CHARACTER BACK PUSH AF ; SAVE IT AGAIN LD C,A ; COPY IT LD A,(FCONTP) ; GET PRINTER ECHO FLAG OR A ; TEST IT CALL NZ,LIST ; NON ZERO => OUTPUT CHAR TO PRINTER LD A,(FLAGS) ; GET FLAG BYTE BIT 1,A ; TEST DELAY 256 BYTES ACTIVE JR Z,WRCON2 ; NO THEN EXIT LD HL,DELAY ; GET DELAY COUNTER XOR A ; A=0 OR (HL) ; TEST COUNTER=0 JR Z,WRCON2 ; YES THEN EXIT DEC (HL) ; ELSE DECREMENT COUNTER WRCON2: POP AF ; RESTORE CHARACTER ; FALL THROUGH TO COUNT ROUTINE ; ; COUNT CHARACTERS IN LINE ; COUNTC: LD HL,TABCNT ; GET POINTER TO TAB COUNTER CP RUBOUT ; TEST IF CHARACTER = RUBOUT RET Z ; YES NO UPDATE TAB COUNTER INC (HL) ; INCREMENT TAB COUNTER CP ' ' ; TEST IF CHAR >= ' ' RET NC ; YES, NORMAL CHARACTER THEN EXIT DEC (HL) ; CONTROL CHARACTER, DECREMENT TAB COUNT CP CONTH ; TEST BACKSPACE JR NZ,COUNT0 ; NO BACKSPACE THEN JUMP DEC (HL) ; DECREMENT TAB COUNTER RET ; AND EXIT COUNT0: CP CR ; TEST CARRIAGE RETURN JR NZ,COUNT1 ; NO THEN JUMP LD (HL),0 ; RESET TAB COUNT RET ; AND EXIT COUNT1: CP TAB ; TEST TAB CHARACTER RET NZ ; NO THEN EXIT PUSH AF ; SAVE CHARACTER LD A,(HL) ; GET TAB COUNT ADD A,8 ; ADVANCE IT 8 POSITION AND 0F8H ; SET IT TO NEXT TAB POSITION LD (HL),A ; SAVE IT POP AF ; RESTORE CHARACTER RET ; AND EXIT ; ; GET CHARACTER FROM CONSOLE ; GETCH: LD HL,LASTCH ; GET POINTER TO LAST INPUT CHARACTER LD A,(HL) ; GET CHARACTER LD (HL),0 ; RESET LAST CHARACTER OR A ; TEST IF CHARACTER PRESENT RET NZ ; RETURN IF SO JP CONIN ; ELSE GET CHARACTER ; ; GET CONSOLE STATUS ; GCONST: LD A,(DELAY) ; GET 256 BYTES DELAY OR A ; TEST IT JR NZ,GCONS0 ; NON ZERO, DELAY STILL ACTIVE OR DISABLED CALL CONST ; GET CONSOLE STATUS OR A ; TEST IT JR NZ,GCONS1 ; NON ZERO THEN GET CHARACTER GCONS0: LD A,(LASTCH) ; GET LAST CHARACTER OR A ; TEST IT JR NZ,GCONS3 ; NON ZERO THEN CHARACTER PRESENT CALL CONST ; GET CONSOLE STATUS OR A ; TEST IT RET Z ; RETURN IF NO CHARACTER PRESENT GCONS1: CALL CONIN ; GET CHARACTER CP CONTS ; TEST STOP CHARACTER JR NZ,GCONS2 ; NOT THEN EXIT CHARACTER GCONS4: CALL CONIN ; GET NEXT CHARACTER CP CONTC ; TEST IF USER WANTS TO EXIT JP Z,RAMLOW+00000H ; YES THEN WARM BOOT ; IF XONOFF CP CONTQ ; ^Q to turn on console output? JR NZ,GCONS4 ; no, igore character ELSE IF NOXOFF CP CONTS ; another ^S? JR Z,GCONS4 ; yes, don't restart console output ENDIF ENDIF ; JR GCONST ; TEST AGAIN GCONS2: LD (LASTCH),A ; SAVE CHARACTER LD A,0FFH ; SET DELAY COUNTER LD (DELAY),A ; AND SAVE IT GCONS3: LD A,1 ; CHARACTER PRESENT CODE RET ; RETURN TO CALLER ; ; TEST CHARACTER ; EXIT CARRY=0: CR,LF,TAB,CONTH OR >=SPACE ; CARRY=1: ALL OTHER CHARACTERS ; TSTCH: CP CR ; TEST CARRIAGE RETURN RET Z ; RETURN IF SO CP LF ; TEST LINE FEED RET Z ; RETURN IF SO CP TAB ; TEST TAB RET Z ; RETURN IF SO CP CONTH ; TEST BACKSPACE RET Z ; RETURN IF SO CP ' ' ; TEST >=SPACE RET ; RETURN TO CALLER ; ; WRITE BACKSPACE,SPACE,BACKCPACE ; WCONTH: CALL WCONT0 ; WRITE BACKSPACE LD C,' ' ; LOAD SPACE CALL CONOUT ; AND OUTPUT IT WCONT0: LD C,CONTH ; LOAD BACKSPACE JP CONOUT ; AND OUTPUT IT ; ; OUTPUT MESSAGE ; MESS: LD A,(DE) ; GET BYTE FROM BUFFER CP '$' ; TEST LAST BYTE RET Z ; YES, THEN RETURN TO CALLER INC DE ; POINT TO NEXT BYTE PUSH DE ; SAVE POINTER CALL WRCON ; OUTPUT CHARACTER POP DE ; RESTORE POINTER JR MESS ; AND TEST AGAIN ; ; AGAIN PRINTS #,CR,LF AND ADVANCES TO TABCX1 ; AGAIN: LD A,'#' ; LOAD '#' CALL WRCON ; OUTPUT IT AGAIN0: CALL CROUT ; OUTPUT CARRIAGE RETURN/LINE FEED AGAIN1: LD HL,TABCNT ; GET TAB COUNT POINTER LD A,(TABCX1) ; GET POSITION FIRST CHARACTER LINE CP (HL) ; CHECK IT RET Z ; RETURN IF ON SAME POSITION LD A,' ' ; LOAD SPACE CALL WRCON ; OUTPUT IT JR AGAIN1 ; AND TEST AGAIN ; ; DELETE CHAR ; ENTRY : HL=START BUFFER-1 ; B =CHARACTER COUNTER (ALWAYS>0) ; DELCH: DEC B ; DECREMENT CHARACTER COUNTER LD A,(TABCNT) ; GET TAB COUNTER PUSH AF ; SAVE IT PUSH BC ; SAVE CHARACTER COUNTER LD A,(TABCX1) ; GET POSITION FIRST CHARACTER LINE LD (TABCNT),A ; SAVE IT IN TAB COUNTER DELCH0: LD A,B ; COPY CHARACTER COUNTER OR A ; TEST IF 0 JR Z,DELCH2 ; YES THEN JUMP DEC B ; DECREMENT IT INC HL ; INCREMENT BUFFER POINTER LD A,(HL) ; GET CHARACTER FROM BUFFER PUSH HL ; SAVE BUFFER POINTER CALL TSTCH ; TEST IF CR,LF,TAB,CONTH OR >=SP JR NC,DELCH1 ; YES THEN JUMP RRA ; ELSE MUST BE CONTROL CHARACTER CALL COUNTC ; COUNT CONTROL CHARACTER TWICE DELCH1: CALL COUNTC ; COUNT CHARACTER POP HL ; GET BUFFER POINTER JR DELCH0 ; AND TEST AGAIN DELCH2: POP BC ; RESTORE CHARACTER COUNTER POP AF ; AND TAB COUNTER PUSH HL ; SAVE BUFFER POINTER PUSH BC ; AND CHARACTER COUNTER LD HL,TABCNT ; GET TAB COUNTER POINTER SUB (HL) ; CALCULATE DIFFERENCE DELCH3: DEC A ; DECREMENT IT CP 8 ; COMPARE WITH 8 JR NC,DELCH4 ; JUMP IF >=8 PUSH AF ; SAVE DIFFERENCE CALL WCONTH ; REMOVE CHARACTER END LINE POP AF ; RESTORE COUNTER JR DELCH3 ; REMOVE MORE CHARACTERS DELCH4: POP BC ; RESTORE CHARACTER COUNTER POP HL ; RESTORE BUFFER POINTER RET ; AND RETURN TO CALLER ; ; READ BUFFER ; RDBUF: LD A,(TABCNT) ; GET CURRENT POSITION CURSOR LD (TABCX1),A ; SAVE IT RDBUF0: PUSH IX ; SAVE START ADDRESS BUFFER POP HL ; GET IT IN HL LD C,(HL) ; GET MAXIMUM LINE LENGTH INC HL ; INCREMENT TO LINE LENGTH POSITION LD B,0 ; CLEAR LINE LENGTH COUNTER PUSH HL ; SAVE START LINE - 1 RDBUF1: PUSH HL ; SAVE REGISTERS PUSH BC RDBUF2: CALL GETCH ; GET CHARACTER POP BC ; RESTORE REGISTERS POP HL AND 07FH ; MASK CHARACTER CP CONTE ; TEST IF CONTE JR NZ,RDBUF3 ; NOT THEN JUMP PUSH HL ; SAVE REGISTERS PUSH BC CALL AGAIN0 ; MOVE CURSOR TO NEXT LINE JR RDBUF2 ; AND GET NEXT CHAR RDBUF3: CP CONTH ; TEST BACKSPACE JR NZ,RDBUF4 ; NOT THEN JUMP DOBACK: LD A,B ; TEST IF DELETING CHAR FROM EMPTY LINE OR A JR Z,RDBUF1 ; YES THEN GET NEXT CHAR POP HL ; GET START LINE PUSH HL ; AND SAVE IT AGAIN CALL DELCH ; DELETE CHARACTER JR RDBUF1 ; GET NEXT CHARACTER RDBUF4: CP CONTP ; TEST PRINT ENABLE/DISABLE JR NZ,RDBUF6 ; NOT THEN JUMP LD A,(FCONTP) ; COMPLEMENT PRINT FLAG CPL LD (FCONTP),A RDBUF5: JR RDBUF1 ; AND GET NEXT CHARACTER RDBUF6: CP CONTR ; TEST REPEAT LINE JR NZ,RDBUFA ; NOT THEN JUMP PUSH BC ; SAVE REGISTERS CALL AGAIN ; MOVE CURSOR TO NEXT LINE POP BC ; RESTORE REGISTERS POP HL ; GET START LINE PUSH HL ; SAVE IT AGAIN PUSH BC ; SAVE LINE COUNTER/MAXIMUM LINE LENGTH RDBUF7: LD A,B ; TEST LAST CHARACTER ECHOED OR A JR Z,RDBUF8 ; YES THEN JUMP INC HL ; INCREMENT POINTER LD A,(HL) ; GET CHARACTER DEC B ; DECREMENT LINE COUNTER PUSH HL ; SAVE REGISTERS PUSH BC CALL OUTCH ; OUTPUT CHARACTER POP BC ; RESTORE REGISTERS POP HL JR RDBUF7 ; AND TEST END LINE RDBUF8: POP BC ; RESTORE LINE COUNTER/MAX LINE LENGTH RDBUF9: JR RDBUF5 ; AND GET NEXT CHAR RDBUFA: CP CONTU ; TEST DELETE LINE JR NZ,RDBUFC ; NOT THEN JUMP POP HL ; GET START LINE CALL AGAIN ; MOVE CURSOR TO NEXT LINE RDBUFB: JR RDBUF ; AND START ROUTINE AGAIN RDBUFC: CP CONTX ; TEST DELETE LINE JR NZ,RDBUFE ; NOT THEN JUMP RDBUFD: POP HL ; GET START LINE LD A,B ; TEST IF LAST CHARACTER DELETED OR A JR Z,RDBUFB ; YES START ROUTINE AGAIN PUSH HL ; SAVE POINTER CALL DELCH ; DELETE LAST CHARACTER LINE JR RDBUFD ; TEST LAST CHARACTER DELETED RDBUFE: CP RUBOUT ; TEST DELETE LAST CHARACTER JR Z,DOBACK ; Part of delete key fix ;Remove code for echoing deleted character--B.H. ; LD A,B ; TEST FIRST CHARACTER LINE ; OR A ; JR Z,RDBUF9 ; YES, DO NOT DELETE ; LD A,(HL) ; GET LAST CHARACTER ; DEC HL ; DECREMENT POINTER LINE ; DEC B ; DECREMENT LINE COUNTER ; JR RDBUFG ; ECHO LAST CHARACTER CP CR ; TEST CARRIAGE RETURN JR Z,RDBUFI ; YES, THEN EXIT CP LF ; TEST LINE FEED JR Z,RDBUFI ; YES THEN EXIT INC HL ; INCREMENT POINTER LD (HL),A ; AND SAVE CHARACTER INC B ; INCREMENT LINE COUNTER RDBUFG: PUSH HL ; SAVE REGISTERS PUSH BC CALL OUTCH ; ECHO CHARACTER POP BC ; RESTORE REGISTERS POP HL CP CONTC ; TEST WARM BOOT LD A,B ; GET LINE COUNT JR NZ,RDBUFH ; NO WARM BOOT THEN JUMP CP 1 ; TEST CONTC IS FIRST CHARACTER LINE JP Z,RAMLOW+00000H ; YES THEN EXECUTE WARM BOOT RDBUFH: CP C ; TEST LINE LENGTH=MAXIMUM LINE LENGTH JR NZ,RDBUF9 ; NOT THEN GET NEXT CHARACTER RDBUFI: POP HL ; GET START LINE - 1 LD (HL),B ; SAVE LINE COUNTER LD A,CR ; LOAD CARRIAGE RETURN JP WRCON ; AND ECHO IT ; ;****************************************************************************** ;* * ;* DISK FUNCTIONS * ;* * ;****************************************************************************** ; ; RETURN VERSION NUMBER ; CMND12: LD A,22H ; SET VERSION NUMBER JR CMD25A ; AND EXIT ; ; RESET DISK SYSTEM ; CMND13: IF RESDSK ;detect change between single and double sided disks if this function is ;supported.--B.H. CALL SETDSK ENDIF LD HL,0 ; LOAD ZERO LD (LOGIN),HL ; ALL DRIVES LOGED OUT LD (DSKRO),HL ; ALL DRIVES READ/WRITE LD HL,RAMLOW+00080H ; SET UP DMA ADDRESS LD (DMA),HL ; AND SAVE IT CALL STDMA ; DO P2BIOS CALL XOR A ; SET DEFAULT DRIVE = 'A' LD (DEFDRV),A ; SAVE IT CALL SELDK ; SELECT DRIVE 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 OCCURENCE FILE ; CMND18: LD IX,(DCOPY) ; GET LAST FCB USED BY SEARCH CALL SELDRV ; SELEXT 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 ALV 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 ; ; CHANGE STATUS ; CMND30: CALL SELDRV ; SELECT DRIVE FROM FCB CALL CSTAT ; CHANGE STATUS JR CMD19A ; AND EXIT ; ; RETURN DRIVE TABLE ; 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 COMMAND ; 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 MULTIPLE LOGIN DRIVE ; 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,(DSKRO) ; GET DRIVE R/O 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 (DSKRO),HL ; SAVE DRIVE R/O VECTOR LD A,(DEFDRV) ; log in default drive if needed CALL SELDK XOR A ; flag success JP EXIT ; and return ; ;****************************************************************************** ;* * ;* ERROR ROUTINES * ;* * ;****************************************************************************** ; ; Bad sector error message separated into read/write error messages--B.H. ; BAD SECTOR ERROR ; BADSEC: JP (HL) ; go to RDERR or WRTERR routine ; ; SELECT ERROR ; SELERR: LD DE,MSEL ; LOAD SELECT ERROR MESSAGE JR WERROR ; AND DISPLAY ERROR ; ; FILE READ ONLY ERROR ; FILRO: LD DE,MFILRO ; LOAD FILE R/O MESSAGE LD BC,0FFFFH ; SET FILE R/O and ignore MESSAGE FLAG JR ERROR ; AND DISPLAY ERROR ; ; Read Error Message--B.H. ; RDERR: LD DE,MRDERR JR WERROR ; ; Write Error Message--B.H. WRTERR: LD DE,MWRTER WERROR: LD B,00H ; set not ok to ignore JR DERROR ; ; DRIVE READ ONLY ERROR ; RDONLY: LD DE,MRO ; LOAD DRIVE R/O MESSAGE LD B,0FFH ; set ok to ignore DERROR: LD C,0 ; SET NO FILE R/O MESSAGE ; ; ; DISPLAY ERROR MESSAGE ; ; P2DOS ERROR ON D: ERROR MESSAGE ; FUNCTION = NN [FILE = FILENAME.TYP] ; ERROR: PUSH BC ; SAVE FILE R/O and IGNORE FLAG PUSH DE ; SAVE ERROR MESSAGE POINTER CALL CROUT ; DISPLAY CR/LF LD A,(DEFDRV) ; GET CURRENT DRIVE ADD A,'A' ; MAKE ASCII LD (MDRIVE),A ; SAVE IT LD DE,MBERR ; LOAD MESSAGE "Disk error on " CALL MESS ; DISPLAY MESSAGE POP DE ; GET ERROR MESSAGE POINTER CALL MESS ; DISPLAY MESSAGE CALL CROUT ; DISPLAY CR/LF LD DE,MBFUNC ; LOAD MESSAGE "FUNCTION =" CALL MESS ; DISPLAY MESSAGE LD A,(FUNCT) ; GET FUNCTION NUMBER PUSH AF ; SAVE IT LD BC,100 ; DISPLAY NUMBER / 100 CALL NUM LD C,10 ; DISPLAY NUMBER / 10 CALL NUM LD BC,101H ; ALWAYS DISPLAY NUMBER / 1 CALL NUM POP AF ; GET FUNCTION NUMBER POP BC ; GET FILE R/O FLAG PUSH BC CP 15 ; TEST IF FCB USED IN COMMAND JR C,ERROR3 CP 24 JR C,ERROR1 CP 30 JR Z,ERROR1 CP 33 JR C,ERROR3 CP 37 JR C,ERROR1 CP 40 JR NZ,ERROR3 ERROR1: PUSH IX ; YES THEN DISPLAY "FILE =" SUB 19 ; TEST DELETE FILE FUNCTION JR NZ,ERROR2 ; NOT THEN JUMP OR C ; TEST FILE R/O FLAG JR Z,ERROR2 ; NO FILE R/O THEN JUMP CALL CALDIR ; GET FCB FROM DIRECTORY BUFFER EX (SP),HL ; SAVE IT ERROR2: LD DE,MFILE ; GET MESSAGE " FILE =" CALL MESS ; DISPLAY MESSAGE POP HL ; GET POINTER FCB LD B,8 ; DISPLAY FISRT 8 CHARACTERS CALL FILENM LD A,'.' ; LOAD '.' PUSH HL ; SAVE FCB POINTER CALL WRCON ; ECHO IT POP HL ; RESTORE FCB POINTER LD B,3 ; DISPLAY LAST 3 CHARACTERS CALL FILENM ERROR3: CALL GCONST ; TEST IF CHARACTER PRESENT OR A JR Z,ERROR4 ; NO THEN JUMP CALL GETCH ; GET CHARACTER JR ERROR3 ; AND TEST AGAIN ERROR4: CALL GETCH ; GET CHARACTER ;P2DOS had a bug which did not allow the user to ignore a read/write error ;by hitting a key other than Control-C. This is the fix.--B.H. ; ;further modified to accept only a single ignore character ; POP BC ; get back ignore flag CP CONTC ; warm boot? JR Z,ERROR5 ; yes AND B ; possible to ignore (r/o error?) JR Z,ERROR5 ; no LD HL,FLAGS ; ignore enabled? BIT 2,(HL) ERROR5: JP Z,RAMLOW+00000H ; no CP IGNORE ; ignore? RET Z ; yes PUSH BC ; save ignore flag JR ERROR4 ; ; DISPLAY NUMBER ; NUM: LD D,0FFH ; LOAD NUMBER -1 NUM1: INC D ; INCREMENT NUMBER SUB C ; DIVIDE BY C JR NC,NUM1 ; NOT FINISHED THEN LOOP ADD A,C ; RESTORE LAST VALUE PUSH AF ; SAVE IT LD A,D ; TEST IF "0" OR B ; AND IF LEADING ZERO JR Z,NUM2 ; YES, THEN EXIT LD B,D ; SET NO LEADING ZERO LD A,D ; GET NUMBER ADD A,'0' ; MAKE ASCII PUSH BC ; SAVE REGISTERS CALL WRCON ; ECHO NUMBER POP BC ; RESTORE REGISTERS NUM2: POP AF ; RESTORE NUMBER RET ; AND EXIT ; ; DISPLAY FILNAME.TYP ; FILENM: INC HL ; INCREMENT POINTER FCB LD A,(HL) ; GET CHARACTER FROM FCB AND 07FH ; MASK IT PUSH HL ; SAVE REGISTERS PUSH BC CALL WRCON ; ECHO CHARACTER POP BC ; RESTORE REGISTERS POP HL DJNZ FILENM ; REPEAT B TIMES RET ; AND EXIT ; ; ERROR MESSAGES ; Made more meaningful-B.H. ; ;Bad sector message replaced by read/write error messages ;MBADSC: DB 'Bad sector$' ; MSEL: DB 'Non-existent drive$' ; MFILRO: DB 'File is ' ; MRO: DB 'Read-Only$' ; MBERR: DB 'Disk error on ' MDRIVE: DB 0 DB DRVSEP DB ' $' ; MBFUNC: DB 'Function = $' ; MFILE: DB '; File = $' ; MRDERR: DB 'Read error$' ; MWRTER: DB 'Write error$' ; ; 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 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,(IX+0) ; GET DRIVE FROM FCB 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 ; ; SELECT DISK ; SELDK: AND 0FH ; MASK DRIVE NUMBER 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 ; COPY DRIVE NUMBER CALL SELDSK ; DO P2BIOS SELECT LD A,H ; TEST IF ERROR OR L JR NZ,SELDK3 ; DRIVE NUMBER LEGAL LD HL,(STSEL) ; load error message address JP (HL) ; go to error routine SELDK3: 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 INC HL ; INCREMENT TO NEXT ADDRESS INC HL LD (TEMP1),HL ; SAVE ADDRESS TEMP1 INC HL ; INCREMENT TO NEXT ADDRESS INC HL LD (TEMP2),HL ; SAVE ADDRESS TEMP2 INC HL ; INCREMENT TO NEXT ADDRESS INC HL LD DE,DIRBUF ; LOAD DIRBUF POINTER LD BC,8 ; COPY 8 BYTES LDIR 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 ; ; INIT DRIVE ; CLEAR ALV 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 LD HL,(ALV) ; GET POINTER ALV BUFFER PUSH HL INITD1: INC HL ; zero n-1 bytes (skip first) LD (HL),0 ; CLEAR 8 BITS 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) ; now, 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 LD (HL),A ; CLEAR LSB INC HL ; INCREMENT POINTER LD (HL),A ; CLEAR MSB LD (SUBFLG),A ; CLEAR SUBMIT FLAG (RESET DISK COMMAND) LD (DIFF),A ; clear disk changed flag 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 ; AND GET NEXT FCB ; ; SET DRIVE BIT IN HL ; 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) ; RESULT 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 RETORE 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 ; P2BIOS CALL SET TRACK POP BC ; RESTORE SECTOR NUMBER LD DE,(TRANS) ; GET TRANSLATION TABLE ADDRESS CALL SECTRN ; P2BIOS CALL SECTOR TRANSLATION LD B,H ; COPY RESULT TO BC LD C,L JP SETSEC ; P2BIOS CALL SET SECTOR ; ; GET DISK MAP BLOCK NUMBER FROM FCB ; EXIT HL=ADDRESS FCB ; DE=DM ; BC=OFFSET IN DM ; 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 EXTENT MASK AND (IX+12) ; MASK WITH EXTENT 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 ; 16 bits => jump LD E,(HL) ; GET 8 BIT VALUE LD D,A ; MAKE MSB ZERO (if a=0) RET Z ; AND EXIT ADD HL,BC ; else, 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 WHIT 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 ; 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 DE-(HL) SUB (HL) INC HL LD A,D SBC A,(HL) 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 FISRT 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 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 ;Automatic disk logging--instead of setting read/only flag when disk is ;changed, a disk changed flag is set. The disk is reset when the SEARCH ;routine is called. ; JP SETWPD LD A,TRUE ; set disk changed flag LD (DIFF),A JP SETFN ; set number of files CHKDR1: LD (HL),A ; UPDATE CHECKSUM RET ; AND EXIT ; ; READ SECTOR FROM DRIVE ; ; ;Readr and Writer modified to give separate error messages--B.H. READR: CALL READ ; P2BIOS CALL READ SECTOR LD HL,RDERR JR WRITE0 ; ; WRITE SECTOR ON DRIVE ; WRITER: CALL WRITE ; P2BIOS CALL WRITE SECTOR LD HL,WRTERR WRITE0: OR A ; TEST EXIT CODE RET Z ; EXIT IF OK PUSH HL ; go to "bad sector" routine LD HL,(STBDSC) EX (SP),HL RET ; P2DOS ERROR ON D: BAD SECTOR ; ; 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