home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
BDOS
/
P2DOS23.LBR
/
P2DOS1.MZC
/
P2DOS1.MAC
Wrap
Text File
|
2000-06-30
|
37KB
|
1,319 lines
;
; 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